Compilador doido? Questão de prova. (Resolvido)

9 respostas
bruno_7317
public class Redwood extends Tree {
	public static void main(String[] args) {
		Tree t = (Redwood) new Tree();
	}
}

class Tree {}

No código acima, temos uma Runtime Exception.
Minha dúvida é por quê isso gera uma Runtime ao invés de um Compilation-time.
Por quê o compilador não identifica esse cast absurdo?

9 Respostas

C

Boa tarde

Então bruno, ele compila porque a classe Radwood herda a classe Tree, por isso a compilação ocorre.

Falou.

bruno_7317

Claro que não!

Um cast do tipo

code Superclasse;[/code] É um absurdo sem tamanho!

E

Um tiipo de questão assim, rigorosamente, não deveria cair na prova, por que é uma coisa que está “escrita em letras miúdas na especificação”.

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#238146

O compilador entende que a expressão “new Tree()” é uma expressão cujo tipo é Tree (ou seja, new Tree, nesse ponto, poderia retornar um objeto de qualquer classe que fosse Tree ou até mesmo uma subclasse de Tree). É por isso que ele força um run-time check em vez de indicar um erro de compilação.

Tree t = (Redwood) new Tree();

é equivalente, para o compilador, a uma coisa como:

public static Tree newTree() { return new Redwood(); }
...
Tree t = (Redwood) newTree();

Concordo com você que neste caso em especial o compilador deveria indicar que o tipo dessa expressão não pode ser uma subclasse de Tree e portanto o cast pode ser provado estaticamente que vai sempre ser incorreto. Veja se o mesmo problema ocorre com o compilador do Eclipse (que não é o javac, que é usado pelo NetBeans).

C

Quando fiz a prova não lembro de todas as questões sobre Cast, mas é sempre bom ficar atento porque tem algumas que confundem, como este exemplo acima.

Até mais.

bruno_7317

Mesmo compilation-fail no eclipse.

Mas como você sabe que o compilador lê meu códigoTree t = (Redwood) new Tree(); como public static Tree newTree() { return new Redwood(); } ... Tree t = (Redwood) newTree();

Isso seria o mesmo que dizer que Tree é uma subclasse de Redwood, o que continua sendo um absurdo. Não entendi.

E

É assim.

Ao ler a expressão, ele cria uma árvore sintática abstrata (AST, “Abstract Syntax Tree”) e vai atribuindo os tipos a cada nó dessa árvore. Ao ver a expressão “new Tree()”, ele cria um nó para essa expressão, cujo tipo é Tree.

Só que o compilador não guarda a informação de que o tipo dessa expressão é EXATAMENTE Tree (não pode ser uma subclasse de Tree). Acho que isso é feito porque o caso em que é necessário saber esse tipo de informação é só necessário quando usar algumas particularidades do Generics (lembra-se daquelas histórias de “super T” ou “extends T” que você vê às vezes? Pois é…)

Portanto, como você está fazendo um “upcast” (cast de uma expressão cujo tipo é Tree, ou seja, o objeto retornado por essa expressão tem o tipo Tree ou então um tipo que é uma subclasse de Tree), ele simplesmente põe um “run-time check” em vez de reclamar que o cast não pode ser efetuado. E é por isso que eu pus a expressão equivalente “newTree” porque o compilador guarda exatamente a mesma descrição para o tipo dessa expressão para “new Tree()” ou “Tree newTree()”.

bruno_7317

entanglement:

Ao ler a expressão, ele cria uma árvore sintática abstrata (AST, “Abstract Syntax Tree”) e vai atribuindo os tipos a cada nó dessa árvore. Ao ver a expressão “new Tree()”, ele cria um nó para essa expressão, cujo tipo é Tree.

É grego? rs

Entendi tudo. Obrigado, cara!

E

O código abaixo roda e funciona direitinho. Por que é que você disse que ele é absurdo?

public static Tree newTree() { return new Redwood(); }    
...    
Tree t = (Redwood) newTree();
bruno_7317

entanglement:
O código abaixo roda e funciona direitinho. Por que é que você disse que ele é absurdo?

public static Tree newTree() { return new Redwood(); } ... Tree t = (Redwood) newTree();

O newTree pode retornar tanto um Tree quanto um Redwood, por isso ele deixa pra verificar em runtime.
Entendi. Obrigado novamente.

Criado 22 de dezembro de 2011
Ultima resposta 22 de dez. de 2011
Respostas 9
Participantes 3