webForumDet fria alternativet

Generik före returtyp

5 svar · 759 visningar · startad av Gein

GeinMedlem sedan sep. 20005 700 inlägg
#1

Vad innebär det fetmarkerade i följande kodsnutt? Jag förstår generics men jag förstår inte vad följden blir att skriva sådär före returtypen.

public class UsingReflection<T> {

    public static [b]<T>[/b] void createInstance(Class<T> clazz) {
      T instance;
      try {
          instance = clazz.newInstance(); // does not work for every class
      } catch (InstantiationException e) {
          //...
      } catch (IllegalAccessException e) {
          //...
      }

      //...

    }
}
nitro2k01Medlem sedan aug. 20039 342 inlägg
#2

Vad jag kan se, att returtypen är den samma som den klass som clazz pekar mot. Du borde t ex kunna göra detta:

UsingReflection<MinKlass> klassObjekt = new UsingReflection();
// och sedan
MinKlass x = klassObjekt.createInstance(MinKlass);

Det fetmarkerade <T> bör då referera till retur-typen, som alltså är MinKlass i exemplet.

Edit: Feltänk.

spangoMedlem sedan juni 20008 205 inlägg
#3

Gein skrev:

Vad innebär det fetmarkerade i följande kodsnutt? Jag förstår generics men jag förstår inte vad följden blir att skriva sådär före returtypen.

Därför att annars skulle kompilatorn tro att T var ett klassnamn, så din kod skulle inte funka. Statiska metoder kan inte använda de typparametrar som deras klass tar emot - typparametrar är icke-statiska - "per objekt", inte "per klass". Exempelvis är new Foo<X>() av samma klass som new Foo<Y>(), till skillnad från hur det är i t.ex. C# och C++.

GeinMedlem sedan sep. 20005 700 inlägg
#4

spango skrev:

Därför att annars skulle kompilatorn tro att T var ett klassnamn, så din kod skulle inte funka. Statiska metoder kan inte använda de typparametrar som deras klass tar emot - typparametrar är icke-statiska - "per objekt", inte "per klass". Exempelvis är new Foo<X>() av samma klass som new Foo<Y>(), till skillnad från hur det är i t.ex. C# och C++.

Nu vet jag inte riktigt... svarade du verkligen på min fråga nu? Att kompilatorn skulle tro att T var ett klassnamn utan < > förstår jag. Men vad innebär det att skriva <T> framför returtypen? Att typparametrarna är per-objekt och inte per-klass är jag också med på. Men jag förstår inte metodsignaturen:

 public static <T> void createInstance(Class<T> clazz)
LimeMedlem sedan sep. 2001961 inlägg
#5

Du deklarerar den generiska variabeln T på det sättet.

public static <T> void createInstance(Class<T> clazz)

Denna rad betyder "skapa en generisk metod som tar en typ med variabelnamn T och deklarera den som public static void createInstance(Class<T> clazz)". Eftersom man vill deklarera en variabel innan den kan användas så vill man ha den så tidigt som möjligt, och det blir då strax före returtypen.

Det går ju faktiskt att skriva:

   public <T> T downCast(Class<? extends T> t){
        return (T) t;
    }

(men den är svår att använda...)

Varför man kaplsar in typen T i statiska anrop beror helt enkelt på att man vill komma åt klassen och inte objekten. Klassen Class är även den generisk numera och till denna kan man ge en typ. Class<T> kan man läsa som ta typ T och låt den bli inkapslad i en Class, för att man ska kunna komma åt det man kan komma åt på en klass... t.ex. statiska metoder.

GeinMedlem sedan sep. 20005 700 inlägg
#6

Aha, tack för ett utförligt svar!
Inser samtidigt att spango faktiskt svarade på min fråga.

133 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
131 ms — hämta tråd, inlägg och bilagor (db)