Java的反射机制

Java的反射机制

什么是反射?

Java的反射是指程序在运行期间可以拿到一个对象的所有信息。

正常情况下,如果我们要调用一个对象的方法,或者访问一个对象的字段,通常会传入对象的实例。

import cn.wustxiao.learnjava.Person;

public class Main{
  String getFullName(Person p){
    return p.getFirstName() + " " + p.getLastName();
  }
}

但是如果不能获得Person类,只有一个Object实例,比如这样:

String getFullName(Object obj){
  return ???
}

所以,反射是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法。

Class类

除了int等基本类型外,Java的其他类型全部都是class(包括interface)。例如:

  • String
  • Object
  • Runnable
  • Exception

仔细思考,我们可以得出结论:class(包括interface)的本质是数据类型(Type)。无继承关系的数据类型无法赋值:

Number n = new Double(123.456); // OK
String s = new Double(123.456); // compile error!

class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时,将其加载进内存。每加载一种class,JVM就为其创建一个class类型的实例,并关联起来。注意:这里的Class类型是一个名叫Classclass

public final class Class{
  private Class(){}
}

String类为例,当JVM加载String类时,它首先读取String.class文件到内存,然后,为String类创建一个Class实例并关联起来:

Class cls = new Class(String);

这个Class实例是JVM内部创建的,如果我们查看JDK源码,可以发现Class类的构造方法是private,只有JVM能创建Class实例,我们自己的Java程序是无法创建Class实例的。

所以,JVM持有的每个Class实例都指向一个数据类型(classinterface)

一个Class实例包含了该class的所有完整信息:

Class Instance   -- String
name = "java.lang.String"
package = "java.lang"
super = "java.lang.Object"
interface = CharSequence...
field = value[],hash,...
method = indexOf()...

如何通过Class实例获取到该实例对应的class的所有方法

由于JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该Class的所有信息,包括类名,包名,父类,实现的接口,所有方法,字段等,因此,如果获取了某个Clsss实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息

这种通过Class实例获取class信息的方法称为反射

如何获取一个classClass实例?有三个方法:

方法一:直接通过一个class的静态变量class获取:

Class cls = String.class;

方法二:如果我们有一个实例变量,可以通过该实例变量提供的getClass()方法获取:

String s = "Hello"
Class cls = s.getClass();

方法三:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取:

Class cls = Class.forName("java.lang.String");

因为Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例。可以用==比较两个Class实例:

Class cls1 = String.class;

String s = "Hello";
Class cls2 = s.getClass();

Class cls3 = Class.forName('java.lang.String');

boolean sameClass = cls1 = cls2 = cls3; // true

注意一下Class实例比较和instanceOf的差别

Integer n = new Integer(123);

boolean b3 = n instanceof Integer; // true
boolean b4 = n instanceof Number;	 // true

boolean b1 = n.getClass() == Integer.class;  // true
boolean b2 = n.getClass() == Number.class;   // false

动态加载class的特性对于Java程序非常重要。利用JVM动态加载class的特性,我们才能在运行期根据条件加载不同的实现类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值