Encontrei a seguinte pergunta no meu livro de estudo e um pouco confuso:
Dado o código a seguir, qual opção, se usada para substituir /* INSERT CODE
HERE */
, irá habilitar uma variável de referência do tipo Roamable
para se referir a um objeto do
Phone
aula? (Selecione 1 opção.)
interface Roamable{}
class Phone {}
class Tablet extends Phone implements Roamable {
//INSERT CODE HERE
}
Opções são:
Roamable var = new Phone();
Roamable var = (Roamable)Phone();
Roamable var = (Roamable)new Phone();
- Porque interface
Roamable
e classePhone
não estão relacionados, uma variável de referência do tipoRoamable
não pode se referir a um objeto de classePhone
.
Achei que a opção correta é 4, mas diz que é 3.
Mas, Phone
não implementa Roamable
interface, para que você não possa transmitir, pode?
Respostas:
10 para resposta № 1A resposta correta é 3
: O compilador vê apenas que um Phone
está sendo lançado para um Roamable
e essa Phone
não é final, então ele pensa que o objeto sendo lançado, embora referido como Phone
pode ser uma subclasse de Phone
aquele faz implemento Roamable
, portanto, nenhum erro de tempo de compilação ou aviso é emitido.
De acordo com JLS capítulo 5
5.5.1. Fundição de Tipo de Referência
Dado um tipo de referência de tempo de compilação S (fonte)e um tipo de referência de tempo de compilação T (destino), existe uma conversão de conversão de S para T se nenhum erro de tempo de compilação ocorrer devido às seguintes regras. Se T for um tipo de interface:
Se S não for uma classe final (§8.1.1), então, se existe um supertipo X de T, e um supertipo Y de S, de tal forma que X e Y são tipos parametrizados comprovadamente distintos, e que os apagamentos de X e Y são iguais, um erro em tempo de compilação ocorre.
Caso contrário, o elenco é sempre válido no momento da compilação (porque mesmo que S não implemente T, uma subclasse de S poderia).
Se S for uma classe final (§8.1.1), então S deve implementar T, ou ocorrerá um erro em tempo de compilação.
O seguinte código compila:
interface Roamable{}
class Phone {}
class Tablet extends Phone implements Roamable {
Roamable var = (Roamable)new Phone(); // Compiles
}
1 para resposta № 2
A resposta seria 4
Como
1 is incorrect(explanation --> 4)
2 is incorrect syntax
3 is incorrect typecast.
Observe que resposta 3 é válido contanto que seja apenas sobre compilação. Quando você diz que tem uma instância de Phone
classe em que você pode digitar cast Tablet
(Semelhante a você pode lançar Object
para String
). E desde Tablet
implementa Roamable
você pode muito bem usar um Roamable
referência para referenciá-lo. Problem will occur at runtime
Enquanto o Object
é realmente do tipo Phone
.
Este é apenas um dos padrões de ligação (no contexto atual) que permite uma compilação bem-sucedida. Mas, como Bohemian mencionou em sua resposta em geral
Se estivermos fazendo um typecasting de uma referência de tempo de compilação S (não final) para a referência de tempo de compilação T, então a compilação será bem-sucedida como
even if S does not implement T, a subclass of S might
. Se S for uma classe final, então S deve implementar T, ou ocorrerá um erro em tempo de compilação.
Na verdade, não há necessidade de Tablet
classe estendendo Phone
classe em tudo. Contanto que a classe Phone seja not final
a compilação será bem sucedida
interface Roamable{}
class Phone {}
class Tablet implements Roamable {
Roamable var = (Roamable)new Phone(); // Compiles
}