Ġeneriċi Java spjegati f’forma qasira b’eżempji

Jekk jogħġbok ara din il-FAQ għal aktar informazzjoni:

http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html#SECTION1

Hawn fil-qosor xi punti importanti minn din il-FAQ.

Eżempju (ta’ tip ġeneriku):

class Pair<X,Y>  { 
  private X first;
  private Y second;   public Pair(X a1, Y a2) {
    first  = a1;
    second = a2;
  }
  public X getFirst()  { return first; }
  public Y getSecond() { return second; }
  public void setFirst(X arg)  { first = arg; }
  public void setSecond(Y arg) { second = arg; }
}

Il-klassi Par għandha żewġ parametri tat-tip X u Y .  Huma sostitwiti b’argumenti tat-tip meta t-tip ġeneriku Par hija instanzjata. Per eżempju, fid-dikjarazzjoni Pair<String, Data> il-parametru tat-tip X huwa mibdul bl-argument tat-tip Spag u Y is replaced by  Data .
L-ambitu tal-identifikaturi X u Y huwa id-definizzjoni kollha tal-klassi.  F’dan l-ambitu iż-żewġ parametri tat-tip X u Y huma użati bħal dawn kienu tipi (b’xi restrizzjonijiet). Fl-eżempju ta ‘hawn fuq, il-parametri tat-tip jintużaw bħala l-argument u t-tip ta’ ritorn ta ‘metodi ta’ istanza u t-tipi ta ‘oqsma ta’ istanza.
Il-parametri tat-tip jistgħu jiġu ddikjarati bil-limiti. Il-limiti jagħtu aċċess għal metodi tat-tip mhux magħruf li jirrappreżenta l-parametru tat-tip. Fl-eżempju tagħna, aħna ma ninvokaw l-ebda metodu tat-tipi mhux magħrufa X u Y . Għal din ir-raġuni, iż-żewġ parametri tat-tip huma bla limitu.

Eżempju (ta’ tip parametrizzat konkret):

public void printPar( Pair<String,Long> par) {
  System.out.println("("+pair.getFirst()+","+pair.getSecond()+")");
} Pair<String,Long> limitu = ġdid Pair<String,Long> ("massimu",1024L);
printPair(limitu);

Eżempju (ta’ tip ta’ wildcard parametrizzat):

public void printPar( Par<?,?> par) {
  System.out.println("("+pair.getFirst()+","+pair.getSecond()+")");
} Par<?,?> limitu = ġdid Pair<String,Long> ("massimu",1024L);
printPair(limitu);

L-istanziazzjonijiet kollha ta’ tip ġeneriku jaqsmu l-istess rappreżentazzjoni tat-tip runtime, jiġifieri r-rappreżentazzjoni tat-tip mhux maħdum. Per eżempju, l-istanziazzjonijiet ta ‘tip ġeneriku Lista , bħal Lista<Data> , Lista<String> , Lista<Long> , eċċ għandhom tipi statiċi differenti fil-ħin tal-kumpilazzjoni, iżda l-istess tip dinamiku Lista waqt ir-runtime.

Cast jikkonsisti f’żewġ partijiet:

  • verifika tat-tip statika mwettqa mill-kompilatur fil-ħin tal-kumpilazzjoni u
  • verifika tat-tip dinamika mwettqa mill-magna virtwali waqt ir-runtime.

Il-parti statika tissortja kasti bla sens, li ma jistgħux jirnexxu, bħall-mitfugħa minn Spag dak Data jew minn Lista<String> dak Lista<Data> .

Il-parti dinamika tuża l-informazzjoni tat-tip runtime u twettaq verifika tat-tip waqt ir-runtime.  Hija tqajjem a ClassCastException jekk it-tip dinamiku tal-oġġett mhuwiex it-tip fil-mira (jew sottotip tat-tip fil-mira) tal-cast. Eżempji ta ‘casts b’parti dinamika huma l-cast minn Għan dak Spag jew minn Għan dak Lista<String> .  Dawn huma l-hekk imsejħa downcasts, minn supertip ‘l isfel għal sottotip.

Eżempji ta ‘tipi parametrizzati konkreti huma Lista<String> , Map<String,Data> , imma le Lista<? jestendi Numru> jew Map<String,?> .

Xi drabi huwa mistenni li a Lista<Object> ikun supertip ta’ a Lista<String> , għax Għan huwa supertip ta Spag .  This expectation stems from the fact that such a type relationship exists for arrays:  Oġġett[] huwa supertip ta String[] , għax Għan huwa supertip ta Spag . (Dan it-tip ta’ relazzjoni hija magħrufa bħala kovarjanza .) Ir-relazzjoni tas-super-subtip tat-tipi ta ‘komponenti testendi fit-tipi ta’ firxa korrispondenti. Ma teżisti l-ebda relazzjoni ta’ tip bħal din għal istanziazzjonijiet ta’ tipi ġeneriċi. (It-tipi parametrizzati huma le kovarjant.)

In-nuqqas ta’ relazzjoni super-subtip fost istanziazzjonijiet tal-istess tip ġeneriku għandu konsegwenzi varji.  Hawn eżempju.

Eżempju:

void printAll(ArrayList<Object> c) {
  for (Object o : c) 
    System.out.println(o);
} ArrayList<String> lista = ArrayList<String>();
... imla l-lista ...
printAll(lista);   // żball

A ArrayList<String> oġġett ma jistax jiġi mgħoddi bħala argument għal metodu li jitlob a ArrayList<Object> minħabba li ż-żewġ tipi huma istanziazzjonijiet tal-istess tip ġeneriku, iżda għal differenti argumenti tat-tip, u għal din ir-raġuni mhumiex kompatibbli ma’ xulxin.

Tipi parametrizzati konkreti huma istanziazzjonijiet konkreti ta ‘tip ġeneriku.  Huma kważi bħal tipi; hemm biss ftit restrizzjonijiet.  MHUX JISTGĦU jintużaw għall-għanijiet li ġejjin:

  • għall-ħolqien ta’ arrays
  • fl-immaniġġjar ta’ eċċezzjoni
  • fi klassi letterali
  • fi an istanza ta espressjoni

Arrays li jżommu elementi li t-tip tagħhom huwa tip parametrizzat konkret huma illegali.

Eżempju (ta’ tip ta’ firxa illegali):

test tal-vojt statiku () {
  Par<Iteger,Integer>[] intPairArr = ġdid Par<Integer,Integer>[10] ; // żball
  addElements(intPairArr); 
  Pair<Integer,Integer> pair = intPairArr[1];
  Integer i = pair.getFirst();
  pair.setSecond(i);
}
static void addElements ( Oġġett[] objArr) {
  objArr[0] = new Pair<Integer,Integer>(0,0);
  objArr[1] = new Pair<String,String>("","");      // should fail with ArrayStoreException
}

Il-kompilatur jipprojbixxi l-ħolqien ta ‘arrays li t-tip ta’ komponent tagħhom huwa tip parametrizzat konkret, bħal Par<Integer,Integer> fl-eżempju tagħna.  Iddiskutejna fl-entrata preċedenti għaliex huwa raġonevoli li l-kompilatur jikkwalifika a Par<Iteger,Integer>[] bħala illegali.  Il-problema ewlenija hija li l-kompilatur u s-sistema runtime għandhom jiżguraw li firxa hija a omoġenju sekwenza ta’ elementi ta’ l-istess tip.  Waħda mill-kontrolli tat-tip, jiġifieri l-kontroll tal-firxa tal-maħżen imwettaq mill-magna virtwali waqt ir-runtime, tonqos milli tiskopri l-inserzjoni offensiva ta ‘element aljeni. Fl-eżempju t-tieni inserzjoni fil- addElements metodu għandu jonqos, minħabba li kienu qed iżidu par ta ‘kordi għal firxa ta’ valuri integrali, iżda ma jonqosx kif mistenni. Ir-raġunijiet ġew diskussi fl-entrata preċedenti.

Jekk ma nistgħux nużaw arrays li jżommu elementi li t-tip tagħhom huwa tip parametrizzat konkret, x’nużaw bħala soluzzjoni?

Ejja nikkunsidraw 3 soluzzjonijiet konċepibbli:

  • firxa ta ‘tipi mhux maħduma
  • firxa ta’ tip parametrizzat ta’ wildcard bla limitu
  • ġbir minflok firxa

Filwaqt li arrays ta’ tipi parametrizzati tal-konkrit huma illegali, kollezzjonijiet ta’ tipi parametrizzati tal-konkrit huma permessi.

Tip parametrizzat ta’ wildcard huwa instanzjazzjoni ta’ tip ġeneriku fejn mill-inqas argument tat-tip wieħed huwa wildcard.  Eżempji ta ‘tipi parametrizzati wildcard huma Ġbir<?> , Lista<? jestendi Numru> , Komparatur<? super String> u Pair<String,?> . Tip parametrizzat wildcard jindika familja ta’ tipi li jinkludu istanziazzjonijiet konkreti ta’ tip ġeneriku.  It-tip ta’ wildcard li qed tintuża jiddetermina liema tipi parametrizzati konkreti jappartjenu għall-familja.  Per eżempju, it-tip parametrizzat wildcard Ġbir<?> tindika l-familja tal-istanziazzjonijiet kollha tal- Ġbir interface irrispettivament mill-argument tat-tip.  It-tip parametrizzat tal-wildcard Lista<? jestendi Numru> denotes the family of all list types where the element type is a subtype of  Numru .  It-tip parametrizzat tal-wildcard Komparatur<? super String> hija l-familja tal-istanziazzjonijiet kollha tal- Komparatur interface għal tipi ta’ argument tat-tip li huma supertipi ta’ Spag.

Tip parametrizzat wildcard mhuwiex tip fis-sens regolari (differenti minn klassi/interface mhux parametrizzata jew tip mhux maħdum).

Tipi parametrizzati wildcard jistgħu jintużaw għat-tajpjar (bħal klassijiet u interfaces mhux parametrizzati):

  • bħala argument u tipi ta ‘ritorn ta’ metodi
  • bħala tip ta’ qasam jew varjabbli ta’ referenza lokali
  • bħala tip ta ‘komponent ta’ argument tat-tip arrayas ta ‘tipi parametrizzati oħra
  • bħala tip ta’ mira fil-casts

Mhux biss it-tipi jistgħu jkunu ġeneriċi, iżda l-metodi jistgħu jkunu ġeneriċi wkoll. Metodi statiċi u mhux statiċi kif ukoll kostrutturi jista ‘jkollhom parametri tat-tip. Is-sintassi għad-dikjarazzjoni tal-parametri tat-tip formali hija simili għas-sintassi għal tipi ġeneriċi. Is-sezzjoni tal-parametru tat-tip hija delimitata minn parentesi angolari u tidher qabel it-tip ta ‘ritorn tal-metodu. Is-sintassi u t-tifsira tiegħu huma identiċi għal-lista tal-parametri tat-tip ta’ tip ġeneriku.

Hawn hu l-eżempju ta ‘ġeneriku max metodu li jikkalkula l-akbar valur f’ġabra ta’ elementi ta’ tip mhux magħruf A .

Eżempju (ta’ metodu ġeneriku):

Kollezzjonijiet tal-klassi {
  public static <A jestendi Komparable<A>> A max(Kollezzjoni< A > xs) {
    Iterator< A > xi = xs.iterator();
    A w = xi.li jmiss ();
    while (xi.hasNext()) {
      A x = xi.li jmiss ();
      if (w.compareTo(x) < 0) w = x;
    }
    return w;
  }
} 

Il- max metodu għandu parametru tat-tip wieħed, imsemmi A .  Huwa detentur tal-post għat-tip ta ‘element tal-ġbir li jaħdem fuqu l-metodu. Il-parametru tat-tip għandu bound; għandu jkun tip li huwa sottotip ta Komparabbli<A>

Eżempju (tal-istess tip ġeneriku, din id-darba ma limiti):

interface pubbliku Kumparabbli<T> {
  public int compareTo(T arg);
}
klassi pubblika TreeMap<Key testendi Comparable<Key> ,Data>{
  private static class Entry<K,V> {
     K key;
     V value;
     Entry<K,V> left = null;
     Entry<K,V> right = null;
     Entry<K,V> parent;
  }
  private transient Entry<Key,Data> root = null;
  ...
  private Entry<Key,Data> getEntry(Key key) {
     Entry<Key,Data> p = root;
     Key k = key;
     while (p != null) {
       int cmp = k. paragunTo(p.key) ; 
       if (cmp == 0)
         return p;
       else if (cmp < 0)
         p = p.left;
       else 
         p = p.right; 
     }
     return null;
  }
  public boolean containsKey(Key key) {
     return getEntry(key) != null;
  }
  ...
}

Fl-eżempju ta ‘hawn fuq, il-parametru tat-tip Ewlenin għandha l-irbit Komparabbli<Key> .  L-ispeċifikazzjoni ta’ rbit għandha żewġ effetti:

  • Jagħti aċċess għall-metodi li l-irbit jispeċifika .  Fl-eżempju, l-irbit Komparabbli<Key> jagħti aċċess għall- qabbelTo metodu li rridu ninvokaw fl-implimentazzjoni ta tagħna TreeMap klassi.
  • Tipi biss “fil-limiti” jistgħu jintużaw għall-instanzjazzjoni tat-tip ġeneriku.   In the example, a parameterized type such as TreeMap<Number,String> tkun miċħuda, minħabba li t-tip Numru mhix sottotip ta’ Komparabbli<Number> .  Tip parametrizzat simili TreeMap<String,String> ikun aċċettat, minħabba li t-tip String huwa fil-limiti, jiġifieri huwa subtip ta Komparabbli<String> .

Il-klassijiet, l-interfaces, u t-tipi kollha enum jistgħu jintużaw bħala parametru tat-tip marbut, inklużi tipi nested u interni.  La tipi primittivi u lanqas tipi ta’ firxa ma jintużaw bħala parametru tat-tip marbut.

Eżempji (tal-limiti tal-parametri tat-tip):

klassi X0 <T testendi int > { ... }      // żball
klassi X1 <T testendi Oġġett[] > { ... } // żball
klassi X2 <T testendi Numru > { ... }
klassi X3 <T testendi Spag > { ... }
klassi X4 <T testendi Jiġi mħaddma > { ... }
klassi X5 <T testendi Thread.State > { ... }
klassi X6 <T testendi Lista > { ... }
klassi X7 <T testendi Lista<String> > { ... }
klassi X8 <T testendi Lista<? jestendi Numru> > { ... }
klassi X9 <T testendi Komparabbli<? super Numru> > { ... }
klassi X10<T testendi Mappa.Dħul<?,?> > { ... }

Il-kampjun tal-kodiċi juri li tipi primittivi bħal int u tipi ta’ firxa bħal Oġġett[] mhumiex permessi bħala parametru tat-tip marbut.

Tipi ta ‘klassi, bħal Numru jew Spag , u tipi ta’ interface, bħal Jiġi mħaddma , huma permessi bħala parametru tat-tip marbut.

Enum tipi, bħal Thread.State huma permessi wkoll bħala parametru tat-tip marbut. Thread.State huwa eżempju ta’ tip ibbed użat bħala parametru tat-tip marbut.  Tipi interni mhux statiċi huma permessi wkoll.

Tipi mhux ipproċessati huma permessi bħala parametru tat-tip marbut; Lista huwa eżempju.

Tipi parametrizzati huma permessi bħala parametru tat-tip marbut, inklużi tipi parametrizzati konkreti bħal Lista<String> , tipi parametrizzati wildcard delimitati bħal Lista<? jestendi Numru> u Komparabbli<? super Long> , u tipi parametrizzati wildcard bla limitu bħal Mappa.Dħul<?,?> .  Limitat li huwa tip parametrizzat bħala wildcard jippermetti bħala argument tat-tip it-tipi kollha li jappartjenu għall-familja tat-tip li tindika l-wildcard.  It-tip wildcard parametrizzat marbut jagħti biss aċċess ristrett għall-oqsma u l-metodi; ir-restrizzjonijiet jiddependu fuq it-tip ta’ wildcard.

Eżempju (ta’ tip parametrizzat bħala wildcard bħala parametru tat-tip marbut):

klassi X< T testendi List<? jestendi Numru> > {
  public void someMethod(T t) {
    t.add(new Long(0L));    // żball
    Number n = t.remove(0);
  }
}
Test tal-klassi {
  public static void main(String[] args) {
     X<ArrayList< Twil >>   x1 = new X<ArrayList<Long>>(); 
     X<ArrayList< Spag >> x2 = ġdid X<ArrayList<String>>(); // żball
  }
}

Varjabbli ta’ referenza tat-tip T (il-parametru tat-tip) huma ttrattati bħal varjabbli ta’ referenza ta’ tip wildcard (il-parametru tat-tip marbut).  Fl-eżempju tagħna l-konsegwenza hija li l-kompilatur jirrifjuta l-invokazzjoni ta ‘metodi li jieħdu argument tat-tip “mhux magħruf” li l-parametru tat-tip jirrappreżenta, bħal Lista.add , minħabba li l-irbit huwa tip parametrizzat bħala wildcard b’limitu ta’ fuq.
Fl-istess ħin l-irbit Lista<? jestendi Numru> jiddetermina t-tipi li jistgħu jintużaw bħala argumenti tat-tip. Il-kompilatur jaċċetta l-argumenti tat-tip kollha li jappartjenu għall-familja tat-tip Lista<? jestendi Numru> , jiġifieri, is-sottotipi kollha ta ‘ Lista b’argument tat-tip li huwa sottotip ta’ Numru .

Parametru tat-tip jista’ jintuża bħala l-irbit ta’ parametru tat-tip ieħor.

Eżempju (ta’ parametru tat-tip użat bħala parametru tat-tip marbut):

klassi Triple <T> {
  private T fst, snd, trd;
  public < U testendi T , V testendi T , W testendi T > Triplu(U arg1, V arg2, W arg3) {
    fst = arg1;
    snd = arg2;
    trd = arg3;
  }
}

F’dan l-eżempju l-parametru tat-tip T tal-klassi parametrizzata tintuża bħala marbuta tal-parametri tat-tip U ,  V u W ta’ metodu ta’ istanza parametrizzata ta’ dik il-klassi.

Opportunitajiet ulterjuri għall-użu ta’ parametri tat-tip bħala limiti ta’ parametri ta’ tip ieħor jinkludu sitwazzjonijiet fejn tip ibbed huwa definit ġewwa tip ġeneriku jew klassi lokali hija definita ġewwa metodu ġeneriku.  Huwa saħansitra permess li jintuża parametru tat-tip bħala marbut ma’ parametru tat-tip ieħor fl-istess sezzjoni tal-parametru tat-tip.

Marbuta li hija klassi tagħti aċċess lill-membri pubbliċi kollha tagħha, jiġifieri, oqsma pubbliċi, metodi, u tipi ibbed. Il-kostrutturi biss ma jsirux aċċessibbli, għax m’hemm l-ebda garanzija li subklassi tal-irbit ikollha l-istess kostrutturi bħall-irbit.

Eżempju (ta’ klassi użata bħala rbit ta’ parametru tat-tip):

klassi pubblika SuperKlassi {     // static members
    public enum EnumType {THIS, THAT}
    public static Object staticField;
    public static void staticMethod() { ... }

    // non-static members
    public class InnerClass { ... }
    public Object nonStaticField;
    public void nonStaticMethod() { ... }

    // constructors
    public SuperClass() { ... }

    // private members
    private Object privateField; 

    ...
}

klassi finali pubblika SomeClass<T testendi SuperKlassi > {
    private T object;
    public SomeClass(T t) { object = t; } 

    public String toString() {
        return
         "static nested type    : "+T.EnumType.class+"\n" 
        +"static field          : "+T.staticField+"\n"
        +"static method         : "+T.staticMethod()+"\n"
        +"non-static nested type: "+T.InnerClass.class+"\n"
        +"non-static field      : "+object.nonStaticField+"\n"
        +"non-static method     : "+object.nonStaticMethod()+"\n"
        +"constructor           : "+(new T())+"\n"                    // error
        +"private member        : "+object.privateField+"\n"          // error 
        ;
    }
}

L-irbit SuperKlassi jagħti aċċess għat-tipi nested tiegħu, l-oqsma u l-metodi statiċi u l-oqsma u l-metodi mhux statiċi.  Il-kostruttur biss mhuwiex aċċessibbli.  Dan għaliex il-kostrutturi ma jintirtux. Kull subklassi tiddefinixxi l-kostrutturi tagħha stess u m’għandhiex għalfejn tappoġġja l-kostrutturi tas-superklassi tagħha.  Għalhekk m’hemm l-ebda garanzija li subklassi ta ‘ SuperKlassi se jkollu l-istess kostruttur bħas-superklassi tiegħu.

Il-kuntest li fih Enum<E jestendi Enum<E>> “jidher hija d-dikjarazzjoni tal- Enum klassi fil-pakkett java.lang :

klassi astratta pubblika Enum<E jestendi Enum<E>> {
  ...
}

It-tip Enum hija l-klassi bażi komuni tat-tipi kollha ta’ enumerazzjoni.  Fil-Java tip ta’ enumerazzjoni bħal Kulur tiġi tradotta fi klassi Kulur li testendi Enum<Color> . L-iskop tas-superklassi Enum huwa li tipprovdi funzjonalità li hija komuni għat-tipi kollha ta’ enumerazzjoni.

Hawn skeċċ tal-klassi Enum :

klassi astratta pubblika Enum< E testendi Enum<E>> timplimenta Comparable< E >, Serjalizzabbli {
  private final String name;
  public  final String name() { ... }   private final int ordinal;
  public  final int ordinal() { ... }

  protected Enum(String name, int ordinal) { ... }

  public String           toString() { ... }
  public final boolean    equals(Object other) { ... }
  public final int        hashCode() { ... }
  protected final Object  clone() throws CloneNotSupportedException { ... }
  public final int        compareTo( E o) { ... }

  public final Class< E > getDeclaringClass() { ... }
  public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { ... }
}

Il-karatteristika sorprendenti fid-dikjarazzjoni “ Enum<E jestendi Enum<E>> ” huwa l-fatt li l-klassi ġdida definita Enum u l-parametru tat-tip definit ġdid tiegħu E jidhru fil-limiti ta’ dak l-istess parametru tat-tip.  Dan ifisser li l- Enum it-tip għandu jiġi instanzjat għal wieħed mis-sottotipi tiegħu.  Sabiex tifhem għaliex dan jagħmel sens, ikkunsidra li kull tip ta ‘enum huwa tradott f’sottotip ta’ Enum .

Hawn hu t-tip ta’ enum maħdum Kulur :

enum Kulur {AĦMAR, BLUE, AĦDAR}

Il-kompilatur jittraduċiha fil-klassi li ġejja:

klassi finali pubblika Kulur testendi Enum<Color> {
  public static final Color[] values() { return (Color[])$VALUES.clone(); }
  public static Color valueOf(String name) { ... }   private Color(String s, int i) { super(s, i); }

  public static final Color RED;
  public static final Color BLUE;
  public static final Color GREEN;

  private static final Color $VALUES[];

  static {
    RED = new Color("RED", 0);
    BLUE = new Color("BLUE", 1);
    GREEN = new Color("GREEN", 2);
    $VALUES = (new Color[] { RED, BLUE, GREEN });
  }
}

Il-wirt għandu l-effett li l- Kulur tip jiret il-metodi kollha implimentati fi Enum<Color> .  Fosthom hemm il- qabbelTo metodu.  Il- Kulur. qabbelTo metodu għandu probabbilment jieħu a Kulur bħala argument.  Sabiex dan iseħħ klassi Enum huwa ġeneriku u l- Enum.compareTo metodu jieħu Enum parametru tat-tip ‘s E bħala argument.  Bħala riżultat, ittajpja Kulur derivati ​​minn Enum<Color> jiret a qabbelTo metodu li jieħu a Kulur kif u argument, eżattament kif suppost.
Jekk nissekkjaw id-dikjarazzjoni “ Enum<E jestendi Enum<E>> “Nistgħu naraw li dan il-mudell għandu diversi aspetti.

L-ewwel, hemm il-fatt li l-parametru tat-tip marbut huwa t-tip innifsu: “ Enum <E jestendi Enum <E>> “. Jagħmel ċert li biss sottotipi ta ‘tip Enum huma permessi bħala argumenti tat-tip. (Teoretikament, ittajpja Enum jista ‘jiġi istantanjat fuq innifsu, bħal fi Enum<Enum> , iżda dan żgur mhuwiex maħsub u huwa diffiċli li wieħed jimmaġina sitwazzjoni li fiha tali instanzjazzjoni tkun utli.)

It-tieni, hemm il-fatt li t-tip marbut mal-parametru huwa t-tip parametrizzat Enum <E> , li juża l-parametru tat-tip E bħala l-argument tat-tip tal-legat. Din id-dikjarazzjoni tiżgura li r-relazzjoni ta’ wirt bejn sottotip u istanziazzjoni ta’ Enum huwa tal-forma X jestendi Enum<X> “. Sottotip bħal “ X jestendi Enum<Y> ” ma tistax tiġi ddikjarata minħabba l-argument tat-tip Y ma jkunx fil-limiti; sottotipi biss ta Enum<X> huma fil-limiti.

It-tielet, hemm il-fatt li Enum hija ġenerika fl-ewwel lok.  Dan ifisser li xi wħud mill-metodi tal-klassi Enum tieħu argument jew tirritorna valur ta’ tip mhux magħruf (jew inkella tiddependi fuq tip mhux magħruf). Kif nafu diġà, dan it-tip mhux magħruf aktar tard se jkun sottotip X ta Enum<X> .  Għalhekk, fit-tip parametrizzat Enum<X> , dawn il-metodi jinvolvu s-sottotip X , u jintirtu fis-sottotip X .  Il- qabbelTo metodu huwa eżempju ta ‘tali metodu; tintiret mis-superklassi f’kull subklassi u għandha firma speċifika tas-subklassi f’kull każ.

Fil-qosor, id-dikjarazzjoni “ Enum<E jestendi Enum<E>> ” jistgħu jiġu deċifrati bħala: Enum huwa tip ġeneriku li jista ‘jiġi instanzjat biss għas-sottotipi tiegħu, u dawk is-sottotipi se jirtu xi metodi utli, li wħud minnhom jieħdu argumenti speċifiċi tas-sottotip (jew inkella jiddependu fuq is-sottotip).

Parametri tat-Tip tal-Klassijiet Limitati Inferjuri

Il-parametri tat-tip jista’ jkollhom diversi limiti, bħal fi klassi Box<T testendi Number> {...} . Iżda parametru tat-tip jista’ jkollu l-ebda limitu t’isfel, jiġifieri, kostruzzjoni bħal klassi Box<T kbir Numru> {...} mhux permess.  Għaliex le?  It-tweġiba hija: huwa inutli għax ma jixtrilek xejn, kieku permess.  Ejja naraw għaliex il-parametri tat-tip ta’ klassijiet tal-limiti inferjuri huma konfużi billi nesploraw xi tfisser limitu ta’ fuq fuq parametru tat-tip.

Il-limitu ta’ fuq fuq parametru tat-tip għandu tliet effetti:

    1. Instanzjazzjoni Ristretta. Il-limitu ta’ fuq jirrestrinġi s-sett ta’ tipi li jistgħu jintużaw għall-instanzjazzjoni tat-tip ġeneriku.  Jekk niddikjaraw a klassi Box<T testendi Number> {...} allura l-kompilatur jiżgura li biss sottotipi ta Numru jista’ jintuża bħala argument tat-tip.  Jiġifieri a Kaxxa<Number> jew a Box<Long> huwa permess, iżda a Kaxxa<Object> jew Box<String> tkun miċħuda

Eżempju (ta’ instanzjazzjoni ristretta minħabba limitu ta’ fuq fuq parametru tat-tip):
class Box<T extends Number> { 
   private T value; 
   public Box(T t) { value = t; } 
   ...
}  Test tal-klassi { 
   public static void main(String[] args) { 
       Box<Long>    boxOfLong   = new Box<Long>(0L);   // multa
       Box<String>  boxOfString = new Box<String>(""); // żball: String mhix fil-limiti
   }
}

  1. Aċċess Għal Membri Mhux Statiċi. Il-limitu ta’ fuq jagħti aċċess għall-metodi u l-oqsma pubbliċi mhux statiċi kollha tal-limitu ta’ fuq.  Fl-implimentazzjoni ta’ tagħna klassi Box<T testendi Number> {...} nistgħu ninvokaw il-metodi pubbliċi kollha mhux statiċi definiti fil-klassi Numru , bħal intValur() pereżempju.  Mingħajr il-limitu ta’ fuq il-kompilatur jirrifjuta kwalunkwe invokazzjoni bħal din. Eżempju (ta’ aċċess għal membri mhux statiċi minħabba limitu ta’ fuq fuq parametru tat-tip):

class Box<T extends Number> { 
   private T value; 
   public Box(T t) { value = t; } 
   public int increment() { return value.intValue()+1; } // <= ikun żball mingħajr in-Numru marbut
   ...
} 

    1. Tħassir tat-Tip. Il-limitu ta’ fuq l-aktar fuq ix-xellug jintuża għat-tħassir tat-tip u jissostitwixxi l-parametru tat-tip fil-kodiċi tal-byte.  Fil tagħna klassi Box<T testendi Number> {...} l-okkorrenzi kollha ta T tkun sostitwita bil-limitu ta’ fuq Numru .  Per eżempju, jekk klassi Kaxxa għandha qasam privat tat-tip T u metodu sett vojt (kontenut T) għall-issettjar ta ‘dan il-qasam privat, allura l-qasam ikun tat-tip Numru wara tħassir tat-tip u l-metodu jiġi tradott għal metodu sett null (kontenut tan-Numru) .

Eżempju (tal-użu tal-limitu ta’ fuq fuq parametru tat-tip fit-tħassir tat-tip – qabel tħassir tat-tip):
klassi Box< T testendi Numru > { 
   privat T valur; 
   public Box( T t) { valur = t; } 
   ...
} 

      Eżempju (tal-użu tal-limitu ta’ fuq fuq parametru tat-tip fit-tħassir tat-tip –

wara

      tħassir tat-tip):

 

Kaxxa tal-klassi { 
   privat Numru valur; 
   public Box( Numru t) { valur = t; } 
   ...
}

    Barra minn hekk, il-limitu ta ‘fuq l-aktar fuq ix-xellug jidher f’postijiet oħra, bħal casts imdaħħla awtomatikament u metodi ta’ pont.

Kieku limiti aktar baxxi kienu permessi fuq il-parametri tat-tip, liema effetti sekondarji jkollhom jew għandhom ikollhom? Jekk kostruzzjoni bħal klassi Box<T kbir Numru> {...} kienu permessi, xi jfisser?  Xi jkunu l-effetti sekondarji 3 ta ‘limitu ta’ parametru tat-tip ta ‘fuq – instanzjazzjoni ristretta, aċċess għal membru mhux statiku, tħassir tat-tip – tfisser għal limitu t’isfel?

Instanziazzjonijiet Ristretti. Il-kompilatur jista’ jirrestrinġi s-sett ta’ tipi li jistgħu jintużaw għall-instanzjazzjoni tat-tip ġeneriku b’parametru tat-tip marbut aktar baxx.  Per eżempju, il-kompilatur jista ‘jippermetti istanziazzjonijiet bħal Kaxxa<Number> u Kaxxa<Object> minn a Box<T kbir Numru> u tirrifjuta istanziazzjonijiet bħal Box<Long> jew Kaxxa<Qasir> .  Dan ikun effett konformi mal-effett sekondarju restrittiv deskritt għal limiti ta’ parametru tat-tip ta’ fuq.

Aċċess Għal Membri Mhux Statiċi. Limitu ta’ parametru tat-tip aktar baxx ma jagħtix aċċess għal xi metodi partikolari lil hinn minn dawk li ntirtu mill-klassi Għan . Fl-eżempju ta Box<T kbir Numru> is-supertipi ta Numru m’għandhom xejn komuni, ħlief li huma tipi ta’ referenza u għalhekk sottotipi ta’ Għan .  Il-kompilatur ma jistax jassumi li l-qasam tat-tip T huwa tat-tip Numru jew sottotip tiegħu.  Minflok, il-qasam tat-tip T jista ‘jkun ta’ kwalunkwe supertip ta ‘ Numru , bħal Serjalizzabbli jew Għan .  L-invokazzjoni ta ‘metodu bħal intValur() m’għadux tip-safe u l-kompilatur ikollu jirrifjutah. Bħala konsegwenza, il-limitu tal-parametru tat-tip aktar baxx ma jagħtix aċċess għal membri mhux statiċi lil hinn minn dawk definiti fil-klassi Għan u għalhekk għandu l-istess effett bħal “no bound”.

Tħassir tat-Tip .  Wara din il-linja tal-loġika, ma jagħmilx sens li tissostitwixxi l-okkorrenzi tal-parametru tat-tip bil-limitu l-aktar tax-xellug tiegħu.  Jiddikjara metodu bħall-kostruttur Kaxxa ( T t) bħala kostruttur Kaxxa ( Numru t) ma jagħmilx sens, meta wieħed iqis li T huwa mibdul b’supertip ta’ Numru .  An Għan jista ‘jiġi mgħoddi ġustament lill-kostruttur f’istanziazzjoni Kaxxa<Object> u l-kostruttur jiċħadha.  Dan ikun ħażin ħażin.   Għalhekk, it-tħassir tat-tip jissostitwixxi l-okkorrenzi kollha tal-varjabbli tat-tip T skond it-tip Għan , u mhux bil-limitu t’isfel tagħha.  Għal darb’oħra, il-limitu t’isfel ikollu l-istess effett bħal “l-ebda limitu”.

Tixtieq insemmu dak li jkun ifisser jekk it-tnejn aktar baxxi _u_ limiti ta’ fuq kienu permessi?   Personalment, lanqas irrid naħseb dwarha u nippreferi nippreżentaha taħt “mhux maniġġabbli”, jekk tippermetti.

L-aħħar linja hija: dak kollu li “ kbir ” marbuta kieku tixtri inti hija r-restrizzjoni li supertipi biss ta ‘ Numru jistgħu jintużaw bħala argumenti tat-tip.  U anke dan huwa spiss mifhum ħażin.  MA jfissirx li klassi Box<T super Number> {...} fih biss każijiet ta’ supertipi ta’ Numru .  Pjuttost bil-maqlub – kif juri l-eżempju hawn taħt!

Eżempju (tal-użu tal-limitu ta’ fuq fuq parametru tat-tip fit-tħassir tat-tip – qabel tħassir tat-tip):

klassi Box< T super Numru > {
   privat T valur;
   public Box( T t) { valur = t; }
   ...
}

Eżempju (tal-użu tal-limitu ta’ fuq fuq parametru tat-tip fit-tħassir tat-tip – wara tħassir tat-tip):

Kaxxa tal-klassi {
   privat Għan valur;
   public Box( Għan t) { valur = t; }
   ...
}

A klassi Box<T kbir Numru> {...} tkun tradotta bit-tħassir tat-tip għal a Kaxxa li jkun fih an Għan qasam u l-kostruttur tiegħu jiġi tradott għal Kaxxa (Oġġett t) . Dik hija fundamentalment differenti minn a klassi Box<T testendi Numru> {...} , li tkun tradotta għal a Kaxxa li jkun fih a Numru qasam u l-kostruttur tiegħu jiġi tradott għal Kaxxa (Numru t) . Konsegwentement, a Kaxxa<Number> instanzjat minn a klassi Box<T testendi Number> {...} ikun differenti minn a Kaxxa<Number> istanziazzjoni minn a klassi Box<T super Number> {...} , li x’aktarx tikkawża konfużjoni.  Għal din ir-raġuni limiti aktar baxxi ma jagħmlux sens fuq parametri tat-tip tal-klassijiet.

 


 

Parametri tat-Tip tal-Metodi Limitati Inferjuri

Flimkien mal-metodi u t-tipi ta’ argumenti tagħhom, parametru tat-tip b’limitu aktar baxx jista’ kultant ikun utli.

Eżempju (ta’ metodu li jibbenefika minn parametru tat-tip b’limitu aktar baxx):

klassi Pair<X,Y> {
   private X first;
   private Y second;
   ...
   public < Super X , B super Y > B addToMap(Map<A,B> mappa) { // żball: parametru tat-tip ma jistax ikollu limitu inferjuri
      return map.put(first, second);
   }
}
Test tal-klassi { 
   public static void main(String[] args) { 
     Pair<String,Long> pair = new Pair<>("ABC",42L);
     Map<CharSequence, Number> map = HashMap<CharSequence, Number>();
     Number number = pair.addToMap(map);
   }
}

Il- addToMap() metodu jżid il-kontenut tal-par għal mappa.  Kwalunkwe mappa li tista ‘żżomm supertipi ta’ X u Y tagħmel.  Il-mappa poġġi () metodu jirritorna l-valur misjub fil-mappa għaċ-ċavetta mogħtija, jekk diġà hemm dħul ta ‘valur ewlieni għaċ-ċavetta fil-mappa.  Il-valur tar-ritorn tal-mappa poġġi () metodu għandu jintbagħat lura mill- addToMap() metodu.  Taħt dawn iċ-ċirkostanzi wieħed jixtieq jiddikjara l-metodu kif muri hawn fuq: Il-mappa hija parametrizzata b’supertipi tal-parametri tat-tip tal-par u l- addToMap() It-tip ta’ ritorn tal-metodu huwa t-tip ta’ valur tal-mappa.

Peress li l-kompilatur ma jippermettix limiti aktar baxxi fuq il-parametri tat-tip neħtieġu work-around.

Soluzzjoni waħda li tiġi f’moħħna hija l-użu ta’ wildcard, minħabba li l-wildcards jista’ jkollhom limitu inferjuri.  Hawnhekk huwa work-around bl-użu ta ‘wildcard.

Eżempju (ta’ soluzzjoni għall-eżempju preċedenti bl-użu ta’ wildcards):

klassi Pair<X,Y> {
   private X first;
   private Y second;
   ...
   public Għan addToMap(Map< ? Super X , ? super Y mappa >) { 
      return map.put(first, second);
   }
}
Test tal-klassi { 
   public static void main(String[] args) { 
     Pair<String,Long> pair = new Pair<>("ABC",42L);
     Map<CharSequence, Number> map = HashMap<CharSequence, Number>();
     Number number = (Numru) pair.addToMap(mappa);
   }
}

Taħdem, ħlief li m’hemm l-ebda mod biex tiddikjara t-tip ta ‘ritorn kif mixtieq.  Ikun is-supertip ta Y li l-kompilatur jaqbad mit-tip tal-mappa, iżda m’hemm l-ebda sintassi biex tiġi speċifikata.  M’għandniex niddikjaraw it-tip ta’ ritorn a “ ? super Y “, għax “ ? super Y ” hija wildcard u mhux tip u għalhekk mhux permess bħala tip ta ‘ritorn. M’għandniex għażla u għandna nużaw Għan minflok bħala tip ta ‘ritorn tal-metodu tagħna.  Dan it-tip ta’ ritorn pjuttost mhux speċifiku min-naħa tiegħu jġiegħel lil min iċempel tal- addToMap() metodu fis-ikkastjar tal-valur tar-ritorn ‘l isfel minn Għan għat-tip attwali tagħha.  Dan mhux eżattament dak li kellna f’moħħna.

Ħidma oħra hija l-użu ta ‘metodi statiċi.  Hawnhekk huwa work-around b’metodu statiku minflok mhux statiku.

Eżempju (ta’ soluzzjoni għall-eżempju preċedenti bl-użu ta’ metodu statiku):

klassi Pair<X,Y> {
   private X first;
   private Y second;
   ...
   public statiku < A , B ,X testendi A ,Y testendi B > B addToMap(Par<X,Y> par, Map< A , B mappa >) {
      return map.put(pair.first,pair.second);
   }
}
Test tal-klassi { 
   public static void main(String[] args) { 
     Pair<String,Long> pair = new Pair<>("ABC",42L);
     Map<CharSequence, Number> map = HashMap<CharSequence, Number>();
     Number number = Par .addToMap( par ,mappa);
   }
}

Il-ġeneriku addToMap() metodu għandu erba ‘parametri tat-tip: żewġ placeholders X u Y għat-tip tal-par u żewġ placeholders A u B għat-tip tal-mappa. A u B huma supertipi ta X u Y , għax X u Y   are declared with A u B bħala l-limiti ta’ fuq tagħhom. (Innota, li l-parametri tat-tip tal-metodu ġeneriku X u Y m’għandha x’taqsam xejn mal- Par tal-klassi X u Y parametri.  L-ismijiet X u Y jerġgħu jintużaw għall-metodu ġeneriku biex tagħmilhom faċilment rikonoxxibbli bħala l-parametri tat-tip tal-par. Bl-użu ta ‘erba’ parametri tat-tip nistgħu niddikjaraw it-tip ta ‘ritorn preċiż kif mixtieq: huwa l-istess tip bħat-tip ta’ valur tal-mappa.

Eżempju (ta ‘użu illegali tal-parametru tat-tip f’kuntest statiku ta’ klassi ġenerika):

klassi SomeClass <T> {
  // initializer statiku, qasam statiku, metodu statiku
  statiku {
    SomeClass< T Test > = ġdid SomeClass< T >(); // żball
  }
  privat statiku T globalInfo;          // żball
  public  statiku T getGlobalInfo() {        // żball
    return globalInfo;
  }
  // initializer mhux statiku, qasam mhux statiku, metodu mhux statiku
  { 
    SomeClass< T Test > = ġdid SomeClass< T >();
  }
  privat        T localInfo;
  public         T getLocalInfo() { 
    return localInfo;
  }
  // tipi nested statiċi
  public statiku klassi Il-falliment jestendi l-Eċċezzjoni {
    private final T info;           // żball
    public Failure( T t) { info = t; }      // żball
    public T getInfo() { return info; }    // żball
   }
  privat interface Kopjabbli {
    T copy();                       // żball
  }
  privat enum Stat {
    VALID, INVALID;
    privat T info; // żball
    public void setInfo( T t) { info = t; } // żball
    public T getInfo() { return info; }    // żball
  }
  // tipi nested mhux statiċi
  public klassi Aċċessor {
    public T getInfo () { return localInfo; }
  }
}

L-eżempju juri li l-parametru tat-tip ma jistax jintuża fil-kuntest statiku ta ‘klassi ġenerika.  Juri wkoll li l-interfaces nested u t-tipi enum huma kkunsidrati bħala membri tat-tip statiku tal-klassi.  Klassijiet interni biss, jiġifieri klassijiet ibdew mhux statiċi, jistgħu jużaw il-parametru tat-tip tal-klassi ġenerika li tinkludi.

L-ambitu tal-parametru tat-tip ta’ interface huwa d-definizzjoni sħiħa ta’ l-interface, ħlief kwalunkwe qasam jew tipi nested.  Dan huwa minħabba li l-oqsma u t-tipi nested definiti f’interface huma impliċitament statiċi.

Eżempju (ta ‘użu illegali ta’ parametru tat-tip f’interface ġenerika):

interface SomeInterface <T> {
  // qasam
  SomeClass< T Valur > = ġdid SomeClass< T >();  // żball
  // tip nested
  klassi Aċċessor {
    public T getInfo() {            // żball
      return value.getGlobalInfo();
    }
  }
  // metodi
  T getValur();
}

L-eżempju juri li l-oqsma ta ‘interface huma impliċitament statiċi, sabiex il-parametru tat-tip ma jistax jintuża kullimkien fid-dikjarazzjoni ta’ qasam ta ‘interface ġenerika.  Bl-istess mod, il-klassi nested titqies bħala klassi nested statika, mhux klassi interna, u għal din ir-raġuni l-użu tal-parametru tat-tip kullimkien fil-klassi nested huwa illegali.

Soluzzjoni għall-klassijiet u l-interfaces statiċi mdaħħla:

Fil-każ ta’ klassijiet u interfaces ibestjati statiċi din mhix diżastru maġġuri.  Bħala soluzzjoni nistgħu niġġeneraw il-klassi statika jew l-interface innifsu.

Eżempju (soluzzjoni – iġġenera t-tip statiku nested):

klassi Wrapper <T> {
  private final T theObject;

  public Wrapper( T t) { theObject = t; }
  public T getWrapper () { ritorn theObject; }   public Immutable <T> makeImmutable () {
        return new Immutable <T> (l-Oġġett);
  }
  public Mutable <T> makeMutable () {
        return new Mutable <T> (l-Oġġett);
  }
  private static <A> A makeClone(A theObject) { ... }

  public static final class Immutable <A> { // issa hija klassi ġenerika
        private final A theObject;

        public Immutable( A arg) {
            theObject = makeClone(arg);
        }
        public A getWrappedItem () {
            return makeClone(theObject);
        }
  }
  public static class Mutable <A> {
        ... similar ...
  }
}

M’hemm l-ebda soluzzjoni bħal din għal tipi enum imnaqqsa minħabba li ma jistgħux ikunu ġeneriċi.

Soluzzjoni għall-klassijiet statiċi mdaħħla:

Jekk it-tip statiku nested huwa klassi, soluzzjoni alternattiva tkun iddawwar il-klassi statika fi klassi interna mhux statika.

Eżempju (soluzzjoni – uża klassi interna):

klassi Wrapper <T> {
  private final T theObject;

  public Wrapper( T t) { theObject = t; }
  public T getWrapper () { ritorn theObject; }   public Mutable makeMutable() {
      return dan. ġdid Mutabbli(theObject);
  }
  public Immutable makeImmutable() {
      return dan. ġdid Immutabbli(theObject);
  }
  private static <A> A makeClone(A theObject) { ... }

  public final class Immutable {  // m'għadhiex klassi statika
      private final T theObject;

      public Immutable( T arg) {
          theObject = makeClone(arg);
      }
      public T getWrappedItem () {
          return makeClone(theObject);
      }
  }
  public class Mutable 
        ... similar ...
  }
}

Din il-soluzzjoni tiġi flimkien ma ‘ċertu ammont ta’ overhead minħabba li l-klassijiet interni kollha għandhom referenza moħbija għal eżempju tat-tip ta ‘barra, li f’dan l-eżempju la għandhom bżonn u lanqas jieħdu vantaġġ minnu; ir-referenza moħbija hija biss bagalji.  Ħafna drabi, il-klassijiet interni huma kkombinati ma ‘interfaces sabiex iżommu l-klassi interna dettall ta’ implimentazzjoni privata tal-klassi ta ‘għeluq.  Nistgħu nagħmlu l-istess hawn.

Eżempju (il-soluzzjoni preċedenti rfinuta):

klassi Wrapper <T> {
  private final T theObject;

  public Wrapper( T t) { theObject = t; }
  public T getWrapper () { ritorn theObject; }   public Mutable <T> makeMutable () {
      return this.new Mutable(theObject);
  }
  public Immutable <T> makeImmutable () {
      return this.new Immutable(theObject);
  }
  private static <A> A makeClone(A theObject) { ... }

  interface pubbliku Immutabbli<S> {
      S getWrappedItem();
  }
  interface pubbliku Mutable<S> {
      S getWrappedItem();
      void setWrappedItem(S arg);
  }
  privat klassi finali ImmutableImplementation jimplimenta Immutable<T> { 

      private final T theObject;

      public ImmutableImplementation(T arg) {
          theObject = makeClone(arg);
      }
      public T getWrappedItem() {
          return makeClone(theObject);
      }
  }
  privat klassi MutableImplementation jimplimenta Mutable<T> { 
        ... similar ...
  }
}

Kif tistgħu taraw, l-interfaces pubbliċi nested jeħtieġ li jkunu ġeneriċi filwaqt li l-klassijiet privati ​​ta ‘ġewwa jistgħu jużaw il-parametru tat-tip tal-klassi magħluqa.

 

 

 

 

 

Ħalli Tweġiba

Skopri aktar minn Velislav Krastev Blog

Abbona issa biex tkompli taqra u tikseb aċċess għall-arkivju sħiħ.

Kompli qari