その他のJavaメモ
文法・API関連
環境関連


文法・API関連
配列をリストに変換する
配列をリストに変換するには、java.utils.Arrays#asList()を使います。

String[] files = {"a.txt", "b.txt", "c.txt"};
List fileList = Arrays.asList(files);

また、ArrayListを次のように一行で初期化する書き方もあります。

List<String> params = Arrays.asList("1", "2", "3");

リストを配列に変換する
その逆は java.util.collections#toArray()を使います。

String[] files = fileList.toArray(new String[fileList.size()]);

配列やリストをログ出力のために簡易に文字列に整形する
最も簡単な方法を集めてみました。

String[] arr = //...
System.out.println(Arrays.toString(arr));
String[][] d2arr = //...
System.out.println(Arrays.deepToString(d2arr));

List alist = //...
// リストは単純にtoString()で行ける
System.out.println(alist.toString());

// 配列のリスト
List blist = //...
System.out.println(Arrays.deepToString(blist.toArray()));

ただしこれらは改行などの整形は行わず、1行に表示するだけなので、 見やすく凝った整形にしたい場合は外部ライブラリを使うか、自分でループして記述する必要があります。

リストの要素を削除しながらループする
一例として、次のように作ったListから、空欄の要素を全て削除したいです。

List<String> a = new ArrayList<String>();
a.add("Taro");
a.add("");
a.add("Jiro");
a.add("");
a.add("");
a.add("Saburo");
a.add("Shiro");
a.add("");
a.add("Goro");

まず駄目な例から。これだと、連続する""の内、後ろの方が残ってしまいます。 つまり要素の削除によって後ろの要素が前に詰まるため、ループを飛ばされる要素が出てしまいます。

for (int i = 0; i < a.size(); i++) {
    if(a.get(i).equals("")) {
        a.remove(i);
    }
}

これに対して主な方法は3つあります。まず最初の例は、当然ながら末尾の要素から逆向きにループする方法。 これなら飛ばされる要素が出る問題は起きません。

for (int i = a.size()-1; i > 0; i--) {
    if(a.get(i).equals("")) {
        a.remove(i);
    }
}

2つ目の方法。これも当然ながら、削除するたびループカウンタも--する方法。 ただしループ内にループカウンタを操作するのはトリッキーなので、バグの混入に注意がいりそうです。

for (int i = 0; i < a.size(); i++) {
    if(a.get(i).equals("")) {
        a.remove(i--);
    }
}

最後がIterator経由で削除する方法。可読性が良く堅牢な方法と言えます。 これだと前方方向にループしながら、要素が飛ぶことも回避できます。

Iterator<String> iter = a.iterator();
while(iter.hasNext()) {
    String s = iter.next();
    if(s.equals("")) {
        iter.remove();
    }
}

ファイルのパス区切りを正規化する
ファイルのパスを文字列処理していて、UNIXのパス区切り("/") と Windowsのパス区切り("\")が混ざってしまった場合、 これをプラットフォームのパス区切り文字に統一する簡単な方法です。

String s = "\usr\home/data/temp";
System.out.println(new File(s).getCanonicalPath());

ディレクトリとファイル名を連結してパスを作る
これでok

String filePath = new File(dirPath, fileName).getPath();

doubleを小数点以下指定桁で四捨五入するには?
"DecimalFormatで文字列にする"というのは無しで、本当にdoubleを四捨五入する方法です。
ちなみに、Math.round()は常に整数に丸めようとするので、今回の目的には使えません。

// vを小数点3桁で四捨五入し、小数点以下2桁のdoubleにする。
double v2 = new BigDecimal(v).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

文字列をbooleanに変換するには?
Java APIを読んで慌てて使うと間違えやすいのですが、 「Boolean.getBoolean(String)」メソッドでは、文字列をbooleanには変換できません。 これは引数のシステムプロパティの値がtrueどうかを返すメソッドです。 上記目的のためには、「Boolean.valueOf(String).booleanValue()」とするのが正解です。

String.compareTo()の返す値はどっちがどっちだっけ?

int result = str1.compareTo(str2);

は、「str1の方が大きければ正の値」=「str2の方が小さければ正の値」です。
同じ文字列なら0です。

staticメソッドはオーバーライドできないの?
できません。
基底クラスと派生クラスの両方で同じ名前のstaticメソッドを定義できますが、 それはオーバーライドではありません。Overrideアノテーションをつけるとエラーになります。


環境関連
システムプロパティをコマンドライン以外の場所で共通設定する
システムプロパティは一例で「java -Duser.language=ja」のようにjavaのコマンドラインに-Dオプションで付与できますが、 毎回指定しなくても共通の場所で定義すれば効くようにしたい。
というときは、

export JAVA_TOOL_OPTIONS="-Duser.language=ja -Duser.country=JP"

のような行を個人単位なら~/.bashrcか~/.bash_profile、 全ユーザー共通なら/etc/profile.d/java-cmdline.sh (名前は任意です)というファイルに記入すればOKです。
設定されたかを確認するには次のような簡単なJavaプログラムを作り、

public class ListSystemProperties {
    public static void main(String[] args) {
        System.getProperties().forEach((key, value) -> {
            System.out.println(key + ": " + value);
        });
    }
}

コンパイルして実行すればOKです。
または最近のjavaはコンパイルしなくても.javaソースのまま実行できますよ。
ちなみに、標準出力に設定の一覧を出力するだけでいいなら、以下の1行でokです。

System.getProperties().list(System.out);

実行しているJavaVMのデフォルトエンコーディングを得る

String encoding = System.getProperty("file.encoding");

この値は"windows-31j"だったり"UTF-8"だったり、UNIXのSJISだと"PCK"だったりします。
ものすごくニッチな用途としては、「全角ハイフン」の文字化け問題を解決するために、 エンコーディングがSJISの環境に限り\uFF0Dを\u2212に変換するとかの判定に使えます。

ロード済のあるクラスが、どこに置かれたJarファイルからロードされたのかを知るには?

MyCustomPredicate o = new MyCustomPredicate();
ClassLoader classLoader = o.getClass().getClassLoader();
URL classURL = classLoader.getResource("jp/co/my/custom/MyCustomPredicate.class");
System.out.println(classURL.toString());
classURL = classLoader.getResource("org/apache/commons/collections/Predicate.class");
System.out.println(classURL.toString());

ClassLoader#getResource()を使えば可能です。
このときクラスのパッケージ階層は、リソースとして指定するので、 .ではなくスラッシュ/で区切ることと、".class"もつける必要があることに要注意。
なお上のPredicateのように、インターフェースの.classファイルも調べることができます。
上記の結果は、 「jar:file:/C:/usr/java/lib/commons-collections-3.2.jar!/org/apache/commons/collections/Predicate.class」 のような形式で得られます。

WindowsでのCLASSPATHのうっかり1

set CLASSPATH=".\classes;C:\the\path\of\aaa.jar;C:\the\path\of\bbb.jar"
java sample.SampleMain

を実行するとNoClassDefFoundErrorが出て延々悩みました。
CLASSPATHは引用符で全体を囲んだら駄目です。つけないのが正解。

set CLASSPATH=.\classes;C:\the\path\of\aaa.jar;C:\the\path\of\bbb.jar
java sample.SampleMain

WindowsでのCLASSPATHのうっかり2

set CLASSPATH=C:\Wintools\groovy-3.0.5\lib\groovy-3.0.5.jar
set CLASSPATH=%CLASSPATH%;D:\usr\java\lib\poi4\*.jar

を実行するとNoClassDefFoundErrorが出て延々悩みました。(2回目)
ワイルドカードは「*.jar」や「*.JAR」と書いては駄目です。必ず「*」と書かないと効きません。

set CLASSPATH=C:\Wintools\groovy-3.0.5\lib\groovy-3.0.5.jar
set CLASSPATH=%CLASSPATH%;D:\usr\java\lib\poi4\*

jarコマンドでwarファイルを作る
コマンドラインの例です。

cd \temp
jar cvf webapp01.war -C C:/usr/java/projects/webapp01 .

java.lang.IncompatibleClassChangeError?
この珍しいエラーには、2回別々の原因で出会ったことがあります。

  1. あるインターフェースAと、それを参照するクラスBを作り、それぞれコンパイルしました。
  2. Aをインターフェースから抽象クラスに変更し、Aだけをコンパイルしました。
  3. Bをインスタンス化するか、またはObjectからキャストして初めてそのどれかのメソッドをコールしようとすると、 このエラーが出ました。
もう1つは、クラスローダが何種類かあるTomcatで、 クラスAがクラスBに、クラスBがインターフェースCに依存している状態で、 クラスローダ1がAとCをロードし、クラスローダ2がBをロードしてしまったような場合です。

The hierarchy of the type *** is inconsistent
このエラーは、クラスAを作ってaaa.jarに含めていて、 Aを継承して作ったクラスBをbbb.karに含めていて、 Bを継承してクラスCを作ろうとしているとき、 aaa.jarがclasspathに含まれていないと発生します。

VMのメモリ使用状況を確認するには
次のようにして、JavaVMの空きメモリ容量、総メモリ容量、使用可能な最大容量を取得できます。 (maxMemoryは定義されていない場合は取得できないこともあるらしい)

long free  = Runtime.getRuntime().freeMemory();
long total = Runtime.getRuntime().totalMemory();
long max   = Runtime.getRuntime().maxMemory();

JUnitで、例外が想定通りに発生したかどうかを検証するには
JUnitについてはメモページがまだないのでここでtipsを。 これは逆に、fail()メソッドを使って、例外が発生「しなかったら」 テストが失敗するように書けばOKです。

try {
    int result = targetObj.targetMethod("argumenttt");
    fail();
} catch(IllegalFormatException ex){
    // 例外が予想通りに発生した。
}

Java kowaza Top

(first uploaded 2004/05/03 last updated 2025/09/23, URANO398)