Java generics - compilation error [duplicate] - java

This question already has an answer here:
Java generic collection, cannot add list to list
(1 answer)
Closed 5 years ago.
Why it doesn't work ?
class W<A extends Number>
{
public void create(A value)
{
}
}
public void calculate(W<? extends Number> w)
{
Integer v = 5;
w.create(v); // Compilation error
}
Could somebody explain what is wrong with that code and how to fix it?
Compilation error : "create (capture) in W cannot be applied to (java.lang.Integer)"

You have a common misconception about wildcards in generics. You think that ? means you can pass any type (as long as it extends Number), but you cannot.
? extends Number does not mean that you can pass any type that extends Number. It means "a specific, but unknown type that extends Number". Since the exact type is unknown to the compiler, it cannot allow you to use Integer - the compiler at that point simply has not enough information to check if it is type-safe. (It doesn't know if the actual type of the W that you pass to the method is Integer or some other type that extends Number).
This is exactly the same reason as why you cannot add anything to a List<?>, for example, which is a question that people often ask.

This follows straight from the core generics principle. When you use ? extends SomeType, you cannot pass/consume anything into the reference, as this might violate type safety guarantee provided by the Generics when retrieving these items. One would then be able to do -
List<Long> longs = Arrays.asList(5L, 10L, 20L);
List<? extends Number> numbers = longs;
// Trouble!
numbers.add(10.5);
See one of my blog posts here for details on how subtyping works with Generics.

You can use bounderies in the create method:
public <T extends Number> void create(final T value) {
}
Example:
class W<A extends Number> {
public <T extends Number> void create(final T value) {
}
public void calculate(final W<? extends Number> w) {
final Integer v = 5;
w.create(v); // Compilation error
}
}

You have to declare what kind of W you're using before you use it
public void calculate(W<? extends Number> w) {
Integer v = 5;
new W<Integer>().create(v);
}
or, you can change the create method to accept any number
public void create(Number value) {
}

Both objects should extend Number, but that does NOT mean these objects cannot be siblings:
ClassA extends Number {..}
ClassB extends Number {..}
ClassA cannot be casted to ClassB, and this is what could happen in your code. It can be both ClassA but your compiler cannot be sure of that as it could be ClassB or any other class extending Number, so it gives a compile error.

Related

Why is Class<T extends Base> not applicable to Class<Base>? [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 4 years ago.
I am in the creation of a small application and I stumbled over the following problem.
There is a List<Class<MyCustomBaseClass>> in my application and a function with the signature public <T extends MyCustomBaseClass> void addClass(Class<T> clazz).
The AddClass should put the clazz into the List. But I get the following error there:
The method add(Class<MyCustomBaseClass>) in the type List<Class<MyCustomBaseClass>> is not applicable for the arguments (Class<T>)
Here are my 3 classes as simplified as I could make them:
// Program.java
package me.mischa.stackoverflow;
import java.util.ArrayList;
import java.util.List;
public class Program {
private List<Class<MyCustomBaseClass>> _listOfClasses;
private static Program _instance;
public Program() {
_listOfClasses = new ArrayList<>();
}
public static void main(String[] args) {
Program program = new Program();
program.addClass(MyCustomChildClass.class);
}
public <T extends MyCustomBaseClass> void addClass(Class<T> clazz) {
_listOfClasses.add(clazz);
}
}
.
// MyCustomBaseClass.java
package me.mischa.stackoverflow;
public class MyCustomBaseClass {
}
.
// MyCustomChildClass.java
package me.mischa.stackoverflow;
public class MyCustomChildClass extends MyCustomBaseClass {
}
The error is at the line _listOfClasses.add(clazz);
I do not understand why <T extends MyCustomBaseClass> should not be compatible with <MyCustomBaseClass>
Java's generics are invariant. That means that, as a type parameter, Class<MyCustomBaseClass> means exactly that, no Class object representing a subclass of MyCustomBaseClass is allowed.
In your addClass method, you've only given an upper bound on T when defining it -- T could be a subclass of MyCustomBaseClass, e.g. your class MyCustomChildClass. The compiler disallows this call because of the mismatch.
You can widen what's allowed in _listOfClasses by providing a matching upper bound, which will allow the method addClass to compile.
private List<Class<? extends MyCustomBaseClass>> _listOfClasses;
Incidentally, because it doesn't really matter exactly what type T is in addClass, you can remove it and use a wildcard.
public void addClass(Class<? extends MyCustomBaseClass> clazz) {
Java's generics are invariant. There's a reason for that. Imagine the following code (NOTE: Number is a supertype of both Integer and Double):
List<Double> doublesOnly = new ArrayList<Double>();
List<Number> numbers = doublesOnly;
numbers.add(new Integer(5));
Double d = doublesOnly.get(0);
In the above, if it had been valid java, you are assigning an Integer to a Double, which is a problem because an Integer isn't a Double. This is why in actual fact, if you attempt to compile the above, it won't work; the second line is marked as invalid java, because a List<Double> cannot be assigned to a List<Number>. There is a solution:
List<Double> doublesOnly = new ArrayList<Double>();
List<? extends Number> numbers = doublesOnly;
numbers.add(new Integer(5));
Double d = doublesOnly.get(0);
This time, line 3 is the error: You cannot add anything to a List<? extends Something>, other than null. There's no way to fix this code and that's good because we're doing something fundamentally bad.
The solution in your specific case is two-fold:
More generally you should avoid the notion of using Class<?> in your APIs. Generally, use factories instead.
If you must, try something like: List<Class<? extends MyCustomBaseClass>>. Yes, 2 extends. You can add a Class<MyCustomChildClass> to this list.

When to use a producer and consumer logic / Wildcards JAVA

Can someone help me with understanding logic behind this code:
import java.util.List;
import java.util.Arrays;
interface DoubleValue<T> {
public void dv(T e);
}
public class InTest2 {
public static void main(String[] a) {
DoubleValue<Number> func = e -> System.out.println(e.doubleValue());
List<Number> l = Arrays.asList(1, 2, 3);
InTest2.sumOfListNotWorking(l, func);
InTest2.sumOfListWorking(l, func);
InTest2.sumOfListWorkingSuper(l, func);
}
// I thought this should work
public static void sumOfListNotWorking(List<? extends Number> list, DoubleValue<? extends Number> f) {
for (Number n : list)
f.dv(n); // This line give error: The method dv(capture#2-of ? extends Number) in the type DoubleValue<capture#2-of ? extends Number> is not applicable for the arguments (Number)
}
public static void sumOfListWorking(List<? extends Number> list, DoubleValue<Number> f) {
for (Number n : list)
f.dv(n);
}
public static void sumOfListWorkingSuper(List<? extends Number> list, DoubleValue<? super Number> f) {
for (Number n : list)
f.dv(n);
}
}
sumOfListNotWorking:
Here I pass to DoubleValue.dv(<? extends Number> e) a Number and I thought it's OK.
But compiler says that it's not. Why?
I expect with DoubleValue<Number>.dv as e -> e.doubleValue() this should be typical consumer: I get value <? extends Number> and do something with it.
sumOfListWorkingSuper:
Behavior of sumOfListWorkingSuper puzzles me too.
Interface DoubleValue<? super Number> can't be a consumer cause value of <? super Number> can't be changed in place (Number is immutable), but compiler is OK with it.
UPDATE:
Apparently I didn't understand correctly logic of "producer" and "consumer".
sumOfListNotWorking:
This method doesn't compile because I use:
List<? extends Number> list as a producer (in method I take out
values from list with loop).
DoubleValue<? extends Number> as a consumer (in method I pass Number to f.dv(n)), but when I try to pass value Number to f compiler told me that f is defined as a producer (<? extends Number> - have some values of Number or it's children) and it can not accept any values. What if I passed to f argument DoubleValue<Integer> then I would try to put Number where should be Integer - this isn't possible. All this error happens because I define a producer instead of a consumer.
Thanks for pointing out word accept in logic of a consumer and a producer.
List<? extends Number> means "we don't know what this List contains, but whatever it is, it is a descendant of Number or Number itself."
Similarly, DoubleValue<? extends Number> means "we don't know what this DoubleValue can accept to operate with, but whatever it is it accepts, it is a descendant of Number or Number itself".
Here the relevant part is "we don't know what it accepts". We don't know, so you can't give anything to it and expect it will be accepted: because you don't know if it is accepted. The rest of the information is irrelevant. It's relevant in a List<? extends Number> because there at least we know that whatever elements it gives out, can be safely cast to Number after they're given out. But your DoubleValue class doesn't give out anything. It only takes in things. So all that "but we know that it is a descendant of" is completely useless.
<? extends Stuff> is useful on classes that give out objects. It's useless on those that don't give out objects.
<? super Stuff> is useful on classes that take in objects. It's useless on those that don't take in objects.
In addition to #kumesana's answer, this is how you can fix your method:
public static <T extends Number> void sumOfListNotWorking(
List<? extends T> list,
DoubleValue<? super T> f) {
for (T n : list)
f.dv(n);
}
You only needed to make that "unknown" type in wildcards known (T).
Also see the PECS rule. Here, list provides items (i.e. it is a producer), f accepts items (it is a consumer). So type in list should extend T, type in f should super T. This allows passing List<Integer> and DoubleValue<Number>.

Why can't I add an instance of A to a collection declared as Set<? extends A>? [duplicate]

This question already has answers here:
Why adding an element (of correct type) into a List through a method of <?> is a compilation error? [duplicate]
(1 answer)
How can I add to List<? extends Number> data structures?
(7 answers)
Closed 9 years ago.
I have:
class Document { ... }
class DocumentCluster extends Document { ... }
And I'm trying to define a set of documents this way:
Set<? extends Document> docs = new HashSet<Document>();
However, when I'm trying to insert a document to my set:
docs.add(d);
I'm getting:
The method add(capture#10-of ? extends Document) in the type Set<capture#10-of ? extends Document> is not applicable for the arguments (Document)
What am I doing wrong?
Because it might only allow objects of type B.
A classic question, answered a million of times. Non-intuitive, but also not a design bug of Java.
Here is the classic example: let A be Fruit.
Can I put an Apple into a Set<? extends Fruit>?
No, because it could be a Set<Banana> which obviously must not contain apples.
? extends Fruit says some specific kind of fruit, and not "any kind of fruit". Then it would be a Set<Fruit> which indeed can take any kind of Fruit.
As a rule of thumb:
when putting ? super Fruit is convenient. It takes "at least" fruits
when getting ? extends Fruit is convenient. It may return only one kind of fruit, but they will all be fruit.
Consider this method:
public static double computeAverage(Collection<? extends Number> col) {
double sum = 0.;
for (Number n : col) {
sum += n.doubleValue();
}
return sum / n.size();
}
This method can work with List<Integer>. Because it does not put Double into the list, but only takes Number objects out.
public static void put(Collection<? super Number> col, Number n) {
col.put(n);
}
Here, we have the opposite case. We need a list that accepts arbitrary numbers (otherwise, we could not put the unspecific number in it). It may accept more, though:
put(new List<Object>(), (Double) 1.);
is valid, because I may put doubles into a list of Objects.
But the compiler correctly prevents put( new List<Integer>(), (Double) 1.).
It can get much messier than that:
public static <I,O> void transfer(Collection<? extends I> input,
Collection<? super O> output,
Converter<? super I, ? extends O> converter) {
for (I inobj : input) {
O outobj = converter.convert(inobj);
output.put(outobj);
}
}
But the compiler may be unable to figure out I and O automatically for you every time.
Set<? extends A> can't be added to because you don't exactly what type you are adding to the collection, only that you are adding SOMETHING that extends A. You can guarentee that when you use get() you will get a class that extends A, but when you use add() because you don't know the definitive type, you can't add to the collection
If you want to take advantage of polymorphism, use Set<A>. This will do the exact same thing - any member that is type compatible, ie, extends, from A can be placed in the Set<K>.
EDIT:
#Anony-Mousse explained this much better with an example.

Why do we need bounded wilcard <? extends T> in Collections.max() method

I've read awesome "Effective Java" by Joshua Bloch. But one example in the books is left unclear to me. It's taken from chapter about generics, exact item is "Item 28: Use bounded wildcards to increase API flexibility".
In this item it's shown how to write the most universal and bulletproof (at the type system point of view) version of the algorithm of selection maximum element from collection using bounded type parameters and bounded wildcard types.
The final signature of the static method written looks like this:
public static <T extends Comparable<? super T>> T max(List<? extends T> list)
And it's mostly the same as the one of Collections#max function from standard library.
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
I understand why we need bounded wildcard in T extends Comparable<? super T> type constraint, but is it really necessary in type of the argument? It seems to me that it will be the same if we leave just List<T> or Collection<T>, isn't it? I mean something like this:
public static <T extends Comparable<? super T>> T wrongMin(Collection<T> xs)
I've written the following silly example of using both signatures and don't see any diferrence:
public class Algorithms {
public static class ColoredPoint extends Point {
public final Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
#Override
public String toString() {
return String.format("ColoredPoint(x=%d, y=%d, color=%s)", x, y, color);
}
}
public static class Point implements Comparable<Point> {
public final int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return String.format("Point(x=%d, y=%d)", x, y);
}
#Override
public int compareTo(Point p) {
return x != p.x ? x - p.x : y - p.y;
}
}
public static <T extends Comparable<? super T>> T min(Collection<? extends T> xs) {
Iterator<? extends T> iter = xs.iterator();
if (!iter.hasNext()) {
throw new IllegalArgumentException("Collection is empty");
}
T minElem = iter.next();
while (iter.hasNext()) {
T elem = iter.next();
if (elem.compareTo(minElem) < 0) {
minElem = elem;
}
}
return minElem;
}
public static <T extends Comparable<? super T>> T wrongMin(Collection<T> xs) {
return min(xs);
}
public static void main(String[] args) {
List<ColoredPoint> points = Arrays.asList(
new ColoredPoint(1, 2, Color.BLACK),
new ColoredPoint(0, 2, Color.BLUE),
new ColoredPoint(0, -1, Color.RED)
);
Point p1 = wrongMin(points);
Point p2 = min(points);
System.out.println("Minimum element is " + p1);
}
So can you suggest an example where such simplified signature will be inacceptable?
P.S. And why the heck there is T extends Object in official implementation?
Answer
Well, thanks to #Bohemian I've managed to figure out what's the difference between them.
Consider the following two auxiliary methods
private static void expectsPointOrColoredPoint(Point p) {
System.out.println("Overloaded for Point");
}
private static void expectsPointOrColoredPoint(ColoredPoint p) {
System.out.println("Overloaded for ColoredPoint");
}
Sure, it's not very smart to overload method both for superclass and its subclass, but it let us see what type of return value was actually inferred (points is List<ColoredPoint> as before).
expectsPointOrColoredPoint(min(points)); // print "Overloaded for ColoredPoint"
expectsPointOrColoredPoint(wrongMin(points)); // print "Overloaded for ColoredPoint"
For both methods inferred type was ColoredPoint.
Sometimes you want be explicit about type passed to overloaded function. You may do it a couple of ways:
You can cast:
expectsPointOrColoredPoint((Point) min(points)); // print "Overloaded for Point"
expectsPointOrColoredPoint((Point) wrongMin(points)); // print "Overloaded for Point"
Still no difference...
Or you can tell compiler what type should be inferred using syntax class.<type>method:
expectsPointOrColoredPoint(Algorithms.<Point>min(points)); // print "Overloaded for Point"
expectsPointOrColoredPoint(Algorithms.<Point>wrongMin(points)); // will not compile
Aha! Here is the answer. List<ColoredPoint> can't be passed to function expecting Collection<Point> because generics are not covariant (unlike arrays), but can be passed to function expecting Collection<? extends Point>.
I'm not sure where or who may prefer to use explicit type parameter in such case, but at least it shows where the wrongMin may be inappropriate.
And thanks to #erickson and #tom-hawtin-tackline for answers about purpose of T extends Object constraint.
The difference is in the type returned, especially influenced by inference, whereby the type may be a type hierarchically between the Comparable type and the List type. Let me give an example:
class Top {
}
class Middle extends Top implements Comparable<Top> {
#Override
public int compareTo(Top o) {
//
}
}
class Bottom extends Middle {
}
Using the signature you've provided:
public static <T extends Comparable<? super T>> T max(List<? extends T> list)
we can code this without errors, warnings or (importantly) casts:
List<Bottom> list;
Middle max = max(list); // T inferred to be Middle
And if you need a Middle result, without inference, you can explicitly type the call to Middle:
Comparable<Top> max = MyClass.<Middle>max(list); // No cast
or to pass to a method that accepts Middle (where inference won't work)
someGenericMethodThatExpectsGenericBoundedToMiddle(MyClass.<Middle>max(list));
I don't know if this helps, but to illustrate the types the compiler as allowed/inferred, the signature would look like this (not that this compiles, of course):
public static <Middle extends Comparable<Top>> Middle max(List<Bottom> list)
The difference between
T max(Collection<? extends T> coll)
and
T wrongMax(Collection<T> xs)
is that the return type of the second version is exactly the same as the collection's element type T, while in the first version T can be a super type of the element type.
The second question: the reason for T extends Object makes sure that T is a class and not an interface.
Update: A slightly more "natural" demonstration of the difference: Suppose you define these two methods:
static void happy(ColoredPoint p, Point q) {}
static void happy(Point p, ColoredPoint q) {}
And call the first one them like this:
happy(coloredPoint, min(points));
happy(coloredPoint, wrongMin(points));
The type inference engine could be able to deduce that in the first call the return type of min should be Point and the code would compile. The second call would fail to compile since the call to happy is ambiguous.
Unfortunately the type inference engine isn't powerful enough at least in Java 7, so in reality both calls fail to compile. The difference is that the first call can be fixed by specifying the type parameter as in Algorithms.<Point>min, while fixing the second call would require an explicit cast.
Not an easy one, but i'll try to be as specific as possible:
in T max(Collection<? extends T> coll)
you could pass an argument like this List<Animal> or List<Cat> or List<Dog>,
and in T wrongMax(Collection<T> xs)
where T is Animal you can't pass as an Argument this
List<Dog>, List<Cat> of course in Runtime you could add Cat or Dog objects in List<Animal> but in compilation time you wouldn't be able to pass a subclass of Animal in the Type of the List being passed as an argument in the wrongMax method, in the other hand, in the max method you could. Sorry for my english, i still learning it :), Regards.

java Generics Wildcard

I have a question on the use of wildcards in Java's generic types: what is the basic difference between List<? extends Set> and List<T extends Set>? When would I use either?
Two reasons:
To avoid unnecessary casts:
You have to use the T variant for cases like this:
public <T extends Set> T firstOf(List<T> l) {
return l.get(0);
}
With ? this would become:
public Set firstOf2(List<? extends Set> l) {
return l.get(0);
}
...which doesn't give the same amount of information to the caller of the firstOf method. The first version allows the caller to do this:
SubSet first = firstOf(listOfSubSet);
while with the second version, you are forced to use a cast to make it compile:
SubSet first = (SubSet)firstOf(listOfSubSet);
To enforce matching argument types:
public <T extends Set> boolean compareSets(List<T> a, List<T> b) {
boolean same = true;
for(T at : a) {
for (T bt: b) {
same &= at.equals(bt);
}
}
return same;
}
There is no direct equivalent using ? instead of T for this. Note that due to Java's single-dispatch, in the above version, the compiler will call at's equals(T) method which may well differ from at's equals(Set) or equals(Object) method.
The difference here is that in the second version, you have a type variable T that refers to the specific subtype of Set that the List contains. You need this in cases where you need to ensure that something else is the same type as the type contained in the list. A couple simple examples:
// want to ensure that the method returns the same type contained in the list
public <T extends Set> T something(List<T> list) {
...
}
// want to ensure both lists contain the exact same type
public <T extends Set> List<T> somethingElse(List<T> first, List<T> second) {
...
}
Simple rule: Use a type variable T extends Foo in your method signature if the same type is necessary in two places. Method parameters are each one place and the method return type is another place. Use the wildcard ? extends Foo if you just need to ensure you're dealing with "something that is a Foo" in one place.
Aside: don't use the raw type Set.
You use List<? extends Set> when you declare a varlable. For example:
List<? extends Number> l = new ArrayList<Integer>();
List<T extends Number> can be used in class or methode declaration. This will allow you to write T instead of <? extends Number> later on in the function.
public <T extends Number> int addAll(List<T> list) {
int result = 0;
for (T t : list) {
result += t.intValue();
}
return result;
}
We use wildcards to specify that the type element matches anything. The ? stands for unknown type.
List<? extends Set> is an example of a bounded wildcard and that states that the list can accept any subtype of a Set (e.g. HashSet)
List<T extends Set>, on the other hand is, allows T to be bounded to a type that extends Set.
I use wildcards when I need a collection of data irrespective pf it's exact type.
A wildcard type G<? extends A> is a super type of any G<Ai> where Ai is a subtype of A
In another word, G<? extends A> is the union type of G<A0>, ..., G<An>.

Categories

Resources