7. Generics

  • erasure

  • bridge method

7.1. Basic generic

 1public static class Record<T> {
 2  T[] data;
 3
 4  public Record(T[] data) {
 5    this.data = data;
 6  }
 7
 8  @Override
 9  public String toString() {
10    StringBuilder sb = new StringBuilder();
11    for (int i = 0; i < data.length; i++) {
12      sb.append(data[i]);
13      if (i < data.length - 1) {
14        sb.append(',');
15      }
16    }
17    return sb.toString();
18  }
19}
1var record1 = new Record<Integer>(new Integer[] { 1, 2, 3});
2var record2 = new Record<Double>(new Double[] { 1d, 2d, 3d });
3
4System.out.println(record1);
5System.out.println(record2);

7.2. Generic with two types

 1public static class Record<I, T> {
 2  I id;
 3  T[] data;
 4
 5  public Record(I id, T[] data) {
 6    this.id = id;
 7    this.data = data;
 8  }
 9
10  @Override
11  public String toString() {
12    StringBuilder sb = new StringBuilder();
13    sb.append(id).append(':');
14
15    for (int i = 0; i < data.length; i++) {
16      sb.append(data[i]);
17      if (i < data.length - 1) {
18        sb.append(',');
19      }
20    }
21
22    return sb.toString();
23  }
24}
1var record1 = new Record<Integer, Integer>(0, new Integer[] { 1, 2, 3});
2var record2 = new Record<String, Double>("a", new Double[] { 1d, 2d, 3d });
3
4System.out.println(record1);
5System.out.println(record2);

7.3. Generic with bounded type

 1public static class Data<T extends Number> {
 2  private T[] data;
 3
 4  public Data(T[] data) {
 5    this.data = data;
 6  }
 7
 8  public double getSum() {
 9    double sum = 0.0d;
10    for (T item : data) {
11      sum += item.doubleValue();
12    }
13    return sum;
14  }
15}
1var data1 = new Data<Integer>(new Integer[] { 1, 2, 3, 4});
2var data2 = new Data<Double>(new Double[] { 5d, 6d, 7d, 8d});
3
4System.out.println(data1.getSum());
5System.out.println(data2.getSum());

7.4. Generic with wild card

 1public static class Data<T extends Number> {
 2  private T[] data;
 3
 4  public Data(T[] data) {
 5    this.data = data;
 6  }
 7
 8  public double getSum() {
 9    double sum = 0.0d;
10    for (T item : data) {
11      sum += item.doubleValue();
12    }
13    return sum;
14  }
15
16  public T[] getData() {
17    return data;
18  }
19
20  public boolean isSameLength(Data<?> that) {
21    return this.data.length == that.data.length;
22  }
23}
1var data1 = new Data<Integer>(new Integer[] { 1, 2, 3, 4, 9, 10});
2var data2 = new Data<Double>(new Double[] { 5d, 6d, 7d, 8d});
3
4System.out.println(data1.isSameLength(data2));

7.5. Generic interface

 1public interface Pet<I> {
 2  I getId();
 3  String getName();
 4  String makeNoise();
 5}
 6
 7public static class PetImpl implements Pet<Integer> {
 8  private final Integer id;
 9  private final String name;
10  private final String noise;
11
12  public PetImpl(Integer id, String name, String noise) {
13    this.id = id;
14    this.name = name;
15    this.noise = noise;
16  }
17
18  @Override
19  public Integer getId() {
20    return id;
21  }
22
23  @Override
24  public String getName() {
25    return name;
26  }
27
28  @Override
29  public String makeNoise() {
30    return noise;
31  }
32}
1var dog1 = new PetImpl(0, "Max", "woof!");
2var dog2 = new PetImpl(0, "Dax", "bark!");
3var dogs = new Pet[] { dog1, dog2 };
4
5for (Pet pet : dogs) {
6  System.out.println(pet.getId() + ": " + pet.getName() + " says " + pet.makeNoise());
7}