美文网首页
反射基础

反射基础

作者: 陈柴盐 | 来源:发表于2018-11-26 23:40 被阅读0次

    材料准备

    public class Student {
    
                private int id;
                private String name;
                private int age;
    
                public Student(int id, String name, int age) {
                    this.id = id;
                    this.name = name;
                    this.age = age;
                }
    
    
                public Student(String name) {
                    this.name = name;
                }
    
                public Student() {
                }
    
                public int getId() {
                    return id;
                }
    
                public void setId(int id) {
                    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;
                }
    
                @Override
                public String toString() {
                    return "Student{" +
                            "id=" + id +
                            ", name='" + name + '\'' +
                            ", age=" + age +
                            '}' + "\n";
                }
    
    
                @Override
                public boolean equals(Object o) {
                    if (this == o) {return true;}
                    if (o == null || getClass() != o.getClass()) {return false;}
    
                    Student student = (Student) o;
    
                    if (id != student.id) {return false;}
                    if (age != student.age) {return false;}
                    return name != null ? name.equals(student.name) : student.name == null;
                }
    
                @Override
                public int hashCode() {
                    int result = id;
                    result = 31 * result + (name != null ? name.hashCode() : 0);
                    result = 31 * result + age;
                    return result;
                }
    
    
                /*方法*/
            public void method1(String string) {
                System.out.println(string);
            }
    
            public void method2(String string,int i) {
                System.out.println(string+i);
            }
    
            public void method3(String string,Integer integer,String s) {
                System.out.println(string+integer+s);
            }
    }
    
    

    Class类

    获取Class对象

    1. 通过类名.class获取
    2. 通过对象名.getClass()获得
    3. 通过Class类的静态方法forName("类全名字符串")获得
    Class c1 = Student.class;
    
    Student s =  new Student();
    Class c2 = s.getClass();
    
    Class c3 = Class.forName("xxx.Student");
    

    Constructor类

    类中的每一个构造方法都是一个Constructor类的对象

    通过Class对象获取Constructor对象

    1. Constructor getConstructor(Class... parameterTypes)//根据参数获取构造器
    2. Constructor[] getConstructors()//获取所有的构造方法

    常用方法

    1. T newInstance(Object... initargs)//创建对象

    代码示例:

    public static void main(String[] args) throws Exception {
            Class<Student> studentClass = Student.class;
    
            //获取无参构造方法
            Constructor<Student> constructor = studentClass.getConstructor();
            System.out.println("constructor = " + constructor);
            Student student = constructor.newInstance();
            System.out.println("student = " + student);
            System.out.println("=============================");
        
            //获取有参构造方法
            Constructor<Student> constructor1 = studentClass.getConstructor(String.class);
            System.out.println("constructor1 = " + constructor1);
            Student student1 = constructor1.newInstance("权属");
            System.out.println("student1 = " + student1);
            System.out.println("=============================");
        
            //获取有参构造方法2
            Constructor<Student> constructor2 = studentClass.getConstructor(int.class, String.class, int.class);
            System.out.println("constructor2 = " + constructor2);
            Student student2 = constructor2.newInstance(1, "内容", 18);
            System.out.println(student2);
            System.out.println("=============================");
        
            //获取所有构造方法
            Constructor<?>[] constructors = studentClass.getConstructors();
            for (Constructor<?> subConstructor : constructors) {
                System.out.println(subConstructor);
            }
    
        }
    

    输出结果

    constructor = public junit和反射和注解.反射.Student()
    student = Student{id=0, name='null', age=0}
    
    =============================
    constructor1 = public junit和反射和注解.反射.Student(java.lang.String)
    student1 = Student{id=0, name='权属', age=0}
    
    =============================
    constructor2 = public junit和反射和注解.反射.Student(int,java.lang.String,int)
    Student{id=1, name='内容', age=18}
    
    =============================
    public junit和反射和注解.反射.Student()
    public junit和反射和注解.反射.Student(java.lang.String)
    public junit和反射和注解.反射.Student(int,java.lang.String,int)
    

    Method类

    类中每一个成员方法都是一个Method对象

    通过Class对象获取Method对象

    1. Method getMethod(String methodName, Class...param)//根据方法名和参数获取方法对象
    2. Method[] getMethods()//获取所有方法对象
    3. Method[] getDeclaredMethods()//获取不包括父类方法的独享

    method类的常用方法

    1. Object invoke(Object obj,Object...args)

    代码示例:

        public static void main(String[] args) throws Exception{
            Class<Student> studentClass = Student.class;
    
            Method method1 = studentClass.getMethod("method1", String.class);
            Method method2 = studentClass.getMethod("method2", String.class, int.class);
            Method method3 = studentClass.getMethod("method3", String.class, Integer.class, String.class);
    
            method1.invoke(studentClass.getConstructor().newInstance(), "你");
            method2.invoke(studentClass.getConstructor().newInstance(), "我", 1);
            method3.invoke(studentClass.getConstructor().newInstance(),"他",1,"们");
    
            System.out.println("=============================");
    
            Method[] methods = studentClass.getMethods();
            for (Method method : methods) {
                System.out.println(method);
            }
    
            System.out.println("=============================");
    
            //不包括父类的方法
            Method[] declaredMethods = studentClass.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                System.out.println(declaredMethod);
            }
        }
    

    输出结果

    你
    我1
    他1们
    =============================
    public void exercise.Student.setAge(int)
    public void exercise.Student.setId(int)
    public int exercise.Student.getAge()
    public void exercise.Student.method2(java.lang.String,int)
    public void exercise.Student.method1(java.lang.String)
    public void exercise.Student.method3(java.lang.String,java.lang.Integer,java.lang.String)
    ......
    

    Field类

    类中的每一个成员变量都是一个Field对象

    Class对象中获取Field对象的方法

    1. Field getDeclaredField(String name);//根据变量名获取对应的Field对象
    2. Field[] getDeclaredFields();//获取所有的Field对象

    Field类的常用方法
    ​ void set(Object obj, Object value)
    ​ void setInt(Object obj, int i)
    ​ void setLong(Object obj, long l)
    ​ void setBoolean(Object obj, boolean z)
    ​ void setDouble(Object obj, double d)

    ​ Object get(Object obj)
    ​ int getInt(Object obj)
    ​ long getLong(Object obj)
    ​ boolean getBoolean(Object ob)
    ​ double getDouble(Object obj)

    private修饰的变量需要设置setAccessible(true)才可以反射设置属性值

    ​ void setAccessible(true);

    * 设置是否取消权限检查
    
    • true:取消,不检查权限
    • false:不取消,要检查权限,默认值
    • 暴力反射,设置为可以直接访问私有类型的属性。

    代码示例

    public static void main(String[] args) throws Exception{
    
            //Class对象是放在方法区(性质跟常量池像的那个,方法区包含常量池)
            Class<Student> studentClass = Student.class;
    
            Field age = studentClass.getDeclaredField("name");
            Student student = studentClass.getConstructor().newInstance();
            System.out.println("studentBefore = " + student);
            age.setAccessible(true);
            age.set(student,"one");
            System.out.println("studentAfter = " + student);
    
            Field[] fields = studentClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                if (field.getType()==int.class) {
                    System.out.println("属性是整型");
                }else if(field.getType()==String.class){
                    System.out.println("属性是String类型");
                }
            }
        }
    

    输出结果

    studentBefore = Student{id=0, name='null', age=0}
    
    studentAfter = Student{id=0, name='one', age=0}
    
    属性是整型
    属性是String类型
    属性是整型
    
    

    Annotation类

    类中每一个注解都是Annotation的子类

    AnnotatedElement接口,定义了获取注解信息的方法

    Class,Constructor,Method,Field等类都实现了AnnotatedElement接口

    Annotation接口的方法:

    1. T getAnnotation(Class<T> annotationClass)//根据注解类型获取注解对象那个
    2. Annotation[] getAnnotations()//获取所有注解对象,可以获父类上注解对象,前提标注元注解@Inherited
    3. Annotation[] getDeclaredAnnotations()//获取所有注解对象,仅限本类中的
    4. boolean isAnnotationPresent(Class annotationClass)//判断是否使用了某个注解

    获取注解对象的方法:

    ​ 注解作用在哪个成员上就获得该成员对应的对象获得注解信息

    ​ 比如:注解作用在类上,那么应该通过Class对象的getAnnotation(Class<T> annotationClass)方法获取

    ​ 注解作用在方法上,那么应该通过Method对象的getAnnotation(Class<T> annotationClass)方法

    ​ 构造器和Field同理

    相关文章

      网友评论

          本文标题:反射基础

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