Java 9で@SafeVarargsアノテーションが必要な理由とは?
Javaの可変長引数(varargs)機能は、配列型のパラメータを定義したり、同じメソッドのオーバーロード版を複数作成したりすることなく、可変数の引数を受け取るメソッドを手軽に実装できるようにするために導入されました。
しかし、Java 9より前のバージョンでは、varargsメソッドをジェネリクスと組み合わせて使用すると、必ず警告メッセージが表示されるという問題がありました。実際にはすべてのメソッドがヒープ汚染(heap pollution)を引き起こすわけではないにもかかわらず、コンパイラはジェネリクスを使うすべてのvarargsメソッドに対して一律に警告を出していたのです。
この課題を解決するために、Java 9では@SafeVarargsアノテーションが正式に拡張されました。このアノテーションを付与すると、そのメソッドが型安全であることを開発者が明示的に保証したことになり、コンパイラはunchecked関連の警告を表示しなくなります。
なお、@SafeVarargsはstaticメソッド、finalメソッド、privateメソッドに適用できます。特にJava 9からは、従来適用できなかったprivateインスタンスメソッドにも使用可能になりました。
まず、警告を確認するために、以下のコマンドでコードをコンパイルしてみましょう。
javac -Xlint:unchecked SafeVarargsTest1.java
例1:@SafeVarargsを付けていない場合
次の例では、ジェネリクスを使用したvarargsメソッドに対して、コンパイラが警告メッセージを表示します。
import java.util.Arrays;
import java.util.List;
public class SafeVarargsTest1 {
public static void main(String args[]) {
SafeVarargsTest1 test = new SafeVarargsTest1();
test.varargsMethod(Arrays.asList("Adithya", "Jaidev"), Arrays.asList("Raja", "Chaitanya"));
}
private void varargsMethod(List<String>... list) {
for(List list1: list)
System.out.println(list1);
}
}
出力結果
SafeVarargsTest.java:7: warning: [unchecked] unchecked generic array creation for varargs parameter of type List[]
test.varargsMethod(Arrays.asList("Adithya", "Jaidev"), Arrays.asList("Raja", "Chaitanya"));
^
SafeVarargsTest.java:9: warning: [unchecked] Possible heap pollution from parameterized vararg type List
private void varargsMethod(List... list) {
^
2 warnings
[Adithya, Jaidev]
[Raja, Chaitanya]
このように、プログラム自体は正常に動作していますが、「unchecked generic array creation」と「Possible heap pollution」という2つの警告が出力されています。
例2:@SafeVarargsを付けた場合
次の例では、privateメソッドの直前に@SafeVarargsアノテーションを付与しています。その結果、警告メッセージは一切表示されなくなります。
import java.util.Arrays;
import java.util.List;
public class SafeVarargsTest2 {
public static void main(String args[]) {
SafeVarargsTest2 test = new SafeVarargsTest2();
test.varargsMethod(Arrays.asList("Adithya", "Jaidev"), Arrays.asList("Raja", "Chaitanya"));
}
@SafeVarargs
private void varargsMethod(List<String>... list) {
for(List list1: list)
System.out.println(list1);
}
}
出力結果
[Adithya, Jaidev] [Raja, Chaitanya]
このように、@SafeVarargsアノテーションを使用することで、ジェネリクスとvarargsを組み合わせた安全なメソッドについて、不要なコンパイラ警告を抑制し、よりクリーンなコードを実現できます。ただし、このアノテーションは「そのメソッドが実際にヒープ汚染を引き起こさない」ことを開発者が責任を持って保証する場合にのみ使用すべき点には注意しましょう。
-
JavaでArrayListをループ処理する5つの方法を徹底解説
このチュートリアルでは、JavaでArrayListを反復処理(イテレーション)する5つの異なる方法を紹介します。Java 8以降では、forEachメソッドやIteratorクラスを使ってArrayListをループ処理することも可能です。 ArrayListをループ処理する主な方法 ArrayListをループ処理する方法は、主に以下の5つがあります。 従来のfor文(クラシックForループ) 拡張for文 Iterator(イテレータ) while文 forEachメソッド(Java 8) まずは、各ループの例で使用するArrayListを作成しましょう。 import java.uti
-
JavaでList(リスト)を配列に変換する方法|toArray()とArrays.asList()の使い方
Javaの開発において、List(リスト)と配列(Array)の相互変換は非常によく使われる基本的な操作です。 Listを配列に変換する最も簡単かつ推奨される方法は、.toArray()メソッドを使うことです。逆に、配列をListに戻したい場合は、Arrays.asList()メソッドを使用します。 以下では、文字列(String)のListや整数(Integer)のListを、それぞれ対応する配列に変換する具体例を紹介します。 String型のListを配列に変換する import java.util.ArrayList; import java.util.List; public cl