Konstruktor Generik di Java

1. Ikhtisar

Kami sebelumnya membahas dasar-dasar Java Generics. Dalam tutorial ini, kita akan melihat Konstruktor Generik di Java.

Konstruktor generik adalah konstruktor yang memiliki setidaknya satu parameter dari tipe generik.

Kita akan melihat bahwa konstruktor generik tidak harus berada dalam kelas generik, dan tidak semua konstruktor dalam kelas generik harus generik.

2. Kelas Non-Generik

Pertama, kami memiliki entri kelas sederhana , yang bukan kelas umum:

public class Entry { private String data; private int rank; }

Di kelas ini, kita akan menambahkan dua konstruktor: konstruktor dasar dengan dua parameter, dan konstruktor generik.

2.1. Pembuat Dasar

Konstruktor Entri pertama adalah konstruktor sederhana dengan dua parameter:

public Entry(String data, int rank) { this.data = data; this.rank = rank; }

Sekarang, mari gunakan konstruktor dasar ini untuk membuat objek Entri :

@Test public void givenNonGenericConstructor_whenCreateNonGenericEntry_thenOK() { Entry entry = new Entry("sample", 1); assertEquals("sample", entry.getData()); assertEquals(1, entry.getRank()); }

2.2. Pembuat Generik

Selanjutnya, konstruktor kedua kita adalah konstruktor generik:

public  Entry(E element) { this.data = element.toString(); this.rank = element.getRank(); }

Meskipun Masuk kelas tidak generik, ia memiliki konstruktor generik, karena memiliki parameter elemen tipe E .

Tipe generik E dibatasi dan harus mengimplementasikan antarmuka Rankable dan Serializable .

Sekarang, mari kita lihat antarmuka Rankable , yang memiliki satu metode:

public interface Rankable { public int getRank(); }

Dan, misalkan kita memiliki Produk kelas yang mengimplementasikan antarmuka Rankable :

public class Product implements Rankable, Serializable { private String name; private double price; private int sales; public Product(String name, double price) { this.name = name; this.price = price; } @Override public int getRank() { return sales; } }

Kita kemudian dapat menggunakan konstruktor generik untuk membuat objek Entri menggunakan Produk :

@Test public void givenGenericConstructor_whenCreateNonGenericEntry_thenOK() { Product product = new Product("milk", 2.5); product.setSales(30); Entry entry = new Entry(product); assertEquals(product.toString(), entry.getData()); assertEquals(30, entry.getRank()); }

3. Kelas Generik

Selanjutnya, kita akan melihat kelas generik yang disebut GenericEntry :

public class GenericEntry { private T data; private int rank; }

Kami akan menambahkan dua jenis konstruktor yang sama seperti bagian sebelumnya di kelas ini juga.

3.1. Pembuat Dasar

Pertama, mari kita tulis konstruktor non-generik sederhana untuk kelas GenericEntry kita :

public GenericEntry(int rank) { this.rank = rank; }

Meskipun GenericEntry adalah kelas generik, ini adalah konstruktor sederhana yang tidak memiliki parameter tipe generik.

Sekarang, kita dapat menggunakan konstruktor ini untuk membuat GenericEntry :

@Test public void givenNonGenericConstructor_whenCreateGenericEntry_thenOK() { GenericEntry entry = new GenericEntry(1); assertNull(entry.getData()); assertEquals(1, entry.getRank()); }

3.2. Pembuat Generik

Selanjutnya, mari tambahkan konstruktor kedua ke kelas kita:

public GenericEntry(T data, int rank) { this.data = data; this.rank = rank; }

Ini adalah konstruktor generik, karena memiliki parameter data tipe T generik . Perhatikan bahwa kami tidak perlu menambahkan di deklarasi konstruktor, karena secara implisit ada di sana.

Sekarang, mari kita uji konstruktor generik kita:

@Test public void givenGenericConstructor_whenCreateGenericEntry_thenOK() { GenericEntry entry = new GenericEntry("sample", 1); assertEquals("sample", entry.getData()); assertEquals(1, entry.getRank()); }

4. Pembuat Generik dengan Tipe Berbeda

Di kelas generik kita, kita juga bisa memiliki konstruktor dengan tipe generik yang berbeda dari tipe generik kelas:

public  GenericEntry(E element) { this.data = (T) element; this.rank = element.getRank(); }

Konstruktor GenericEntry ini memiliki elemen parameter dengan tipe E , yang berbeda dengan tipe T. Mari kita lihat aksinya:

@Test public void givenGenericConstructorWithDifferentType_whenCreateGenericEntry_thenOK() { Product product = new Product("milk", 2.5); product.setSales(30); GenericEntry entry = new GenericEntry(product); assertEquals(product, entry.getData()); assertEquals(30, entry.getRank()); }

Perhatikan bahwa:

  • Dalam contoh kami, kami menggunakan Product ( E ) untuk membuat GenericEntry tipe Serializable ( T )
  • Kita hanya dapat menggunakan konstruktor ini jika parameter tipe E dapat dilemparkan ke T.

5. Beberapa Jenis Generik

Selanjutnya, kami memiliki MapEntry kelas generik dengan dua tipe umum:

public class MapEntry { private K key; private V value; public MapEntry(K key, V value) { this.key = key; this.value = value; } }

MapEntry memiliki satu konstruktor generik dengan dua parameter, masing-masing dengan tipe yang berbeda. Mari kita gunakan dalam pengujian unit sederhana:

@Test public void givenGenericConstructor_whenCreateGenericEntryWithTwoTypes_thenOK() { MapEntry entry = new MapEntry("sample", 1); assertEquals("sample", entry.getKey()); assertEquals(1, entry.getValue().intValue()); }

6. Karakter pengganti

Akhirnya, kita bisa menggunakan wildcard dalam konstruktor generik:

public GenericEntry(Optional optional) { if (optional.isPresent()) { this.data = (T) optional.get(); this.rank = optional.get().getRank(); } }

Di sini, kami menggunakan wildcard dalam konstruktor GenericEntry ini untuk mengikat tipe Opsional :

@Test public void givenGenericConstructorWithWildCard_whenCreateGenericEntry_thenOK() { Product product = new Product("milk", 2.5); product.setSales(30); Optional optional = Optional.of(product); GenericEntry entry = new GenericEntry(optional); assertEquals(product, entry.getData()); assertEquals(30, entry.getRank()); }

Perhatikan bahwa kita harus dapat mentransmisikan tipe parameter opsional (dalam kasus kami, Produk ) ke tipe GenericEntry (dalam kasus kami, Serializable ).

7. Kesimpulan

Dalam artikel ini, kita belajar bagaimana mendefinisikan dan menggunakan konstruktor generik di kelas generik dan non-generik.

Kode sumber lengkap dapat ditemukan di GitHub.