Java中RTTI(Java编程思想第14章--类型信息)整理

为什么需要RTTI(Run-Time Type Information/Identification):
        Java中所有类型转换都是在运行时进行正确性检测的(即:在运行时识别一个对象的类型,检验类型转换是否合法)。以下是RTTI的一种使用形式:
例子1:很多时候需要进行向上转型,比如TV类派生出LeTV、MiTV和SanTV类,但是现有的方法只需要将TV引用作为参数,实际传入的则是其派生类的引用。那么RTTI就在此时起到了作用,比如通过RTTI能识别出LeTV、MiTV和SanTV类是TV的派生类,这样就能够向上转型为TV(类似的,在用接口作为参数时,向上转型更为常用)。RTTI此时能够判断是否可以进行向上转型。每个导出类都会覆盖tvshow,那么在调用tvshow方法时表现出不同的行为,则是多态机制。

public class EveryTV {
    public static void tvshow(TV tv){
        tv.show();
    }

    public static void main(String[] args) {
        tvshow(new LeTV());
        tvshow(new MiTV());
        tvshow(new SanTV());
    }
}

例子2 : 在本例中将Shape的导出类对象放入List<Shape>数组中时会发生向上转型,但在转换为Shape类型时也丢失了Shape对象所具有不的属性,从List中取出元素时会自动转回Shape类型对象。(由于:容器<Class(泛型)>–将所有传入他的对象都当做Object持有–从容器中取出时会自动转型为Class(泛型)类型)。
        在编译期,由容器和Java的泛型系统来强制确保上述机制。在运行期,由RTTI来确保这一机制。
        我们平时所知道的List<Shape>保存的都是Shape对象引用,这底层的机制如上所述。

public class Shapes {
  public static void main(String[] args) {
    List<Shape> shapeList = Arrays.asList(
      new Circle(), new Square(), new Triangle()
    );
    for(Shape shape : shapeList)
      shape.draw();
  }
}

RTTI的三中类型:
1、传统的类型转换:如‘’(Shape)‘’,由RTTI来确保类型转换的正确性。如果执行了错误的类型转换,在运行时会抛出ClassCastException异常。如上面的例1和例2,如果转型不合法则抛出该异常。
2、代表对象的类型的Class对象,通过查询Class对象可以获取运行时所需的信息。获取Class对象的方法有3种:

  • Class.forName(),加载时会进行初始化;
  • 拥有了该class的对象(或者直接在该类中),通过调用getClass方法,如:object.getClass()或者直接在该类中使用getClass();
  • 类字面常量,如:FancyToy.class。不会自动初始化该Class对象。初始化被延迟到了对静态方法或者非常数静态域进行首次引用时才执行。

首先解释什么是Class对象?
        class是关键字,定义一个类的,class指一个类;对象则是一个类的实例;Class是类的一种。为什么要Class呢?Class类有很多对所有class进行公共操作的方法,还可以干一些厉害的工作——如反射。
        在Java中,每个class都有一个相应的Class对象,用来表示运行时的类型信息(包含了类的相关信息)。当我们编写并编译完成后就会产生一个Class对象(并且存放在生成的同名.class文件中),用于表示这个类的类型信息。一旦class的Class对象被载入内存,该Class对象就被用来创建该class的所有对象。
        所有的类都是在其第一次使用时,被JVM动态的加载到内存中的。
a、JVM将启用“类加载器”的子系统;
b、类加载器首先检测该class的Class对象是否被加载到了内存中;
c、如果尚未加载,默认加载器就会根据类名查找.class文件;

例子3:Class.forName()(在使用Class关键字时可以引入泛型语法,提供编译期检查,以便在编译期就能发现类型错误。如:Class<Name>)

import static net.mindview.util.Print.*;

class Candy {
  static { print("Loading Candy"); }
}

class Gum {
  static { print("Loading Gum"); }
}

class Cookie {
  static { print("Loading Cookie"); }
}

public class SweetShop {
  public static void main(String[] args) {  
    print("inside main");
    new Candy();
    print("After creating Candy");
    try {
      Class.forName("Gum");
    } catch(ClassNotFoundException e) {
      print("Couldn't find Gum");
    }
    print("After Class.forName(\"Gum\")");
    new Cookie();
    print("After creating Cookie");
  }
}

例子4:类字面常量.class

import java.util.*;

class Initable {
  static final int staticFinal = 47;
  static final int staticFinal2 =
    ClassInitialization.rand.nextInt(1000);
  static {
    System.out.println("Initializing Initable");
  }
}

class Initable2 {
  static int staticNonFinal = 147;
  static {
    System.out.println("Initializing Initable2");
  }
}

class Initable3 {
  static int staticNonFinal = 74;
  static {
    System.out.println("Initializing Initable3");
  }
}

public class ClassInitialization {
  public static Random rand = new Random(47);
  public static void main(String[] args) throws Exception {
    Class initable = Initable.class;
    System.out.println("After creating Initable ref");
    // Does not trigger initialization:
    System.out.println(Initable.staticFinal);
    // Does trigger initialization:
    System.out.println(Initable.staticFinal2);
    // Does trigger initialization:
    System.out.println(Initable2.staticNonFinal);
    Class initable3 = Class.forName("Initable3");
    System.out.println("After creating Initable3 ref");
    System.out.println(Initable3.staticNonFinal);
  }

3、关键字instanceof(或者isInstance),它返回一个boolean值,告诉我们对象是不是某个特定类型的实例。在不知道该对象属于什么类型时,进行向下转型前使用instanceof是非常重要的,以免得到ClassCastException。例子可参见Java编程思想14章。
反射机制:
        

参考资料:http://m.blog.csdn.net/iaiti/article/details/39180927
http://www.mamicode.com/info-detail-1232623.html
http://m.blog.csdn.net/qq_34743046/article/details/71438728
https://www.cnblogs.com/aaron-shu/p/7429488.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值