Возврат нескольких значений из метода Java: почему нет объектов из n кортежей?

Почему нет (стандартного, сертифицированного для Java) решения как части самого языка Java для возврата нескольких значений из метода Java вместо того, чтобы разработчикам приходилось использовать свои собственные средства, такие как карты, списки, пары и т. д. .? Почему Java не поддерживает объекты n-tuple?

Особенно мысли о тривиальных частных методах, которые могут изменять два объекта вместе (в тандеме), и в этом случае типизированный объект в качестве возврата звучит излишним.


person Saket    schedule 19.09.2011    source источник
comment
Хм...............? Использование таких структур данных является стандартом, не так ли?   -  person mrkhrts    schedule 19.09.2011
comment
Потому что, конечно же, никто не проделал работу, чтобы взять одно из этих нестандартных решений и стандартизировать его!   -  person Donal Fellows    schedule 19.09.2011
comment
Есть стандартный способ: это называется объект.   -  person toto2    schedule 19.09.2011
comment
да, это стандартная структура данных, но нет ли способов поместить ее как часть языковой конструкции, а не обернуть ее в коллекции? Простая аналогия, если позволите, заключается в том, что вы можете передать несколько аргументов методу двумя способами: (a). Иметь переменную с одним параметром, которая является списком‹?›, и извлекать из нее отдельные параметры или (b). иметь разные переменные параметров для каждого аргумента. Просто мысли вслух...   -  person Saket    schedule 19.09.2011
comment
То, что вы пытаетесь сделать, нестандартно. Стандартные подходы включают использование карт, списков или пользовательских объектов!   -  person adarshr    schedule 19.09.2011
comment
@adarshr - возможно, это звучит «нестандартно», потому что стандарта как такового пока не существует, что я и пытаюсь найти :) Опять же, я просто пытаюсь открыть дискуссию.   -  person Saket    schedule 19.09.2011
comment
Возможный дубликат stackoverflow.com/questions/457629/   -  person Raedwald    schedule 19.09.2011
comment
Я видел сообщение выше, в котором рассказывается о том, как это сделать. Но я пытаюсь открыть, зачем нужны такие средства.   -  person Saket    schedule 19.09.2011
comment
Я просто пытаюсь открыть дискуссию: обсуждение здесь не рекомендуется. См. stackoverflow.com/faq#dontask.   -  person Raedwald    schedule 19.09.2011
comment
@Raedwald - «обсуждение» ... не буквально :). Я пытаюсь (вместе с некоторыми другими) понять/изучить теорию, стоящую за этим.   -  person Saket    schedule 19.09.2011
comment
См. также: stackoverflow.com/questions/457775/does-java-need-tuples   -  person Raedwald    schedule 19.09.2011
comment
Возможно, java делает это, чтобы заставить вас использовать возвращаемые значения именованного стиля, поэтому нет путаницы в отношении того, что возвращается...   -  person rogerdpack    schedule 17.04.2013
comment
Другие языки делают это, используя синтаксис передачи по ссылке (или псевдопередачу по ссылке, например, используя & (оператор адреса) в C или C++. Именно так люди обходились в старые времена. Я пытаюсь решить, как это сделать для чего-то, и я могу выбрать частный статический класс, описанный ниже, в качестве выбранного ответа.   -  person titania424    schedule 09.10.2013
comment
Почему бы не создать свой собственный класс Tuple, как в этом вопросе?   -  person jk7    schedule 10.01.2018


Ответы (6)


Я предполагаю, что OP означает «Почему Java не поддерживает объекты с n кортежами?». Python, Haskell, Lisp, ML и т. д. имеют разнородные возможности n-кортежей. Также часто способность явно возвращать несколько объектов в языке является синтаксическим сахаром (например, в python возвращаются «a», «b»).

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

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

ИМХО, хотя это раздражает, я часто борюсь с этой проблемой, создавая статические встроенные классы:

private static class Combo {
   String name;
   int weight;
}

Да, это утомительно, но позже я часто повторно использую и реорганизую эти классы, делая их высшего уровня и добавляя поведение. На самом деле, одно из преимуществ этого пути заключается в том, что гораздо проще добавлять новые поля там, где есть анонимная структура данных (например, в языках FP), становится намного сложнее добавить поле (в конечном итоге вы изменяете тонну кода).

Я должен отметить, что для 2-кортежей некоторые люди используют (или злоупотребляют) java.util.Map.Entry, поскольку в Java 6 есть java.util.AbstractMap.SimpleEntry. Также некоторые люди теперь используют Поддержка пар Commons Lang3 (2-tuple).

Scala имеет поддержку n-кортежей своего рода читерством и имеет целую кучу интерфейсов из 2-16 кортежей, которые являются стандартными для языка и синтаксически скрыты от программиста.

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

ОБНОВЛЕНИЕ: для Java 8

Java 8 будет/возможно (так что вот мой номер... позвоните мне, возможно) будет поддерживать интерфейс с именем java.lang.BiValue с конкретной реализацией, которую вы можете использовать, с именем java.lang.BiVal . Эти классы должны помочь поддерживать новую функциональность лямбда. Но обратите внимание, что это только для двух кортежей.

ОБНОВЛЕНИЕ: за 2015 год

Java 8 не поддерживает кортежи.

ОБНОВЛЕНИЕ: от автора 2015 г.

Если вам все еще нужна поддержка кортежей, есть три библиотеки, которые хорошо поддерживают кортежи:

  • javatuples — поддерживает JDK 5 и выше. До 10-кортежа.
  • JOOλ — от автора jOOQ, но требуется JDK 8.
  • Commons Lang 3 — теперь поддерживает Triple (3-кортеж) и поддерживает JDK 6 и выше.
person Adam Gent    schedule 19.09.2011
comment
Map.Entry — мой любимый. Зачем создавать именованный объект для простой задачи, которую другие языки выполняют на лету? - person Erel Segal-Halevi; 26.02.2013
comment
С этим шаблоном могут быть проблемы с параллелизмом (безопасная публикация). Шаблон, описанный в этом ответе на аналогичный вопрос (final + конструктор), должен решить эту проблему. - person Bruno; 10.10.2013
comment
Да, я поставил выше только для краткости, а не для полного повторного использования. Неизменяемые объекты — всегда хороший выбор. - person Adam Gent; 10.10.2013
comment
Что делать, если мне нужно вернуть 3 объекта? - person Dejell; 17.12.2013
comment
+1 за возвращение и фактическое обновление ответа перед лицом меняющихся условий. Я хочу, чтобы больше людей делали это. - person Chris Warth; 12.06.2015
comment
Я не вижу java.lang.BiValue, встроенного в Java 8, как было предложено выше. Может быть, удалить упоминание об этом. - person matanster; 05.04.2018

Методы Java возвращают точно ноль или одно значение; что является стандартом для Java. Если вам нужно вернуть несколько значений, создайте объект с несколькими значениями и верните его.

person DwB    schedule 19.09.2011
comment
единственное, что для очень тривиального (частного) метода это иногда звучит излишеством... - person Saket; 19.09.2011
comment
void — тип возвращаемого значения в java, кстати. - person Buhake Sindi; 19.09.2011
comment
@The Elite Gentleman Говоря о том, что вы также можете выбросить ноль, что означает, что ноль должен быть исключением :) - person Adam Gent; 19.09.2011
comment
Это не ответ на вопрос Почему его нет - person Alexey; 03.07.2015
comment
Вопрос «почему нет» так же важен, как вопрос «как обезьяна?». Это глупый вопрос. Для java нет нескольких возвращаемых значений. - person DwB; 03.02.2016

Если вы хотите вернуть два объекта, вы обычно хотите вернуть один объект, который вместо этого инкапсулирует два объекта.

person Psychologist    schedule 19.09.2011

Есть много хакерских способов сделать это, один из них - вернуть Object[], но тогда у вас есть индексы, о которых нужно беспокоиться, и проверки нулевого указателя, это просто становится неприятно. Другой способ — вернуть String, но тогда вам придется его анализировать, и это становится неприятным.

Я думаю, главный вопрос в том, почему?

Вот в чем загвоздка: если бы я работал с вами над проектом и увидел такое поведение, я бы переписал его, чтобы вы могли увидеть, как с этим следует обращаться. Если вы предоставите пример кода, я перепишу его для иллюстрации.

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

person Travis    schedule 19.09.2011
comment
Хороший аргумент с единственной ответственностью - person Wivani; 19.09.2011
comment
использование объекта и разбиение на более мелкие методы - очень хорошие подходы, как объясняется в ответе. - person Jayy; 19.09.2011
comment
@Travis допустим, у нас есть объект дискового кеша с методом, который возвращает как кэшированное значение, так и его аннотации (например, время последнего изменения). Множественные возвращаемые значения намного чище, чем использование объекта-оболочки. Мы не можем использовать два вызова метода, потому что кеш может меняться между вызовами метода. - person fhucho; 16.03.2013
comment
@fhucho Это тот случай, когда это применимо, это имеет смысл. То, что вы ищете, это последняя запись и ее детали/метаданные. Почему это не должно быть инкапсулировано в объект? - person Travis; 18.03.2013
comment
@Travis Я думаю, что это приведет к более чистому и понятному коду. Кроме того, нет необходимости в классе-оболочке. Но это вопрос мнения, я думаю. - person fhucho; 19.03.2013

Доступен новый стиль шаблона, который соответствует «полностью асинхронной» природе, которую вы можете увидеть в таких языках, как JavaScript.

Сейчас большая часть моего кода выглядит так :-)

public class Class1 {

    public interface Callback {
       void setData(String item1, String item2);
    }
    public void getThing(Callback callback) {
        callback.setData("a", "b");
    }
}

public class Class2 {

    public void doWithThing(Class1 o) {
        o.getThing(new Class1.Callback() {
            public void setData(String item1, String item2) {
                ... do something with item 1 and item 2 ...
            }
        });
    }

}

Никаких новых объектов для создания и не так много дополнительных классов, поскольку интерфейс является внутренним классом объекта.

Именно это делает Swift таким замечательным. Код может выглядеть так:

o.getThing({ item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
});

А так как единственный аргумент это блок, то даже это:

o.getThing { item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
};

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

person Paul Hamilton    schedule 23.05.2015

Потому что возврат нескольких значений из метода не рекомендуется (в Java).

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

Возврат нескольких значений в других языках (например, Go) используется, например, для возврата кода ошибки, но Java был разработан по-другому с использованием исключений.

person OscarRyz    schedule 19.09.2011