反射:
Java反射机制可以让我们在编译期之外的运行期检查类,接口,变量以及方法的信息。
可以通过反射获得Class对象 类名 修饰符 包信息 父类 实现的接口 构造器 方法 变量 注解信息
使用Java反射机制你可以运行期检查一个类的变量信息(成员变量)或者获取或者设置变量的值。
Java反射机制可以让我们在编译期之外的运行期检查类,接口,变量以及方法的信息。
可以通过反射获得Class对象 类名 修饰符 包信息 父类 实现的接口 构造器 方法 变量 注解信息
(1)获取类的class对象
两种情况三种方式
//第一种情况:在编译期知道一个类的名字的话,
//使用Object中的getClass()
person p=new person();
Class c = p.getClass();//已知类对象获取class对象
//第二种情况:不知道类对象的情况下
//任何数据类型的静态属性class
Class c1=person.class;
//Class类中的方法:forName(String className)类路径:包名.类名
Class c2 = Class.forName("classdemo.person");
//如果在调用Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,
//那么将会抛出ClassNotFoundException。
(2)通过字节码对象获取构造方法并使用
分为两种情况:获取全部1个或者多个构造方法(也可能1个)
//先获取字节码对象
Class c = Class.forName("classdemo.person");
//获取多个构造方法:
//public Constructor<?>[] getConstructors()
//Class 对象所表示的类的所有公共构造方法
Constructor[] cons = c.getConstructors();
//public Constructor<?>[] getDeclaredConstructors()
//获取当前字节码文件对象中的所有的构造方法
Constructor[] conds = c.getDeclaredConstructors();
//获取1个构造方法(特指的构造方法)
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
// 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor con = c.getConstructor();//获取无参构造方法
Constructor con2 = c.getConstructor(int.class);
//如果没有指定的构造方法能满足匹配的方法参数则会抛出:NoSuchMethodException。
//通过字节码获取到的构造方法创建对象
//newInstance(Object... initargs)
//使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
//无参构造
Object n1 = con.newInstance();
//有参,参数是int类型创建对象
Object n2 = con2.newInstance(18);
//用私有的构造方法创建对象
//person中有private person(String name){}的私有构造方法
//class提供了私有变公共的方法
//public void setAccessible(boolean flag)
//值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
Constructor son3 = c.getDeclaredConstructor(String.class);
son3.setAccessible(true);
Object n3 = son3.newInstance("张三");
System.out.println(n3);
//输出:Person [name=张三, age=0, address=null]
通过字节码文件获取成员变量使用Java反射机制你可以运行期检查一个类的变量信息(成员变量)或者获取或者设置变量的值。
通过使用java.lang.reflect.Field类就可以实现功能。
//创建class对象
Class c = Class.forName("classdemo.person");
//获取同一类的成员变量或者所有的
//获取所有的公共的成员变量
//public Field[] getFields()
//API:返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Field[] fs1 = c.getFields();
//获取所有的成员变量(无论是否私有)
//public Field[] getDeclaredFields():获取当前字节码文件对象中所有的字段
//API:返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
Field[] fs2 = c.getDeclaredFields();
//通过class创建对象
Constructor con = c.getConstructor();
Object n = con.newInstance();
//获取指定的成员变量
//public Field getField(String name):获取的是公共的字段
//API:返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field addressf = c.getField("address");
//public void set(Object obj,Object value)
//API:将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
//参数1:表示给哪个对象设置当前字段的值
//参数2:表示给当前获取的哪个Field对象的字段设置一个新的值
addressf.set(n, "西安");
System.out.println(n);
//输出:Person [name=null, age=0, address=西安]
//获取指定私有的成员变量
//person中有 private String name ;
//public Field getDeclaredField(String name):指定的字段
//API: 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
//依然用 setAccessible(boolean flag)方法来取消 Java 语言访问检查
Field namef = c.getDeclaredField("name");
namef.setAccessible(true);
namef.set(n, "张三");
System.out.println(n);
//输出:Person [name=张三, age=0, address=西安]
通过字节码获取成员方法并使用
//创建person的class对象
Class c = Class.forName("classdemo.person");
Constructor con = c.getConstructor();
Object n = con.newInstance();
//获取同一类型的方法
//public Method[] getMethods()
//获取当前字节码文件对象中的所有的公共的成员方法(包括父类中的)
//API: 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口
//(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method[] ms1 = c.getMethods();
//public Method[] getDeclaredMethods()
//获取所有公共的成员方法
//返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,
//包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method[] ms2 = c.getDeclaredMethods();
//获取指定的成员方法
//调用无参公共方法
//过去公共的
//public Method getMethod(String name, Class<?>... parameterTypes)
// 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
//参数1: 表示方法名
//参数2:表示当前方法的参数数据类型的静态class属性
Method m1 = c.getMethod("show");
//public Object invoke(Object obj, Object... args)
//API: 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
//参数1:指定的哪个对象上调用底层invoke(),
//参数2:表示的调用那个方法所传递的实际参数
m1.invoke(n);//调用show方法
//输出:show Person
//调用有参公共方法
Method m2 = c.getMethod("method", String.class);
m2.invoke(n,"java");
//输出:methodjava
//获取指定私有方法
//person私有方法:private void function(){
// System.out.println(str+"function Preson");}
//调方法
Method m3 = c.getDeclaredMethod("function",String.class);
//取消 Java 语言访问检查
m3.setAccessible(true);
//用方法
m3.invoke(n, "hello");
//输出:hellofunction Preson