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();
}

本文标签: 反射