I am trying to understand this method signature:
public final <T> FluentIterable<T> transform(Function<? super E,T> function)
(taken from http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/FluentIterable.html#transform%28com.google.common.base.Function%29)
I understand that transform returns a FluentIterable<T>, but I don't understand what the <T> before FluentIterable<T> means?
Further, in Function<? super E,T>, I understand what ? super E means, but I can't imagine how the compiler can check this - isn't E unknown at compile time, so how shall the compiler know, if ? is a supertype of E?
<T> means that this is a method with the generic type parameter T. This is similiar to <T> after a class name (like List<T>), just for methods.
E is not unknown at compile time. E is also a generic type parameter defined in the class definition:
public abstract class FluentIterable<E> extends Object implements Iterable<E>
When you create an instance of this class the compiler knows the type of E.
Related
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.
What is the difference between the following two method declarations:
1. <R> Stream<R> myFunc(Function<? super T, ? extends R> mapper);
2. Stream<R> myFunc(Function<? super T, ? extends R> mapper);
For the 2nd declaration to compile, I need to add type parameter to class like this.
public class MyGenericsTest<T, R>
In this case compiler is ensuring that the return type of myFunc is determined at the compile time. The compiler could have known that from the method signature as well. I am confused on why these 2 declarations are treated differently by compiler.
By writing <R> Stream<R> myFunc(Function<? super T, ? extends R> mapper) you are telling the compiler that:
R is any class and is local to the method (by starting with<R> at the beginning)
The return type is a Stream of R
T is a class specified in the type parameter of MyGenericsTest<T> (if you dont specify it, it wont work as the compiler will not know T)
If you change to Stream<R> myFunc(Function<? super T, ? extends R> mapper), R and T are not local (no <R, T> at the beginning of the method) and the compiler expects them to be defined at a class level as MyGenericsTest<T, R>
The second form:
Stream<R> myFunc(Function<? super T, ? extends R> mapper);
really isn't any different from this:
Stream<String> myFunc(Function<? super T, ? extends String> mapper);
to the compiler, except that it uses a different type. The second one returns a stream of String. The first one returns a stream of R, whatever R is. The compiler already knows what String is. For the first one, the compiler has to know what R is, which means it has to be defined somewhere. It can be a generic parameter on an outer class, but it could also be a non-generic class that you import from somewhere else (written by someone who is very bad at coming up with meaningful names).
Keep in mind that although we often use single upper-case letters as generic parameters, that's just a human convention. The compiler just treats it like any other identifier.
But that's why your two examples are so different. The first one is a syntax that defines the method as a generic method with a type parameter that you're calling R. The second one is the exact same syntax as a method that returns Stream<String> or List<Integer> or something.
<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 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've got this code:
public <T extends Scrapper> Class<T> getScrapper() {
return MyScrapper.class;
}
MyScrapper is a class implementing Scrapper interface. Why is this not working? U'm getting the following error in JDK7:
error: incompatible types
required: Class<T>
found: Class<MyScrapper>
where T is a type-variable:
T extends Scrapper declared in method <T>getScrapper()
P.S.
I've honestly tried searching for whole 30-40 minutes.
Update:
if i declare the method as public Class<? extends Scrapper> getScrapper() { it works. but I still don't understand why the original declaration was not compiling. what's wrong with it?
With a generic method like getScrapper(), the caller of the method determines what the actual type argument to the method is (T in this case). The caller could pick any subtype of Scrapper as T, and your method (which always returns MyScrapper.class) would not be returning the correct class.
Given the signature of the method, the caller of this method would expect to be able to do this:
Class<MyOtherScrapper> c = foo.<MyOtherScrapper>getScrapper();
Changing the method to return Class<? extends Scrapper> makes it no longer a generic method... there are no type parameters for the caller to set. Instead, the signature says that the method returns the class object for some unknown subtype of Scrapper, and MyScrapper.class does fit the bill for that.