[解決済み] Java SafeVargsアノテーション、標準やベストプラクティスは存在するのか?
質問
私は最近、Javaの
@SafeVarargs
というアノテーションがあります。Javaで可変長関数を安全でなくするものについてググると、かなり混乱しました(ヒープポイズニング? 消去された型?
-
で可変長のJava関数が安全でない理由は何ですか?
@SafeVarargs
の意味で、(できれば詳細な例の形で説明されるのが望ましい)? -
なぜこのアノテーションはプログラマーの裁量に任されているのでしょうか?これはコンパイラがチェックできるはずのものではないのですか?
-
自分の関数が本当にバラグセーフであることを確認するために、守らなければならない基準がありますか?もしそうでなければ、それを保証するためのベストプラクティスは何でしょうか?
どのように解決するのですか?
1) ジェネリックとバラグに関する特殊な問題については、インターネットやStackOverflowに多くの事例があります。基本的には、型-パラメータ型の引数を可変個にした場合です。
<T> void foo(T... args);
Java では、varargs は構文上の糖であり、コンパイル時に単純に "書き直し" が行われます。
X...
のパラメータに変換されます。
X[]
そして、この varargs メソッドを呼び出すたびに、コンパイラは varargs パラメータに入るすべての "variable arguments" を収集し、次のような配列を作成します。
new X[] { ...(arguments go here)... }
.
これは、varargs の型が次のような具象的なものである場合にうまく機能します。
String...
. のような型変数である場合
T...
の場合にも有効です。
T
は、その呼び出しの具象型であることが知られています。例えば、上記のメソッドがクラス
Foo<T>
があり、その中に
Foo<String>
を参照すると
foo
がわかっているので、問題ないでしょう。
T
は
String
を、その時点のコードで表示します。
しかし、quot;value" の場合はうまくいきません。
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");
}
}
ここで問題なのは、「Subject」の型に依存していることです。
args
になるように
T[]
として返すために
T[]
. しかし、実際には実行時の引数の型は
T[]
.
3) メソッドに型の引数がある場合
T...
(ここでTは任意の型パラメータ)である。
-
安全です。のインスタンスであることにのみ依存する場合、そのメソッドは安全です。
T
-
安全でない 配列のインスタンスが
T[]
配列の実行時型に依存するものには、以下のようなものがあります:型として返すこと
T[]
のパラメータに引数として渡す。
T[]
を使用して配列の型を取得します。
.getClass()
のように、配列の実行時の型に依存するメソッドに渡します。
List.toArray()
と
Arrays.copyOf()
など。
2) 上で述べたような区別は複雑すぎて、簡単に自動で区別することはできない。
関連
-
springboot project MIMEタイプ text/htmlで転送された静的ファイルを読み込む。
-
スレッド "main" で例外発生 java.lang.ArrayIndexOutOfBoundsException: 0 at One1.main(One1.java:3)
-
[解決済み] Javaはパラメータのデフォルト値をサポートしていますか?
-
[解決済み] Javaの「for each」ループはどのように機能するのですか?
-
[解決済み] なぜJavaにはtransientフィールドがあるのですか?
-
[解決済み] Javaで、オブジェクトの大きさを決定する最も良い方法は何ですか?
-
[解決済み] Javaは複数行の文字列をサポートしていますか?
-
[解決済み] Transactionalアノテーションはどこに属しますか?
-
[解決済み】Javaではfinallyブロックは必ず実行されるのですか?
-
[解決済み】array[idx++]+="a "は、Java 8ではidxを1回増やすが、Java 9と10では2回増やすのはなぜか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
スタイルシートとして解釈されるリソースが、MIMEタイプtext/htmlで転送される。
-
java の例外が発生しました java
-
myeclipseでコンパイルするとAntエラーが発生する javaの例外が発生しました。
-
final, finally, finalizeの違いについて話してください。
-
Android Studio 3.1.2 で v4, v7 パッケージが見つからない シンボル 'AppCompatActivity' を解決できない
-
プロジェクトの依存関係を解決できなかった 解決
-
Spring BootのテストメソッドFailed to load ApplicationContextの問題を解決する
-
起動時にEclipseエラーが発生しました。起動中に内部エラーが発生しました。java.lang.NullPoin: "Javaツーリングの初期化 "中に内部エラーが発生しました。
-
[解決済み] varargs パラメータでヒープを汚染する可能性があります。
-
[解決済み】Javaでvarargsを使うのはどんなとき?