Java反射及简单使用

86 阅读3分钟

Java反射就是指Java提供的一个能够对类的内部变量和方法等一些信息进行获取和使用的机制

一、添加User类

添加User类,以User类作为例子执行一些常用的反射操作。

public interface Run {
    void run();
}
public class User implements Run{

    public static final String TYPE = "人类";
    public String name;
    private Integer age;

    public User(){

    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public void run() {
        System.out.println("人使用脚走路的");
    }

    private Integer getAge() {
        return age;
    }

    private void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

二、获取User的Class对象

User的所有反射操作都需要通过User的Class对象进行操作。

获取User的Class对象

//方式一:
Class<User> userClass = User.class;

//方式二:
User user = new User();
Class<? extends User> aClass = user.getClass();

//方式三:
Class<?> aClass = Class.forName("com.hlt.User");


三、获取User类的构造函数

Constructor类封装了User类的一个构造函数的信息,包括方法名、方法参数类型等。

  1. getConstructors():获取非私有的构造函数
  2. getDeclaredConstructors():获取所有的构造函数
  3. getConstructor(Class<?>... parameterTypes):根据参数类型获取非私有构造函
  4. getDeclaredConstructor(Class<?>... parameterTypes):根据参数类型获取构造函数

技巧 获取类信息,比如成员变量、方法时,方法中有Declared的表示可以获取所有的,没有Declared的表示可以获取非私有的。获取的信息方法名有复数的表示获取所有,没有复数的表示获取一个。

获取User类的非私有构造函数:

Constructor<?>[] constructors = userClass.getConstructors();
//遍历constructors,获取构造函数名、构造方法参数数量和构造方法参数类型
Arrays.stream(constructors).forEach(con->{
    System.out.println("构造方法名:"+con.getName());
    System.out.println("构造方法参数数量:"+con.getParameterCount());
    Arrays.stream(con.getParameterTypes()).forEach(type-> System.out.println("构造方法参数类型:"+type.getName()));
});

运行结果

构造方法名:com.hlt.User
构造方法参数数量:0
构造方法名:com.hlt.User
构造方法参数数量:2
构造方法参数类型:java.lang.String
构造方法参数类型:java.lang.Integer

通过无参构造函数创建User对象

Class<User> userClass = User.class;
Constructor<User> constructor = userClass.getConstructor(null);
User user = constructor.newInstance(null);
System.out.println(user);

运行结果:

User{name='null', age=null}

通过有参构造函数创建User对象

Class<User> userClass = User.class;
Constructor<User> constructor = userClass.getConstructor(java.lang.String.class,java.lang.Integer.class);
User zhansang = constructor.newInstance("zhansang", 18);
System.out.println(zhansang);

运行结果:

User{name='zhansang', age=18}

四、获取类的成员变量

Field类是用来存储类成员变量(包括普通成员变量、类成员变量)的。

获取非私有的成员变量

//获取类非私有成员变量
Field[] fields = userClass.getFields();
Arrays.stream(fields).forEach(field-> System.out.println("非私有成员变量"+field.getName()));

运行结果:

非私有成员变量TYPE
非私有成员变量name

获取所有变量可参考前面获取构造方法的例子,后面不在提示。

五、获取类中的方法,并执行该方法

获取所有非私有方法

User user = new User("zhansang",18);
Class<? extends User> aClass = user.getClass();
Method[] methods = aClass.getMethods();
//遍历methods
Arrays.stream(methods).forEach(method->{
    System.out.println("方法名:" + method.getName());
    System.out.println("方法参数数量:"+method.getParameterCount());
    Arrays.stream(method.getParameterTypes()).forEach(type-> System.out.println("方法参数类型"+type.getName()));
    System.out.println("方法返回类型:"+method.getReturnType().getName());
});

获取私有方法getAge,并执行该方法

User user = new User("zhansang",18);
Class<? extends User> aClass = user.getClass();
Method getAge = aClass.getDeclaredMethod("getAge", null);
//私有方法需要设置开放访问权限
getAge.setAccessible(true);
Object invoke = getAge.invoke(user);
System.out.println(invoke);

运行结果:18

获取公有方法run,并执行该方法

User user = new User("zhansang",18);
Class<? extends User> aClass = user.getClass();
Method getAge = aClass.getMethod("run",null);
getAge.invoke(user);

运行结果:人使用脚走路的

六、获取User类的实现接口和父类

获取实现接口

Class<User> userClass = User.class;
Class<?>[] interfaces = userClass.getInterfaces();
Arrays.stream(interfaces).forEach(inter->System.out.println("接口类型:" + inter.getName()));

运行结果:

接口类型:com.hlt.Run

获取父类

Class<User> userClass = User.class;
Class<? super User> superclass = userClass.getSuperclass();
System.out.println(superclass.getName());

运行结果:java.lang.Object