Java Reflection
- Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
- java反射机制提供的功能
1)在运行时判断任意一个对象所属的类
2)在运行时构造一个类的对象
3)在运行时判断任意一个类所具有的成员变量和方法
4)在运行时调用任意一个对象的成员变量和方法
5)生成动态代理
反射相关的API
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
实例:
public class TestReflection { /** * 在反射以前如何创建一个类的对象,并调用其中的方法和属性 */ @Test public void test1(){ Person person = new Person(); person.setAge(23); person.setName("bule"); System.out.println(person); person.show(); person.display("HK"); } /** * 有了反射,可以通过反射创建一个类的对象,并调用其中的结构 */ @Test public void test() throws Exception { Class<Person> clazz = Person.class; //1、可以根据clazz创建对应的运行时类Person类的对象 Person person = clazz.newInstance(); //2、通过反射调用运行时类的指定属性 /**这种写法是类的属性范围设置为public */ Field name = clazz.getField("name"); name.set(person,"小明"); System.out.println(person); /**这种写法是类的属性范围设置为private */ Field age = clazz.getDeclaredField("age"); //这样表示设置可以访问private属性的权限 age.setAccessible(true); age.set(person,34); System.out.println(person); //3、通过反射调用运行时类的方法 //①没有参数的 Method show = clazz.getMethod("show"); show.invoke(person);//调用方法 //②有参数的 Method display = clazz.getMethod("display", String.class); display.invoke(person,"中国"); } }
反射的源头Class
在Object类中定义了如下的方法,此方法将被所有子类继承:
- public final Class getClass( );
以上方法的返回值是一个Class类,此类是java反射的源头,实际上所谓的反射从程序的运行结果来看:可以通过对象的反射求出类的名称
/** * java.lang.Class:反射的源头 * 我们创建了一个类,通过编译(javac.exe),生成对应的 .class文件(字节码文件)。 * 之后我们用java.exe加载(JVM的类加载器来完成的)此 .class文件。 * 此 .class文件加载到内存以后就是一个运行时类,存放在缓存区。这个运行时类本身就是一个Class的实例 * 1、每一个运行时类只加载一次! * 2、有了Class实例我们才可以进行如下的操作: * 1)创建对应的运行时类的对象 * 2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解 * 3)调用对应的运行时类的指定的结构(属性、方法、构造器) * 4)反射的应用:动态代理 */ @Test public void test3(){ Person person = new Person(); Class clazz = person.getClass(); System.out.println(clazz); }
获取Class类的实例的方法(四种)
1、前提:若已知具体的类,可以通过class属性获取,该方法安全可靠,程序性能最高
实例:
Class clazz1 = Person.class;
2、前提:若已知某个类的实例,调用该实例的getClass()方法获取Class对象
实例:
Class clazz = “www.atguigu.com”.getClass();
3、前提:已知一个类的全类名,且该类在类路径下,可以通过Class的静态方法forName()获取,可能抛出ClassNotFoundException
实例:
String className = "Progress.reflection.Person";
Class clazz3 = Class.forName(className);
4、通过类的加载器
实例:
ClassLoader classLoader = this.getClass().getClassLoader();
Class clazz4 = classLoader.loadClass(className);
/** * 如何获取Class的实例(掌握的是3种) */ @Test public void test4() throws ClassNotFoundException { //1、调用运行时类本身的 .class属性 Class clazz1 = Person.class; System.out.println(clazz1); //2、通过运行时类的对象获取 Person person = new Person(); Class clazz2 = person.getClass(); System.out.println(clazz2); //3、通过Class的静态方法获取.通过此方法体验反射的动态性 String className = "Progress.reflection.Person"; Class clazz3 = Class.forName(className); System.out.println(clazz3); //4、(了解)通过类的加载器 ClassLoader classLoader = this.getClass().getClassLoader(); Class clazz4 = classLoader.loadClass(className); System.out.println(clazz4); }