1:什么是反射?
JAVA反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的字節(jié)碼文件對象。而解剖使用的就是Class類中的方法.所以先要獲取到每一個字節(jié)碼文件對應的Class類型的對象.
2:三種拿取字節(jié)碼文件的方式
Person person = new Person();//原來創(chuàng)建對象的方式
//拿取字節(jié)碼文件對象(第一種)
Class alz = person.getClass();
//拿取字節(jié)碼文件對象(第二種)
Class alzs =Person.class;
//數(shù)據(jù)庫里拿字節(jié)碼文件,通過反射(第三種)
Class aClass = Class.forName("com.pp.Person");
Person 實例類代碼如下圖所示:
package com.pp;
public class Person {
//成員變量
public String name;
public int age;
private String address;
//構(gòu)造方法
public Person() {
System.out.println("空參數(shù)構(gòu)造方法");
}
public Person(String name) {
this.name = name;
System.out.println("帶有String的構(gòu)造方法");
}
//私有的構(gòu)造方法
private Person(String name, int age){
this.name = name;
this.age = age;
System.out.println("帶有String,int的構(gòu)造方法");
}
public Person(String name, int age, String address){
this.name = name;
this.age = age;
this.address = address;
System.out.println("帶有String, int, String的構(gòu)造方法");
}
//成員方法
//沒有返回值沒有參數(shù)的方法
public void method1(){
System.out.println("沒有返回值沒有參數(shù)的方法");
}
//沒有返回值,有參數(shù)的方法
public void method2(String name){
System.out.println("沒有返回值,有參數(shù)的方法 name= "+ name);
}
//有返回值,沒有參數(shù)
public int method3(){
System.out.println("有返回值,沒有參數(shù)的方法");
return 123;
}
//有返回值,有參數(shù)的方法
public String method4(String name){
System.out.println("有返回值,有參數(shù)的方法");
return "哈哈" + name;
}
//私有方法
private void method5(){
System.out.println("私有方法");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";
}
}
3:通過反射拿構(gòu)造方法
a:拿取所有
Class c = Class.forName("com.pp.Person");//稱C為字節(jié)碼對象
//拿取多個構(gòu)造方法
Constructor[] cons = c.getDeclaredConstructors();
//遍歷每一個構(gòu)造方法
for(Constructor con :cons){
System.out.println(con);
四個構(gòu)造方法如下圖所示:
public com.pp.Person(java.lang.String,int,java.lang.String)
private com.pp.Person(java.lang.String,int)
public com.pp.Person(java.lang.String)
public com.pp.Person()
b:只拿其中一個構(gòu)造方法(比如拿取上面第一條)
Class c = Class.forName("com.pp.Person");
Constructor con = c.getDeclaredConstructor(String.class,int.class,String.class);
System.out.println(con);
結(jié)果如下:
public com.pp.Person(java.lang.String,int,java.lang.String)
4:創(chuàng)建對象(Public)
Class c = Class.forName("com.pp.Person");
Constructor con = c.getDeclaredConstructor(String.class,int.class,String.class);
Object instance = con.newInstance("張三", 12,"北京");
System.out.println(instance);
運行結(jié)果如下:
帶有String, int, String的構(gòu)造方法
Person [name=張三, age=12, address=北京]
5:私有構(gòu)造方法創(chuàng)建對象
Class c = Class.forName("com.pp.Person");
Constructor con = c.getDeclaredConstructor(String.class,int.class);
//暴力反射
con.setAccessible(true);//取消語言檢查
Object instance = con.newInstance("李四", 22);
System.out.println(instance);
運行結(jié)果:
帶有String,int的構(gòu)造方法
Person [name=李四, age=22, address=null]
6:拿取成員變量
A:拿取所有公開字段
Class c = Class.forName("com.pp.Person");
Field[] fields = c.getFields();
for(Field field:fields){
System.out.println(field);
運行結(jié)果如下圖:
只可以拿到公開字段name和age,因為address是私有的,所以看不到。
public java.lang.String com.pp.Person.name
public int com.pp.Person.age
B:拿取一個字段
Class c = Class.forName("com.pp.Person");
Field age= c.getField("age");
System.out.println(age);
結(jié)果如下:
public int com.pp.Person.age
7:通過反射創(chuàng)建對象獲取指定成員變量進行賦值操作
a:public字段
Class c = Class.forName("com.pp.Person");
Constructor declaredConstructor = c.getDeclaredConstructor(String.class);
Object instance = declaredConstructor.newInstance("王五");
Field age= c.getField("age");//public
//獲取值
age.get(instance);
//賦值
age.set(instance,12);
System.out.println( age.get(instance));
運行結(jié)果:
12
b:private字段
強制暴力反射拿到private字段
Class c = Class.forName("com.pp.Person");
Constructor Constructor = c.getDeclaredConstructor(String.class);
Object instance = Constructor.newInstance("王五");
Field address= c.getDeclaredField("address");//public
address.setAccessible(true);//跳過訪問權(quán)限
address.set(instance,"北京");
System.out.println( address.get(instance));
運行結(jié)果:
帶有String的構(gòu)造方法
北京
8:通過反射拿方法
a:public
Class c = Class.forName("com.pp.Person");
Constructor con= c.getDeclaredConstructor(String.class);//獲取單個構(gòu)造方法
Object instance = con.newInstance("lisi");
Method method = c.getMethod("method4", String.class);
Object invoke = method.invoke(instance,"王芝洋");
System.out.println(invoke);
運行結(jié)果如下圖所示:
帶有String的構(gòu)造方法
有返回值,有參數(shù)的方法
哈哈王芝洋
b:private
Class c = Class.forName("com.pp.Person");
Constructor con= c.getDeclaredConstructor(String.class);//獲取單個構(gòu)造方法
Object instance = con.newInstance("lisi");
Method method= c.getDeclaredMethod("method5");
method.setAccessible(true);//跳過訪問權(quán)限
Object invoke = method.invoke(instance,null);
System.out.println(invoke);
運行結(jié)果如下圖:
帶有String的構(gòu)造方法
私有方法
null