I have following two classes:
class ProblematicConverter implements Converter<List<?>> {};
class NonProblematicConverter implements Converter<List> {};
And method of class Utils:
<T> void addConverter(Class<? extends T> cls, Converter<T> converter);
Now, first function invocation is ok but second produces error:
addConverter(List.class, new ProblematicConverter());
addConverter(List.class, new NonProblematicConverter());
Error says:
"The method addConverter(Class, Converter) in the type Utils is not applicable for the arguments (Class, ProblematicConverter)"
I do not understand why it's like that.
Based on your comment, I think the right thing to do here might be to use an unchecked cast on List.class, but first, the reason the code in the question doesn't compile is roughly:
T of addConverter is inferred to be List<?>.
The bounded wildcard in cls requires that its type argument be T or a subtype of T, but the raw type List is a supertype of List<?> (specified here).
Therefore, Class<List> is incompatible with the inferred type of cls which is Class<? extends List<?>>.
So, for example, either of the following two declarations would compile with the invocations in the question:
<T> void m(Class<T> cls, Converter<? extends T> converter) {}
<T> void m(Class<? super T> cls, Converter<T> converter) {}
That of course doesn't help you out, but it illustrates the relationship between List and List<?>.
You might see also these two answers of mine which discuss similar situations.
So anyway, based on your comment saying that you're trying to eliminate raw types and can't change the declaration of addConverter, what could be appropriate is to use an unchecked cast from Class<List> to Class<List<?>>:
#SuppressWarnings("unchecked")
static final Class<List<?>> WILD_LIST =
(Class<List<?>>) (Class<? super List<?>>) List.class;
This will let you call e.g.:
addConverter(WILD_LIST, new ProblematicConverter());
However, I'd like to point out that unchecked casting is not a general solution. It's a solution to this specific problem of converting e.g. a Class<GenericType> to a Class<GenericType<?>>. It's safe to do because GenericType<?> is a more restrictive type than the raw type GenericType and because Class has a very limited range of things it can do with its type argument.
If you could change the declaration of addConverter, I think I would recommend using something like Guava TypeToken instead of Class, because then you don't have this sort of problem.
Related
I'm trying to use java.util.Function object as an input to a library class.
Function<? extends MyEntity, List> mapper;
public MyLibraryClass(Function<? extends MyEntity,List> mapper) {
...
}
public void aMethod(ClassExtendsMyEntity e) {
mapper.apply(e);
}
The line mapper.apply(e) doesn't compile.
If I change to use ? super instead of ? extends, then the fail will be in the client using this library in the following code:
Function<ClassExtendsMyEntity, List> mapper = e -> e.getListObjects();
new MyLibraryClass(mapper);
Can anyone help explain why getting this issue and if there is a way to get this working?
Function<? extends MyEntity,List> mapper;
This does not say "any subclass of MyEntity can be passed to mapper". It says "there exists some subclass of MyEntity that can be passed to mapper". It might be ClassExtendsMyEntity, it might be MyEntity itself, or it might be some crazy class that you've never even heard of.
Function<T, S> provides one function: S apply(T arg). Since your argument type is ? extends MyEntity, the only valid argument you can pass to mapper.apply is a value which is of every subtype of MyEntity at once, and there is no value that satisfies that condition.
Put more technically, the first argument of Function<T, S> is, in principle, contravariant, so using the covariant ? extends T annotation makes little sense on it.
Depending on what you want, there are two solutions. If your function works for any MyEntity, then you should simply write Function<MyEntity, List> and forgo the generics/wildcards altogether. On the other hand, if you want MyLibraryClass to support only one subtype, but a subtype that you know about, then you need to make that a generic argument to MyLibraryClass.
public class MyLibraryClass<T extends MyEntity> {
Function<? super T, List> mapper;
public MyLibraryClass(Function<? super T, List> mapper) {
...
}
public void aMethod(T e) {
mapper.apply(e);
}
}
Again, the first type argument of Function is, in principle, contravariant, so we should use ? super T to bound it by our type argument T. That means that if I have a MyLibraryClass<ClassExtendsMyEntity>, the function inside that might be a Function<ClassExtendsMyEntity, List>, or a Function<MyEntity, List>, or a Function<Object, List>, since all of those support ClassExtendsMyEntity arguments. For more on the reasoning behind that, see What is PECS.
The declaration Function<? extends MyEntity,List> mapper means:
mapper expects an argument of some type X which is a subtype of MyEntity. The problem is, it doesn't tell what type it is.
And therefore the compiler can't verify if your call passing an instance of type ClassExtendsMyEntity is valid. After all X might be SomeOtherClassExtendingMyEntity.
In order to fix this just make the function type Function<MyEntity,List>
<D extends com.j256.ormlite.dao.Dao<T,?>,T> D getDao(Class<T> clazz)
I am not able to understand above statement
getDao(Class clazz) returns D
D having following constraints
D extends com.j256.ormlite.dao.Dao<T,?>
and extra ,T i am not able to understand.
Could you please explain it ?
This method has two type parameters, D and T, with D having an additional extends constraint, depending on T. Don't get confused by this <T,?>,T syntax; the ,T does not belong to the constraint, but is the second parameter, telling Java that T is not the name of a concrete class.
If you add a space or swap the parameters, it will be clearer. Here's a similar, but somewhat simpler example. These method signatures are all equivalent:
<D extends List<T>,T> D createListOf(Class<T> clazz) // your version
<D extends List<T>, T> D createListOf(Class<T> clazz) // extra space
<T, D extends List<T>> D createListOf(Class<T> clazz) // different order
Keep in mind that, even though it may seem apparent that T is another type parameter, this is not clear to Java. There could be an actual class named T, so we have to be explicit that T is a type parameter.
class T { ... } // this T is not what I want!
Conversely, type parameters are not restricted to single characters. You could also have a type parameter called Foo, or even String, if you want to utterly confuse your co-workers. Maybe that makes clear why the declaration of all type parameters using <...> is necessary.
// just a deterrent example; don't do this! String as parameter, not class
<String, Foo extends List<String>> Foo createListOf(Class<String> clazz)
This method will:
Return an object of type D
Where D is or extends com.j256.ormlite.dao.Dao, parametrized with an object of type T or extending/implementing T and an unknown type parameter
If given as argument a class of type T
It uses a lot of generic abstraction, which is not surprising given it delivers a DAO (Data Access Object).
I'm attempting to write a method that will take a Collection<?> and remove all objects that are not of type T, returning either the original collection or a new collection, shown in this method signature:
public static <T,C extends Collection<T>> C objectsOfType(Collection<?> in, Class<T> type, Class<C> collectionType);
For example, I have a Collection<?> which contains Strings, and some other objects. I want a List<String> from it:
Collection<?> allObjects = getAllObjects();
List<String> stringObjects = objectsOfType(allObjects, String.class, ArrayList.class);
It all works out in the end. objectsOfType will return allObjects if it is an ArrayList containing only Strings, and will otherwise create a new ArrayList<String> and populate it with the String elements of allObjects. I would need to add another argument to allow any List to be returned since ArrayList is more specific than necessary for the return value, because the class must have a constructor. But that's not the problem.
The problem is a compiler warning on the invocation of objectsOfType, and I can't figure out why:
Type safety: Unchecked invocation
objectsOfType(Collection<capture#1-of ?>, Class<String>, Class<ArrayList>)
of the generic method objectsOfType(Collection<?>, Class<T>, Class<C>)
of type CollectionUtilities
What's causing this warning, and how can I fix it? As far as I can tell, everything is safe. The implementation of the method itself is not in question. That doesn't raise any warnings. Only its invocation is the problem.
ArrayList.class is not assignable to Class<C>, i.e., Class<List<String>> in a strict/checked context, so passing this argument requires an unchecked assignment, hence the warning. The type of ArrayList.class is simply Class<ArrayList>, where ArrayList is a raw type. There is no way to use the .class operator to specify the class ArrayList<String>.
Do you really need the Class<C> argument in the signature? What if you replaced it with a factory callback (e.g., something like Java 8's Supplier<C>)?
Alternatively, just return a List<T> (and use the same List implementation in all cases), simplifying your signature in the process:
public static <T> List<T> objectsOfType(Collection<?> in, Class<T> type);
You could also drop the wildcard and let the compiler infer the source item type:
public static <T, R> List<R> objectsOfType(Collection<T> in, Class<R> type);
Note, however, that both of the above are lax with respect to the input collection type (which you may have intended). If you want to be strict, you could limit the input item type to a superclass of the result type:
public static <T> List<T> objectsOfType(Collection<? super T> in, Class<T> type);
I am having an issue with generics and what I presume is type erasure whilst trying to reflect some generic information.
I am using a class based on http://www.artima.com/weblogs/viewpost.jsp?thread=208860 to do the reflection, but that isn't the issue.
The code below demonstrates the issue:
private <U extends MyClass1> U doSomething(MyClass2<U> p) {
Class<U> classIWant = null;
for (Class<?> c : GenericTypeUtils.getTypeArguments(MyClass2.class, p.getClass())) {
if (MyClass1.class.isAssignableFrom(c)) {
classIWant = c.asSubclass(MyClass1.class);
break;
}
}
}
Unfortunately the line
classIWant = c.asSubclass(MyClass1.class);
Shows the following error
java: incompatible types
required: java.lang.Class<U>
found: java.lang.Class<capture#4 of ? extends MyClass1>
And that's really confusing me. U extends MyClass1 and therefore U is a MyClass1.
Obviously there is some piece of type erasure I am not understanding here - can anybody help, please. BTW this is Java 1.7.0_40
Thanks
Conrad Winchester
The method asSubclass() is implemented like so
public <U> Class<? extends U> asSubclass(Class<U> clazz) {
if (clazz.isAssignableFrom(this))
return (Class<? extends U>) this;
else
throw new ClassCastException(this.toString());
}
with a return type of Class<? extends U>. Note, that your U and the U in the asSubclass method are completely unrelated type variables.
So the method asSubclass() returns a value declared with the type Class of some unknown subtype of U, where U in this case is MyClass1.
You are trying to assign this value to a variable of type Class with some known subtype of MyClass1. The compiler can't guarantee that they match and therefore doesn't allow compilation.
You can cast the returned value if you wish, but may end up getting ClassCastException at runtime, if the types don't match.
The Java compiler is unable to guarantee that the Class object c matches the generic type U. Because of type erasure, it is up to the compiler to guarantee type safety, and ensure that the Class coming back from c.asSubclass matches Class<U>, but it can't.
The asSubclass method returns a Class<? extends U>. In the Class class, U represents the type of Class passed into asSubclass. When you call it, that is c. But the compiler cannot guarantee that this return type matches your own declared <U extends MyClass1>. They could be different subclasses of MyClass1.
If you can guarantee that c.asSubclass will return a Class<U>, then cast it as a Class<U>:
classIWant = (Class<U>) c.asSubclass(MyClass1.class);
You will receive an "unchecked cast" warning. This is there because the compiler cannot guarantee that is really is a Class<U>, but you are saying that it is. Be careful as this may result in a hard-to-track-down ClassCastException elsewhere, even after you return the U. Do this only if you can guarantee the type safety yourself.
I'm reading "Generics in the Java Programming Language" by Gilad Bracha and I'm confused about a style of declaration. The following code is found on page 8:
interface Collection<E>
{
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
interface Collection<E>
{
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
// hey, type variables can have bounds too!
}
My point of confusion comes from the second declaration. It's not clear to me what the purpose the <T> declaration serves in the following line:
public <T> boolean containsAll(Collection<T> c);
The method already has a type (boolean) associated with it.
Why would you use the <T> and what does it tell the complier?
I think my question needs to be a bit more specific.
Why would you write:
public <T> boolean containsAll(Collection<T> c);
vs
public boolean containsAll(Collection<T> c);
It's not clear to me, what the purpose of <T> is, in the first declaration of containsAll.
As far as I can tell, in this case <T> doesn't provide anything useful at all. It creates a method that is completely functionally equivalent to those using the wildcard instead.
Here are a couple of examples where it would be useful:
public List<?> transform(List<?> in);
//vs
public <T> List<T> transform(List<T> in);
In the above, you can correlate the return type with the input type. The first example cannot correlate the runtime type of the two wildcards.
public void add(List<?> list, Object obj);
//vs
public <T> void add(List<? super T> list, T obj);
In the above, the first method won't even be able to add obj to list since it can't be deemed to be type safe. The generic parameter in the second ensures that list can hold whatever type obj is.
The method already has a type (boolean) associated with it.
That is the return type. The full type of the method is “method that takes a Collection<T> (for some T) parameter and returns a boolean”.
And this is where T comes in: the parameter of the function uses it. In other words, this method can be called with different types as argument. The only restriction of these types is that they must implement the Collection<T> interface, which itself relies on a generic argument T (the type of the objects stored in the collection).
The ? is simply a wildcard. It means that the method will accept a Collection of any type.
The <T> is a type parameter for the method. It is essentially assigning the wildcard a name which can then be referred to elsewhere in the method declaration and definition.
A better illustration of the difference would be if the return type of the method varied based on the type that was passed in.
Say you started with a method like
Object getRandomElement( Collection<?> c )
This will accept any Collection, but there's no way to constrain its return type. So a caller would have to cast the result back to whatever type it expected -- which should work, but raises unsafe type-conversion warnings.
With a type parameter you would instead write
<T> T getRandomElement( Collection<T> c )
In this case, if you call this method with a Collection<String>, the compiler knows that it will return a String.
<T> as used here (in method declaration, before return type) is a generic type declaration. You can define new generic type for use within a method: http://download.oracle.com/javase/tutorial/java/generics/genmethods.html
Try compiling it without the <T>.
Basically, it's telling the compiler that this method contains a generic. It isn't required in the first example because ? is a special case, and the second method is referencing the type defined in the Interface itself.
On an unrelated note, public is not required in an Interface. Methods in an interface are public by default, so can save you a bit of typing.
It declares the generic type T used by the method. While the generic type E is the same for the whole interface T is limited to the method it is declared for.