【概要】
Eclipseの「ウィンドウ -> 設定 -> Java -> コンパイラー -> エラー/警告」でエラー/警告が発生する具体的なコードを書きました。
一部コードの書き方が分からない項目もありましたが、分からなかったものについてはソース上に「実装方法不明」とコメントしています。
【環境】
Java 17
Eclipse Version: 2023-06 (4.28.0)、Build id: 20230608-1333
【エラー/警告の一覧表】
下記表の項番はソースコードでコメントしている項番と一致しています。
コード・スタイル
項番 | エラー/警告 項目名 |
---|---|
1-1 | staticメンバーへの非staticアクセス |
1-2 | staticメンバーへの間接アクセス |
1-3 | インスタンス・フィールドへの限定されていないアクセス |
1-4 | エンクロージング型のアクセス不可メンバーへのアクセス |
1-5 | パラメータ代入 |
1-6 | 外部化されていないString(欠落している/未使用の$NON-NLS$タグ) |
1-7 | 何も記述のない空のブロック |
1-8 | try-with-resourceで管理されていないリソース(1.7以上) |
1-9 | コンストラクター名を持つメソッド |
1-10 | staticにできるメソッド |
1-11 | 潜在的にstaticにできるメソッド |
潜在的なプログラミングの問題
項番 | エラー/警告 項目名 |
---|---|
2-1 | 同じ値の比較('x == x') |
2-2 | 効果のない代入(例:「x = x」) |
2-3 | 予期しない論理代入の可能性(たとえば、'if(a = b)') |
2-4 | ボクシングおよびアンボクシング変換 |
2-5 | ストリング連結での文字列配列の使用 |
2-6 | 可変長引数の型の一致が不正確 |
2-7 | ありそうもない'Object'を使用するコレクション・メソッドの引数型 |
2-7-1 | 予想される型に対して厳密な分析を実行する |
2-8 | ありそうもないequals()メソッドの引数型 |
2-9 | 空のステートメント |
2-10 | 未使用のオブジェクト割り振り |
2-11 | enumの不完全な'switch'ケース |
2-11-1 | 'default'ケースが存在する場合も知らせる |
2-12 | 'default'ケースが欠落した'switch' |
2-13 | 'switch'文のcaseのフォールスルー |
2-14 | 隠れたcatchブロック |
2-15 | 'finally'が正常に完了しない |
2-16 | デッド・コード(例:'if (false)') |
2-17 | リソース・リーク |
2-18 | 潜在的なリソース・リーク |
2-19 | serialVersionUIDなしのシリアライズ可能クラス |
2-20 | 継承されたメソッドのsynchronized修飾子の欠落 |
2-21 | 'equals()' をオーバーライドしているが 'hashCode()' がオーバーライドされていないクラス: |
名前のシャドーイングおよび競合
項番 | エラー/警告 項目名 |
---|---|
3-1 | フィールド宣言が他のフィールドまたは変数を隠蔽 |
3-2 | ローカル変数宣言が他のフィールドまたは変数を隠蔽 |
3-2-1 | コンストラクターまたはsetterメソッド・パラメーターを含む |
3-3 | 型パラメーターが別の型を隠蔽 |
3-4 | メソッドがパッケージ可視メソッドを非オーバーライド |
3-5 | protectedの'Object'メソッドと競合するインターフェース・メソッド |
使用すべきではない制限されたAPI
項番 | エラー/警告 項目名 |
---|---|
4-1 | 使用すべきではないAPI |
4-1-1 | 使用すべきではないコード内での使用すべきではないAPIの使用を知らせる |
4-1-2 | 使用すべきではないメソッドのオーバーライドまたは実装を知らせる |
4-2 | 除去とマークされた廃止予定のAPI |
4-3 | 禁止された参照(アクセス・ルール) |
4-4 | 阻止された参照(アクセス・ルール) |
モジュール
項番 | エラー/警告 項目名 |
---|---|
5-1 | APIリーク |
5-2 | 不安定な名前が必要な自動モジュール |
不要なコード
項番 | エラー/警告 項目名 |
---|---|
6-1 | ローカル変数の値が未使用 |
6-2 | メソッド・パラメーターの値が未使用 |
6-2-1 | オーバーライドしたメソッドの実装を無視 |
6-3 | 未使用の型パラメーター |
6-4 | '@param'タグで未使用の文書化されたパラメーターを無視 |
6-5 | 例外パラメーターの値が未使用 |
6-6 | 未使用のインポート |
6-7 | 未使用のprivateメンバー |
6-8 | 不要な'else'ステートメント |
6-9 | 不要なキャストまたは'instansof'操作 |
6-10 | 不要な例外スロー宣言 |
6-10-1 | オーバーライドしたメソッドの実装を無視 |
6-10-2 | '@throws'または'@exception'で文書化された例外を無視 |
6-10-3 | 'Exception'および'Throwable'を無視 |
6-11 | 未使用の'break'または'continue'ラベル |
6-12 | 冗長なスーパー・インターフェース |
総称型
項番 | エラー/警告 項目名 |
---|---|
7-1 | 未検査の総称型操作 |
7-2 | raw型の使用 |
7-3 | finalな型で制約された総称型パラメーター |
7-4 | 冗長な型引数(1.7以上) |
7-5 | raw APIが原因で避けられない総称型問題を無視 |
注釈
項番 | エラー/警告 項目名 |
---|---|
8-1 | '@Override'注釈の欠落 |
8-1-1 | インターフェース・メソッドの実装を含める(1.6以上) |
8-2 | '@Deprecated'注釈の欠落 |
8-3 | 注釈をスーパー・インターフェースとして使用 |
8-4 | '@SuppressWarnings'で処理されないトークン |
8-5 | '@SuppressWarnings'注釈の使用可能化 |
8-5-1 | 未使用の'@SuppressWarnings'トークン |
8-5-2 | 関連するオプションが'無視'に設定され、完全には認識されない'未使用'ステータス |
8-5-3 | '@SuppressWarnings'でオプション・エラーを抑制 |
Null分析
項番 | エラー/警告 項目名 |
---|---|
9-1 | nullポインター・アクセス |
9-2 | 潜在的なnullポインター・アクセス |
9-3 | 冗長なnull検査 |
9-4 | null分析で'assert'を含める |
9-5 | 注釈ベースのnull分析を使用可能にする |
9-5-1 | null仕様違反 |
9-5-2 | null注釈およびnullインスタンスへの競合 |
9-5-3 | 非注釈型から@NonNull型への未検査変換 |
9-5-4 | 注釈付きのパラメーター化された型から注釈の少ないタイプへの安全でない変換 |
9-5-5 | 自由型変数のための悲観的な分析によって検出された問題 |
9-5-6 | ライブラリーからの自由型変数の安全でない'@Nonnull'の解釈 |
9-5-7 | 冗長なnull注釈 |
9-5-8 | オーバーライドするメソッドで注釈が付けられていない'@NonNull'パラメーター |
9-5-9 | パッケージの'@NonNullByDefault'注釈が欠落 |
9-5-10 | null仕様のデフォルト注釈を使用する |
9-5-11 | null注釈の継承 |
9-5-12 | フィールドの構文null分析を使用可能にする |
9-5-13 | すべてのビルド・パス・ロケーションで外部注釈を検索する |
【GitHubにアップロードしたプロジェクト構成】
- errors-warnings
- Null分析以外のソースコード
- errors-warnings-null-analysis
- Null分析だけのソースコード(@org.eclipse.jdt.annotation.NonNullを使用するには、Springプロジェクトで作成する必要があったため)
- unstableAutoModuleName
- モジュールで利用するためのjar作成用のソースコード
【ソースコード】
errors-warningsプロジェクト
コード・スタイル
CodeStyle.java
package codestyle;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class CodeStyle extends CodeStyleParent {
private static final int CODE_STYLE = 0;
private void indirectStaticAccess() {
CodeStyle codeStyle = new CodeStyle();
// 1-1. staticメンバーへの非staticアクセス
int a = codeStyle.CODE_STYLE;
}
private void staticAccessReceiver() {
// 1-2. staticメンバーへの間接アクセス
int a = CodeStyle.CODE;
}
private int codeStyle;
private void unqualifiedFieldAccess() {
// 1-3. インスタンス・フィールドへの限定されていないアクセス
int a = codeStyle;
}
private void syntheticAccessEmulation() {
EnclosingClass ec = new EnclosingClass();
// 1-4. エンクロージング型のアクセス不可メンバーへのアクセス
// おそらくJava8以前のバージョンにしないとエラー/警告が起きない
// 少なくともJava8のバージョンではエラー/警告が起きることを確認済み
int a = ec.a;
}
class EnclosingClass {
private int a;
int b;
}
private void parameterAssignment(int a) {
// 1-5. パラメータ代入
a = 1;
}
private void nonExternalizedStringLiteral() {
// 1-6. 外部化されていないString(欠落している/未使用の$NON-NLS$タグ)
String a = "a";
int b = 1; //$NON-NLS-1$
}
private void undocumentedEmptyBlock(boolean can) {
// 1-7. 何も記述のない空のブロック
if (true) {
}
}
private void explicitlyClosedAutoCloseable() throws IOException {
// 1-8. try-with-resourceで管理されていないリソース(1.7以上)
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(".classpath"), "UTF-8"));
try {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
throw e;
} finally {
try {
reader.close();
} catch (IOException e) {
throw e;
}
}
}
// 1-9. コンストラクター名を持つメソッド
private void CodeStyle() {
}
// 1-10. staticにできるメソッド
private void reportMethodCanBeStatic() {
int a = 1;
}
// 1-11. 潜在的にstaticにできるメソッド
public void reportMethodCanBePotentiallyStatic() {
int a = CodeStyle.CODE;
}
}
CodeStyleParent.java
package codestyle;
public class CodeStyleParent {
public static final int CODE = 1;
}
潜在的なプログラミングの問題
ProgrammingProblem.java
package programmingproblem;
import java.io.BufferedReader;
import java.io.CharConversionException;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.io.UncheckedIOException;
import java.nio.file.DirectoryIteratorException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
// 2-21. 'equals()'をオーバーライドしているが'hashCode()'がオーバーライドされていないクラス
public class ProgrammingProblem extends ProgrammingProblemParent {
private void comparingIdentical(int a) {
// 2-1. 同じ値の比較('x == x')
if (a == a) {
}
}
private void noEffectAssignment(int a) {
// 2-2. 効果のない代入(例:「x = x」)
a = a;
}
private void possibleAccidentalBooleanAssignment(boolean a, boolean b) {
// 2-3. 予期しない論理代入の可能性(たとえば、'if(a = b)')
if (a = b) {
}
}
private void autoboxing(int a, Integer b) {
// 2-4. ボクシングおよびアンボクシング変換
// ボクシング変換
Integer c = a;
// アンボクシング変換
int d = b;
}
private void noImplicitStringConversion() {
// 2-5. ストリング連結での文字列配列の使用
String a = "hello" + new char[] { 'w', 'o', 'r', 'l', 'd' };
}
private void varargsArgumentNeedCast() {
// 2-6. 可変長引数の型の一致が不正確
Arrays.asList(null);
}
private void unlikelyCollectionMethodArgumentType() {
Map<String, String> a = new HashMap<>();
// 2-7. ありそうもない'Object'を使用するコレクション・メソッドの引数型
a.get(1);
}
private void unlikelyCollectionMethodArgumentTypeStrict(Object o) {
Map<?, ?> a = new HashMap<>();
// 2-7-1. 予想される型に対して厳密な分析を実行する にチェックあり
a.get(o);
}
private void unlikelyEqualsArgumentType(Collection<Path> aaa) {
// 2-8. ありそうもないequals()メソッドの引数型
"abc".equals(1);
}
private void emptyStatement() {
// 2-9. 空のステートメント
;
}
private void unusedObjectAllocation() {
// 2-10. 未使用のオブジェクト割り振り
new ArrayList<>();
}
private enum Color {
RED, GREEN, BLUE
}
private void incompleteEnumSwitch(Color color) {
// 2-11. enumの不完全な'switch'ケース
switch (color) {
case RED:
System.out.println("赤");
break;
case GREEN:
System.out.println("緑");
break;
}
// 2-11-1. 'default'ケースが存在する場合も知らせる にチェックあり
switch (color) {
case RED:
System.out.println("赤");
break;
case GREEN:
System.out.println("緑");
break;
default:
System.out.println("その他");
}
}
private void missingDefaultCase(Color color) {
// 2-12. 'default'ケースが欠落した'switch'
switch (color) {
case RED:
System.out.println("赤");
break;
case GREEN:
System.out.println("緑");
break;
}
}
private void fallthroughCase(Color color) {
switch (color) {
case RED:
System.out.println("赤");
// 2-13. 'switch'文のcaseのフォールスルー
case GREEN:
System.out.println("緑");
break;
}
}
private void hiddenCatchBlock() {
try {
throw new CharConversionException();
} catch (CharConversionException e) {
// 2-14. 隠れたcatchブロック
} catch (IOException e) {
}
}
private void finallyBlockNotCompletingNormally() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(".classpath"), "UTF-8"));
try {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
throw e;
// 2-15. 'finally'が正常に完了しない
} finally {
try {
reader.close();
return;
} catch (IOException e) {
throw e;
}
}
}
private void deadCode() {
if (true) {
// 2-16. デッド・コード(例:'if (false)')
} else {
}
}
private void unclosedCloseable() throws IOException {
// 2-17. リソース・リーク
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(".classpath"), "UTF-8"));
try {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
throw e;
}
}
// java.nio.file.Filesのlist(Path dir)の実装をそのままコピーしたもの
private Stream<Path> potentiallyUnclosedCloseable(Path dir) throws IOException {
DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
try {
final Iterator<Path> delegate = ds.iterator();
// Re-wrap DirectoryIteratorException to UncheckedIOException
Iterator<Path> iterator = new Iterator<>() {
@Override
public boolean hasNext() {
try {
return delegate.hasNext();
} catch (DirectoryIteratorException e) {
throw new UncheckedIOException(e.getCause());
}
}
@Override
public Path next() {
try {
return delegate.next();
} catch (DirectoryIteratorException e) {
throw new UncheckedIOException(e.getCause());
}
}
};
Spliterator<Path> spliterator =
Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT);
// 2-18. 潜在的なリソース・リーク
return StreamSupport.stream(spliterator, false)
.onClose(asUncheckedRunnable(ds));
} catch (Error|RuntimeException e) {
try {
ds.close();
} catch (IOException ex) {
try {
e.addSuppressed(ex);
} catch (Throwable ignore) {}
}
throw e;
}
}
private static Runnable asUncheckedRunnable(Closeable c) {
return () -> {
try {
c.close();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
};
}
// 2-19. serialVersionUIDなしのシリアライズ可能クラス
private class MissingSerialVersion implements Serializable {
}
@Override
// 2-20. 継承されたメソッドのsynchronized修飾子の欠落
protected void synchronizedMethod() {
}
@Override
public boolean equals(Object obj) {
return true;
}
}
ProgrammingProblemParent.java
package programmingproblem;
public class ProgrammingProblemParent {
protected synchronized void synchronizedMethod() {
}
}
名前のシャドーイングおよび競合
NameShadow.java
package nameshadow;
import nameshadow.override.NameShadowParent;
public class NameShadow extends NameShadowParent {
// 3-1. フィールド宣言が他のフィールドまたは変数を隠蔽
private int a;
private void localVariableHiding() {
// 3-2. ローカル変数宣言が他のフィールドまたは変数を隠蔽
int a;
}
// 3-2-1. コンストラクターまたはsetterメソッド・パラメーターを含む にチェックあり
private NameShadow(int a) {
}
// 3-3. 型パラメーターが別の型を隠蔽
private class Outer<T> {
class Inner<T> {
}
}
// 3-4. メソッドがパッケージ可視メソッドを非オーバーライド
void overridingPackageDefaultMethod() {
}
}
NameShadowParent.java
package nameshadow.override;
public abstract class NameShadowParent {
protected int a;
void overridingPackageDefaultMethod() {
}
}
NameShadowInterface.java
package nameshadow;
public interface NameShadowInterface {
// 3-5. protectedの'Object'メソッドと競合するインターフェース・メソッド
int clone();
}
使用すべきではない制限されたAPI
DeprecatedApi.java
package deprecatedapi;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
public class DeprecatedApi extends DeprecatedApiParent {
private void deprecation() {
// 4-1. 使用すべきではないAPI
Character.isJavaLetter('a');
}
@Deprecated
public void deprecationInDeprecatedCode() {
// 4-1-1. 使用すべきではないコード内での使用すべきではないAPIの使用を知らせる にチェックあり
super.deprecationWhenOverridingDeprecatedMethod();
}
@Override
// 4-1-2. 使用すべきではないメソッドのオーバーライドまたは実装を知らせる にチェックあり
public void deprecationWhenOverridingDeprecatedMethod() {
}
// 4-2. 除去とマークされた廃止予定のAPI は実装方法不明
private void forbiddenReference() throws URISyntaxException {
// 4-3. 禁止された参照(アクセス・ルール)
// ビルドパスのアクセスルールに追加が必要
URI uri = new URI("https://qiita.com");
}
private void discouragedReference() throws MalformedURLException {
// 4-4. 阻止された参照(アクセス・ルール)
// ビルドパスのアクセスルールに追加が必要
URL url = new URL("https://qiita.com");
}
}
DeprecatedApiParent.java
package deprecatedapi;
public class DeprecatedApiParent {
@Deprecated
public void deprecationWhenOverridingDeprecatedMethod() {
}
}
モジュール
Module.java
package modules;
public class Module {
// 5-1. APIリーク
public ApiLeak apiLeak() {
return new ApiLeak();
}
private class ApiLeak {
}
}
module-info.java
module modules {
exports modules;
// 5-2. 不安定な名前が必要な自動モジュール
requires unstableAutoModuleName;
}
不要なコード
UnNecessaryCode.java
package unnecessarycode;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
// 6-6. 未使用のインポート
// ファイル保存時に不要なインポートが自動削除される場合があるため、コメントアウトしている
// 警告確認時はコメントアウトを外す必要がある
// import java.util.regex.Matcher;
//6-12. 冗長なスーパー・インターフェース
public class UnNecessaryCode extends UnNecessaryCodeParent implements UnNecessaryCodeInterface {
private void unusedLocal() {
// 6-1. ローカル変数の値が未使用
int a;
}
// 6-2. メソッド・パラメーターの値が未使用
private void unusedParameter(int a) {
}
@Override
// 6-2-1. オーバーライドしたメソッドの実装を無視 にチェックなし
public void unusedParameterWhenOverridingConcrete(int a) {
}
// 6-3. 未使用の型パラメーター
private <E> void unusedTypeParameter(List<?> list) {
}
/**
*
* @param <E>
* @param list
*/
// 6-3. 未使用の型パラメーター
// 6-4. '@param'タグで未使用の文書化されたパラメーターを無視 にチェックなし
private <E> void unusedParameterIncludeDocCommentReference(List<?> list) {
}
private void unusedExceptionParameter() {
try (BufferedReader twrReader = new BufferedReader(
new InputStreamReader(new FileInputStream(".classpath"), "UTF-8"));) {
String line;
while ((line = twrReader.readLine()) != null) {
System.out.println(line);
}
// 6-5. 例外パラメーターの値が未使用
} catch (IOException e) {
}
}
// 6-7. 未使用のprivateメンバー
private int a;
private void unnecessaryElse() {
if (true) {
return;
// 6-8. 不要な'else'ステートメント
} else {
}
}
private void unnecessaryTypeCheck() {
// 6-9. 不要なキャストまたは'instansof'操作
int a = (int) 1;
}
// 6-10. 不要な例外スロー宣言
private void unusedDeclaredThrownException() throws IOException {
}
@Override
// 6-10-1. オーバーライドしたメソッドの実装を無視 にチェックなし
public void unusedDeclaredThrownExceptionWhenOverriding() throws IOException {
}
/**
*
* @throws IOException
*/
// 6-10-2. '@throws'または'@exception'で文書化された例外を無視 にチェックなし
private void unusedDeclaredThrownExceptionIncludeDocCommentReference() throws IOException {
}
// 6-10-3. 'Exception'および'Throwable'を無視 にチェックなし
private void unusedDeclaredThrownExceptionExemptExceptionAndThrowable() throws Exception {
}
// 6-11. 未使用の'break'または'continue'ラベル
private void unusedLabel() {
label: for (int i = 1; i < 10; i++) {
}
}
}
UnNecessaryCodeParent.java
package unnecessarycode;
import java.io.IOException;
public class UnNecessaryCodeParent implements UnNecessaryCodeInterface {
public void unusedParameterWhenOverridingConcrete(int a) {
}
public void unusedDeclaredThrownExceptionWhenOverriding() throws IOException {
}
@Override
public void redundantSuperinterface() {
}
}
UnNecessaryCodeInterface.java
package unnecessarycode;
public interface UnNecessaryCodeInterface {
public void redundantSuperinterface();
}
総称型
Generics.java
package generics;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Generics extends GenericsParent {
private void uncheckedTypeOperation() {
// 7-1. 未検査の総称型操作
List<Integer> a = new ArrayList(Arrays.asList(1));
}
private void rawTypeReference() {
// 7-2. raw型の使用
List a;
}
// 7-3. finalな型で制約された総称型パラメーター
private <T extends String> T finalParameterBound() {
return null;
}
private void redundantSpecificationOfTypeArguments() {
// 7-4. 冗長な型引数(1.7以上)
List<Integer> a = new ArrayList<Integer>();
}
@Override
// 7-2. raw型の使用
// 7-5. raw APIが原因で避けられない総称型問題を無視 にチェックなし
public void unavoidableGenericTypeProblems(ArrayList list) {
}
}
GenericsParent.java
package generics;
import java.util.ArrayList;
public class GenericsParent {
public void unavoidableGenericTypeProblems(ArrayList list) {
}
}
注釈
Annotation.java
package annotation;
public class Annotation extends AnnotationParent implements AnnotationInterface {
// 8-1. '@Override'注釈の欠落
public void missingOverrideAnnotation() {
}
// 8-1-1. インターフェース・メソッドの実装を含める(1.6以上) にチェックあり
public void missingOverrideAnnotationForInterfaceMethodImplementation() {
}
/**
* @deprecated
*/
// 8-2. '@Deprecated'注釈の欠落
private void missingDeprecatedAnnotation() {
}
// 8-4. '@SuppressWarnings'で処理されないトークン
@SuppressWarnings(value = { "test" })
private void unhandledWarningToken() {
}
// 8-5. '@SuppressWarnings'注釈の使用可能化
@SuppressWarnings("deprecation")
private void suppressWarnings() {
Character.isJavaLetter('a');
}
// 8-5. '@SuppressWarnings'注釈の使用可能化 にチェックあり
// 8-5-1. 未使用の'@SuppressWarnings'トークン
@SuppressWarnings("deprecation")
private void unusedWarningToken() {
}
// 6-7. 未使用のprivateメンバー を"無視"に設定
// 8-5. '@SuppressWarnings'注釈の使用可能化 にチェックあり
// 8-5-2. 関連するオプションが'無視'に設定され、完全には認識されない'未使用'ステータス
@SuppressWarnings("unused")
private void suppressWarningsNotFullyAnalysed() {
}
@SuppressWarnings("all")
private void suppressOptionalErrors(int a) {
// 2-1. 同じ値の比較('x == x')
// 8-5. '@SuppressWarnings'注釈の使用可能化 にチェックあり
// 8-5-3. '@SuppressWarnings'でオプション・エラーを抑制 にチェックなし
if (a == a) {
}
}
@Override
public Class<? extends java.lang.annotation.Annotation> annotationType() {
return null;
}
}
AnnotationParent.java
package annotation;
public class AnnotationParent {
public void missingOverrideAnnotation() {
}
}
AnnotationInterface.java
package annotation;
// 8-3. 注釈をスーパー・インターフェースとして使用
public interface AnnotationInterface extends Override {
public void missingOverrideAnnotationForInterfaceMethodImplementation();
}
errors-warnings-null-analysisプロジェクト
Null分析
NullAnalysis.java
package com.example.demo.nullanalysis;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
public class NullAnalysis {
private void nullReference() {
String a = null;
// 9-1. nullポインター・アクセス
a.length();
}
private void potentialNullReference(String a) {
boolean isNull = a == null;
if (isNull) {
// 9-2. 潜在的なnullポインター・アクセス
a.length();
}
}
private void redundantNullCheck() {
String a = "test";
int b = a.length();
// 9-3. 冗長なnull検査
if (a == null) {
}
}
private void includeNullInfoFromAsserts(String a) {
assert a != null;
// 9-3. 冗長なnull検査
// 9-4. null分析で'assert'を含める
if (a != null) {
}
}
private void nullSpecViolation(@org.eclipse.jdt.annotation.NonNull String a) {
// 9-5-1. null仕様違反
a = null;
}
private void nullAnnotationInferenceConflict(boolean can) {
@org.eclipse.jdt.annotation.NonNull
String a = "a";
String b = "b";
if (can) {
b = null;
}
// 9-5-2. null注釈およびnullインスタンスへの競合
a = b;
}
private void nullUncheckedConversion(boolean can) {
@org.eclipse.jdt.annotation.NonNull
String a;
if (can) {
// 9-5-3. 非注釈型から@NonNull型への未検査変換
a = nullUncheckedConversionSub();
}
}
private String nullUncheckedConversionSub() {
return null;
}
private void annotatedTypeArgumentToUnannotated() {
List<@org.eclipse.jdt.annotation.NonNull String> a = new ArrayList<>();
List<String> b = new ArrayList<>();
// 9-5-4. 注釈付きのパラメーター化された型から注釈の少ないタイプへの安全でない変換
b = a;
}
private class PessimisticNullAnalysisForFreeTypeVariables<T extends Number> {
int consume(T a) {
// 9-5-5. 自由型変数のための悲観的な分析によって検出された問題
return a.intValue();
}
T provide() {
// 9-5-5. 自由型変数のための悲観的な分析によって検出された問題
return null;
}
}
// 9-5-6. ライブラリーからの自由型変数の安全でない'@Nonnull'の解釈 は実装方法不明
@NonNullByDefault
private class RedundantNullAnnotation {
// 9-5-7. 冗長なnull注釈
@org.eclipse.jdt.annotation.NonNull
public String redundantNullAnnotation() {
return "a";
}
}
@NonNullByDefault
private class NonnullParameterAnnotationDroppedParent {
public void nonnullParameterAnnotationDropped(String a) {
}
}
private class NonnullParameterAnnotationDropped extends NonnullParameterAnnotationDroppedParent {
@Override
// 9-5-8. オーバーライドするメソッドで注釈が付けられていない'@NonNull'パラメーター
// 9-5-11. null注釈の継承 にチェックを付けるとエラーがなくなる
public void nonnullParameterAnnotationDropped(String a) {
}
}
@org.eclipse.jdt.annotation.Nullable
private Object a;
private void syntacticNullAnalysisForFields() {
if (a != null)
// 9-2. 潜在的なnullポインター・アクセス
// 9-5-12. フィールドの構文null分析を使用可能にする にチェックを付けるとエラーがなくなる
a.toString();
}
// 9-5-13. すべてのビルド・パス・ロケーションで外部注釈を検索する は実装方法不明
}
MissingNonNullByDefaultAnnotation.java
// 9-5-9. パッケージの'@NonNullByDefault'注釈が欠落
public class MissingNonNullByDefaultAnnotation {
}
【必要だったプロジェクト設定】
使用すべきではない制限されたAPI
下記項目についてはアクセス・ルールの追加が必要でした。
- 4-3. 禁止された参照(アクセス・ルール)
- 4-4. 阻止された参照(アクセス・ルール)
モジュール
下記項目についてはunstableAutoModuleNameプロジェクトをjarにして、外部jarの追加が必要でした。
- 5-2. 不安定な名前が必要な自動モジュール