一篇文章带你搞定 Java 中反射的应用(取得类的结构)

626 阅读3分钟

框架:半成品软件,可以在框架的基础上进行软件开发,简化编码

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

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

一、基本概念

在反射机制中,还可以通过反射得到一个类的完整结构,这就需要使用 java.lang.reflect 包中的以下几个类:

Constructor:表示类中的构造方法
Field:表示类中的属性
Method:表示类中的方法

这三个类都是 AccessibleObject 类的子类: 在这里插入图片描述

interface China{
    public static final String NATIONAL = "China";
    public static final String AUTHOR = "Java";
    public void sayChina();//定义无参的抽象方法
    public String sayHello(String name,int age);//定义有参的抽象方法
}
class Person implements China{
    private String name;
    private int age;
    public Person(){
    }
    public Person(String name){//声明有一个参数的构造方法
        this.name = name;
    }
    public Person(String name,int age){
        this(name);
        this.setAge(age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void sayChina() {
        System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL);
    }

    @Override
    public String sayHello(String name, int age) {
        return name + "你好!我今年" + age + "岁了!";
    }
}

二、取得所实现的全部接口

要取得一个类所实现的全部接口,必须使用 Class 类中的 getInterfaces() 方法,该方法定义:

public Class[] getInterfaces()

getInterfaces() 方法返回一个 Class 类的对象数组,之后直接利用 Class 类中的 getName() 方法输出即可。

public class Root{
    public static void main(String[] args) {
        Class<?> c1 = null;//声明 Class对象
        try{
            c1 = Class.forName("Person");
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        Class<?> c[] = c1.getInterfaces();//取得实现的全部接口
        for (int i=0;i<c.length;i++){
            System.out.println("实现的接口名称:" + c[i].getName());//输出接口名称
        }
    }
}

因为接口是类的特殊形式,而且一个类可以实现多个接口,所以此时以 Class 数组的形式将全部的接口对象返回,并利用循环的方式将内容依次输出

三、取得父类

一个类可以实现多个接口,但是只能继承一个父类,所以要想取得一个类的父类,可以直接使用 Class 类中的 getSuperclass() 方法,该方法定义:

public Class<? super T> getSuperclass()

getSuperclass() 方法返回的是 Class 实例,和之前得到的接口一样,可以通过 getName() 方法取得名称。

public class Test{
    public static void main(String[] args) {
        Class<?> c1 = null;
        try {
            c1 = Class.forName("Person");
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        Class<?> c2 = c1.getSuperclass();//取得父类信息
        System.out.println("父类名称:" + c2.getName());
    }
}

在这里插入图片描述 Person 类在编写时没有明确地继承一个父类,所以默认继承 Object 类

四、取得全部构造方法

要取得一个类中的全部构造方法,必须使用 Class 类中的 getConstructors() 方法。

  1. 取得 Person 类的全部构造方法
import java.lang.reflect.Constructor;

public class Test{
    public static void main(String[] args) {
        Class<?> c1 = null;
        try {
            c1 = Class.forName("Person");
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        Constructor<?> con[] = c1.getConstructors();//得到全部构造方法
        for (int i=0;i<con.length;i++){
            System.out.println("构造方法:" + con[i]);
        }
    }
}
  1. 取得一个类的全部构造方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class Test{
    public static void main(String[] args) {
        Class<?> c1 = null;
        try {
            c1 = Class.forName("Person");
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        Constructor<?> con[] = c1.getConstructors();//得到全部构造方法
        for (int i=0;i<con.length;i++){
            Class<?> p[] = con[i].getParameterTypes();//列出构造中的参数类型
            System.out.print("构造方法:");
            int mo = con[i].getModifiers();//取出权限
            System.out.print(Modifier.toString(mo) + " ");//还原权限
            System.out.print(con[i].getName());//输出构造方法名称
            System.out.print("(");
            for (int j=0;j<p.length;j++){
                System.out.print(p[j].getName() + " arg" + i);
                if (j<p.length-1){//打印参数类型,判断是否要输出“,”
                    System.out.print(",");
                }
            }
            System.out.println("){}");
        }
    }
}

在这里插入图片描述

五、取得全部方法

要取得一个类中的全部方法,可以使用 Class 类中的 getMethods() 方法,该方法返回一个 Method 类的对象数组。该方法的常用方法: 在这里插入图片描述

在这里插入图片描述

取得一个类的全部方法定义:

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test{
    public static void main(String[] args) {
        Class<?> c1 = null;
        try {
            c1 = Class.forName("Person");
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        Method m[] = c1.getMethods();//取得全部的方法
        for (int i=0;i<m.length;i++){
            Class<?> r = m[i].getReturnType();//取出方法的返回值类型
            Class<?> p[] = m[i].getParameterTypes();//得到全部的参数类型
            int xx = m[i].getModifiers();//得到方法的修饰符
            System.out.print(Modifier.toString(xx) + " ");//还原修饰符
            System.out.print(r.getName() + " ");//得到方法名称
            System.out.print(m[i].getName());//取得方法名称
            System.out.print("(");
            for (int x=0;x<p.length;x++){
                System.out.print(p[x].getName() + " " + "arg" + x);//输出参数
                if (x<p.length-1){
                    System.out.print(",");//判断是否输出","
                }
            }
            Class<?> ex[] = m[i].getExceptionTypes();//得到全部的异常抛出
            if (ex.length>0){
                System.out.print(") throws ");//输出“) throws”
            }else {
                System.out.print(")");
            }
            for (int j=0;j<ex.length;j++){
                System.out.print(ex[j].getName());//输出异常信息
                if (j<ex.length-1){
                    System.out.print(",");
                }
            }
            System.out.println();
        }
    }
}

开发工具就是利用了反射的原理

六、取得全部属性

在反射操作中也同样可以取得一个类中的全部属性,有两种不同的操作:

得到实现的接口或父类中的公共属性:public Field[] getFields() throws SecurityException
得到本类中的全部属性:public Field[] getDeclareDeclaredFields() throws SecurityException

上述方法返回的都是 Field 的数组,每一个 Field 对象表示类中的一个属性,而要想取得属性的进一步信息,需要使用: 在这里插入图片描述 取得 Person 类中的属性

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Test{
    public static void main(String[] args) {
        Class<?> c1 = null;
        try {
            c1 = Class.forName("Person");
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        {//普通代码块
            Field f[] = c1.getDeclaredFields();//取得本类属性
            for (int i=0;i<f.length;i++){
                Class<?> r = f[i].getType();//取得属性的类型
                int mo = f[i].getModifiers();//得到修饰符数字
                String priv = Modifier.toString(mo);//取得属性的修饰符
                System.out.print("本类属性:");
                System.out.print(priv + " ");//输出修饰符
                System.out.print(r.getName() + " ");//输出属性类型
                System.out.print(f[i].getName());//输出属性名称
                System.out.println(";");//换行
            }
        }
        System.out.println("===========================");
        {
            Field f[] = c1.getFields();//取得父类公共属性
            for (int i=0;i<f.length;i++){
                Class<?> r = f[i].getType();//取得属性的类型
                int mo = f[i].getModifiers();//取得修饰符数字
                String priv = Modifier.toString(mo);//取得属性修饰符
                System.out.print("公共属性:");
                System.out.print(priv + " ");//输出修饰符
                System.out.print(r.getName() + " ");//输出参数类型
                System.out.print(f[i].getName());//输出属性名称
                System.out.println(";");
            }
        }
    }
}