美文网首页
类型信息

类型信息

作者: zlb | 来源:发表于2016-03-17 23:13 被阅读14次

    运行时的类型信息使得你可以在程序运行时发现和使用类型信息

    • 为什么需要RTTI(Runtime Type Information)
    public abstract class School {
        String name;
        public String getName(String name){
            this.name = name;
            System.out.println(this.getClass().getName()+name);
            return this.name;
    }
        public abstract String toString();
    }
    public class Primary extends School{
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "Primary";
        }
    }
    public class University extends School{
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "University";
        }
    }
    import java.util.Arrays;
    import java.util.List;
    public class test {
        public static void main(String[] args) {
            List<School> school = Arrays.asList(new Primary(),new High(),new University());
            for(School str : school){
                str.getName("hello");
            }
        }
    }
    

    面向对象编程的基本目的是:让代码只操纵对基类引用。在这个例子的School接口中动态的绑定了draw()方法,目的就是让程序员使用泛化的School引用来调用getName()方法
    因此:它解放了程序在编期间执行的面向类型的操作,不管是程序的安全性还是可扩展性和可维护性,都得到了大大的加强。

    • Class对象
      Class对象是RTTI在Java中工作机制的核心。Java程序是由一个一个的类组成的。而对于每一个类,都有一个class对象与之对应,所有的类都是在对其第一次使用时,动态的加载到JVM中去的。当程序创建第一个对类的静态成员时用时,就会加载这个类,这个也证明构造器也是类的静态方法
      类加载器首先检查这个类的Class对象是否已经加载,如果未加载。默认的类加载器就会根据累吗查找.class文件,一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象
     interface HasBatteries{}
    interface WaterProof{}
    interface Shoots{}
    class Toy{
        Toy(int i){
        }
    }
    class FancyToy extends Toy implements HasBatteries,WaterProof,Shoots{
        //FancyToy(){}
        FancyToy(int i){super(i);}
    }
    public class ToyTest {
        static void printInfo(Class c){
            System.out.println("class name is \t"+c.getName()+"\tis intercace?"+c.isInterface());
            System.out.println("getSimpleName:\t"+c.getSimpleName());//产生类名
            System.out.println("getCanonicalName\t"+c.getCanonicalName());//产生全限定的类名  包括包名
        }
        public static void main(String[] args) throws ClassNotFoundException {
            // TODO Auto-generated method stub
            Class cc= null;
            try{
                cc = Class.forName("FancyToy");
            }catch(ClassNotFoundException ex){
                throw new ClassNotFoundException("这个类未发现");
            }
            System.out.println(cc);
            for(Class c : cc.getInterfaces()){
                System.out.println(c);
            }
            Class up = cc.getSuperclass();//得到基类
            Object obj = null;
            try {
                obj =  up.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            printInfo(obj.getClass());
        }
    }
    

    <b>注意如果把默认的构造器注释掉,则会出现java.lang.InstantiationException 错误,因为需要这个默认的构造器创建对象</b>
    例子中有三种获得Class对象的方法:
    Class.forName();最简单的,也是最快捷的方式,因为我们并不需要为了获得class对象而持有该类的对象实例。
    obj.getClass;当我们已经拥有了一个感兴趣的类型的对象时,这个方法很好用
    obj.class;类字面常量,这种方式很安全,因为它在编译时就会得到检查(因此不需要放到try语句块中),而且高效。

    • 类型转换前先做类型的检查
     class A{  
    }  
    class B extends A {  
    }  
    class C extends B {  
    }  
    public class IsInstance {  
        public static void main(String[] args) {  
            // TODO Auto-generated method stub  
            C c = new C();  
            B b = new B();  
            A a = new A();  
            B bc = new C();  
            A ac = new C();  
            System.out.println(c instanceof C);  
            System.out.println(c instanceof B);  
            System.out.println(c instanceof A);  
            System.out.println();  
            System.out.println(c.getClass().isInstance(c));  
            System.out.println(c.getClass().isInstance(b));  
            System.out.println(c.getClass().isInstance(a));  
            System.out.println();  
            System.out.println(c.getClass().isInstance(bc));  
            System.out.println(c.getClass().isInstance(ac));  
            System.out.println();  
            System.out.println(A.class.isInstance(a));  
            System.out.println(A.class.isInstance(b));  
            System.out.println(A.class.isInstance(c));  
            System.out.println(A.class.isInstance(ac));  
            System.out.println(A.class.isInstance(bc));  
            System.out.println();  
            System.out.println(B.class.isInstance(a));  
            System.out.println(B.class.isInstance(b));  
            System.out.println(B.class.isInstance(c));  
            System.out.println(B.class.isInstance(ac));  
            System.out.println(B.class.isInstance(bc));  
        }  
    }  
    

    需要判断一个对象是否his一个类的实力上时,可以用.isInstance()和instanceof 方法
    instanceof运算符 只被用于对象引用变量
    Class类的isInstance(Object obj)方法,obj是被测试的对象,如果obj是调用这个方法的class或接口 的实例,则返回true。这个方法是instanceof运算符的动态等价。

    • 泛化的Class引用
      Class引用总是指向某个Class对象,可以制造类的实例,并包含课可作用于这些实例的所有方法的代码,还包含该类的静态成员,因此,Class引用表示的就是他所指的对象的确切的类型,而该对象便是Class的一个对象
    public class Generic_1 {
        public static void main(String[] args) {
            Class initClass = int.class;
            Class<Integer> generClass = int.class;
            generClass = Integer.class;
            initClass = double.class;
        }
    }
    

    如果希望稍微放松一些这种限制,应该怎么办呢?我们使用了通配符? 它是java泛型的一部分

     import java.util.ArrayList;
    import java.util.List;
    class CounterInteger{
        private static long couter;
        private final long id = couter++;
        public String toString(){
            return Long.toString(id);
        }       
    }
    public class FilledList<T> {
        private Class<T> type;
        public FilledList(Class<T> type){
            this.type = type;
        }
        public List<T> create(int ele){
            List<T> result = new ArrayList<T>();
            try{
                System.out.print(type.newInstance() instanceof CounterInteger);
                for(int i=0;i<ele;i++){
                    result.add(type.newInstance());
                }
            }catch(Exception ex){
                throw new RuntimeException();
            }
            return result;
        }
        public static void main(String[] args) {
             FilledList<CounterInteger> list = new FilledList<CounterInteger>(CounterInteger.class);
             System.out.println(list.create(10));
        }
    }
    
    • 反射,运行时的类信息

    相关文章

      网友评论

          本文标题:类型信息

          本文链接:https://www.haomeiwen.com/subject/mnmclttx.html