反射

作者: MononokeHime | 来源:发表于2019-11-04 19:52 被阅读0次

    将类的各个组成部分封装为其他对象,就是反射机制


    image.png

    反射的好处:

    • 在程序的运行过程中,操作这些对象
    • 可以解耦,提高程序的可扩展性

    获取class对象(对应三个阶段)

    • class.forName("全类名"):将字节码文件加载进内存
    • 类名.class:通过类名的属性class获取
    • 对象.getClass():getClass()方法在Object类中定义着
    class Person{
        private int age;
        private String name;
        public String a;
        protected String b;
        String c;
    
        public Person(){
        }
    
        public Person(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        public void eat(){
            System.out.println("eating");
        }
    
        public void eat(String food){
            System.out.println("eating:" + food);
    
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    ", a='" + a + '\'' +
                    ", b='" + b + '\'' +
                    ", c='" + c + '\'' +
                    '}';
        }
    }
    
    
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            Class cls1 = Class.forName("Person");
            System.out.println(cls1);
    
            Class cls2 = Person.class;
            System.out.println(cls2);
    
            Person p = new Person();
            Class cls3 = p.getClass();
            System.out.println(cls3);
    
            // 比较三个对象的内存地址
            System.out.println(cls1 == cls2);  // true
            System.out.println(cls1 == cls3);  // true
        }
    }
    

    结论:
    同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个

    class对象功能:
    1.获取功能

    • 获取成员变量们
      Field[] getFields():获取所有public修饰的成员变量
      Field getField(String name):获取指定名称的public修饰的成员变量
      Field[] getDeclaredFields():获取所有成员变量,不考虑修饰符(对于private,需设置setAccessible=true)
      Field getDeclaredField(String name):获取指定名称的成员变量

    • 获取构造方法们

    • 获取成员方法们

    • 获取类名

    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            Class cls = Person.class;
            Field[] fields = cls.getFields();
            for(Field f: fields){
                System.out.println(f);
            }  // 只打印 public java.lang.String Person.a
    
            Field a = cls.getField("a");
            Person p = new Person();
            Object value = a.get(p);
            System.out.println(value);  // null
    
            // 设置a的值
            a.set(p, "张三");
            System.out.println(p);  // Person{age=0, name='null', a='张三', b='null', c='null'}
        }
    }
    
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            Class cls = Person.class;
            Field f2 = cls.getDeclaredField("name");
            f2.setAccessible(true);  // 没有这句话会报错
            Person p = new Person();
            Object value = f2.get(p);
            System.out.println(value);
    
        }
    }
    

    构造方法
    获取到构造器的最主要的目的就是创建对象

    public class ReflectDemo {
    
        public static void main(String[] args) throws Exception {
            Class cls = Person.class;
    
            // 带参的构造器使用
            Constructor constructor = cls.getConstructor(int.class, String.class);
            System.out.println(constructor);  // public Person(int,java.lang.String)
            // 创建对象
            Object person = constructor.newInstance(18, "张三");
            System.out.println(person);  // Person{age=18, name='张三', a='null', b='null', c='null'}
    
            // 无参构造器的使用
            Constructor constructor1 = cls.getConstructor();
            Object person1 = constructor1.newInstance();
            System.out.println(person1);
    
            // 等价于上面的无参构造
            Object o = cls.newInstance();
            System.out.println(o);
    
        }
    }
    

    获取成员方法

    public class ReflectDemo {
    
        public static void main(String[] args) throws Exception {
            Class cls = Person.class;
    
            Method method = cls.getMethod("eat");
            Person p = new Person();
            method.invoke(p);
    
            Method method1 = cls.getMethod("eat", String.class);
            method1.invoke(p, "fish");
    
            Method[] method2 = cls.getMethods();
            for(Method m: method2){
                // m.setAccessible(true);
                String name = m.getName();
                System.out.println(m);
            }
    
        }
    }
    

    相关文章

      网友评论

          本文标题:反射

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