java - 在方法和类中使用泛型和接口(interface)有什么区别

标签 java generics interface type-erasure

我想知道在泛型类或方法中使用接口(interface)(或父类(super class)型)与使用带边界的泛型方法(T 扩展接口(interface))有什么区别。

假设我有两个实现类和接口(interface)类(简单示例):

public interface MeasurableDistance {
    public Point getPosition();
}

public class Person implements MeasurableDistance {
    private Point position;

    public Point getPosition() {
        return position;
    }
}

public class House implements MeasurableDistance {
    private Point position;

    public Point getPosition() {
        return position;
    }
}

1) 以下列方式编写方法有什么区别:

public int computeDistance(MeasurableDistance a, MeasurableDistance b) {
    Point a = a.getPosition();
    Point b = b.getPosition();
    //compute distance
    return distance,
}

和类似的东西

public <T extends MeasurableDistance, S extends MeasurableDistance> int computeDistance(T a, S b) {
    Point a = a.getPosition();
    Point b = b.getPosition();
    //compute distance
    return distance,
}

2) 如果我想要一个类来保存一个 MeasurableDistance 对象:

public class Holder {
    private MeasurableDistance holder;

    public Holder() {};
    public add(MeasurableDistance a) {
        holder = a;
    }
}

或者类似的东西

public class Holder<T extends MeasurableDistance> {
    private T holder;

    public Holder<T>() {};
    public add(T a) {
        holder = a;
    };
}

对于 1,我认为它们应该非常相似,对吧?明明调用的是非泛型版本

Person a = new Person();
Person b = new Person();
House c = new House();
House d = new House();
computeDistance(a,c);
computeDistance(a,b);
computeDistance(c,d);

将始终有效,因为由于多态性,computeDistance() 会将这些对象视为 MeasurableDistance。通用版本应该也能正常工作吧?编译器会推断出 MeasurableDistance 类型并相应地添加强制转换。即使我想这样调用它:

<Person, House>computeDistance(a,c);

效果是一样的,方法是这样的

    Point a = (MeasurableDistance) a.getPosition();
    Point b = (MeasurableDistance) b.getPosition();

如果我没记错的话。或者,现在我想想,它应该是这样的:

    Point a = (Person) a.getPosition();
    Point b = (House) b.getPosition();

它会起作用,因为 Person 和 House 都在实现该方法。

那么泛型方法的优势是什么?我读到它是类型安全的,因为转换总是正确的,但是使用非通用方法你根本不会有转换。

最佳答案

您似乎混淆了使用泛型的原因和使用有界泛型的原因。

使用有界泛型的原因意味着已经有使用泛型的原因。

让我回顾一下。


Java tutorials 中解释了使用泛型的原因。 ,最明显的原因之一是:

The following code snippet without generics requires casting:

List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);

When re-written to use generics, the code does not require casting:

List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);   // no cast

使用有界泛型的原因与使用泛型的原因是分开的。 如果您有使用泛型的理由,使用边界让您要求某种类型的功能:

public class MyClass<T> {
    private List<T> list;
    ...
    public void disposeAll() {
        for(T e : list)
            e.dispose(); // compile time error
    }
}

上面的错误可以通过加bound来解决:

public class MyClass<T extends Disposable> {...}

正如您所指出的那样,您展示的案例实际上没有理由使用有界泛型。但这是因为他们一开始就没有(充分的)理由使用泛型。

在情况 2 中,泛型让您可以限制 Holder 可以持有的对象类型:

Holder<House> holder = new Holder<>();
holder.add(new Person()); // compile time error
holder.add(new House());

这不是很有用。没有真正的理由在那里使用泛型。

但如果您还检索值,泛型会很有用:

Holder<House> holder = new Holder<>();
// holder.add(new Person());
holder.add(new House());
House h = holder.get(); // no cast

关于java - 在方法和类中使用泛型和接口(interface)有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37907526/

相关文章:

java - 测试容器在等待容器端口打开时超时,使用 Elasticsearch docker 镜像

java - 关于Java中Object类的问题

c# - 将泛型传递给扩展方法

java - 从 Web ui 启动/停止 Java 应用程序

dictionary - 无法访问 [] 接口(interface)内 map 中的键

java - 如何使用 selenium webdriver 和浏览器 HtmlunitDriver for Java 设置代理?

c# - 运行时自定义属性泛型

C# 异步回调仍在后台线程...帮助! (最好没有 InvokeRequired)

go - 无效操作 : a > b (operator > not defined on interface)

java - 这个项目中的 ItemExampleBinding 对象是什么?