- Wildcards could be used to expand the code usage to certain type hierarchy instead of limiting to one type, the super and extends keywords provide help here.
- With wildcards, sometimes same object will be labeled as different captures. Help method could be used to synchronize the type in another method.
- Explicit type parameter is in this format: Class.<Type>method(). It could be used to declare a limit to a wild card.
The following code shows examples of:
- wildcard with super and extends
- wildcard with help method
- explicit type parameter
- example of multiple extends
public class GenericUsages {
// this list is a destination or consumer: super
public static void addNumbers(final List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i);
}
}
// this list is a source or producer: extends
public static int sumOfList(final List<? extends Integer> list) {
int s = 0;
for (Number n : list)
s += n.doubleValue();
return s;
}
@Test
public void
testSimpleSuperAndExtend() {
System.out.println("===testSimpleSuperAndExtend===");
final
List<Integer> intList = new ArrayList<>();
addNumbers(intList);
final int result = sumOfList(intList);
System.out.println(result);
}
public static void
increment(Map<?, String> in) {
incrementInternal(in);
}
// A help method to avoid compiling errors
private static <T> void incrementInternal(final Map<T,
String> in) {
Set<T> keySet = in.keySet();
for (T key : keySet) {
in.put(key, in.get(key) + ":)");
}
}
@Test
public void testHelpMethod() {
System.out.println("===testHelper===");
Map<Number, String> map = new HashMap<>();
map.put(1, "Integer
1");
map.put(2.0, "Double
2.0");
map.put(3L, "Long
3");
increment(map);
System.out.println(map);
Map<String, String> map2 = new HashMap<>();
map2.put("k1", "v1");
map2.put("k2", "v2");
map2.put("k3", "v3");
increment(map2);
System.out.println(map2);
}
public static <E>
Set<E> union(final Set<? extends E> s1, final Set<? extends E> s2) {
final Set<E> result = new HashSet<>(s1);
result.addAll(s2);
return result;
}
@Test
public void
testExplicitTypeParameter() {
System.out.println("===testExplicitTypeParameter===");
Set<Integer> integers = new HashSet<>();
integers.add(1);
integers.add(2);
Set<Double> doubles = new HashSet<>();
doubles.add(1.0);
doubles.add(2.0);
Set<Number> result =
GenericUsages.<Number>union(integers, doubles);
System.out.println(result);
Set<String> strings = new HashSet<>();
strings.add("1s");
strings.add("2s");
Set<?> result2 = GenericUsages.union(integers, strings);
// Compiling errors:
// Set<Number> result2 =
GenericUsages.union(integers, strings);
// Set<?> result3 =
GenericUsages.<Number>union(integers, strings);
System.out.println(result2);
}
interface Label<T> {
String getLabel();
}
public static <S extends Label<? super S>, U extends Label<? super U>> String
m1(final S s, final U u) {
final String result = s.getLabel().toString()
+ u.getLabel().toString();
return result;
}
public static class Base implements Label<Base>
{
private String label;
public Base(final String label) {
this.label = label;
}
@Override
public String getLabel()
{
return this.label;
}
}
public static class S1 extends Base {
public S1() {
super("S1");
}
}
public static class U1 extends Base {
public U1() {
super("U1");
}
}
@Test
public void
testComplicatedSuperAndExtend() {
System.out.println("===testComplicatedSuperAndExtend===");
final S1 s1 = new S1();
final U1 u1 = new U1();
String result = m1(s1, u1);
System.out.println(result);
}
public static <X extends A & B &
C> C m2(final X x) {
return x;
}
public static class A {
}
interface B {
}
interface C {
}
public static class D extends A implements B, C {
}
@Test
public void
testMultipleSuperTypes() {
System.out.println("===testMultipleSuperTypes===");
final D d = new D();
System.out.println(m2(d).toString());
}
}
|
No comments:
Post a Comment