Porque o primeiro compila e o segundo não?
Muitos falam porque a classe Integer é final, más porque o primeiro compila?
Cade os desenvolvedores do compilador para explicar?
no primeiro ta acontecendo o autoboxing do java 5 por isso compila e no segundo vc eestá retornando um objeto e nao um inteiro. o autoboxing nao vai funciona ai…
Olha, em teoria os dois são equivalentes.
O primeiro, com o autoboxing, o compilador transformaria em algo equivalente ao segundo.
Não vejo motivo nenhum para um compilar e outro não, vou fazer uns testes aqui.
EDIT: Para mim nenhum dos dois compilou. O compilador queria um T, mas achou um Integer. Fica mais fácil entender se o código fosse assim:
public <T extends Integer> T soma2(Class<T> c) {
return new Integer(35);
}Neste caso, suponha que existissem subclasses de Integer (o compilador não verifica se a classe é final), você estaria retornando a subclasse sendo que o retorno desejado poderia ser uma subclasse.
Se no seu compilador o primeiro método compila, então você achou um bug no compilador.
[quote=victorwss]Olha, em teoria os dois são equivalentes.
O primeiro, com o autoboxing, o compilador transformaria em algo equivalente ao segundo.
Não vejo motivo nenhum para um compilar e outro não, vou fazer uns testes aqui.[/quote]
é vou testar tb, meio estranho se ele fou que nao compila… .
Independente de qualquer coisa, preciso fazer a conversão para indicar o retorno correto
public <T extends Integer> T soma2() {
return (T) new Integer(35);
}
O estranho é que foi permitido indicar o extends para uma classe final. não sabia que isso era possível. Vou ficar de olho para ver se alguém aparece com uma boa explicação.
Prezados, me perdoem se eu estiver me metendo em uma briga de gente grande Meu objetivo é acompanhar a discussão e aprender…
Não seria esse o caso discutido no livro Effective Java 2 ed. no capitulo sobre Generics , item 28: “Use bounded wildcards to increase API flexibility”. http://java.sun.com/docs/books/effective/
Na página 137 do capitulo 5 (exatamente o capitulo que tá disponivel no link da Sun, acima) o autor diz:[quote] Do not use wildcard types as return
types. Rather than providing additional flexibility for your users, it would force
them to use wildcard types in client code.[/quote]
Negritos do autor. Não é isso que acontece aqui?: public <T extends Integer> T soma2() {
return new Integer(35);
} ?
Nesse capítulo ele descreve alguns detalhes das especificações da linguagem e sobre o compilador, que me pareceu ter relação com o primeiro codigo nao ter funcionado, mas funcionar quando fez um cast explícito return (T) new Integer(35);
[quote=estundidher]public T soma1() {
return 35;
}
public T soma2() {
return new Integer(35);
}
Porque o primeiro compila e o segundo não?
Muitos falam porque a classe Integer é final, más porque o primeiro compila?
Cade os desenvolvedores do compilador para explicar?
AHUAHUAHA[/quote]
No primeiro caso o retorno é um int primitivo e o compilador faz o autoboxing. <T extends Integer> quer dizer que o compilador vai aceitar um T ou um Integer, o compilador vê que um int não é um T e (nem pode ser convertido para um) e vai para a superclasse, que é um Integer. testa, vê que um int pode ser convertido automaticamente para um Integer (depois do Java 5) e compila.
No segundo caso o compilador percebe que o Integer 35 já deveria poder ser um T, mas isso não é possível pois Integer é final e T não pode extender Integer, isso nem compila.
Não é uma explicação, é uma narração do que, a meu ver, parece estar acontecendo, muito estranho, vou ver se acho alguma explicação.
[quote=victorwss]
EDIT: Para mim nenhum dos dois compilou. O compilador queria um T, mas achou um Integer.
…
Se no seu compilador o primeiro método compila, então você achou um bug no compilador.[/quote]
Aqui compilou o primeiro, mas não o segundo…
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing)
Eclipse Platform
Version: 3.4.1
Build id: M20080911-1700
[quote=MarceloS][quote=victorwss]
EDIT: Para mim nenhum dos dois compilou. O compilador queria um T, mas achou um Integer.
…
Se no seu compilador o primeiro método compila, então você achou um bug no compilador.[/quote]
Aqui compilou o primeiro, mas não o segundo…
[code]
java version "1.6.0_10"
Java™ SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot™ Client VM (build 11.0-b15, mixed mode, sharing)
O meu também é 1.6.0_10-b33.
Estou usando o seguinte código:[code]public class StrangeInt {
public <T extends Integer> T soma1() {
return 35;
}
public <T extends Integer> T soma2() {
return new Integer(35);
}
}[/code]e o resultado é:StrangeInt.java:3: incompatible types
found : int
required: T
return 35;
^
StrangeInt.java:7: incompatible types
found : java.lang.Integer
required: T
return new Integer(35);
^
2 errors
Posta aí o código completo que você usou. Talvez tenha algum outro detalhe que não vimos.
Só mais um detalhinho.
Alguém compilou com o compilador do Eclipse ? (Estou sem o Eclipse aqui).
Ele deve dar um diagnóstico diferente.
Se ele compilar um deles, ou não compilar nenhum deles, ou compilar ambos, estamos frente a algum caso que não está claramente definido na JLS, e isso deve ser reportado tanto à Sun quanto à Eclipse, para que digam o que está correto e concordem sobre o que fazer.
[quote=thingol]Só mais um detalhinho.
Alguém compilou com o compilador do Eclipse ? (Estou sem o Eclipse aqui).
Ele deve dar um diagnóstico diferente.
Se ele compilar um deles, ou não compilar nenhum deles, ou compilar ambos, estamos frente a algum caso que não está claramente definido na JLS, e isso deve ser reportado tanto à Sun quanto à Eclipse, para que digam o que está correto e concordem sobre o que fazer.
[/quote]
Eu fiz sem o eclipse. Com o eclipse compila e roda.
Realmente “this is a compiler bug.” No compilador do eclipse.
Bom… acho que é o caso de submeter o tal programa ao pessoal do Eclipse e ao pessoal da Sun, para que decidam qual é o comportamento esperado. Eu simplesmente não sei, só de olhar a JLS, qual seria o resultado esperado.
[quote=thingol]Bom… acho que é o caso de submeter o tal programa ao pessoal do Eclipse e ao pessoal da Sun, para que decidam qual é o comportamento esperado. Eu simplesmente não sei, só de olhar a JLS, qual seria o resultado esperado.
[/quote]
Acredito que é o eclipse que está errado, pois o método “manualboxed” falha nos dois.
public class TesteGenerics {
public <T extends Integer> T soma1() {
return 35;
}
public <T extends Integer> T soma2() {
return new Integer(35);
}
}
C:\tmp>javac TesteGenerics.java
TesteGenerics.java:4: incompatible types
found : int
required: T
return 35;
^
TesteGenerics.java:8: incompatible types
found : java.lang.Integer
required: T
return new Integer(35);
^
2 errors
Eu vou me limitar à explicação da função soma2(), que é um erro que faz mas sentido pra mim:
public <T extends Integer> T soma2() {
return new Integer(35);
}
Dá erro porque, quando digo , estou querendo dizer: “meu retorno é um Integer ou qualquer subclasse de Integer”. É claro que isso é só teoria, na prática, por Integer ser final, não existe uma sublasse pra ela. Mas, se fizéssemos assim:
public <T extends NumberFormat> T soma2() {
// TODO
}