В чем разница между Void и отсутствием параметра?

У меня есть класс, который определяет два перегруженных метода

public void handle(Void e) 

protected void handle() 

Очевидно, они разные, особенно handle(Void e) это public.


В чем разница между этими двумя?

Как вызвать первый метод? Я использую handle(null) - это правильно?


person Adam Lee    schedule 25.12.2012    source источник
comment
На основе параметра и доступа, который вы можете вызвать, если handle(), он вызовет второй метод и handle(null) или handle(null), он вызовет первый   -  person Vinit Prajapati    schedule 25.12.2012
comment
@VinitPrajapati.. Вы не можете создать экземпляр Void   -  person Rohit Jain    schedule 25.12.2012
comment
@RohitJain Исправлен комментарий   -  person Vinit Prajapati    schedule 25.12.2012
comment
это другое я думаю   -  person Adam Lee    schedule 25.12.2012
comment
да это правильно. вы можете вызвать public void handle(Void e) только с помощью вызова handle(null)   -  person M. Atif Riaz    schedule 25.12.2012


Ответы (4)


Первая функция — это функция одного аргумента, который должен быть предоставлен и может принимать только допустимое значение null. Любое значение, отличное от null, не будет компилироваться. Вторая функция не принимает никаких аргументов, и передача ей null не будет компилироваться.

person Confusion    schedule 25.12.2012
comment
есть ли цель использовать Void в качестве параметра? - person Adam Lee; 25.12.2012
comment
Нет, как говорит Богемиан, он существует для того, чтобы иметь возможность представлять возвращаемое значение метода void для целей отражения. - person Confusion; 25.12.2012
comment
Итак, каков конкретный вариант использования параметра Void функции? - person Emre Tapcı; 13.09.2019

Void — это специальный класс, обычно используемый только для отражения. Его основное назначение — представлять возвращаемый тип метода void. Из javadoc для Void:

Класс Void — это нереальный класс-заполнитель для хранения ссылки на объект Class, представляющий ключевое слово Java void.

Поскольку класс Void не может быть создан, единственным значением, которое вы можете передать методу с параметром типа Void, например handle(Void e), является null.


Это официальная версия событий, но для тех, кто заинтересован, несмотря на заявления об обратном в javadoc Void, вы можете фактически создать экземпляр Void:

Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance(); // Hello sailor!


Тем не менее, я видел, что Void "полезно" используется в качестве универсального типа параметра, когда вы хотите указать, что тип "игнорируется", например:

Callable<Void> ignoreResult = new Callable<Void> () {
    public Void call() throws Exception {
        // do something
        return null; // only possible value for a Void type
    }
}

Общий параметр Callable является возвращаемым типом, поэтому когда Void используется таким образом, это четкий сигнал читателям кода о том, что возвращаемое значение не важно, даже если требуется использование интерфейса Callable, например, при использовании Executor фреймворк.

person Bohemian♦    schedule 25.12.2012
comment
Это не означает, что меня не волнует тип, это означает, что я не хочу ничего возвращать, но дженерики не поддерживают void, поскольку это не класс, поэтому вместо этого я использую Void. - person josefx; 25.12.2012
comment
+1 Я считаю, что вы можете создать экземпляр Void с помощью Reflection. - person Eng.Fouad; 25.12.2012
comment
@ Адам, это может показаться странным запросом, но не мог бы ты, Минг, принять другой ответ? Причина в том, что я получу специальную шляпу, если один из моих ответов превзойдет принятый. Это был бы хороший рождественский подарок :) - Спасибо - person Bohemian♦; 26.12.2012
comment
@ Адам, это должно было быть умом, а не Мингом :) Вот тебе и крапнология автокоррекции iPhone... :/ - person Bohemian♦; 26.12.2012
comment
Я использовал Void, возможно, нетрадиционно, для разрешения конфликтов при расширении методов с большим количеством параметров (не спрашивайте, почему). Если methodA(String) нужно расширить до methodA(String, String), но methodA(String, String) уже существует с другим значением, я бы расширил первый метод как methodA(String, Void, String) (и назвал бы его methodA(strA, (Void)null, strB)). Конечно, я могу сделать это methodB(String, String), но иногда нет. (Опять же, не спрашивайте, почему!) - person ADTC; 23.07.2014
comment
@ADTC Я бы просто сделал это methodB(String, String) - person Bohemian♦; 23.07.2014
comment
Я бы тоже, но иногда не могу. Не спрашивайте, почему. :/ (Преимущества работы с большими корпоративными системами.) - person ADTC; 23.07.2014
comment
Полезный ответ. Хотя в начале ответа вы говорите, что обычно используется только для размышлений, а затем вы говорите, что полезно использовать в качестве общего типа параметра. Я также видел это последнее использование - разве это не противоречит тому, что вы сказали ранее о том, что оно используется только для размышлений (хотя и определяется как обычно)? - person flow2k; 24.10.2017

Рассмотрим API для AsyncTask<T1, T2, T3> из системы Android, который предоставляет три крючка:

class AsyncTask<S, T, V> {
  void doInBackground(S...);
  void onProgressUpdate(T...);
  void onPostExecute(V);
}

Когда вы расширяете общий тип AsyncTask<T1, T2, T3>, вам может не понадобиться использовать параметры для хуков progress и result, поэтому ваша реализация будет выглядеть так:

class HTTPDownloader extends AsyncTask<URL, Void, Void> {
  void doInBackground(URL... urls) {}
  void onProgressUpdate(Void... unused) {}
  void onPostExecute(Void unused) {}
}

и вы можете вызывать эти методы с параметром null, поскольку Void не может быть создан.

person Raffaele    schedule 25.12.2012
comment
Void ... необходим для сохранения количества аргументов, поэтому onProgressUpdate правильно переопределяет тот же метод в родительском (поскольку в java отсутствие передачи аргумента в this приведет к тому, что он станет новой функцией, а не переопределением). - person Zags; 29.10.2014

Если Void на самом деле не является экземпляром параметра типа (где это, очевидно, имеет смысл), также имеет смысл объявить handle(Void), если ваш метод handle подчиняется экстралингвистическому контракту, в котором говорится, что объект, который хочет участвовать в определенном протокол должен реализовать метод дескриптора с одним аргументом, независимо от фактического типа аргумента. Теперь может быть реализация для особого случая, которая не может обрабатывать ничего, кроме null, поэтому имеет смысл объявить handle(Void) для такой реализации.

person Marko Topolnik    schedule 25.12.2012