Java 泛型 - 为什么 new Money<Dollar>(4.0) === new Money<Franc>(4.0) 相等?

标签 java generics jvm typeclass

为什么是assertNotEquals(new Money<Dollar>(4.0), new Money<Franc>(4.0));相等吗?

此测试失败。

我真的不明白为什么这个断言不成功。

是因为assertNotEquals匹配Money的父类(super class)吗? 根据我的理解,这两个内联实例化应该是两种不同的类型。

我认为当你用 Scala 实现这个时就是这样。

但我不明白这里发生了什么。 这是 JVM 特有的问题吗? 货币.java:

public class Currency {

    private final String shortcut;

    public Currency(String shortcut) {
        this.shortcut = shortcut;
    }

    public String getShortcut() {
        return shortcut;
    }
}

Dollar.java(与 Franc.java 类似)

public class Dollar extends Currency {
    public Dollar() {
        super("USD");
    }
}

汇率.java

@Value // lombok
public class ExchangeRate<C extends Currency, TargetC extends Currency> {

    Double rate;

}

Money.java

@Value
public class Money<C extends Currency> {

    private final Double amount;

    public final <TargetC extends Currency> Money<TargetC> exchange(ExchangeRate<C, TargetC> rate) {
        return new Money<TargetC>(amount * rate.getRate());
    }

}

最佳答案

泛型类型会在运行时被删除。

运行时无法判断 Money 对象是 Money<Dollar> 还是 Money<Franc> 。它们看起来都像 Money

那么,如果不是货币,那么您的 Money 对象在运行时实际拥有什么数据呢?好吧,只有 amount 。只能比较 amount 的值,因为丢失了 Dollar 还是 Franc 的信息。在本例中,金额都是 4.0 ,因此就运行时而言,它们被认为是相等的。

为了使测试成功,您可以存储一个额外的 Class<?> 字段:

@Value
public class Money<C extends Currency> {

    private final Double amount;
    private final Class<C> currencyClass;
}

当您创建 Money 时,您将被迫传递货币类别:

new Money(4.0, Dollar.class)

关于Java 泛型 - 为什么 new Money<Dollar>(4.0) === new Money<Franc>(4.0) 相等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57952767/

相关文章:

java - 在 setter 中进行修剪是一种好习惯吗?

swift - 在 Swift 中将协议(protocol)实现者升级为协议(protocol)的通用方法

java - 如何调试 JVM 中的挂起线程?

java - 字符串实习如何在 Java 7+ 中工作?

java - 使用 Java 字典进行高效字符串搜索

java - 如何从推文中仅提取英文标签

ios - 如何根据 Swift 中的字符串创建对象?

jvm - 为什么第一次调用 scrypt() 仅使用 1% CPU 并且在 GCE 中花费了半个小时?

java - 如何使用常量输入多个@CrossOrigin?

java - 获取Map(TreeMap/HashMap)中对应最大值关联的key