Usos para o tipo de referência do Java Void?


163

Existe um tipo de referência Java Void- V maiúsculo . A única situação que eu já vi usada é parametrizar s Callable

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

Existem outros usos para o Voidtipo de referência Java ? Pode ser atribuído algo além de null? Se sim, você tem exemplos?



Respostas:


116

Voidtornou-se uma convenção para um argumento genérico no qual você não está interessado. Não há motivo para usar qualquer outro tipo não instável, como System.

Também é frequentemente usado em por exemplo Mapvalores (embora os Collections.newSetFromMapusos Booleancomo mapas não precisem aceitar nullvalores) e java.security.PrivilegedAction.

Eu escrevi um post do blog em Voidalguns anos atrás.


quem fez essa convenção? docs state docs.oracle.com/javase/tutorial/java/generics/types.html "Convenções de nomenclatura de parâmetro de tipo Por convenção, os nomes de parâmetro de tipo são letras maiúsculas e únicas".
barlop

4
@ barlop É o argumento, não o nome do parâmetro. Ou seja, é o tipo java.lang.Void. / Josh Bloch popularizou a convenção, embora uma vez que você a tenha visto, seja a escolha óbvia.
Tom Hawtin - defina

2
Essa entrada do blog está morta
mFeinstein 17/10

51

Você pode criar uma instância do Void usando reflexos, mas eles não são úteis para nada. Vazio é uma maneira de indicar que um método genérico não retorna nada.

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

imprime algo como

I have a java.lang.Void@75636731

22
+1 para instanciar uma classe que a documentação diz ser instável. Também fiz isso e concordo que os vazios instanciados são inúteis.
22420 Luke Woodward

1
Construtor <Void> cv = Void.class.getDeclaredConstructor (); cv.setAccessible (true); Vazio v = cv.newInstance (); System.out.println (v); //;)
Peter Lawrey 14/03/2009

Como exercício, tente criar uma nova classe usando reflexões e veja o que acontece.
31540 Peter Lawrey

Eu recebi um java.lang.InstantiationException de sun.reflect.InstantiationExceptionConstructorAccessorImpl. :(
Luke Woodward

7
Isso é específico da implementação e pode mudar a qualquer momento. Não há garantia de que a classe tenha um construtor sem argumento e mesmo que tenha um que possa fazer alguma coisa (talvez System.exit(0)). Eu costumo escrever classes de utilidade com um construtor como private Void() { throw new Error(); }. Alguns podem preferir uma enumeração sem valor.
Tom Hawtin - defina


19

Dado que não há construtores públicos , eu diria que não pode ser atribuído nada além de null. Eu apenas o usei como espaço reservado para "Não preciso usar esse parâmetro genérico", como mostra seu exemplo.

Também poderia ser usado na reflexão, pelo que diz o Javadoc :

A classe Void é uma classe de espaço reservado instável para manter uma referência ao objeto Class que representa a palavra-chave Java void.


Engraçado o suficiente para ver o Oracle / Sun descrevê-lo dessa maneira, pois null é uma instância de todos os tipos. De qualquer forma, como você disse, o significado puro é "Eu poderia escrever qualquer tipo aqui, pois não estou interessado nela, então colocarei o Void para garantir que as pessoas que leem meu código entendam exatamente isso"
Snicolas

17

Todos os classe empacotadora ( Integer, Byte, Boolean, Double, etc.) conter uma referência para a classe correspondente primitiva em um estático TYPEcampo, por exemplo:

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

Voidfoi criado inicialmente como um local para colocar uma referência ao voidtipo:

Void.TYPE == void.class

No entanto, você realmente não ganha nada usando Void.TYPE. Quando você usa void.class, é muito mais claro que você está fazendo algo com o voidtipo.

Como um aparte, a última vez que tentei, o BeanShell não reconheceu void.class, então você precisa usá Void.TYPE-lo.


8
Portanto, há uma classe Void.class e uma void.class!
Tom Anderson

8

Quando você usa o padrão de visitante , pode ser mais limpo usar Void, em vez de Object, quando quiser ter certeza de que o valor de retorno será nulo.

Exemplo

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

   OUT visit(Leaf2 leaf);
}

Quando você implementa seu visitante, pode explicitamente definir OUT como nulo, para que saiba que seu visitante sempre retornará nulo, em vez de usar Objeto

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

Antes dos genéricos, ele era criado para a API de reflexão, para manter TYPE retornado por Method.getReturnType () para um método nulo, correspondente às outras classes de tipos primitivos.

EDIT: No JavaDoc do Void: "A classe Void é uma classe de espaço reservado instável para manter uma referência ao objeto Class que representa a palavra-chave Java void". Antes da Genéricos, não tenho outra utilidade além da reflexão.


Eu não acredito nisso. Não tenho uma JVM 1.4 ou anterior agora, mas acredito que Method.getReturnType () sempre retornou void.class para um método void.
22420 Luke Woodward

@Pour: estou dizendo que, antes dos genéricos, o único uso que tenho conhecimento é manter TYPE (como no Void.TYPE), que foi usado no Method.getReturnType () da reflexão para um método nulo.
Lawrence Dol

De alguma forma, não retorna Void. Veja stackoverflow.com/questions/34248693/…
Alireza Fattahi

3

Como você não pode instanciar o Void, você pode usar o objeto nulo do Apache commons , então

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

na primeira linha, você tem um objeto, então aNullObject != nullmantém, enquanto na segunda linha não há referência, então noObjectHere == nullmantém

Para responder à pergunta original do pôster, o uso para isso é diferenciar entre "o nada" e "nada", que são coisas completamente diferentes.

PS: Diga não ao padrão de objeto nulo


1

Vazio é criar para quebrar seu tipo de vazio primitivo. Todo tipo primitivo tem seu tipo de referência correspondente. O void é usado para instanciar uma classe genérica ou o uso de um método genérico. Argumentos genéricos nos quais você não está interessado. E aqui está um exemplo ...

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());
      }
    });
  } 

aqui, como você pode ver, não quero nada do servidor que estou pedindo para criar um novo registro, mas public interface AsyncCallback<T> { .... }é uma interface genérica, então forneço o Void, pois os genéricos não aceitam tipos primitivos


0

Também é comumente usado em retornos de chamada de conclusão de Async-IO quando você não precisa de um Attachmentobjeto. Nesse caso, você especifique nulo para a operação IO e implementar CompletionHandler<Integer,Void>.


0

Pode ser um caso raro, mas uma vez eu usei Voidnas classes de aspecto.

Esse era um aspecto que é executado após os métodos que possuem uma @Loganotação e registra o método retornado e algumas informações se o tipo de retorno do método não for nulo.

 @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
         }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.