Java generics T vs Object

2019-01-08 04:06发布

问题:

I was wondering what is the difference between the following two method declarations:

public Object doSomething(Object obj) {....}

public <T> T doSomething(T t) {....}

Is there something you can/would do with one but not the other? I could not find this question elsewhere on this site.

回答1:

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.


回答2:

The difference here is that in the first, we specify that the caller must pass an Object instance (any class), and it will get back another Object (any class, not necessarily of the same type).

In the second, the type returned will be the same type as that given when the class was defined.

Example ex = new Example<Integer>();

Here we specify what type T will be which allows us to enforce more constraints on a class or method. For example we can instantiate a LinkedList<Integer> or LinkedList<Example> and we know that when we call one of these methods, we'll get back an Integer or Example instance.

The main goal here is that the calling code can specify what type of objects a class will operate upon, instead of relying on type-casting to enforce this.

See Java Generics* from Oracle.

*Updated Link.



回答3:

The difference is that with generic methods I don't need to cast and I get a compilation error when I do wrong:

public class App {

    public static void main(String[] args) {

        String s = process("vv");
        String b = process(new Object()); // Compilation error
    }

    public static <T> T process(T val) {

        return val;
    }
}

Using object I always need to cast and I don't get any errors when I do wrong:

public class App {

    public static void main(String[] args) {

        String s = (String)process("vv");
        String b = (String)process(new Object());
    }

    public static Object process(Object val) {

        return val;
    }
}


回答4:

At runtime, nothing. But at compile time the second will do type checking to make sure the type of the parameter and the type of the return value match (or are subtypes of) whatever type T resolves to (the first example also does type checking but every object is a subtype of Object so every type will be accepted).



回答5:

T is a generic type. Meaning it can be substituted by any qualifying object at runtime. You may invoke such a method as follows:

String response = doSomething("hello world");

OR

MyObject response = doSomething(new MyObject());

OR

Integer response = doSomething(31);

As you can see, there is polymorphism here.

But if it is declared to return Object, you can't do this unless you type cast things.



回答6:

You don't need to do additional class casting. In first case you will always get an object of class java.lang.Object which you will need to cast to your class. In second case T will be replaced with the class defined in generic signature and no class casting will be needed.



回答7:

in the first case it takes a parameter of any type e.g.string and return a type foo. In the second case it takes a parameter of type foo and returns an object of type foo.



标签: java generics