Java generik T vs Object

127

Saya bertanya-tanya apa perbedaan antara dua deklarasi metode berikut:

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

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

Adakah sesuatu yang dapat / akan Anda lakukan dengan yang satu tetapi tidak dengan yang lain? Saya tidak dapat menemukan pertanyaan ini di tempat lain di situs ini.

Abidi
sumber

Jawaban:

112

Terisolasi dari konteks - tidak ada perbedaan. Pada keduanya tdan objAnda hanya dapat memanggil metode Object.

Tetapi dengan konteks - jika Anda memiliki kelas generik:

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

Kemudian:

Foo newFoo = my.doSomething(foo);

Kode yang sama dengan objek

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

Dua keuntungan:

  • tidak perlu casting (kompilator menyembunyikan ini dari Anda)
  • menyusun keamanan waktu yang berhasil. Jika Objectversinya digunakan, Anda tidak akan yakin bahwa metode ini selalu mengembalikan Foo. Jika kembali Bar, Anda akan memiliki ClassCastException, pada saat runtime.
Bozho
sumber
14

Perbedaannya di sini adalah bahwa di bagian pertama, kita menetapkan bahwa pemanggil harus meneruskan instance Object (kelas apa pun), dan itu akan mendapatkan kembali Object lain (kelas apa pun, tidak harus dari tipe yang sama).

Yang kedua, tipe yang dikembalikan akan menjadi tipe yang sama seperti yang diberikan saat kelas didefinisikan.

Example ex = new Example<Integer>();

Di sini kita menentukan tipe T apa yang memungkinkan kita untuk memberlakukan lebih banyak batasan pada kelas atau metode. Misalnya kita dapat membuat LinkedList<Integer>atau LinkedList<Example>dan kita tahu bahwa ketika kita memanggil salah satu metode ini, kita akan mendapatkan kembali contoh Integer atau Contoh.

Tujuan utamanya di sini adalah bahwa kode pemanggil dapat menentukan tipe objek apa yang akan dioperasikan kelas, alih-alih mengandalkan tipe-casting untuk memberlakukannya.

Lihat Java Generics * dari Oracle.

* Tautan yang Diperbarui.

Adam
sumber
13

Perbedaannya adalah bahwa dengan metode umum saya tidak perlu melakukan transmisi dan saya mendapatkan kesalahan kompilasi saat melakukan kesalahan:

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;
    }
}

Menggunakan objek yang selalu perlu saya transmisikan dan saya tidak mendapatkan kesalahan saat melakukan kesalahan:

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;
    }
}
pengguna1883212
sumber
hanya ingin menyebutkan Anda juga tidak perlu membuang objek, mulai Android 6.
John Lord
2

Anda tidak perlu melakukan transmisi kelas tambahan. Dalam kasus pertama, Anda akan selalu mendapatkan objek dari kelas java.lang.Object yang perlu Anda transmisikan ke kelas Anda. Dalam kasus kedua, T akan diganti dengan kelas yang ditentukan dalam tanda tangan generik dan tidak diperlukan pengecoran kelas.

Andrey Adamovich
sumber
2

Saat runtime, tidak ada. Tetapi pada waktu kompilasi yang kedua akan melakukan pemeriksaan tipe untuk memastikan jenis parameter dan jenis nilai yang dikembalikan cocok (atau merupakan subtipe dari) apa pun tipe T (contoh pertama juga melakukan pemeriksaan jenis tetapi setiap objek adalah a subtipe Objek sehingga setiap tipe akan diterima).

Jonathan
sumber
2

T adalah tipe generik. Artinya itu dapat diganti dengan objek yang memenuhi syarat pada saat runtime. Anda dapat menggunakan metode seperti berikut:

String response = doSomething("hello world");

ATAU

MyObject response = doSomething(new MyObject());

ATAU

Integer response = doSomething(31);

Seperti yang Anda lihat, ada polimorfisme di sini.

Tetapi jika itu dideklarasikan untuk mengembalikan Object, Anda tidak dapat melakukan ini kecuali Anda mengetik cast.

adarshr
sumber
Bisakah kita mengatakan bahwa dengan <T>tidak ada autoboxing?
SMUsamaShah
0

dalam kasus pertama ini mengambil parameter dari semua tipe egstring dan mengembalikan tipe foo. Dalam kasus kedua, dibutuhkan parameter berjenis foo dan mengembalikan objek berjenis foo.

fastcodejava.dll
sumber