相关文章推荐
严肃的荒野  ·  山东女排0:3不敌上海无缘冠军!2021年全 ...·  6 月前    · 
另类的甜瓜  ·  6天3人接连丧命!2022曼岛TT摩托车赛再 ...·  2 年前    · 
求醉的酸菜鱼  ·  《惊声尖叫6》发布新预告 ...·  2 年前    · 
千年单身的开水瓶  ·  胡山总领事往见悉尼大学校长斯宾塞博士·  2 年前    · 
冲动的显示器  ·  又看了另一部反映他们夫妇的纪录片《心火:写给 ...·  2 年前    · 
Code  ›  深入理解 Java 反射:Class (反射的入口)开发者社区
引用类型
https://cloud.tencent.com/developer/article/1015077
热心的砖头
2 年前
作者头像
张拭心 shixinzhang
0 篇文章

深入理解 Java 反射:Class (反射的入口)

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > 拭心的安卓进阶之路 > 正文

深入理解 Java 反射:Class (反射的入口)

发布 于 2018-01-08 10:38:30
1.1K 0
举报

深入理解 Java 反射系列:

  • 深入理解 Java 反射:Class (反射的入口)
  • 深入理解 Java 反射:Field (成员变量)
  • 深入理解 Java 反射:Method (成员方法)

什么是 Reflection 反射,为什么要用它

Java 强类型语言,但是我们在运行时有了解、修改信息的需求,包括类信息、成员信息以及数组信息。

Java 中 Reflection 和 Introspection 区别?

说起反射,还有一个相似的概念 ‘Introspection’,字面意思是“自省、内省”,它们之间的区别如下:

  • 内省
    • 在运行时检查一个对象的类型或者属性
    • 最常见的例子就是运行时通过 a instanceof A 来判断 a 对象的类型
  • 反射
    • 用来在运行时检查或者修改一个对象信息
    • 可以用来实现看似不可能的操作,比如访问私有方法,动态创建对象

可以看到,反射是在内省的基础上,增加了修改的能力。

反射的入口: java.lang.Class

日常开发中的对象,分为两种, 基本类型 和 引用类型 :

  • 基本类型 ,(固定的 8 种)
    • 整数:byte, short, int, long
    • 小数:float, double
    • 字符:char
    • 布尔值:boolean
  • 引用类型
    • 所有的引用类型都继承自 java.lang.Object
    • 类,枚举,数组,接口都是引用类型
    • java.io.Serializable 接口,基本类型的包装类(比如 java.lang.Double )也是引用类型

对每一种对象,JVM 都会实例化一个 java.lang.Class 的实例,java.lang.Class 为我们提供了在运行时访问对象的属性和类型信息的能力。Class 还提供了创建新的类和对象的能力。最重要的是,Class 是调用其他反射 API 的入口,我们必须先获得一个 Class 实例才可以进行接下来的操作。

得到一个 Class 对象

除了 java.lang.reflect.ReflectPermission 以外, java.lang.reflect 中的其他类都没有 public 的构造函数,也就是说要得到这些类,我们必须通过 Class 。

下面是几种得到 Class 对象的不同方法:

1.Object.getClass 方法

如果我们已经拿到了一个对象,可以很方便地使用它的 getClass 方法获得一个 Class 对象(当然这 仅限于引用类型 的对象):

Class c = "shixinzhang.top".getClass();

返回的对象 c 是 String 类型。

enum Sex{
    FEMALE,
Class c = FEMALE.getClass();

上述例子中 FEMALE 是 枚举 Sex 的实例,因此 FEMALE.getClass() 返回的就是 枚举类型 Sex 的 Class。

byte[] bytes = new byte[1024];
Class<? extends byte[]>c = bytes.getClass();

由于数组也是 Object 的一种,因此我们可以调用 getClass() 方法获得 byte 数组类型的 Class。

2. .class 语法

如果我们当前没有某个类的对象,无法使用 getClass() 方法,那还可以使用另外一种方法获取 Class: 在要获得的类名后加上 .class ,比如这样:

Integer.class.newInstance();
int.class.newInstance()

可以看到,这种方式不仅能用于引用类型,基本类型也可以。

当然数组也可以喽:

Class b = int[][].class;

3.Class.forName()

如果我们有一个类的完整路径,就可以使用 Class.forName(“类完整的路径”) 来得到相应的 Class,这个方法 只能用于引用类型 ,比如:

Class<?> c = Class.forName("java.lang.String");
Class<?> aClass = Class.forName("top.shixinzhang.androiddemo2.beans.BookBean");

4.静态属性 TYPE

上面介绍,使用 .class 后缀可以很方便地获得基本类型的 Class。

对于基本类型和 void 的包装类,还有另外一种方式获得 Class,那就是静态属性 TYPE 。

每个包装类都有 TYPE 属性,以 Double 为例:

public static final Class<Double> TYPE
        = (Class<Double>) double[].class.getComponentType();

可以看到这个属性就是使用 .class 的方式获得 Class 并保存。

因此我们可以直接调用包装类的 TYPE:

Class<Integer> integerWrapper = Integer.TYPE;
Class<Double> doubleWrapper = Double.TYPE;
Class<Void> voidWrapper = Void.TYPE;

5.返回 Class 的方法

如果我们已经有了一个 Class,可以使用下面的一些方法来获得它相关的类:

  • Class.getSuperclass()
    • 返回调用类的父类
  • Class.getClasses()
    • 返回调用类的所有公共类、接口、枚举组成的 Class 数组,包括继承的
  • Class.getDeclaredClasses()
    • 返回调用类显式声明的所有类、接口、枚举组成的 Class 数组
  • Class.getDeclaringClass()
  • java.lang.reflect.Field.getDeclaringClass()
  • java.lang.reflect.Method.getDeclaringClass()
  • java.lang.reflect.Constructor.getDeclaringClass()
    • 返回类/属性/方法/构造器所在的类

Class 的修饰符:Modifier

一个 Class 可以被以下修饰符的一种或者多种修饰:

  • 访问权限控制符: public , protected , private
  • 抽象的、需要实现的: abstract
  • 限制只能有一个实例的: static
  • 不允许修改的: final
  • 线程同步锁: synchronized
  • 原生函数: native
  • 采用严格的浮点精度: strictfp
  • 接口
  • 注解

当然上面的修饰符不是所有 Class 都可以修饰,比如:

  • Interface 不能是 final 的
  • enum 不能是 abstract 的

java.lang.reflect.Modifier 提供了对 Class 修饰符的解码,我们可以使用 Class.getModifiers() 获得调用类的修饰符的二进制值,然后使用 Modifier.toString(int modifiers) 将二进制值转换为字符串, Modifier.toString() 方法实现如下:

public static java.lang.String toString(int modifiers) {
    StringBuilder buf = new StringBuilder();
    if (isPublic(modifiers)) {
        buf.append("public ");
    if (isProtected(modifiers)) {
        buf.append("protected ");
    if (isPrivate(modifiers)) {
        buf.append("private ");
    if (isAbstract(modifiers)) {
        buf.append("abstract ");
    if (isStatic(modifiers)) {
        buf.append("static ");
    if (isFinal(modifiers)) {
        buf.append("final ");
    if (isTransient(modifiers)) {
        buf.append("transient ");
    if (isVolatile(modifiers)) {
        buf.append("volatile ");
    if (isSynchronized(modifiers)) {
        buf.append("synchronized ");
    if (isNative(modifiers)) {
        buf.append("native ");
    if (isStrict(modifiers)) {
        buf.append("strictfp ");
    if (isInterface(modifiers)) {
        buf.append("interface ");
    if (buf.length() == 0) {
        return "";
 
推荐文章
严肃的荒野  ·  山东女排0:3不敌上海无缘冠军!2021年全国女排锦标赛在江门落幕!_工作动态_江门市文化广电旅游体育局
6 月前
另类的甜瓜  ·  6天3人接连丧命!2022曼岛TT摩托车赛再出大事故|赛车|戴维|tt_网易体育
2 年前
求醉的酸菜鱼  ·  《惊声尖叫6》发布新预告 鬼脸噩梦再度来袭_手机新浪网
2 年前
千年单身的开水瓶  ·  胡山总领事往见悉尼大学校长斯宾塞博士
2 年前
冲动的显示器  ·  又看了另一部反映他们夫妇的纪录片《心火:写给火山夫妇的安魂曲 - 知乎
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号