Використовує тип опосередкування Java Void?


163

Існує типVoid V - верхнього регістру Java . Єдина ситуація, яку я коли-небудь бачив, - це параметризувати s Callable

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

Чи є якісь інші види використання для Voidпосилального типу Java ? Чи може коли-небудь присвоїти що-небудь, крім null? Якщо так, чи є у вас приклади?



Відповіді:


116

Voidстала умовою для загального аргументу, який вас не цікавить. Немає жодної причини, щоб вам слід було використовувати будь-який інший ненаданий тип, наприклад System.

Він також часто використовується, наприклад, у Mapзначеннях (хоча Collections.newSetFromMapвикористання Booleanяк карт не має приймати nullзначення) та java.security.PrivilegedAction.

Я написав запис розділу на Voidкілька років назад.


хто склав цю конвенцію? Документи стан docs.oracle.com/javase/tutorial/java/generics/types.html «Тип параметри угоди про іменах За угодою, імена параметрів типу поодинокі, прописні букв."
барлоп

4
@barlop Це аргумент не назва параметра. Тобто це тип java.lang.Void. / Джош Блок популяризував конвенцію, хоча колись ви її побачили, це очевидний вибір.
Том Хотін - тайклін

2
Цей запис у блозі мертвий
mFeinstein

51

Ви можете створити екземпляр 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 для присвоєння ідентифікації класу, який, згідно з документацією, є незрозумілим. Я теж це зробив, і я погоджуюся з тим, що спостережувані порожнечі марні.
Люк Вудвард

1
Конструктор <Void> cv = Void.class.getDeclaredConstructor (); cv.setAccessible (правда); Void v = cv.newInstance (); System.out.println (v); //;)
Пітер Лорі

Як вправу спробуйте створити новий Клас за допомогою роздумів і подивіться, що відбувається.
Пітер Лорі

Я отримав java.lang.InstantiationException від sun.reflect.InstantiationExceptionConstructorAccessorImpl. :(
Люк Вудвард

7
Це специфічне для впровадження та може змінитися в будь-який час. Немає гарантії, що клас має конструктор без аргументів, і навіть якщо він має такий, який може робити що-небудь (можливо System.exit(0)). Я схильний писати утилітні класи з конструктором як private Void() { throw new Error(); }. Деякі можуть віддати перевагу безцінному перерахунку.
Том Хотін - тайклін

27

Future<Void>працює як шарм. :)


6
Future<?>Частіше (наприклад, у Guava) використовувати , оскільки майбутнє часто матиме законне значення (нетипового Void), але використовується в контексті, який не хвилює значення.
Девід Філліпс

1
CompletableFuture<Void>також працює як шарм.
andrybak

19

Зважаючи на те, що громадських конструкторів немає , я б сказав, що це не може бути призначено, крім іншого null. Я використовував його лише як заповнювач для "мені не потрібно використовувати цей загальний параметр", як показує ваш приклад.

Він також може бути використаний для роздумів з того, що говорить його Javadoc :

Клас Void - це невідповідний клас заповнення місця, який містить посилання на об’єкт Class, що представляє ключове слово Java void.


Досить смішно бачити, як Oracle / Sun описує його таким чином, як null - це екземпляр усіх типів. Так чи інакше, як ви сказали, чистий сенс цього полягає в тому, що "я міг би написати тут будь-який тип, оскільки мені це не цікаво, тому я поставив би антену, щоб переконатися, що люди, які читають мій код, точно розуміють це"
Snicolas

17

Все примітивні класи обгортки ( Integer, Byte, Boolean, Doubleі т.д.) містять посилання на відповідному примітивний клас в статичному TYPEполі, наприклад:

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

VoidСпочатку було створено як десь, щоб поставити посилання на voidтип:

Void.TYPE == void.class

Однак ви нічого не отримуєте, використовуючи Void.TYPE. Під час використання void.classнабагато зрозуміліше, що ти щось робиш із voidтипом.

Що стосується останнього разу, коли я його спробував, BeanShell не впізнав void.class, тому вам доведеться Void.TYPEтам користуватися.


8
Отже, існує і Void.class, і void.class!
Том Андерсон

8

Коли ви використовуєте шаблон відвідувача, можна очистити використання Void замість Object, коли ви хочете бути впевненим, що значення, що повертається, буде нульовим

Приклад

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

   OUT visit(Leaf2 leaf);
}

Коли ви реалізуєте свого відвідувача, ви можете явно встановити, що OUT є недійсним, так що ви знаєте, що ваш відвідувач завжди поверне нуль, а не використовувати Object

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

Перед дженериками було створено для API відображення, щоб утримувати TYPE, повернутий Method.getReturnType () для методу void, відповідного іншим примітивним класам типів.

EDIT: Від JavaDoc of Void: "Клас Void - це невідповідний клас заповнення місця, який містить посилання на об'єкт Class, що представляє ключове слово Java void". До Generic я знаю, що немає нічого іншого, крім рефлексії.


Я не вірю в це. У мене зараз немає JVM 1.4 або раніше, але я вважаю, що Method.getReturnType () завжди повертав void.class для методу void.
Люк Вудвард

@Pour: Я кажу, що перед дженериками я знаю єдине використання, яке я маю TIPE (як у Void.TYPE), яке було використано у Method.getReturnType () для відображення методу недійсності.
Лоуренс Дол

Це якось не повертається Void. Будь ласка , дивіться stackoverflow.com/questions/34248693 / ...
Реза Фаттах

3

Оскільки ви не можете створити ідентифікатор Void, ви можете використовувати Apache commons Null object , так

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

у першому рядку у вас є об'єкт, тож aNullObject != nullутримується, а у другому рядку немає посилання, тому noObjectHere == nullтримається

Щоб відповісти на оригінальне запитання плаката, використання для цього полягає у розмежуванні "нічого" та "нічого", які є абсолютно різними речами.

PS: Скажіть "Нет" об'єкта "Null"


1

Пустота - це створити, щоб обернути свій примітивний тип порожнечі. Кожен примітивний тип має відповідний тип довідки. Пустота використовується для створення загального класу або використання загального методу. Загальні аргументи, які вас не цікавлять. Ось приклад ...

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> { .... }це загальний інтерфейс, тому я надаю недійсність, оскільки generics не приймає примітивні типи


0

Він також часто використовується для зворотних викликів завершення Async-IO, коли у вас немає потреби в Attachmentоб'єкті. У цьому випадку ви вказуєте нульове значення для операції вводу-виводу та реалізації CompletionHandler<Integer,Void>.


0

Це може бути рідкісний випадок, але колись я використовувався Voidв аспектних класах.

Це був аспект, який працює після методів, що мають @Logанотацію, і записує метод повернутого методу та деяку інформацію, якщо тип повернення методу недійсний.

 @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
         }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.