反射

框架的灵魂

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

Java反射机制是在运行状态中,对于任意一个类们都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它任意一个方法和属性,这种动态获取信息以及动态调用对象的方法的功能称为反射

好处:

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

Person类

package com.company;

public class Person {
    String name;
    Integer age;
    private String gender;
    public Person(){
        super();
    }
    public Person(String name,Integer age){
        super();
        this.name=name;
        this.age=age;
    }
    public void show(){
        System.out.println("我是"+this.name+"年龄"+this.age+"gender");
    }
}

Main类

package com.company;
import java.io.*;

public class Main {

    public static void main(String[] args) throws Exception {
        //获取字节码
        Class clazz=Class.forName("com.company.Person");
        Class clazz2=Person.class;
        Person p=new Person();
        Class clazz3=p.getClass();
        //以上三种方式获取的字节码相等

    }
}

getClass和.Class区别?
我们一般所使用的对象都直接或间接继承自Object类,getClass()是Object类的方法,它可以获得一个实例的类型类。
类型类指的是代表一个类型的类,因为一切皆是对象,类型也不例外,在Java使用类型类来表示一个类型。所有的类型类都是Class类的实例。
public static void main(String[] args) {
ClassA a=new ClassA();
System.out.println(a.getClass());
System.out.println(ClassA.class);
}

对象a是A的一个实例,ClassA是某一个类,在Java中表示一个特定类型的类型类可以用“类型.class”的方式获得,因为a.getClass()获得是ClassA的类型类,也就是ClassA.class。所以ClassA.class和a.getClass()是一样的。
类型类是一一对应的,父类的类型类和子类的类型类是不同的,因此,假设ClassA是ClassB的子类,那么ClassB.class和a.getClass是不一样的。

getClass方法,有多态能力,运行时可以返回子类的类型信息,
.class是没有多态的,是静态解析的,编译时可以确定类型信息

构造器使用

package com.company;

import java.lang.reflect.Constructor;

public class Main {

    public static void main(String[] args) throws Exception {
        //获取字节码
        Class<Person> clazz2=Person.class;
        //以上三种方式获取的字节码相等

        Person p = clazz2.newInstance();
        p.name="zs";
        p.age=10;
        p.show();

        //通过参数的构造器来创建对象
        //先去获取构造器
        Constructor c = clazz2.getConstructor(String.class, Integer.class);
        //通过构造器来创建对象
        Person p2=(Person)c.newInstance("鲁班",7);
        p2.show();

    }
}

通过反射获取字段与方法

package com.company;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Main {

    public static void main(String[] args) throws Exception {
        //获取字节码
        Class<Person> clazz2=Person.class;

        Person p = clazz2.newInstance();
        p.name="zs";
        p.age=10;
        p.show();

        //通过参数的构造器来创建对象
        //先去获取构造器
        Constructor c = clazz2.getConstructor(String.class, Integer.class);
        //通过构造器来创建对象
        Person p2=(Person)c.newInstance("鲁班",7);
        p2.show();

        //获取字段
        Field f= clazz2.getField("name");
        f.set(p2,"李白");
        p2.show();
        //获取私有的字段
        Field f2=clazz2.getDeclaredField("gender");
        //去除私有权限
        f2.setAccessible(true);
        f2.set(p2,"男");
        p2.show();

        //获取公共方法
        Method m1=clazz2.getMethod("show");
        System.out.println(m1.getName());
        m1.invoke(p2);

        //获取私有方法  方法名称 方法参数
        Method m2=clazz2.getDeclaredMethod("eat",String.class);
        //去除私有的权限
        m2.setAccessible(true);
        m2.invoke(p2,"米饭");
    }
}

通过反射越过arraylist的类型检测

泛型在编译成字节码的时候会把泛型擦除

package com.company;

import java.lang.reflect.Method;
import java.util.ArrayList;
public class Main {

    public static void main(String[] args) throws Exception {
        ArrayList<Integer>list=new ArrayList<>();
        list.add(1);
        Class<?>clazz= Class.forName("java.util.ArrayList");
        clazz.getMethod("add",Object.class);
        Method m =clazz.getMethod("add",Object.class);
        m.invoke(list,"myxq");
        System.out.println(list);
    }
}
Last modification:April 22, 2022
如果觉得我的文章对你有用,请随意赞赏