Análise a sentença a seguir:Arrays.asList(new X(), newY()).s...
Análise a sentença a seguir:
Arrays.asList(new X(), new
Y()).stream().mapToInt(X::m).sum()?
Dadas as classes X e Y, respectivamente, class X {int m() {return 1;}} e class Y extends X{int m(){return 2;}}, essa sentença apresentada
Gabarito comentado
Confira o gabarito comentado por um dos nossos professores
Alternativa correta: A - não compila.
Para entendermos o motivo pelo qual a alternativa A é a correta, precisamos discutir alguns conceitos da linguagem Java que estão sendo aplicados na sentença em questão.
O código apresentado tenta utilizar a Stream API do Java para processar uma lista de objetos e somar os valores retornados pelo método m()
desses objetos. No entanto, o erro ocorre devido a um problema de tipagem na expressão lambda utilizada.
A expressão Arrays.asList(new X(), new Y())
cria uma lista contendo objetos das classes X
e Y
. A classe Y
é uma subclasse de X
, e ambas as classes possuem um método chamado m()
, mas isso não é suficiente para o uso da expressão X::m
diretamente na stream.
No Java, métodos referenciados dessa forma são resolvidos em tempo de compilação, e o compilador espera que o método referenciado seja compatível com a assinatura exigida pela operação que está sendo realizada na stream. No caso de mapToInt
, espera-se uma função que receba um objeto do tipo da stream e retorne um int
. Entretanto, o método m()
não é estático, e portanto precisa de uma instância do tipo X
para ser invocado.
O compilador Java não pode determinar um tipo comum aos objetos new X()
e new Y()
que seja capaz de invocar o método m()
de forma não ambígua. A classe Y
herda o método m()
de X
, mas também o sobrescreve com sua própria implementação. Isso causa um problema de ambiguidade para o compilador, que não consegue determinar qual versão do método m()
deveria ser invocada em cada caso.
Para resolver essa questão em um contexto real, seria necessário fornecer um lambda que explicitamente determinasse como cada objeto da lista deve ser tratado, por exemplo, utilizando uma expressão lambda que chame o método m()
para cada objeto, como: .mapToInt(x -> x.m())
. Isso forçaria a chamada do método m()
da instância correta em cada caso.
Portanto, a alternativa A está correta porque o código apresentado tem um erro de compilação causado pela ambiguidade na referência ao método m()
em um contexto onde objetos de diferentes tipos são tratados de forma indistinguível pelo compilador.
Clique para visualizar este gabarito
Visualize o gabarito desta questão clicando no botão abaixo
Comentários
Veja os comentários dos nossos alunos
Que M, esse negócio vai é explodir o PC
O código compila, gabarito é a letra D.
int sum = Arrays.asList(new X(), new Y()).stream().mapToInt(X::m).sum();
System.out.println(sum);
3
O erro é a interrogação no final.
Arrays.asList(new X(), new Y()).stream().mapToInt(X::m).sum()?
Se tivesse o ";" seria 3 o resultado.
Clique para visualizar este comentário
Visualize os comentários desta questão clicando no botão abaixo