我想知道以下两种方法声明之间的区别:
public Object doSomething(Object obj) {....}
public <T> T doSomething(T t) {....}
你能用其中一个做些什么,而另一个却不能吗?我在这个网站上没有找到这个问题的答案。
与上下文隔离 - 没有区别。在 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
。Example ex = new Example<Integer>();
LinkedList<Integer>
或LinkedList<Example>
,并且我们知道当我们调用这些方法时,我们将会得到一个Integer或Example实例。区别在于使用泛型方法时,我不需要进行强制类型转换,而且如果我操作不当会得到编译错误:
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;
}
}
无需进行额外的类转换。在第一种情况下,您将始终得到一个java.lang.Object类的对象,您需要将其强制转换为您的类。在第二种情况下,T将被替换为泛型签名中定义的类,不需要进行类转换。
在运行时,没有任何区别。但是在编译时,第二个示例将进行类型检查,以确保参数的类型和返回值的类型匹配(或是T类型的子类型)。而第一个示例也进行了类型检查,但由于每个对象都是Object的子类型,因此每种类型都会被接受。
T是一种通用类型,意味着它可以在运行时由任何符合条件的对象进行替换。您可以按照以下方式调用此类方法:
String response = doSomething("你好世界");
或者
MyObject response = doSomething(new MyObject());
或者
Integer response = doSomething(31);
正如您所看到的,这里存在多态性。
但如果声明返回Object,则除非您对事物进行类型转换,否则无法执行此操作。
<T>
就没有自动装箱吗? - SMUsamaShah在第一种情况下,它接受任何类型的参数,例如字符串,并返回类型为foo的结果。在第二种情况下,它接受类型为foo的参数并返回类型为foo的对象。
在Java中,您可以考虑使用泛型而不是Object类型的原因有: