java 类型信息

为什么需要RTTI

package rtti;
import java.util.Arrays;
import java.util.List;
abstract class Shape {
    void draw() {
        System.out.println(this + ".draw()");
 }
    abstract public String toString();
}
class Circle extends Shape {
    @Override
    public String toString() {
        return "Circle";
    }
    void sayHello() {
        System.out.println("hello");
    }
}
class Square extends Shape {
    @Override
    public String toString() {
        return "Square";
    }
}
public   class Shapes {
    public static void main(String[] args) {
        List shapeList = Arrays.asList(new Circle(), new Square());
        //容器的所有事物都当作object持有,当取出时会自动转型为Shape
        for (Shape shape :
                shapeList) {
            shape.draw();
        }
    }
}
  • RTTI名称的含义:在运行时,识别一个对象的类型
  • 面向对象编程中基本的目的是,让代码只操纵对基类的引用,多态
  • 有时需要操作特定类的独有方法,而这是无法从基类获取的,这就是使用RTTI的意义

Class对象

  • 类型信息在运行时由Class对象表示,每个类都有一个Class对象,包含与类相关的信息
  • 每当编译一个新类,就会由jvm中的类加载器子系统生成一个同名的Class对象(.class)
  • 类加载器子系统是一条类加载器链,原生的类加载器加载可信类,包括java api类,也可以额外增加类加载器
  • 所有类都是在第一次使用的时候(创建第一个对类的静态成员的引用时),动态加载到jvm中。这说明,构造器也是静态的。
  • 一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象
  • 想在运行时使用类型信息,就必须先获得对Class对象的引用
package rtti;
interface HasBatteries{};
interface Waterproot{};
interface Shoots{};
class Toy{
    public Toy() { }
    public Toy(int i) { }
}
class FancyToy extends Toy implements HasBatteries,Waterproot,Shoots {
    FancyToy(){ super(1);}
}
public class ToyTest {
    static void printInfo(Class cc) {
        System.out.println("Class name:"+cc.getName()+"n" //获取全限定类名
        +"isInterface:"+cc.isInterface()+"n" 
        + "Simple name:"+cc.getSimpleName()+"n" //获取不含包名的类名
        + "Canonocal name:"+cc.getCanonicalName()+"n"////获取全限定类名
        );
    }
    public static void main(String[] args) {
        Class c = null;
        try {
            c = Class.forName("rtti.FancyToy");
        } catch (ClassNotFoundException e) {
            System.out.println("can't find FancyToy");
            System.exit(1);
    }
        System.out.println(c);
        for (Class face :
                c.getInterfaces()) {//获取接口数组
            printInfo(face);
        }
        Class up = c.getSuperclass();//获取父类Class对象的引用
        Object obj = null;
        try {
            obj = up.newInstance();//通过class对象,创建类的实例
        } catch (InstantiationException e) {
            System.out.println("can not instantiate");
            System.exit(1);
        } catch (IllegalAccessException e) {
            System.out.println("can not access");
            System.exit(1);
        }
        printInfo(obj.getClass());
    }
}
  • Class.forName()是获取Class对象引用的一种方法,必须传入全限定类名
  • 它有一个副作用,如果类没有加载就加载它
  • 另一种方式是getClass()方法,这个方法属于根object的一部分
  • newInstance()是实现虚拟构造器的一种途径,虚拟构造器允许声明“我不知道你的确切类型,但无论如何要正确的创建自己”
  • 使用newInstance()来创建的类必须要带有默认构造器

类字面常量

你可能感兴趣的