Java 断言等于 int long float
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41242135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
assert equals int long float
提问by Pavel Niedoba
Is there an elegant way to assert numbers are equal while ignoring their classes? I want to use it in JUnit tests framework but for example
有没有一种优雅的方法来断言数字相等而忽略它们的类?我想在 JUnit 测试框架中使用它,但例如
Assert.assertEquals(1,1L)
fails with java.lang.AssertionError: expected: java.lang.Integer<1> but was: java.lang.Long<1>
因 java.lang.AssertionError 失败:预期:java.lang.Integer<1> 但为:java.lang.Long<1>
I expect there is a nice method somewhere which compares only value and works with int, long, float, byte, double, BigDecimal, BigInteger, you name it...
我希望在某处有一个很好的方法,它只比较值并与 int、long、float、byte、double、BigDecimal、BigInteger 一起使用,您可以命名它...
采纳答案by Mena
One workaround with some overhead would be to wrap the values in BigDecimalobjects, as BigDecimal
constructor overloads take long
, int
and double
primitives.
一些开销的一种解决方法是将包裹中的值的BigDecimal对象,BigDecimal
构造函数重载需要long
,int
和double
原语。
Since new BigDecimal(1l).equals(new BigDecimal(1.0))
holds true
,
既然new BigDecimal(1l).equals(new BigDecimal(1.0))
成立true
,
Assert.assertEquals(new BigDecimal(1.0), new BigDecimal(1l));
should work for you.
应该为你工作。
Edit
编辑
As Hulkstates below, the scale of the BigDecimal
objects is used in the equals
comparison, but not in the compareTo
comparison.
While the scale is set to a default 0
for the constructor taking long
, it is inferred through some calculation in the constructor taking double
.
Therefore the safest way to compare values (i.e. in edge cases for double
values) mightbe through invoking compareTo
and checking the outcome is 0
instead.
正如Hulk在下面所说的,BigDecimal
对象的比例用于equals
比较,但不用于compareTo
比较。虽然比例设置0
为构造函数的默认值long
,但它是通过构造函数中的一些计算推断出来的double
。因此,比较值的最安全方法(即在值的边缘情况下double
)可能是通过调用compareTo
和检查结果来0
代替。
回答by Roland
Wrap that functionality in your own Matcherand use it with assertThat
.
将该功能包装在您自己的Matcher 中并将其与assertThat
.
Sample matcher:
样本匹配器:
class IsAnyNumber extends BaseMatcher {
final Object expected;
//...
public boolean matches(Object actual) {
// compare / transform / check type / ensure: String, double, int, long
// example via BigDecimal as seen from Mena (without checks)
return new BigDecimal(expected).equals(new BigDecimal(actual));
}
// ...
}
// somewhere else:
public static IsAnyNumber is(Object expected) {
return new IsAnyNumber(expected);
}
In your tests you then call that static method:
在您的测试中,您然后调用该静态方法:
assertThat(1, is(1L));
assertThat(1, is(1.0));
assertThat(1L, is(1));
This way you can reuse your matcher and the assert statement is more readable in the end.
通过这种方式,您可以重用匹配器,并且断言语句最终更具可读性。
Disclaimer: this is only pseudo-code and was not yet tested, but should work with some tweaking.
免责声明:这只是伪代码,尚未经过测试,但应该进行一些调整。
But beware also from Comparing Numbers in Java
但也要注意比较 Java 中的数字
回答by Stefan
Create your own assert methods and compare the double values for the primitives. If a BigDecimal
is used, the primitive value has to be converted to a BigDecimal
创建您自己的断言方法并比较基元的双精度值。如果使用 a BigDecimal
,则原始值必须转换为 aBigDecimal
static void assertEquals(Number number1, Number number2) {
Assert.assertEquals(number1.doubleValue(), number2.doubleValue());
}
static void assertEquals(BigDecimal number1, BigDecimal number2) {
if (number2.compareTo(number1) != 0) {
Assert.fail("Values are not equal. ..... ");
}
}
static void assertEquals(Number number1, BigDecimal number2) {
assertEquals(new BigDecimal(number1.doubleValue()), number2);
}
static void assertEquals(BigDecimal number1, Number number2) {
assertEquals(number2, number1);
}
It can be used this way:
它可以这样使用:
assertEquals(1, new BigDecimal("1.0"));
assertEquals(1.0d, 1);
assertEquals(new Float(1.0f), 1.0d);
assertEquals(new BigDecimal("1.00000"), new BigDecimal("1.0"));
...
回答by Stephen C
According to my reading of the JLS, the overload resolution for
根据我对 JLS 的阅读,对于
Assert.assertEquals(1,1L)
should resolve to
应该解决
Assert.assertEquals(long, long)
(For the record, assertEquals(long, long)
, assertEquals(float, float)
and assertEquals(double, double)
are applicable by strict invocation, and the first one is the most specific; see JLS 15.12.2.2. The strict invocation context allows primitive widening, but not boxing or unboxing.)
(根据记录,assertEquals(long, long)
,assertEquals(float, float)
和assertEquals(double, double)
是适用通过严格调用,和第一个是最具体的;参见JLS 15.12.2.2。严格调用上下文允许原始加宽,但不是拳击或取消装箱)
If (as the evidence suggests) your call is resolving to Assert.assertEquals(Object, Object)
, that implies that one of the operands must alreadybe a boxed type. The problem with that overload is that it is using the equals(Object)
method to compare objects, and the contract for that method specifiesthat the result is false
if the objects' respective types are different.
如果(如证据所示)您的调用解析为Assert.assertEquals(Object, Object)
,则意味着其中一个操作数必须已经是装箱类型。该重载的问题在于它使用该equals(Object)
方法来比较对象,并且该方法的约定指定结果是false
对象各自的类型是否不同。
If that is what is going on in your real code, then I doubt that the suggestion of using the is(T)
Matcher
will work either. The is(T)
matcher is equivalent to is(equalTo(T))
and the latter relies on equals(Object)
...
如果这就是您的真实代码中发生的事情,那么我怀疑使用 的建议is(T)
Matcher
是否有效。该is(T)
匹配相当于is(equalTo(T))
后者依赖于equals(Object)
...
Is there an existing "nice method"?
是否有现有的“好方法”?
AFAIK, no.
AFAIK,没有。
I think that the real solution is to be a bit more attentive to the types; e.g.
我认为真正的解决方案是更加关注类型;例如
int i = 1;
Long l = 1L;
Assert.assertEquals(i, l); // Fails
Assert.assertEquals((long) i, l); // OK - assertEquals(Object, Object)
Assert.assertEquals((Long) i, l); // OK - assertEquals(Object, Object)
Assert.assertEquals(i, (int) l); // OK - assertEquals(long, long)
// it would bind to an (int, int)
// overload ... it it existed.
Assert.assertEquals(i, (long) l); // OK - assertEquals(long, long)
Writing a custom Matcher
would work too.
编写自定义Matcher
也可以。
回答by leeyuiwah
I think to accept all eight types of numerical values (primitive and object), the method has to take string arguments. The caller will have to remember to cast the value to string by this idiom:
我认为要接受所有八种类型的数值(原始和对象),该方法必须采用字符串参数。调用者必须记住通过这个习语将值转换为字符串:
""+value
Also, in case the value is not an integer (int
, Integer
, long
, Long
) but a floating point representation (float
, double
, Float
, Double
), the method must also take a argument epsilon
to tolerate imprecision due to the representation.
此外,如果该值不是整数 ( int
, Integer
, long
, Long
) 而是浮点表示 ( float
, double
, Float
, Double
),则该方法还必须接受一个参数epsilon
以容忍由于表示引起的不精确性。
So here is an implementation idea (for now I ignore the cases of NaN and positive and negative zeros of double -- these can be added if a truly solid implementation is needed)
所以这是一个实现想法(现在我忽略 NaN 和 double 的正负零的情况——如果需要真正可靠的实现,可以添加这些)
private static boolean equalsNumerically(String n1String
, String n2String
, double epsilon) {
try {
Long n1Long = new Long(n1String);
Long n2Long = new Long(n2String);
return n1Long.equals(n2Long);
} catch (NumberFormatException e) {
/*
* If either one of the number is not an integer, try comparing
* the two as Double
*/
try {
Double n1Double = new Double(n1String);
Double n2Double = new Double(n2String);
double delta = ( n1Double - n2Double) / n2Double;
if (delta<epsilon) {
return true;
} else {
return false;
}
} catch (NumberFormatException e2) {
return false;
}
}
}
Testing code
测试代码
int primitiveInt = 1;
long primitiveLong = 1L;
float primitiveFloat = 0.999999F;
double primitiveDouble = 0.999999D;
Integer objectInt = new Integer(1);
Long objectLong = new Long(1);
Float objectFloat = new Float(0.999999);
Double objectDouble = new Double(0.999999);
final double epsilon = 1E-3;
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, 0));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+primitiveInt"
+ ", \"\"+primitiveLong, 0): %s %s %s%n"
, primitiveInt, primitiveLong, epsilon);
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, epsilon));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+primitiveInt"
+ ", \"\"+primitiveLong, epsilon)): %s %s %s%n"
, primitiveInt, primitiveLong, epsilon);
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveFloat, epsilon));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+primitiveInt"
+ ", \"\"+primitiveFloat, 0): %s %s %s%n"
, primitiveInt, primitiveFloat, epsilon);
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveDouble, epsilon));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+primitiveInt"
+ ", \"\"+primitiveDouble, epsilon): %s %s %s%n"
, primitiveInt, primitiveDouble, epsilon);
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectInt, 0));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+primitiveInt"
+ ", \"\"+objectInt, 0): %s %s %s%n"
, primitiveInt, objectInt, epsilon);
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectLong, 0));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+objectLong"
+ ", \"\"+objectLong, 0): %s %s %s%n"
, primitiveInt, primitiveLong, epsilon);
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectFloat, epsilon));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+primitiveInt"
+ ", \"\"+objectFloat, epsilon)): %s %s %s%n"
, primitiveInt, objectFloat, epsilon);
Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectDouble, epsilon));
System.out.format("Test passed: "
+ "Assert.assertTrue(equalsNumerically(\"\"+primitiveInt"
+ ", \"\"+objectDouble, 0): %s %s %s%n"
, primitiveInt, objectDouble, epsilon);
Test output
测试输出
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, 0): 1 1 0.001
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, epsilon)): 1 1 0.001
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveFloat, 0): 1 0.999999 0.001
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveDouble, epsilon): 1 0.999999 0.001
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectInt, 0): 1 1 0.001
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectLong, 0): 1 1 0.001
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectFloat, epsilon)): 1 0.999999 0.001
Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectDouble, 0): 1 0.999999 0.001