2014-03-13 79 views
0

这里是我的一群学生提出的问题的意译,而且事实证明,找到一个答案是有点麻烦(对我来说,反正)比我预期:测试方法是否返回双打

假设您要求我编写一个具有String参数的方法f,并返回一个double。你现在希望通过编写你自己的测试代码来测试我是否已经正确地完成了自己的工作,如果我已经按照指定编写了f,那么这些代码将会被编译,但是如果我没有编写则不会编译。

有些学生提出的这个不正确的解决方案:

System.out.println(f("cat")); 

这不是一个很好的测试,因为它并不测试方法的返回类型。也就是说,即使我写了f来返回一个String或一个int或一个布尔值,它也会被编译,等等。

我提出的这个解决方案给学生:

double d = f("cat"); 

我的理由是,这个测试F是否接受字符串并返回双打。但是,真的,这也不好。 f可以返回一个int(或任何“较窄”的原始数据类型),并且结果可以存储在d中。

所以,我正在寻找的想法,一个简单的解决(代码一行或两行,也许?)的问题:写代码如果f已被正确定义(字符串参数,将编译,双倍返还),但如果f没有按照指定写入,则不会编译。

+0

[反思](http://docs.oracle.com/javase/tutorial/reflect/)。 – Maroun

+0

我意识到Java的反射存在,但没有使用它。我不知道它满足摆在问题中的“编译时测试”部分,但我确实知道Reflection有很多开销。有没有非反射解决方案? – normKrumpe

回答

4

反思是最适合在这里一般(这是一个非常不寻常的要求),但别的东西,至少会的工作是使用重载决议:提供可供选择的方法与floatlongDouble参数,但void返回类型...和一个带有参数类型为double的方法和一个非void返回类型。然后检查是否可以为调用该方法的结果分配一个值,结果为f。例如:

public void foo(long x) {} 
public void foo(float x) {} 
public void foo(Double x) {} 
public void foo(Object x) {} 
public int foo(double x) { 
    return 0; 
} 

// This will only compile if f is declared to return double 
int check = foo(f("cat")); 
+0

天才解决方案。 – Maroun

+0

不应该'检查'是'双'吗? (虽然编译器无关紧要) – Maroun

+0

@MarounMaroun:不是 - 它与'foo'返回的类型是相同的返回类型,它与'f'返回的类型完全不同。重要的是这是一个非虚无的方法......这就是我们真正关心的。 –

0

使用反射:获得类java.lang.reflect.Method中,与名F和参数类型的字符串相匹配的实例,该实例的使用返回类型等于双。TYPE

从Double类类文档:

公共静态final类TYPE表示基本类型双

1

这里的Class实例是一个编译时断言(虽然会产生假积极DoubleObject):

List<Double> a = new ArrayList<Double>(); 
a.add(f("cat")); 

或者干脆:

double[] a = {f("cat")}; 

这里是一个运行时断言(虽然会产生假阳性DoubleFloatfloat):

try 
{ 
    double d = f("cat")/0; 
} 
catch (Exception e) 
{ 
    return false; 
} 
return true; 
+0

对于您的第一个解决方案,我喜欢它,并且它暗示ArrayList是不必要的...只是尝试将返回存储在Double中。但是,如果f被误写为返回Double而不是double,那该怎么办? – normKrumpe

+0

@normKrumpe,正如我所说:“它会产生'双重'的误报*。 –

0

我们可以返回的对象类型,而不是和禁用的编译器选项自动装箱的IDE错误以获得确切的返回类型以及.exc:int不能返回整数..等等

对于原语,我们需要反射,这可能是一个有点沉重的操作。