Como são retornados vários valores em Java?


11

Às vezes, você deseja retornar vários valores de uma função. Como isso é feito normalmente em Java?

Uma opção é usar uma matriz, como este trecho de código Python que retorna uma lista ou tupla:

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

Outra opção seria retornar um hash / dict, como este exemplo de JavaScript:

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

Mais um seria criar um objeto personalizado apenas para esse fim, como este exemplo de Java:

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

É claro que você também pode usar algumas variáveis ​​globais para armazenar o que precisa, em vez de repassar as coisas, mas digamos que não é uma opção.


As pessoas Java "reais" realmente enfrentam o problema de usar getters e setters públicos para ocultar campos em pequenas classes internas como essa? Apenas curioso.
Chris Farmer

3
Sim, a maioria faz. Como muitas estruturas esperam o padrão JavaBean, você pode se arrepender de não ter getters e setters. De qualquer forma, seu IDE irá gerá-los para você.
Eric Wilson

3
Ou você pode simplesmente deixá-los de fora, com base no princípio YAGNI. Mas isso não parece acontecer com a frequência esperada.
MatrixFrog

@ Farmacoy: Eu acho que entendo para beans e afins, mas o OP implica que esta é apenas uma classe única projetada para retornar vários valores.
25711 Chris Farmer

@ ChrisFarmer Acho que, com esse contexto, nunca vi um programador Java 'real' criar uma classe para esse fim.
Eric Wilson

Respostas:


26

Como isso é feito normalmente em Java?

Dolorosamente.

Uma opção é usar uma matriz, como este trecho de código Python que retorna uma lista ou tupla ...

Outra opção seria retornar um hash / dict, como este exemplo de JavaScript ...

Essas técnicas não funcionam bem em Java; os valores teriam que ser baixados do objeto.

Mais um seria criar um objeto personalizado apenas para esse fim, como este exemplo de Java ...

Isso é mais comum, mas é tedioso criar todas essas pequenas classes. Em C ++, é comum usar std :: pair, mas isso geralmente não é feito em Java.

Com o Lombok , é muito fácil criar pequenos objetos personalizados:

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

}


10
"Como isso é feito normalmente em Java?" "Dolorosamente." lol como um desenvolvedor Java que eu tenho que +1-lo por isso
TheLQ

Usando um compacto imutável struct-como classe não é tão doloroso ... É realmente como escrever um struct C ...
Guillaume

1
@ Guillaume - claro, mas todas essas pequenas coisas se somam no tempo e no espaço. Não sei por que a comunidade Java não adotou um conjunto padrão de genéricos como "classe Par <T1, T2> {public T1 first; public T2 second; ...}"; nas línguas modernas você apenas "retorna a, b"; e escreva "x, y = f ()";
Kevin cline

1
Tenho certeza de que uma linguagem 'antiga' também é capaz de fazê-lo :) IMHO Encontrei vários valores de retorno que podem levar à bagunça total e, se você precisar adicionar outros campos de retorno, basta atualizar sua estrutura como a classe sem precisar altere sua assinatura de método.
Guillaume

1
Isso "dolorosamente". me impressionou, sim, é exatamente o que eu sinto como desenvolvedor Java quando encontro situações semelhantes.
Artjom # 25/13

13

Sim, a maneira de criar um struct/ tuple/ recordem Java é criando uma classe. Se for apenas para uso interno, prefiro usar uma pequena classe imutável de estrutura com campos públicos.

Exemplos:

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

Isso é muito mais fácil de fazer no Scala:

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

8
Na verdade, em Scala, você provavelmente provavelmente retornaria a Tuple2[Boolean, Int]. Embora neste exemplo específico , você retorne um Option[Int].
Jörg W Mittag

2
Portanto, isso responde à pergunta de Chris Farmer (nos comentários do Q) de que pessoas reais de Java não criam necessariamente getters e setters para pequenas classes internas. Você é uma pessoa Java "real", certo?
Mike M. Lin

2
Em outras notícias, não existem escoceses verdadeiros.
Joseph Weissman

5

Para o exemplo que você deu, lançar uma exceção seria a maneira mais padrão de lidar com isso:

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

Além disso, se você se esforçar para ter funções que "realizem uma coisa", o recurso de retornar vários valores é menos necessário, embora ocasionalmente conveniente.


4

Temos uma classe genérica Pair que pode armazenar uma instância de A e uma instância de B. Você provavelmente pode criar um Tripleto ou Quádruplo da mesma maneira.

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

1
isso cria um código REALMENTE ilegível. se um método retornar Pair<String, Integer>, o que isso significa? o que esses valores representam? você não pode saber sem ler a implementação do método.
Sara

1

Em Java, sua função retornaria um objeto (ou talvez nulo no caso de uma falha). Dessa forma, vários dados podem ser retornados.


1

Não há uma maneira explícita de retornar várias variáveis ​​em Java, no entanto, existem algumas abordagens:

  1. O primeiro é seguir o caminho da matriz. Isso realmente funciona se você tiver tudo como o mesmo tipo de dados ou se puder convertê-los temporariamente em um tipo.
  2. A segunda maneira é criar uma classe com a finalidade de transferir vários tipos de variáveis. No meu trabalho, nos referimos a eles como DTOs ou Data Transfer Objects.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.