Может ли одна функция Java возвращать два типа в разных условиях? - PullRequest
1 голос
/ 14 сентября 2011
public String[] getValue(String keyName) {

    ArrayList arraylist = (ArrayList) value.get(getKey(keyName));

    String[] valueArray = new String[arraylist.size()];

    for (int i = 0; i < valueArray.length; i++)
        valueArray[i] = arraylist.get(i).toString();

    return valueArray;
}

Я хочу изменить эту функцию, чтобы упростить ее использование. Если возвращаемый массив String содержит только один элемент. Я хочу, чтобы он возвращался в типе String (не String).

Как я могу сделать это на Java?

Ответы [ 3 ]

10 голосов
/ 14 сентября 2011

Хорошо, вы можете объявить, что метод возвращает Object вместо String[] ... но это делает его сложнее использовать, а не проще.

  • Вы не можете объявить, что метод может возвращать тип X или тип Y, если только X или Y не является супертипом другого (в этом случае могут быть возвращены и другие подтипы)
  • Вы не можете объявить два метода, которые отличаются только типом возврата

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

Конечно, вы всегда можете создать свой собственный интерфейс OneOrMany, который включает в себя общие операции и может иметь либо один элемент, либо несколько ... но, опять же, я не вижу преимущества. (Я могу увидеть преимущество в возвращении List<String> или Iterable<String> вместо массива.)

РЕДАКТИРОВАТЬ: увидев ваш комментарий к ответу Дилума, в ситуации, когда у вызывающей стороны есть ожидание одного элемента, я бы либо создал вспомогательные методы, которые позволяли бы выражать это для коллекций, либо просто два метода:

public Collection<String> getValues()
{
    ...
}

public String getSingleValue()
{
    // Throws an exception if there's more than one
}

Последний может либо идти по первому методу, либо потенциально может быть оптимизирован для случая ожидания (и проверки) одного результата.

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

Я бы, наверное, не ввел бы новый интерфейс, поскольку это означало бы, что мне придется либо обернуть существующие классы коллекций, либо создать их подкласс (argh). В C # это просто, так как вы можете просто использовать метод расширения Single() (наряду с SingleOrDefault, FirstOrDefault и т. Д.) ...

5 голосов
/ 14 сентября 2011

Нет.

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

XXX foo = getValue(keyName);
^^^
What goes here?
3 голосов
/ 14 сентября 2011

Проект, над которым я работал, должен был иметь дело с чем-то похожим.Были некоторые похожие на карту объекты.Каждый ключ имел ноль или более значений.Но были некоторые ключи, где мы знали, что есть только одно значение.У других был максимум один.У других было ноль или более.

Мы решили это, введя расширение для Collection:

public class CardinalityException extends RuntimeException {
  ...
}

public interface Values<T> extends Collection<T> {

  /**
   * @return the equivalent of iterator().next() if size() == 1
   * @throws CardinalityException if collection is empty 
   *         or contains more than one element.
   */
  T unique() throws CardinalityException;

  /**
   * @return one element from the collection, or null if empty
   */
  T one();
}

Итак, по сути, мы всегда возвращали Values<T>.Если бы вызывающая сторона знала, что было только одно значение, она просто использовала бы unique() или one() в зависимости от того, не было ли значение допустимым.

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

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