java 反射机制的入门,使用,原理

Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态的获取信息以及动态调用对象的方法的功能称为Java 的反射机制。

首先先定义一个类

@Data  //getset  lombok 插件
@AllArgsConstructor  //有参构造
@NoArgsConstructor  //无参构造
public class Student {
    public String stuName;
}
    //正常调用
        Student student = new Student();
        student.setStuName("ws");
        System.out.println(student.getStuName());
输出结果 ws

这时候,我们使用 JDK 提供的反射 API 进行反射调用:

 //获取 Class 类对象
        Class student1 = Class.forName("Student");
        // 获取方法的 Method 对象
        Method setStuName = student1.getMethod("setStuName", String.class); //第一个参数 方法名称   第二个参数入参类型
        //根据class对象获取构造器
        Constructor constructor = student1.getConstructor();
        //使用 Constructor 对象的 newInstance 方法获取反射类对象
          Object o = constructor.newInstance();
          //利用 invoke 方法调用方法
         setStuName.invoke(o, "ws");
         //获取方法的Method 对象
        Method getStuName = student1.getMethod("getStuName");
        System.out.println(getStuName.invoke(o));

上面两段代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Student),而第二段代码则是在运行时通过字符串值才得知要运行的类(“Student”)。

从这个简单的例子可以看出,一般情况下我们使用反射获取一个对象的步骤:

  • 获取class实例
   Class student1 = Class.forName("Student");
  • 根据 Class 对象实例获取 Constructor 对象
 Constructor constructor = student1.getConstructor();
  • 使用 Constructor 对象的 newInstance 方法获取反射类对象
Object o = constructor.newInstance();

而如果要调用某一个方法,则需要经过下面的步骤:

  • 获取方法的 Method 对象
  Method setStuName = student1.getMethod("setStuName", String.class); //第一个参数 方法名称   第二个参数入参类型
  • 利用 invoke 方法调用方法
  setStuName.invoke(o, "yhl");

反射常用API

class 对象

Class对象是Java反射的基础,它包含了与类相关的信息,事实上,Class对象就是用来创建类的所有对象的。Class对象是java.lang.Class这个类生成的对象,其中类型参数T表示由此 Class 对象建模的类的类型。例如,String.class的类型是 Class;如果将被建模的类未知,则使用Class<?>

获取反射中的Class对象

(1) 通过实例变量的getClass()方法。例如:

Class c1 = new String("abc").getClass();

(2) 通过Class类的静态方法——forName()来实现,例如:

Class class =Class.forName(className);

注意:当使用Class.forName()方法时,你必须提供完全限定类名。即类名要包括所有包

名。例如,如果MyObject是位于包com.jenkov.myapp下,那么类的完全限定名称是com.jenkov.myapp.MyObject。如果在运行时类路径上找不到类,Class.forName()方法会抛出一个ClassNotFoundException。

(3) 使用类字面常量或TYPE字段,例如:

Class myObjectClass= MyObject.class;//(类字面常量不仅可以应用于普通的类,也可以应用

于接口、数组以及基本数据类型),这种方式不仅更简单,而且更安全,因为它在编译时就会受到检查,并且根除了对forName方法的调用,所以也更高效,建议使用“.class”的形式。

Class c = Integer.TYPE;
(TYPE是基本数据类型的包装类型的一个标准字段,它是一个引用,指向对应的基本数据类型的Class对象),附表如下,两边等价:
在这里插入图片描述

类名

从Class对象中可以获取两个不同的类名。完全限定类名(包括包名)可以使用getName()或getCanonicalName()方法获取,例如:

Class aClass = MyObject.class;
String className = aClass.getName();
String className1 = aClass.getCanonicalName();

如果想要获取不含包名的类名可以使用getSimpleName() 方法,如下:

 Class  aClass = MyObject.class;
     String simpleClassName = aClass.getSimpleName();

修饰符

使用Class对象可以获取一个类的修饰符.类的修饰符即关键字"public",“private”, "static"等. 如下:

 Class aClass = MyObject.class;
    int modifiers = aClass.getModifiers();

包信息

使用Class对象可以获取包信息,如下:

Class aClass = MyObject.class;
Package package = aClass.getPackage();
String packageName = package.getname();

父类

通过Class对象可以获取类的父类,如下:

Class  aClass = MyObject.class;
Class superclass = aClass.getSuperclass();
//父类的Class对象和其它Class对象一样是一个Class对象,可以继续使用反射.

实现的接口

通过给定的类可以获取这个类所实现的接口列表,如下:

Class aClass = MyObject.class;
Class[] interfaces = aClass.getInterfaces();

构造函数

使用Class对象可以获取类的构造函数,如下:

  Class aClass = MyObject.class;
Constructor[] constructors = aClass.getConstructors();

通过反射创建类对象

通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。

第一种:通过 Class 对象的 newInstance() 方法。

Class<Student> studentClass = Student.class;
  Student ww = (Student)student1.newInstance();

第二种:通过 Constructor 对象的 newInstance() 方法

    Class<Student> studentClass = Student.class;
Constructor constructor = studentClass.getConstructor();
Student ww  = (Student )constructor.newInstance();

通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。
下面的代码就调用了一个有参数的构造方法进行了类对象的初始化。

  Class<Student> studentClass = Student.class;
        Constructor<Student> constructor = studentClass.getConstructor(String.class);// 参数的类型  
        Student ww = constructor.newInstance("ww");

通过反射获取类属性、方法

我们通过 Class 对象的 getFields() 方法可以获取 Class 类的属性,但无法获取私有属性。

 Class<Student> stu = Student.class;
        Field[] fields = stu.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }

而如果使用 Class 对象的 getDeclaredFields() 方法则可以获取包括私有属性在内的所有属性
与获取类属性一样,当我们去获取类方法、类构造器时,如果要获取私有方法或私有构造器,则必须使用有 declared 关键字的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值