Как множественные значения возвращаются в Java?


11

Иногда вы хотите вернуть несколько значений из функции. Как это обычно делается в Java?

Один из вариантов - использовать массив, например, этот фрагмент Python, который возвращает список или кортеж:

value, success = read_unreliably()
if success:
    print value

Другой вариант - вернуть хеш / dict, как в следующем примере JavaScript:

var result = readUnreliably()
if (result.success) {
    alert(value);
}

Еще один - создать пользовательский объект именно для этой цели, например, в следующем примере Java:

ReadUnreliablyResult result = readUnreliably()
if (result.getSuccess()) {
    System.out.println(result.getValue());
}

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


Действительно ли "настоящие" Java-люди сталкиваются с проблемой использования публичных методов получения и установки, чтобы скрыть поля в таких маленьких внутренних классах? Просто любопытно.
Крис Фармер

3
Да, большинство делает. Поскольку многие фреймворки ожидают стандарт JavaBean, вы можете сожалеть об отсутствии геттеров и сеттеров. В любом случае ваша IDE сгенерирует их для вас.
Эрик Уилсон

3
Или вы можете просто оставить их, основываясь на принципе ЯГНИ. Но это не так часто, как можно было бы ожидать.
MatrixFrog

@FarmBoy: Полагаю, я понимаю, что такое bean-компоненты и тому подобное, но OP подразумевает, что это просто одноразовый класс, предназначенный для возврата нескольких значений.
Крис Фармер

@ChrisFarmer Я думаю, что в этом контексте я никогда не видел, чтобы «настоящий» программист на Java создавал класс для этой цели.
Эрик Уилсон

Ответы:


26

Как это обычно делается в Java?

Больно.

Один из вариантов - использовать массив, например, этот фрагмент Python, который возвращает список или кортеж ...

Другой вариант - вернуть хеш / dict, как в этом примере JavaScript ...

Эти методы не работают в Java; значения должны быть понижены от объекта.

Еще один - создать пользовательский объект именно для этой цели, как в примере с Java ...

Это наиболее часто, но создавать все эти маленькие классы утомительно. В C ++ обычно используется std :: pair, но в Java это обычно не делается.

С Lombok довольно легко создавать небольшие пользовательские объекты:

@RequiredArgsConstructor
public class X {
  private final boolean status;
  private final byte[] data;

}


10
"Как это обычно делается в Java?" «Больно» . LOL, как разработчик Java, я должен +1 вам за это
TheLQ

Использование компактного неизменяемого структурно-подобного класса не так уж больно ... Это действительно похоже на написание структуры C ...
Гийом

1
@Guillaume - конечно, но все эти мелочи складываются во времени и пространстве. Я не знаю, почему сообщество Java не приняло стандартный набор обобщений, таких как "class Pair <T1, T2> {public T1 first; public T2 second; ...}"; в современных языках вы просто «вернуть a, b»; и затем напишите «x, y = f ()»;
Кевин Клайн

1
Я уверен, что некоторые «древние» языки тоже могут это делать :) ИМХО Я обнаружил, что множественные возвращаемые значения могут привести к полному беспорядку, и если вам нужно добавить другие возвращаемые поля, вам просто нужно обновить свою структуру как класс без измените подпись вашего метода.
Гийом

1
Что "больно". меня сильно поразило, да, это именно то, что я чувствую как разработчик Java, когда сталкиваюсь с подобными ситуациями.
artjom

13

Да, так , чтобы создать struct/ tuple/ recordв Java является создание класса. Если это только для внутреннего использования, я предпочитаю использовать небольшой неизменяемый структурный класс с открытыми полями.

Примеры:

public class Unreliably {
    public final boolean success;
    public final int value;
    public Unreliably(boolean success, int value) {
        this.success = success; this.value = value;
    }
}

Это гораздо проще сделать в Scala:

case class Unreliably(success: Boolean, value: Int)

8
На самом деле, в Scala вы, скорее всего, просто вернете a Tuple2[Boolean, Int]. Хотя в этом конкретном примере вы бы вернули Option[Int].
Йорг Миттаг

2
Таким образом, это отвечает на вопрос Криса Фармера (в комментариях Q), что настоящие Java-люди не обязательно создают геттеры и сеттеры для маленьких внутренних классов. Вы "настоящий" Java-человек, верно?
Майк М. Лин

2
В других новостях нет настоящих шотландцев.
Джозеф Вайсман

5

Для примера, который вы привели, выдача исключения будет самым стандартным способом его обработки:

try {
    result = readUnreliably();
    System.out.println(result);
} (catch IOException e) {
    System.out.println("Could not read file");
}

Более того, если вы стремитесь иметь функции, которые «делают одно», функция возврата нескольких значений становится менее необходимой, хотя иногда и удобной.


4

У нас есть универсальный класс Pair, который может хранить один экземпляр A и один экземпляр B. Вероятно, вы можете создать Triplet или Quadruplet таким же образом.

public class Pair<A, B>
{
    ...
}

1
это делает для некоторого ДЕЙСТВИТЕЛЬНО нечитаемого кода все же. если метод возвращает Pair<String, Integer>, что это значит? что представляют эти значения? Вы не можете знать, не читая реализацию метода.
Сара

1

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


1

В Java нет явного способа вернуть несколько переменных, однако есть несколько подходов:

  1. Во-первых, идти по пути массива. Это действительно работает, только если у вас все данные одного типа или вы можете временно преобразовать их в один тип.
  2. Второй способ - создать класс с целью передачи нескольких типов переменных. В моей работе мы называем их DTO или объектами передачи данных.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.