//是這樣嗎?
創新互聯長期為千余家客戶提供的網站建設服務,團隊從業經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態環境。為北海企業提供專業的網站設計制作、成都網站制作,北海網站改版等技術服務。擁有十載豐富建站經驗和眾多成功案例,為您定制開發。
public class FTestDraw {
public static void main(String[] args) {
DrawMethodShape dm = new DrawMethodShape(new Circle());
dm.shape.draw();
}
}
abstract class Shape{
abstract void draw();
}
class Circle extends Shape{
@Override
void draw() {
System.out.println("這是圓形");
}
}
class Rectangle extends Shape{
@Override
void draw(){
System.out.println("這是長方形");
}
}
class Triangle extends Shape{
@Override
void draw(){
System.out.println("這是三角形");
}
}
class DrawMethodT extends Shape{
T shape = null;
public DrawMethod(T tt){
shape = tt;
}
}
您好,我用斷點調試解釋吧[真的很高興能與你討論][啊啦上回不好意思但還是說對一部分滴].
1-----你在go方法中,沒有給list限制泛型約束,所以1.1不加check的存儲進arraylist了.
2-----"1.1"是被內部機制轉換為Double存儲進arraylist的:
[在System.out.println(list.get(1));處下斷點,點調試.可以看到list里是
[1, 1.1],
elementData[]為
[1, 1.1, null, null, null, null, null, null, null, null].
elementData[0]的值是"1",
elementData[1]的值為Double (標識=37).]
也就是說,go方法add時因為沒有約束,所以由內部機制將1.1轉換為Double存入了以String為約束的list里.
3-----點"單步跳入",看到代碼跳到了arraylist的get里:
public E get(int index) {
RangeCheck(index);
return elementData[index];
}
關鍵點就在這了,由第2步看到elementData[1]的類型為Double,而在main里為list設置的約束是String,所以E 為String.上面的代碼就變為:
public String get(int index) {
RangeCheck(index);
return 1.1; //double
}
繼續跳,
看到他照樣返回了一個加著String標簽的double值.
4-----繼續點然后報錯了.這個是由于syso輸出是輸出String.這個后面會說.
如果你加一個方法:
public static void go1(List list)
{
System.out.println(list.get(1));
}
這樣沒約束的情況下syso,是沒有錯的.因為get后的對象沒有加類型標簽,會由內部機制判斷他到底是哪個類.
而加了String返回類型標簽后就不做判斷直接調用syso(String)的方法來輸出Double了.所以報告了class cast錯誤.
如果你繼續看,會看到是String類的init出現的錯誤.
因為前面調試中看到syso(args)的args為String[],而返回的卻是Double.類型沒匹配上.
正確的那個例子不用說了吧,調試一下會發現他syso時String.valueof(obj)了,"1.1"肯定滿足條件.[如果不滿足條件,會打印object,這也是能輸出syso(list)的原因][SYSO在控制臺輸出的是字符,如果是double會轉為字符輸出]
而錯的那個因為返回標明了是String,所以程序不加判斷就直接write了,輸出字符卻給個double,就出錯了.
上班了...打一中午,555,可能說的有錯誤,樓主自己調試一下,以自己的方式理解一下吧_
PS:其實俺上回說的有一部分對...我樓上那位5級大哥說的也部分對,但1.1是double傳進去的,沒轉換成int.調試過我就明白了,一開始我也那么想.
1.1 list.get()返回類型為?,所以你只能用Object接收,Object足以確保type-safe,因為java中任何class都是Object的subclass。(當然,如果你非要使用類型強制轉換,轉換成什么阿貓阿狗的class,也沒人攔得住你,對此只能說“編譯器盡力了,你行你上啊”,反正ClassCastException什么的最有愛了)
2.2 list.put()除了null以外,任何參數都不接收。這也足以確保list中類型的type-safe,要知道,java的泛型的implementation是基于ERASURE(擦除)的,舉個具體的例子,LinkedListE的內部數據結構肯定是基于NodeE,那么一個Node有2個field,E element和NodeE next,而實際上在runtime環境中,LinkedListString中的Node并不是NodeString,僅僅是Node,Node里面的element的類型也不是String,僅僅是Object,也就是說,compile-time的type-information都被抹除了(Quote: For backward-compatibility)。試想這么一個情景,Tom傳了一個ListDog給Mike,Mike的interface是List?,Mike往list中放了一個Cat(假設compiler沒有阻止Mike),然后Tom取出該List中所有的object并當成Dog使用(compiler會自動加上類型轉換的代碼——which is how java generics worked),然后Tom就悲劇地得到了一個ClassCastException——這就是為什么除了null其他參數都不接收的原因——阻止Mike隨便放東西進去。
2、List
raw-type就是這么個情況,相當于你對compiler說:“我并不在乎這個List里面的element的runtime-type是什么,不管我怎么操作這個list或者list中取出來的object,你都別管,實在看不過去就給我個warning就行了”。這種情況下:
2.1 list.get()返回類型為Object,當然,也是type-safe的(如果你不強制轉換的話)
2.2 list.put()的參數類型為Object,也就是說,你愛往里面放什么object就放什么object,還是上面那個例子,就算Tom給Mike的是ListString,但由于Mike的interface是List,所以Mike放個BigInteger甚至什么Cat、Dog,compiler都不會阻止Mike(但是,要知道,Mike是無法得知其他人會怎么使用這個List的,比如說Mike無法得知Tom相信編譯器確保了list中的object都是String,但是由于Mike的raw-type interface,Tom就難免吃ClassCastException咯)
名稱欄目:java泛型list代碼,java list泛型集合
轉載來于:http://vcdvsql.cn/article18/hecggp.html
成都網站建設公司_創新互聯,為您提供營銷型網站建設、電子商務、小程序開發、網站策劃、微信小程序、網站維護
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯