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

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

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

Existem outros usos para o tipo de referência do Java Void ? Pode ser atribuído algo diferente de null ? Se sim, você tem exemplos?

Void tornou-se uma convenção para um argumento genérico no qual você não está interessado. Não há razão para usar outro tipo não instanciável, como o System .

Ele também é frequentemente usado em, por exemplo, valores de Map (embora Collections.newSetFromMap use Boolean pois os mapas não precisam aceitar valores null ) e java.security.PrivilegedAction .

Eu escrevi uma input de blog no Void há alguns anos atrás.

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

 Constructor 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 

Future funciona como charme. 🙂

Dado que não existem construtores públicos , eu diria que não pode ser atribuído nada além de null . Eu usei-o apenas como um marcador para “Não preciso usar esse parâmetro genérico”, como mostra o exemplo.

Também poderia ser usado em reflection, do que seu Javadoc diz:

A class Void é uma class de espaço reservado não instanciável para manter uma referência ao object Class que representa a palavra-chave Java void.

Todas as classs de wrapper primitivas ( Integer , Byte , Boolean , Double , etc.) contêm uma referência à class primitiva correspondente em um campo TYPE estático, por exemplo:

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

Void foi criado inicialmente como um lugar para colocar uma referência ao tipo de void :

 Void.TYPE == void.class 

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

Como um aparte, a última vez que tentei, o BeanShell não reconheceu o void.class , então você tem que usar o Void.TYPE lá.

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

Exemplo

 public interface LeavesVisitor { OUT visit(Leaf1 leaf); OUT visit(Leaf2 leaf); } 

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

 public class MyVoidVisitor implements LeavesVisitor { 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; } } 

Antes dos genéricos, ele foi criado para a API de reflection, para manter o TYPE retornado por Method.getReturnType () para um método void, correspondente às outras classs de tipo primitivo.

EDIT: Do JavaDoc do Void: “A class Void é uma class de espaço reservado não instanciável para manter uma referência ao object Class representando a palavra-chave Java void”. Antes de Generics, estou ciente de nenhum outro uso além de reflection.

O vazio é criado para envolver seu tipo de vazio primitivo. Cada tipo primitivo tem seu tipo de referência correspondente. Vazio é usado para instanciar uma class genérica ou o uso de um método genérico, um argumento genérico sobre o qual 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() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(Void result) { eventBus.fireEvent(new NewRegistrationSuccessEvent()); } }); } 

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

Como você não pode instanciar o Void, você pode usar objects nulos do Apache commons , então

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

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

Para responder à pergunta original do autor, o uso para isso é diferenciar entre “o nada” e “nada”, que são coisas completamente diferentes.

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

Ele também é comumente usado em retornos de chamada de conclusão do Async-IO quando você não precisa do object Attachment . Nesse caso, você especifica null para a operação de E / S e implementa o CompletionHandler .

Pode ser um caso raro, mas uma vez, usei o Void em classs de aspecto.

Este foi um aspecto que é executado após methods que possuem uma anotação @Log , 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 } }