var args construtores / métodos vs listas

5

No longo debate de usar arrays vs listas na API pública de classes Java, prefiro preferir listas na maioria das situações. No entanto, também achei conveniente usar argumentos var em muitos construtores e métodos, que exigem a declaração de um argumento do método (o último) como uma matriz (implicitamente adicionando "..." antes do nome do parâmetro).

Como em muitos desses métodos eu quero fornecer ao programador a possibilidade de listar explicitamente os argumentos (com var args) ou usar uma coleção pré-definida ao invocar o método, eu freqüentemente acabam definindo um construtor ou método com argumentos var e uma versão sobrecarregada que aceita uma lista em vez da matriz var args. Por exemplo:

public void myMethod(X ...items) {  
    myMethod(Arrays.asList(items));
}  

private void myMethod(List<X> items) {  
    ...  
}  

Eu sei que em teoria eu não preciso sobrecarregar o método substituindo a matriz var args por uma lista se eu quiser que o programador envie uma coleção de objetos. Ele poderia apenas enviar uma matriz.

A razão pela qual eu geralmente faço isso é porque a maioria (se não todos) dos métodos em minha API usam listas em vez de arrays, e é um pouco estranho que para um ou dois métodos que requerem coleta de objetos, o programador precise trabalhe com arrays (nos casos em que os argumentos var não são convenientes). Então eu forneço uma versão sobrecarregada trabalhando com lista para consistência.

No entanto, como esse é um problema recorrente, tenho a sensação desconfortável de estar escrevendo código clichê com muita frequência. Eu gostaria de receber feedback se minha motivação de manter minha interface consistente (aceitar var arrays ou listas, mas não forçar o programador a trabalhar com arrays se não for realmente necessária) é válida o suficiente para continuar escrevendo versões sobrecarregadas usando listas para a maioria dos meus métodos requerendo argumentos var.

Gostaria de destacar que sei que, para determinados métodos, os arrays podem ser mais convenientes do que as listas. Minha pergunta diz respeito a situações em que a única motivação para declarar o último argumento do método como um array é porque, em certos cenários, usar argumentos var pode ser conveniente.

UPDATE

Obrigado pelo seu feedback. Minhas conclusões no momento são as seguintes:

  • Reduza o uso de var args o máximo possível.
  • Continue adicionando uma versão sobrecarregada do método com var args, como o argumento array é substituído por uma lista (ou um Iterable , como @Kevin apontou), nos casos em que pode ser útil ter a escolha para invocar o método com var args ou com uma coleção.
  • Pare de usar o Java o mais rápido possível :) (eu já sabia disso)
por Sergio 10.02.2013 / 21:26
fonte

3 respostas

4

Você está pensando demais sobre o problema. Você quer usar uma lista (matriz ou algum outro iterável) para seus argumentos quando é provável que o consumidor de sua função já tenha coisas em uma lista. Você deseja usar argumentos variáveis quando quiser chamar uma função com um número diferente de argumentos.

Um exemplo clássico de quando você deve usar varargs é o printf() de C. Usar varargs faz sentido aqui porque, no caso geral, não há razão para colocar um monte de valores arbitrários em uma lista apenas para imprimir algo. Um bom exemplo de onde você provavelmente deseja uma lista é um sum() , em que você provavelmente está operando com vários valores relacionados que provavelmente seriam armazenados juntos.

Não é algo que você precisa ser dogmático ou ter regras para. Use algum bom senso e escreva códigos que as pessoas possam seguir & não te força a saltar através de arcos arbitrários.

    
por 12.02.2013 / 19:23
fonte
-2

A única justificativa para um cliente querer um varargs que eu possa pensar é simplesmente um argumento de estilo onde ele não "sente" certo para um cliente agrupar as coisas em uma coleção do lado deles.

Um exemplo pode ser quando seu cliente possui vários DAOs que implementam uma interface comum, mas conversam com origens de dados logicamente distintas, como uma tabela Customer e uma tabela Address. Embora um aplicativo cliente possa usar uma interface comum para acessar esses dados, os termos de consulta usados provavelmente não serão os mesmos para ambos (você pode consultar Clientes pelo sobrenome, mas não consultaria Endereços dessa maneira). Como um cliente normalmente não teria um caso de uso para iterar em uma Lista dessa interface, provavelmente eles não armazenariam naturalmente esses dois DAOs em uma lista.

No entanto, as listas são uma estrutura de dados mais útil para se trabalhar do que matrizes. Alocação de memória dinâmica, .sublist (x, y), .clear (), iteradores, etc são todos úteis para ter o que provavelmente é porque você já tem o hábito de usar listas no backend. Então, por que não esperar que o cliente chamando sua API se sinta da mesma maneira? Arrays.asList (item1, item2) é fácil para um cliente usar, então não vejo razão para fornecer a API varargs. Forneça apenas a API de lista.

Além disso, não concordo com o comentário de Kevin de que você deve especificar a interface Iterable na sua API. Você perde todas as APIs úteis na interface List apenas para salvar seu cliente que tem um conjunto de chamadas "new ArrayList (set)" e passando isso para sua API. No mínimo, sua API deve receber uma coleção.

    
por 11.02.2013 / 02:54
fonte
-6

Varargs é uma má idéia em linguagens modernas. Era uma suposição simplificadora em C, mas nunca deveria ter dado o salto para Java ou C # (C ++ pode ser perdoado porque realmente queria ser um superconjunto de C). Qualquer idioma que tenha um List de primeira classe, mesmo antes de genéricos e List<Object> , deve ser capaz de representar qualquer função varargs muito melhor com um parâmetro de lista. E se você eliminar varargs completamente, muitas assinaturas de métodos que são ambíguas com varargs deixam de existir.

    
por 10.02.2013 / 22:46
fonte

Tags