/ / Java lançando um objeto para uma interface que não está implementada - java, interface, lançando

Java lançando um objeto para uma interface que não está implementada - java, interface, casting

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:

  1. Roamable var = new Phone();
  2. Roamable var = (Roamable)Phone();
  3. Roamable var = (Roamable)new Phone();
  4. Porque interface Roamable e classe Phone não estão relacionados, uma variável de referência do tipo Roamable não pode se referir a um objeto de classe Phone.

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 № 1

A 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
}