当前位置: 首页 > 面试题库 >

Java SafeVarargs批注,是否存在标准或最佳实践?

燕烨
2023-03-14
问题内容

我最近遇到了Java
@SafeVarargs批注。搜寻是什么使Java中的可变参数功能不安全,这让我感到很困惑(堆中毒?擦除了类型?),所以我想知道一些事情:

  1. 是什么使得可变参数Java函数在@SafeVarargs某种意义上不安全(最好以深入示例的形式进行解释)?

  2. 为什么该注释留给程序员自己决定?这不是编译器应该能够检查的东西吗?

  3. 为了确保其功能确实是安全的,是否必须遵循一些标准?如果没有,有什么最佳实践来确保呢?


问题答案:

1)Internet和StackOverflow上有许多有关泛型和varargs特定问题的示例。基本上,就是当您有数量可变的类型参数类型的参数时:

<T> void foo(T... args);

在Java中,varargs是一种语法糖,在编译时会进行简单的“重写”:类型X...为varargs的参数将转换为类型为的参数X[];每次调用此varargs方法时,编译器都会收集varargs参数中包含的所有“变量参数”,并像创建一个数组new X[] { ...(arguments go here)... }

当varargs类型为时,此方法效果很好String...。当它是类型变量(如)时T...,也可以在T已知为该调用的具体类型时使用。例如,如果上面的方法是class的一部分Foo<T>,并且您有一个Foo<String>引用,则可以进行调用foo,因为我们知道代码中T正是String在这一点上。

但是,当of的“值” T是另一个类型参数时,它将不起作用。在Java中,不可能创建类型参数组件类型(new T[] { ... })的数组。因此,Java改为使用new Object[] { ... }(这Object是的上限T;如果上限不同,则用代替Object),然后向您发出编译器警告。

那么创建new Object[]而不是new T[]什么有什么问题呢?好吧,Java中的数组在运行时知道其组件类型。因此,传递的数组对象在运行时将具有错误的组件类型。

对于varargs的最常见用法,只需遍历元素,这没问题(您不必关心数组的运行时类型),因此这是安全的:

@SafeVarargs
final <T> void foo(T... args) {
    for (T x : args) {
        // do stuff with x
    }
}

但是,对于任何依赖于所传递数组的运行时组件类型的事物,这都是不安全的。这是不安全并崩溃的简单示例:

class UnSafeVarargs
{
  static <T> T[] asArray(T... args) {
    return args;
  }

  static <T> T[] arrayOfTwo(T a, T b) {
    return asArray(a, b);
  }

  public static void main(String[] args) {
    String[] bar = arrayOfTwo("hi", "mom");
  }
}

这里的问题是,我们依靠的类型argsT[]为了回击T[]。但是实际上,运行时参数的类型不是的实例T[]

3)如果您的方法具有T...类型参数(其中T是任何类型参数),则:

  • 安全:如果您的方法仅取决于以下事实,即数组的元素是以下元素的实例: T
  • 不安全:如果取决于数组是以下对象的实例的事实 T[]

依赖于数组的运行时类型的事情包括:将其作为类型返回T[],将其作为参数传递给type参数T[],使用获取数组类型.getClass(),将其传递给依赖于数组的运行时类型的方法,例如List.toArray()Arrays.copyOf()

2)我上面提到的区分太复杂了,以至于无法自动区分。



 类似资料:
  • 我最近遇到了java注释。谷歌搜索是什么使Java中的可变函数变得不安全,这让我相当困惑(堆中毒?删除类型?),所以我想知道一些事情: > 在意义上,是什么使一个不同的Java函数不安全(最好以深入示例的形式解释)? 是否有一些标准必须遵守,以确保他的功能确实是安全的?如果没有,有什么最佳做法来确保它?

  • 问题内容: 在python中,您通常使用PEP 8-Python代码样式指南 作为您的编码标准/准则吗?您还有其他更喜欢的正式标准吗? 问题答案: “在python中,您通常使用PEP 8-Python代码样式指南作为您的编码标准/准则吗?您是否还需要其他正式的标准?” 如您所提到的,请遵循PEP 8作为主要文本,并遵循PEP 257 作为文档字符串约定 与Python样式指南一起,建议您参考以下

  • 问题内容: 我想知道是否存在某种“标准”用于在数据库中存储美国地址?看来这是一项常见的任务,应该有某种标准。 我正在寻找的是数据库表应如何工作和交互的 特定 模式,已经是第三种标准形式,包括数据类型(MySQL)。一个好的UML文档将起作用。 也许我只是在偷懒,但这是一个非常常见的任务,而且我确信有人发布了在某处进行此操作的有效方法。我只是不知道在哪里寻找,而Google并没有帮助。请指出我的资源

  • 问题内容: 我们有很多对象,我们希望为其实现简单的输出对象属性的对象。其中一些属性可能是复杂的对象本身。 是否有任何标准,或者仅仅是样式的最佳实践?我在想类似的东西: 在这种情况下,嵌套值将如下所示: 我们正在使用Java,但是我发现自己在大多数语言中都在问同样的问题! 问题答案: 就我个人而言,我发现混合使用它并不太容易立即获得层次结构的视图。 我喜欢这种格式(并且已经在很多地方看到它使用过):

  • 问题内容: 我用来处理我的Go依赖项。最好也将目录提交到版本控制中吗?还是在签出存储库后始终执行的最佳实践? 问题答案: 该工具的常见问题解答可以回答以下问题: 我应该提交供应商目录吗? 由你决定: 优点 * 这是获得真正可复制的构建的唯一方法,因为它可以防止上游重命名,删除和提交历史记录覆盖。*在执行大多数操作(例如,获取,克隆,获取最新信息,合并等)之后,无需额外的dep确保步骤即可将供应商/

  • 我有一个存储库层,有许多方法组合,以匹配搜索标准…重用这个标准的最佳方法是什么?我认为像FindByNameAndidandBirthdayandAccouncAnumber这样的方法名称不是一个好主意!谢了! }