java基础——类型信息

上一篇 / 下一篇  2015-01-23 08:29:40 / 个人分类:原创

java在运行时识别对象和类的信息,主要有两种方式:
1、传统的RTTI:假定我们再编译时已经知道了所有的类型;
2、反射机制:在运行时发现和使用类的信息。

14.2Class对象
类是程序的一部分,每个类都有一个Class对象每当编写并且编译一个新类就会产生一个Class对象(被保存在一个同名的.class文件中)
类加载器子系统包含一条类加载器链,只有一个原生类加载器,他是JVM实现的一部分。原生类加载器加载的是可信类,包括Java API类。如果有特殊需要(如:支持WEb服务器应用,或者在网络中下载类)可添加额外的类加载器。

Class.forName("<类名>")方法:取得Class对象的引用。参数为目标类的文本名(String类型),若存在包名,也应包含在参数内(格式为:包名.类名)
例如:Class.forName("Toy");或Class.forName("typeInfo.toys.Fancy")

Class.newInstance()方法:创建指定Class对象(必须带有默认构造器才可以通过该方法创建对象)

类字面常量:
除Class.forName("类名")方法外,还可以使用类名.class来生成对Class对象的引用。并且这种方法是在编译时就受到检查的,不需要置于try块中,也更加高效。使用.class语法来获得对类的引用,有效地实现了尽可能的“惰性”,如:读取static final的编译期常量,则不需要对类进行初始化就可以读取;但如果是static final的非编译期常量,则会强制进行类的初始化。如果要读取一个static域不是final的,那么需要先进行链接(为这个域分配存储空间)和初始化(初始化该存储空间)。

类字面常量不仅可以应用于普通的类,也可以应用于接口、数组及基本数据类型。基本数据类型的包装器类,有一个标准字段TYPE。TYPE字段是一个引用,指向对应的基本数据类型的Class对象。(char.class-----Character.TYPE)


14.2.2泛化的Class引用
1、Class<Integer> intClass = int.class(Integer.class不可以是其他类型如:double.class);
2、Class<?> intClass = int.class(可是是任意类型);
3、Class<? extends Number> bounded = int.class;
bounded = double.class;
bounded = Number.class;
(创建一个Class引用,它被限定为某种类型或该类型的任意子类)
4、Class<Number> numberClass = int.class;这种写法是不合法的,虽然Integer继承自Number,但是Integer Class并不是Number Class的子类。

向Class引入添加泛型语法的原因是为了提供编译期类型检查,因此如果操作有误,立即就会发现这一点。在使用普通Class引用,需到运行时才会发现。

14.2.3新的转型语法
1、子类对象 = (子类)父类对象;(向下转型)
如:House h = (House)b;---------------(House extends b.class)
2、House h = houseType.cast(b);(houseType = House.class)
cast()方法接受参数对象,并将其转型为Class引用的类型。
该方法作用:若存储了Class引用,并希望以后通过这个引用来执行转型。

instanceof与isInstance的区别
instanceof语法:  对象 instanceof 类
自身实例或子类实例 instanceof 自身类,返回true
isInstance语法: 类.class.isInstance(对象)
自身类.class.isInstance(自身实例或子类实例),则返回true

Class.isInstance()方法是一种动态检测对象的方法(参考14.3.2例子)

14.4注册工厂

14.7动态**
**:为了提供额外的或不同的操作,而插入的用它来代替“实际”对象的对象。
**对象的作用——封装修改

Java动态**:可以动态的创建**并动态的处理对所**方法的调用。在动态**上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。

---------------------------------------
InvocationHandler(Interface)及Proxy(class)
每一个动态**类必须实现InvocationHandler接口,并且每个**类的实例都关联了一个handler(调用处理程序)。当**实例上的一个方法被调用时,这个方法的调用就会被转发为InvocationHandler接口的invoke方法来进行调用。

Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy:我们所**的真实对象
method:我们要调用真是对象的某个方法的Method对象
args:嗲用真实对象某个方法时接收到参数

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:ClassLoader对象,定义了由哪个ClassLoader对象来对生成的**对象进行加载。
interfaces:一个interface数组,表示将要给需要**的对象提供一组什么接口( **对象就宣称实现了这些借口,就可以调用这组接口中的方法了)
h:一个InvocationHandler对象,表示当这个动态**对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。
---------------------------------------

静态方法Proxy.newProxyInstance()可以创建动态**,这个方法需要得到一个类加载器(可以从已经被夹在的对象中获取其类加载器,然后传递给它),一个虚妄该**实现的接口列表,以及InvocationHandler接口的一个实现。动态**可以将所有调用重定向到调用处理器,因此通常会想调用处理器的构造器传递一个“实际”对象的引用,从而使得调用处理器在执行其中介任务时可以将请求转发。

——————14.8空对象——未进行





TAG:

 

评分:0

我来说两句

日历

« 2024-04-08  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 18213
  • 日志数: 25
  • 建立时间: 2014-11-10
  • 更新时间: 2015-03-12

RSS订阅

Open Toolbar