Java中的反射Reflection
反射知识:
获取类型模板对象有三种方式:
1. 通过对象调用Object类中的getClass()方法来获取Class对象。
2. 利用Class类中的forName( String className)方法来获取class对象。
注:其中的className即为类全名(类全名 =包名.类名)。
3. 通过类型名来获取class对象。
代码如下:
package day11.javaAdvance.exercise.reflection.Class; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ClassTest1 { public static void main(String[] args) throws Exception { /* * 获取类型模板对象有三种方法: */ // 1.通过对象调用getClass方法获取Class对象 Student stu = new Student("wangwang", 4); // 类型模板对象 Class c1 = stu.getClass(); System.out.println("1..." + c1); System.out.println("^^^" + c1.getName()); // 2.利用Class对象来获取 Class c2 = Class.forName("day11.javaAdvance.exercise.reflection.Class.Student");//方法:forName("类全名"); System.out.println("2..." + c2); // 3.通过类型名来获取 Class c3 = Student.class; System.out.println("3..." + c3); /* * 获得此类的属性方法 */ Field f[] = c1.getFields(); for (int i = 0; i < f.length; i++) { System.out.println("属性有:" + f[i].getName()); } } } class Student { public String name; public int age; public Student(String name, int age) { this.name = name; this.age = age; } private void show() { } public void print() { System.out.println("name=" + name + "," + "age=" + age); } }
通过反射方法动态来获取类中的方法和构造函数(五步)
1. 先获取类型模板对象:Class c=Student.class;
2. 通过类型模板对象来获取构造函数: Class arr[]={}; Constructor con=c.getDeclaredConstructor(arr);
3. 调用构造方法创建对象:Object obj1[]={}; Object obj=con.newInstance(obj1);
System.out.println(obj);
4. 获取方法:Method m=c.getMethod("show", arr);
5. 利用Mehtod对象调用方法invoke
Object o=m.invoke(obj, obj1);
package day11.javaAdvance.exercise.reflection.Class; import java.lang.reflect.Constructor; import java.lang.reflect.Method; /* * 重点: 通过反射方法动态来获取类中的方法以及构造函数(五步)。 */ public class ClassTest3 { public static void main(String[] args) throws Exception { // 1. 获得类型模板对象 Class cc = Studentd.class; // 2.通过类型模板对象来获取构造方法 Class arrl[] = {}; // 在java.lang.reflect 类 Constructor<T>包中 Constructor cons = cc.getDeclaredConstructor(arrl); // 3.调用构造方法创建实例 Object arr2[] = {}; Object obj1 = cons.newInstance(arr2); System.out.println("%%% " + obj1); // 4.获取方法 /* * public Method getMethod(String name, Class<?>... parameterTypes) *它反映此Class 对象所表示的类或接口的指定公共成员方法。 */ Method m = cc.getMethod("show", arrl); //5.invoke method 调用方法: /* *public Object invoke(Object obj,Object... args) 对带有指定参数的指定对象调用由此 * Method 对象表示的底层方法。 */ Object obj = m.invoke(obj1, arr2); Constructor[] con = cc.getConstructors(); for (int i = 0; i < con.length; i++) { System.out.println("@@@ " + con[i]); } } } class Studentd { public String name; private int age; public Studentd(String name, int age) { this.name = name; this.age = age; } public Studentd() { } public void show() { System.out.println("~~~~呵呵....."); } private void show1() { System.out.println("Hello!....."); } public void print() { System.out.println("name=" + name + "," + "age=" + age); } }
package day11.javaAdvance.exercise.reflection.Class; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Properties; public class ClassTest4 { public static void main(String[] args) { Biz1 b = new Biz1(); b.finteat(); } } class Biz1 { Animal animal = (Animal) AnimalFactory.getObject("impl"); public void finteat() { animal.eat(); } } class AnimalFactory { static Properties pro = new Properties(); static { try { pro.load(new FileInputStream("config2.properties"));// 文件放在根目录下 } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static Object getObject(String name) { Object obj = null; String className = pro.getProperty(name);// name即是key键值,className即是value值。 try { Class c = Class.forName(className); Class[] cl = {}; Constructor con = c.getDeclaredConstructor(cl); Object[] obj1 = {}; obj = con.newInstance(obj1); System.out.println("类全名是:" + obj); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return obj; } } interface Animal1 { public void eat(); } class Dog1 implements Animal { public void eat() { System.out.println("dog eatting ...."); } } class Cat1 implements Animal { public void eat() { System.out.println("cat eatting...."); } }
其中的配置文件在config2.properties文件中。
配置文件中是键值对,其中的key=impl,value分别是Dog1类和Cat1类,以类全名方式赋值。其内容是:
impl= day11.javaAdvance.exercise.reflection.Class.Dog1
#impl=day11.javaAdvance.exercise.reflection.Class.Cat1
这样我们只要传递键值,即可得到配置文件中的value值即是代码中的:String className = pro.getProperty(name);得到的className即是value值。
使用配置文件的好处:不需在源代码中去修改代码,只需在配置文件中修改,这样很好体现了java的封装性这一特点。