java反射基本知識

1.反射是什麼

反射機制:指在運行狀態下,對於任意一個類,可以知道該類的屬性和方法、並且可以調用它們;這種動態獲取信息以及動態調用對象方法的功能成爲Java 語言的反射機制。 現有的框架都以反射爲基礎,是將框架和類揉在一起的調和劑。

2.反射核心類

2.1 Class類

Class爲反射核心類,Class第一個字母爲大寫,注意不是class,在運行的時候,jvm中只會含有一份Class對象。先創建一個A類,下面所有的例子均以此爲基礎。

public class A {
    public String address;
    private int age;
    private String name;

    public A() {
    }
    public A(int age, String name) {
        this.age = age;
        this.name = name;
    }
    private A (int age){
    }

    public int getAge() {
        return age;
    }

    @Deprecated
    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private void setAge1(int age){
        this.age = age;
    }
    @Override
    public String toString() {
        return "A{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

創建Class對象有三種方式。

 //一:得到Class的三種方式
    //1.使用class靜態成員變量
    Class c1 = A.class;
    //2.使用對象的getClass()
    Class c2 = a.getClass();
    //3.通過路徑名得到
    Class c3 = Class.forName("reflex.A");
     
	//驗證是否相等
    System.out.println(c1==c2);
    System.out.println(c2==c3);

    //打印結果爲:
    true
    true

打印結果均爲true,說明不管用哪種方式得到的Class對象,都是同一個。

2.2 創建一個對象的方法

由於可以通過Class類得到該類的屬性和方法,這樣的話,也會導致創建該類的對象有多種。

 	//第一種方式new
    A b = new A();
    //第二種方式,通過得到的Class對象的newInstance();
    A c = (A) c1.newInstance();
    //第三種方式,通過用Constructor對象的 newInstance()方法,參數爲Class類型。
    Constructor constructor = c1.getConstructor(int.class,String.class);
    A d = (A) constructor.newInstance(18,"zhangsan");
   
    //打印結果爲: 
    A{age=0, name='null'}
    A{age=0, name='null'}
    A{age=18, name='zhangsan'}

3.Constructor類

通過Class對象得到該類的構造函數的方法,主要有四種,區別在於指定、所有、還有公有等。

//第一種方式:返回類的特定的public的構造函數,參數可以指定
Constructor Constructor1 = c1.getConstructor(int.class,String.class);
System.out.println("第一種方式:");
System.out.println(Constructor1);

//第二種方式:返回類的所有的public的構造函數
Constructor[] Constructor2 = c1.getConstructors();
System.out.println("第二種方式:");
for(Constructor constructor : Constructor2){
	System.out.println(constructor);
}
//第三種方式:返回類的特定的構造函數(不限制爲Public),參數可以指定
Constructor Constructor3 = c1.getDeclaredConstructor(int.class);
System.out.println("第三種方式:");
System.out.println(Constructor3);

//第四種方式:返回類的所有的構造函數
Constructor[] Constructor4 = c1.getDeclaredConstructors();
System.out.println("第四種方式:");
for(Constructor constructor : Constructor4){
	System.out.println(constructor);
}

//打印結果爲:
第一種方式:
public reflex.A(int,java.lang.String)
第二種方式:
public reflex.A(int,java.lang.String)
public reflex.A()
第三種方式:
private reflex.A(int)
第四種方式:
private reflex.A(int)
public reflex.A(int,java.lang.String)
public reflex.A()

4.Field類

通過Class對象得到該類的方法,主要有四種,區別在於指定、所有、還有公有等。

//第一種方式:通過getField(),根據名稱獲取public成員變量
Field field1 = c1.getField("address");
System.out.println("第一種方式");
System.out.println(field1);

//第二種方式:通過getFields()獲取所有的public成員變量
Field[] fields2 = c1.getFields();
System.out.println("第二種方式");
for(Field field:fields2){
	System.out.println("成員變量名稱:" +field.getName());
}

//第三種方式:通過getDeclaredField(),根據名稱獲取成員變量,不包含父類
Field field3 = c1.getDeclaredField("age");
System.out.println("第三種方式");
System.out.println(field3);
//第四種方式:通過getDeclaredFields(),獲取所有的成員變量,不包含父類
Field[] fields4 = c1.getDeclaredFields();
System.out.println("第四種方式");
for(Field field:fields4){
	System.out.println("成員變量名稱:" +field.getName());
}

//打印結果爲:
第一種方式
public java.lang.String reflex.A.address
第二種方式
成員變量名稱:address
第三種方式
private int reflex.A.age
第四種方式
成員變量名稱:address
成員變量名稱:age
成員變量名稱:name

5.Method類

通過Class對象得到該類的變量,區別在於指定、所有、還有公有等

 //第一種方法:使用getMethod()得到指定的public方法,第一個參數方法名,後面爲參數類對應的Class對象
    Method method1 = c1.getMethod("setAge",int.class);
    System.out.println("第一種方法:");
    System.out.println(method1);
    //使用invoke調用方法,a是對象
    method1.invoke(a,20);
    System.out.println(a.getAge());
    
    //第二種方法:使用getMethods()得到所有的public方法,包括父類的Public方法
    Method[] methods2 = c1.getMethods();
    System.out.println("第二種方法:");
    for (Method method:methods2){
    	System.out.println(method);
    }
    //第三種方法:使用getDeclaredMethod()得到指定的方法,第一個參數方法名,後面爲參數類對應的Class對象
    Method method3 = c1.getDeclaredMethod("setAge1", int.class);
    System.out.println("第三種方法:");
    System.out.println(method3);
    
    //第四種方法:getDeclaredMethods()得到所有的方法,不包括父類的方法
    Method[] methods4 = c1.getDeclaredMethods();
    System.out.println("第四種方法:");
    for (Method method:methods4){
    	System.out.println(method);
    }

    //打印結果爲:
    第一種方法:
    public void reflex.A.setAge(int)
    20
    第二種方法:
    public java.lang.String reflex.A.toString()
    public java.lang.String reflex.A.getName()
    public void reflex.A.setName(java.lang.String)
    public void reflex.A.setAge(int)
    public int reflex.A.getAge()
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    第三種方法:
    private void reflex.A.setAge1(int)
    第四種方法:
    public java.lang.String reflex.A.toString()
    public java.lang.String reflex.A.getName()
    public void reflex.A.setName(java.lang.String)
    private void reflex.A.setAge1(int)
    public void reflex.A.setAge(int)
    public int reflex.A.getAge()

另外還可以得到該方法的參數、返回類型、方法名以及是否含有註解等基本信息。

 //得到類的方法,可以方法的名稱、返回類型
    Method method5 = c1.getMethod("setAge",int.class);
    System.out.println("-------");
    //然後可以得到方法的返回值類型的類類型
    Class returnType = method5.getReturnType();
    //得到方法的返回值類型的名字
    System.out.println("方法的返回類型:"+returnType.getName()+" ");
    //得到方法的名稱
    System.out.println("方法的名稱:"+method5.getName() + " ");
    //得到方法的參數
    Class[] paramTypes = method5.getParameterTypes();
    for (Class class1 : paramTypes) {
    	System.out.println("方法的參數:"+class1.getName()+" ");
    }
    Annotation[] annotations = method5.getAnnotations();
    for (Annotation annotation : annotations) {
    	System.out.println("註解:"+annotation+" ");
    }
    
    //打印的結果爲:
    方法的返回類型:void 
    方法的名稱:setAge 
    方法的參數:int 
    註解:@java.lang.Deprecated() 

6.總結

主要使用一個思維導圖來概括一下基本的函數和內容。
在使用反射得到該類的信息時,基本步驟爲:
1.首先得到該類的Class對象。
2.調用對應的方法,得到構造函數、方法、屬性。
3.在上面的基礎上,可以創建對象、調用函數、解析註解等操作
圖1

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