What are the 'good' reasons to use <?> in Java Generics? - java

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())

Related

Why/when should generic methods be used?

Studying Java, I've come across generic methods.
public <T> void foo(T variable) { }
That is, a method which takes a parameter with an undecided type (รก la PHP?). I'm however unable to see how this would be a good solution - especially since I've come to fall in love with a strongly typed languages after coming from a loose ones.
Is there any reason to use generic methods? If so, when?
Those who are coming from prior to Java 5 background knows that how inconvenient it was to store object in Collection and then cast it back to correct Type before using it. Generics prevents from those. it provides compile time type-safety and ensures that you only insert correct Type in collection and avoids ClassCastException in runtime.
So it provides compile time type-safety and casting. When you want to write complex APIs with complex method signatures it will save you a lot both when writing the API and when using the API and prevents writing lots of code for casting part and catch your errors at compile time. just take a look at java.util.Collection package and see the source code.
As a developer I always want compiler to catch my error at compile time and inform me when I want to compile it then i will fix my errors and at runtime there won't be many errors related to type-safety.
for more info see :
http://javarevisited.blogspot.com/2011/09/generics-java-example-tutorial.html
http://javarevisited.blogspot.com/2012/06/10-interview-questions-on-java-generics.html
Generics, among other things, give you a way to provide a template -- i.e. you want to do the same thing, and the only difference is the type.
For example, look at the List API, you will see the methods
add(E e)
For every list of the same type you declare, the only thing different about the add method is the type of the thing going into the list. This is a prime example of where generics are useful. (Before generics were introduced to Java, you would declare a list, and you could add anything to the list, but you would have to cast the object when you retrieved it)
More specifically, you might want 2 ArrayList instances, one that takes type1 and one that takes type2. The list code for add is going to do the same thing, execute the same code, for each list (since the two lists are both ArrayList instances), right? So the only thing different is what's in the lists.
(As #michael points out, add isn't a true example of a generic method, but there are true generic methods in the API linked, and the concept is the same)
There's nothing non-strongly typed about generic functions in general. The type is resolved and checked at compile time. It's not an undecided type, it's one of a range of possible types (these can be constrained, in your example they are not). At compile time it is known and decided.
As hvgotcodes says, the Collections API contains a number of good examples of this in use.
The main objective of Generic concepts are :
To provide type safety to the Collections so that they can hold only
one particular type of object.
To resolve typecasting problems.
To hold only String type of object a Generic version of ArrayList can be declare as follows :
ArrayList l = new ArrayList ();
To know more : http://algovalley.com/java/generics.php

What's this generics usage in Java? X.<Y>method()

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.

ArrayList<T> vs ArrayList<?>

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>

Java bounded generic constraints on fields

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.

Which Java generic should be used in ambiguous cases?

I'm having some problems with a Wicket 1.3 -> Wicket 1.4 migration, but this question could be applied to Java generics overall, too. The migration has caused hundreds of warnings to spring up out of nowhere -- for those unfamiliar with Wicket, many Wicket classes are derived from a common ancestor, which became generified in v1.4 -- and I'm not sure what parameters to apply in some cases, mostly assorted forms and tables. I'm thinking they could do with <?>, <Object> or <Void>, but I'm not sure which.
<?> seems most appropriate to me, but there are many places where I can't use a wildcard. <Object> works in all cases, but it makes me uneasy because it's basically writing a wildcard without using the wildcard, which just feels inherently wrong to part of my brain. And using <Void> was suggested in the Wicket migration guide.
So what is the proper thing to do in this case?
EDIT 2: I think my first edit (now at the bottom of the question) confused people by making it seem like I was just asking about collections of strings. Here are other examples and their warnings:
public class DocumentProcessor extends Form implements DocumentManagement { ...
Form is a raw type. References to generic type Form should be parameterized
AjaxFallbackDefaultDataTable theTable = new AjaxFallbackDefaultDataTable("theTable", cols, dataProvider, recPerPg);
Multiple markers at this line
- Type safety: The constructor AjaxFallbackDefaultDataTable(String, List, ISortableDataProvider, int) belongs to the raw type AjaxFallbackDefaultDataTable. References to generic type AjaxFallbackDefaultDataTable should be parameterized
- AjaxFallbackDefaultDataTable is a raw type. References to generic type AjaxFallbackDefaultDataTable should be parameterized
- AjaxFallbackDefaultDataTable is a raw type. References to generic type AjaxFallbackDefaultDataTable should be parameterized
EDIT: I was hoping to make the question so broad it didn't need sample code, but here is some.
List<IColumn> columns = new ArrayList<IColumn>();
columns.add(new PropertyColumn(new Model<String>("Number"), "revisionID"));
These warnings are generated:
Multiple markers at [the first] line
- IColumn is a raw type. References to generic type IColumn should be parameterized
- IColumn is a raw type. References to generic type IColumn should be parameterized
Multiple markers at [the second] line
- Type safety: The constructor PropertyColumn(IModel, String) belongs to the raw type PropertyColumn. References to generic type PropertyColumn should be parameterized
- PropertyColumn is a raw type. References to generic type PropertyColumn should be parameterized
There are no errors.
Use Void if you're not going to make use of the component's underlying model object.
Semantically, it is more sound and conveys better the idea that it's not that the model object can be anything, but that it is semantically nothing and will never be used. The Void keyword is mostly used as the conventional solution in this kind of situation.
If you're going to use the model object and don't care, which I don't think is what you meant, **use wildcards where you can** and, where you can't (constructor arguments, etc), either Void, Object, or possibly some other "encompassing" class, making a decision based on your component's specific semantics and desired generic-typing behavior (as an example, in the case of a constructor for a component variable, you'd think about what your constructor will do with a Void or an Object typing).
Of course, that's in terms of "good programming practices" theory, in practice you don't have to care much, though this kind of thinking can help your teammates maintain your code, and can help you better understand it, maybe even predict bugs.
Using wildcards everywhere is fairly common among wicket users, perhaps even more common than deciding as I suggested, but that's not because wildcards are the convention, but is most likely simply due to most code examples that pop up in search engines preferring wildcards. Nonetheless, as the migration guide's suggestion of Void shows, not only are wildcards less semantically coherent, but also they don't seem to be an absolute convention, even challenged, it would seem, by wicket's developers, who, we'd better assume, know enough about their types' inner workings for their recommendations to be taken seriously.
Alternatives available would be:
To just use the raw type, as you have in the sample code, simply ignore the warnings
To use the wildcard/Object generic
To use an extends generic
I am assuming from your question that #1 is not a viable option for you.
Example for #2 (wildcard/Object)
List<IColumn<?>> columns = new ArrayList<IColumn<?>>();
OR
List<IColumn<Object>> columns = new ArrayList<IColumn<Object>>();
IMO I don't think it really matters whether you choose ? or Object, and neither one is more correct than the other, at least functionally.
If you don't care what the generic is, and you never access it, then it is of nigh consequence; although think ahead carefully, if indeed it is possible you would use generics here in the future. This will likely be the case only where in your pre-migration code, you found yourself not having to typecast anything from within the IColumn objects.
Example for #3 (extends generic)
Create a supertype or common interface to all the possible generics of the IColumn type. Where
T extends MyType:
List<IColumn<T>> columns = new ArrayList<IColumn<T>>();
I would base the decision in choosing, between the 2nd and 3rd method, on what the possible generic attributes for IColumn actually are.
If they are your own classes AND you actualy want to access objects of the generic type, I would go for the 3rd method,
otherwise, for example with String or boxed primitives such as Integer, or if you don't acees the objects of the generic type, I would go for method 2.
HTH
Semantically, using <?> means "I don't know the type, and I actually don't care at all. Using anything else sets expectations on the form of the expected content.
Practically, <Object> does the same, but states you'll use the properties of your generic that use the parameter type.
So the rule of thumb should be:
if you only work on the genetic object but not with it's parametrized content, use <?> so you know at first sight the parameter doesn't matter to the behavior.
in any other case, use the most specific parameter that encompasses all types your method is designed to work with. Extreme case is <Object>, other include <? extends SomeTopLevelType>
I haven't used wicket and Vodafone is blocking me from seeing API docs. However, it appears that you are missing many generic arguments and want something like:
List<IColumn<String>> columns = new ArrayList<IColumn<String>>();
columns.add(new PropertyColumn<String>(new Model<String>("Number"), "revisionID"));
If you want to add other IColumns with unrelated generic argument, you will need something like;
List<IColumn<?>> columns = new ArrayList<IColumn<?>>();
columns.add(new PropertyColumn<String>(new Model<String>("Number"), "revisionID"));
Or if you need to get at the column's properties, perhaps something like:
List<IColumn<String>> strColumns = new ArrayList<IColumn<String>>();
List<IColumn<?>> columns = new ArrayList<IColumn<?>>();
PropertyColumn<String> column =
new PropertyColumn<String>(new Model<String>("Number"), "revisionID");
strColumns.add(column);
columns.add(column);
You want to use the type of the model associated with your component. That is, use the type returned by a call to getModelObject(). So, to use an example from the migration guide:
ListView<Person> peopleListView = new ListView<Person>("people", people) {
protected void populateItem(ListItem<Person> item) {
item.add(new Link<Person>("editPerson", item.getModel()){
public void onClick() {
Person p = getModelObject();
setResponsePage(new EditPersonPage(p));
}
});
}
};
With generics it is easy to tell that that is a list of Persons, with a link to an edit page that uses a person as it's model. Unfortunately, very often in wicket your components won't have a model associated with them. In that case getModel() will return null so the proper type to use is <Void>, which is essentially a place holder for null.
DocumentProcessor
public class DocumentProcessor extends Form implements DocumentManagement { ...
if you aren't setting the model for DocumentProcessor it would look like so:
public class DocumentProcessor extends Form<Void> implements DocumentManagement {
public DocumentProcessor(String id) {
super(id);
....
but with a model DocumentProcessor looks something like this:
public class DocumentProcessor extends Form<Document> implements DocumentManagement {
public DocumentProcessor(String id, Document doc) {
super(id, doc);
AjaxFallbackDefaultDataTable
Judging from it's constructors AjaxFallbackDefaultDataTable will likely store either an IColumn[] or List in it's model, but for your implementation you don't know or care so <?> is appropriate, the difference between this and DocumentProcessor is that you're extending Form and therefore do know and do care how it is using it's model.
IColumn
For the IColumn/PropertyColumn example, I'm going to assume that the revisionID field is a Long, then I would write it like so:
List<PropertyColumn> columns = new ArrayList<PropertyColumn>();
columns.add(new PropertyColumn<Long>(new Model<String>("Number"), "revisionID"));
You might look at
More 1.4 Migration info
Void type parameter
The warnings say that IColumn interface and PropertyColumn class are parameterized types, so you just need to define type parameters for them.
Consider the following example:
List<Set> list = new ArrayList<Set>();
List and ArrayList are parameterized types and their type parameters are defined. However, Set is parameterized type as well but it's raw version is used as a type parameter, hence, compiler generates a warning at that case.
We can fix our example by explicitly specifying all type arguments, e.g.
List<Set<Integer>> list1 = new ArrayList<Set<Integer>>();
List<Set<String>> list1 = new ArrayList<Set<String>>();
You need to do the same thing for your generic classes and interfaces.

Categories

Resources