What is the difference between ? and Object in Java generics?
An instance of HashMap<String, String>
matches Map<String, ?>
but not Map<String, Object>
. Say you want to write a method that accepts maps from String
s to anything: If you would write
public void foobar(Map<String, Object> ms) {
...
}
you can't supply a HashMap<String, String>
. If you write
public void foobar(Map<String, ?> ms) {
...
}
it works!
A thing sometimes misunderstood in Java's generics is that List<String>
is not a subtype of List<Object>
. (But String[]
is in fact a subtype of Object[]
, that's one of the reasons why generics and arrays don't mix well. (arrays in Java are covariant, generics are not, they are invariant)).
Sample:
If you'd like to write a method that accepts List
s of InputStream
s and subtypes of InputStream
, you'd write
public void foobar(List<? extends InputStream> ms) {
...
}
By the way: Joshua Bloch's Effective Java is an excellent resource when you'd like to understand the not so simple things in Java. (Your question above is also covered very well in the book.)
What is difference between Generic type and Object in method declaration?
Like that there is no difference, for T you are using the type twice so you have a reason to use it but for J it is only used once.
If it really can be any object at all and you never use that type again then there is no reason to use generics for it. Generics allow you to take the return type and parameters of the method and link 2 or more of them together. They also allow you to link together multiple methods when using generics in a class definition.
Neither of those use cases applies here.
Java generics T vs Object
Isolated from context - no difference. On both t
and obj
you can invoke only the methods of Object
.
But with context - if you have a generic class:
MyClass<Foo> my = new MyClass<Foo>();
Foo foo = new Foo();
Then:
Foo newFoo = my.doSomething(foo);
Same code with object
Foo newFoo = (Foo) my.doSomething(foo);
Two advantages:
- no need of casting (the compiler hides this from you)
- compile time safety that works. If the
Object
version is used, you won't be sure that the method always returnsFoo
. If it returnsBar
, you'll have aClassCastException
, at runtime.
What is the difference between type T and Object?
At runtime, there is no difference: Java generics are implemented through Type Erasure, so the same class is used in all implementations.
At compile time, however, the difference is enormous, because it lets you avoid casting every time that you use an object, making you code look a lot cleaner.
Consider this example:
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
for (Integer n : list) {
System.out.println(n+5);
}
This compiles and runs well, and it also easy to read. If you wanted to use List<Object>
instead, the code would not look as clean:
List<Object> list = new ArrayList<Object>();
list.add(1);
list.add(2);
list.add(3);
for (Object o : list) {
// Now an explicit cast is required
Integer n = (Integer)o;
System.out.println(n+5);
}
Internally, though, the two code snippets use the same exact implementation for their list
object.
What's the difference between ? and ? extends Object in Java Generics?
<?>
and <? extends Object>
are synonymous, as you'd expect.
There are a few cases with generics where extends Object
is not actually redundant. For example, <T extends Object & Foo>
will cause T
to become Object
under erasure, whereas with <T extends Foo>
it will become Foo
under erasure. (This can matter if you're trying to retain compatibility with a pre-generics API that used Object
.)
Source: http://download.oracle.com/javase/tutorial/extra/generics/convert.html; it explains why the JDK's java.util.Collections
class has a method with this signature:
public static <T extends Object & Comparable<? super T>> T max(
Collection<? extends T> coll
)
Java generics, Unbound wildcards ? vs Object
There are two separate issues here. A List<Object>
can in fact take any object as you say. A List<Number>
can take at least Number
objects, or of course any subclasses, like Integer
.
However a method like this:
public void print(List<Number> list);
will actually only take a List
which is exactly List<Number>
. It will not take any list which is declared List<Integer>
.
So the difference is List<?>
will take any List with whatever declaration, but List<Object>
will only take something that was declared as List<Object>
, nothing else.
The last quote simply states, that List<?>
is a list for which you literally don't know what type its items are. Because of that, you can not add anything to it other than null
.
Generics vs Object vs Comparable
The conceptual thing to know about: Java arrays are covariant!
That means: you can write a method like
public void sort(Object[] data)
and use that with an array of Objects, but also with an Integer[], String[] whatever.
That has the advantage that you can write code that works "generically" for all kinds of different input.
But the problem with that is that it can lead to surprises at runtime, for example when your array contains Integer and String objects.
Thus the Java language folks decides to make generics, and more specifically collections of Generics invariant. Therefore you can't do
public void sort(List<Number> numbers)
and call that with some List<Integer>
.
In that sense: when using arrays, then there isn't much sense in using generics. But: when using generics, you would (most of the time) prefer using collections over arrays! And then, you have to really know about the conceptual differences.
Java generics, objects and wildcards differences & clarifications
I will list the main differences between T
and ?
:
Basic:
T
is a type parameter and?
is a wildcard.Meaning:
T
is used as a type parameter when defining a generic class.T
will be replaced by a concrete type when you instantiate the generic class.
On the other hand, we use?
when we want to refer to an unknown type argument.- Place of definition: You need to declare
T
on the top of the class, or method if you define a generic method. You can use?
everywhere. - Mapping: Every use of
T
is mapped to the same type (in the same class). Every use of?
can be mapped to a different type. - Object instantiation: You can create objects with the generic parameter
T
likenew ArrayList<T>()
. You cannot instantiate objects but only pointers with?
. Collections updating: You can add objects to a collection of type
T
. You cannot add object to a collection of type?
(since you don't know its type).Type erasures: With generics, type erasure applies to the use of generics. when generics are used, they are converted into compile-time checks and execution-time casts. So if you have this code for example:
List<String> myList = new ArrayList<String>();
and then you wish to add to your list so you domyList.add("Hello World");
and then you want toget
the item you just added by performingString myString = myList.get(0);
then the compiler will compile your code toList myList = new ArrayList();
andString myString = (String) myList.get(0);
(theadd
stays the same for obvious reasons).
So basically, at execution time there is no way of finding out thatT
is essentiallyString
for the list object (that information is gone).
Now for wildcards the story is different. A wildcard (?
) is replaced by anObject
(since it's unbounded). This is not very useful. At build-time the compiler will check you are only callingObject
's behaviours. If you have something like? extends Foo
, then the?
is replaced with its boundFoo
(at build-time the compiler will check you are only passingFoo
or any of its subtypes (types that inherit fromFoo
) as an argument).
For differences between ?
and Object
& T
and Object
you may read here and here respectively.
Generics: What is the difference between ?, Object, and raw type of a single instance?
The Java Language Specification writes:
The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of generics into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.
That leaves the other two. As ScheduledFuture
only uses its type parameter in a method return type, ScheduledFuture<?>
(which is the same as ScheduledFuture<? extends Object>
) is equivalent to ScheduledFuture<Object>
to calling code.
However, code that actually creates an instance of a ScheduledFuture needs to work with a subclass of ScheduledFuture, and may care a great deal about the type parameter that subclass implements ScheduledFuture with.
When declaring a method that returns a ScheduledFuture, you will therefore want to use the type ScheduledFuture<?>
as that signature is easier to implement for the producer of the ScheduledFuture, but equally useful to its consumer. (This is simply a special case of the PECS rule.)
Related Topics
Configuring Log4J Loggers Programmatically
Javafx - Border Radius <-> Background Color
Androidruntime Error: Parcel: Unable to Marshal Value
Reading a JSON Array in Android
How to Send Data from Dialogfragment to a Fragment
Android Httppost: How to Get the Result
Android App in Eclipse: Edit Text Not Showing on Graphical Layout
Clearing and Setting the Default Home Application
How to Use Jsp/Jstl to Generate Dynamic CSS/JavaScript Files
What Exactly Does Urlconnection.Setdooutput() Affect
Android Post Picture to Facebook Wall
Deprecated Managedquery() Issue