Java泛型,如何强制一个方法的两个参数来扩展一个超类,使其具有相同的类型?
假设我有一个类层次结构,如下所示:
class Vehicle;
class Car extends Vehicle;
class Plane extends Vehicle;
我有一个比较两个对象的函数
public <T extends Vehicle> generateDiff(T original, T copy)
在编译时,上面的方法保证两个对象是Vehicle
,但不能确保两个对象的类型相同
generateDiff(new Car(), new Car()); //OK
generateDiff(new Plane(), new Plane()); //OK
generateDiff(new Car(), new Plane()); //WRONG
我可以在编译时使用泛型实现这一点吗
另外:目前,我已经实现了,如果两个对象的Class
不相同,它将抛出异常。但我对此并不满意
提前谢谢
# 1 楼答案
是的,你可以(有点)
类型
T
正在从参数中inferred删除,但您可以指定类型:如果不键入该方法,则类型
T
被推断为满足所用边界的最窄类,因此对于参数Car
和Plane
,将起作用的最窄类型是Vehicle
,因此这两行是等效的:上面的代码假定
generateDiff()
是一个静态方法。如果它是一个实例方法,那么可以键入类并在方法中使用该类型# 2 楼答案
一旦你深入其中,它就会变得有点抽象。您还必须为函数提供类类型(见下文)。如果您想强制执行这种行为,我建议您编写单独的方法来接受您希望比较的类型。不管怎样:
你可以这样使用它:
不知道为什么任何理智的人都想这么做!:)
# 3 楼答案
不,无论是否使用泛型,这都无法实现。本质上,您是在询问是否可以告诉编译器违反多态性规则
即使您明确定义了一个没有泛型的方法,比如下面的方法,它仍然会接受任何一对扩展
Vehicle
的类有一种情况是例外,但我不建议这样做。如果对扩展
Vehicle
的final
类对象(或任何未扩展的类)调用该方法,则可以重写该方法以匹配该类对每个参数的签名。但是你需要明确地定义每一个# 4 楼答案
严格地说,你的问题的答案是“不,不可能”
然而,有一个workaround。创建一个方法
<T extends Vehicle> VehicleDiffer<T> compare(T vehicleA)
,其中VehicleDiffer<T>
有一个方法ReturnType with(T vehicleB)
。现在,您可以执行以下调用:以下操作将失败:
# 5 楼答案
在我看来,任何能够接受汽车作为论据的方法都不可能接受汽车和飞机。由于编译器不知道将出现什么类型的对象(可以是汽车、公共汽车、飞机),因此无法保证两个参数的类型完全相同。如果有人扩展汽车,创造一辆福特?这两个对象都是CAR类型
确保这一点的唯一方法是在运行时使用自定义逻辑
# 6 楼答案
没有,因为类型是在运行时设置的,但是如果向函数发送了无效类型,您可以简单地使用内省并引发异常,尽管如果是这样,那么它们可能在您的设计中存在缺陷,但这只是我的观点
instanceof
运算符将检查底层类型,因此您可以引发异常或执行更合适的操作因为你可能会比较不同的类型,也许你不应该有一个单一的函数,因为它需要相当数量的
if else
在每个类中相应地实现该函数可能更明智,这样它们就可以与适当类型的对象进行适当的比较,尽管我采取了相当数量的假设,这可能是错误的