Java Generics T VS Object

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 returns Foo. If it returns Bar, you'll have a ClassCastException, 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 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 Strings 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 Lists of InputStreams 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.)

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.

Dart. What the difference between using generic T and Object?

Generics allows to avoid many declarations when only types change between several classes. In your example the TestObject class can be removed and replaced with TestGeneric<Object> everywhere TestObject appears.

Your expected output for (new TestObject()).Pass('string').runtimeType is not correct. runtimeType returns the type of the object. Here it is 'string' that is returned and so 'string'.runtimeType is String.

To know the return type of a method you have to use mirrors at runtime or analyzer at build time.

What is the difference between 'E', 'T', and '?' for Java generics?

Well there's no difference between the first two - they're just using different names for the type parameter (E or T).

The third isn't a valid declaration - ? is used as a wildcard which is used when providing a type argument, e.g. List<?> foo = ... means that foo refers to a list of some type, but we don't know what.

All of this is generics, which is a pretty huge topic. You may wish to learn about it through the following resources, although there are more available of course:

  • Java Tutorial on Generics
  • Language guide to generics
  • Generics in the Java programming language
  • Angelika Langer's Java Generics FAQ (massive and comprehensive; more for reference though)

What is the difference between T and T extends Object in java?

There's no difference. <T> and <T extends Object> are equivalent.

Why are generics needed when we can do casting to Object class?

I can make a list in the "pre-generic" way and do something terrible like this. The result is I can't know the type of the object I get from the list without resorting to reflection.

List myList = new ArrayList();
myList.add(new Integer(1));
myList.add(new Cat());

Object whatIsThis = myList.get(1);

With generics, I can say

List<Cat> myList = new ArrayList();    
myList.add(new Cat());
myList.add(new Integer(1)); // compile time error
myList.add(new Dog()); // compile time error

Cat whatIsThis = myList.get(1); // I *know* this must be a Cat


Related Topics



Leave a reply



Submit