2010-10-09 12 views
6

W poniższym kodzie typem x jest I (chociaż x również implementuje J, ale nie jest to znane w czasie kompilacji), dlaczego więc kod w punkcie (1) nie powoduje błędu czasu kompilacji. Ponieważ w czasie kompilacji brany jest pod uwagę tylko typ odniesienia.Dlaczego ten kod wystąpienia działa i nie powoduje błędu czasu kompilacji?

public class MyClass { 
    public static void main(String[] args) { 
     I x = new D(); 
     if (x instanceof J) //(1) 
      System.out.println("J"); 
    } 
} 

interface I {} 

interface J {} 

class C implements I {} 

class D extends C implements J {} 
+1

Nota boczna - proszę nie zapomnieć dodać znacznika dla języka. Dodałem "java" dla ciebie. – EboMike

+0

Przepraszam, powinienem mieć – user439526

Odpowiedz

12

instanceof służy do określania typu obiektu podczas runtime. Próbujesz ustalić, czy x jest naprawdę obiektem typu J, gdy program jest uruchomiony, więc kompiluje.

Czy myślisz, że powinno to spowodować błąd podczas kompilacji, ponieważ uważasz, że kompilator nie zna typu x?

Edit

Jak Kirk Woll skomentował (dzięki Kirk Woll!), Jeśli były sprawdzenie czy x jest instanceof konkretna klasa, a kompilator może określić x „s typ, a następnie dostaniesz błąd podczas kompilacji.

Z języka Java Specification:

Jeżeli odlew RelationalExpression do ReferenceType zostanie odrzucony jako błąd kompilacji, a następnie wyrażenie relacyjne instanceof również produkuje błąd kompilacji. W takiej sytuacji wynik instancji wyrażenia nigdy nie byłby prawdziwy.

Jako przykład tego:

import java.io.Serializable; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.io.ObjectInputStream; 

class SerializableClass implements Serializable 
{ 
    private writeObject(ObjectOutputStream out) {} 
    private readObject(ObjectInputStream in) {} 
} 

public class DerivedSerializableClass extends SerializableClass 
{ 
    public static void main(String[] args) 
    { 
     DerivedSerializableClass dsc = new DerivedSerializableClass(); 

     if (dsc instanceof DerivedSerializableClass) {} // fine 
     if (dsc instanceof Serializable) {} // fine because check is done at runtime 
     if (dsc instanceof String) {} // error because compiler knows dsc has no derivation from String in the hierarchy 

     Object o = (Object)dsc; 
     if (o instanceof DerivedSerializableClass) {} // fine because you made it Object, so runtime determination is necessary 
    } 
} 
+1

+1, a jeśli to * nie był * operatorem uruchomieniowym, co na tym byłby sens? Użyte w nim wyrażenia "if" nie miałyby sensu. –

+0

Cóż z tego, co przeczytałem, jest wstępna kontrola czasu kompilacji podczas korzystania z operatora instanceof, który określa, czy źródło i miejsce docelowe mają relację podtypu i nadtypu. Następnie rzeczywisty obiekt źródła służy do określenia, czy źródło jest podtypem typu miejsca docelowego. – user439526

+1

Proszę poprawić moje zrozumienie, jak to powinno działać. Więc w tym kodzie chociaż obiekt odwołujący się do x jest podtypem J, ale nie ma związku między I i J. Więc ponieważ x jest typu I w powyższym kodzie, to znaczy I x = nowy D() ;, powinien grać rola w czasie kompilacji? – user439526

2

instanceof jest operatorem run-time, a nie w czasie kompilacji, więc to jest oceniane przy użyciu rzeczywisty typ obiektu, którego dotyczy odwołanie.

+0

Ale może powodować błędy kompilacji. .. – EJP

+0

Tak, jeśli dostanie statyczne dane wejściowe (tj. Klasy zamiast referencji). Powinienem edytować moją odpowiedź, chociaż Kuropenguin już udzielił wyczerpującej odpowiedzi, więc to jest dyskusja. – EboMike

Powiązane problemy