java類型信息

運(yùn)行時(shí)類型信息使得你能夠在程序運(yùn)行時(shí)發(fā)現(xiàn)和使用類型信息;
java在運(yùn)行中識(shí)別類型信息主要有兩類,一是從傳統(tǒng)的RTTI,另一種是反射機(jī)制;


1、Class對(duì)象

要理解RTTI是在java中的工作原理,必須要知道,類型信息在運(yùn)行中是如何表示的,這項(xiàng)工作是由Class類來完成的,它包含了與類有關(guān)的信息;
類是程序的一部分,每一個(gè)類都有一個(gè)Class對(duì)象,換言之,每當(dāng)編寫并編譯一個(gè)新類,就會(huì)產(chǎn)生一個(gè)Class對(duì)象(保存在對(duì)應(yīng)的同名.class文件中),為了生成這個(gè)類的對(duì)象,java虛擬機(jī)將使用成為類加載器的子系統(tǒng);
所有的類都是在其第一次使用時(shí),動(dòng)態(tài)的加載到JVM中,當(dāng)程序創(chuàng)建的第一個(gè)對(duì)類的靜態(tài)成員的引用時(shí),就會(huì)加載此類。這證明構(gòu)造器也是一種靜態(tài)方法,即使構(gòu)造器之前并沒有使用關(guān)鍵詞static。因此,使用new關(guān)鍵字創(chuàng)造的新對(duì)象也會(huì)被當(dāng)作對(duì)類的靜態(tài)成員的引用;
因此,java程序在其開始運(yùn)行之前并非全部加載,其各個(gè)部分只有需要的時(shí)候才被加載。

package com.innerclass;

class Candy{
    static {
        System.out.println("Candy has been load...");
    }
}
class Gum{
    static {
        System.out.println("Gum has been load...");
    }
}
class Cookie{
    static {
        System.out.println("Cookie has been load...");
    }
}
public class classform {
    public static void main(String[] args){
        System.out.println("inside main");
        new Candy();
        System.out.println("After creating Candy");
        try{
            Class.forName("com.innerclass.Gum");
        } catch (ClassNotFoundException e) {
            //e.printStackTrace();
            System.out.println("Gum not found");
        }
        /*
        try {
            Class<?> g=Gum.class;
        }catch (Exception e){
            System.out.println("未加載成功...");
        }
        */
        System.out.println("After Class.forName(\"Gum\") ");
        new Cookie();
        System.out.println("After creating Cookie");
    }
}
inside main
Candy has been load...
After creating Candy
Gum has been load...
After Class.forName("Gum") 
Cookie has been load...
After creating Cookie

上面一個(gè)例子證明,類僅在其需要的時(shí)候加載,static初始化,是在類加載的時(shí)候進(jìn)行的。
實(shí)現(xiàn)class對(duì)象的引用方法,可以通過Class.forName()方法,根類的.getClass()方法和.Class方法進(jìn)行使用;
Class類還有一些別的方法:

package com.innerclass;

interface Web{}
interface Applaction{}
interface Net{}

class Candy{
    static {
        System.out.println("Candy has been load...");
    }
}
class Gum extends Candy implements Web,Applaction,Net{
    static {
        System.out.println("Gum has been load...");
    }
}

public class classform {
    public static void main(String[] args){
        Class c=null;
        try{
            c=Class.forName("com.innerclass.Gum");
        } catch (ClassNotFoundException e) {
            System.out.println("cannt find Gum");
            System.exit(1);
        }
        System.out.println(c);
        for(Class face:c.getInterfaces()){
            System.out.println("c.getInterfaces"+face);
            Class up=c.getSuperclass();
            Object object=null;
            try {
                object=up.newInstance();
            } catch (IllegalAccessException e) {
                System.out.println("cannt access");
                System.exit(1);
            } catch (InstantiationException e) {
                System.out.println("cannt instantiate");
                System.exit(1);
            }
            System.out.println("c.getSuperclass"+object.getClass());
        }
    }
}

注意上例的newInstance()方法,是實(shí)現(xiàn)虛擬構(gòu)造器的一種途徑,并且由該方法創(chuàng)建的類,必須含有默認(rèn)無參構(gòu)造器;

2、類字面常量

java生成引用的另外一個(gè)方法,.class方法,即類字面常量;這樣做不僅簡(jiǎn)單,而且安全,因?yàn)樗诰幾g的時(shí)候已經(jīng)檢查,故無需采用try語句;它不僅可以應(yīng)用到普通的類,還可以應(yīng)用到接口、數(shù)組以及基本數(shù)據(jù)類型;對(duì)于包裝類型,還有一個(gè)標(biāo)準(zhǔn)的字段TYPE;
即對(duì)于包裝類型:
boolean.class等價(jià)于Boolean.TYPE
當(dāng)使用.class來創(chuàng)建Class對(duì)象時(shí),不會(huì)自動(dòng)的初始化該Class對(duì)象,為了使用類而做的準(zhǔn)備實(shí)際上包括三個(gè)步驟:
1、加載,有類加載器執(zhí)行,該步驟查找字節(jié)碼,并從這些字節(jié)碼中創(chuàng)建一個(gè)Class對(duì)象;
2、鏈接:在鏈接階段將驗(yàn)證碼類中的字節(jié)碼,為靜態(tài)域分配存儲(chǔ)空間,同時(shí)解析該類創(chuàng)建的對(duì)其他類的引用;
3、初始化:如果該類有超類的話,先對(duì)其超類進(jìn)行初始化,執(zhí)行其靜態(tài)初始化構(gòu)造器或靜態(tài)代碼塊,而初始化延遲到,對(duì)靜態(tài)方法或者常數(shù)靜態(tài)域進(jìn)行首次引用;

package com;

class FatheCLss{
    private static FatheCLss fatheCLss=new FatheCLss();
    private final  static String str="hello world";
    private static int age=1;
    private String name="lihua";
    public FatheCLss(){
        System.out.println("執(zhí)行FatheClss的構(gòu)造方法"+"  age"+age+"  name"+name+ str);
    }
    static {
        System.out.println("執(zhí)行FatherClss的靜態(tài)代碼塊"+age+str);
        age=38;
        System.out.println("執(zhí)行FatherClss的靜態(tài)代碼塊"+age+str);
    }
    {
        System.out.println("執(zhí)行"+this.getClass()+"的非靜態(tài)代碼塊"+"   age:"+age+"   name:"+name+str);
        age=12;
        System.out.println("執(zhí)行"+this.getClass()+"的非靜態(tài)代碼塊"+"   age:"+age+"   name:"+name+str);
    }
}
public class CLassLoad extends FatheCLss {
    private static double height;
    public CLassLoad(){
        super();
        System.out.println("執(zhí)行CLassLoad的構(gòu)造方法"+height);
    }
    static {
        System.out.println("執(zhí)行CLassLoad 的靜態(tài)代碼塊"+height);
        height=12;
        System.out.println("執(zhí)行CLassLoad 的靜態(tài)代碼塊"+height);
    }
    public static void main(String args[]){
        new CLassLoad();
    }
}


執(zhí)行class com.FatheCLss的非靜態(tài)代碼塊   age:0   name:lihuahello world
執(zhí)行class com.FatheCLss的非靜態(tài)代碼塊   age:12   name:lihuahello world
執(zhí)行FatheClss的構(gòu)造方法  age12  namelihuahello world
執(zhí)行FatherClss的靜態(tài)代碼塊1hello world
執(zhí)行FatherClss的靜態(tài)代碼塊38hello world
執(zhí)行CLassLoad 的靜態(tài)代碼塊0.0
執(zhí)行CLassLoad 的靜態(tài)代碼塊12.0
執(zhí)行class com.CLassLoad的非靜態(tài)代碼塊   age:38   name:lihuahello world
執(zhí)行class com.CLassLoad的非靜態(tài)代碼塊   age:12   name:lihuahello world
執(zhí)行FatheClss的構(gòu)造方法  age12  namelihuahello world
執(zhí)行CLassLoad的構(gòu)造方法12.0

package com;

class FatheCLss{
   // private static FatheCLss fatheCLss=new FatheCLss();
     static final  String STR="hello world";
     static int age=1;
     int width=12;
     final int height=1;
     String name="lihua";
    public FatheCLss(){
        System.out.println("執(zhí)行FatheClss的構(gòu)造方法"+"  age"+age+"  name"+name+ STR);
    }
    static {
        System.out.println("執(zhí)行FatherClss的靜態(tài)代碼塊"+age+STR);
        age=38;
        System.out.println("執(zhí)行FatherClss的靜態(tài)代碼塊"+age+STR);
    }
    {
        System.out.println("執(zhí)行"+this.getClass()+"的非靜態(tài)代碼塊"+"   age:"+age+"   name:"+name+STR);
        age=12;
        System.out.println("執(zhí)行"+this.getClass()+"的非靜態(tài)代碼塊"+"   age:"+age+"   name:"+name+STR);
    }
}
public class CLassLoad {

    public static void main(String args[]){
        Class father=FatheCLss.class;

       System.out.println("before fatherClass 實(shí)例化");
        System.out.println(FatheCLss.STR);
        System.out.println("fatheclass 的 str");
        System.out.println(FatheCLss.age);

    }
}


可以看出對(duì)于static final修飾的值,代表為編譯器常量,不需要對(duì)其進(jìn)行初始化即可得到;
而,一個(gè)static域而不是final的,那么對(duì)其訪問時(shí),總是要求在它被讀之前進(jìn)行鏈接和初始化;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,767評(píng)論 18 399
  • 2.3 Java類型信息詳解 運(yùn)行時(shí)類型信息(RTTI)使得我們可以在程序運(yùn)行時(shí)發(fā)現(xiàn)和使用類型信息,其工作原理是C...
    jianhuih閱讀 1,903評(píng)論 0 1
  • 歡迎轉(zhuǎn)載,但請(qǐng)保留作者鏈接:http://www.lxweimin.com/p/5a6bad3752d9 有Java...
    郭非文閱讀 4,287評(píng)論 4 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,973評(píng)論 19 139
  • 昨天參加完學(xué)校的迎新晚會(huì),一個(gè)人隨著人流走回宿舍,并行的同學(xué)有夸獎(jiǎng)的也有說無聊的,而我認(rèn)為ta們非常棒。...
    songgenkui閱讀 305評(píng)論 0 1