摘要:如果需要收集參數(shù)化類(lèi)型對(duì)象,只有使用警告這節(jié)討論,向參數(shù)可變的方法傳遞一個(gè)泛型類(lèi)型的實(shí)例。異常不能拋出或捕獲泛型類(lèi)的實(shí)例實(shí)際上,泛型類(lèi)擴(kuò)展也是不合法的。
Object:所有類(lèi)的超類(lèi)
java中每個(gè)類(lèi)都是由它擴(kuò)展而來(lái),但是并不需要這樣寫(xiě):class Employee extends Object.如果沒(méi)有明確指出超類(lèi),Object類(lèi)就被認(rèn)為是這個(gè)的超類(lèi)。
可以使用Object類(lèi)型的變量引用任何類(lèi)型的對(duì)象Object obj=new Employee().
在java中,只有基本類(lèi)型(int,boolean,...)不是對(duì)象,所有的數(shù)組類(lèi)型,不管是對(duì)象數(shù)組還是基本類(lèi)型的數(shù)組都擴(kuò)展自O(shè)bject類(lèi)。
Employee[] staff=new Employee[10]; Object obj=staff;//ok obj=new int[10];//ok對(duì)象包裝器與自動(dòng)裝箱
有時(shí)需要將int這樣的基本類(lèi)型轉(zhuǎn)換為對(duì)象,所有基本對(duì)象都有一個(gè)與之對(duì)應(yīng)的類(lèi)。如int->Integer.這些類(lèi)稱(chēng)為包裝類(lèi)(wrapper).具體的,包括Integer,Long,Float,Double,Short,Byte,Character,Void,Boolean,前6個(gè)派生于它們公共的超類(lèi)Number.
對(duì)象包裝類(lèi)是不可變的,一旦創(chuàng)建,就不允許更改包裝在其中的值。
對(duì)象包裝類(lèi)還是final,不能定義它們的子類(lèi)。
java5之后,調(diào)用list.add(3)將自動(dòng)變換成list.add(Integer.valueOf(3)),這種變換稱(chēng)為自動(dòng)裝箱。相反的,將一個(gè)Integer對(duì)象賦值給一個(gè)int值時(shí),會(huì)自動(dòng)拆箱。
Listlist=new ArrayList (); list.add(3); int n=list.get(0);//等同于list.get(0).intValue();
在算術(shù)表達(dá)式中,也可以自動(dòng)裝箱,自動(dòng)拆箱。
Integer n=3; n++;//拆箱->自增->裝箱
==運(yùn)算符用于比較包裝器對(duì)象,只不過(guò)檢測(cè)的是對(duì)象是否指向同一個(gè)存儲(chǔ)區(qū)域。因此,下面比較不會(huì)成立
Integer a=1000; Integer b=1000; System.out.println(a==b);//false
但是如果包裝的值經(jīng)常出現(xiàn),==比較就有可能相等
Integer a=100; Integer b=100; System.out.println(a==b);//true
這個(gè)和python類(lèi)似
python并不是對(duì)創(chuàng)建的所有對(duì)象都會(huì)重新申請(qǐng)新的一塊內(nèi)存空間。作為一種優(yōu)化,python會(huì)緩存不變的對(duì)象(如數(shù)值較小的數(shù)字,字符串,元組等)并對(duì)其進(jìn)行復(fù)用。
因此,java設(shè)定了自動(dòng)裝箱規(guī)范
boolean
byte
char<=127
介于-128和127之間的short,int
被包裝到固定的對(duì)象中。
上面例子a,b是100,第二次賦值時(shí),java不會(huì)重新申請(qǐng)新的一塊內(nèi)存空間,存儲(chǔ)100這個(gè)值。
接口特性
接口不是類(lèi),不能使用new運(yùn)算符實(shí)例化一個(gè)接口
可以聲明接口變量,但必須引用實(shí)現(xiàn)了接口的類(lèi)對(duì)象
可以使用instanceof檢查一個(gè)對(duì)象是否實(shí)現(xiàn)了某個(gè)特定的接口
接口可以繼承接口InterfaceA extends InterfaceB
接口中不能包含實(shí)例變量或靜態(tài)方法,卻可以包含常量
public interface Interface { String name="aaa";//a public static final constant }
常量會(huì)自動(dòng)被設(shè)為public static final
盡管每個(gè)類(lèi)只允許擁有一個(gè)超類(lèi),卻可以實(shí)現(xiàn)多個(gè)接口class Concrete implements InterfaceA,InterfaceB
內(nèi)部類(lèi)內(nèi)部類(lèi)方法可以訪問(wèn)該類(lèi)所在的作用域中的數(shù)據(jù),包括私有數(shù)據(jù)
內(nèi)部類(lèi)可以對(duì)同一個(gè)包中的其他類(lèi)隱藏起來(lái)
當(dāng)想要定義一個(gè)回調(diào)函數(shù)且不想寫(xiě)大量代碼時(shí),使用匿名內(nèi)部類(lèi)比較方便
泛型 泛型類(lèi)泛型類(lèi):具有一個(gè)或多個(gè)類(lèi)型變量的類(lèi)。類(lèi)型變量可以指定方法的返回類(lèi)型以及類(lèi)變量和局部變量的類(lèi)型
public class Pair{ T first; T second; Pair(){ this.first=null; this.second=null; } Pair(T first,T second){ this.first=first; this.second=second; } public T getFirst() { return first; } public void setFirst(T first) { this.first = first; } public T getSecond() { return second; } public void setSecond(T second) { this.second = second; } }
Pair類(lèi)引入一個(gè)類(lèi)型變量T,用尖括號(hào)(<>)括起來(lái),并放在類(lèi)名的后面。
泛型可以有多個(gè)類(lèi)型變量``
public class Pair{ ... }
實(shí)例化Pair
泛型方法可以定義在普通類(lèi)中。
publicT getMethod(T... a){}
類(lèi)型變量放在修飾符(這里是public)的后面,返回類(lèi)型的前面
調(diào)用class.
如果是上面情況,大多數(shù)時(shí)候,方法調(diào)用可以省略
但是,如果是下面代碼
double result=class.getMethod(1.23,123,0);
編譯器會(huì)自動(dòng)將參數(shù)打包為1個(gè)Double和2個(gè)Integer對(duì)象,然后尋找這些類(lèi)的共同超類(lèi)型,最終找到兩個(gè)這樣的超類(lèi)Number和Comparable,其本身也是泛型類(lèi)型,這種情況下,只有將所有的參數(shù)寫(xiě)成double值。
如果想知道一個(gè)泛型方法最終推斷出哪種類(lèi)型,可以有目的的引入一個(gè)錯(cuò)誤,看產(chǎn)生的錯(cuò)誤信息,比如
class.getMethod("aaa",0,null); //found:java.lang.Object&java.io.Serializable&java.util.Comparable...
意思是可以將結(jié)果賦給Object,Serializable或Comparable.
類(lèi)型變量的限定T min(T[] a);
上面代碼將T限制為實(shí)現(xiàn)了Comparable接口的類(lèi),這樣min方法只能被實(shí)現(xiàn)了實(shí)現(xiàn)了Comparable接口的類(lèi)(如String,Date類(lèi))的數(shù)組調(diào)用。
注意這里用的是extends關(guān)鍵字
一個(gè)類(lèi)型變量或通配符可以有多個(gè)限定,如T extends Serializable&Comparable.&隔開(kāi)限定類(lèi)型,,隔開(kāi)類(lèi)型變量。
由于對(duì)類(lèi)是單繼承,對(duì)接口多重繼承,如果限定類(lèi)型中有類(lèi)又有接口,必須將類(lèi)作為限定列表中的第一個(gè)。
大多數(shù)限制都是由類(lèi)型擦除引起的,類(lèi)型擦除可以參見(jiàn)Java泛型:類(lèi)型擦除
不能用基本類(lèi)型實(shí)例化類(lèi)型參數(shù)。
沒(méi)有Pair
運(yùn)行時(shí)類(lèi)型查詢(xún)只試用于原始類(lèi)型。
虛擬機(jī)中的對(duì)象總有一個(gè)特定的非泛型類(lèi)型,因此所有的類(lèi)型查詢(xún)只產(chǎn)生原始類(lèi)型。
if(a instanceof Pair)...//error if(a instanceof Pair )...//error Pair p=(Pair ) a;//warning,can only test that a is a Pair
同樣的道理,getClass方法總是返回原始類(lèi)型。
PairstringPair=...; Pair employeePair=...; if(stringPair.getClass()==employeePair.getClass())...//they are equal
上面代碼兩次調(diào)用getClass都將返回Pair.class.
不能創(chuàng)建參數(shù)化類(lèi)型的數(shù)組
Pair[] paris=new Pair [10]; //error,The type of the expression must be an array type but it resolved to Pair
上面代碼的問(wèn)題在于,類(lèi)型擦除后,paris的類(lèi)型是Pair[],可以轉(zhuǎn)換為Object[]
Object[] objarray=pairs;
數(shù)組會(huì)記住它的元素類(lèi)型,如果試圖存儲(chǔ)其他類(lèi)型的元素,就會(huì)拋出Array-StoreException.
只是不允許這樣創(chuàng)建數(shù)組,而聲明類(lèi)型為Pair
可以聲明通配類(lèi)型的數(shù)組,然后類(lèi)型轉(zhuǎn)換
Pair[] pairs=(Pair []) new Pair>[10];
但這樣類(lèi)型是不安全的。
如果需要收集參數(shù)化類(lèi)型對(duì)象,只有使用ArrayList
Varargs警告
這節(jié)討論,向參數(shù)可變的方法傳遞一個(gè)泛型類(lèi)型的實(shí)例。
staticvoid addAll(Collection coll,T... ts){ for(T t:ts) coll.add(t); } Collection > coll=...; Pair pair1=...; Pair pair2=...; addAll(coll,pair1,pair2);
為了調(diào)用addAll方法,java虛擬機(jī)必須建立一個(gè)Pair
不過(guò),對(duì)于這種情況,規(guī)則有所放松,只會(huì)得到一個(gè)警告,而不是錯(cuò)誤。
有兩種方法抑制這個(gè)警告
為包含addAll調(diào)用的方法添加標(biāo)注@SuppressWarnings("unchecked").
如果是java7或其后面版本,用@SafeVarargs直接標(biāo)注addAll方法。
@SafeVarargs staticvoid addAll(Collection coll,T... ts)
不能實(shí)例化類(lèi)型變量
不能使用像new T(),new T[],T.class這樣的表達(dá)式中的類(lèi)型變量。
泛型類(lèi)中靜態(tài)類(lèi)型變量無(wú)效
不能在靜態(tài)域或方法中引用類(lèi)型變量
public class singleton{ static T instance;//error static T getInstance(){//error ... } }
類(lèi)型擦除后,Singleton類(lèi)只包含一個(gè)instance域變量。
異常不能拋出或捕獲泛型類(lèi)的實(shí)例
實(shí)際上,泛型類(lèi)擴(kuò)展Throwable也是不合法的。
Class Problemextends Exception{...}//error,can"t extend Throwable
catch子句中不能使用類(lèi)型變量。
void dowork(T t) throws T{ try{ ... }catch(T t){//error ... } }
不過(guò)在其中使用類(lèi)型變量是允許的。
void dowork(T t) throws T{ try{ ... }catch(Throwable realCause){//error t.initCause(realCause); throw t; } }
注意擦除后的沖突
類(lèi)型擦除后,無(wú)法創(chuàng)建引發(fā)沖突的條件。
public class Pair{ ... boolean equals(T value){ return this.first.equals(value)&&this.second.equals(value); } }
上面代碼類(lèi)型擦除后boolean equals(T)變成boolean equals(Object),與Object類(lèi)本身的equals方法發(fā)生沖突。所以編譯器會(huì)發(fā)出警告,equals(T)方法沒(méi)有override Object類(lèi)中的equals(Object).
泛型類(lèi)型的繼承規(guī)則考慮一個(gè)類(lèi)和一個(gè)子類(lèi),如Employee和Manager.顯然Pair
注意泛型和數(shù)組間的重要區(qū)別,可以將一個(gè)Manager[]數(shù)組賦值給一個(gè)類(lèi)型為Employee[]的變量。
public class Manager extends Employee{ public static void main(String[] args){ Manager ceo=new Manager(); Manager cto=new Manager(); Manager[] managers=new Manager[]{ceo,cto}; Employee[] employs=managers; System.out.println(employs.length);//2 } }
另外,可以參數(shù)化類(lèi)型轉(zhuǎn)換為原始類(lèi)型,如Pair
public class Pair{ T first; T second; Pair(T first,T second){ this.first=first; this.second=second; } public T getFirst() { return first; } public void setFirst(T first) { this.first = first; } }
public class Manager{ public static void main(String[] args){ Manager ceo=new Manager(); Manager cto=new Manager(); Pairpair=new Pair<>(ceo,cto); Pair pair1=pair;//ok pair1.setFirst(new File(""));//類(lèi)型警告,但是可運(yùn)行 Manager manager=(Manager)pair1.getFirst(); //ClassCastException,java.io.File cannot be cast to com.Manager Manager manager1=pair.getFirst(); //ClassCastException,java.io.File cannot be cast to com.Manager } }
最后,泛型類(lèi)可以擴(kuò)展或?qū)崿F(xiàn)其他泛型類(lèi),這和普通類(lèi)沒(méi)什么區(qū)別。如ArrayList類(lèi)實(shí)現(xiàn)List接口,這意味著ArrayList
但是如前面所見(jiàn),ArrayList
Pair extends Employee>表示類(lèi)型參數(shù)是Employee類(lèi)的子類(lèi).
看下面代碼
void print(Pairp){ Employee first=p.getFirst(); Employee second=p.getSecond(); ... }
正如前面所說(shuō),這里不能將Pair
void print(Pair extends Employee> p)
類(lèi)型Pair
下面考慮
Pairmanager=new Pair<>(); Pair extends Employee> pair=manager;//ok pair.setFirst(manager); //編譯錯(cuò)誤,The method setFirst(capture#1-of ? extends Employee) in the type //Pair is not applicable for the arguments (Pair )
不過(guò)將getFirst方法的返回值賦值給一個(gè)Employee引用就不存在問(wèn)題。
通配符的超類(lèi)型限定如? super Manager,這個(gè)通配符限制類(lèi)型變量為Manager的所有超類(lèi)型。
上面代碼 extends Manager>如果換成 super Manager>,將會(huì)表現(xiàn)為可以為方法通過(guò)參數(shù)(set),但不能使用返回值(get).
帶有超類(lèi)型限定的通配符( super Manager>)可以向泛型對(duì)象寫(xiě)入,帶有子類(lèi)型限定的( extends Manager>)可以從泛型對(duì)象讀取
如Pair>有方法
? getFirst()
void setFirst(?)
getFirst的返回值只能賦值給一個(gè)Object,而setFirst方法不能被調(diào)用,甚至用Object做參數(shù)也不能。
可以調(diào)用setFirst(null)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64680.html
摘要:關(guān)鍵字作用調(diào)用超類(lèi)方法調(diào)用超類(lèi)構(gòu)造器關(guān)鍵字作用引用隱式參數(shù)如調(diào)用該類(lèi)的其他構(gòu)造器在覆蓋一個(gè)方法時(shí),子類(lèi)方法可見(jiàn)性不能低于超類(lèi)方法阻止繼承類(lèi)和方法目的確保它們不會(huì)在子類(lèi)中改變語(yǔ)義。但是如果將一個(gè)類(lèi)聲明為后面可以改變類(lèi)變量的值了。 數(shù)據(jù)類(lèi)型 整型 int 存儲(chǔ)要求:4byte 取值范圍:-2147483648 -- 2147483647(超過(guò)20億) short 存儲(chǔ)要求:2byte 取...
摘要:然而,這兩個(gè)方法都只是讀取對(duì)象狀態(tài),如果只是讀取操作,就可以允許線程并行,這樣讀取效率將會(huì)提高。分配線程執(zhí)行子任務(wù)執(zhí)行子任務(wù)獲得子任務(wù)進(jìn)行完成的結(jié)果 Lock Lock接口主要操作類(lèi)是ReentrantLock,可以起到synchronized的作用,另外也提供額外的功能。用Lock重寫(xiě)上一篇中的死鎖例子 import java.util.concurrent.locks.Lock; ...
摘要:注本文內(nèi)容來(lái)深入面向?qū)ο竽J脚c實(shí)踐中節(jié)。面向?qū)ο笤O(shè)計(jì)與過(guò)程式編程面向?qū)ο笤O(shè)計(jì)和過(guò)程式編程有什么不同呢可能有些人認(rèn)為最大的不同在于面向?qū)ο缶幊讨邪瑢?duì)象。面向?qū)ο缶幊毯瓦^(guò)程式編程的一個(gè)核心區(qū)別是如何分配職責(zé)。 注:本文內(nèi)容來(lái)中6.2節(jié)。 6.2 面向?qū)ο笤O(shè)計(jì)與過(guò)程式編程 ??面向?qū)ο笤O(shè)計(jì)和過(guò)程式編程有什么不同呢?可能有些人認(rèn)為最大的不同在于面向?qū)ο缶幊讨邪瑢?duì)象。事實(shí)上,這種說(shuō)法不準(zhǔn)確。...
摘要:一讓廣播明星黯然失色要建立頁(yè)面,需要?jiǎng)?chuàng)建用超文本標(biāo)記語(yǔ)言,編寫(xiě)的文件,把它們放在一個(gè)服務(wù)器上二服務(wù)器能做什么服務(wù)器在互聯(lián)網(wǎng)上有一份全天候的工作。一、Web讓廣播明星黯然失色 要建立Web頁(yè)面,需要?jiǎng)?chuàng)建用超文本標(biāo)記語(yǔ)言(HyperText Markup Language,HTML)編寫(xiě)的文件,把它們放在一個(gè)Web服務(wù)器上二、Web服務(wù)器能做什么? Web服務(wù)器在互聯(lián)網(wǎng)上有一份全天候的工...
摘要:包括元素的高度上下內(nèi)邊距上下邊框值,如果元素的的值為那么該值為。該值為元素的包含元素。最后,所有這些偏移量都是只讀的,而且每次訪問(wèn)他們都需要重新計(jì)算。為了避免重復(fù)計(jì)算,可以將計(jì)算的值保存起來(lái),以提高性能。 offsetHeight 包括元素的高度、上下內(nèi)邊距、上下邊框值,如果元素的style.display的值為none,那么該值為0。offsetWidth 包括元素的寬度、左...
閱讀 702·2023-04-25 19:53
閱讀 4304·2021-09-22 15:13
閱讀 2580·2019-08-30 10:56
閱讀 1337·2019-08-29 16:27
閱讀 2947·2019-08-29 14:00
閱讀 2426·2019-08-26 13:56
閱讀 452·2019-08-26 13:29
閱讀 1627·2019-08-26 11:31