Avatar billede kernelx Juniormester
20. august 2008 - 08:50 Der er 9 kommentarer og
1 løsning

Generics som return-value

hi,

jeg vil gerne finde ud af, hvad T er for en class.

+++
public <T> T get() {
  T value = ???;
  System.out.println( value.getClass().getCanonicalName() );
  return null;
}
+++

Hvordan kan jeg lave en test-instance til "value"?
Eller er der en anden mulighed for at faa fat i class'en af T?

med venlig hilsen
KernelX
Avatar billede schwarz84 Nybegynder
20. august 2008 - 11:33 #1
Som du har skrevet din type så skal value kunne assignes til en variabel af en hvilken som helst type. Null er den eneste værdi som har den egenskab...
Avatar billede kernelx Juniormester
20. august 2008 - 12:51 #2
saa det er kun muligt at faa fat i denne information ved at lave det paa foelgende maade?

+++
public <T> T get( Class<T> type ) {
  System.out.println( type.getCanonicalName() );
  return null;
}
+++

String value = this.get( String.class );
Avatar billede schwarz84 Nybegynder
20. august 2008 - 13:24 #3
Nej, lige i dit eksempel kan du godt returnere null fra dit første eksempel, men du kan ikke returnere andet. Din anden stump kode tvinger bare dit type argument til at være samme type som det der returneres.
Generics har noget at gøre med typer ikke med klasser så det giver ikke mening at snakke om en class af T.

Hvad er det konkret du vil opnå?
Avatar billede kernelx Juniormester
20. august 2008 - 13:49 #4
Jeg vil proeve noget i denne stil
(bare uden param Class<T> type):
+++
String stringValue = this.get( String.class );
int intValue = this.get( Integer.class );
byte[] byteValue = this.get( byte[].class );
+++
public <T> T get( Class<T> type ) {
  if ( type.getCanonicalName().equals( "byte[]" ) ) {
    byte[] returnValue = ...
    return (T)returnValue;
  }
  else if ( ... ) {

  }
  ...
}
+++
Avatar billede arne_v Ekspert
20. august 2008 - 15:19 #5
Den bliver nok vanskelig.

Fordi generics i Java er en compile time thingy. I den genererede kode vil din value
variabel have typen Object !
Avatar billede kernelx Juniormester
21. august 2008 - 08:07 #6
mange tak.
husk at skrive et eller andet som svar
Avatar billede schwarz84 Nybegynder
21. august 2008 - 09:02 #7
Det er ikke java's erasure implementation, du er rendt ind i som arne_v antyder. Du forsøger på at bruge type-inferensen til at give et implicit parameter til en metod, hvilket er en sammenblanding af type-begrebet og klasse-begrebet som slet ikke giver mening i Java-verdenen. Ligemeget hvordan man implementerer generics så er typecheck/type-inferens en compile time ting.
Dvs måde med at give en parameter med er den eneste som giver sprogligt mening.
Avatar billede arne_v Ekspert
22. august 2008 - 04:40 #8
public static T Get<T>() where T : new()
        {
            T o = new T();
            Console.WriteLine(o.GetType().Name);
            return o;
        }

virker ellers fint i C#
Avatar billede schwarz84 Nybegynder
22. august 2008 - 07:15 #9
arne_v: Vi kan helt sikkert blive enige om at der er ret stor forskel på C#'s generics og Java's generics. T i C# dækker kun over parameteriserede konkrete typer, mens T i Java er væsentligt mere generel, derfor giver sådan en konstruktion slet ikke mening i Java-sammenhæng. Java's typeinferens kan udover modellen i C# inferere T til at være alt fra forskellige rekursive typer til en delmængde af eksistensielle typer, og i alle de tilfælde giver det ikke mening at have sådan en new() konstruktion, da der ikke findes klasser for disse typer.
Når man skriver som ovenstående i C#, så er der altid en klasse svarende til typen og compileren kan give den med som parameter og ved et lille reflection-hack (ved ikke om det er implementeret sådan), så virker det.
Derfor giver det mening at have sådan noget i C#, men ikke i Java. Vi er vist udover hvad kernelx spurgte om...
Avatar billede arne_v Ekspert
24. august 2008 - 04:25 #10
Eksemplet svarer så vidt jeg kan se præcis til hvad spørger efterlyste i spørgsmåls
teksten.

Og nej T i C# generics behøver ikke at være en konkret type.

Det gør det naturligvis når man sætter en restriktion på at den skal have en
constructor uden argumenter.

Man kunne også godt lave en sådan restriktion i Java.

Men der vil ikke være nogen pointe. new T() kan ikke fungere med type erasure.

Det er netop der forskellen på generics i C# og Java ligger.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester