Voidオブジェクトを返す


113

Voidそれがプリミティブではないときに、型を返す正しい方法は何ですか?例えば。現在、以下のようにnullを使用しています。

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something
        return null;
    }
}

1
インタープリターパターンを使用して、ファイル形式のインタープリターを作成していますが、一部の式に戻り値がありません
Robert

2
Void型をインスタンス化する方法はないため、その型の何かを本当に返す必要がある場合は、nullが唯一のオプションです。ただし、おそらく何にも戻り値は必要ないため、nullで十分です。
Jorn

ええ、それは私の論理でもありました。もっとセマンティックな方法があるかどうか疑問に思いました
Robert

1
私はあなたの例のようにそれをコード化します。それは素晴らしいアプローチです。
David Roussel

回答:


134

Voidクラスは、インスタンス化できないプレースホルダークラスであり、Javaキーワードvoidを表すClassオブジェクトへの参照を保持します。

したがって、次のいずれかで十分です。

  • でパラメータ化しObjectて返す、new Object()またはnull
  • でパラメータ化しVoidて返すnull
  • NullObjectあなたのもののパラメータ化

このメソッドを作成することはできません。void他のものは何かを返します。その何かは無視されるので、何でも返すことができます。


2
次に、戻り値の型のvoidを実現するための一般的に正しい方法は何ですか?
Robert

1
nullをvoidとして返したい場合は、場合によってはキャストする必要があります:(Void)null
Patrick Favre

return (Void)null;
Alex R

(Void)nullは、何らかの方法でnullと区別できますか?
Orangle

13

Java 8ではOptional<T>、このような場合に使用できる新しいクラスが導入されました。これを使用するには、次のようにコードを少し変更します。

interface B<E>{ Optional<E> method(); }

class A implements B<Void>{

    public Optional<Void> method(){
        // do something
        return Optional.empty();
    }
}

これにより、返すものがない場合でも、メソッドから常に null以外の戻り値を取得できます。これnullは、Eclipse @NonNull@Nullableアノテーションなど、返される可能性があるかどうかを検出するツールと組み合わせて使用​​すると特に強力です。


5
私の意見では、これは間違った方向に進んでいるということです。より明確な意味を伝える、より制約されたタイプを返すことをお勧めします。Optional<Void>あなたが与えるのと同じ理由で何かを返すものを持つことは不必要です、あなたはいつもOptional<Void>空のものを手に入れるので、他のすべてのメソッドは無意味です。これは、オプションの値を使用する必要がある理由の逆です。値がある場合とない場合があるため、これを使用します。また、コンパイラはmethod()それを正しく実装することを強制できません。これは実行時に失敗します:return Optional.of(null)
steinybot 2017年

3

タイプとして何も必要ない場合は、voidを使用できます。これは、機能またはアクションの実装に使用できます。その後、次のようなことを行うことができます。

interface Action<T> {
    public T execute();
}

abstract class VoidAction implements Action<Void> {
    public Void execute() {
        executeInternal();
        return null;
    }

    abstract void executeInternal();
}

または、抽象クラスを省略して、自分で戻り値を必要としないすべてのアクションでnullを返すこともできます。

次に、これらのアクションを次のように使用できます。

与えられた方法

private static <T> T executeAction(Action<T> action) {
    return action.execute();
}

あなたはそれを

String result = executeAction(new Action<String>() {
    @Override
    public String execute() {
        //code here
        return "Return me!";
    }
});

または、voidアクションの場合(結果を何にも割り当てないことに注意してください)

executeAction(new VoidAction() {
    @Override
    public void executeInternal() {
        //code here
    }
});

2
これは私が既に持っているものとどう違うのですか?私が提案したように、それでもまだnullを返します
Robert

なぜ他に何かを返さなければならないのですか?私が強調しようとしている点は、戻り値は必要ないため、何を返すかは問題ではありません。私は自分の編集でそれを明確にしようとしました。
Jorn

1

それだけのために、もちろんVoidリフレクションを使用してインスタンスを作成する可能性があります:

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something

        try {
            Constructor<Void> voidConstructor = Void.class.getDeclaredConstructor();
            voidConstructor.setAccessible(true);
            return voidConstructor.newInstance();
        } catch (Exception ex) {
            // Rethrow, or return null, or whatever.
        }
    }
}

本番環境では、おそらくそれを行わないでしょう。


0

メソッドが何も返さないことをコンパイラーに伝えるジェネリック型はありません。

慣習は、型パラメーターとして継承するときにObjectを使用することです

または

型パラメーターを上に伝播し、クラスのユーザーがObjectを使用してインスタンス化し、type-wildcardを使用して型指定された変数にオブジェクトを割り当てられるようにします?

interface B<E>{ E method(); }

class A<T> implements B<T>{

    public T method(){
        // do something
        return null;
    }
}

A<?> a = new A<Object>();

1
これは、ジェネリックで戻り値の型をvoidに設定するための規則ですか?それは私にはあまり見えませんか?
Robert

私はこれが進むべき道だと信じています。クラスのユーザーはA<?>、の戻り値を使用できませんmethod()
クリストファーOezbek
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.