Skip to content

Instantly share code, notes, and snippets.

@gdemarcsek
Created September 18, 2016 22:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gdemarcsek/3d979c8f948e2be9b83f821079861a50 to your computer and use it in GitHub Desktop.
Save gdemarcsek/3d979c8f948e2be9b83f821079861a50 to your computer and use it in GitHub Desktop.
Playing with Java Generics
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
class A {
}
class B extends A {
public int X = 42;
}
class C extends B {
public String Y = "Generics, yaaay! :)";
}
public class Playground
{
public static void listAllThings(List<? extends B> ofThese) { // Use-side covariance
for(B t : ofThese) { // We can get a B from any collection that can hold objects of subtypes of B (including B)
System.out.println(t.X);
}
}
public static void addBunchOfThings(List<? super B> toThis) { // Use-side contravariance
for (int i = 0; i < 3; ++i) { // We can add a B or C to any collection that can hold objects of supertypes of B
toThis.add(new C());
toThis.add(new B());
}
}
public static void withBunchOfAnything(List<?> ofThese) {
for (Object o : ofThese) // We can get an object from any collection that can hold any type...
System.out.println(o);
//ofThese.add(new Object()); // ...although, we cannot add anything to it, since ofThese can be List<Integer> or List<B>, ...
}
public static void cannotPass(List<Object> here) {
for (Object o : here) System.out.println(o); // This is a pretty useless thingy here...
}
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
//cannotPass(thingies); // This will not work, since List<B> does not extend List<Object> despite B does extend Object...
cannotPass(new ArrayList<Object>()); // only List<Object> will be acceptable -- by default, generics in Java are "invariant", but...
List<B> thingies = new ArrayList<>(); // ...Ok, so this is a List of Bs...
addBunchOfThings(thingies); // ...then of course we can do this...
addBunchOfThings(new ArrayList<A>()); // ...but also this thanks to contravariance...
listAllThings(thingies); // ...and of course, we can do this...
listAllThings(new ArrayList<C>(Arrays.asList(new C[] { new C(), new C() }))); // ...but also this thanks to covariance...
List<? super B> l = new ArrayList<>(); // The inferred type will be B...
l.add(new B());
l.add(new C()); // ...so this works because of Liskov-substiution principle
//l.add(new A()); // and this won't, so the "super" keyword here might be a bit misleading, but that is the point ;)
addBunchOfThings(new ArrayList<A>());
withBunchOfAnything(l);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment