Java 泛型 T 与对象

问题描述 投票:0回答:9

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

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

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

有什么事情是你可以/愿意用其中一个做而另一个却不能做的吗?我在本网站的其他地方找不到这个问题。

java generics
9个回答
143
投票

与上下文隔离——没有区别。在

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

18
投票

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

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

Example ex = new Example<Integer>();

这里我们指定 T 的类型,这允许我们对类或方法施加更多约束。例如,我们可以实例化一个

LinkedList<Integer>
LinkedList<Example>
,并且我们知道当我们调用其中一个方法时,我们将返回一个 Integer 或 Example 实例。

这里的主要目标是调用代码可以指定类将操作的对象类型,而不是依赖类型转换来强制执行此操作。

请参阅 Oracle 的 Java 泛型*。

*更新了链接。


18
投票

不同之处在于,使用泛型方法时,我不需要强制转换,并且当我做错时会收到编译错误:

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
投票

您不需要进行额外的班级选角。在第一种情况下,您将始终获得 java.lang.Object 类的对象,您需要将其转换为您的类。在第二种情况下,T 将被替换为通用签名中定义的类,并且不需要类转换。


2
投票

在运行时,什么也没有。但在编译时,第二个将进行类型检查,以确保参数的类型和返回值的类型与 T 解析的任何类型匹配(或者是其子类型)(第一个示例也进行类型检查,但每个对象都是一个对象的子类型,因此每种类型都会被接受)。


2
投票

T 是泛型类型。这意味着它可以在运行时被任何符合条件的对象替换。您可以按如下方式调用此类方法:

String response = doSomething("hello world");

MyObject response = doSomething(new MyObject());

Integer response = doSomething(31);

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

但是,如果它被声明为返回 Object,则除非您键入强制类型转换,否则您无法执行此操作。


0
投票

在第一种情况下,它接受任何类型的参数,例如 string 并返回 foo 类型。在第二种情况下,它接受 foo 类型的参数并返回 foo 类型的对象。


0
投票

在 Java 中您可以考虑使用泛型而不是对象类型的原因如下:

  1. 泛型灵活且安全。同时,使用需要类型转换的对象很容易出错
  2. Java 中的类型转换很慢 参考:[1]:https://www.infoworld.com/article/2076555/java-performance-programming--part-2--the-cost-of-casting.html

0
投票

就像下面的示例一样,您可以更安全地使用泛型。类型T必须扩展“BaseClass”,其他类将产生编译错误。

public class MyClass<T extends BaseClass> {
    List<T> list;
}
© www.soinside.com 2019 - 2024. All rights reserved.