将泛型参数限制为 Java 中的不同类型

Constraining generic parameters to be different types in Java

我不记得它的正确名称,这就是为什么我不能 Google 它,所以我会用一个例子来问这个,所以它会立即响铃。

这是给 Java 的。

我正在使用抽象 类 和有界类型参数的接口,就像这样:

public interface DBInterface<T, E> {
    public int delete(T element);
}

我的问题是,当我尝试重载这样的函数时:

public interface DBInterface<T, E> {
    public int delete(T element);
    public int delete(E example);
}

IDE 抱怨 T 可能与 E 相同,所以它认为我声明了两次完全相同的方法(因为,事实上,T 在该声明中可能与 E 相同) .

我的问题是:

  1. 这个怎么称呼?我想使用适当的术语重写问题,以便将来对其他人更有用
  2. 如何声明接口中的 T 和 E 以保证它们不是同一类型?

像这样:

public interface DBInterface<T, E != T> {
    public int delete(T element);
}

我现在的做法是像这样分隔合法类型。这是正确的方法吗?有没有办法允许除提供的另一个对象之外的任何对象?:

public interface DBInterface<T extends DatabaseObject, E> {
}

存在一个问题,因为编译器必须为您的方法使用参数化类型的擦除。由于 TE 没有进入运行时,编译器会以系统的方式替换您的方法参数类型。

根据教程(检查 this and this),无界类型参数被替换为 Object,并且对有界类型参数强制执行边界。 也就是说你编译后的接口方法签名是这样的:

public interface DBInterface {
    public int delete(Object element);
    public int delete(Object example);
}

你的第二个版本:

public interface DBInterface<T extends DatabaseObject, E> {
    public int delete(DatabaseObject element);
    public int delete(Object example);
}

我相信这会使您的第一个代码片段的问题变得显而易见。

How can I declare T and E in the interface to guarantee they will not be the same type?

本题不接受不合格答案。实际答案取决于 TE 的含义。例如,建议对这些类型参数进行不同的限制是没有意义的,因为在某些情况下这可能没有意义。

话虽如此,您应该考虑的一件事是重命名方法:我想不出 DBInterface 具有两个类型相似但作用不同的参数。例如,方法可以是:

public int deleteById(T element);
public int deleteByKey(E key);

换句话说,如果我们忘记 single-letter 泛型类型命名约定,您会如何命名您的类型参数?

public interface DBInterface<IdColumnType, PKColumnType> {}

我不明白为什么这不应该应用于您的方法名称,毕竟您必须承认您已经允许您的用户为两种类型的参数传递相同的 class。 ..(也就是说,即使编译器不进行类型擦除,您在技术上仍然存在问题)