Pegadinha fácil para quem é fera em Generics

Olá

Na especificação do Java, no capítulo 4, item 4.11 há o seguinte exemplo:

[code]
import java.util.Random;
import java.util.Collection;
import java.util.ArrayList;

// Java Language Specification
// Third Edition
// CHAPTER 4
// Types, Values, and Variables

// 4.11 Where Types Are Used

class MiscMath {
int divisor;

MiscMath(int divisor) {
   this.divisor = divisor;
}

float ratio(long l) {
    try {
        l /= divisor;
    } catch (Exception e) {
        if (e instanceof ArithmeticException)
            l = Long.MAX_VALUE;
        else
            l = 0;
        }
    return (float)l;
}

double gausser() {
    Random r = new Random();
    double[] val = new double[2];
    val[0] = r.nextGaussian();
    val[1] = r.nextGaussian();
    return (val[0] + val[1]) / 2;
}

Collection<Number> fromArray(Number[] na) {
    Collection<Number> cn = new ArrayList<Number>();
    for (Number n : na) {
        cn.add(n);
    }
    return cn;
}

void <S> loop(S s) { 
    this.<S>loop(s);
}

}[/code]

Observando o último método void <S> loop(S s), aparece a seguinte dúvida. Há alguma diferença entre colocar <S> depois de void como está no exemplo da especificação e que repeti abaixo na classe Depois ou se deveria colocar <S> void loop (S s) tal como na classe Antes.

public class Depois { void <S> loop(S s) { this.<S>loop(s); } }

public class Antes { <S> void loop(S s) { this.<S>loop(s); } }

Quem pode explicar exatamente o que acontece?

[]s
Luca

Eu podia jurar que essa classe não compilaria por causa da linha

void <S> loop(S s){

já que o deveria vir antes do tipo de retorno do método

Olá

[quote=Ataxexe]Eu podia jurar que essa classe não compilaria por causa da linha

void <S> loop(S s){

já que o deveria vir antes do tipo de retorno do método[/quote]

Então neste caso o texto da especificação contém um erro. Pode explicar porque acha que deve acontecer um erro de compilação?

[]s
Luca

Porque o tipo genérico pode se referir a todo o contexto do método, inclusive seu tipo de retorno. Então eu acho que ele geraria um erro de compilação porque caso o método mude para retornar uma variável S, ela não poderia ser resolvida porque a declaração do tipo genérico estaria depois do tipo de retorno.

Olá

Acho que você está no caminho mas a explicação ainda não está muito boa.

Sugiro a todos que compilem os exemplos, inclusive o da classe MiscMath que está na especificação.

[]s
Luca

Tirando o fato de estar faltando um ponto-e-vírgula num foreach, o erro acontece porque o void é tratado como um modificador de acesso e o tipo de retorno fica indeterminado pelo compilador. Tudo isso por causa do estar no lugar “errado” que na verdade é tratado como se ele estivesse após o último modificador de acesso (o “void”) e antes do retorno do método (o “”). O compilador se perde por causa disso.

Olá

Certo, além dos imports tive também que corrigir isto no código que postei.

Mais alguém para tecer alguma consideração sobre este erro na especificação?

[]s
Luca