I know what ArrayList<T> is used for, but when should I use ArrayList<?> ? can you explain with example? thanks.
As far as I've been able to tell, ArrayList<?> basically tells the compiler:
Yes, I know that there is a generic version of ArrayList available to me, but I really, genuinely don't know what kind of objects I'm expecting to be in this one. So don't give me warnings that I'm not using generics the way I should be.
Update
I just learned that there is a real difference between using Raw Types (ArrayList) and generics with wildcards (ArrayList<?>) that goes beyond avoiding compiler warnings. Apparently once you declare something as a Raw type, no generics will work on any methods of that type, even if the generics weren't based on the type you omitted. See here for an example.
So while my original answer was generally correct, I thought it would be important to mention that using ArrayList<?> instead of ArrayList is more than just a matter of removing compiler warnings.
http://download.oracle.com/javase/tutorial/java/generics/wildcards.html
Note: It's also possible to specify a lower bound by using the super
keyword instead of extends. The code <? super Animal>, therefore,
would be read as "an unknown type that is a supertype of Animal,
possibly Animal itself". You can also specify an unknown type with an
unbounded wildcard, which simply looks like <?>. An unbounded wildcard
is essentially the same as saying <? extends Object>.
ArrayList<?> indicates a collection of an unknown object, that is, it can be anything. It is possible to read from it, but you cannot write to it.
It sounds something like that:
I am a collection! I can read the unknown, but since I do not know what its type, I cannot add stuff
see this very useful tutorial by Oracle.
Also, I find these slides from an MIT Software Construction class very useful, and this generics tutorial.
Here is a concrete example. Let's say you have a
class Base {}
Then class Extender extends Base{}
Now if you have Collection<Extender> collection and you want to call it using this method.
public void doSomething(Collection<Base> c){...}
Above will not work or copmpile. What will work is
doSomething(Collection<? extends Base> c)
This basically says that I don't care what type ? is but it has to extend Base. Now that you get that, it will help you understand what ? mean. It the same as using <? extends Object>
Related
I was wondering if it is possible to create a construtor function:
public <C, T> C newInstance(Class<C> constructor_class,
Class<T> type,
Object...parameters){
// create a new Instance with the generic type and the paramters
//so basicly like this, but with generics and parameters
return constructor_class.newInstance();
}
You basically can't. Your example is broken - what is type supposed to represent?
Let's say you want to dynamically create a HashMap<String, Integer>. This would require that you pass in HashMap.class, String.class, and Integer.class, but we run into a TON of problems right off the bat:
How do we know that HashMap has 2 args? We don't, so you'd have to pass 2 class references via varargs and at runtime I guess we throw an exception if you passed the wrong number of classes.
What if you pass Map, which cannot be instantiated at all?
But most of all, this is completely useless, generics that do not show up in method/field/class signatures are figments of the compiler's imagination: javac uses it during compilation to warn or error, as well as to generate invisible caste operations, and then chucks this info away. By doing it dynamically, all that 'at compile time' stuff cannot work by definition (we're compiling, not running, the whole point is for the types to be dynamic, so javac cannot do), so to javac it is useless, and the info is then chucked. So that makes it fully useless, then, no?
Furthermore, Class cannot be used to convey generics args. What if I wanted a HashMap<List<String>, Integer> instead? List<String> does not exist as a class literal, so java.lang.Class<T> cannot be used here. There are also class objects (specifically, int.class) that aren't legal in generics. So, we have ?, ? super Foo, A, B extends A, C extends A & Serializable, List<String> all as examples of things that can go in <> but which cannot be a java.lang.Class reference, and int.class that is a legal class ref but which cannot go in <>. You can't put a square peg in a round hole. Let alone the fact that even if you could, it would do literally absolutely nothing whatsoever (see point #3: This is useless - most generics, and definitely the generics you'd use here, affect compilation and cease to exist afterwards).
There are crazy hacks in this space (super type tokens, for example), but if you do not fully understand how generics work under the hood, there is 0.00001% or less chance you will be able to use such hacks usefully, so don't bother until then. And asking this question, especially with that pseudocode, strongly suggests you don't understand enough of it yet.
I've read the whole SCJP6 book Sierra and Bates book, scored 88% the exam.
But still, i never heard of how this kind of code works as it's not explained in the generics chapter:
Collections.<TimeUnit>reverseOrder()
What is this kind of generics usage?
I discovered it in some code but never read anything about it.
It seems to me it permits to give some help to type inference.
I've tried to search about that but it's not so easy to find (and it's not even in the SCJP book/exam!)
So can someone give me a proper explaination of how it works, which are all the usecases etc?
Thanks
Edit
Thanks for the answers but i expected more details :) so if someone want to add some extra informations:
What about more complex cases like
Using a type declared in class , can i do something like Collections.<T>reverseOrder() for exemple?
Using extends, super?
Using ?
Giving the compiler only partial help (ie O.manyTypesMethod<?,MyHelpTypeNotInfered,?,?,?,?,?>() )
It is explicit type specification of a generic method. You can always do it, but in most cases it's not needed. However, it is required in some cases if the compiler is unable to infer generic type on its own.
See an example towards the end of the tutorial page.
Update: only the first of your examples is valid. The explicit type argument must be, well, explicit, so no wildcards, extends or super is allowed there. Moreover, either you specify each type argument explicitly or none of them; i.e. the number of explicit type arguments must match the number of type parameters of the called method. A type parameter such as T is allowed if it is well defined in the current scope, e.g. as a type parameter of the enclosing class.
You are 100% correct, it is to help with type inference. Most of the time you don't need to do this in Java, as it can infer the type (even from the left hand side of an assignment, which is quite cool). This syntax is covered in the generics tutorial on the Java website.
Just a small addition to the other responses.
When getting the according compiler error:
While the "traditional" casting approach
(Comparator<TimeUnit>) Collections.reverseOrder()
looks similar to the generics approach
Collections.<TimeUnit>reverseOrder()
the casting approach is of course not type-safe (possible runtime exception), while the generics approach would create a compilation error, if there is an issue. Thus the generics approach is preferred, of course.
As the other answers have clarified, it's to help the compiler figure out what generic type you want. It's usually needed when using the Collections utility methods that return something of a generic type and do not receive parameters.
For example, consider the Collections.empty* methods, which return an empty collection. If you have a method that expects a Map<String, String>:
public static void foo(Map<String, String> map) { }
You cannot directly pass Collections.emptyMap() to it. The compiler will complain even if it knows that it expects a Map<String, String>:
// This won't compile.
foo(Collections.emptyMap());
You have to explicitly declare the type you want in the call, which i think looks quite ugly:
foo(Collections.<String, String>emptyMap());
Or you can omit that type declaration in the method call if you assign the emptyMap return value to a variable before passing it to the function, which i think is quite ridiculous, because it seems unnecessary and it shows that the compiler is really inconsistent: it sometimes does type inference on generic methods with no parameters, but sometimes it doesn't:
Map<String, String> map = Collections.emptyMap();
foo(map);
It may not seem like a very important thing, but when the generic types start getting more complex (e.g. Map<String, List<SomeOtherGenericType<Blah>>>) one kind of starts wishing that Java would have more intelligent type inference (but, as it doesn't, one will probably start writing new classes where it's not needed, just to avoid all those ugly <> =D).
In this case it is a way of telling the reverseOrder method what kind of ordering should be imposed on the object, based on what type you specify. The comparator needs to get specific information about how to order things.
Now and then in my code I find that I can solve a problem by either using a naked generic class or one with wildcards.
I have a design where a class like this:
Class World<T, C> { .... }
definitely in general is making my code cleaner than it would have been without generics.
Yet, sometimes I use
World theWorld;
or sometimes I end up with
World<?, ?> theWorld;
I do this because it seems to be what it takes to make the compiler accept it and my
attempts to avoid them lead me to more casting or inheriting complexity.
It looks ugly and smelly to me and yet I cannot justify the added complexity it looks like I need to introduce to avoid it.
What are some cases (if any) that you believe using a naked or wildcarded generic is acceptable idiomatic Java?
There is a good example (use case) of using <?> in the Wildcards section of the Generics tutorial.
A sort summary: if you want to write a printCollection method which accepts all kinds of Collection you could use Collection<?> as a parameter type. You cannot use Collection<Object> as the parameter type for this purpose because it is not a supertype of all kinds of collections.
Using Collection<?> instead of "pure" Collection in this case is safer because you cannot add items to Collection<?> (except for null) in the printCollection method.
Any time you could use generics but don't need it in that specific situation. <?> tells the compiler roughly: "I know about generics, but I don't need the type now".
Maybe the type is needed in other situation. E.g. if you have a Set that just stores anything, like a cache, and you just don't care for the type of the elements at all. At other times you do, when you process specific elements.
It smells if you use too loosely bound type parameters (like <?> which is quite loose) but try to determine the type afterwards, e.g. with instanceof or some custom type discriminator. Then something was designed poorly.
The Wildcard also proves as very useful, when you want to store multiple objects, that are a subclass of another class.
For example:
Collection<? extends Shape> myShapes
This Collection now could keep all the objects, that are a subclass of Shape.
So you are type-safe when adding any object that is a subclass of Shape. For Example:
myShapes.add(new Rectangle())
myShapes.add(new Triangle())
I have a class that has a propery List<String> or List<SomeObject>.
I get the type of the property as this:
propertyClass = PropertyUtils.getPropertyType(currentObject, property);
What I want to do is check that the propertyClass is a List<SomeType> and get the class object for the type in the list. After this I will want to create an ArrayList of the given type and fill it with object of that type (all created dynamically, I will use this to dynamically load some data from a file).
Is there I way I can do this using reflection?
Generics are erased after compilation (due to type erasure). So you can't use them at runtime.
I have a similar problem and I actually found a solution that works for me!
This can be done but it might be unreliable (i.e. it doesn't work in all situations).
First you need to get the "Field" (via reflections). Then get the "GenericType". Then try to cast this to "ParameterizedType". This is possible if it actually has a parameter.
Then get "ActualTypeArguments". Usually those are "Class"es, so you can cast them (if not you could try Class.forName(...)) and then you already have the type of the elements in the list.
However, this doesnt work if I do this:
class MyList extends List<String> {... }
And then later:
MyList list = new MyList(); // This would be List<String>
You'd actually need to inspect the type to see if it is a List and if it has a type declared in any class or interface. But there could be more than one and the type could be bound to many interfaces, not just one class.
of course you could just ignore properties that aren't "List" and maybe throw a compiler error if there is one (I'll probably do just that).
Then there is the problem with wildcards: List list = ...
All you can do is substitute it with "Object", but that isn't safe if you want to add elements to the list! (again, you could check that at compile time and throw an error if there are wildcards)
Another solution is to use a checked List (see Collections.checkedList(List, Class)) and try to get that type at runtime (you probably need reflection for that). This would work much better and would be much more robust than just generics.
I have found another answer by Bob Lee, Sven Mawson, and Jesse Wilson:
[public class TypeToken:] Represents a generic type T. Java doesn't yet provide a way to
represent generic types, so this class does. Forces clients to create
a subclass of this class which enables retrieval the type information
even at runtime.
Source: http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/reflect/TypeToken.html
There even is an example using List<String> and it really works. The TypeToken will have a rawType of java.util.List and typeArguments is set to [java.lang.String]. There is no type erasure here! However it does also not work for wildcards such as List<? extends Foo>.
Note that this is a bit different from the other solution I explained in my other answer. Here you don't analyze a property on a java bean to get the type information. Here you actually create a field that stores the type information. I can't find any public constructor or factory method to create a TypeToken from type information that you got some other way. So I guess it really can only be used as an empty anonymous inner class.
There have been a couple of times when I've felt the need to do something like the following:
private <T extends Type> Map<GenericClass1<T>,GenericClass2<T>> map;
...or something to that effect. Essentially, using an identical bound in the two arguments for map. (This isn't an actual example, just shows the idea.)
I know this (unfortunately) isn't possible and that it's only available on class definitions and method signatures. My question however is why isn't it available on fields? Is it purely a design choice or is there some technical reason behind it that I'm missing? I've had a think and can't see why this shouldn't be possible from a technical perspective, as far as I can see everything is there for the compiler to work it out correctly and none of the generic information is required at runtime.
<T> means ONE class, not A class.
When your object is instanced T is bound to this ONE class.
You are trying to put two objects with diffrent interfaces (used diffrently because they take/return diffrent types) in to the same container. This is a error because when you take them out of the container (the map) you dont know what it was you put in.
Hope this is the answer you were looking for.
Edit: That said you can have a container that holds members based on there class, to automatically create a new map for EACH type of T. You would then need to know what T was in order to access it.
In general, if you dont want the type information anymore, throw it away. If you do then putting it in the same container as something of another type will throw it away anyway for all practical reasons.
Let's assume that you want to instantiate your map variable. Theoretically you will have to write something like this:
map = new HashMap<GenericClass1<String>,GenericClass2<String>>();
Ok. But now what does not make sense to me anymore is what arguments the put or get methods will accept/return? T? Uh... what is T? GenericClass1|2<String>? Again makes no sense, does it? After all I see no String in the map declaration. So I guess there is no really correct instantiation and usage of this generic variable.
Cheers!
Oh, how I have longed for something like:
private <T> Map<Class<T>, T> instanceCache;
public <T> T getInstanceOf(Class<T> clazz) {
return instanceCache.get(clazz);
}
But as you mentioned, it's completely impossible in Java. The method declaration above is fine, but there's no way to declare the variable such that there's not a cast in the method. Simply add this to the growing list of things you hate about generics and move on.
You can use ? as following:
private List<? extends List> l = new ArrayList<List>();
I hope this helps.