Java generic of generic factory not compiling - java

I have a CacheListener<T> and a CacheListenerLoader which implements CacheListener<Activity>.
I then have a Provider<CacheListenerLoader> Guice so the type has to be CacheListenerLoader so google produces the right ones.
Line 4 does not compile:
CacheListenerLoader listTemp;
OurCacheListener<Activity> t2 = listTemp;
Provider<CacheListenerLoader> prov;
Provider<OurCacheListener<Activity>> temp = prov;
That is important because I am trying to call this method:
private <T> void put(Class<T> klass, Provider<OurCacheListener<T>> provider)
then pass the right combination of Provider and class type so that I'm guaranteed at compile time the class type lookup results in something that can process the given class.
I pass in Activity.class and temp to my put method and that works fine and checks the types. The key is the 4th line above is not working which looks like generics is failing me here but I am not sure why since it is a compile time thing.

I'm going to assume that CacheListener is the correct type and what you want to do is pass your Provider<CacheListenerLoader> to your put method.
The problem here is that a Provider<CacheListenerLoader> is not a subtype of Provider<CacheListener<Activity>> in the world of generics. It's just like how you can't assign a List<Integer> to the type List<Number>... because if you did that, you'd be allowed to add Doubles to the List<Number> and then try to retrieve them from the List<Integer> as Integers, causing a ClassCastException.
Of course, since you can't add anything to your providers, this isn't an issue. But you still have to tell the type system that! What you need to do is change the signature of put to:
private <T> void put(Class<T> clazz,
Provider<? extends CacheListener<T>> provider)
This says that you just want any provider that can return something that is a CacheListener<T> and that you don't need to be able to call any methods that try to consume a CacheListener<T>.

You need wo use some wildcards. Which ones exactly is not easy for me to tell because you provide so little code, but I'd say something like
Provider<? extends OurCacheListener<Activity>> temp = prov;
For reference, read
Java Generics and Collections
Angelika Langer's Generics FAQ
Java theory and practice: Going wild
with generics, Part 2

you stumbled over a generics restriction: Provider and Provider are not compatible, even if A extends or implements B.

Related

How to use a generic class as a parameter and extend the type?

I am attempting to use generics in my project to have a base class that can make use of different types of objects. But I am having trouble when trying to pass these generic typed classes as parameters in some cases.
So I guess my question is, is there any way to use a certain generic typed interface and pass in extensions of the generic type?
I am sorry if I am phrasing this strangely, I am not very used to trying to explain these types of questions. I would be glad for some kind of insight into generics, I feel like I can't get a grip on how they really worked. I have read many posts about them but I couldn't find any that describe my problem or really help me understand it all.
I have tried numerous variations on extending the generic type T, also trying to use wildcards. But I always just end up with way to many nested generics and captures of wildcards and I just make a mess.
I have this interface:
public interface NiceObject<T extends SomeClass> {}
And then I want to be able to extend it with different implementations:
public class EpicClass extends SomeClass {}
public class CoolObject implements NiceObject<EpicClass> {}
This works fine for me, but when I attempt to pass an implementation of NiceObject as a parameter of type NiceObject<T> where T is an extension of SomeClass it tells me that the type is not applicable.
public void coolMethod(NiceObject<SomeClass> obj);
CoolObject obj = new CoolObject();
coolMethod(obj);
// this does not work
I have also tried changing the method in some ways:
public void coolMethod(NiceObject<?> obj);
public void coolMethod(NiceObject<? extends SomeClass> obj);
public <S extends SomeClass> void coolMethod(NiceObject<S> obj);
// None of these produce my desired result
// I just end up with non-applicable parameters somewhere in my program.
EDIT
I'll try to make my question a bit clearer:
NiceObject<EpicClass> obj = new CoolObject();
coolMethod(obj);
// Message:
// The method coolMethod(NiceObject<SomeClass>) in the type NiceMethods
// is not applicable for the arguments (NiceObject<EpicClass>)
What confuses me is that EpicClass is clearly an extension of SomeClass, shouldn't the compiler be able to accept it as a SomeClass because it inherits the same properties as one?
EDIT 2
It seems like I have resolved my issue now. I have a tendency to solve my problem right after I make a post about it.
As a comment proposed, it was more about the problems it caused in other parts of the program. I didn't want to mix in other parts of my program because the structure of it and my overuse of generics is kind of dumb and I did not want to make it even more confusing.
When I modified the coolMethod() to be able to accept any kind of NiceObject<SomeClass> other problems appeared. I had methods in a NiceObject that had to use it's own type of NiceObject as parameters. I solved it by creating a method that would return itself and subtypes would implement that method.
public interface NiceObjectUser <N extends NiceObjectUser<N>> {
public N getSelf();
}
I also did other silly things to make the errors disappear and I had to refactor quite a few other classes. in the end though, it works so whatever.
I do appreciate the answer which explained some things about generics which I have now accepted. I now feel like I have a greater level of understanding of generics.
The issue here is that even though EpicClass is a subtype of SomeClass, NiceObject<EpicClass> is a subtype of NiceObject<SomeClass>. To see why, consider:
class Box<T> {
private T value;
T get() {
return value;
}
void set(T value) {
this.value = value;
}
}
Now think of two classes like Object and String, where String is a subtype of Object. Let's say we allowed Box<String> to be a subtype of Box<Object>. That would mean you can use a Box<String> anywhere that was expecting a Box<Object>. Now think about code like this:
Box<String> stringBox = new Box<String>();
Box<Object> objectBox = stringBox;
objectBox.set(new NonStringObject());
String string = stringBox.get(); // Error! Got a NonStringObject() from a string box!
In general, the fact that a box might consume a T or produce a T means that subtyping rules don't work the way you might expect. In general the proposed alternatives you posted are the way to go when you run into a problem like this; in order to figure out why they're not working we're going to have to know more about the specifics of what you're trying to do.

Java generics - When is ? wildcard needed

Say you have some class with type T:
class MyClass<T extends SomeOtherClass> {
....
}
Now, you want to store instances of this class into a collection, but you don't really care about the type. I would express this as following:
private final List<MyClass> entries = new ArrayList<>();
Is there any good reason/advantage to write the following instead?
private final List<MyClass<?>> entries = new ArrayList<>();
Or even:
private final List<MyClass<? extends SomeOtherClass> entries = new ArrayList<>();
I myself can only find a bad reason to do this: whenever the type definition of MyClass changes (for example addition of another type), you have to alter the List<MyClass<?>> or List<MyClass<? extends SomeOtherClass>> definitions all over your code as well.
update
To update my question:
Why isn't the compiler to be able to track the type(s) of MyClass when your write List<MyClass> (or even List<MyClass<? extends SomeOtherClass>>)? He knows that MyClass is defined as MyClass<T extends SomeOtherClass>, so why isn't he able/allowed to do that when you write List<MyClass>?
In other words, why is List<MyClass> not equal to List<MyClass<?>> (or even List<MyClass<? extends SomeOtherClass>>)? The compiler has all the information to make that conclusion himself, afaik.
The ? wildcard is useful when you don't need to refer to the type again and so you don't need to make a specific identifier.
Your first snippet starts with class MyClass<T extends SomeOtherClass>. This is necessary when T is important later on, perhaps to declare a field argument, or return type. For example:
class MyClass<T extends SomeOtherClass> {
private final List<T> aListOfT;
public T getSomething() {
return this.aListOfT.get(0);
}
Since MyClass is a generic type, all references to it should be qualified to avoid avoidable runtime errors. Thus when you declare List<MyClass> you get a compiler warning that you use the raw type MyClass. If you don't care at that location in the code what sort of type MyClass is qualified with, then you use the ? to tell the compiler that you don't care and let it track the type and check all operations for validity.
Your first declaration means, you are not giving any information about your generic data for the future reflection systems, could be used by plugins, which are written for your main program.
The second declaration tells them, that the field contains an Object generics.
The third one is the more specific, it means, that the reflection systems knows, what is this field about detailly.
Using the first type, java will assume that the generic type is Object. The reason for this is, that generics were introduced in version 1.5. Before then the collection-classes stored everything as an object. For compatibility reasons giving no generic parameter means that you are using object.
The second type simply says you don't know or don't care what type it is. This information is preserved when the code gets compiled. So other programmer who might use your code would know that you don't care.
Because of java's type-erasure, there is no difference between these two at runtime.
With the last form you say:
I don't care what it is, but it has to be SomeOtherClass or a derivated type. Which is the same as:
List<MyClass<SomeOtherClass>>
You can also do it the other way around:
List<MyClass<? super SomeOtherClass>>
says that you don't care what type it is, unless it is a supertype of SomeOtherClass.

Proper use of Java Generics

I have the following function:
/**
* Finds all entities of a certain type
* #param <T> The type of the entity
* #param entityType The class of the entity
* #return A list of all the entities found, null if the entity is not in the database
* or on error
*/
public <T> List<T> findAll(Class entityType)
{
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityType));
return getEntityManager().createQuery(cq).getResultList();
}
You will note it is rather repetitive. Is there anyway that I can refactor this function so that it does not need to take a Class as a parameter. Is there anyway that I can use the generic type being passed in?
No, you cannot — directly. In a couple paragraphs I'll show you another way around the problem.
Java generics are implemented via type erasure, meaning that all type information is stripped away at runtime. When your method is invoked, it knows that it is supposed to return a List, but at run time there is nothing to tell it that it is supposed to return List<Foo>. The ArrayList constructor doesn't need access to the class object to do its job; your code, however, does.
The way around this is to just pass the class which, since this is a generic method (as opposed to a generic class), you can do. If you change the declaration of your method to be
public <T> List<T> findAll(Class<T> entityType)
Then you can call it with the class:
findAll(String.class)
and the compiler will automatically detect that it is supposed to return a List<String>. It reduces the redundancy, but by inferring the type argument from the class rather than the other way around. This is the standard way to solve this kind of problem — it shows up a lot in libraries like Guava.
The standard practice to create a "Generic DAO" is to have an abstract class that is parametrizable and have subclasses with a specific parameter. This way, the method itself is already parametrized with the correct type.
Take a look at this for an example:
http://netbeans.org/projects/samples/sources/samples-source-code/content/samples/javaee/AffableBean/src/java/session/AbstractFacade.java
Not really, no. Generics are a compile time feature. At run time a caller of your API can supply any instance of Class<T> for entityType so you need it available at runtime to provide to hibernate. The compiler has no ability to basically build a separate version of the method for every possible T, which is what it would have to do in order to omit the class parameter.
Also, Class is a raw type, you are already using generics improperly ;)
Java uses Type erasure, which means that the generic type parameter is not available at runtime (used at compile time to ensure your code is correct wrt to types). This means that to use persistence you will need to explicitly pass the class so the runtime can figure out how to do the persistence (e.g. what class the persisted object belongs to)
The simple answer is "no". Due to something called type erasure, all parameterized types are treated as Object.class at runtime in the compiled bytecode. The generic types are only used at compile time to prevent you from using things wrong.
You can more or less do what you're asking in Scala. (I'm not sure if you can use scala, but just for reference, here it is).
object Main extends App{
def findAll[T : Manifest]() : Array[T] = {
var a = new Array[T](0)
println(a.getClass)
a
}
var result = findAll[String]()
println(result.getClass)
var result2 = findAll[Array[Int]]()
println(result2.getClass)
}
By using the implicit Manfiest, the scala compiler keeps a record of what generics get erased on compile.

Creating a generic array instance in a generic method

I'm trying to build a helper method to turn the two line list to array conversion into a single line. The problem I've ran into is that I'm not sure how to create a a T[] instance.
I've tried
Array.newInstance(T.class, list.size) but I can't feed it T.class..
Also tried new T[](list.size) but it doesn't like the parameters.
public <T> T[] ConvertToArray(List<T> list)
{
T[] result = ???
result = list.toArray(result);
return result;
}
Any other ideas?
Thanks
You can't mix generics and arrays like that. Generics have compile-time checking, arrays have runtime checking, and those approaches are mostly incompatible. At first I suggested this:
#SuppressWarnings("unchecked")
public <T> T[] ConvertToArray(List<T> list)
{
Object[] result = new Object[list.size()];
result = list.toArray(result);
return (T[])result;
}
This is wrong in a stealthy way, as at least one other person on here thought it would work! However when you run it you get an incompatible type error, because you can't cast an Object[] to an Integer[]. Why can't we get T.class and create an array the right type? Or do new T[]?
Generics use type erasure to preserve backward compatibility. They are checked at compile time, but stripped from the runtime, so the bytecode is compatible with pre-generics JVMs. This means you cannot have class knowledge of a generic variable at runtime!
So while you can guarantee that T[] result will be of the type Integer[] ahead of time, the code list.toArray(result); (or new T[], or Array.newInstance(T.class, list.size());) will only happen at runtime, and it cannot know what T is!
Here's a version that does work, as a reward for reading that lecture:
public static <T> T[] convertToArray(List<?> list, Class<T> c) {
#SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(c, list.size());
result = list.toArray(result);
return (T[]) result;
}
Note that we have a second parameter to provide the class at runtime (as well as at compile time via generics). You would use this like so:
Integer[] arrayOfIntegers = convertToArray(listOfIntegers, Integer.class);
Is this worth the hassle? We still need to suppress a warning, so is it definitely safe?
My answer is yes. The warning generated there is just an "I'm not sure" from the compiler. By stepping through it, we can confirm that that cast will always succeed - even if you put the wrong class in as the second parameter, a compile-time warning is thrown.
The major advantage of doing this is that we have centralised the warning to one single place. We only need to prove this one place correct, and we know the code will always succeed. To quote the Java documentation:
the language is designed to guarantee that if your entire application has been compiled without unchecked warnings using javac -source 1.5, it is type safe[1]
So now rather than having these warnings all over your code, it's just in one place, and you can use this without having to worry - there's a massively reduced risk of you making a mistake by using it.
You may also want to look at this SO answer which explains the issue in more depth, and this answer which was my crib sheet when writing this. As well as the already cited Java documentation, another handy reference I used was this blog post by Neal Gafter, ex senior staff engineer at Sun Microsystems and co-designer of 1.4 and 5.0's language features.
And of course, thanks to ShaneC who rightly pointed out that my first answer failed at runtime!
If you can't pass in T.class, then you're basically screwed. Type erasure means you simply won't know the type of T at execution time.
Of course there are other ways of specifying types, such as super type tokens - but my guess is that if you can't pass in T.class, you won't be able to pass in a type token either. If you can, then that's great :)
The problem is that because of type erasure, a List does not know it's component type at runtime, while the component type is what you would need to create the array.
So you have the two options you will find all over the API:
pass in the Array's component class (as suggested by Jon Skeet) or
create an Object[] array and cast it (as suggested by ZoFrex)
The only other possibility I can think of would be a huge hassle:
Iterate over all items of the list and find the "Greatest Common Divisor", the most specific class or interface that all the items extend or implement.
Create an array of that type
But that's going to be a lot more lines than your two (and it may also lead to client code making invalid assumptions).
Does this really need to be changed to a one-liner? With any concrete class, you can already do a List to Array conversion in one line:
MyClass[] result = list.toArray(new MyClass[0]);
Granted, this won't work for generic arguments in a class.
See Joshua Bloch's Effective Java Second Edition, Item 25: Prefer lists to array (pp 119-123). Which is part of the sample chapter PDF.
Here's the closest I can see to doing what you want. This makes the big assumptions that you know the class at the time you write the code and that all the objects in the list are the same class, i.e. no subclasses. I'm sure this could be made more sophisticated to relieve the assumption about no subclasses, but I don't see how in Java you could get around the assumption of knowing the class at coding time.
package play1;
import java.util.*;
public class Play
{
public static void main (String args[])
{
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("Shalom");
list.add("Godspidanya");
ArrayTool<String> arrayTool=new ArrayTool<String>();
String[] array=arrayTool.arrayify(list);
for (int x=0;x<array.length;++x)
{
System.out.println(array[x]);
}
}
}
class ArrayTool<T>
{
public T[] arrayify(List<T> list)
{
Class clazz=list.get(0).getClass();
T[] a=(T[]) Array.newInstance(clazz, list.size());
return list.toArray(a);
}
}

Code explanation in Java

this morning I came across this code, and I have absolutely no idea what that means. Can anyone explain me what do these <T> represent? For example:
public class MyClass<T>
...
some bits of code then
private Something<T> so;
private OtherThing<T> to;
private Class<T> c;
Thank you
You have bumped into "generics". They are explained very nicely in this guide.
In short, they allow you to specify what type that a storage-class, such as a List or Set contains. If you write Set<String>, you have stated that this set must only contain Strings, and will get a compilation error if you try to put something else in there:
Set<String> stringSet = new HashSet<String>();
stringSet.add("hello"); //ok.
stringSet.add(3);
^^^^^^^^^^^ //does not compile
Furthermore, another useful example of what generics can do is that they allow you to more closely specify an abstract class:
public abstract class AbstClass<T extends Variable> {
In this way, the extending classes does not have to extend Variable, but they need to extend a class that extends Variable.
Accordingly, a method that handles an AbstClass can be defined like this:
public void doThing(AbstClass<?> abstExtension) {
where ? is a wildcard that means "all classes that extend AbstClass with some Variable".
What you see here is something called Generics. They were introduced to Java in release 1.5.
You can read about them here and here. Hope this helps.
Imagine you're writing a List or Array class. This class must be able to hold elements of an unknown type. How do you do that?
Generics answers this question. Those <T> you're seeing can be read as some type. With generics you can write class MyList<T> { ... }, which in this context means a list that holds some type.
As an usage example, declare a list to store integers, MyList<Integer> listOfInts, or strings, MyList<String> listOfStrings, or one class you've written yourself MyList<MyClass> listOfMyClass.
What you are seeing is Java generics, which allows classes and methods to be parameterized by other classes. This is especially useful when creating container classes, since it saves you having to create separate classes for "a list of integers", "a list of strings", etc. Instead, you can have a single "list of some type T, where T is a variable" and then you can instantiate the list for some specific type T. Note that Java generics is not quite the same as template types in C++; Java generics actually use the same class definition but add implicit casting (generated by the compiler) and add additional type-checking. However, the different instantiations actually make use of the same exact type (this is known as erasure), where the parameterized types are replaced with Object. You can read more about this at the link.
Since noone has mentioned it yet, there is a very comprehensive guide/FAQ/tutorial on generics which can be found on Angelika Langer's site.

Categories