類型信息

運(yùn)行時的類型信息使得你可以在程序運(yùn)行時發(fā)現(xiàn)和使用類型信息

  • 為什么需要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");
        }
    }
}

面向?qū)ο缶幊痰幕灸康氖牵鹤尨a只操縱對基類引用。在這個例子的School接口中動態(tài)的綁定了draw()方法,目的就是讓程序員使用泛化的School引用來調(diào)用getName()方法
因此:它解放了程序在編期間執(zhí)行的面向類型的操作,不管是程序的安全性還是可擴(kuò)展性和可維護(hù)性,都得到了大大的加強(qiáng)。

  • Class對象
    Class對象是RTTI在Java中工作機(jī)制的核心。Java程序是由一個一個的類組成的。而對于每一個類,都有一個class對象與之對應(yīng),所有的類都是在對其第一次使用時,動態(tài)的加載到JVM中去的。當(dāng)程序創(chuàng)建第一個對類的靜態(tài)成員時用時,就會加載這個類,這個也證明構(gòu)造器也是類的靜態(tài)方法
    類加載器首先檢查這個類的Class對象是否已經(jīng)加載,如果未加載。默認(rèn)的類加載器就會根據(jù)累嗎查找.class文件,一旦某個類的Class對象被載入內(nèi)存,它就被用來創(chuàng)建這個類的所有對象
 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());//產(chǎn)生類名
        System.out.println("getCanonicalName\t"+c.getCanonicalName());//產(chǎn)生全限定的類名  包括包名
    }
    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("這個類未發(fā)現(xiàn)");
        }
        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>注意如果把默認(rèn)的構(gòu)造器注釋掉,則會出現(xiàn)java.lang.InstantiationException 錯誤,因?yàn)樾枰@個默認(rèn)的構(gòu)造器創(chuàng)建對象</b>
例子中有三種獲得Class對象的方法:
Class.forName();最簡單的,也是最快捷的方式,因?yàn)槲覀儾⒉恍枰獮榱双@得class對象而持有該類的對象實(shí)例。
obj.getClass;當(dāng)我們已經(jīng)擁有了一個感興趣的類型的對象時,這個方法很好用
obj.class;類字面常量,這種方式很安全,因?yàn)樗诰幾g時就會得到檢查(因此不需要放到try語句塊中),而且高效。

  • 類型轉(zhuǎn)換前先做類型的檢查
 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一個類的實(shí)力上時,可以用.isInstance()和instanceof 方法
instanceof運(yùn)算符 只被用于對象引用變量
Class類的isInstance(Object obj)方法,obj是被測試的對象,如果obj是調(diào)用這個方法的class或接口 的實(shí)例,則返回true。這個方法是instanceof運(yùn)算符的動態(tài)等價。

  • 泛化的Class引用
    Class引用總是指向某個Class對象,可以制造類的實(shí)例,并包含課可作用于這些實(shí)例的所有方法的代碼,還包含該類的靜態(tài)成員,因此,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;
    }
}

如果希望稍微放松一些這種限制,應(yīng)該怎么辦呢?我們使用了通配符? 它是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));
    }
}
  • 反射,運(yùn)行時的類信息
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,806評論 18 399
  • 運(yùn)行時類型信息使得你可以在程序運(yùn)行時發(fā)現(xiàn)和使用類型信息 為什么需要RTTI(運(yùn)行時類型信息):比如,我們使用```...
    扈扈哈嘿閱讀 323評論 0 2
  • 多態(tài) 任何域的訪問操作都將有編譯器解析,如果某個方法是靜態(tài)的,它的行為就不具有多態(tài)性 java默認(rèn)對象的銷毀順序與...
    yueyue_projects閱讀 1,094評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,678評論 19 139
  • 原文Subroutines 標(biāo)題 概要 6: 子例程 版本 創(chuàng)建于: 2003 年 5 月 21 上一次更新: 2...
    焉知非魚閱讀 310評論 0 0

友情鏈接更多精彩內(nèi)容