Pegadinha de varargs

Olá

Analisem o código abaixo e digam o que acontecerá explicando a resposta:

[code]
public class A extends B {
A(int…aarr) {
}

public static void main(String args[]) {
    A a = new A(1, 2, 3, 4, 5);
    a.print();
}

}

class B {
int array[];

B(int...barr) {
    array = barr;
}

void print() {
    for (int i : array)
    System.out.println(i);
}

}[/code]

Respostas:
a) Erro de compilação
b) Lança uma exceção em tempo de execução
c) Imprime 1 2 3 4 5
d) Não imprime nada
e) Imprime 1

[]s
Luca

Letra d),

Como no construtor de A, não chamamos explicitamente o contrutor de B, logo o contrutor de B recebe um array vazio.

A não ser que alterarmos o construtor de A e colocarmos a referencia para o construtor de B passando o array aarr, assim:

     A(int...aarr) {
         super(aarr);
     }

Neste caso a saída seria diferente.

É isso?

Olá

Perfeita a explicação, com louvor!

Putz, a pegadinha não pegou ninguém e me pegaram!

[]s
Luca

Isso teria que dar erro de compilação, pois B não possui um construtor default.

que coisa mais estranha… não consegui encontrar uma explicação para o que acontece aqui.

ele passa um array de tamanho 0 pro construtor do B? porque isso?

(aliás tentei achar vargars na especificacao do java e nao achei)

[quote=rmarin]Letra d),

Como no construtor de A, não chamamos explicitamente o contrutor de B, logo o contrutor de B recebe um array vazio.

A não ser que alterarmos o construtor de A e colocarmos a referencia para o construtor de B passando o array aarr, assim:

     A(int...aarr) {
         super(aarr);
     }

Neste caso a saída seria diferente.

É isso?
[/quote]

desculpe mas isso nao me conveceu… vc nao explicou, só escreveu o q acontece
a questao é: porque o construtor de B recebe um array de tamanho 0?

ele nao esta instanciando a classe B entao nao tem pq chamar algum ou qquer contrutor.

quando vc tem uma variavel nao instanciada o for simplismente nao é executado … no primeiro teste ele nao faz nada … por isso nao imprime nada …

tanto que se voce mudar o construtor para

    A( int ... arrr ){
        super(arrr);
    }

ele vai imprimir os numeros normalmente

Olá

Daniel, coloquei public na classe A só para poder compilar. Experimente e verá que não dá erro.

Inclua a chamada para o super do Marin e veja que imprime certinho.

[]s
Luca

chama o construtor de B sim, porque A é subclasse de B.
(regra de chamada autoatica de construtores dos pais)

[quote=fmeyer]
quando vc tem uma variavel nao instanciada o for simplismente nao é executado … no primeiro teste ele nao faz nada … por isso nao imprime nada … [/quote]

a variavel nao eh null
ela eh um array de tamanho 0!

Olá

O compilador cria um array com o tamanho do número de argumentos atuais. Se não foi passado nenhum argumento, ele gera um array de comprimento zero.

<editado>Pera aí… acho q eu disse bobagem…escrever falando no telefone não dá certo… :oops:

[]s
Luca

Mas não tem a parada de chama implicita de super() no construtor de A?
Teria que dar pau.

tmb acho.
a primeira linha de todo construtor é uma chamada a super da classe pai. como foi definido um construtor com parametros na classe B, o compilador não vai inserir o construtor default em B e na chamada do construtor de A o compilador vai tentar inserir uma chamada ao construtor default de B pq não foi inserida nenhuma. ficou complicado? :smiley:

[]'s

[quote=danieldestro]Mas não tem a parada de chama implicita de super() no construtor de A?
Teria que dar pau.[/quote]

realmente… pensando no q o luca escreveu (mesmo ao telefone) concluimos que um construtor com varargs assume a chamada a super() pra ele e por isso que fica com array de tamanho 0.

entendi o lance do array de tamanho 0 (pq o super() foi chamado logico) mas tbm acho q deveria dar algum tipo de erro aqui… o compilador nao poderia colocar a chamada a super() às cegas, sem saber se vai chamar o default ou outro… sei la

Olhem o que está escrito no livro da Kathy Sierra:

Se sua superclasse não tiver um construtor sem argumentos, você terá que criar um construtor a inserir uma chamada a super() que coincidam com os do construtor da superclasse.

logo…teria de dar pau! estranho :shock:

ah tah…agora saquei tbm depois da explicação do Sérgio! :smiley:

algumas brincadeirinhas:

adicione mais um construtor com varargs a B e A nao compila mais (erro: construtor implicito é ambiguo)

adicione um construtor padrao a B e A volta a compilar. neste caso a chamada a super(), como era de se esperar, chama o default de B

Òlá

Também não achei varargs. Mas achei a seguinte nomenclatura:

[quote=JLS 3.0 8.4.1]
LastFormalParameter:
VariableModifiers Type…opt VariableDeclaratorId
FormalParameter[/quote]

[quote=JLS 3.0 15.1.4.2]
If the method being invoked is a variable arity method (§8.4.1) m, it necessarily has formal parameters. The final formal parameter of m necessarily has type T[] for some T, and m is necessarily being invoked with actual argument expressions.[/quote]

[]s
Luca

Olá

[quote=danieldestro]Mas não tem a parada de chama implicita de super() no construtor de A?
Teria que dar pau.[/quote]

[quote=JLS 3.0 8.8.7]
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body is implicitly assumed by the compiler to begin with a super class constructor invocation “super();”, an invocation of the constructor of its direct superclass that takes no arguments.[/quote]

O construtor B(int…barr) é um construtor da super classe com zero ou mais argumentos e assim foi chamado com zero argumentos.

Lição desta pegadinha: Cuidado com construtores usando varargs!

Mas isto é coisa que só existe no teste da Sun…hehehe

[]s
Luca

Olhem o seguinte código:

    public static void main(String[] args) {
        x();
        System.out.println("Viu?");
    }
    
    public static int x(int ...array) {
        return 0;
    }

Este código não apresenta erro de compilação.

O mesmo ocorre no caso do construtor. Eu chamei o método x, sem passar nenhum parametro. No método x, neste caso, será um array vazio.

É isso que o Luca disse mesmo. Eu lembro de ter visto isso em uma matéria da MJ com o Paulo Silveira sobre a nova certificação 1.5. Lá ele comenta algo sobre isso mesmo.