什么是反射?先看看正常的Java代码如何在执行的,可以简单的分为三个阶段:
首先是Source源代码阶段:比如Person.java类经过javac编译后成为Person.class,.class文件通过类加载器(ClassLoader)生Class类对象到第二个阶段Class类对象阶段,Class类对象中有成员变量Field[] fields,构造方法Constructor[] cons,成员方法Method[] methods;最后创建对象到第三个阶段Runtime运行时阶段。
反射是指对于任何一个Class类,在运行的时候都可以直接得到这个类全部成分在运行时,可以直接得到这个类的构造器对象:Constructor,成员变量对象:Field,成员方法对象:Method。反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分。
HelloWorld.java -> javac -> HelloWorld.class Class c = HelloWorld.class;2、如何获取Class类对象?
有三种方式可以获取
2.1 forname获得 Class c1 = Class.forName(“全类名”)Class.forName("全类名")将字节码文件加载进入内存,返回Class对象
Class cls1 = Class.forName("test.src.domain.Person"); System.out.println(cls1);2.2 通过类名.class获得Class c2 = 类名.class
Class cls2= Person.class; System.out.println(cls2);2.3 通过对象获得 Class c3 = 对象.getClass()
Person p=new Person(); Class cls3=p.getClass(); System.out.println(cls3);3、获取Constructor构造器对象并使用
获得Constructor对象,然后创建对象,Class类中用于获取构造器的方法如下:
Constructor类中用于创建对象的方法:
例如:
Class personClass = Person.class; //获取构造方法们 Constructor[] constructors = personClass.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } Constructor constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); //创建对象 Object person = constructor.newInstance("张三", 23); System.out.println(person);4、获得Field对象并使用
获取Fiedl对象,赋值或取值。得到类对象,然后从类对象中获取类的成员对象,Class类中用于获取成员变量的方法。
Field类中用于赋值和取值的方法
例如:
Class personClass = Person.class; //1获取成员变量们,获取public修饰的成员变量 Field[] fields = personClass.getFields(); for (Field field : fields) { System.out.println(field); } Field a = personClass.getField("a"); System.out.println(a); //获取成员变量a的值 Person p=new Person(); Object value =a.get(p); System.out.println(value); //设置a的值 a.set(p,"111"); System.out.println(p); //获取所有的成员变量,不考虑修饰符 Field[] declaredFields = personClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } Field d = personClass.getDeclaredField("d"); //忽略访问权限修饰符的安全检查 d.setAccessible(true);//暴力反射 Object value2 = d.get(p); System.out.println(value2);5、获取Method方法对象并使用
获取Method对象并运行,Class类中用于获取成员方法的方法如下:
Method类中用于触发执行的方法:
例如:
Class6、反射的作用personClass = Person.class; //获取成员方法们 Method eat = personClass.getMethod("eat"); Person p=new Person(); //执行方法 eat.invoke(p); Method eat1 = personClass.getMethod("eat", String.class); eat1.invoke(p,"饭"); //获取所有public修饰的方法 Method[] methods = personClass.getMethods(); for (Method method : methods) { System.out.println(method); }
可以在运行时得到一个类的全部成分然后 *** 作。可以破坏封装性。(很突出)也可以破坏泛型的约束性。(很突出)更重要的用途是适合:做Java高级框架。基本上主流框架都会基于反射设计一些通用技术功能。
7、补充例子中的Person类:
public class Person { private String name; private int age; public String a; protected String b; String c; private String d; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { } @Override public String toString() { return "Person{" + "name='" + name + ''' + ", age=" + age + ", a='" + a + ''' + ", b='" + b + ''' + ", c='" + c + ''' + ", d='" + d + ''' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void eat(){ System.out.println("eat..."); } public void eat(String food){ System.out.println("eat..."+food); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)