admin管理员组文章数量:1122855
反射
反射(Reflection)
反射是使java称为准动态语言的关键
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象,一个类只有一个class对象,这个对象就包含了这个完整类的结构信息,这个过程就称为反射。
Class类
反射的根源
获取class类的几种方法
1、类名.class 这个方法是最为安全可靠的
2、对象名.getClass()
3、Class.forName(“类的路径”)
4、基本内置类型的包装类都有一个Type属性
// 通过Class的静态方法
Class userClass = Class.forName("com.reflection.User");
// 通过对象的getClass方法获得
User user = new User();
Class aClass = user.getClass();// 通过类的class获得
Class userClass1 = User.class;// 内置类型的Type
Class type = Integer.TYPE;
哪些类型有class对象
class 类、成员内部类、静态内部类、局部内部类、匿名内部类
接口interface
数组
枚举enum
注解annotation
基本数据类型
void
类的加载过程
类的加载—》类的连接—》类的初始化
类的加载器
种类:
1、启动类加载器Bootstrap
负责加载类jre的核心类库
2、扩展类加载器Extension
主要加载JAVA_HOME/lib/ext目录中的类库
3、应用程序类加载器System
负责加载用户路径classpath中的类
4、用户自定义加载器
负责加载用户自定义路径下的类
双亲委派机制
当一个Hello.class这样的文件要被加载时。不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理也会先检查自己是否已经加载过,如果没有再往上。注意这个类似递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。
为什么要设计这种机制?
这种设计有个好处是,如果有人想替换系统级别的类:String.java。篡改它的实现,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了(为什么?因为当一个类需要加载的时候,最先去尝试加载的就是BootstrapClassLoader),所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入。
原文链接:
源码:
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}
获取运行时类的完整结构
Field、Method、Constructor、Superclass、Interface、Annotation
Class aClass = Class.forName("com.reflection.User");// 获得类的名字System.out.println("aClass.getName() = " + aClass.getName());System.out.println("aClass.getSimpleName() = " + aClass.getSimpleName());// 获取类的属性System.out.println("-----------------------------------------");// 可以得到public类型的属性Field[] fields1 = aClass.getFields();for (Field field : fields1) {System.out.println("field = " + field);}// 可以找到全部的属性Field[] fields = aClass.getDeclaredFields();for (Field field : fields) {System.out.println("field = " + field);}// 得到指定名字的属性Field name = aClass.getDeclaredField("name");System.out.println("name = " + name);System.out.println("--------------------------");// 获取本类的父类的全部方法for (Method method : aClass.getMethods()) {System.out.println("method = " + method);}// 获取本类的全部的方法for (Method declaredMethod : aClass.getDeclaredMethods()) {System.out.println("declaredMethod = " + declaredMethod);}// 获得指定的方法Method getName = aClass.getMethod("getName", null);System.out.println("getName = " + getName);Method setName = aClass.getMethod("setName", String.class);System.out.println("setName = " + setName);System.out.println("---------------------");// 获取全部的构造器for (Constructor constructor : aClass.getConstructors()) {System.out.println("constructor = " + constructor);}for (Constructor declaredConstructor : aClass.getDeclaredConstructors()) {System.out.println("获取全部declaredConstructor = " + declaredConstructor);}// 获取指定的构造器Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class, Integer.class);System.out.println("获取指定declaredConstructor = " + declaredConstructor);
动态创建对象的执行方法
// 获得class对象Class c1 = Class.forName("com.reflection.User");// 构造对象User user = (User) c1.newInstance();System.out.println("user = " + user);// 通过构造器创建对象那个Constructor constructor = c1.getDeclaredConstructor(String.class, Integer.class, Integer.class);User user2 = (User) constructor.newInstance("liufeng", 18, 1);System.out.println("user2 = " + user2);// 通过反射调用方法User user3 = (User) c1.newInstance();Method setName = c1.getMethod("setName", String.class);setName.invoke(user3, "贾可爱"); // 激活(第一个参数是对象,第二个参数是一个值)System.out.println("user3.getName() = " + user3.getName());// 通过反射操作属性User user4 = (User) c1.newInstance();Field name = c1.getDeclaredField("name");name.setAccessible(true); // 操作私有的属性name.set(user4,"贾晨霞");System.out.println("user4.getName() = " + user4.getName());
效率问题
正常的创建对象的效率是最快的
通过反射生成的类的时间是正常生成类的几百倍,效率明显下降
而在设置了setAccessible(true)以后,效率会提升三倍左右
获取泛型的信息
public class Test11 {public void test01(Map<Object, String> map, List<User> users) {System.out.println("test01");}public Map<Object, String> test02(List<User> users) {System.out.println("test02");return null;}public static void main(String[] args) throws NoSuchMethodException {// 获取这个类的test01方法Method test01 = Test11.class.getMethod("test01", Map.class, List.class);// 循环得到这个方法的参数列表的类型for (Type genericParameterType : test01.getGenericParameterTypes()) {System.out.println("== genericParameterType = " + genericParameterType);// 判断得到的类型是否是参数化的类型if (genericParameterType instanceof ParameterizedType) { // 如果是就强转成参数化的类型,然后遍历这个类型里面的类型for (Type actualTypeArgument : ((ParameterizedType) genericParameterType).getActualTypeArguments()) {// 得到这个参数化类型里面的类型System.out.println("actualTypeArgument = " + actualTypeArgument);}}}System.out.println("------------------------------------------");Method test02 = Test11.class.getMethod("test02", List.class);
// 得到这个方法的返回值的类型,这个返回值的类型只有一个Type genericReturnType = test02.getGenericReturnType();// 判断这个类型是不是参数化的类型if (genericReturnType instanceof ParameterizedType) {for (Type actualTypeArgument : ((ParameterizedType) genericReturnType).getActualTypeArguments()) {System.out.println("actualTypeArgument = " + actualTypeArgument);}}}
}
获取注解的信息
ORM对象关系映射
public class Test12 {public static void main(String[] args) {Class<Student> aClass = Student.class;// 通过反射获取注解for (Annotation annotation : aClass.getAnnotations()) {System.out.println("annotation = " + annotation);}// 获取注解里面的valueTableName annotation = aClass.getAnnotation(TableName.class);System.out.println("annotation.value() = " + annotation.value());// 获取方法上面的注解里面的内容for (java.lang.reflect.Field declaredField : aClass.getDeclaredFields()) {System.out.println("--- declaredField = " + declaredField);Field annotation1 = declaredField.getAnnotation(Field.class);System.out.println("annotation1.columnName() = " + annotation1.columnName());System.out.println("annotation1.type() = " + annotation1.type());System.out.println("annotation1.length() = " + annotation1.length());}}
}@TableName("lf_student")
class Student {@Field(columnName = "lf_id", type = "int", length = 10)private int id;@Field(columnName = "lf_age", type = "int", length = 10)private int age;@Field(columnName = "lf_name", type = "varchar", length = 5)private String name;public Student() {}public Student(int id, int age, String name) {this.id = id;this.age = age;this.name = name;}public int getId() {return id;}public Student setId(int id) {this.id = id;return this;}public int getAge() {return age;}public Student setAge(int age) {this.age = age;return this;}public String getName() {return name;}public Student setName(String name) {this.name = name;return this;}@Overridepublic String toString() {return "Student{" +"id=" + id +", age=" + age +", name='" + name + '\'' +'}';}
}@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{String value();
}@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{String columnName();String type();int length();
}
本文标签: 反射
版权声明:本文标题:反射 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1702063431a530083.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论