运行时类型信息是Java的一大特点,他可以在程序运行时发现和使用类型信息。
1.为什么需要RTTI(Run-time type information)
多态的体现,运行时后期绑定对象的引用,面向接口编程或面向基类编程。
处理文理:假设在运行之前,我就已经知道了具体对象引用的类型,然后要找出其他的类型?
2.Class对象
java.lang.class是final类。
RTTI在Java中的工作原理,必须知道类型信息在运行时如何表示的,这项工作是由成为Class对象的特殊对象完成的,它包含了与类有关的信息。Java使用Class对象来执行其RTTI,即使你正在执行的类式转型这样的操作。
每编写并且编译了一个信了,就会产生一个class对象(更恰当的是被保存在一个同名的.class文件中)。为了生成这个类的对象,运行这个程序的(Java虚拟机JVM)将使用被称为类加载器
动态加载:即在调用这个对象的时候生成 class对象,并保存在内存中(工作区间)。
一旦某个类的Class对象被载入内存,它就被用来创建这个类所有的对象
package com.myboy.classdemo;
class A {
static{//加载的时候直接调用
System.out.println("zhuluzuishuai");
}
static void f() {//静态方法,只有在调用的时候,才会执行。但是已经被加载成
//.class文件了
System.out.println("zhuluzhenshuai");
}
}
public class Test2 {
public static void main(String[] args) {
try {
Class.forName("com.myboy.classdemo.A");//直接去找.class文件,找不到就ClassNotFoundException
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
类字面常量(类.class加载,建议使用这种格式的)
泛化的Class引用
Class<Number> clazz=int.class //ok,多态,向上转型,后期绑定
3.类型转换前先做检查
1.在传统的类型转换:由RTTI进行类型绑定,错误的类型转化报ClassCastException
2.代表对象的类型的Class对象,通过查询Class对象可以得到具体的类型。
3.用instanceof关键字来区别
4.注册工厂(后面学习设计模式在研究)
5.反射:运行时的类信息(此处需加强研究,后续框架,设计模式均用到了这些东西)
如果不知道某个对象的确切类型,RTTI可以告诉你。但是有一个限制:这个类型在编译时必须以知,这样才能使用RTTI识别它,并利用信息进行下一步操作。这种操作是知道类型和信息的情况下,如果知道类的类型,但是具体的不知道信息的时候,进行反射操作。
反射的基本应用去看Java API。(java.lang.reflect.Method.invoke(Object obj, Object...obj))此处需多注意
package com.myboy.classdemo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test4 {
public void f() {
System.out.println("zhuluzuishuai");
}
public void g() {
System.out.println("zhuluzhenshuai");
}
public static void main(String[] args) {
Class clazz = Test4.class;
try {
// public Method getMethod(String name, Class<?>... parameterTypes)
/**
* class<?>...parameterTypes 变量,传进方法的参数,如:new class{String.class,int.class}
*/
Method m = clazz.getMethod("f");
try {
m.invoke(clazz.newInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
6.动态代理(重要,十分重要,后续设计模式重点研究)7.空对象
当你使用内置的null表示缺少对象时,在每次使用引用时都必须测试是否为null,这显得枯燥。如果创建了空对象来表表达空(此处是对象)
package com.myboy.classdemo;
class Test3 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = "NULL";
}
}
public class Test3NULL{
private static final Test3 t3=new Test3();//静态,全局唯一
}
8.在论接口信息和类型信息的解耦合
接口的解耦合>类型信息的解耦合。基类的类型信息永远存在限制