JavagenericsT vs Object

我想知道以下两个方法声明有什么区别:

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

有一个你可以/会做一个,而不是另一个? 我在这个网站的其他地方找不到这个问题。

从背景分离 – 没有区别。 在tobj都可以只调用Object的方法。

但是与上下文 – 如果你有一个generics类:

 MyClass<Foo> my = new MyClass<Foo>(); Foo foo = new Foo(); 

然后:

 Foo newFoo = my.doSomething(foo); 

与对象相同的代码

 Foo newFoo = (Foo) my.doSomething(foo); 

两个优点:

  • 不需要强制转换(编译器将其隐藏起来)
  • 编译时间安全的工作。 如果使用Object版本,则不能肯定该方法总是返回Foo 。 如果它返回Bar ,你将在运行时产生ClassCastException

这里的区别在于,在第一个中,我们指定调用者必须传递一个Object实例(任何类),并且它将返回另一个Object(任何类,不一定是相同的types)。

在第二种情况下,返回的types将与定义类时给出的types相同。

 Example ex = new Example<Integer>(); 

在这里我们指定什么types的T将允许我们执行更多的类或方法的约束。 例如,我们可以实例化一个LinkedList<Integer>LinkedList<Example> ,我们知道当我们调用其中的一个方法时,我们将返回一个Integer或Example实例。

这里的主要目标是调用代码可以指定一个类将在什么types的对象上运行,而不是依靠types转换来强制执行。

请参阅Oracle的Java Generics *。

*更新的链接。

不同之处在于使用generics方法时,我不需要进行强制转换,并且在执行错误时出现编译错误:

 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; } } 

使用对象我总是需要施放,而当我做错时,我不会有任何错误:

 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; } } 

在运行时,什么都没有 但在编译时,第二个会做types检查,以确保参数的types和返回值的types匹配(或是子types),无论typesTparsing为(第一个例子也做types检查,但每个对象是一个对象的子types,所以每种types都将被接受)。

T是一个通用types。 这意味着它可以在运行时被任何合格的对象替代。 您可以调用如下方法:

String response = doSomething("hello world");

要么

MyObject response = doSomething(new MyObject());

要么

Integer response = doSomething(31);

正如你所看到的,这里有多态性。

但是,如果它被声明为返回Object,则不能这样做,除非您键入投射的东西。

你不需要进行额外的类别转换。 在第一种情况下,您将总是得到类java.lang.Object的对象,您将需要将其转换为类。 在第二种情况下,T将被replace为通用签名中定义的类,不需要类转换。

在第一种情况下,它接受任何typesegstring的参数并返回一个footypes。 在第二种情况下,它使用footypes的参数并返回一个footypes的对象。