Java 反射--获取类的内部结构详解

Posted 路 宇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 反射--获取类的内部结构详解相关的知识,希望对你有一定的参考价值。

准备工作: 提供丰富的Person类结构,继承父类,实现接口,加上注解

1.自定义父类Creature

public class Creature<T> implements Serializable {
    private char gender;
    public double weight;
    private void breath(){
        System.out.println("生物呼吸");
    }
    private void eat(){
        System.out.println("生物吃东西");
    }
}

2.自定义注解MyAnnotation

@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "hello";
}

3.自定义接口MyInstance

public interface MyInstance {
    void info();
}

4.自定义Person

package www.demo9;

import java.util.Arrays;
@MyAnnotation(value = "hi")
public class Person extends Creature<String> implements Comparable<String>,MyInstance {
    private String name;
    int age;
    public int id;
    public Person(){

    }
    @MyAnnotation(value = "abc")
    private Person(String name){
        this.name=name;
    }
    Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    private String display(String interests,int age){
        return interests+age;
    }
    @MyAnnotation
    private String show(String nation) throws NullPointerException,ClassCastException{
        System.out.println("我的国籍是:"+nation);
        return nation;
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }

    @Override
    public void info() {
        System.out.println("我是一个人");
    }
     private static void showDesc(){
        System.out.println("我是一个可爱的人!");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\\'' +
                ", age=" + age +
                ", id=" + id +
                '}';
    }
}

做好准备工作之后,接下来就是通过反射获取运行时类的内部的各种结构。
一、获取运行时类的属性结构,权限修饰符,数据类型,变量名
代码如下:

	@Test
    public void test1(){
        Class<Person> clazz = Person.class;
        //获取属性结构
        //getFields():获取当前运行时类及其所有父类中声明为public访问权限的属性
        Field[] fields = clazz.getFields();
        for(Field f:fields){
            System.out.println(f);
        }
        System.out.println();
        //getDeclaredFields():获取当前运行时类的所有属性(不包含父类中声明的属性)
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field f:declaredFields){
            System.out.println(f);
        }
    }
    //获取权限修饰符,数据类型,变量名
    @Test
    public void test2(){
        Class<Person> clazz = Person.class;
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field f:declaredFields){
            //1.权限修饰符
            int modifier = f.getModifiers();
            System.out.print(Modifier.toString(modifier)+"\\t");
            //2.数据类型
            Class type = f.getType();
            System.out.print(type.getName()+"\\t");
            //3.变量名
            String name = f.getName();
            System.out.print(name);

            System.out.println();
        }
    }

输出结果:

单元测试 test1():输出结果:
public int www.demo9.Person.id
public double www.demo9.Creature.weight

private java.lang.String www.demo9.Person.name
int www.demo9.Person.age
public int www.demo9.Person.id

单元测试 test2():输出结果:
private	java.lang.String	name
	int	age
public	int	id

二、获取运行时类的方法结构

	@Test
    public void test3(){
        Class<Person> clazz = Person.class;
        //getMethods():获取当前运行时类及其所有父类中权限声明为public的方法
        Method[] methods = clazz.getMethods();
        for(Method m:methods){
            System.out.println(m);
        }
        System.out.println();
        //getDeclaredMethods():获取当前运行时类中所有的方法(不包含父类中声明的方法)
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for(Method m:declaredMethods){
            System.out.println(m);
        }
    }

输出结果:

public int www.demo9.Person.compareTo(java.lang.String)
public int www.demo9.Person.compareTo(java.lang.Object)
public void www.demo9.Person.info()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

public int www.demo9.Person.compareTo(java.lang.String)
public int www.demo9.Person.compareTo(java.lang.Object)
public void www.demo9.Person.info()
private java.lang.String www.demo9.Person.display(java.lang.String)
private java.lang.String www.demo9.Person.show(java.lang.String)

三、获取运行时类的方法的内部结构:

 	@Test
    public void test4(){
        Class<Person> clazz = Person.class;
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method m:declaredMethods){
            //1.获取方法的注解
            Annotation[] annotations = m.getAnnotations();
            for(Annotation a:annotations){
                System.out.println(a);
            }
            //2.获取方法的权限修饰符
            System.out.print(Modifier.toString(m.getModifiers())+"\\t");
            //3.获取方法的返回值类型
            System.out.print(m.getReturnType().getName()+"\\t");
            //4.方法名
            System.out.print(m.getName());
            System.out.print("(");
            //5.形参列表
            Class[] parameterTypes = m.getParameterTypes();
            if (!(parameterTypes==null&&parameterTypes.length==0)){
                for (int i=0;i<parameterTypes.length;i++) {
                    if (i==parameterTypes.length-1){
                        System.out.print(parameterTypes[i].getName()+"arg");
                        break;
                    }
                    System.out.print(parameterTypes[i].getName()+"arg"+",");
                }
            }
            System.out.print(")");

            //6.抛出的异常
            Class[] exceptionTypes = m.getExceptionTypes();
            if (exceptionTypes.length>0){
                System.out.print("throws");
                for (int i = 0; i < exceptionTypes.length; i++) {
                    System.out.print(exceptionTypes[i].getName()+",");
                    if (i==exceptionTypes.length-1){
                        System.out.print(exceptionTypes[i].getName());
                        break;
                    }
                }
            }
            System.out.println();
        }
    }

四、获取运行时类的构造器结构:

@Test
    public void test5(){
        Class<Person> clazz = Person.class;
        //获取当前运行时类中声明为public的构造器
        Constructor[] constructors = clazz.getConstructors();
        for(Constructor c:constructors){
            System.out.println(c);
        }
        System.out.println();
        //获取当前运行时类中所有的构造器
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for(Constructor c:declaredConstructors){
            System.out.println(c);
        }
    }

输出结果:

public www.demo9.Person()

www.demo9.Person(java.lang.String,int)
private www.demo9.Person(java.lang.String)
public www.demo9.Person()

五、获取运行时类的父类及其父类的泛型

@Test
    public void test6(){
        Class<Person> clazz = Person.class;
        //获取当前运行时类的父类
        Class superclass = clazz.getSuperclass();
        System.out.println(superclass);

        //获取当前运行时类的带泛型的父类
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass);
    }
    @Test
    public void test7(){
        Class<Person> clazz = Person.class;
        //获取运行时类的带泛型的父类的泛型
        Type genericSuperclass = clazz.getGenericSuperclass();
        ParameterizedType param = (ParameterizedType) genericSuperclass;
        //获取泛型
        Type[] actualTypeArguments = param.getActualTypeArguments();
//        System.out.println(actualTypeArguments[0].getTypeName());
        System.out.println(((Class)actualTypeArguments[0]).getName());
    }

输出结果:

单元测试test6()
class www.demo9.Creature
www.demo9.Creature<java.lang.String>

单元测试test7()
java.lang.String

六、获取运行时类的接口,注解,所在的包

@Test
    public void test8(){
        Class<Person> clazz = Person.class;
        //获取运行时类实现的接口
        Class[] interfaces = clazz.getInterfaces();
        for(Class inter:interfaces){
            System.out.println(inter);
        }
        //获取运行时类的父类实现的接口
        Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
        for(Class inter1:interfaces1){
            System.out.println(inter1);
        }
        //获取运行时类的注解
        Annotation[] annotations = clazz.getAnnotations();
        for(Annotation annotation:annotations){
            System.out.println(annotation);
        }
        //获取运行时类所在的包
        Package pack = clazz.getPackage();
        System.out.println(pack);
    }

输出结果:

interface java.lang.Comparable
interface www.demo9.MyInstance
interface java.io.Serializable
@www.demo9.MyAnnotation(value=hi)
package www.demo9

以上是关于Java 反射--获取类的内部结构详解的主要内容,如果未能解决你的问题,请参考以下文章

Java反射详解

java反射机制

31反射(获取Class实例剖析运行时类的完整结构读取properties文件反射创建类越过泛型检查)枚举

12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路

Java 反射之调用运行时类中指定的属性

Java反射机制详解