您的位置:首页 > 编程语言 > Java开发

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

2012-12-24 11:26 756 查看
三种方式:

1.传统类型转换

2.查询Class对象

3.instanceof

1.传统类型转换

String string = (String) s;

2.查询Class对象

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

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

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

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

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

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

[java]
view plaincopyprint?

static{  
    //...   
}  

static{
//...
}


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

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

[java]
view plaincopyprint?

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

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


[java]
view plaincopyprint?

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

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


 public class SweetShop {

[java]
view plaincopyprint?

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\")");  
}  

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.classBoolean.TYPE
char.classCharacter.TYPE
byte.classByte.TYPE
short.classShort.TYPE
int.classInteger.TYPE
long.classLong.TYPE
float.classFloat.TYPE
double.classDouble.TYPE
void.classVoid.TYPE
3.instanceof

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

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

instanceof与Class的等价性

[java]
view plaincopyprint?

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());  
    }  
}  

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是类型检查,==是对象比较,不考虑继承等关系.

个人觉得比较好理解



类加载器

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: