Java Void参照タイプの使用?


163

JavaはありVoidV--大文字- 参照型。私がこれまでに使用したことのある唯一の状況は、Callables をパラメータ化することです

final Callable<Void> callable = new Callable<Void>() {
            public Void call() {
                foobar();
                return null;
            }
        };

Java Void参照型の他の用途はありますか?これ以外に割り当てることはできますnullか?はいの場合、例はありますか?



回答:


116

Void興味のない一般的な引数の規則になっていますSystem。など、インスタンス化できない他のタイプを使用する理由はありません。

それはまた、多くの場合、例のために使用されているMap値(が、Collections.newSetFromMap用途Booleanマップなどを受け入れることはありませんnull値)とjava.security.PrivilegedAction

私が書いたブログエントリVoid数年前に。


誰がその大会を作ったのですか?docs状態docs.oracle.com/javase/tutorial/java/generics/types.html 「タイプパラメータの命名規則規約により、タイプパラメータ名は単一の大文字です。」
barlop

4
@barlopパラメータ名ではなく引数です。つまり、タイプjava.lang.Voidです。/ジョシュ・ブロッホはこの慣習を広めましたが、それを見たら、それは当然の選択です。
トム・ホーティン-タックライン2015

2
そのブログエントリは死んでいます
mFeinstein

51

リフレクションを使用してVoidのインスタンスを作成できますが、それらは何にも役立ちません。Voidは、ジェネリックメソッドが何も返さないことを示す方法です。

Constructor<Void> constructor = Void.class.getDeclaredConstructor();
constructor.setAccessible(true);
Void v = constructor.newInstance();
System.out.println("I have a " + v);

のようなものを印刷します

I have a java.lang.Void@75636731

22
ドキュメントがインスタンス化不可能であると言うクラスをインスタンス化するための+1。私もこれを行い、インスタンス化されたVoidは役に立たないことに同意します。
ルークウッドワード

1
コンストラクター<Void> cv = Void.class.getDeclaredConstructor(); cv.setAccessible(true); Void v = cv.newInstance(); System.out.println(v); //;)
Peter Lawrey

演習として、リフレクションを使用して新しいクラスを作成し、何が起こるかを確認してください。
Peter Lawrey

sun.reflect.InstantiationExceptionConstructorAccessorImplからjava.lang.InstantiationExceptionを受け取りました。:(
ルークウッドワード

7
これは実装固有であり、いつでも変更される可能性があります。クラスが引数なしのコンストラクターを持っていることは保証されていませんSystem.exit(0)。私は、コンストラクターを使用してユーティリティクラスを作成する傾向がありますprivate Void() { throw new Error(); }。値のない列挙型を好む人もいます。
トム・ホーティン-


19

パブリックコンストラクターないことを考えると、以外に何も割り当てることはできませんnull。あなたの例が示すように、「この汎用パラメーターを使用する必要がない」のプレースホルダーとしてのみ使用しました。

また、Javadocによると、リフレクションで使用することもできます。

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


nullはすべての型のインスタンスであるため、Oracle / Sunがそのように説明しているのを見るのはおかしいです。とにかく、あなたが言ったように、それの純粋な意味は「私はそれに興味がないのでここに任意のタイプを書くことができるので、私は私のコードを読んだ人々がそれを正確に理解するようにVoidを入れます」
Snicolas

17

すべてのプリミティブラッパークラス(IntegerByteBooleanDouble、など)を静的に対応するプリミティブクラスへの参照を含むTYPE、例えば、フィールド:

Integer.TYPE == int.class
Byte.TYPE == byte.class
Boolean.TYPE == boolean.class
Double.TYPE == double.class

Voidvoid型への参照を置く場所として最初に作成されました:

Void.TYPE == void.class

ただし、を使用しても実際には何も得られませんVoid.TYPE。使用void.classすると、void型で何かをしていることがより明確になります。

余談ですが、前回私が試したとき、BeanShellはを認識しなかったvoid.classため、そこで使用する必要Void.TYPEがあります。


8
したがって、Void.classとvoid.classの両方があります。
トムアンダーソン

8

あなたが使用している場合、訪問者のパターンを、あなたが戻り値がnullになることを確認したいとき、代わりに、オブジェクトのボイドを使用するようにきれいにすることができます

public interface LeavesVisitor<OUT>
{
   OUT visit(Leaf1 leaf);

   OUT visit(Leaf2 leaf);
}

ビジターを実装するときに、OUTを明示的にVoidに設定して、ビジターがObjectを使用する代わりに常にnullを返すようにすることができます。

public class MyVoidVisitor implements LeavesVisitor<Void>
{
    Void visit(Leaf1 leaf){
        //...do what you want on your leaf
        return null;
    }

    Void visit(Leaf2 leaf){
        //...do what you want on your leaf
        return null;
    }
}

5

ジェネリックの前は、他のプリミティブ型クラスに対応するvoidメソッドのMethod.getReturnType()によって返されたTYPEを保持するために、リフレクションAPI用に作成されていました。

編集:VoidのJavaDocから:「Voidクラスは、Javaキーワードvoidを表すClassオブジェクトへの参照を保持するインスタンス化できないプレースホルダークラスです。」Genericsが登場する前は、リフレクション以外の用途はありませんでした。


私はこれを信じていません。私の目の前には1.4以前のJVMがありませんが、Method.getReturnType()は常にvoidメソッドのvoid.classを返していると思います。
ルークウッドワード

@Pour:ジェネリックスの前に私が知っている唯一の使用法は、voidメソッドのリフレクションのMethod.getReturnType()で使用されたTYPE(Void.TYPEのように)を保持することだけであることを言っています。
Lawrence Dol 2010

なんとか戻らないVoidstackoverflow.com/questions/34248693/を

3

Voidをインスタンス化できないため、Apache commons Nullオブジェクトを使用できます。

Null aNullObject = ObjectUtils.Null;
Null noObjectHere = null;

1行目にはオブジェクトがあるためaNullObject != null保持されますが、2行目には参照がないためnoObjectHere == null保持されます

投稿者の元の質問に答えるために、これの使用法は、まったく異なるものである「なし」と「なし」を区別することです。

PS:Nullオブジェクトパターンにノーと言います


1

Voidは、そのプリミティブなvoid型をラップするために作成されます。すべてのプリミティブ型には、対応する参照型があります。Voidは、ジェネリッククラスまたはジェネリックメソッドの使用をインスタンス化するために使用されます。興味のないジェネリック引数の魔女です。ここに例があります...

public void onNewRegistration() {
    newRegistrationService.createNewUser(view.getUsername(), view.getPassword(),
            view.getInitialAmount(), view.getCurrency(), new AsyncCallback<Void>() {
      @Override
      public void onFailure(Throwable caught) {

      }

      @Override
      public void onSuccess(Void result) {
        eventBus.fireEvent(new NewRegistrationSuccessEvent());
      }
    });
  } 

ここでわかるように、新しい登録を作成するように求めているサーバーには何も必要ありませんpublic interface AsyncCallback<T> { .... }が、ジェネリックインターフェイスなので、ジェネリックはプリミティブ型を受け入れないため、Voidを提供しています


0

また、Attachmentオブジェクトが不要な場合、Async-IO完了コールバックでも一般的に使用されます。その場合、IO操作にnullを指定して実装しCompletionHandler<Integer,Void>ます。


0

まれなケースかもしれませんが、一度Voidアスペクトクラスで使用しました。

これは、@Logアノテーションを持つメソッドの後に実行され、返されたメソッドと、メソッドの戻り値の型がvoidでない場合はいくつかの情報をログに記録する側面でした。

 @AfterReturning(value = "@annotation(log)", 
       returning = "returnValue", 
       argNames = "joinPoint, log, returnValue"
      )
    public void afterReturning(final JoinPoint joinPoint, final Log log,
            final Object returnValue) {

            Class<?> returnType = ((MethodSignature) joinPoint.getSignature())
            .getReturnType();
           if (Void.class.isAssignableFrom (returnType)) ) {
            //Do some log
         }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.