日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 泛型 extends 多个

發(fā)布時間:2024/4/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 泛型 extends 多个 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://blog.csdn.net/chjttony/article/details/6801406

1.泛型邊界:

Java泛型編程時,編譯器忽略泛型參數(shù)的具體類型,認為使用泛型的類、方法對Object都適用,這在泛型編程中稱為類型信息檫除。

例如:

[java] view plaincopyprint?
  • class?GenericType{??
  • ????public?static?void?main(String[]?args){??
  • ????????System.out.println(new?ArrayList<String>().getClass());??
  • ????????System.out.println(new?ArrayList<Integer>().getClass());??
  • }??
  • }??
  • class GenericType{public static void main(String[] args){System.out.println(new ArrayList<String>().getClass());System.out.println(new ArrayList<Integer>().getClass()); } }


    ?

    輸出結果為:

    java.util.ArrayList

    java.util.ArrayList

    泛型忽略了集合容器中具體的類型,這就是類型檫除。

    但是如果某些泛型的類/方法只想針對某種特定類型獲取相關子類應用,這時就必須使用泛型邊界來為泛型參數(shù)指定限制條件。

    例如:

    [java] view plaincopyprint?
  • interface?HasColor{??
  • ????java.awt.Color?getColor();??
  • }??
  • class?Colored<T?extends?HasColor>{??
  • ????T?item;??
  • ????Colored(T?item){??
  • ????????this.item?=?item;??
  • }??
  • java.awt.Color?color(){??
  • ????//調(diào)用HasColor接口實現(xiàn)類的getColor()方法 ??
  • ????return?item.getColor();??
  • }??
  • }??
  • class?Dimension{??
  • ????public?int?x,?y,?z;??
  • }??
  • Class?ColoredDimension<T?extends?Dimension?&?HasColor>{??
  • ????T?item;??
  • ????ColoredDimension(T?item){??
  • ????????this.item?=?item;??
  • }??
  • T?getItem(){??
  • ????return?item;??
  • }??
  • java.awt.Color?color(){??
  • ????//調(diào)用HasColor實現(xiàn)類中的getColor()方法 ??
  • ????return?item.getColor();??
  • }??
  • //獲取Dimension類中定義的x,y,z成員變量 ??
  • int?getX(){??
  • ????return?item.x;??
  • }??
  • int?getY(){??
  • ????return?item.y;??
  • }??
  • int?getZ(){??
  • ????return?item.z;??
  • }??
  • }??
  • interface?Weight{??
  • ????int?weight();??
  • }??
  • class?Solid<T?extends?Dimension?&?HasColor?&?Weight>{??
  • ????T?item;??
  • ????Solide(T?item){??
  • ????????this.item?=?item;??
  • }??
  • T?getItem(){??
  • ????return?item;??
  • }??
  • java.awt.Color?color(){??
  • ????//調(diào)用HasColor實現(xiàn)類中的getColor()方法 ??
  • ????return?item.getColor();??
  • }??
  • //獲取Dimension類中定義的x,y,z成員變量 ??
  • int?getX(){??
  • ????return?item.x;??
  • }??
  • int?getY(){??
  • ????return?item.y;??
  • }??
  • int?getZ(){??
  • ????return?item.z;??
  • }??
  • int?weight(){??
  • ????//調(diào)用Weight接口實現(xiàn)類的weight()方法 ??
  • ????return?item.weight();??
  • }??
  • }??
  • class?Bounded?extends?Dimension?implements?HasColor,?Weight{??
  • ????public?java.awt.Color?getColor{??
  • ????????return?null;??
  • }??
  • public?int?weight(){??
  • ????return?0;??
  • }??
  • }??
  • public?class?BasicBounds{??
  • ????public?static?void?main(String[]?args){??
  • ????????Solid<Bounded>?solid?=?new?Solid<Bounded>(new?Bounded());??
  • ????????solid.color();??
  • ????????solid.getX();??
  • ????????solid.getY();??
  • ????????solid.getZ();??
  • ????????solid.weight();??
  • }??
  • }??
  • interface HasColor{java.awt.Color getColor(); } class Colored<T extends HasColor>{T item;Colored(T item){this.item = item; } java.awt.Color color(){//調(diào)用HasColor接口實現(xiàn)類的getColor()方法return item.getColor(); } } class Dimension{public int x, y, z; } Class ColoredDimension<T extends Dimension & HasColor>{T item;ColoredDimension(T item){this.item = item; } T getItem(){return item; } java.awt.Color color(){//調(diào)用HasColor實現(xiàn)類中的getColor()方法return item.getColor(); } //獲取Dimension類中定義的x,y,z成員變量 int getX(){return item.x; } int getY(){return item.y; } int getZ(){return item.z; } } interface Weight{int weight(); } class Solid<T extends Dimension & HasColor & Weight>{T item;Solide(T item){this.item = item; } T getItem(){return item; } java.awt.Color color(){//調(diào)用HasColor實現(xiàn)類中的getColor()方法return item.getColor(); } //獲取Dimension類中定義的x,y,z成員變量 int getX(){return item.x; } int getY(){return item.y; } int getZ(){return item.z; } int weight(){//調(diào)用Weight接口實現(xiàn)類的weight()方法return item.weight(); } } class Bounded extends Dimension implements HasColor, Weight{public java.awt.Color getColor{return null; } public int weight(){return 0; } } public class BasicBounds{public static void main(String[] args){Solid<Bounded> solid = new Solid<Bounded>(new Bounded());solid.color();solid.getX();solid.getY();solid.getZ();solid.weight(); } }


    ?

    Java泛型編程中使用extends關鍵字指定泛型參數(shù)類型的上邊界(后面還會講到使用super關鍵字指定泛型的下邊界),即泛型只能適用于extends關鍵字后面類或接口的子類。

    Java泛型編程的邊界可以是多個,使用如<T extends A & B & C>語法來聲明,其中只能有一個是類,并且只能是extends后面的第一個為類,其他的均只能為接口(和類/接口中的extends意義不同)。

    使用了泛型邊界之后,泛型對象就可以使用邊界對象中公共的成員變量和方法。

    2.泛型通配符:

    泛型初始化過程中,一旦給定了參數(shù)類型之后,參數(shù)類型就會被限制,無法隨著復制的類型而動態(tài)改變,如:

    [java] view plaincopyprint?
  • class?Fruit{??
  • }??
  • class?Apple?extends?Fruit{??
  • }??
  • class?Jonathan?extends?Apple{??
  • }??
  • class?Orange?extends?Fruit{??
  • }??
  • 如果使用數(shù)組:??
  • public?class?ConvariantArrays{??
  • ????Fruit?fruit?=?new?Apple[10];??
  • ????Fruit[0]?=?new?Apple();??
  • ????Fruit[1]?=?new?Jonathan();??
  • ????try{??
  • ????????fruit[0]?=?new?Fruit();??
  • }catch(Exception?e){??
  • ????System.out.println(e);??
  • }??
  • try{??
  • ????????fruit[0]?=?new?Orange();??
  • }catch(Exception?e){??
  • ????System.out.println(e);??
  • }??
  • }??
  • class Fruit{ } class Apple extends Fruit{ } class Jonathan extends Apple{ } class Orange extends Fruit{ } 如果使用數(shù)組: public class ConvariantArrays{Fruit fruit = new Apple[10];Fruit[0] = new Apple();Fruit[1] = new Jonathan();try{fruit[0] = new Fruit(); }catch(Exception e){System.out.println(e); } try{fruit[0] = new Orange(); }catch(Exception e){System.out.println(e); } }


    ?

    編譯時沒有任何錯誤,運行時會報如下異常:

    java.lang.ArrayStoreException:Fruit

    java.lang.ArrayStoreException:Orange

    為了使得泛型在編譯時就可以進行參數(shù)類型檢查,我們推薦使用java的集合容器類,如下:

    [java] view plaincopyprint?
  • public?class?NonConvariantGenerics{??
  • ????List<Fruit>?flist?=?new?ArrayList<Apple>();??
  • }??
  • public class NonConvariantGenerics{List<Fruit> flist = new ArrayList<Apple>(); }


    ?

    很不幸的是,這段代碼會報編譯錯誤:incompatible types,不兼容的參數(shù)類型,集合認為雖然Apple繼承自Fruit,但是List的Fruit和List的Apple是不相同的,因為泛型參數(shù)在聲明時給定之后就被限制了,無法隨著具體的初始化實例而動態(tài)改變,為解決這個問題,泛型引入了通配符”?”。

    對于這個問題的解決,使用通配符如下:

    [java] view plaincopyprint?
  • public?class?NonConvariantGenerics{??
  • ????List<??extends?Fruit>?flist?=?new?ArrayList<Apple>();??
  • }??
  • public class NonConvariantGenerics{List<? extends Fruit> flist = new ArrayList<Apple>(); }


    ?

    泛型通配符”?”的意思是任何特定繼承Fruit的類,java編譯器在編譯時會根據(jù)具體的類型實例化。

    另外,一個比較經(jīng)典泛型通配符的例子如下:

    public class SampleClass < T extendsS> {…}

    假如A,B,C,…Z這26個class都實現(xiàn)了S接口。我們使用時需要使用到這26個class類型的泛型參數(shù)。那實例化的時候怎么辦呢?依次寫下

    SampleClass<A> a = new SampleClass();

    SampleClass<B> a = new SampleClass();

    SampleClass<Z> a = new SampleClass();

    這顯然很冗余,還不如使用Object而不使用泛型,使用通配符非常方便:

    SampleClass<? Extends S> sc = newSampleClass();

    3.泛型下邊界:

    在1中大概了解了泛型上邊界,使用extends關鍵字指定泛型實例化參數(shù)只能是指定類的子類,在泛型中還可以指定參數(shù)的下邊界,是一super關鍵字可以指定泛型實例化時的參數(shù)只能是指定類的父類。

    例如:

    [java] view plaincopyprint?
  • class?Fruit{??
  • }??
  • class?Apple?extends?Fruit{??
  • }??
  • class?Jonathan?extends?Apple{??
  • }??
  • class?Orange?extends?Fruit{??
  • }??
  • public?superTypeWildcards{??
  • ????public?static?void?writeTo(List<??super?Apple>?apples){??
  • ????????apples.add(new?Apple());??
  • ????????apples.add(new?Jonathan());??
  • }??
  • }??
  • class Fruit{ } class Apple extends Fruit{ } class Jonathan extends Apple{ } class Orange extends Fruit{ } public superTypeWildcards{public static void writeTo(List<? super Apple> apples){apples.add(new Apple());apples.add(new Jonathan()); } }


    ?

    通過? Super限制了List元素只能是Apple的父類。

    泛型下邊界還可以使用<?super T>,但是注意不能使用<Tsuper A>,即super之前的只能是泛型通配符,如:

    [java] view plaincopyprint?
  • public?class?GenericWriting{??
  • ????static?List<Apple>?apples?=?new?ArrayList<Apple>();??
  • ????static?List<Fruit>?fruits?=?new?ArrayList<Fruit>();??
  • ????static?<T>?void?writeExact(List<T>?list,?T?item){??
  • ????????list.add(item);??
  • }??
  • static?<T>?void?writeWithWildcards(List<??super?T>?list,?T?item){??
  • ????list.add(item);??
  • }??
  • static?void?f1(){??
  • ????writeExact(apples,?new?Apple());??
  • }??
  • static?void?f2(){??
  • writeWithWildcards(apples,?new?Apple());??
  • ????writeWithWildcards(fruits,?new?Apple());??
  • }??
  • public?static?void?main(String[]?args){??
  • ????f1();??
  • ????f2();??
  • }??
  • }??
  • public class GenericWriting{static List<Apple> apples = new ArrayList<Apple>();static List<Fruit> fruits = new ArrayList<Fruit>();static <T> void writeExact(List<T> list, T item){list.add(item); } static <T> void writeWithWildcards(List<? super T> list, T item){list.add(item); } static void f1(){writeExact(apples, new Apple()); } static void f2(){ writeWithWildcards(apples, new Apple());writeWithWildcards(fruits, new Apple()); } public static void main(String[] args){f1();f2(); } }


    ?

    4.無邊界的通配符:

    泛型的通配符也可以不指定邊界,沒有邊界的通配符意思是不確定參數(shù)的類型,編譯時泛型檫除類型信息,認為是Object類型。如:

    [java] view plaincopyprint?
  • public?class?UnboundedWildcard{??
  • ????static?List?list1;??
  • ????static?List<?>?list2;??
  • ????static?List<??extends?Object>?list3;??
  • ????static?void?assign1(List?list){??
  • ????????list1?=?list;??
  • ????????list2?=?list;??
  • ????????//list3?=?list;?//有未檢查轉(zhuǎn)換警告 ??
  • }???
  • static?void?assign2(List<?>?list){??
  • ????????list1?=?list;??
  • ????????list2?=?list;??
  • ????list3?=?list;??
  • }??
  • static?void?assign3(List<??extends?Object>?list){??
  • ????????list1?=?list;??
  • ????????list2?=?list;??
  • ????list3?=?list;??
  • }??
  • public?static?void?main(String[]?args){??
  • ????assign1(new?ArrayList());??
  • assign2(new?ArrayList());??
  • //assign3(new?ArrayList());?//有未檢查轉(zhuǎn)換警告??
  • assign1(new?ArrayList<String>());??
  • assign2(new?ArrayList<String>());??
  • assign3(new?ArrayList<String>());???
  • List<?>?wildList?=?new?ArrayList();??
  • assign1(wildList);??
  • assign2(wildList);??
  • assign3(wildList);???
  • }??
  • }??
  • public class UnboundedWildcard{static List list1;static List<?> list2;static List<? extends Object> list3;static void assign1(List list){list1 = list;list2 = list;//list3 = list; //有未檢查轉(zhuǎn)換警告 } static void assign2(List<?> list){list1 = list;list2 = list;list3 = list; } static void assign3(List<? extends Object> list){list1 = list;list2 = list;list3 = list; } public static void main(String[] args){assign1(new ArrayList()); assign2(new ArrayList()); //assign3(new ArrayList()); //有未檢查轉(zhuǎn)換警告 assign1(new ArrayList<String>()); assign2(new ArrayList<String>()); assign3(new ArrayList<String>()); List<?> wildList = new ArrayList(); assign1(wildList); assign2(wildList); assign3(wildList); } }


    ?

    List和List<?>的區(qū)別是:List是一個原始類型的List,它可以存放任何Object類型的對象,不需要編譯時類型檢查。List<?>等價于List<Object>,它不是一個原始類型的List,它存放一些特定類型,只是暫時還不確定是什么類型,需要編譯時類型檢查。因此List的效率要比List<?>高。

    5.實現(xiàn)泛型接口注意事項:

    由于泛型在編譯過程中檫除了參數(shù)類型信息,所以一個類不能實現(xiàn)以泛型參數(shù)區(qū)別的多個接口,如:

    [java] view plaincopyprint?
  • interface?Payable<T>{??
  • }??
  • class?Employee?implements?Payable<Employee>{??
  • }??
  • class?Hourly?extends?Employee?implements?Payable<Hourly>{??
  • }??
  • interface Payable<T>{ } class Employee implements Payable<Employee>{ } class Hourly extends Employee implements Payable<Hourly>{ }


    ?

    類Hourly無法編譯,因為由于泛型類型檫除,Payable<Employee>和Payable<Hourly>在編譯時是同一個類型Payable,因此無法同時實現(xiàn)一個接口兩次。

    6.泛型方法重載注意事項:

    由于泛型在編譯時將參數(shù)類型檫除,因此以參數(shù)類型來進行方法重載在泛型中要特別注意,如:

    [java] view plaincopyprint?
  • public?class?GenericMethod<W,T>{??
  • ????void?f(List<T>?v)?{??
  • }??
  • void?f(List<W>?v){??
  • }??
  • }??
  • public class GenericMethod<W,T>{void f(List<T> v) { } void f(List<W> v){ } }


    ?

    無法通過編譯,因為泛型檫除類型信息,上面兩個方法的參數(shù)都被看作為Object類型,使用參數(shù)類型已經(jīng)無法區(qū)別上面兩個方法,因此無法重載。

    7.泛型中的自綁定:

    通常情況下,一個類無法直接繼承一個泛型參數(shù),但是你可以通過繼承一個聲明泛型參數(shù)的類,這就是java泛型編程中的自綁定,如:

    [java] view plaincopyprint?
  • class?SelfBounded<T?extends?SelfBounded<T>>{??
  • ????T?element;??
  • ????SelfBounded<T>?set(T?arg){??
  • ????????Element?=?arg;??
  • ????????return?this;??
  • }???
  • T?get(){??
  • ????return?element;??
  • }??
  • }??
  • class?A?extends?SelfBounded<A>{??
  • }??
  • class?B?extends?SelfBounded<A>{??
  • }??
  • class?C?extends?SelfBounded<C>{??
  • ????C?setAndGet(C?arg){??
  • ????????set(arg);??
  • ????????return?get();??
  • }??
  • }??
  • public?class?SelfBounding{??
  • ????public?static?void?main(String[]?args){??
  • ????????A?a?=?new?A();??
  • ????????a.set(new?A());??
  • ????????a?=?a.set(new?A()).get();??
  • ????????a?=?a.get();??
  • ????????C?c?=?new?C();??
  • ????????C?=?c.setAndGet(new?C());??
  • }??
  • }??
  • class SelfBounded<T extends SelfBounded<T>>{T element;SelfBounded<T> set(T arg){Element = arg;return this; } T get(){return element; } } class A extends SelfBounded<A>{ } class B extends SelfBounded<A>{ } class C extends SelfBounded<C>{C setAndGet(C arg){set(arg);return get(); } } public class SelfBounding{public static void main(String[] args){A a = new A();a.set(new A());a = a.set(new A()).get();a = a.get();C c = new C();C = c.setAndGet(new C()); } }


    ?

    泛型的自綁定約束目的是用于強制繼承關系,即使用泛型參數(shù)的類的基類是相同的,強制所有人使用相同的方式使用參數(shù)基類。


    ===========

    public class Generic <T,S,R extends S>{
    public <E> E getR(E e) {
    return e;
    }

    public static void main(String[] args) {
    Generic<Integer, Object, Number> g = new Generic<Integer, Object, Number>();
    BigDecimal bd = new BigDecimal(1);
    g.getR(0.1);

    Generic<?,?,?> g1= new Generic<Integer, Object, Number>();

    List<Integer>[] iListArray = new ArrayList[10];
    }
    }


    class MyGeneric<T extends Object & Serializable > {

    }
    class YourGeneric<E,T,S,R extends S> extends Generic<T,S,R> implements List<E>{...}

    ?

    總結

    以上是生活随笔為你收集整理的java 泛型 extends 多个的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。