Reference:

Java编程思想

java 反射(Reflect)

Java系列笔记(2) - Java RTTI和反射机制

Java Reflection in Action, 有空再补

----------------------------------------------------------------------------------------------

对于面向对象, 以多态的方式编写程序是首选的方式, 即使用基类reference, 而不是具体的类对象来编写程序

在这种情况下, 你根本就不需要知道基类reference具体指向的是那个类对象, 因为编译器会自动调用相应的逻辑, 大大的简化了编程的复杂度

比如下面的例子, 对于draw, 只需要写Shape.draw(), 此时Shape可以指向circle, square, triangle, 任一个对象

所以对于绝大部分情况下, 其实是不需要知道RTTI (Run-time Type Identification)的, 所以当你用到RTTI, 首先确认你真的需要吗, 设计没有问题吗, 不应该使用多态吗?

当然对于一些特殊和复杂的情况下, 获取RTTI是有较大帮助的,

比如上面的例子, 你只想把circle画成红色来高亮强调, 或则在调用旋转操作的时候想要跳过circle(因为旋转对circle没有意义), 这个时候就需要RTTI

对于Java的RTTI, 无论什么形式, 没有什么神秘的, 毫无例外的都是通过class对象来获得信息.

传统的RTTI和新的Reflection的唯一差别, 就是在何时去check class对象文件
传统的RTTI是在编译时候去check, 这个其实可以满足绝大部分需求

但是对于某些需求,
从磁盘, 或网络连接中读取一个对象, 在编译的时候还没有读, 所以你无法在编译的时候check
在RMI(远程方法调用)中, 需要知道你调用的类的各种信息
这些情况下, class对象文件必须到运行时才能获取(从磁盘或网络上), 这是传统的RTTI无法支持的
这时就需要使用Reflection接口

Class对象

可以看到class对象是RTTI的核心, 下面就具体来看看这个对象

在Java中, 每个class都有一个相应的Class对象(每个类编译完成后, 存放在生成的.class文件中), 用于表示这个类的类型信息.
Class对象用于创建类的所有普通的instance, 并且RTTI也是通过Class对象实现, 哪怕是最简单的cast

当类第一次被使用时, class对象会被类加载器加载到JVM中,

确切的说, 当第一次引用该类的static member时, class对象会被加载. 构造函数是隐含的static member, 所以用new创建对象的时候也会被当作引用static member

This happens when the program makes the first reference to a static member of that class.
It turns out that the constructor is also a static method of a class, even though the static keyword is not used for a constructor. Therefore, creating a new object of that class using the new operator also counts as a reference to a static member of the class.

类加载器, 会先check该class对象是否已经被加载, 如果没有加载, 首先找到对应的.class文件, 然后check这个class文件是否被破坏或含有不良代码, 一旦class对象被载入, 就可以用来创建普通对象

Class对象的生成方式

1. 使用Class的静态成员forName

Class.forName("类名字符串") (注意: 类名字符串必须是全称, 包名+类名), 如果找不到该类会抛ClassNotFoundException异常

2. Class literals, 更加安全和高效的方法, 类名.class

Class literals work with regular classes as well as interfaces, arrays, and primitive types.

可用于接口, 数组和基本类型

需要注意的是, 使用Class literals来创建class对象时, 会有惰性, 对象初始化会被延迟到真正使用, 即引用静态成员时发生

对于基本类型, 还可以使用包装器类的Type

3.实例对象.getClass()

public class ClassTest {
public static void main(String [] args)throws Exception{
String str1="abc";
Class cls1=str1.getClass();
Class cls2=String.class;
Class cls3=Class.forName("java.lang.String");
System.out.println(cls1==cls2); //True
System.out.println(cls1==cls3); //True
}
}

RTTI的形式

总结一下传统的RTTI的形式, 如下3种

1. 向上转型或向下转型(upcasting and downcasting)

向上转型(子类cast到父类)是绝对安全的, 所以不需要check, 可以通过赋值操作完成
但是向下转型(父类cast到子类)却是有风险的, 编译器需要check向下转型是否合理, 这就需要使用RTTI来check实际类型

2. Class对象

传统的RTTI和反射都依赖于Class对象, 什么时候是传统RTTI, 什么时候是反射?

Class<?> c = Class.forName(args[0]); //这种情况就是反射, 只有在运行时产能得到args[0]
Method[] methods = c.getMethods();
Constructor[] ctors = c.getConstructors();

3. instanceof或isInstance()

从下面看出两种的不同用法,

//x是否是Dog类的instance
x instanceof Dog // obj instanceof classname
Dog.class.isInstance(x) //动态的instanceof, classobj.isInstance(obj)

Reflection, 反射

反射, 即在Java运行时环境中动态获取类的信息, 以及动态调用对象的方法的功能, 让Java跨入半动态语言的行列, 毕竟Java不允许动态的更改.

Java 反射机制主要提供了以下功能:

- 在运行时判断任意一个对象所属的类

- 在运行时构造任意一个类的对象

- 在运行时判断任意一个类所具有的成员变量和方法

- 在运行时调用任意一个对象的方法

- 生成动态代理

在JDK中, 主要由以下类来实现Java 反射机制, 这些类都位于java.lang.reflect包中:

- Java.lang.Class类: 代表一个类

- Field类: 代表类的成员变量(成员变量也称为类的属性)

- Method类: 代表类的方法

- Constructor类: 代表类的构造方法

- Array类: 提供了动态创建数组 以及访问数组元素的静态方法

使用的例子, 参考java 反射(Reflect)

动态代理

普通的代理, 静态代理, 很简单, 问题就是必须手工的写代理
那么如果真实的对象中有100个方法, 那么在代理类中就需要写100个代理接口, 是不是很麻烦

动态代理, 就是可以自动生成代理类, 其实代理类是很简单的, 实现代理类的关键就是知道真正的对象中有哪些接口, Reflection出场...

Reflection包中封装实现了动态代理, 可以直接使用

下面给出两种创建动态代理的方法

一种, 先生成代理类, 再创建代理对象

另一种, 直接生成代理对象

/**** 方式一****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);
//创建动态代理类
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
//创建动态代理类的实例
Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler }); /**** 方式二****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);
//直接创建动态代理类的实例
Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[] { Foo.class }, handler);

Java RTTI and Reflection的更多相关文章

  1. JAVA RTTI

    基础类可接收我们发给派生类的任何消息,因为两者拥有完全一致的接口.我们要做的全部事情就是从派生上溯造型,而且永远不需要回过头来检查对象的准确类型是什么.所有细节都已通过多态性获得了完美的控制. 但经过 ...

  2. Java进阶之reflection(反射机制)——反射概念与基础

    反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...

  3. Java - 反射机制(Reflection)

    Java - 反射机制(Reflection)     > Reflection 是被视为 动态语言的关键,反射机制允许程序在执行期借助于 Reflection API 取得任何类的       ...

  4. 浅析Java RTTI 和 反射的概念

    一.概念: RTTI(Run-Time Type Identification,运行时类型识别)的含义就是在运行时识别一个对象的类型,其对应的类是Class对象,怎么理解这个Class对象呢?如果说类 ...

  5. java 反射(Reflection)

    看了很多关于java 反射的文章,自己把所看到的总结一下.对自己,对他人或多或少有帮助吧. Java Reflection是什么? 首先来看看官方文档Oracle里面对Reflection的描述: R ...

  6. Java系列笔记(2) - Java RTTI和反射机制

    目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这 ...

  7. Java RTTI机制与反射机制

    1.1 什么是RTTI? 维基百科的定义:In computer programming, RTTI (Run-Time Type Information, or Run-Time Type Iden ...

  8. Java RTTI和反射

    一.Java的RTTI  RTTI(Run-Time Type Identification,通过运行时类型识别)的含义就是在运行时识别一个对象的类型,其对应的类是Class对象,每个java里面的类 ...

  9. java RTTI笔记 之Class学习笔记(摘自java编程思想)

    1.java 使用Class对象来执行其RTTI.java 中每个类在编译后都会对应产生一个Class对象(更恰当地说是被保存在一个同名的.class文件中),甚至void和基本类型也都对应一个cla ...

随机推荐

  1. Wpf ScrollBar自定义样式

    Wpf的ScrollBar可以分为六个区域:A.背景.B.向上按钮.C.向下的按钮.D.Track里面向上的按钮.E.Track里面向下的按钮.F.Track的Thumb 详情见下图 下面通过一个例子 ...

  2. vivado设计四:自定义IP核测试

    在vivado设计三中:http://blog.chinaaet.com/detail/37177已经建立了vivado工程和封装好了自定义IP核. 那么接下来,我们对这个自定义IP核进行测试了:我们 ...

  3. python学习之urllib.parse.unquote()

    urllib.parse.unquote(string,encoding ='utf-8',errors ='replace') 用同一个字符换成%xx转义.相当于JS中的urldecode(),对u ...

  4. CCRenderTexture画点出现十字架"歪解"

    在泰然论坛发个了帖子,没有人解答,内容如下: 遇到奇葩问题了,cocos2dx 2.2 CCRenderTexture* tex=CCRenderTexture::create(, ); tex-&g ...

  5. 质问微软 WP8.1开发HTTPS 真费劲

    本人用C#多年,WPF2年,一直想做点应用为WP生态贡献一点力量,最近终于有机会接触了 家里的本子是2年前的低压I3,不支持虚拟化,一直没有真机.最近同事妈妈换下来一个820给我拿来做开发用,非常感谢 ...

  6. [转]Spark能否取代Hadoop?

    大数据的浪潮风靡全球的时候,Spark火了.在国外 Yahoo!.Twitter.Intel.Amazon.Cloudera 等公司率先应用并推广 Spark 技术,在国内阿里巴巴.百度.淘宝.腾讯. ...

  7. 什么是ORM,以及在php上的使用?

    ORM:object relation mapping,即对象关系映射,简单的说就是对象模型和关系模型的一种映射.为什么要有这么一个映射?很简单,因为现在的开发语言基本都是oop的,但是传统的数据库却 ...

  8. .NET学习笔记(1)

    把 DataSet 绑定到 Repeater 控件 Repeater 控件用于显示重复的项目列表,这些项目被限制在该控件.Repeater 控件可被绑定到数据库表.XML 文件或者其他项目列表. 获取 ...

  9. mysql中RAND()随便查询记录效率问题和解决的方法分享

    在我们做开发的中效率一直是个问题,特别是对于非常多大数据量操作,今天我们碰到一个要随机查询数据,一開始我们可能想到最简单的order by rand() 来操作但效率不敢恭维啊 近期因为须要大概研究了 ...

  10. 卡友pos机使用流程

    Q: pos机正常使用步骤 A: 1. 按开机键开机2. 输入“01”进行签到3. 系统提示输入密码,密码为“0000”4. 系统提示“请刷卡”,可正常刷卡消费首次使用请务必登陆商户后台核对结算收款账 ...