我正在研究Java标准库(6)中compare(double,double)的实现。内容为:
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
此实现的优点是什么?
编辑:“优点”是一个(非常)错误的单词选择。我想知道这是如何工作的。
@Shoover的答案是正确的(阅读它!),但是它还不止于此。
由于javadoc中的Double::equals
规定:
“此定义允许哈希表正常运行。”
假设Java设计者决定采用equals(...)
与包装实例compare(...)
相同的语义来实现。这意味着将始终返回包装好的NaN。现在考虑如果您尝试在地图或集合中使用包装的NaN会发生什么。==``double``equals()``false
List<Double> l = new ArrayList<Double>();
l.add(Double.NaN);
if (l.contains(Double.NaN)) {
// this wont be executed.
}
Map<Object,String> m = new HashMap<Object,String>();
m.put(Double.NaN, "Hi mum");
if (m.get(Double.NaN) != null) {
// this wont be executed.
}
这样做没有多大意义!
存在其他异常,因为-0.0
并且+0.0
具有不同的位模式,但根据,它们相等==
。
因此,Java设计人员决定(正确地是IMO)决定了当今我们对这些Double方法更复杂(但更直观)的定义。
我查看了源代码中的一些内容,并注意到虽然(或其长的对应部分)是这样实现的: 这对我来说是完全有意义的,这和我想做的是一样的。但是,double/float的实现是这样的: 我完全傻眼了。是否将与其自身进行比较?第二张支票是为了什么?为什么它的实现方式不像int/long版本一样?
问题内容: 和之间有什么区别? 问题答案: 是一个对象,并且是原始数据类型。 有关更多详细信息,请参见此答案。 Double类将原始类型double的值包装在对象中。类型为Double的对象包含单个类型为double的字段。 来源:http : //docs.oracle.com/javase/7/docs/api/java/lang/Double.html
问题内容: 为什么Math.max的实现不是可变函数? 可以这样实现: 没有任何理由为什么不能这样实现? 问题答案: 尽管其他人已经回答了为什么不是可变参数的问题,但他们没有回答为什么引入可变参数功能时不会创建这种方法的原因。 我什至不知道(有一个开放的bug报告),所以我只能猜测: 的确没有在中实现它,但是如果我们研究以下方法: 尽管类型签名看起来很丑陋(它必须足够灵活以处理协方差和协方差),但
问题内容: 在我的一个实验室的示例Java程序中,我有两种分别采用Double和double参数的不同方法。 将参数传递给它们时,如何区分它们? 问题答案: 首先,您需要了解两种类型之间的区别。 是基本类型,而是对象。 下面的代码显示了一个重载的方法,我认为它与您的实验室代码相似。 有几种方法可以调用这些方法: 这些调用将导致:
为什么在JUnit5中不再推荐assertEquals(double,double)?
问题内容: 今天,我正在为即将参加的Java考试而学习,但遇到了这个问题: 设一个定义如下的类: 该指令产生的输出是什么? 答案似乎是,但我不明白为什么。有人可以给我适当的解释吗? 问题答案: 与具有可变参数列表的函数相比,重载解析始终偏向于使用具有明显数量的参数的函数,即使这意味着该函数是自动装箱的。 更详细地说,根据JLS 15.12.2 选择具有此优先级的函数: 类型加宽 自动装箱 可变参数