1. 程式人生 > >type介面和class的區別(型別和類)

type介面和class的區別(型別和類)

Class public final class Class < T > implements java . io . Serializable GenericDeclaration Type AnnotatedElement { }
Type public interface Type {   default
String getTypeName () { return toString (); } } 以上是類和介面的程式碼。 Class 類的例項也就是物件表示正在執行的 Java 應用程式中的類(class)和介面(type),從JDK的原始碼可以看出type是class實現的一個介面,Type是一個空介面是所有型別的公共介面也就是父介面,其意義表示Java所有型別,class是對於現實物件的抽象每一個例項物件是其class 的一個例項,class可以看成是類例項的類,每一個類被載入到JVM中都會產生唯一的一個類例項,記錄型別的詳細資訊,如A類被載入到JVM中會產生一個類例項,其型別為Class,可以通過A.class獲得這個類例項。而type是對Java語言的物件而言,這裡的型別是對於java語言而言,比如原始型別、引數化型別(泛型)、型別變數及其陣列等. 注意區分型別(Type)與類(Class)的區別,這裡Class是Type的一種是Type的子集,
直接子類只有一個也就是Class,代表著型別中的原始型別以及基本型別。 ,而像陣列、列舉等“型別”是相對於Class來說。   Type是JDK5開始引入的,其引入主要是為了泛型,沒有泛型的之前,只有所謂的原始型別。此時,所有的原始型別都通過位元組碼檔案類Class類進行抽象。Class類的一個具體物件就代表一個指定的原始型別。 泛型出現之後,也就擴充了資料型別。從只有原始型別擴充了引數化型別、型別變數型別、泛型陣列型別,也就是Type的子介面。那為什麼沒有統一到Class下,而是增加一個Type呢?(Class也是種類的意思,Type是型別的意思,是為了程式的擴充套件性,最終引入了Type介面作為Class,ParameterizedType,GenericArrayType,TypeVariable和WildcardType這幾種型別的總的父介面。這樣實現了Type型別引數接受以上五種子類的實參或者返回值型別就是Type型別的引數。
1: 型別的概念  概念:型別刻劃了一組值及其上可施行的操作,可理解為值集和操作集構成的二元組。 型別的概念與值的概念相對立,前者是程式中的概念,後者則是程式執行時的概念,兩者通過標識值的語言成分(例如,變數、表示式等)聯絡起來。 比如變數v說明為具有型別T,型別T所刻劃的值集為{v1,v2,…vn,…},則變數v執行時能取且只能取某個vi為值。由此可見,型別規定了具有該型別的變數或表示式的取值範圍。 
2: 類與型別  A: 共性 :在物件式語言中,“值”為物件(或物件索引,但本質上仍為物件)。所以物件式語言中的型別刻劃了一組物件上可施行的操作。類也刻劃了一組物件以及其上的操作。 兩者的共性在於二者均刻劃了一組物件及其上的操作,所以既可以說物件是型別的例項,也可以說物件是類的例項,型別和類在與物件的關係上是相同的。不過,型別欲刻劃一組物件上的操作必須藉助於類,因為類是達到這種目的的唯一設施。由此可見型別是以類為基礎的,是通過類來定義的,這體現了二者的聯絡。 
B: 區別  (1)作用不同 :類是程式的構造單位,是描述一組物件及其上操作的唯一語言成分,故其作用主要是具體描述這組物件,提供執行時建立這些物件的“模板”。例如,基於類間的繼承關係的派生類定義設施就反映了類在描述物件方面的作用。 型別則不是,它只是標誌變數或表示式取值範圍的一種語言成分。
(2)與物件聯絡的緊密程式不同 :類描述物件的具體形式和其上可施行的具體操作,且強調所描述的一組物件的共性,因而,與具體物件聯絡較密切,而與物件集的大小則聯絡較少。 型別強調所描述的一組物件的範圍和可施行操作的範圍,與物件集的大小聯絡較密切,而與其中具體物件則聯絡較少。 
(3)不是所有類都可直接作為型別使用 :類是型別的基礎,型別靠類來定義,有些類可直接作為型別來使用,在這種意義下,我們也可稱這些類是型別。 但是,也有一些類不能直接作為型別來使用,這是因為,從型別的約束作用來看,型別強調所刻劃的物件的確定性,即物件範圍的確定性。因此,只有所描述的物件的範圍確定的類才可直接用作型別。
物件操作所定義的所有操作型構的集合被稱為介面,該介面描述了該物件所能接受的全部請求,任何匹配物件介面中型構的請求都可以傳送給該物件。 型別是用來標識特定介面的一個名字,如果一個物件接受某個介面所定義的所有操作請求,就可以認為該物件具有這個型別,介面可以包含其他介面作為子集,當一個型別的介面包含另外一個型別的介面時,我們就說它是另一個型別的子型別。當給物件傳送請求時,所引起的具體操作與請求本身和接受的物件有關,支援相同請求的不同物件可能對請求激發的操作有不同的實現,傳送給物件的請求和它相應的操作在執行時刻的連線稱之為動態繫結,即是指傳送的請求直到執行的時刻才受你的具體實現的約束。 設計模式根據通過確定介面的主要組成部分及介面傳送的資料型別,來幫助使用者定義介面,還會告訴使用者不能包含哪些東西,同時也指定了介面之間的關係。
描述物件的實現

物件的實現是由類定義的,類指定了物件內部的資料和表示,也定義了物件能夠完成的操作。 抽象類的主要目的是為了它的子類定義公共介面,一個抽象類將把它的部分或全部操作的實現延伸到子類中。而混入類是給其他類提供可選擇的介面或功能的類,域抽象類一樣不能例項化。 類繼承與介面的比較:首先理解物件的類與物件的型別的區別很重要,一個物件的類定義了物件是怎麼實現的,但是物件的型別只與它的介面有關,不同類的物件具有相同的型別,同時物件的類和型別也是具有緊密聯絡的,因為類定義了物件所能執行的操作,也定義了物件的型別,當說一個物件是一個類的例項時,即指該物件支援類所定義的介面。然後回到繼承和介面,類繼承根據一個物件的實現定義了另外一個物件的實現,簡而言之就是程式碼和表示的共享機制,但是介面繼承描述了一個物件什麼時候可以被另外一個物件替代,很多語言不區分這兩個概念,所以容易混淆。儘管大部分設計語言不區分介面繼承和實現繼承這兩個的區別但是使用中還是分別對待它們,很多設計模式依賴於這種差別,比如說一個模式中的物件必須有一個公共型別,但一般情況下它們不具有公共的實現。 對介面程式設計,雖然類繼承允許從已存在的類中繼承所需要的絕大部分功能,就可以獲得新的實現,然和實現的複用只實現了一半,定義具有相同介面的物件族這一功能很重要,因為多型需要這種能力,只根據抽象介面程式設計有兩個好處:客戶無需知道使用物件的特定型別,只需物件有客戶所期望的型別,無須知道使用的物件是用什麼類來實現的,只須知道定義介面的抽象類。這將極大的減少子系統實現之間的相互依賴關係,也產生了可複用的看向物件的設計原則,針對介面程式設計而不是針對實現程式設計。 不將變數宣告某個特定的具體類的例項對像,而是遵從抽象類所定義的介面。


   Type的直接子介面
1.ParameterizedType: 表示一種引數化的型別,比如Collection,即普通的泛型。  2.TypeVariable:是各種型別變數的公共父介面,就是泛型裡面的類似T、E。  3.GenericArrayType:表示一種元素型別是引數化型別或者型別變數的陣列型別,比如List<>[],T[]這種。  4.WildcardType:代表一種萬用字元型別表示式,類似? super T這樣的萬用字元表示式。


Type子介面解析
1.ParameterizedType:引數化型別,即泛型,類似List<T>、Map<Integer, String>、List<? extends Number>帶有型別引數的型別,也可以是自定義的,再呼叫getRawType()與getActualTypeArguments()兩個方法,就可以得到宣告此引數化型別的類(java.lang.Comparable)和實際的型別引數陣列([? super T]),而這個? super T又是一個WildcardType型別。  public interface ParameterizedType extends Type { //1.獲得<>中實際型別 Type[] getActualTypeArguments(); //2.獲得<>前面實際型別 Type getRawType(); //3.如果這個型別是某個型別所屬,獲得這個所有者型別,否則返回null Type getOwnerType();  }

2.TypeVariable:型別變數,如引數化型別中的E、K等型別變數,表示泛指任何類,如果加上extends/super限定,則就會有相應的上限、下限。  public interface TypeVariable< D extends GenericDeclaration> extends Type { //獲得泛型的上限,若未明確宣告上邊界則預設為Object Type[] getBounds(); //獲取宣告該型別變數實體(即獲得類、方法或構造器名) D getGenericDeclaration(); //獲得名稱,即K、V、E之類名稱 String getName();  }

3.GenericArrayType:泛型陣列,表示上面兩種的陣列型別,即形如:A<T>[],T[][]型別。  public interface GenericArrayType extends Type { //獲得這個陣列元素型別,即獲得:A<T>(A<T>[])或T(T[]) Type getGenericComponentType(); // 獲取泛型陣列中元素的型別,要注意的是: 無論從左向右有幾個[]並列,這個方法僅僅脫去最右邊的[]之後剩下的內容就作為這個方法的返回值。 } 以下是getGenericComponentType()函式的原始碼 classA<K>[][] key; Type type = Main. class.getDeclaredField( "key").getGenericType(); System.out.println(((GenericArrayType) type). getGenericComponentType()); //輸出結果 //com.fcc.test.classA<K>[]

4.WildcardType:萬用字元表示式,或泛型表示式,它雖然是Type的一個子介面,但並不是Java型別中的一種,表示的僅僅是類似 ? extends T、? super K這樣的萬用字元表示式。  public interface WildcardType extends Type { //獲得泛型表示式上界(上限) Type[] getUpperBounds(); //獲得泛型表示式下界(下限) Type[] getLowerBounds();  }
Java的所有型別包括:  1. raw type:原始型別,對應Class ,不僅僅指平常所指的類,還包括陣列、介面、註解、列舉等結構。  2. parameterized types:引數化型別,對應ParameterizedType  3. array types:陣列型別,對應GenericArrayType ,應該指的是2、4型別的陣列而不是一般我們說的陣列,一般所說的陣列是指1、5型別陣列,它們依舊屬於1,也就是Class型別。 4. type variables:型別變數,對應TypeVariable  5. primitive types:基本型別,仍然對應Class