我想知道以下两个方法声明之间有什么区别:
public Object doSomething(Object obj) {....}
public <T> T doSomething(T t) {....}
你可以/可以用一个而不是另一个吗?我在本网站的其他地方找不到这个问题。
答案 0 :(得分:92)
与上下文隔离 - 没有区别。在t
和obj
上,您只能调用Object
的方法。
但是有了上下文 - 如果你有一个泛型类:
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
。答案 1 :(得分:10)
这里的区别在于,在第一个中,我们指定调用者必须传递一个Object实例(任何类),它将返回另一个Object(任何类,不一定是同一类型)。
在第二种情况下,返回的类型与定义类时给出的类型相同。
Example ex = new Example<Integer>();
这里我们指定T将是什么类型,它允许我们对类或方法强制执行更多约束。例如,我们可以实例化LinkedList<Integer>
或LinkedList<Example>
,我们知道当我们调用其中一个方法时,我们将返回一个Integer或Example实例。
这里的主要目标是调用代码可以指定类将操作的对象类型,而不是依赖于类型转换来强制执行此操作。
请参阅Oracle的Java Generics *。
*更新链接。
答案 2 :(得分:7)
不同之处在于使用通用方法我不需要进行转换,并且在出错时遇到编译错误:
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;
}
}
答案 3 :(得分:2)
在运行时,没有。但是在编译时,第二个将进行类型检查以确保参数的类型和返回值的类型匹配(或者是子类型)T解析为什么类型(第一个示例也进行类型检查但每个对象都是Object的子类型,因此将接受每种类型。
答案 4 :(得分:2)
T是通用类型。这意味着它可以在运行时由任何限定对象替换。您可以调用以下方法:
String response = doSomething("hello world");
OR
MyObject response = doSomething(new MyObject());
OR
Integer response = doSomething(31);
如您所见,这里存在多态性。
但是如果它被声明为返回Object,除非你输入cast的东西,否则你不能这样做。
答案 5 :(得分:1)
您无需进行额外的类投射。在第一种情况下,您将始终获得类java.lang.Object的对象,您需要将其强制转换为您的类。在第二种情况下,T将被替换为通用签名中定义的类,并且不需要类转换。
答案 6 :(得分:0)
在第一种情况下,它采用任何类型的参数egstring并返回一个类型foo。在第二种情况下,它采用foo类型的参数并返回类型为foo的对象。
答案 7 :(得分:0)
在Java中可以考虑泛型而不是对象类型的原因有很多: