`
yuanlanjun
  • 浏览: 1177040 次
文章分类
社区版块
存档分类
最新评论

java 运行时类型识别(RTTI) - 1 - Class与instanceof

 
阅读更多

java 运行时类型识别(RTTI) - 1 - Class与instanceof

java 运行时类型识别(RTTI) - 2 - 反射


三种方式:

1.传统类型转换

2.查询Class对象

3.instanceof


1.传统类型转换

String string = (String) s;

2.查询Class对象

首先需要了解一下java.lang.Class这个类


类型信息在运行时的表示是有Class这个类的实例完成的

java使用Class对象来执行其RTTI,即使是类似转型的这样的操作

每个类都有一个Class对象(被保存在一个同名的.class文件中),为了生成这个类的对象,运行这个程序的JVM将使用被称为"类加载器"的子系统

(有关类加载器的内容,稍后介绍)


一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象

static{
    //...
}

这些代码在类第一次加载时执行


下面看看think in java中的示例代码

public class Candy {
    static {
        System.out.println("Loading Candy");
    }
}
public class Gum {
    static {
        System.out.println("Loading Gum");
    }
}


public class SweetShop {

	public static void main(String[] args) {
		System.out.println("inside main");
		new Candy();
		System.out.println("After creating Candy");
		try {
			Class.forName("Gum");
		} catch(ClassNotFoundException e) {
			e.printStackTrace();
		}
		System.out.println("After Class.forName(\"Gum\")");
	}
}

运行结果

inside main

Loading Candy

After creating Candy

Loading Gum

After Class.forName("Gum")



Class仅在需要时加载,不然Loading Candy和Loading Gum应该在前面就输出了

这里要注意下Class.forName("Gum");

从log中看出,这句话也使得类Gum被加载了


生成Class引用可以用下面两种方式

1.newInstance()

newInstance使用的时候需要注意:

a.类需要有默认的构造器才可以,不然则会出现java.lang.InstantiationException

b.默认构造器必须能访问才行,不然会出现java.lang.IllegalAccessException

2.类字面常量

使用类字面量常量更简单,更安全:因为它在编译时被检查,所以也不需要try catch

并且使用类字面量不会初始化该Class

类字面量可以用于类、接口、数组、基本类型

对于基本数据类型的包装器类,有一个标准字段TYPE.TYPE是一个引用,指向对应的基本数据类型的Class

...等价于...
boolean.class Boolean.TYPE
char.class Character.TYPE
byte.class Byte.TYPE
short.class Short.TYPE
int.class Integer.TYPE
long.class Long.TYPE
float.class Float.TYPE
double.class Double.TYPE
void.class Void.TYPE

3.instanceof

我们可以使用关键字instanceof来做类型检查(x instanceof Gum),它返回一个boolean

我们也可以使用动态的boolean java.lang.Class.isInstance(Object obj)来做类型检查


instanceof与Class的等价性

public class Test {
	static class Base{}
	static class Derived extends Base{}
	
	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 Derived " + (x instanceof Derived));
		System.out.println("Base.isInstance(x) " + (Base.class.isInstance(x)));
		System.out.println("Derived.isInstance(x) " + (Derived.class.isInstance(x)));
		System.out.println("x.getClass() == Base.class " + (x.getClass() == Base.class));
		System.out.println("x.getClass() == Derived.class " + (x.getClass() == Derived.class));
		System.out.println("x.getClass().equals(Base.class) " + (x.getClass().equals(Base.class)));
		System.out.println("x.getClass().equals(Derived.class) " + (x.getClass().equals(Derived.class)));
	}
	
	public static void main(String[] args) {
		Test.test(new Base());
		System.err.println("----------------------------");
		Test.test(new Derived());
	}
}

结果

Testing x of type class Test$Base

x instanceof Base true

x instanceof Derived false

Base.isInstance(x) true

Derived.isInstance(x) false

x.getClass() == Base.class true

x.getClass() == Derived.class false

x.getClass().equals(Base.class) true

x.getClass().equals(Derived.class) false

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

Testing x of type class Test$Derived

x instanceof Base true

x instanceof Derived true

Base.isInstance(x) true

Derived.isInstance(x) true

x.getClass() == Base.class false

x.getClass() == Derived.class true

x.getClass().equals(Base.class) false

x.getClass().equals(Derived.class) true


可以看出:instanceof与isInstance()结果一样,equals和==的结果一样

instanceof是类型检查,==是对象比较,不考虑继承等关系.

个人觉得比较好理解



类加载器

这里只贴出笔记,之后在总结虚拟机的时候再详细说明,会在这里给出链接

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics