Java の落穂拾い
[履歴] [最終更新] (2017/07/05 00:23:36)
最近の投稿
注目の記事

ラムダ式 (Java 8)

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

class Main {

    public static String myFunc(Function<String, String> callback) {
        return callback.apply("hi");
    }

    public static void main(String args[]) {

        // コールバック関数
        System.out.println(myFunc(s -> s + "!")); //=> hi!

        // Scala のようなコレクション操作
        List<String> list = Arrays.asList("aaa", "bbb");

        list.forEach(s -> System.out.println(s)); 

        for(String s: list) {   // Java 7 までのよくある書き方
            System.out.println(s);
        }

        // 変数に代入
        Function<String, String> func = (String s) -> {
            return s + "!";
        };
        Function<String, String> func2 = (String s) -> s + "!"; // 一行記法
        Function<String, String> func3 = s -> s + "!"; // 型の省略
        System.out.println(func.apply("hi")); //=> hi!
        System.out.println(func2.apply("hi")); //=> hi!
        System.out.println(func3.apply("hi")); //=> hi!
    }
}

実装のあるインターフェース (Java 8)

Java 8 から Interface が実装をもてるようになりました。Scala トレイトのようなものです。

MyInterface.java

public interface MyInterface {
    default public String func() {
        return "MyInterface.func";
    }
}

MyClass.java

public class MyClass implements MyInterface {
    // オーバーライドする場合
    // public String func() {
    //     return "hello, " + MyInterface.super.func();
    // }
}

Main.java

class Main {
    public static void main(String args[]) {
        MyInterface obj = new MyClass();
        System.out.println(obj.func());
    }
}

実行例

$ javac *.java && java Main
MyInterface.func

static インポート

通常 import は、あるパッケージのクラスを指定します。import static とすることで、あるパッケージのクラスの静的メンバを指定できます。

import static java.lang.Math.PI;
import static java.lang.Math.cos;

class Main {
    public static void main(String args[]) {
        System.out.println(cos(PI)); //=> -1.0
    }
}

インナークラス

MyClass.java

public class MyClass {
    private String str = "abc";

    private class MyInnerClass {
        private String func() {
            return str;
        }
    }

    public String func() {
        MyInnerClass obj = new MyInnerClass();
        return obj.func();
    }
}

Main.java

class Main {
    public static void main(String args[]) {
        MyClass obj = new MyClass();
        System.out.println(obj.func());
    }
}

実行例

$ javac *.java && java Main
abc

例外について

Java の例外クラスは java.lang.Throwable を継承する以下の三つのクラスのいずれかを継承しています。

  • java.lang.Error (JVM の実行が継続できない致命的なエラー; try-catch-finally で扱うものではありません)
  • java.lang.Exception (検査例外; コンパイル時に try-catch-finally の実装が強制されます)
  • java.lang.RuntimeException (実行時例外; コンパイル時に try-catch-finally の実装が強制されません。java.lang.Exception を継承しています)

Error, Exception, RuntimeException それぞれの具体例は、以下の Javadoc で確認できます。例えば NullPointerExceptionRuntimeException です。

実行時例外の例

class Main {

    public static void myFunc() throws ArithmeticException, NullPointerException { // いずれも実行時例外
        throw new NullPointerException("ぬるぽ");
    }

    public static void main(String args[]) {
        myFunc(); // 実行時例外は try-catch で囲まなくてもコンパイルは通ります。
    }
}

例外情報の表示

class Main {
    public static void main(String args[]) {
        try {
            throw new NullPointerException("ぬるぽ");
        }
        catch (ArithmeticException | NullPointerException e) {
            System.out.println(e.getMessage()); //=> ぬるぽ
            e.printStackTrace(); //=> java.lang.NullPointerException: ぬるぽ...
        }
    }
}

Java 7 から利用できる、リソースを自動でクローズする構文 (try-with-resources)

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.IOException;

class Main {
    public static void main(String args[]) {
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("Main.java"), "UTF-8"));
            BufferedReader reader2 = new BufferedReader(new InputStreamReader(new FileInputStream("Main.java"), "UTF-8"))) {
            String line = null;
            while((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
}

外部コマンドの実行

import java.util.Map;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

class Main {
    public static void main(String args[]) {
        try {
            // コマンド指定
            ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l");

            // 環境変数の操作
            Map<String, String> environment = processBuilder.environment();
            System.out.println(environment.get("PATH"));
            environment.put("DUMMY", "aaa");

            // プロセスの動作ディレクトリを指定して非同期実行
            Process process = processBuilder.directory(new File("/")).start();

            // 標準 (エラー) 出力を取得
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = null;
            while((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // 非同期実行したプロセスが終了するのを待つ
            process.waitFor();
            // process.destroy(); // 強制終了したい場合

            // 終了ステータス
            System.out.println(process.exitValue()); //=> 0 (正常)
        }
        catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

JVM 設定 (システムプロパティと環境変数)

import java.util.Arrays;
import java.util.List;
import java.util.Map;

class Main {
    public static void main(String args[]) {

        // JVM システムプロパティ (Java 8 で表示する例)
        System.setProperty("my.prop1", "123"); // `java -Dmy.prop1=123 Main` と同じ効果

        List<String> list = Arrays.asList("my.prop1", //=> 123
                                          "file.encoding", //=> UTF-8
                                          "file.separator", //=> /
                                          "path.separator", //=> :
                                          "java.version", //=> 1.8.0_60
                                          "java.vm.name", //=> Java HotSpot(TM) 64-Bit Server VM
                                          "java.home", //=> /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre
                                          "java.library.path", //=> /Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
                                          "os.name", //=> Mac OS X
                                          "os.version", //=> 10.10.5
                                          "os.arch", //=> x86_64
                                          "user.dir"); //=> /path/to/current/dir

        list.forEach(s -> System.out.println(System.getProperty(s)));

        // JVM プロセスの環境変数 (Java 8 で表示する例)
        Map<String, String> map = System.getenv();
        map.forEach((key, value) -> System.out.println(key + "=" + value));
        System.out.println(System.getenv("PATH")); //=> /usr/local/bin:/usr/bin:/bin
    }
}

リフレクション

クラスの構造を実行中に読み取ることができます。

Main.java

import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Main {

    public static String toString(Object obj) {

        StringBuilder sb = new StringBuilder();
        Class clazz = obj.getClass(); // Class インスタンス

        sb.append(clazz.getName());

        Field[] fields = clazz.getDeclaredFields();
        Method[] methods = clazz.getDeclaredMethods();

        for(Field field : fields) {
            sb.append("," + field.getName());
        }
        for(Method method : methods) {
            sb.append("," + method.getName());
        }
        return sb.toString();
    }

    public static void main(String args[]) {
        MyClass obj = new MyClass();
        System.out.println(Main.toString(obj));
    }
}

MyClass.java

public class MyClass {
    public int iPublic;
    private int iPrivate;
    public void methodPublic(){}
    private void methodPrivate(){}
}

実行例

$ javac *.java && java Main
MyClass,iPublic,iPrivate,methodPublic,methodPrivate

ジェネリクス

Java SE 5 から導入された、C++ のテンプレートのような機能です。こちらのページでまとめた Java コレクションのリストで List<Integer> list といった記述を行うことで、リストに格納される要素の型を明記できます。リストクラスのように、型を明記せずにジェネリックな状態で汎用的に定義することで、特定の型に依存しないクラスを定義できます。

Main.java

package myproject;

public class Main {

    public static void main(String[] args) {
        MyClass<String> objStr = new MyClass<String>("string");
        System.out.println(objStr.get());
    }
}

MyClass.java

package myproject;

public class MyClass<T> {
    T obj;

    public MyClass(T obj) {
        this.obj = obj;
    }

    public T get() {
        return obj;
    }
}

実行例

string
関連ページ
    正規表現 import java.util.regex.Pattern; import java.util.regex.Matcher; class Main { public static void main(String args[]) { { // 完全一致 Pattern pattern = Pattern.com
    概要 Java SE 5 から導入されたアノテーション機能に関する基本事項をまとめます。アノテーションは @Xxx の形式で、Java の言語機能としては表現できない補足情報を注釈 (annotation) として記述するための仕組みです。クラス、インターフェース、メソッド、メンバ変数、メソッド引数などの定義箇所に記述します。
    概要 Android におけるデータ保存の方法は主に三つ用意されています。それぞれの利用方法をまとめます。 関連する公式ドキュメント Training / Saving Data Key-Value Sets Files SQL Databases API Guides / Storage Options
    概要 Spring フレームワークにおける @Transactional アノテーションを利用すると DB トランザクション処理が簡単に設定できます。ここでは特に、こちらのページで環境構築した Spring Boot から MyBatis を経由して MySQL を利用する場合を対象としますが、JDBC を利用して他の DB を操作する場合も考え方は同じです。
    サンプルプログラム sample.py #!/usr/bin/python class MainClass: x = 128 def setX(self, x): self.x = x def getX(self): return self.x class SubClass(MainClass): def __init__(se