Created
September 18, 2016 22:06
-
-
Save gdemarcsek/3d979c8f948e2be9b83f821079861a50 to your computer and use it in GitHub Desktop.
Playing with Java Generics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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