Reflection(反射)是JAVA被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API 取得任何类的内部信息,并直接能操作任意对象的内部属性及方法
加载完类之后,在堆的方法区中就产生了一个Class类型的对象(一个类只有一个Class 对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构,这个对象就像一面镜子,通过这个镜子看到类的结构,所以我们形象的称之为:反射
package com.njit.reflection; public class Test01 { public static void main(String[] args) throws ClassNotFoundException { // 通过反射获取类的Class对象 Class c1 = Class.forName("com.njit.reflection.User"); Class c2 = Class.forName("com.njit.reflection.User"); Class c3 = Class.forName("com.njit.reflection.User"); //一个类在内存中只有一个Class对象 // 一个类被加载后,类的整体结构都会被封装在Class对象中 System.out.println(c1.hashCode()); System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); } }
/** 实体类 */ class User { private String name; private int id; private int age; public User() { } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } }
package reflection; public class Test02 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); //方式1:通过对象获取 Class c1 = person.getClass(); System.out.println(c1.hashCode()); //方式2:通过forName获取 Class c2 = Class.forName("reflection.Person"); System.out.println(c2.hashCode()); //方式3:通过类名 Class c3 = Student.class; System.out.println(c3.hashCode()); // 方式4:基本内置类型的包装类都有一个TYPE类型 Class c4 = Integer.TYPE; System.out.println(c4); // 获取父类的Class Class c5 = c1.getSuperclass(); System.out.println(c5.hashCode()); } } //父类 class Person{ private String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person{ public Student(){ super("学生"); } } class Teacher extends Person{ public Teacher(){ super("老师"); } }
package reflection; public class Test03 { public static void main(String[] args) throws ClassNotFoundException { // 获取系统类的加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //返回jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd // 获取系统类加载器的父类加载器-->扩展加载器 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent);// 返回jdk.internal.loader.ClassLoaders$PlatformClassLoader@43a25848 // 获取扩展类加载器的父类加载器-->根加载器(c/c++) ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //返回null 根加载器是无法直接获取的 // 测试当前类是用哪个加载器加载的 ClassLoader classLoader = Class.forName("reflection.Test03").getClassLoader(); System.out.println(classLoader); // 返回 jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd // 测试JDK内置的类是使用什么加载器加载的 ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader1); // 返回 null // 获取系统加载器可以加载的路径 System.out.println(System.getProperty("java.class.path")); } }
双亲委派的意思是如果一个类加载器需要加载类,那么首先它会把这个类请求委派给父类加载器去完成,每一层都是如此。一直递归到顶层,当父加载器无法完成这个请求时,子类才会尝试去加载。
这个机制主要出去安全性方面的考虑,就是用户自定义一个类,和基础类有冲突,会优先执行基础类,不加载用户自定义的类
总结:
方法是否加Declared这个单词的,表示是否获取所有方法,不加Declared这个的方法,只能获取public属性对应的东西,如果加了,则能获得包含私有属性的东西
如果是复数形式的方法,表示获得的是该类所有的属性
如果是单数形式的方法,则需要加上对应的name,参数,表示的是获得指定属性
示列代码如下:
package reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; //获得类的信息 public class Test04 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("reflection.User"); // 获得类的名字 System.out.println(c1.getName()); //包名加类名 reflection.User System.out.println(c1.getSimpleName()); //类名 User // c1.getFields(); 这个只能找到public属性 Field[] fields = c1.getDeclaredFields();//可以找到所有的属性 for (Field field : fields) { System.out.println(field); } // 获得指定属性的值 // Field name = c1.getField("name"); // System.out.println(name); Field name1 = c1.getDeclaredField("name"); System.out.println(name1); // 获取类的方法 Method[] methods = c1.getMethods(); //获取本类的public方法 for (Method method : methods) { System.out.println(method); } Method[] declaredMethods = c1.getDeclaredMethods(); //获得本类的所有的方法 for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } // 获取指定的方法 Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); System.out.println(getName); System.out.println(setName); // 获取构造器 Constructor[] constructors = c1.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } Constructor[] declaredConstructors = c1.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } // 获得指定的构造器 Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); System.out.println(declaredConstructor); } }
创建一个class对象
//获得class对象 Class c1 = Class.forName("reflection.User"); //构建一个对象 // User user =(User)c1.newInstance(); // System.out.println(user); // 通过构造器创建对象 Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User user2 = (User) declaredConstructor.newInstance("gek", 001, 19); System.out.println(user2);
通过反射去创建一个方法
// 通过反射去获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); // invoke :激活 // (对象,"方法的值") setName.invoke(user2,"gek2"); System.out.println(user2.getName());
通过反射操作属性
// 通过反射获取属性 Field name = c1.getDeclaredField("name"); // 不能直接操作私有属性,关闭权限检测 name.setAccessible(true); name.set(user2,"gek3"); System.out.println(user2.getName());
总结:
操作方法步骤:
1、通过反射去获得方法
2、通过invoke方法激活使用:方法.invoke(对象,方法的值)
操作属性步骤:
1、通过反射获取属性
2、必须关闭权限检测 通过属性.setAccessible(true)
3、操作属性
性能总结:普通方式性能>关闭检测反射方法>直接用反射方法
代码示例
package reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test06 { /** * 普通方式 */ public static void test01(){ User user = new User(); long starttime = System.currentTimeMillis(); for (int i = 0; i <100000000 ; i++) { user.getName(); } long endtime = System.currentTimeMillis(); System.out.println("普通方法执行了:"+(endtime-starttime)); } /** * 反射方法 */ public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getMethod("getName", null); long starttime = System.currentTimeMillis(); for (int i = 0; i < 100000000; i++) { getName.invoke(user,null); } long endtime = System.currentTimeMillis(); System.out.println("反射执行的时间为:"+(endtime-starttime)); } /** * 反射关闭检测 */ public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getMethod("getName", null); getName.setAccessible(true); long starttime = System.currentTimeMillis(); for (int i = 0; i <100000000 ; i++) { getName.invoke(user,null); } long endtime = System.currentTimeMillis(); System.out.println("反射关闭检测时间:"+(endtime-starttime)); } public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { test01(); test02(); test03(); } /** * 普通方法执行了:3ms * 反射执行的时间为:248ms * 反射关闭检测时间:145ms */ }
反射操作泛型
package reflection; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; public class Test07 { public static void test01(Map<String,User> map, List<Integer> list){ System.out.println("test01"); } public static Map<String,User> test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method method = Test07.class.getMethod("test01", Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println("####"+genericParameterType); if(genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } Method method2 = Test07.class.getMethod("test02"); Type returnType = method2.getReturnType(); if(returnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } } /** * ####java.util.Map<java.lang.String, reflection.User> * class java.lang.String * class reflection.User * ####java.util.List<java.lang.Integer> * class java.lang.Integer */
package reflection; import java.lang.annotation.*; import java.lang.reflect.Field; public class Test08 { public static void main(String[] args) throws NoSuchFieldException { Class c1 = Test08.class.getClass(); // 通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); System.out.println(annotations); // 获取注解的value值 MyAnnotation annotation = (MyAnnotation) c1.getAnnotation(MyAnnotation.class); System.out.println(annotation.value()); // 获取类的字段的指定注解 Field name = c1.getDeclaredField("name"); MyAnnotation2 annotation1 = name.getAnnotation(MyAnnotation2.class); System.out.println(annotation1.columnName()); System.out.println(annotation1.Type()); System.out.println(annotation1.Length()); } } @MyAnnotation("test1") class User2{ @MyAnnotation2(columnName = "name",Type = "String",Length = 10) private String name; @MyAnnotation2(columnName = "age",Type = "Integer",Length = 8) private int age; @MyAnnotation2(columnName = "id",Type = "Integer",Length = 10) private int id; public User2(){ } public User2(String name,int age,int id){ this.name=name; this.age=age; this.id=id; } 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 int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "User2{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}'; } } @Target(value = {ElementType.TYPE}) @Retention(value = RetentionPolicy.RUNTIME) @interface MyAnnotation{ String value(); } @Target(value = {ElementType.FIELD}) @Retention(value = RetentionPolicy.RUNTIME) @interface MyAnnotation2{ String columnName(); String Type(); int Length(); }