Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何测试泛化API的类型安全性?_Java_Api_Generics_Testing_Type Safety - Fatal编程技术网

Java 如何测试泛化API的类型安全性?

Java 如何测试泛化API的类型安全性?,java,api,generics,testing,type-safety,Java,Api,Generics,Testing,Type Safety,例如,您可以使用JUnit来测试库的功能,但是如何测试泛型和通配符的类型安全性呢 只有针对编译代码的测试才是“快乐路径”测试;您是否应该针对非类型安全的用法测试您的API,并确认这些代码不可编译 // how do you write and verify these kinds of "tests"? List<Number> numbers = new ArrayList<Number>(); List<Object> object

例如,您可以使用JUnit来测试库的功能,但是如何测试泛型和通配符的类型安全性呢

只有针对编译代码的测试才是“快乐路径”测试;您是否应该针对非类型安全的用法测试您的API,并确认这些代码不可编译

   // how do you write and verify these kinds of "tests"?

    List<Number> numbers = new ArrayList<Number>();
    List<Object> objects = new ArrayList<Object>();

    objects.addAll(numbers); // expect: this compiles

    numbers.addAll(objects); // expect: this does not compile
//如何编写和验证这些类型的“测试”?
列表编号=新的ArrayList();
列表对象=新的ArrayList();
objects.addAll(数字);//expect:此编译
number.addAll(对象);//expect:这不会编译
那么,如何验证泛型API在编译时是否引发了正确的错误呢?您是否只是构建了一个非编译代码的套件来测试您的库,并将编译错误视为测试成功,反之亦然?(当然,您必须确认错误与泛型相关)


是否有框架可以促进此类测试?

听起来您正在尝试测试Java编译器,以确保如果您分配了错误的类型,它将引发正确的编译错误(而不是测试您自己的api)


如果是这样的话,为什么不担心编译器在为字符串字段分配整数、调用尚未初始化的对象上的方法以及编译器在编译代码时应该检查的其他数百万项时不会失败呢

我想你的问题并不局限于泛型。我们可以对非泛型代码提出同样的问题。如果你描述的工具存在,我会害怕的。有很多人非常乐意测试他们的能手和二传手(并尝试在其他人身上实施)。现在,他们更乐于编写新的测试,以确保不会编译对其私有字段的访问!哦,人性


但我猜泛型要复杂得多,所以你的问题没有意义。对于大多数程序员来说,如果他们能最终编译他们该死的泛型代码,他们会很高兴的。如果一段泛型代码没有编译(这是开发过程中的常态),他们真的不知道该怪谁。

因为这不是传统意义上的测试(也就是说,你不能“运行”测试),我认为这样的工具不存在,我可以建议如下:

  • 进行定期的单元测试
  • 在其中生成代码-正确的代码和错误的代码
  • 使用尝试编译它并检查结果

  • 您可以为该功能制作一个易于使用的包装器,并为任何有需求的人提供它。

    也许您可以在单元测试中使用Collections.checkedList()。下面的示例将编译,但会引发ClassCassException。以下示例摘自@Simon G

    List<String> stringList = new ArrayList<String>();
    List<Number> numberList = Collections.checkedList(new ArrayList<Number>(), Number.class);
    stringList.add("a string");
    List list = stringList;
    numberList.addAll(list);
    System.out.println("Number list is " + numberList);
    
    List-stringList=new-ArrayList();
    List numberList=Collections.checkedList(新的ArrayList(),Number.class);
    添加(“字符串”);
    列表=字符串列表;
    numberList.addAll(列表);
    System.out.println(“数字列表为”+numberList);
    
    测试编译失败听起来像是找错了方向,然后用螺丝刀再次剥去树皮。为正确的工作使用正确的工具

    我认为您需要一个或多个:

    • 代码审查(可能由JRT之类的代码审查工具支持)
    • 静态分析工具(FindBugs/CheckStyle)
    • 切换语言到C++,支持实现(也可能需要将宇宙切换到其中存在这样一个实现的一个)。
    如果您真的需要将其作为“测试”来处理,您可以使用反射来强制执行任何所需的规则,比如“任何以add开头的函数都必须有一个泛型参数”。这与传统的API没有太大区别,只是更笨拙、更不易重用。

    如何测试您的泛型API的类型安全性?IMHO,您的问题的简短答案应该是:

    • 不要使用任何
      @SuppressWarnings
    • 确保编译时没有警告(或错误)
    较长的答案是,“类型安全性”不是API的属性,而是编程语言及其类型系统的属性。Java 5泛型是类型安全的,因为它保证在运行时不会出现类型错误(
    ClassCastException
    ),除非它源于用户级的强制转换操作(如果使用泛型编程,则很少再需要此类强制转换)。唯一的后门是使用原始类型与Java 5之前的代码进行互操作,但是对于这些情况,编译器将发出警告,例如臭名昭著的“unchecked cast”警告,以指示类型安全性可能受到损害。但是,如果没有此类警告,Java将保证您的类型安全


    因此,除非您是编译器编写者(或者您不信任编译器),否则想要测试“类型安全性”似乎很奇怪。在您给出的代码示例中,如果您是
    ArrayList
    的实现者,您应该只注意为
    addAll
    提供最灵活的类型签名,以允许您编写功能正确的实现。例如,可以将参数键入“代码>集合< /COD>”,也可以作为“代码>集合< <代码> >或代码>集合> p>,在C++中,他们试图用概念来实现这一点,但从标准中启动。 使用Eclipse,当Java中的某些东西无法编译时,我可以很快地恢复,并且错误消息非常直接。例如,如果您希望一个类型有一个特定的方法调用,但它没有,那么您的编译器会告诉您需要知道什么。与类型不匹配的情况相同


    幸运的是,将编译时概念构建到java:p

    中需要直观地验证预期不可编译代码的编译是否工作似乎不符合单元测试的精神,单元测试应该能够通过单击按钮或快速键盘快捷键来运行。你也许可以