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

时间:2019-09-16 08:10:56

标签: java generics jvm typeclass

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

此测试失败。

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

是因为assertNotEquals匹配Money的超类吗? 据我了解,这两个内联实例应该是两种不同的类型。

我认为在使用Scala实施此操作时就是这样。

但是我不明白这里发生了什么。 这是JVM的特定问题吗? Currency.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");
    }
}

ExchangeRate.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());
    }

}

1 个答案:

答案 0 :(得分:4)

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

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

那么,Money对象在运行时实际上具有哪些数据(如果不是货币的话)?好吧,只有amount。由于amountDollar还是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) 时,您将被迫传递货币类:

....
  // wait for the DOM to be loaded 
    $(document).ready(function() { 
        const form = document.getElementById('test'); 
        form.onsubmit = function (event) {
        alert("");  
       // For this example, don't actually submit the form
       event.preventDefault();
}

....