Java反射学习

Java反射

  • 1.加载类、获取类的字节码:Class对象
    • 1.1 获取Class对象的方式
  • 2. 获取类的构造器:Constructor对象
    • 2.1 获取类构造器的作用
    • 2.2 Constructor所提供的方法
  • 3.获取类的成员变量:Filed对象
    • 3.1 Class提供的从类中获取成员变量的方法
    • 3.2 获取成员变量的作用
    • 3.3 Field所提供的方法
  • 4.获取类的成员方法
    • 4.1 Class所提供的从类中获取成员方法的API
    • 4.2 获取成员方法的作用
    • 4.3 Method提供的方法
  • 5. 本文所用测试类

在java.lang包下,提供用于获取类和对象的反射信息的类和接口。加载完类后,在堆中产生一个Class对象,该对象包含了类的完整结构信息,此时我们可以通过该Class对象看到类的结构。

注:本文所用测试类在文末

1.加载类、获取类的字节码:Class对象

1.1 获取Class对象的方式

① Class xxx = 类名.class

Class clazz = Student.class;

② 调用Class所提供的方法:
public static Class forName(String package)

Class clazz = Class.forName("_reflect.User");
//输出全类名
System.out.println(clazz.getName());
//输出简名
System.out.println(clazz.getSimpleName());

③ 调用Object提供的方法:
public Class getClass()

User user = new User();
Class clazz = user.getClass();
//输出类名
System.out.println(clazz.getSimpleName());

2. 获取类的构造器:Constructor对象

① Constructor[] getConstructors()
获取public修饰的所有构造器

//获取Class对象
Class clazz = User.class;
//获取类中用public修饰的所有构造器
Constructor[] constructors = clazz.getConstructors();
//遍历构造器对象
for (Constructor constructor : constructors) {
	System.out.println(constructor.getName() + "-->" + 
	constructor.getParameterCount)
	//public int getParameterCount:返回在此方法对象上定义的形式参数的数量
}

② Constructor[] getDeclaredConstructors()
获取所有构造器(包括private修饰的)

//获取Class对象
Class clazz = User.class;
//获取类中g的所有构造器
Constructor[] constructors = clazz.getDeclaredConstructors();
//遍历构造器对象
for (Constructor constructor : constructors) {
	System.out.println(constructor.getName() + "-->" + 
	constructor.getParameterCount)
	//public int getParameterCount:返回在此方法对象上定义的形式参数的数量
}

③ Constructor getConstructor(Class… parameterType)
获取某个用public修饰的构造器

//1.获取Class对象
Class clazz = User.class;
//2.获取用public修饰的某带参的Constructor对象
Constructor constructor = clazz.getConstructor(String.class, int.class);
//输出构造器对象名
System.out.println(constructor.getName());

④ Constructor getDeclaredConstructor(Class… parameterTypes)
获取某个构造器(不限修饰符)

//1.获取Class对象
Class clazz = User.class;
//2.获取构造器对象
Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class, String.class, String.class);
//3.输出构造器名
System.out.println(constructor.getName());

获取空参构造器同上,只需去掉参数即可

2.1 获取类构造器的作用

获取类构造的作用是初始化对象返回

2.2 Constructor所提供的方法

① T newInstance(Object… intargs)
调用此构造器对象显示的构造器,并传入参数,完成对象的初始化并返回

② public void setAccessible(boolean flag)
设置为true,表示禁止检查访问控制(暴力反射)

//1.获取Class对象
Class clazz = User.class;
//2.获取Constructor对象
Constructor constructor = clazz.getDeclaredConstructor(String.class, String.class);
//3.设置检查访问控制
constructor.setAccessible(true);//禁止检查访问权限
//4.创建对象(方法1,强转)
User user = (User)constructor.newInstance("张三", "中国");
//方法2(泛型)
Constructor<User> cons = clazz.getDeclaredConstructor(String.class, String.class);
cons.setAccessible(true);
User us = cons.newInstance("李四", "中国");
//输出
System.out.println(user);
System.out.println(us);

3.获取类的成员变量:Filed对象

3.1 Class提供的从类中获取成员变量的方法

① public Field[] getFields()
获取类中用public修饰的所有成员变量

//1.获取Class对象
Class clazz = User.class;
//2.获取成员变量
Field[] publicFields = clazz.getFields();
//3.遍历成员变量数组并输出
for (Field field : publicFields) {
	//getType():获取变量类型
	System.out.println(field.getName() + "--->" + field.getType().getSimpleName());
}

② public Field[] getDeclaredFields()
获取类中所有成员变量

//1.获取Class对象
Class clazz = User.class;
//2.获取成员变量
Field[] fields = clazz.getFields();
//3.遍历成员变量数组并输出
for (Field field : fields) {
	//getType():获取变量类型
	System.out.println(field.getName() + "--->" + field.getType().getSimpleName());
}

③ public Field getField(String name)
获取某个用public修饰的成员变量

//1.获取Class对象
Class clazz = User.class;
//2.获取public修饰的某个成员变量
Field fAge = clazz.getField("age");
//3.输出成员变量
System.out.println(fAge.getName() + "--->" + fAge.getType().getSimpleName());

④ public Field getDeclaredField(String name)
获取某个成员变量

//1.获取Class对象
Class clazz = User.class;
//2.获取public修饰的某个成员变量
Field fName = clazz.getDeclaredField("name");
//3.输出成员变量
System.out.println(fName.getName() + "--->" + fName.getType().getSimpleName());

3.2 获取成员变量的作用

获取成员变量的作用是将其用来赋值以及取值

3.3 Field所提供的方法

① void set(Object obj, Object value):赋值
② Object get(Object obj):取值
③ public void setAccessible(boolean flag):暴力反射

//1.获取Class对象
Class clazz = User.class;
//2.获取成员变量
Field fName = clazz.getDeclaredField("name");//private变量,使用getDeclaredField()获取
Field fAge = clazz.getField("age");//public变量,使用getField()获取
Field fNation = clazz.getField("nation");
//3.暴力反射,因为只有name是private修饰的变量,所以这里只对fName设置检查访问控制
fName.setAccessible(true);
//4.创建对象
User user = new User();
//5.赋值
fName.set(user, "张三");
fAge.set(user, 26);
fNation.set(user, "中国");
//6.取值
String name = (String) fName.get(user);
int age = (int) Fage.get(user);
String nation = (String) fNation.get(user);
//7.输出验证
System.out.println(name + "\n" + age + "\n" + nation);

4.获取类的成员方法

4.1 Class所提供的从类中获取成员方法的API

① Method[] getMethods():获取类中用public修饰的所有成员方法

//1.获取Class对象
Class clazz = User.class;
//2.获取public成员方法
Method[] methods = clazz.getMethods();
//3.遍历
for (Method method : methods) {
	System.out.println(method.getName() + "--->" + method.getParameterCount + 
	"--->" + method.getReturnType().getSimpleName());//getReturnType():获取返回值类型
}

② Method[] getDeclaredMethods():获取类中全部成员方法

//1.获取Class对象
Class clazz = User.class;
//2.获取成员变量
Method[] methods = clazz.getDeclaredMethods();
//3.遍历
for (Method method : methods) {
	System.out.println(method.getName() + "--->" + method.getParameterCount + 
	"--->" + method.getReturnType().getSimpleName());
}

③ Method getMethod(String name, Class… parameterTypes):获取类中某个用public修饰的成员方法

//1.获取Class对象
Class clazz = User.class;
//2.获取指定成员变量
Method method = clazz.getMethod("show");//空参方法,不用写参数类型
//3.输出
System.out.println(method.getName() + "--->" + method.getParameterCount + 
	"--->" + method.getReturnType().getSimpleName());

④ Method getDeclaredMethod(String name, Class… parameterTypes):获取类中某个成员方法

//1.获取Class对象
Class clazz = User.clazz;
//2.获取指定成员变量
Method method = clazz.getDeclaredMethod("showNation" + String.class);//带参方法,需指明参数类型
//3.输出
System.out.println(method.getName() + "--->" + method.getParameterCount + 
	"--->" + method.getReturnType().getSimpleName());

注:重载方法需根据参数类型来指定获取

4.2 获取成员方法的作用

获取成员方法的作用是执行该方法

4.3 Method提供的方法

① public Object invoke(Object obj, Object… args):出发某个对象的该方法执行

② public void setAccessible(boolean flag):暴力反射

public方法:

//1.获取Class对象
Class clazz = User.class;
//2.获取方法
Method mShow = clazz.getMethod("show");
/*
show()方法内部没有参数,但执行输出使用的是内部私有name变量,若不设置,则该变量为null
*/
//3.获取成员变量name
Field fName = clazz.getDeclaredField("name");
fName.setAccessible(true);
//4.创建对象
User user = new User();
//5.设置name值
fName.set(user, "高富帅");
System.out.println(mShow.invoke(user));//无返回值,方法执行,输出返回值为null

private方法:

//1.获取Class对象
Class clazz = User.class;
//2.获取方法,带参数则需指明参数类型
Method mShowNation = clazz.getDeclaredMethod("showNation", String.class);
//设置禁止检查访问控制
mShowNation.setAccessible(true);
//3.创建对象
//User user = new User();
Object user = clazz.newInstance();
//4.设置Object对象接收返回值
Object obj = mShowNation.invoke(user, "中国");
//5.输出
System.out.println(obj);

5. 本文所用测试类

public class User {
    private String name;
    public int age;
    private String address;
    public String nation;

    public User(){

    }

    public User(int age){
        this.age = age;
    }

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

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

    private User(String name, int age, String address, String nation) {
        this.name = name;
        this.age = age;
        this.address = address;
        this.nation = nation;
    }

    private User(String name, String nation) {
        this.name = name;
        this.nation = nation;
    }
    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;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public void show(){
        System.out.println("你好,我是" + name);
    }

    private String showNation(String nation){
        return "我的国籍是:" + nation;
    }

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


反射的其他API日后再做补充

你可能感兴趣的:(java,学习,开发语言)