1.反射的概念:
Java的反射机制是在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能成为Java语言的反射机制。
获取该类的字节码文件对象——>class类对象(通过class类对象获取该类里的一些属性<成员变量,构造方法,成员方法>)
2.获取类的字节码文件对象的三种方法
(1)Object类中的getClass() 方法此方法表示正在运行的类:Class类
(2)数据类型的class属性(例如String.class,Student.class)
*(3)Class类中的特有方法:forName(String className)获取字节码文件对象
注:此种方法内的参数className为类的全路径名称
1.成员方法:
(1)public static Class> forName(String className)返回字类的节码文件对象
(2)获取构造器
①public Constructor
返回一个Constructor对象,此 Class 对象所表示的类的指定公共构造方法(只可访问公共构造方法)
②public Constructor>[] getConstructors()
返回一个Constructor对象,这些对象反映此 Class 对象所表示的类的所有公共构造方法
③ public Constructor
该对象反映此 Class 对象所表示的类或接口的指定构造方法(包括私有)
注:此方法可访问私有构造方法,但需加上Constructor类中的setAccessible(true) 方法,取消Java语言访问检查
④public Constructor>[] getDeclaredConstructors()
这些对象反映此 Class 对象表示的类声明的所有构造方法(包括私有)
(3)获取成员变量
①public Field getField(String name)
它反映此 Class 对象所表示的类或接口的指定公共成员字段
②public Field[] getFields()
这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
③public Field getDeclaredField(String name)
该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有)
④public Field[] getDeclaredFields()
这些对象反映此 Class 对象所表示的类或接口所声明的所有字段(包括私有)
(4)获取成员方法
①public Method getMethod(String name,Class>... parameterTypes)
它反映此 Class 对象所表示的类或接口的指定公共成员方法
②public Method[] getMethods()
这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的 那些的类或接口)的公共 member 方法
注:该方法会返回此类的所有方法,包括继承的方法
③public Method getDeclaredMethod(String name,Class>... parameterTypes)
该对象反映此 Class 对象所表示的类或接口的指定已声明方法(此方法可获取单个私有方法)
④public Method[] getDeclaredMethods()
这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方 法,但不包括继承的方法
注:此方法返回此类的所有方法,但不包括继承的方法
1.getConstructor(Class>... parameterTypes)
2.getConstructors()
3.getDeclaredConstructor(Class>... parameterTypes)
4.getDeclaredConstructors()
步骤:
(1)通过forName() 方法获取类的字节码文件对象Class c
(2)通过getConstructor() 方法获取构造器Constructor对象
(3)通过Constructor 的newInstance() 方法创建类的实例Object obj
注:setAccessible(true)方法可以取消Java语言访问检查(可以访问私有构造方法)
1.getField(String name)
2.getFields()
3.getDeclaredField(String name)
4.getDeclaredFields()
步骤:
(1)通过forName() 方法获取类的字节码文件对象Class c
(2)通过getConstructor() 方法获取构造器Constructor对象
(3)通过Constructor 的newInstance() 方法创建类的实例Object obj
需先创建构造器实例
(4)通过Constructor 的getField()方法获取Field对象
(5)通过Field 中的set(Object obj, Object value)方法给成员变量设置值
注:setAccessible(true)方法可以取消Java语言访问检查(可以访问私有成员变量)
1.getMethod(String name,Class>... parameterTypes)
2.getMethods()
3.getDeclaredMethod(String name,Class>... parameterTypes)
4.getDeclaredMethods()
步骤:
(1)通过forName() 方法获取类的字节码文件对象Class c
(2)通过getConstructor() 方法获取构造器Constructor对象
(3)通过Constructor 的newInstance() 方法创建类的实例Object obj
需先创建构造器实例
(4)通过 Constructor 中的getMethod(String name,Class>... parameterTypes)方法获取Method对象(5)通过Method 中的public Object invoke(Object obj, Object... args) 方法赋值获得新的Object对象
注:setAccessible(true)方法可以取消Java语言访问检查(可以访问私有成员方法)
例1:获取类的字节码文件对象的三种方法
// 测试类
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1:通过Object类中的getClass() 方法
Person p1 = new Person();
Class c1 = p1.getClass(); // 得到Person.class字节码文件对象
// 创建对象
Person p2 = new Person();
Class c2 = p1.getClass(); // Person.class字节码文件对象
System.out.println(p1 == p2);// false
System.out.println(c1 == c2);// true
System.out.println("--------------------");
// 方式2:通过数据类型的Class属性
Class c3 = Person.class; // 加载并且获得person.class字节码文件对象
System.out.println(c3 == c1);
System.out.println("----------------------");
// 方式3:获取类的字节码文件
// 参数需要类路径:类的全路径名称
Class c4 = Class.forName("Reflect1.Person");
System.out.println(c4 == c1);
}
}
// 自定义Person类
public class Person {
//成员变量
private String name ;
int age ;
public String address ;
public Person(){}
private Person(String name) {
this.name = name;
}
Person(String name,int age){
this.name = name ;
this.age = age ;
}
public Person(String name,int age,String address){
this.name = name ;
this.age =age ;
this.address = address ;
}
//提供一些成员方法
public void show(){
System.out.println("show");
}
public void method(String s){
System.out.println("method"+s);
}
public String getString(String s, int i) {
return s + "---" + i;
}
private void function(){
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
例2:通过反射获取构造方法(单个私有构造方法)
import java.lang.reflect.Constructor;
public class ConstructorTest {
public static void main(String[] args) throws Exception {
// 1)获取Person类的字节码文件对象
Class c = Class.forName("Reflect1.Person");
// 2)获取私有的构造方法
// public Constructor getDeclaredConstructor(Class>... parameterTypes)
Constructor con = c.getDeclaredConstructor(String.class);
// 3)取消 Java 语言访问检查 setAccessible(boolean flag) 强制性可以访问私有构造方法
con.setAccessible(true);
// 4)创建构造器的实例对象,可以去传递实际参数
Object obj = con.newInstance("伊卡尔迪");
System.out.println(obj);
}
}
例3:获取成员变量并使用
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class FieldTest {
public static void main(String[] args) throws Exception {
// 1)通过反射获取字节码文件对象
Class c = Class.forName("Reflect1.Person");
// 2)创建构造器实例
Constructor con = c.getConstructor();
Object obj = con.newInstance(); // Person的实例对象
// 3)获取成员变量并赋值
// public Field getField(String name):获取公共的指定的字段 参数为当前成员变量名称"address"
Field addressFiled = c.getField("address");
// 赋值 public void set(Object obj, Object value)给obj实例对象里面的成员变量设置一个实际参数---->value
addressFiled.set(obj, "米兰");
System.out.println(obj);
System.out.println("-----------------------------");
// 给name赋值并使用(私有)
// public Field getDeclaredField(String name):获取类或接口中已经声明的指定的字段
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true); // 取消Java语言访问检查
nameField.set(obj, "伊卡尔迪");
System.out.println(obj);
System.out.println("-------------------------------");
// 给age字段赋值并使用
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);// 取消Java语言访问检查
ageField.set(obj, 27);
System.out.println(obj);
}
}
例4:获取成员方法并使用
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class MethodTest {
public static void main(String[] args) throws Exception {
// 1)通过反射获取字节码文件对象并使用
Class c = Class.forName("Reflect1.Person");
// 获取构造器对象,通过构造器创建当前字节码文件的实例对象
Constructor con = c.getConstructor();
Object obj = con.newInstance(); // Person对象
// 2)获取单个成员方法
/**
* public Method getMethod(String name,Class>... parameterTypes):指定公共成员方法
* 参数1:表示方法名 参数2:该方法的参数类型的Class对象(数据类型的class属性) String.class
*/
Method m1 = c.getMethod("show");
/**
* public Object invoke(Object obj, Object... args) 参数1:表示当前针对哪个以实例对象进行方法的调用
* 参数2:当前调用该方法的时候里面传递的实际参数
*/
m1.invoke(obj);
System.out.println("----------------------------");
// 3)调用Method方法 public void method(String s)
Method m2 = c.getMethod("method", String.class);
m2.invoke(obj, "word");
System.out.println("----------------------------");
/**
* public String getString(String s, int i) { return s + "---" + i; }
*/
// 4)调用getString()方法
Method m3 = c.getMethod("getString", String.class, int.class);
Object objString = m3.invoke(obj, "hello",100) ;
System.out.println(objString);
//String objString = (String) m3.invoke(obj, "hello", 100); // 向上转型
System.out.println(objString);
System.out.println("--------------------------");
// 5)调用function()方法 私有方法
// 该方法是私有的,public Method getDeclaredMethod(String name,Class>...
// parameterTypes)
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);// 取消Java语言的访问检查
m4.invoke(obj);
}
}