Javaのボイドタイプ

1. 概要

Java開発者として、私たちはいつか_Void_型に遭遇し、その目的は何かを疑問に思っていたかもしれません。
このクイックチュートリアルでは、この特異なクラスについて学習し、いつどのように使用するか、可能な限り使用しないようにする方法を確認します。

2. _Void_タイプとは

JDK 1.1以降、Javaは_Void_型を提供します。 *その目的は、_void_戻り値の型をクラスとして単に表し、__ Class <Void> __public値を含めることです。*コンストラクターはプライベートであるため、インスタンス化できません。
したがって、a__Void_変数に割り当てることができる値は、_null_のみです。 少し役に立たないように見えるかもしれませんが、このタイプをいつどのように使用するかを見ていきましょう。

3. 使い方

_Void_型を使用すると興味深い場合があります。

3.1. 反射

まず、リフレクションを行うときに使用できます。 実際、* _ void_メソッドの戻り値の型は、前述の_Class <Void> _値を保持するvalue_Void.TYPE_変数と一致します*。
単純な_Calculator_クラスを想像してみましょう:
public class Calculator {
    private int result = 0;

    public int add(int number) {
        return result += number;
    }

    public int sub(int number) {
        return result -= number;
    }

    public void clear() {
        result = 0;
    }

    public void print() {
        System.out.println(result);
    }
}
整数を返すメソッドもあれば、何も返さないメソッドもあります。 さて、リフレクションにより、結果を返さないすべてのメソッドを取得する必要があるとします*。 これを実現するには、_Void.TYPE_変数を使用します。
@Test
void givenCalculator_whenGettingVoidMethodsByReflection_thenOnlyClearAndPrint() {
    Method[] calculatorMethods = Calculator.class.getDeclaredMethods();
    List<Method> calculatorVoidMethods = Arrays.stream(calculatorMethods)
      .filter(method -> method.getReturnType().equals(Void.TYPE))
      .collect(Collectors.toList());

    assertThat(calculatorVoidMethods)
      .allMatch(method -> Arrays.asList("clear", "print").contains(method.getName()));
}
ご覧のとおり、_clear()_および_print()_メソッドのみが取得されています。

3.2. ジェネリックス

_Void_型のもう1つの使用法は、ジェネリッククラスです。 _Callable_パラメーターを必要とするメソッドを呼び出しているとします:
public class Defer {
    public static <V> V defer(Callable<V> callable) throws Exception {
        return callable.call();
    }
}
*しかし、渡したい_Callable_は何も返す必要はありません。 したがって、_Callable <Void> _:*を渡すことができます
@Test
void givenVoidCallable_whenDiffer_thenReturnNull() throws Exception {
    Callable<Void> callable = new Callable<Void>() {
        @Override
        public Void call() {
            System.out.println("Hello!");
            return null;
        }
    };

    assertThat(Defer.defer(callable)).isNull();
}
ランダムタイプ(たとえば、 _Callable <Integer> _)およびreturn _null_またはタイプなし(_Callable)_ですが、* using _Void_は意図を明確に示しています。*
このメソッドをラムダに適用することもできます。 実際のところ、_Callable_はラムダとして記述できます。 a _Function_を必要とするメソッドを想像してみますが、何も返さないa _Function_を使用したいと思います。 次に、それを返す必要があります_Void_:
public static <T, R> R defer(Function<T, R> function, T arg) {
    return function.apply(arg);
}
@Test
void givenVoidFunction_whenDiffer_thenReturnNull() {
    Function<String, Void> function = s -> {
        System.out.println("Hello " + s + "!");
        return null;
    };

    assertThat(Defer.defer(function, "World")).isNull();
}

4. 使用を避ける方法は?

さて、_Void_型のいくつかの使用法を見てきました。 ただし、最初の使用がまったく問題ない場合でも、可能であればジェネリックで_Void_を使用しないようにすることをお勧めします*。 実際、結果が存在しないことを表し、_null_のみを含むことができる戻り値の型に遭遇するのは面倒です。
これらの状況を回避する方法について説明します。 最初に、_Callable_パラメーターを使用したメソッドを検討します。 * a__Callable <Void> _の使用を回避するために、代わりにa__Runnable_パラメーターを使用する別のメソッドを提供できます。*
public static void defer(Runnable runnable) {
    runnable.run();
}
したがって、値を返さない_Runnable_を渡すと、無駄な_return null_を取り除くことができます。
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello!");
    }
};

Defer.defer(runnable);
しかし、その後、_Defer_クラスが変更するものではない場合はどうなりますか? 次に、_Callable <Void> _オプションに固執するか、* _Runnable_を取得してtaking_Defer_クラスへの呼び出しを延期する別のクラスを作成します*。
public class MyOwnDefer {
    public static void defer(Runnable runnable) throws Exception {
        Defer.defer(new Callable<Void>() {
            @Override
            public Void call() {
                runnable.run();
                return null;
            }
        });
    }
}
これにより、面倒な部分を独自のメソッドで一度だけカプセル化し、将来の開発者がよりシンプルなAPIを使用できるようにします。
もちろん、same_Function_についても同じことが実現できます。 この例では、_Function_は何も返さないため、代わりにa__Consumer_を取る別のメソッドを提供できます。
public static <T> void defer(Consumer<T> consumer, T arg) {
    consumer.accept(arg);
}
次に、関数がパラメーターを受け取らない場合はどうなりますか? a _Runnable_を使用するか、独自の機能インターフェイスを作成できます(より明確に思える場合)。
public interface Action {
    void execute();
}
次に、_defer()_メソッドを再度オーバーロードします。
public static void defer(Action action) {
    action.execute();
}
Action action = () -> System.out.println("Hello!");

Defer.defer(action);

5. 結論

この短い記事では、Java _Void_クラスについて説明しました。 その目的と使用方法を確認しました。 また、その使用法の代替案もいくつか学びました。
いつものように、この記事の完全なコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-reflection[our GitHub]にあります。