повернення об'єкта Void


113

Який правильний спосіб повернути Voidтип, коли він не примітив? Напр. Зараз я використовую null, як показано нижче.

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something
        return null;
    }
}

1
Я пишу інтерпретатора для файлового формату, використовуючи шаблон інтерпретатора, але деякі вирази не мають зворотних значень
Роберт

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

так, це теж була моя логіка - просто задумався, чи є більш семантичний шлях
Роберт

1
Я б це кодував так само, як і ваш приклад. Це прекрасний підхід.
Девід Руссель

Відповіді:


134

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

Тому будь-якого з наступного було б достатньо:

  • параметризація з Objectі повернення new Object()абоnull
  • параметризація з Voidі поверненняnull
  • параметризація з NullObjectвашим

Ви не можете зробити цей метод void, і все інше щось повертає . Оскільки це щось ігнорується, ви можете повернути що завгодно.


2
то який загально правильний спосіб досягти зворотного типу порожнечі?
Роберт

1
Якщо ви хочете повернути null як недійсний, його потрібно видалити в деяких випадках: (Void) null
Patrick Favre

return (Void)null;
Alex R

можна (Void) null будь-яким чином відрізнити від null?
апельсин

13

Java 8 представила новий клас Optional<T>, який можна використовувати в таких випадках. Щоб скористатися ним, ви трохи змінили свій код наступним чином:

interface B<E>{ Optional<E> method(); }

class A implements B<Void>{

    public Optional<Void> method(){
        // do something
        return Optional.empty();
    }
}

Це дозволяє вам гарантувати, що ви завжди отримуєте від свого методу ненулеве значення повернення, навіть коли повернути нічого не можна. Це особливо потужно при використанні спільно з інструментами, які виявляють, коли nullможна чи не можна повернути, наприклад, Затемнення @NonNullта @Nullableпримітки.


5
Моя думка, що це йде в неправильному напрямку. Краще повернути набагато більш обмежений тип, який передає значення набагато чіткіше. Якщо щось повертає Optional<Void>непотрібне з тієї ж причини, яку ви надаєте, ви завжди отримуєте Optional<Void>порожнє, і тому всі інші методи безглузді. Це протилежне тому, чому слід використовувати необов'язкове значення. Ви використовуєте його, оскільки це може мати або не мати значення. Також компілятор не може примусити method()його правильно реалізувати. Це зазнає невдачі під час виконання: return Optional.of(null).
steinybot

3

Якщо вам просто нічого не потрібно як ваш тип, ви можете використовувати void. Це можна використовувати для реалізації функцій або дій. Потім ви можете зробити щось подібне:

interface Action<T> {
    public T execute();
}

abstract class VoidAction implements Action<Void> {
    public Void execute() {
        executeInternal();
        return null;
    }

    abstract void executeInternal();
}

Або ви можете опустити абстрактний клас і зробити нульове повернення в кожній дії, що не вимагає повернення значення самостійно.

Потім ви можете використовувати такі дії, як це:

Дано метод

private static <T> T executeAction(Action<T> action) {
    return action.execute();
}

ви можете назвати це як

String result = executeAction(new Action<String>() {
    @Override
    public String execute() {
        //code here
        return "Return me!";
    }
});

або для недійсних дій (зауважте, що ви не привласнюєте результат ні до чого)

executeAction(new VoidAction() {
    @Override
    public void executeInternal() {
        //code here
    }
});

2
чим це відрізняється від того, що я вже маю? він як і раніше повертається до нуля, як я запропонував
Роберт

Чому б вам довелося повертати щось інше? Справа, яку я намагаюся зробити, це те, що вам не потрібно значення повернення, тому не має значення, що ви повертаєте. Я спробував уточнити це своєю правою.
Jorn

1

Тільки заради цього, звичайно, є можливість створити Voidекземпляр за допомогою відображення:

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something

        try {
            Constructor<Void> voidConstructor = Void.class.getDeclaredConstructor();
            voidConstructor.setAccessible(true);
            return voidConstructor.newInstance();
        } catch (Exception ex) {
            // Rethrow, or return null, or whatever.
        }
    }
}

Ви, мабуть, цього не зробите на виробництві.


0

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

Я вважаю, що умовою є використання Object при успадкуванні як параметр типу

АБО

Поширте параметр типу вгору, а потім дозвольте користувачам вашого класу інстанціювати за допомогою Object та призначити об'єкт змінній, введеній за допомогою підстановки типу ?:

interface B<E>{ E method(); }

class A<T> implements B<T>{

    public T method(){
        // do something
        return null;
    }
}

A<?> a = new A<Object>();

1
це умова про встановлення типу повернення до анулювання з дженериками - це не виглядає дуже недійсно для мене?
Роберт

Я вважаю, що це шлях. Будь-який користувач класу A<?>не зможе використати повернене значення method().
Крістофер Йозбек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.