Generici Java T vs Object


127

Mi chiedevo qual è la differenza tra le seguenti due dichiarazioni di metodo:

public Object doSomething(Object obj) {....}

public <T> T doSomething(T t) {....}

C'è qualcosa che puoi / vorresti fare con uno ma non con l'altro? Non sono riuscito a trovare questa domanda altrove su questo sito.

Risposte:


112

Isolato dal contesto - nessuna differenza. Su entrambi te objpuoi invocare solo i metodi di Object.

Ma con il contesto, se hai una classe generica:

MyClass<Foo> my = new MyClass<Foo>();
Foo foo = new Foo();

Poi:

Foo newFoo = my.doSomething(foo);

Stesso codice con oggetto

Foo newFoo = (Foo) my.doSomething(foo);

Due vantaggi:

  • non c'è bisogno di casting (il compilatore te lo nasconde)
  • compilare la sicurezza del tempo che funziona. Se Objectviene utilizzata la versione, non sarai sicuro che il metodo ritorni sempre Foo. Se ritorna Bar, avrai un ClassCastException, in fase di esecuzione.

14

La differenza qui è che nel primo, specifichiamo che il chiamante deve passare un'istanza di Object (qualsiasi classe) e riceverà un altro Object (qualsiasi classe, non necessariamente dello stesso tipo).

Nel secondo, il tipo restituito sarà lo stesso di quello fornito quando è stata definita la classe.

Example ex = new Example<Integer>();

Qui specifichiamo quale sarà il tipo T che ci permette di imporre più vincoli su una classe o un metodo. Ad esempio, possiamo istanziare un LinkedList<Integer>o LinkedList<Example>e sappiamo che quando chiamiamo uno di questi metodi, recupereremo un'istanza Integer o Example.

L'obiettivo principale qui è che il codice chiamante possa specificare il tipo di oggetti su cui opererà una classe, invece di fare affidamento sul casting del tipo per imporlo.

Vedere Java Generics * da Oracle.

* Link aggiornato.


13

La differenza è che con metodi generici non ho bisogno di eseguire il cast e ottengo un errore di compilazione quando sbaglio:

public class App {

    public static void main(String[] args) {

        String s = process("vv");
        String b = process(new Object()); // Compilation error
    }

    public static <T> T process(T val) {

        return val;
    }
}

Utilizzando l'oggetto devo sempre eseguire il cast e non ottengo alcun errore quando sbaglio:

public class App {

    public static void main(String[] args) {

        String s = (String)process("vv");
        String b = (String)process(new Object());
    }

    public static Object process(Object val) {

        return val;
    }
}

solo per accennare che non devi più lanciare oggetti, a partire da Android 6.
John Lord

2

Non è necessario eseguire casting di classe aggiuntivi. Nel primo caso otterrai sempre un oggetto della classe java.lang.Object che dovrai eseguire il cast alla tua classe. Nel secondo caso T verrà sostituita con la classe definita nella firma generica e non sarà necessario alcun casting di classe.


2

In fase di esecuzione, niente. Ma in fase di compilazione il secondo eseguirà il controllo del tipo per assicurarsi che il tipo del parametro e il tipo del valore restituito corrispondano (o siano sottotipi di) qualunque sia il tipo T risolto (il primo esempio esegue anche il controllo del tipo ma ogni oggetto è un sottotipo di Oggetto quindi ogni tipo sarà accettato).


2

T è un tipo generico. Significa che può essere sostituito da qualsiasi oggetto qualificante in fase di esecuzione. Puoi invocare un tale metodo come segue:

String response = doSomething("hello world");

O

MyObject response = doSomething(new MyObject());

O

Integer response = doSomething(31);

Come puoi vedere, qui c'è polimorfismo.

Ma se viene dichiarato che restituisce Object, non puoi farlo a meno che non digiti cast cose.


Possiamo dire che con <T>non c'è l'autoboxing?
SMUsamaShah

0

nel primo caso prende un parametro di qualsiasi tipo egstring e restituisce un tipo foo. Nel secondo caso prende un parametro di tipo foo e restituisce un oggetto di tipo foo.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.