//正常的调用 正射
Apple apple=new Apple();
apple.setPrice(20);
System.out.println("Apple Price:" + apple.getPrice());
//反射调用类中的方法
Class clz = Class.forName("com.test.reflex.Apple");
Method setPriceMethod = clz.getMethod("setPrice", int.class);
Constructor appleConstructor = clz.getConstructor();
Object appleObj = appleConstructor.newInstance();
setPriceMethod.invoke(appleObj, 14);
所以说什么是反射?反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
反射操作的步骤
获取类的 Class 对象实例(有三种方法,任意一种都可以,等价)
Class clz = Class.forName("com.test.reflex.Apple");
//Class clz =Apple.class;
//String apple= new Apple();
//Class clz = apple.getClass();
根据 Class 对象实例获取 Constructor 对象
Constructor appleConstructor = clz.getConstructor();
使用 Constructor 对象的 newInstance 方法获取反射类对象
Object appleObj = appleConstructor.newInstance();
而如果要调用某一个方法,则需要经过下面的步骤:
获取方法的 Method 对象
利用 invoke 方法调用方法
公有方法使用getMethod,int.class是setPrice的参数类型,若方法无参,则去掉
Method setPriceMethod = clz.getMethod("setPrice", int.class);
setPriceMethod.invoke(appleObj, 14);//给方法传入参数14
私有方法使用getDeclaredMethod,并且要用setAccessible置为true
Method m1 = clz.getDeclaredMethod("say");
m1.setAccessible(true);
Constructor cons1 =clz.getConstructor();
Object p = cons1.newInstance();
m1.invoke(p);
//调用多个参数的方法如下 原方法如下public void showme(String name,int age,String job ){...}
Class[] obj={String.class,int.class,String.class};
Method ms = c1.getDeclaredMethod("showme",parameterTypes);
ms.setAccessible(true);
Constructor cons1 = c1.getConstructor();
Object p = cons1.newInstance();
ms.invoke(p,"张三",30,"教师");
不加Declared的只能获取公共的
加Declared能获取所有,包括私有的,使用加Declared方法后要setAccessible为true
反射引用了java.lang.reflect包,其中包括了
Field,Method,Constructor,获取时用
getField(),getMethod()或者getDeclaredField(),getDeclaredMethod()方法 都有参数
Class c2 = Person.class;
//获得指定的属性
Field f1 = c2.getField("age");
//获得指定的私有属性
Field f2 = c2.getDeclaredField("name");
//启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问
f2.setAccessible(true);
而Field[],Method[],Constructor[]是其对应的数组 获取时用
getFields(),getMethods()或者getDeclaredFields(),getDeclaredMethods()方法 都有参数
Class c2 = Person.class;
//获得类的public类型的属性。
System.out.println("2------------");
Field[] fields = c2.getFields();
for(Field field : fields){
System.out.println(field.getName());//age
}
//获得类的所有属性。包括私有的
System.out.println("3------------");
Field [] allFields = c2.getDeclaredFields();
for(Field field : allFields){
System.out.println(field.getName());//name age
}
//获得类的public类型的方法。这里包括 Object 类的一些方法
System.out.println("4------------");
Method [] methods = c2.getMethods();
for(Method method : methods){
System.out.println(method.getName());//work waid equls toString hashCode等
}
//获得类的所有方法。
System.out.println("5------------");
Method [] allMethods = c2.getDeclaredMethods();
for(Method method : allMethods){
System.out.println(method.getName());//work say
}
通过反射创建类对象
通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。
第一种:通过 Class 对象的 newInstance() 方法。
Class clz = Apple.class;
Apple apple = (Apple)clz.newInstance();
第二种:通过 Constructor 对象的 newInstance() 方法
Class clz = Apple.class;
Constructor constructor = clz.getConstructor();
Apple apple = (Apple)constructor.newInstance();
通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。下面的代码就调用了一个有参数的构造方法进行了类对象的初始化。
Class clz = Apple.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Apple apple = (Apple)constructor.newInstance("红富士", 15);
反射的完整例子如下