Java基础——反射有多强,用过才知道

反射是什么

在Java中,反射(Reflection)指的是在程序运行期间可以拿到一个对象的基本信息(属性、方法、注解等),所以反射是为了解决在运行期间,对某个未知的对象去获取其信息,调用其方法

如何使用反射

获取类信息

这里先明确一点,Class对象是在JVM执行过程中动态加载的(使用到了才会去加载),除了八大基本类型,其它类都是class,当然也包括接口(interface)、自定义类等

在这里我们新建一个People类

import lombok.Data;

@Data
public class People {
    private String name;

    public void say(){
        System.out.println("i'm people");
    }
}

Man类继承People类

@Data
public class Man extends People{
    public String name;
    private String sex;
    private int age;

    public Man(){}

    public Man(String name, String sex,int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    public void say(){
        System.out.println("i'm man");
    }

    public void myName(String name){
        System.out.println("i'm " + name);
    }

}

我们先以这个Man类来进行讲解,当JVM加载Man类时,首先读取Man.class文件到内存中,然后为Man创建一个Class对象,有三种方法可以根据类得到一个Class对象

第一种:通过实例对象来获取Class对象

//实例化对象
Man man = new Man();
Class classMan = man.getClass();//运行结果:class Basics.Reflection.Man

第二种:通过一个类对象获取

Class man1 = Man.class;//运行结果:class Basics.Reflection.Man

第三种:若是知道一个类的完整名称,则可以通过静态方法Class.forName()

Class man3 = Class.forName("Basics.Reflection.Man");//运行结果:class Basics.Reflection.Man

第四种:通过类加载器去获取

ClassLoader loader = ClassLoader.getSystemClassLoader();
Class classMan = loader.loadClass("Basics.Reflection.Man");
System.out.println(classMan);//运行结果:class Basics.Reflection.Man

我们还可以通过反射获取类的各种信息,比如类名、父类信息等

获取类名

	//通过Class获取类名
    String className = man1.getSimpleName();
    System.out.println(className);

获取父类

	//获取父类
    String superName = man1.getSuperclass().getSimpleName();
    System.out.println(superName);//打印结果:People
    //获取父类的父类
    String superName = man1.getSuperclass().getSuperclass().getSimpleName();
    System.out.println(superName);//打印结果:Object

还可以通过反射得到包路径

	//获取包路径
    String packageName = man1.getPackage().getName();
    System.out.println(packageName);//打印结果:Basics.Reflection

通过反射还可以判断该Class是否为接口、是否为枚举、是否为列表等操作,功能实属强大

获取实现接口,这里我们用Integer来举例

	Class integerClass = Integer.class;
    Class[] interfaces = integerClass.getInterfaces();
    for(Class interface1 : interfaces){
        System.out.println(interface1);
    }
    //打印结果:interface java.lang.Comparable

注意:getInterfaces()只返回当前类直接实现的接口类型,并不包括其父类实现的接口类型,若是获得父类的实现接口,可以先使用getSuperclass()得到父类的class对象,再去调用getInterfaces()来得到其实现接口

获取类属性

对于一个Object实例,我们获取到了它的Class对象,就可以得到它的一切信息,当然也包括属性

该属性信息是封装在一个Field对象里,Field包括
在这里插入图片描述
最主要的还是三个

name,通过 getName() 返回,表示字段名称

type,通过 getType() 返回,表示字段类型,也是一个Class实例,例如,String.class

modifiers,通过 getModifiers() 返回,表示字段的修饰符,它是一个int,不同的bit表示不同的含义

根据属性名获取某个属性的field(限public,包括父类)

	Man man = new Man();
    Class man1 = Man.class;
    Field remark = man1.getField("name");//这个name属性为Man.class的属性
    System.out.println(remark.getName());//name
    System.out.println(remark.getType());//class java.lang.String
    System.out.println(remark.getModifiers());//1
    

根据属性名名获取当前类的某个field(包括private,不包括父类)

	Man man = new Man();
    Class man1 = Man.class;
	Field remark = man1.getDeclaredField("sex");
    System.out.println(remark.getName());//sex
    System.out.println(remark.getType());//class java.lang.String
    System.out.println(remark.getModifiers());//2

获取所有属性的field[](限public,包括父类)

	Man man = new Man();
	Class man1 = Man.class;
	Field[] attribute = man1.getFields();

获取当前类的所有field[](包括private,不包括父类)

	Man man = new Man();
	Class man1 = Man.class;
	Field[] attributes = man1.getDeclaredFields();

获取类方法

该方法信息是封装在Method对象里,我们来看看Method对象的属性
在这里插入图片描述
比较重要的有四个属性:

name,通过 getName() 返回,表示方法名称

returnType,通过 getReturnType() 返回,表示方法返回类型

parameterTypes,通过 getParameterTypes() 返回,表示方法的参数类型,是一个class[]

modifiers,通过 getModifiers() 返回,它是一个int,不同的bit表示不同的含义

获取类中单个方法(限public,包括父类)

	Man man = new Man();
	Class man1 = Man.class;
	Method method = man1.getMethod("say");
	//调用子类方法,子类没有此方法就去调用父类方法
	method.invoke(man);

获取当前类的某个方法(包括private,不包括父类)

	Man man = new Man();
	Class man1 = Man.class;
	Method method1 = man1.getDeclaredMethod("myName", String.class);
    System.out.println(method1);
	//直接调用private方法,会出现java.lang.IllegalAccessException
	//需要加上下面这一句设置权限
	method1.setAccessible(true);
	//然后调用即可
	method1.invoke(man,"ALiangXLogic");//打印结果:i'm ALiangXLogic

获取所有的方法(限public,包括父类)

	Man man = new Man();
	Class man1 = Man.class;
	Method[] methods = man1.getMethods();

获取当前类的所有方法(包括private,不包括父类)

	Man man = new Man();
	Class man1 = Man.class;
	Method[] methods = man1.getDeclaredMethods();

获取构造器

正常创建实例

Man man = new Man();

通过反射来创造实例,调用Class类中的newInstance(),局限于只能调用public无参构造参数,构造方法若带有参数又或者构造方法为private,则不能通过反射创造实例

class.newInstance();

通过调用反射得到的构造器创建实例,可以反射任何构造器(可带参数),可以反射私有构造器

Constructor.newInstance()

我们主要看看通过反射得到的构造器创建实例,得到的构造器封装在一个Constructor对象里,我们来看看Constructor内部的属性
在这里插入图片描述
里面有几个重要的属性我给大家指出来
declaringClass,通过 getDeclaringClass() 返回,获取生明该构造函数的类

parameterTypes,通过 Class<?>[] getParameterTypes() 返回,获取构造函数参数的类型

modifiers,通过 getModifiers() 返回,它是一个int,不同的bit表示不同的含义

annotations,通过 byte[] getAnnotationBytes() 返回,表示构造器上使用的注解

Parameter[] getParameters() 获取构造函数的参数

获取Constructor(限public)

	Constructor constructor = Man.class.getConstructor(String.class,String.class,int.class);
    Man con = (Man) constructor.newInstance("ALiangXLogic","male",18);
    System.out.println(con);

获取某个Constructor

Constructor constructor = Man.class.getDeclaredConstructor(String.class,String.class,int.class);
//得到构造器就可以执行下面的方法了

获取所有的Constructor(限public)

Constructor[] constructors = Man.class.getConstructors();

获取所有Constructor

Constructor[] constructors = Man.class.getDeclaredConstructors();

获得注解

得到类注解

	Man man = new Man();
	Class man1 = Man.class;
	Annotation[] annotations1 = man1.getDeclaredAnnotations();
    for(Annotation annotation : annotations1){
        System.out.println(annotation);
    }

得到属性注解

	Man man = new Man();
	Class man1 = Man.class;
	Annotation[] annotations2 = man1.getDeclaredField("sex").getAnnotations();
	for(Annotation annotation : annotations2){
        System.out.println(annotation);
    }

完成:2021/4/03 20:08 ALiangXLogic

转载请标注原作者,谢谢你们的支持,能给个小心心吗?
在这里插入图片描述

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉淀顶峰相见的PET

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值