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

简介: 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


目录
相关文章
|
2月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
166 57
|
21天前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
19天前
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
2月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
70 8
|
2月前
|
JSON Java 程序员
Java|如何用一个统一结构接收成员名称不固定的数据
本文介绍了一种 Java 中如何用一个统一结构接收成员名称不固定的数据的方法。
34 3
|
2月前
|
监控 Java
Java基础——反射
本文介绍了Java反射机制的基本概念和使用方法,包括`Class`类的使用、动态加载类、获取方法和成员变量信息、方法反射操作、以及通过反射了解集合泛型的本质。同时,文章还探讨了动态代理的概念及其应用,通过实例展示了如何利用动态代理实现面向切面编程(AOP),例如为方法执行添加性能监控。
|
2月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
2月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
145 4
|
2月前
|
Java Android开发
Eclipse 创建 Java 类
Eclipse 创建 Java 类
32 0
|
5月前
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
68 7