Загальні типи Java для типів void / Void


79

Я реалізую ResponseHandlerдля пакету apache HttpClient, ось так:

new ResponseHandler<int>() {
    public int handleResponse(...) {
        // ... code ...
        return 0;
    }
}

але я хотів би, щоб handleResponseфункція нічого не повертала, тобто void. Чи можливо це? Далі не компілюється, оскільки voidне є дійсним типом Java:

new ResponseHandler<void>() {
        public void handleResponse(...) {
            // ... code ...
        }
}

Я думаю, я міг би замінити voidна, Voidщоб повернути Voidоб'єкт, але це насправді не те, що я хочу. Питання : чи можна організувати цю ситуацію зворотного дзвінка таким чином, щоб я міг повернутися voidз неї handleResponse?

Відповіді:


65

Дженерики обробляють лише об’єктні класи. void та примітивні типи не підтримуються Generics, і ви не можете використовувати їх як параметризований тип. Натомість вам слід використовувати Void.

Чи можете ви сказати, чому ви не хочете використовувати Void?


8
я б просто вважав за краще не включати returnтвердження у функцію, де я нічого не повертаю, в основному для чистоти.
Тревіс Вебб,

8
Ви можете створити абстрактну обгортку, яка викликає вам voidметод і повертається, nullщоб приховати цю потворність.
Пітер Лорі

47
+1 за нагадування, що "будь-яку проблему в галузі інформатики можна вирішити, додавши рівень опосередкованості"
Тревіс Вебб,

@TravisWebb Дивлячись на ваші конкретні потреби, просто не використовуйте генерики взагалі і повертайте Objectтип, якщо це спрацює
Чайтанья

87

VoidТип був створений для цієї конкретної ситуації: створити метод із загальним типом повертається значення, де підтип може бути «порожнеча». Voidбув розроблений таким чином, що жодні об’єкти такого типу не можуть бути створені. Таким чином, метод типу Voidзавжди повертається null(або завершується ненормально), який майже ні до чого не схожий, як ви збираєтеся отримати. Вам доведеться застосувати return nullметод, але це має бути лише незначною незручністю.

Коротше: використовуйте Void.


Arrgh - проблема загальних проблем полягає в тому, що, скажімо, ви визначаєте тип повернення "Void", який ви повинні ввести "return (null);" основною причиною оголосити тип повернення void є те, що вам не потрібно мати оператор return, і ви можете використовувати існуючий метод "void" :) Частина проблеми з Java Generics полягає в поєднанні перевірки типу часу виконання з необхідністю генерації часового коду компіляції та допомоги "ведення бухгалтерії". Потрібні "макроси" та "шаблони", які пропонують зручність у написанні коду на мовній стороні.
peterk

6
+1 Для уточнення, Void існує з JDK1.1. Спочатку він був створений для використання з Reflection, але має аналогічну роль у дженериках.
Джон Маккарті,

@ILMTitan Не могли б ви дати будь-які посилання на документацію щодо оператора "return null" у методах, визначених для повернення Void?
Андрій Симонов

@ andriy-simonov Методи з типом повернення voidне повинні повертати значення. Методи з типом повернення Objectабо будь-яким підкласом, наприклад Void, повинні повертати значення (або не заповнювати нормально). Єдиним значенням, якому можна призначити Voidі повернути його з Voidметоду, є null.
ILMTitan

8

Коли вам потрібно повернутися java.lang.Void, просто поверніться null.


1

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

Подумайте про це як: загальна функція говорить "ця функція повертає щось типу X", і ви можете вказати X, але ви не можете змінити речення на "ця функція нічого не повертає". (Я не впевнений, чи погоджуюсь я з цією семантикою, але вони такі.)

У цьому випадку я завжди роблю тип функції return Objectі фактично завжди повертаю null.


1
Оскільки з типом повернення Object компілятор не може гарантувати, що повертається лише null. Розширюючи відповідь Томаса, спробуйте static Void v() { return null; } static Void n() { return "NotAllowed"; } static Object o() { return "Allowed"; }
наступне

1

Ви не можете мати примітивів у дженериках, тож intце насправді є Integer. Об’єкт Voidаналогічний ключовому слову voidдля дженериків.


4
voidне є примітивним, це просто ключове слово Java. Він не має "типу"
Тревіс Вебб

і це, безумовно, не є синонімом! void(мала літера) - ключове слово, нічого не повернуто; Void(верхній регістр) - (необгрунтований) клас , екземпляр цього класу повертається (може бути лише nullз тих пір, як необгрунтований)
user85421,

@Carlos Heuberger аналогічний для вас кращий?
mark-cs

0

Ця реалізація java.lang.Void у Java начебто говорить сама за себе. Крім того, я написав статтю, яка пов’язує це із загальними засобами. Потрібно було трохи подумати, перш ніж я почав це розуміти: http://www.siteconsortium.com/h/D00006.php . Примітка TYPE = Class.getPrimitiveClass ("void");

пакет java.lang;

public final class Void {

    public static final Class<Void> TYPE = Class.getPrimitiveClass("void");

    private Void() {}
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.