Java中的反射机制

本文介绍了Java的反射机制,包括在运行时动态获取类信息、创建对象、调用方法和访问字段的功能。通过Class对象,可以获取类的构造器、修饰符、方法、字段等,并详细阐述了各种获取方式。此外,还讨论了new与反射创建对象的区别以及如何通过反射调用方法和修改字段值。
摘要由CSDN通过智能技术生成

什么是反射机制:

  • 编译期:编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件
  • 运行期:将可执行文件交给操作系统去执行。
  • JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

java的反射机制提供了什么功能?

  • 在运行时能够判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任一对象的方法
  • 在运行时创建新类对象

new和反射创建有什么区别

  • new: 静态编译,在编译期就将模块编译进来,执行该字节码文件,所有的模块都被加载;
  • 反射:动态编译,编译期没有加载,等到模块被调用时才加载;

Java反射是如何使用的

获取类–获取Class对象

  • 第一种方法:Class<?> classType = Class.forName() 可以通过传入一个全限定类名(包含包名)返回一个该类的Class类对象引用 。
try
{
    Class a = Class.forName("mytest.testclass");//ClassPath:写需要反射的类名,一般是以包名.类名
    System.out.println(a.getName());
}
catch (ClassNotFoundException e){
    e.printStackTrace();
}
  • 第二种方法: Class<?> classType = object.getClass() 通过引用的到Class对象。这种方式主要是需要把类先实例化出来才能继续使用
testclass test = new testclass();//实例化
Class a = test.getClass();//对象的getClass方法实现
  • 第三种方法: Class<?> classType = Object.class 通过类字面常量获得,好处就是懒加载,只有使用时才会加载。
Class test = testclass.class;//直接使用类的.class方法,

第三种方法不需要进行异常捕获,上述两种方法搜需要进行异常处理

获得构造器

  • getDeclaredConstructors();    获取所有的构造函数
  • getDeclaredConstructor(参数类型);  获取一个所有的构造函数
  • getConstructors();          获取所有公开的构造函数
  • getConstructor(参数类型);        获取单个公开的构造函数

import java.lang.reflect.Constructor;

public class Main {
    public static void main(String[] args) {
        Class test = student.class;
        Constructor[] constructors = test.getConstructors();//获取所有公开的构造函数
        Constructor[] constructorsAll = test.getDeclaredConstructors();//获取所有的构造函数,包括私有的
        try
        {

            Constructor constructorsSomeone= test.getConstructor(String.class);//获取指定参数的公开的构造函数
            Constructor constructorsSomeoneAll = test.getDeclaredConstructor(String.class);//获取指定参数的所有构造函数
            student obj = (student)constructorsSomeone.newInstance("哈哈");
            obj.getname();
        }
        catch  (Exception e) {
            e.printStackTrace();
        }
    }
}
class student
{
    private student() {}//私有的构造函数
    public student(String name)
    {
        System.out.println(name);
    }
    public student(String name,int a)
    {
        System.out.println(name);
    }
    public void getname()
    {
        System.out.println("呵呵");
    }
}

获取修饰符

  • getModifiers();  //获取所有修饰符
    返回类型:整数类型,如果有两个修饰符,则返回两个修饰符之和,例如public static void getAll(){ }
    返回值会是public和static之和
    整数定义:
  • 0–默认不写
  • 1–public
  • 2–private
  • 4–protected
  • 8–static
  • 16–final
  • 32–synchronized
  • 64–volatile
  • 128–transient
  • 256–native
  • 512–interface
  • 1024–abstract
Class test = student.class;
Constructor[] constructors = test.getDeclaredConstructors();
for (Constructor constructor : constructors) {
    System.out.println(constructor.getModifiers());
}

获取后可以根据Modifier类进行判断

Constructor[] constructors = test.getDeclaredConstructors();
for (Constructor constructor : constructors) {
    Modifier.isPublic(constructor.getModifiers());
}

获取名字

返回类型:String,可以反射类名,方法名,构造函数名等等
getName();    //获取全名 例如:com.bean.Book
getSimpleName()  //获取类名 例如:Book

Class test = student.class;
String name = test.getName();
String simplename = test.getSimpleName();

获得方法

  • getMethods()  //获取所有公开的方法
    注意:它会将系统自带的方法也得到
Class test = student.class;
Method[] methods = test.getMethods();    //获取所有的公开方法
for (Method method : methods) {
     System.out.println(method.getName());
}
  • getDeclaredMethods()   //获取所有的方法
     注意:它不会获取系统自带的方法
Class test = student.class;
Method[] methods = test.getDeclaredMethods();    //获取所有的公开方法
for (Method method : methods) {
     System.out.println(method.getName());
}
  • getDeclaredMethod(String name)    //获取单个的所有方法 参数是可指定方法名
Method method = test.getDeclaredMethod("getname");    //获取单个所有的方法
System.out.println(method.getName());
  • getDeclaredMethod方法可以重载为getDeclaredMethod (String name ,Class<?>… parameterTypes)
    可以获取该类的重载方法
Method method = test.getDeclaredMethod("getname",String.class);   
System.out.println(method.getName());

获取字段

  • getFields()   //获取所有的公开字段
  • getField(String name)  //参数可以指定字段  获取单个public字段
  • getDeclaredFields()  //获取所有的字段
  • getDeclaredField(String name)  //获取单个字段 参数可以指定字段
Class test = student.class;
try
{
    //Public
    Field[] fields = test.getFields();   //所有公开字段
    Field id = test.getField("age"); //age字段
    //所有
    Field[] declaredFields = test.getDeclaredFields();   //所有字段
    test.getDeclaredField("name");   //name字段
    System.out.println(id.getName());
}
catch (Exception ex)
{
    ex.printStackTrace();
}

获取修改字段相关信息

反射只是通过Class对象获得方法和字段,要获取实例的字段就要传入一个具体的实例。

获取字段值
  1. Object value = field.get( Object obj) 通过get方法获得实例对象obj对应的field的值。
 try
{
    student stu = new student("xxx");//创建实例
    Field field = student.class.getField("name");
    Object value = field.get(stu);//这样获取必须传入一个实例
}
catch (Exception ex)
{
    ex.printStackTrace();
}
  1. 如果field是静态字段则可以直接使用get(null)获取值。
  2. 获取基本类型字段的值 : int value = field.get(Object obj) 获取int类型的字段。还有其他类型也是用同样的方法。
  3. private修饰的字段无法直接获得,必须先设置file.setAccessible(true) 才能访问
获取字段相关信息并通过Modifier解析修饰符
  • Annotation<?> annotation = field.getAnnotation(Class annotationClass) 返回字段上的指定注解
  • Annotation[ ] annotations = field.getDeclaredAnnotations() 返回字段上的所有注解数组
  • Class<?> type = field.getType() 返回 字段 的类型 的 Class对象。
  • int modifier = field.getModifiers() 以int形式返回字段的修饰符。
  1. 通过Modifier静态方法判断是不是某一个权限修饰符,如Modifier.isPrivate(modifier)
  2. Modifier静态方法toString 返回权限标识符。
设置修改字段值
  • field.set( Object obj, Object value) 通过set方法设置实例对象obj对应的file字段的值为value。
  • 设置基本类型字段的值 :field.set(Object obj,int value) 获取int类型的字段。还有其他类型也是用同样的方法。
  • private修饰的字段无法直接设置,必须先设置field.setAccessible(true) 才能设置。
  • 被final修饰的字段,可以通过反射临时修改值,但是不会把原始值修改了,所以final是绝对不可变的。

获取包

返回类型:package
getPackage();

Package aPackage = test.getPackage();

获取接口

返回类型:Class[] interfaces
getInterfaces()

Class[] interfaces = test.getInterfaces();

获取父类/超类

返回类型:Class superclass
getSuperclass()

Class superclass = test.getSuperclass();

获取方法相关信息

和字段一样需要传入一个实例对象。

  • 获取字段相关信息并通过Modifier解析修饰符
  1. Annotation<?> annotation = method.getAnnotation(Class annotationClass) 返回方法上的指定注解
  2. Annotation[ ] annotations = method.getDeclaredAnnotations() 返回方法上的所有注解数组
  3. Class<?> type = field.getReturnType() 返回 方法返回值类型 的 Class对象。
  4. getModifiers()方法使用与获取字段的使用方式相同
  • 通过反射调用方法
  1. method.invoke(Object obj, Object… args) 传入实例对象obj和方法对应的参数。
  2. private修饰的方法无法反射,必须先设置method.setAccessible(true) 才能反射调用。

创建实例对象其他办法

  • 通过反射得来的构造器创建实例
Constructor<?> constructor = test.getConstructor(new Class[]{});
Student student1 = (Student)constructor.newInstance();
Constructor<?> constructor2 = test.getConstructor(new Class[]{int.class});
Student student2 = (Student)constructor2.newInstance(12);
  • 通过Class对象创建实例
Student student = Student.class.newInstance();
  • 还有通过 new 、 反序列化、colon( ) 方法创建对象,Java中所以一共有5种方法创建实例对象

参考链接:
JAVA 反射用法
java反射方法和使用

欢迎关注我的个人博客zenshin’blog

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值