40.反射
java反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法。
对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息及动态调用对象的方法的功能称为java的反射机制。
要想对字节码文件进行解剖,必须要有字节码文件对象。
如何获取字节码文件对象呢?
先建立Person对象
public class Person { private int age; private String name; public Person(){ System.out.println("person run"); } public Person(String name,int age){ super(); this.age=age; this.name=name; System.out.println("person param run"+this.name+":"+this.age); } public void show(){ System.out.println(name+"...show run..."+age); } private void privateMethod(){ System.out.println("method run"); } public void paramMethod(String str,int num){ System.out.println("paramMethod run......"+str+":"+num); } public static void staticMethod(){ System.out.println("static method run"); } }
public class ReflectDemo_01 { public static void main(String[] args) throws ClassNotFoundException { // TODO Auto-generated method stub //getClassObj_1(); //getClassObj_2(); getClassObj_3(); } /* * 获取字节码对象的方式: * 1.Object类中的getClass()方法。 * 想要用这种方式,必须要明确具体的类,并创建对象。麻烦 */ public static void getClassObj_1(){ Person p=new Person(); Class clazz=p.getClass(); Person p1=new Person(); Class clazz1=p1.getClass(); System.out.println(clazz==clazz1);//true 依赖同一个class类对象完成的 } /* *方式二: *2.任何数据类型都具备一个静态的属性.class来获取其对应的Class对象 *相对简单,但是还是要明确用到类中的静态成员class。还是不够扩展。 */ public static void getClassObj_2(){ Class clazz=Person.class; Class clazz1=Person.class; System.out.println(clazz==clazz1); //true } /* * 方式三: * 3.只要通过给定的类的字符串名称就可以获取该类,更为扩展。可以用Class类中的方法完成。该方法就是forName * 这种方式 只要有名称即可,更为方便,扩展性更强 */ public static void getClassObj_3() throws ClassNotFoundException{ String className="day26.Person"; //带包名 Class clazz=Class.forName(className); System.out.println(clazz); } }
构造器
public class ReflectDemo_02 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { // TODO Auto-generated method stub //createNewObj(); createNewObj_1(); } public static void createNewObj() throws ClassNotFoundException, InstantiationException, IllegalAccessException{ //早期:new的时候先根据被new的类的名称找寻该类的字节码文件,加载进内存,并且创建该字节码文件对象,接着创建该字节文件对应的Person对象 //Person p=new Person(); //person run //现在: String name="day26.Person"; //找寻该名称类文件,加载进内存,并产生Class对象 Class clazz=Class.forName(name); //如何产生该类的对象呢? Object obj=clazz.newInstance(); } public static void createNewObj_1() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ //Person p=new Person("zhangsan",22); /* * 当要获取指定名称对应的类中所写的对象时,而该对象初始化不使用空参数构造函数时,该怎么办? * 既然是通过指定的构造函数进行对象的初始化,所以应该先获取到该构造函数。通过字节码文件对象即可完成。 * 该方法是:getConstructor(paramterTypes) */ String name="day26.Person"; Class clazz=Class.forName(name); //获取到指定的构造函数对象 Constructor cons=clazz.getConstructor(String.class,int.class); //任何数据类型都可以被class描述 //通过该构造器的newInstance方法进行对象的初始化 Object obj=cons.newInstance("小明",29); } }
属性
public class ReflectDemo_03 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub getFieldDemo(); } /* * 获取字节码文件中的字段 */ public static void getFieldDemo() throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException{ Class clazz=Class.forName("day26.Person"); Object obj=clazz.newInstance(); Field field=clazz.getDeclaredField("age"); //只能获取本类,但包含私有 //对私有字段的访问,取消权限检查。暴力访问 field.setAccessible(true); field.set(obj, 39); //返回指定对象上此 Field 表示的字段的值。 Object o=field.get(obj); System.out.println(o); } }
方法
public class ReflectDemo_04 { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //getMethodDemo(); getMethodDemo_1(); //getMethodDemo_2(); } /* * 获取指定Class中的所有公共函数 */ public static void getMethodDemo() throws Exception{ Class clazz=Class.forName("day26.Person"); Method[] methods=clazz.getMethods(); //获取的都是共有的方法 methods=clazz.getDeclaredMethods(); //只获取本类中所有方法,包括私有的 for(Method m:methods){ System.out.println(m); } } /* * 调取无参方法 */ public static void getMethodDemo_1() throws Exception{ Class clazz=Class.forName("day26.Person"); Method method=clazz.getMethod("show", null); //获取空参数一般方法 //给对象赋值 Constructor cons=clazz.getConstructor(String.class,int.class); Object obj=cons.newInstance("小明",37); //调用方法 method.invoke(obj, null); } /* * 调取有参方法 */ public static void getMethodDemo_2() throws Exception{ Class clazz=Class.forName("day26.Person"); Method method=clazz.getMethod("paramMethod", String.class,int.class);//获取有参构造器 Object obj=clazz.newInstance(); method.invoke(obj,"张三",29); } }