《Java编程思想》之类型检查(RTTI与反射机制)

1、类型时类型识别(run-timetype identification,RTTI):当之有一个指向对象的引用时,RTTI可以让你找出这个对象的确切类型。

2、Java运行时识别对象和类的信息,主要有俩种方式:

1).一种是“传统“RTTI,它假定我们在运行时已经知道了所有的类型。

2).另一种是“放射“机制,它允许我们在运行时获得类的信息。

3、Class对象:每个类都有一个Class对象,保存在一个同名的.class文件中,它包含了与类相关的信息。

4、在运行时,当我们想生成这个类的对象时,运行这个程序的Java虚拟机(JVM)首先检查这个类的Class对象是否已经加载,就会根据类名查找.class文件,并将其载入。所以Java并非一开始执行就完全加载的,这一点与许多传统语言都不同。        

5、Class.forName(“类名”)是获得Class引用的一种方法,该方法返回一个Class对象的引用。例如:Class.forName(“MyClass”);

在调用该方法时,若MyClass类被还没加载,则加载MyClass类。

6、类字面常量:另一种获得Class引用的方法,MyClass.class(类名.class)。

此方法,更安全,更高效。

7、类字面常量不仅应用于普通的类,也可以应用于接口、数组以及基本数据类型。

8、RTTI的形式包括:

1).传统的类型转化。如Base类是Subclass类基类。

Base base = new Subclass();
Subclass sub= (Subclass)base;//(Subclass),由RTTI确定类型转化正确性。在C++中,经典的类型转换“(Subclass)”并不使用RTTI。

2).代表对象的类型的Class对象。同过查询Class对象可以获取运行时所需的信息。

3).RTTI的第三种形式,使用关键字“instanceof”。如:

boolean yesOrNot = (base instanceof Subclass);

若base是Subclass类的实例,yesOrNot就为true

9、instanceof与Class的等价性:

class Base{}
class Subclass extends Base{};
public class Test{
   static void test(Object x){
      System.out.println("Testing x of type: " + x.getClass());
      System.out.println("x instanceof Base: " + (x instanceof Base));
      System.out.println("x instanceof Subclass: " + (x instanceof Subclass));
      System.out.println("Base.isInstance(x): " + (Base.class.isInstance(x)));
      System.out.println("Subclass.isInstance(x):" + (Subclass.class.isInstance(x)));
      System.out.println("x.getClass() == Base.class: " + (x.getClass() == Base.class));
      System.out.println("x.getClass() == Subclass.class: " + (x.getClass() == Subclass.class));
      System.out.println("x.getClass().equals(Base.class): " + (x.getClass().equals(Base.class)));
      System.out.println("x.getClass().equals(Subclass.class): " + (x.getClass().equals(Subclass.class)));
   }
   public static void main(String[] args){
      test(new Base());
   System.out.println("---------------------------------------------------");
      test(new Subclass());
   }
}

运行结果:


1).instanceof 与 isInstance生成的结果完全一样,equal与==也一样。

2). Instanceof与isInstance保持了类型的概念,它指得是“你是这个类,或者是这个类的派生类吗?”

3).equal与==比较实际的Class对象,没有考虑继承。

10、Java是通过Class对象来实现RTTI机制的,即使我们只是做些诸如类型转换这类的事情。Class类提供的一些方法:


11、RTTI的限制:编译器必须已经知道所有用RTTI来处理的类型。但是,当你从网络连接中获得一串字节,并被告知这些字节代表一个类。可是编译器并不知道这个类的信息。这时你要使用这个类,那么就得使用反射机制

12、RTTI与反射之间的区别:对RTTI来书,编译器在编译时打开和检查.class文件,而对于反射机制,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件的。

13、获取关于类和对象的反射信息在java.lang.reflect库中,它包含了Field、Method以及Constructor类。

1).Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

2). Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

3). Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。 

Base类如下:

class Base{
	private int number = 1;
	public int otherNum = 100;
	public Base(){
		
	}
	public Base(int number){
		this.number = number;
	}
	public void func(){
		number++;
	}
	public void otherFunc(){
		otherNum--;
	}
}
Test:

public class Test{
	public static void main(String[] args){
		Constructor[] constructors = null;
		Method[] methods = null;
		Field[] fields = null;
		try {
			Class c = Class.forName("Base");
			constructors = c.getConstructors();//公有构造方法。
			methods = c.getMethods();//公有方法。
			fields = c.getFields();//公有字段。
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		System.out.println("Base含有的公有构造方法:");
		for(int i = 0; i < constructors.length; i++){
			System.out.println(constructors[i].getName());
		}
		System.out.println("Base含有的公有方法(有些是从Oject继承的):");
		for(int i = 0; i < methods.length; i++){
			System.out.println(methods[i].getName());	
		}
		System.out.println("Base含有的公有字段:");
		for(int i = 0; i < fields.length; i++){
			System.out.println(fields[i].getName());		
		}
	}
}
运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值