Pergunta

Com um terceiro API partido observei o seguinte.

Em vez de usar,

public static string getString(){
   return "Hello World";
}

ele usa algo como

public static void getString(String output){

}

e eu estou começando a string "output" atribuído.

Estou curioso sobre a razão de implementar essa funcionalidade. Quais são as vantagens do uso de tais parâmetros de saída?

Foi útil?

Solução

Algo não está certo no seu exemplo.

class Foo {

    public static void main(String[] args) {
        String x = "foo";
        getString(x);
        System.out.println(x);
    }

    public static void getString(String output){
        output = "Hello World"
    }
}

No programa acima, a string "foo" será emitido, não "Olá Mundo".

Alguns tipos são mutáveis, caso em que você pode modificar um objeto passado para uma função. Para tipos imutáveis ??(como String), você teria que construir algum tipo de classe de mensagens publicitárias que você pode passar em torno de vez:

class Holder<T> {
    public Holder(T value) {
        this.value = value;
    }
    public T value;
}

Depois, você pode em vez passar em torno do titular:

public static void main(String[] args) {
    String x = "foo";
    Holder<String> h = new Holder(x);
    getString(h);
    System.out.println(h.value);
}

public static void getString(Holder<String> output){
    output.value = "Hello World"
}

Outras dicas

Não concordo com Jasper: "Na minha opinião, esta é uma maneira realmente feio e mau para retornar mais de um resultado". No .NET existe uma construção interessante que utilizam os parâmetros de saída:

bool IDictionary.TryGet(key, out value);

Acho que é muito útil e elegante. E é a maneira mais conveniente de aks se um item está na coleção e devolvê-lo ao mesmo tempo. Com ele você pode escrever:

object obj;
if (myList.TryGet(theKey, out obj))
{
  ... work with the obj;
}

I constantemente repreender meus desenvolvedores se eu ver o código de estilo antigo como:

if (myList.Contains(theKey))
{
  obj = myList.Get(theKey);
}

Você vê, ele corta o desempenho pela metade. Em Java não há nenhuma maneira de valor nulo diferenciar de um item existente de não-existência de um item em um mapa em uma chamada. Às vezes isto é necessário.

Esse exemplo é errado, Java não tem parâmetros de saída.

Uma coisa que você poderia fazer para emular este comportamento é:

public void doSomething(String[] output) {
    output[0] = "Hello World!";
}

Mas IMHO isso é uma merda em vários níveis. :)

Se você quer um método para retornar algo, fazê-lo devolvê-lo. Se você precisa de retornar vários objetos, criar uma classe de recipiente para colocar esses objetos para dentro e retornar isso.

Esta funcionalidade tem uma grande desvantagem - ele não funciona. parâmetros da função são locais para a função e atribuindo a eles não tem qualquer impacto fora da função.
Por outro lado

void getString(StringBuilder builder) {
    builder.delete(0, builder.length());
    builder.append("hello world");
}

vai funcionar, mas não vejo nenhuma vantagem de se fazer isso (exceto quando você precisa de retornar mais de um valor).

Cordas são imutáveis, você não pode usar parâmetros de saída pseudo do Java com objetos imutáveis.

Além disso, o âmbito do saída está limitado ao getString método. Se você alterar o saída variável, o chamador não ver nada.

O que você pode fazer, no entanto, é mudar o Estado do parâmetro. Considere o seguinte exemplo:

void handle(Request r) {
    doStuff(r.getContent());
    r.changeState("foobar");
    r.setHandled();
}

Se você tem um gerente chamando vários identificadores com uma única solicitação, você pode alterar o estado do pedido de permitir o tratamento posterior (por outros manipuladores) em um conteúdo modificado. O gerente também poderia decidir processamento de parada.

Vantagens:

  • Você não precisa retornar um objeto especial contendo o novo conteúdo e se o processamento deve parar. Esse objeto só seria usado uma vez e criar a memória resíduos objeto e poder de processamento.
  • Você não tem que criar um outro objeto de solicitação e deixe o coletor de lixo se livrar da referência de idade agora obsoleta.
  • Em alguns casos, você não pode criar um novo objeto. Por exemplo, porque esse objeto foi criado usando uma fábrica, e você não tem acesso a ele, ou porque o objeto tinha ouvintes e você não sabe como contar os objetos que estavam ouvindo o velho solicitação de que, em vez ouvir a nova solicitação.

Na verdade, é impossível ter os parâmetros em java, mas você pode fazer um trabalho em torno de fazer o método take em uma referência de para a cadeia imutável e primitivas por qualquer escrevendo uma classe genérica onde o imutável é o genérico com o valor e setter e getter ou usando uma matriz, onde o elemento 0 (1 de comprimento) é o valor fornecido é instanciar primeiro porque há situações em que você precisa para retornar mais de um valor em ter que escrever uma classe apenas para devolvê-los onde a classe é usada apenas existe apenas um desperdício de texto, e não é reutilizável.

Agora ser um C / C ++ e também Net (mono ou MS), me insta que java não suporta, pelo menos, um de-referência para primitivas; assim, eu recorrer à matriz em vez.

Aqui está um exemplo. Vamos dizer que você precisa para criar uma função (método) para verificar se o índice é válido na matriz, mas você também quiser retornar o comprimento remainding após o índice é validado. Vamos chamá-lo em c como 'bool validate_index (int index, arr_len int, int & rem)'. Uma maneira de fazer isso em java seria 'booleana validate_index (int índice, int arr_len, rem1 int [])'. rem1 significa apenas o elemento de matriz espera 1.

public static Boolean validate_index(int index, int arr_len, int[] rem1)
{
    if (index < 0 || arr_len <= 0) return false;

    Boolean retVal = (index >= 0 && index < arr_len);

    if (retVal && rem1 != null) rem1[0] = (arr_len - (index + 1));

    return retVal;

}

Agora, se nós usamos isso podemos obter tanto o retorno booleana e o restante.

 public static void main(String[] args)
 {
    int[] ints = int[]{1, 2, 3, 4, 5, 6};
    int[] aRem = int[]{-1};
    //because we can only scapegoat the de-ref we need to instantiate it first.
    Boolean result = validate_index(3, ints.length, aRem);

    System.out.println("Validation = " + result.toString());
    System.out.println("Remainding elements equals " + aRem[0].toString());

 }

puts: Validação = True puts: Elementos Remainding é igual a 2

elementos de matriz sempre quer apontar para o objeto na pilha ou o endereço do objeto na pilha. Então, usando-o como um de referências é absolutamente possível, mesmo para matrizes, tornando-a um duplo conjunto instanciar-lo como myArrayPointer = new Class [1] [], em seguida, passá-lo em porque às vezes você não sabe o que o comprimento da vontade variedade até que a chamada passando por um algoritmo como 'booleana tryToGetArray (SomeObject o, T [] [] ppArray)', que seria o mesmo que em c / c ++ como 'modelo bool tryToGetArray (SomeObject * p, T ** ppArray)' ou C # 'boleano tryToGetArray (SomeObject O, ref T [] array)'. Ele funciona e funciona bem, desde que o [] [] ou [] é instanciar na memória pela primeira vez com pelo menos um elemento.

Às vezes, este mecanismo pode evitar a criação de um novo objeto.

Exemplo: Se um objeto apropriado existe de qualquer forma, é mais rápido para passá-lo para o método e se algum campo alterado.

Este é mais eficiente do que criar um novo objeto dentro do método chamado, e retornando e atribuindo sua (lixo produzindo que precisa ser coletado em algum momento) de referência.

Na minha opinião, este é útil quando você tem mais de um resultado em uma função.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top