深入理解 Java 反射系列:

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

读完本文你将了解到:

  • 什么是 Reflection 反射为什么要用它
  • Java 中 Reflection 和 Introspection 区别
  • 反射的入口javalangClass
    • 得到一个 Class 对象
  • Class 的修饰符Modifier
  • Class 的成员Member
    • 获取构造函数
    • 获取成员变量
    • 获取成员方法
  • Thanks

什么是 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,MALE
}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 "";}buf.setLength(buf.length() - 1);return buf.toString();
}

注意:

  • Interface 默认是 abstract 的,虽然我们没有添加,编译器会在编译器为每个 Interface 添加这个修饰符。
  • 只有被 @Retention(RetentionPolicy.RUNTIME) 修饰的注解才可以在运行时被发射获取
  • Java 中预定义的注解 @Deprecated,@Override, 和 @SuppressWarnings 中只有 @Deprecated 可以在运行时被访问到

Class 的成员:Member

java.lang.reflect.Member 是一个接口,代表 Class 的成员,每个成员都有类型,分为是否从父类继承,还有是否可以直接访问。

Member 有三个实现类:

  • java.lang.reflect.Constructor:表示该 Class 的构造函数
  • java.lang.reflect.Field:表示该 Class 的成员变量
  • java.lang.reflect.Method:表示该 Class 的成员方法

获取构造函数

java.lang.Class 提供了以下方法用于获取该类的构造函数:

注意:构造函数无法从父类继承

获取成员变量

java.lang.Class 提供了以下方法用于获取该类的成员变量:

获取成员方法

java.lang.Class 提供了以下方法用于获取该类的成员方法:

Thanks

http://docs.oracle.com/javase/tutorial/reflect/TOC.html
http://stackoverflow.com/questions/2044446/java-introspection-and-reflection
http://stormzhang.com/java/2013/07/29/java-reflection/

http://www.infoq.com/cn/articles/cf-java-reflection-dynamic-proxy
https://github.com/JustinSDK/JavaSE6Tutorial/blob/master/docs/CH16.md

深入理解 Java 反射:Class (反射的入口)相关推荐

  1. 深入理解Java中的反射技术

    Java中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法:并且对于任意一个对象,都能够调用它的任意一个方法:这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射 ...

  2. 深入理解Java中的反射机制和使用原理!详细解析invoke方法的执行和使用

    反射的概念 反射:Refelection,反射是Java的特征之一,允许运行中的Java程序获取自身信息,并可以操作类或者对象的内部属性 通过反射,可以在运行时获得程序或者程序中的每一个类型的成员活成 ...

  3. 理解java中的反射

    就是通过对象来得到类的类类型(class type)以及它所声明的方法啊参数之类的东西.举个例子,通过反射,你可以得到类所声明的方法,可以不用通过这个类的实例对象来执行方法.与反射密切相关的是动态加载 ...

  4. 反射 java 例子 get_Java反射实例

    Java反射(Reflection)就是在运行 Java 程序时,可以加载.探知.使用编译期间完全未知的类.也就是说,Java 程序可以加载一个运行时才得知类名的类,获得类的完整构造方法,并实例化出对 ...

  5. 理解java代理模式

    1.java反射机制 理解代理模式的前提是先理解java中的反射机制,先看一个例子: JDBC加载驱动时,Class.forName("com.mysql.jdbc.Driver" ...

  6. 深入理解java反射机制

    一,java的核心机制 java有两种核心机制:java虚拟机(JavaVirtual Machine)与垃圾收集机制(Garbage collection): Java虚拟机:是运行所有Java程序 ...

  7. 深入理解Java类型信息(Class对象)与反射机制

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java并发之synchronize ...

  8. 如何理解java反射_怎么理解java反射

    怎么理解java反射? 概述 Java 反射是可以让我们在运行时获取类的方法.属性.父类.接口等类的内部信息的机制.也就是说,反射本质上是一个"反着来"的过程.我们通过new创建一 ...

  9. 深入理解Java反射+动态代理,java开发面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起在群里探讨技术. 答: ...

最新文章

  1. ASP.NET Core 2.0 : 三. 项目结构
  2. 搭建Linux0.11系统环境
  3. 数据库的设计(一些观点) _转
  4. http介绍(3)http1.0 和http1.1 区别
  5. 理解进程调度时机跟踪分析进程调度与进程切换的过程
  6. Codeforces Round #628 (Div. 2) E. Ehab‘s REAL Number Theory Problem 巧妙的质因子建图
  7. 做梦都在想的游戏设备
  8. 有序充电matlab仿真,电动汽车有序充电策略研究
  9. python备份文件
  10. 关于管理者应该拥有的的六十…
  11. 打架打出来的牛逼城市!
  12. 【建议收藏】 11个适合程序员逛的在线社区
  13. 北京二手房价10月微涨 业内:坚持限购就不会大涨
  14. Linux下编译链接动态库符号问题
  15. 2017诺贝尔文学奖揭晓!1901-2017年最全诺奖书单来了
  16. 了解RO、RW、ZI和.text .bss .data
  17. Mac解决JAVA_HOME问题
  18. 如何编写好的代码/成为一个更好的程序员
  19. python中算法定义_Python入门进阶笔记--04Python中表示“组”的概念与定义
  20. 干了两晚,带你探索那讲不清的字符串

热门文章

  1. 高新技术企业认定中涉及的领域有哪些?
  2. File System 定额(配额查询)
  3. mysql查询bom清单_Oracle EBS-SQL (BOM-12):BOM清单查询
  4. python能开发小程序吗_搭建小程序用Python语言可以搭建吗?
  5. 相处模式计算机型,三天内,女朋友;大于三天,电脑:两性相处,“尺寸”很重要...
  6. MessageBox in wpf
  7. 关于final修饰的变量赋值的问题
  8. 企业中台最佳实践--组织架构调整(五)
  9. CSS设置高度等于动态的宽度
  10. ROS2机器人笔记20-11-29