📜  Java 9 中的@SafeVarargs 注释与示例

📅  最后修改于: 2022-05-13 01:54:36.612000             🧑  作者: Mango

Java 9 中的@SafeVarargs 注释与示例

@SafeVarargs 注解:@SafeVarargs 注解是在JDK 7 中引入的。@SafeVarargs 注解用于抑制编译时的不安全操作警告。每当在我们的代码中调用具有可变参数(即可变数量的参数)的方法时,就会在编译时出现不安全操作警告。 @SafeVarargs 注释可以与方法/构造函数一起使用,方法应该是最终的或静态的。我们可以将@SafeVarargs 注释与无法覆盖的方法一起使用,因为覆盖方法仍然可以对其可变参数执行不安全的操作。 @SafeVarargs 注解用于表示方法不会造成堆污染。这些方法被认为是安全的。

在 JDK 9 中,JDK 开发人员扩展了 @SafeVarargs 注解的使用,现在除了 final 或 static 方法之外,我们还可以将 @SafeVarargs 注解与私有方法一起使用。这是因为私有方法不能被覆盖。

什么是不安全操作警告?

Java 5 引入了 Varargs 的概念,即可变长度的方法参数,以及 Generics,并且这次仅添加了未检查或不安全操作警告。现在的问题是,当我们使用带有可变参数的方法或使用泛型时,为什么编译器会抛出警告?当编译器抛出不安全操作警告时,编译器通常会要求您以一种或另一种方式更明确地说明类型。

让我们通过一些例子来理解这个概念:

// Program to illustrate the unsafe operation warnings
// message with respect to varargs parameter
  
import java.util.ArrayList;
import java.util.List;
  
public class Geeksforgeeks {
  
    // print is a method with variable argument
    private void print(List... topics)
    {
        for (List topic : topics) {
            System.out.println(topic);
        }
    }
  
    public static void main(String[] args)
    {
        Geeksforgeeks obj = new Geeksforgeeks();
        List list = new ArrayList();
        list.add("OOPS");
        list.add("COLLECTION");
        obj.print(list);
    }
}

编译时控制台:

Note: Geeksforgeeks.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

输出:

[OOPS, COLLECTION]

这里我们有一个 List 类型的可变参数的方法。但是这里我们没有提到 List 将存储的数据类型。这里编译器会警告你我不会检查你的代码。我不会检查您将添加到 ArrayList 的值是否属于任何特定类型。这就是为什么它会在编译时抛出不安全操作警告。这里编译器想知道类型

List geeks = new ArrayList();

如果我们将创建具有类型的 ArrayList,那么编译器将不会在编译时抛出任何警告消息。

让我们在使用 @SafeVarargs 注释后再次运行相同的代码。

// Program to illustrate the
// @SafeVarargs with respect to varargs
  
import java.util.ArrayList;
import java.util.List;
  
public class Geeksforgeeks {
  
    // Here we used @SafeVarargs annotation,
    // now we will not get any unchecked
    // or unsafe operations warning message
    // at compile time
    @SafeVarargs
    private void print(List... topics)
    {
        for (List topic : topics) {
            System.out.println(topic);
        }
    }
  
    public static void main(String[] args)
    {
        Geeksforgeeks obj = new Geeksforgeeks();
        List list = new ArrayList();
        list.add("OOPS");
        list.add("COLLECTION");
        obj.print(list);
    }
}

输出:

[OOPS, COLLECTION]

注意:假设如果您想在 JDK 7 或 JDK 8 中运行上述代码,那么您将收到编译错误,因为这些增强功能是在Java 9 中完成的,在Java 9 之前 - 不允许使用此注释标记私有方法。

// Program to illustrate the unsafe
// operation warnings message
// with respect to Generics
  
import java.util.ArrayList;
import java.util.List;
  
public class Geeks {
  
    private List topics = new ArrayList<>();
  
    // Here add() is a method with varargs of type T
    // Here T is unknown for
    // the compiler at the compile time
    // That's why It will throw unsafe
    // operation warning message
    public final void add(T... toAdd)
    {
        for (T topic : toAdd) {
            topics.add(topic);
        }
    }
  
    public static void main(String[] args)
    {
        Geeks geek = new Geeks();
        geek.add("OOPS",
                 "COLLECTIONS",
                 "EXCEPTION-HANDLING");
        System.out.println(geek.topics);
    }
}

编译时控制台:

Note: Geeks.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

输出:

[OOPS, COLLECTIONS, EXCEPTION-HANDLING]

让我们在使用 @SafeVarargs 注释后再次运行相同的代码。

// Program to illustrate the
// @SafeVarargs with respect to Generics
  
import java.util.ArrayList;
import java.util.List;
  
public class Geeks {
  
    private List topics = new ArrayList<>();
  
    // Here by placing @SafeVarargs annotation
    // to add() method, we are ensuring to the
    // compiler that our action is safe.
    // That's why compiler will not throw
    // any warning message at the compile time.
    @SafeVarargs
    public final void add(T... toAdd)
    {
        for (T topic : toAdd) {
            topics.add(topic);
        }
    }
  
    public static void main(String[] args)
    {
        Geeks geek = new Geeks();
        geek.add("OOPS",
                 "COLLECTIONS",
                 "EXCEPTION-HANDLING");
        System.out.println(geek.topics);
    }
}

输出:

[OOPS, COLLECTIONS, EXCEPTION-HANDLING]