美文网首页小卜java
JAVA基础知识之反射

JAVA基础知识之反射

作者: 汤太咸啊 | 来源:发表于2021-11-04 23:08 被阅读0次

    以下是我总结的一些简单的JAVA反射相关的小例子,非常简单,一看您就明白了,有什么问题您评论,我解答。

    基础bean

    public class Person {
        public int age;
        public String name;
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Person(String name,int age) {
            this.age = age;
            this.name = name;
        }
        public Person() {
        }
    }
    

    三种获取Class的方式

    //第一种
    Class<?> helloClass = "hello".getClass();
    Class<? extends String> helloClassNew = "hello".getClass();
    Class<? extends Object> helloClassNew2 = "hello".getClass();
    //第二种
    Class<?> stringClass = String.class;
    //第三种
    String className ="java.lang.String";
    Class<?> stringClassNew = Class.forName(className);
    

    获取父类型以及实现的接口类型

    Class<?> superClass = stringClass.getSuperclass();
    Class<?>[] interfaces = stringClass.getInterfaces();
    

    获取类的字段

    Class<?> clss = Person.class;
    Field field = clss.getField("age");
    //获取该类也同时包括父类型的全部public字段
    Field[] declaredFields = clss.getDeclaredFields();
    //获取该类内部的全部字段,无论private还是public
    Field[] fields = clss.getFields();
    

    获取方法

    Method method =clss.getMethod("setName", String.class);
    //获取该类也同时包括父类型的全部public方法
    Method[] declaredMethods = clss.getDeclaredMethods();
    //获取所有该类内部的method,无论private还是public
    Method[] methods = clss.getMethods();
    

    获取构造函数

    Constructor<?> constructor = clss.getConstructor(Class<?> ..types);
    //获取该类内部的所有构造函数
    Constructor<?>[] declaredConstructor = clss.getDeclaredConstructors();
    //获取该类内部的所有public构造函数
    Constructor<?>[] constructors = clss.getConstructors();
    

    获取修饰

    int modifiers = constructor.getModifiers();
    boolean isPublic = Modifier.isPublic(modifiers);
    设置字段为public的值,字段age为public
    Person person = new Person();
    Class<?> o = person.getClass();
    Field field = o.getDeclaredField("age");
    field.set(person,"d");
    System.out.println(person.getAge());
    //输出
    d
    

    设置字段为private的值,字段name为private,需要增加setAccessible为true,如果不设置为true则会报IllegalAccessException

    Person person = new Person();
    Class<?> o = person.getClass();
    Field field = o.getDeclaredField("name");
    field.setAccessible(true);
    field.set(person,"d");
    System.out.println(person.getName());
    

    通过获取字段的注解,做操作。

    Person person = new Person();
    Class<?> o = person.getClass();
    Field[] fields = o.getDeclaredFields();
    for(Field field:fields){
        if(field.getAnnotatedType(PrimaryKey.class) !=null){
            //this is the primary key
        }
        if(field.getAnnotatedType(Column.class) !=null){
            //this is an elment to read / write
        }
    }
    

    通过MethodHandles获取类

    MethodHandles.Lookup lookup = MethodHandles.lookup();
    Class<?> personClass = MethodHandles.lookup().findClass(Person.class.getName()); 
    

    创建四种method

    //getter方法
    MethodType getterType = MethodType.methodType(String.class);
    MethodHandle getterHandle = lookup.findVirtual(Person.class,"getName",getterType);
    //setter方法
    MethodType setterType = MethodType.methodType(void.class,String.class);
    MethodHandle setterHandle = lookup.findVirtual(Person.class,"setName",setterType);
    //构造方法
    MethodType constructorType = MethodType.methodType(void.class,String.class,int.class);
    MethodHandle constructorHandle = lookup.findConstructor(Person.class, constructorType);
    //空构造方法
    MethodType emptyConstructorType = MethodType.methodType(void.class);
    MethodHandle emptyConstructorHandle = lookup.findConstructor(Person.class,emptyConstructorType);
    

    通过invoke创建bean

    MethodType constructorType = MethodType.methodType(void.class,String.class,int.class);
    MethodHandle constructorHandle = lookup.findConstructor(Person.class, constructorType);
    
    Person p = (Person)constructorHandle.invoke("Xuesong",33);
    System.out.println(p);
    //输出
    Person{age=33, name='Xuesong'}
    
    MethodType emptyConstructorType = MethodType.methodType(void.class);
    MethodHandle emptyConstructorHandle = lookup.findConstructor(Person.class,emptyConstructorType);
    
    Person p2 = (Person)emptyConstructorHandle.invoke();
    System.out.println(p2);
    //输出
    Person{age=0, name='null'}
    

    通过invoke调用getter和setter

    MethodHandle nameReader = lookup.findGetter(Person.class, "name", String.class);
    MethodHandle nameWriter = lookup.findSetter(Person.class,"name",String.class);
    Person person = new Person("Xuesong",33);
    String name = (String) nameReader.invoke(person);
    //或者
    //String name = (String) getterHandle.invoke(person);
    System.out.println(name);
    //输出
    Xuesong
    nameWriter.invoke(person,"John");
    //或者
    //setterHandle.invoke(person,"John");
    System.out.println(person.getName());
    //输出
    John
    

    针对private的字段需要特殊处理

    Field nameField = Person.class.getDeclaredField("name");
    nameField.setAccessible(true);
    MethodHandle privateNameReader = lookup.unreflectGetter(nameField);
    String name = (String) privateNameReader.invoke(person);
    System.out.println(name);
    MethodHandle privateNameWriter = lookup.unreflectSetter(nameField);
    privateNameWriter.invoke(person,"John");
    System.out.println(person.getName());
    //JDK9以后的方式
    Lookup privateLookup = MethodHandles.privateLookupIn(Person.class, lookup);
    MethodHandle privateNameWriter = privateLookup.findSetter(Person.class,"name",String.class);
    privateNameWriter.invoke(person, "John");
    

    JDK9以后增加了线程安全的一种VarHandle,也可以处理

    VarHandle nameVarHandle = MethodHandles.privateLookupIn(Person.class,lookup)
            .findVarHandle(Person.class,"name",String.class);
    String name = (String) nameVarHandle.get(person);
    String name = (String) nameVarHandle.getVolatile(person);
    

    相关文章

      网友评论

        本文标题:JAVA基础知识之反射

        本文链接:https://www.haomeiwen.com/subject/ovdlzltx.html