概述:
- 通过一个Class文件对象去使用或者修改文件对象中的成员变量,构造方法,成员方法(无论是否私有,都能获取并使用)
之前学习:
- 我们在使用成员之前,得先有一个java文件,然后在实例化的时候,new一下就完事了。
Person p = new Person();
p.eat("汉堡");
现在的船新概念:
- 总归来说,无论是调用什么成员,都是有个对象,归根结底,对象是根据类来的,实际上底层是依赖一个class文件
对于java程序来说,依赖的是这个class文件对应的Class文件对象。
class类:
- 成员变量:Field
- 构造方法:Constructor
- 成员方法:Method
- 方式1:通过Object类中的getClass()方法,返回此Object类的运行时的类
- 方式2:在不new的前提下,获取该类的class文件对象,java中每一个类都有一个静态的属性class
- 方式3:Class类中有一个静态的方法,获取该类的class文件对象 (最常用的)
获取对象对应的class文件对象代码
public class ReflexDemo1 { public static void main(String[] args) { //方式一:通过Object类中的getClass()方法,返回此Object类运行时的类 Person person1 = new Person(); Class<? extends Person> c1 = person1.getClass(); Person person2 = new Person(); Class<? extends Person> c2 = person2.getClass(); System.out.println(c1 == c2); //true //方式二:在不 new 的情况下,获取该类的class文件对象,java中的每一个类都有一个静态的属性class Class<Person> c3 = Person.class; System.out.println(c1 == c3); //true System.out.println(c2 == c3); //true //方式三:Class类中有一个静态方法,获取该类的class文件对象(最常用的) //static Class<?> forName(String className) //返回与给定字符串名称的类或接口相关联的 类对象。 try { Class<?> c4 = Class.forName("com.bigdat.java.day29.Person"); System.out.println(c4); System.out.println(c1 == c4); //true System.out.println(c1 == c4); //true } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
- getConstructors() 返回一个包含Constructor对象的数组,反映由此Constructor对象表示的类的所有公共类函数
- getDeclaredConstructors() 获取的是该类中的所有构造方法,包括私有,被保护的,默认的,公共的
- getConstructor() 返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。
- getDeclaredConstructor() 获取单个私有的带参数的构造方法
- newInstance(Object... initargs)
使用此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。如果使用带参数的构造方法用newInstance创建对象,参数必须一样。形如:Object o = con1.newInstance("张三");- 如果获取带参数的构造方法,里面填的参数是:**类型.class** 。
如:Constructor<?> con2 = c1.getDeclaredConstructor(String.class, int.class);
public class ReflexDemo2 { public static void main(String[] args) { //获取person类的Class文件对象 Class<?> c1 = null; try { c1 = Class.forName("com.bigdatjava.day29.Person"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //获取Class文件对象的构造方法 //public Constructor<?>[] getConstructors() throws SecurityException //返回一个包含Constructor对象的数组,反应由此Constructor对象表示的类的所有的公共类函数 Constructor<?>[] cons1 = c1.getConstructors(); for (Constructor<?> c : cons1) { System.out.println(c); } System.out.println("==========================================================="); //public Constructor<?>[] getDeclaredConstructors() throws SecurityException //返回Constructor 对象表名的类声明的所有Constructor对象的数组类 //获取的是该类中的所有构造方法,包括私有,被保护,默认和公共的 Constructor<?>[] cons2 = c1.getDeclaredConstructors(); for (Constructor<?> c : cons2) { System.out.println(c); } System.out.println("================================================================="); //获取单个的构造方法 //Constructor<T> getConstructor(类<?>... parameterTypes) //返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。 Constructor<?> con1 = null; try { con1 = c1.getConstructor(String.class); System.out.println(con1); } catch (NoSuchMethodException e) { e.printStackTrace(); } //获取单个私有的带参数的构造方法 // Constructor<?> con2 = c1.getConstructor(String.class, int.class); // System.out.println(con2); Constructor<?> con2 = null; try { con2 = c1.getDeclaredConstructor(String.class, int.class); System.out.println(con2); } catch (NoSuchMethodException e) { e.printStackTrace(); } System.out.println("======================================================================"); //使用公共的构造方法创建对象 //使用公共的构造方法创建对象 //T newInstance(Object... initargs) //使用此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。 try { Object o = con1.newInstance("我真蠢!"); Person p = (Person)o; // 向下转型 System.out.println(p); } catch (Exception e) { e.printStackTrace(); } try { con2.setAccessible(true); Object two = con2.newInstance("我是小垃圾", 19); // 向下转型 Person o1 = (Person) two; System.out.println(o1); } catch (Exception e) { e.printStackTrace(); } } }
- 当还是象访问公共对象去访问私有变量时会报 IllegalAccessException 非法的访问异常
- 通过setAccessible(true)方法暴力访问。值是true的化,表示反射对象在使用的时候,取消Java语言的访问检查
public class ReflexDemo3 { public static void main(String[] args) { Class<?> a = null; try { a = Class.forName("com.bigdat.java.day29.Person"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //获取私有的构造方法 Constructor<?> dec1 = null; try { dec1 = a.getDeclaredConstructor(String.class, int.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { // .IllegalAccessException 非法的访问异常 //构造方法是私有的,可以获取的到,但是不能这么使用 //通过构造方法创建对象 //暴力访问 dec1.setAccessible(true); // 如果这里是 true 的话,表示反射对象在这里用的话,取消Java语言的访问检查 Object xh = dec1.newInstance("小花", 100); //向下转型 Person p = (Person) xh; System.out.println(p); p.eat("红烧肉"); } catch (Exception e) { e.printStackTrace(); } } }
- getFields() 返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象。获取当前类所有被public修饰的成员变量
- getDeclaredFields() 返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。获取当前类中所有的成员变量,包括私有的,公共的,被保护的,默认的字段,不包括继承的字段。
- getField() 获取单个的成员变量
- getDeclaredField() 获取私有的成员变量并赋值
- 暴力访问: name.setAccessible(true);
public class ReflexDemo4 { public static void main(String[] args)throws Exception { Class<?> c1 = null; //获取Class的文件对象 try { c1 = forName("com.bigdat.java.day29.Person"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //Field[] getFields() //返回一个包含一个数组的 Filed 对象反射由此表示的类或接口的所有可访问的公共字段 类对象。 //获取当前类所有被public修饰的成员变量 Field[] fields = c1.getFields(); for (Field field : fields) { System.out.println(field); //public java.lang.String com.bigdat.java.day29.Person.id } System.out.println("=============================================================="); //Field[] getDeclaredFields() //返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。 //获取当前类中所有的成员变量,包括私有的,公共的,被保护的,默认的字段,不包括继承的字段。 Field[] dec = c1.getDeclaredFields(); for (Field field : dec) { System.out.println(field); } System.out.println("-----------------------------------------------------------------"); //此方法并不能获得该类继承的其父类的任何属性 Class<?> c2 = null; try { c2 = forName("com.bigdat.java.day29.B"); } catch (ClassNotFoundException e) { e.printStackTrace(); } Field[] declaredFields = c2.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } System.out.println("========================================================"); //获取Class文件的对象 Class<?> c = forName("com.bigdat.java.day29.Person"); //通过 getConstructor 方法来创建一个构造器 Constructor<?> ctr = c.getConstructor(); //通过构造方法来创建一个对象 Object o = ctr.newInstance(); //获取单个的成员变量 Field id = c1.getField("id"); //void set(Object obj, Object value) //将指定对象参数上的此 Field对象表示的字段设置为指定的新值。 //id.set(o,"1001");//给对象o中的成员变量id赋值为"1001" id.set(o, "1001"); System.out.println(o); //获取私有的成员变量并赋值 Field name = c1.getDeclaredField("name"); name.setAccessible(true); // 在使用私有的成员变量时需要进行暴力访问 name.set(o, "名字"); System.out.println(o); // IllegalAccessException 不暴力访问的话会报异常 System.out.println("================================================================"); Field age = c1.getDeclaredField("age"); age.set(o, 101); System.out.println(o); Field address = c1.getDeclaredField("address"); address.set(o,"中国-云南-保山"); System.out.println(o); } } class A{ private String aaa; public int bbb; } class B extends A{ }
-== Method[] getMethods()== 返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。
- getDeclaredMethods() 获取本类中的所有方法,包括私有的,被保护的,默认的,公共的。不获取继承关系父类中的方法
public class ReflexDemo5 { public static void main(String[] args) throws Exception{ //获取person类的class文件对象 Class<?> c = Class.forName("com.bigdat.java.day29.Person"); //获取方法 //Method[] getMethods() //返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。 //获取本类以及父类中所有的公共方法(被public所修饰的方法) Method[] methods = c.getMethods(); for (Method method : methods) { System.out.println(method); } System.out.println("==========================================================="); //获取本类中的所有方法,包括私有,被保护,默认,公共的方法,但是不获取继承关系的父类方法 Method[] declaredMethods = c.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } System.out.println("======================================================================"); //创建对象的构造器 Constructor<?> con = c.getConstructor(); Object o = con.newInstance(); //获取单个的方法并使用 //Object invoke(Object obj, Object... args) //在具有指定参数的 方法对象上调用此 方法对象表示的底层方法。 Method fun1 = c.getMethod("fun1" ); fun1.invoke( o ); System.out.println("================================================================================"); //获取私有的成员方法使用 Method fun2 = c.getDeclaredMethod("fun2",String.class); `fun2.setAccessible(true);` fun2.invoke( o ,"你好!"); System.out.println("=================================================================================="); Method fun3 = c.getDeclaredMethod("fun3"); fun3.invoke( o ); Method fun4 = c.getDeclaredMethod("fun4" ); fun4.invoke( o ); } }