反射

Java基礎知識框架

什麼是類對象?

  • 類的對象:基於某個類new出來的對象,也稱爲實例對象。
  • 類對象:類加載的產物,封裝了一個類的所有信息(類名、父類、接口、屬性、方法、構造方法)
public class TestClassObject {
	public static void main(String[] args) {
		//僞代碼
//		Class c = new Class();
//		c.packageName = "com.qf.day34.reflects.Student";
//		c.className = "Student";
//		c.superClass = "java.lang.Object";
//		C.fileds = new Filed[] {"String name","int age","String sex"};
//		c.methods = new methods[] {"public void study() {}","public void exam() {}","public void work() {}"};
//		c.constructors() = new constructors[] {"(){}","(String name){}"};
		Student s =  new Student();//類的對象,基於模板生成的
		System.out.println(s.getClass().toString());
		Class c = s.getClass();//類對象,類的對象的模板
		c.toString();
	}
}
class Student{
	String name;
	int age;
	String sex;
	public Student() {}
	public Student(String name) {
	}
	
	public Student(int age) {}
	public void study() {}
	public void exam() {}
	public void work() {}
}

模板類Class(類似於做月餅的模具,對象是類的實例,類是對象的模板)

獲取類對象的方法

  • 通過類的對象,獲取類對象
    Student s = new Student();
    Class c = s.getClass();
  • 通過類名獲取類對象
    Class c = 類名.class
  • 通過靜態方法獲取類對象
    Class c = Class.forName(“包名.類名”);
public class TestGetClassObject {
	public static void main(String[] args) throws ClassNotFoundException {
		
		//1.通過類的對象,獲取Class對象
		Person p = new Person();//類的對象
		Class c = p.getClass();//類對象Class對象,保存了Person.class這個文件中類的所有信息
		System.out.println(c.getName());
		
		//2.通過類名獲取Class對象
		Class c2 =  Person.class;//但先有Person再有.class
		System.out.println(c2.getName());
		
		//3.通過Class的靜態方法獲得Class對象
		Class c3 = Class.forName("com.qf.day34.reflects.Person");// throws ClassNotFoundException
		System.out.println(c3.getName());
	}
	//該方法返回一個類對象(Class對象)
	//第一種方式,傳不同類時,需要改Person,頻繁修改。改爲Object
//	public static Class getClassObject(Person p) {
//		Class c = p.getClass();
//		return c;
//	}
	//
	public static Class getClassObject(String className) {	
		Class c = null;
		try {
			c = Class.forName(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}	
		return c;
	}
	
}
class Person{
	
}

常見操作

常見方法:

  • public String getName()
  • public Package getPackage()
  • public Class<? super T>getSuperclass()
  • public Class<?>[] getInterfaces()
  • public Filed[] getFields
  • public Methods[] getMethods()
  • public Constructor<?>[] getConstructors()
  • public T newInstance()
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestClassMethods {
	public static void main(String[] args) throws Exception {
		//1.獲取類對象
		Class c = Class.forName("com.qf.day34.methods.Student");
		System.out.println(c.getName());
		//獲取指定類型的包
		Package  pack = c.getPackage();
		System.out.println(pack.getName());
		
		//獲得父類的Class對象
		Class superClass = c.getSuperclass();
		System.out.println(superClass.getName());
		
		//獲得接口的Class對象
		Class[] interfaces = c.getInterfaces();
		for(Class inter:interfaces) {
			System.out.println(inter.getName());
		}
		
		//獲取屬性(public)自身+父類的公開屬性
		Field[] fields = c.getFields();
		for(Field f : fields) {
			System.out.println(f.getName());	
		}
		
		System.out.println("---------------------");
		//獲得Class對象的自身所在屬性
		Field[] fields2 = c.getDeclaredFields();
		for(Field f : fields2) {
			System.out.println(f.getName());	
		}
		
		System.out.println("--------Method-------------");
		//獲取方法(自身+父類的所有公開方法)
		Method[] methods = c.getMethods();
		for(Method m : methods) {
			System.out.println(m.getName());	
		}
		
		System.out.println("--------Methodshelf-------------");
		//獲取方法(自身+父類的所有公開方法)
		Method[] methods2 = c.getDeclaredMethods();
		for(Method m : methods2) {
			System.out.println(m.getName()+":"+m.getReturnType());	
		}
		
		System.out.println("--------constructor-------------");
		Constructor[] cs = c.getConstructors();
		for(Constructor ct : cs) {
			System.out.print(ct.getName()+":");
			Class[] parm = ct.getParameterTypes();//獲取構造方法的形參
			for(Class p : parm) {
				System.out.println(p.getName());
			}
		}
		System.out.println("---------------------");
		Object o = c.newInstance();
		Student stu = (Student)o;
		System.out.println(stu);
	}
}
class Person{
	public String sex;
	public double money;
	public void eat() {}
	public void sleep() {}
}
class Student extends Person implements Serializable,Runnable,Comparable{
	public String name;
	public int age;
	double score;
	
	public Student() {}
	public Student(String name) {
	}
	public Student(String name,int age) {}
	private int aaa() {
		return 0;
	}
	public Student(int age) {}
	public void study() {}
	public void exam() {}
	public void work() {}
	
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}
}

在這裏插入圖片描述

public class TestNewInstance {
	public static void main(String[] args) throws Exception {
//		//1.手工new對象
//		Teacher t = new Teacher();
//		t.name = "aaa";
//		System.out.println(t.name);
		
		//2.反射通過類對象創建類的對象
//		Class c = Teacher.class;
//		Teacher t = (Teacher)c.newInstance();
//		t.name = "bbb";
//		System.out.println(t.name);
		
		Object o = createObject("com.qf.day34.methods.Teacher");
		System.out.println(o);
	}
	//不直接返回Teacher ,爲普適性
	//創建對象:
	//工廠,創建對象工廠
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

class Teacher{
	String name;
	String sex;
	Integer age;
	public Teacher() {
		
	}
	public Teacher(String name, String sex, Integer age) {
		super();
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	
	public void study() {
		System.out.println("我在學習");
	}
	public void exam() {
		System.out.println("我在考試");
	}
	public void calc() {
		System.out.println("我在計算");
	}
	
}

TestNewInstanceForFiles,案例前需要Files\application.txt創建並添加信息

import java.io.BufferedReader;
import java.io.FileReader;

public class TestNewInstanceForFiles {
	public static void main(String[] args) throws Exception {
		FileReader fr = new FileReader("Files\\application.txt");
		BufferedReader br = new BufferedReader(fr);
		String className = br.readLine();
		Object o = createObject(className);
		System.out.println(o);
	}
	//創建對象:
	//工廠,創建對象工廠
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
class Dog{
	
}

工廠設計模式

  • 開發中有一個非常重要的原則“開閉原則”,對拓展開放、對修改關閉
  • 工廠模式主要負責對象創建的問題
  • 可通過反射進行工廠模式的設計,完成動態的對象創建

invoke方法,執行某個實例

import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Method;

public class TestInvokeMethod {

	public static void main(String[] args)throws Exception{
		FileReader fr = new FileReader("Files\\application.txt");
		BufferedReader br = new BufferedReader(fr);
		String className = br.readLine();
		
		Object o = createObject(className);
		Class c = o.getClass();//類對象
		Method m = c.getMethod("study", null);
		m.invoke(o, null);//通過invoke方法,執行某個實例方法,參數:Object->所需對象,args->調用的方法所需的實參
	    
		
		Method m2 = c.getMethod("study",int.class);
		m2.invoke(o, 111); //接收方法返回值,如果是基本類型,則轉換爲包裝
		
		Method m3 = c.getMethod("exam",int.class,double.class,String.class);
		m3.invoke(o,2,90,"kunyan");
		
//		Method m4 = c.getMethod("clac", null);error無法獲取私有方法
		Method m4 = c.getDeclaredMethod("clac", null);//獲得自身方法,包含私有
		
		//注意:反射是一種Java底層技術,可以取消語言檢查,突破封裝
		m4.setAccessible(true);
		m4.invoke(o, null);
	}
	
	//工廠--->創建對象的
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	

}
class Student{
	String name;
	Integer age;
	String sex;
	Double score;
	public Student() {}
	public Student(String name, Integer age, String sex, Double score) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.score = score;
	}

	public Student(int age) {}
	
	public void study() {
		System.out.println("正在學習。。。。");
	}
	public int study(int a) {
		System.out.println("學習"+a+"小時");
		return 0;
	}
	public void exam(int a, double b ,String s) {
		System.out.println(s+"學習了"+a+"小時"+"考了"+b);
	}
	
	private void clac() {
		System.out.println("計算。。。");
	}
}

通用方式:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Method;

public class TestInvokeAnything {
	public static void main(String[] args) throws Exception {	
		//invokeAny() --->執行方法
		//對象(Object)、方法名稱(String)、形參(Class)、實參(Object)
//		FileReader fr = new FileReader("Files\\application.txt");
//		BufferedReader br = new BufferedReader(fr);
//		String className = br.readLine();
		Object o = createObject("com.qf.day35.reflects.Student");
		
		invokeAny(o,"exam",new Class[] {int.class,double.class,String.class},1,99,"kunyan");
		invokeAny(o,"study",null,null);
		invokeAny(o,"study",new Class[] {int.class},100);
		
	}
	//通用(調用任何一個方法)
	public static void invokeAny(Object obj ,String methodName,Class[] types,Object... args)throws Exception {
		//使用反射技術執行任何方法
		//類對象
		Class c = obj.getClass();
		//獲得方法的對象Methods
		Method m = c.getDeclaredMethod(methodName, types);
		
		//執行方法
		m.invoke(obj, args);
	}
	
	//工廠--->創建對象的
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
}

單例設計模式

  • 只允許創建一個該類的對象
```java
package com.qf.day35.singletons;

public class Test {
	public static void main(String[] args) {
		Student stu  = Student.getStudent();
		Student stu1  = Student.getStudent();
		Student stu2  = Student.getStudent();
		System.out.println(stu);
		System.out.println(stu1);
		System.out.println(stu2);
	}
}
//只創建了一次對象,一個對象----->只能在一個引用中
class Student{
	static int count = 0;
	//構造方法私有化
	private Student() {}
	
	public static Student getStudent() {
		count++;
		if(count>1) {
			return null;
		}else {
			return new Student();
		}
	}
	
}


 - 方式1:餓漢式[類加載時創建,天生線程安全]
 - 方式2:懶漢式[使用時創建,線程不安全,加同步]
 - 方式3:懶漢式(使用時創建,線程安全)

```java
package com.qf.day35.singletons;

public class TestSingleton {
	public static void main(String[] args) {
		Singleton s1 =Singleton.getInstance();
//		Singleton s2 =Singleton.getInstance();
//		Singleton s3 =Singleton.getInstance();
	
//		Singleton.instance=null;加私有,依然不可靠,可以利用setAccessible突破封裝,所以加final
		System.out.println(s1);
//		System.out.println(s2);
//		System.out.println(s3);

		//什麼時候創建的?類加載就創建,如果沒有使用的話則浪費空間
		//線程安全嗎?天生線程安全,無鎖
		
		

		Singleton1 s11 =Singleton1.getInstance();
//		Singleton1 s12 =Singleton1.getInstance();
//		Singleton1 s13 =Singleton1.getInstance();
		System.out.println(s11);
//		System.out.println(s12);
//		System.out.println(s13);
		
		//調用時創建的
		//線程不安全,容易創建不同對象,上鎖後安全,但效率低
		
		
		Singleton2 s23 =Singleton2.getInstance();
		System.out.println(s23);
	}
}
//餓漢式:天生線程安全,無鎖。類加載時創建,但是不用的時候也被創建了,佔用資源
class Singleton{
	private static final Singleton instance = new Singleton();
	private Singleton() {}
	
	public static Singleton getInstance() {
		return instance;
	}
}
//懶漢式:使用時創建、天生線程不安全(加同步鎖)
class Singleton1{
	private static Singleton1 instance = null;
	private Singleton1(){}
	public synchronized static Singleton1 getInstance() {
		if(instance == null) {
			instance = new Singleton1();
		}
		return instance;
	}
}

//懶漢式:使用時創建、天生線程安全
class Singleton2{
	private Singleton2() {}
	private static class Holder{
		static final Singleton2 instance = new Singleton2();
	}
	public  static Singleton2 getInstance() {
		return Holder.instance;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章