/ / Casting Java resultando em erro de tempo de execução em vez de erro de compilação - java

Casting de Java resultando em erro de tempo de execução em vez de erro de compilação - java

O trecho de código a seguir resultará em um tempo de execução:

class Vehicle {
public void printSound() {
System.out.print("vehicle");
}
}

class Car extends Vehicle {
public void printSound() {
System.out.print("car");
}
}

class Bike extends Vehicle {
public void printSound() {
System.out.print("bike");
}
}

public class Test {
public static void main(String[] args) {
Vehicle v = new Car();
Bike b = (Bike) v;

v.printSound();
b.printSound();
}
}

Minha pergunta é: por que isso resulta em um erro de tempo de execução, mas não em um erro de compilação? O compilador não deve saber que "v" já é um "carro" e não pode ser lançado em uma "bicicleta"?

Respostas:

9 para resposta № 1

Em teoria, seria possível para um compilador dizer a si mesmo: "v é variável local, que é designada para ser um Car. Em nenhum momento antes da tentativa de conversão para Bike muda seu valor, e não há como Car para ser lançado com sucesso para Bike. Portanto, isso é um erro ".

No entanto, eu não conheço nenhum compilador Java que façaessa análise para você. Realmente só vale a pena no mais simples dos casos. Em vez disso, o comportamento é que o compilador vê o elenco e raciocina que é possível lançar um Vehicle para um Bikee assim é permitido.

Em geral, isso é o que um elenco significa: Ele diz ao compilador que mesmo que esta atribuição possa falhar, você tem certeza de que ela não irá. Em troca de permitir que o código compile, você assume o risco de uma exceção de tempo de execução.


4 para resposta № 2

Casting da superclasse pode funcionar, por isso é permitido (durante a compilação). Casting de uma classe totalmente diferente não é permitido, por exemplo:

Integer a = 1;
String b = (String)a; // compile error
String b = (String)(Object)a; // runtime error

3 para resposta № 3

Para

R r = /* some code to initialize "r" */
T t = (T) r;

o Especificação da linguagem Java diz:

Se R for uma classe comum (não uma classe de array):

  • Se T é um tipo de classe, então R deve ser a mesma classe que T ou uma subclasse de T, ou uma exceção de tempo de execução é lançada.
  • Se T é um tipo de interface, então R deve implementar a interface T ou uma exceção de tempo de execução é lançada.
  • Se T for um tipo de matriz, será lançada uma exceção de tempo de execução.

1 para resposta № 4

Tipo de conversão de objeto ocorre em tempo de execução para que o compilador não o reconheça


0 para a resposta № 5

Não. v é um Vehicle e pode ser possível lançá-lo para Bike. Não é tarefa do compilador descobrir os tipos reais de tempo de execução de cada objeto (especialmente porque às vezes isso é impossível).


0 para a resposta № 6

A semântica do Java diz que isso deve resultarem um erro de tempo de execução. Neste caso, é possível olhar para o código e ver que ele definitivamente lançará um erro em tempo de execução, mas como o compilador sabe que um ClassCastException não é o que você queria?

Editores como IntelliJ e Eclipse podem (e fazem) notar esses tipos de erros e avisá-los sobre eles, mas as regras do Java dizem que este é um código legítimo que deve ser compilado.


0 para resposta № 7

Este é um erro de tempo de execução porque você já definiu a variável v como um Car. Você não pode converter Car para Bike.

O compilador não verificará este tipo de atribuição de valor porque os compiladores em geral não verificam a semântica.