2013-09-02 14 views
30

ho una classe denominata A in package1 e un'altra classe denominata C in package2. Classe C estende la classe A.intesa di Java

A ha una variabile di istanza che viene dichiarata in questo modo:

protected int protectedInt = 1; 

Ecco il codice per la classe A

package package1; 

public class A { 

    public int publicInt = 1; 
    private int privateInt = 1; 
    int defaultInt = 1; 
    protected int protectedInt = 1; 

} 

E qui è il codice per la classe C :

package package2; 
import package1.A; 

public class C extends A{ 

    public void go(){ 
     //remember the import statement 
     A a = new A(); 
     System.out.println(a.publicInt); 
     System.out.println(a.protectedInt); 

    } 
} 

Eclipse sottolinea l'ultima riga in C.go() e dice "A.protectedInt" non è visibile. Sembra che questo sia in conflitto con la definizione della parola chiave "protetta", fornita nella documentazione di Oracle.

Il modificatore protetto specifica che è possibile accedere al membro solo all'interno del proprio pacchetto (come con package-private) e, inoltre, da una sottoclasse della relativa classe in un altro pacchetto.

Cosa sta succedendo qui?

risposta

31

Cosa sta succedendo qui?

Hai frainteso il significato di protected. È possibile accedere ai membri protetti dichiarati in A dall'interno di C, ma solo per le istanze di C o sottoclassi di C. Vedere section 6.6.2 of the JLS per i dettagli di accesso protetto. In particolare:

Sia C la classe in cui è dichiarato un membro protetto. L'accesso è consentito solo all'interno del corpo di una sottoclasse S di C.

Inoltre, se Id indica un campo di istanza o un metodo esempio, allora:

  • [...]

  • Se l'accesso è tramite un'espressione di accesso al campo E.Id, dove E è un'espressione primaria, o tramite un'espressione di richiamo del metodo E.Id (...), Dove E è un'espressione primaria, l'accesso è consentito se e solo se il tipo di e è S o una sottoclasse di S.

(l'enfasi è mia.)

Quindi questo codice andrebbe bene:

C c = new C(); 
System.out.println(c.publicInt); 
System.out.println(c.protectedInt); 
+0

In tal caso, perché java ha un modificatore protetto? Non sarebbe sufficiente rendere l'estensione A C sufficiente a renderlo non visibile a C? – mahela007

+2

@ mahela007: Non senza che sia 'protected', no - se fosse visibilità predefinita (pacchetto) o' private', non sarebbe visibile. –

+0

Hmm ... La parte enfatizzata nella tua risposta dice "l'accesso è permesso se E è una sottoclasse se S" .. Ma nel mio esempio, C è una sottoclasse di A..e non riesco ancora ad accedere alla variabile protetta. – mahela007

10

Dal C eredita A, C può usare direttamente la protected variabile A come qui di seguito

public class C extends A{ 

    public void go(){ 

     System.out.println(protectedInt); 

    } 
} 

Secondo il vostro codice, stai creando un'istanza di A e accedendo alla variabile protectedtramite tale istanza, che viola la regola di java - Una variabile protetta non è visibile all'esterno del pacchetto

+1

Il codice originale funzionerà se entrambe le classi si trovano nello stesso pacchetto. – blgt

+0

Ho letto questo dal documento JLC che Jon skeet ha pubblicato."È possibile accedere a un membro o costruttore protetto di un oggetto dall'esterno del pacchetto in cui è dichiarato solo dal codice responsabile dell'implementazione di tale oggetto." Come può il codice che "implementa un oggetto" essere al di fuori del pacchetto dello stesso oggetto? – mahela007

+0

@ mahela007: guarda il tuo esempio - i membri sono * dichiarati * in 'A', che è in un diverso pacchetto alla classe' C', che è ciò che "implementa" un oggetto di tipo 'C'. –

2
public void go(){ 
     //remember the import statement 
     A a = new A(); 
     System.out.println(a.publicInt); 
     System.out.println(a.protectedInt); 

    } 

Quando si sta facendo A a = new A(); e a.protectedInt si tenta di accedere a membro protetto di A che è illegale secondo il java standard

Invece è possibile eseguire direttamente this.protectedInt.

1

Non è necessario creare un'istanza di classe di protezione all'interno della classe Protection2. È possibile chiamare direttamente la variabile protetta senza creare un'istanza della classe Protection. Perché la classe Protection2 estende la classe di protezione. Così variabile automaticamente ereditata dalla sottoclasse.

Prova con codice qui sotto:

public class Protection2 extends Protection{ 
Protection2() 
{System.out.println("n_pro = " +n_pro); 
}} 
1

Entro lo stesso pacchetto in cui viene dichiarato il membro protetto, è consentito l'accesso:

package package1; 

public class C extends A{ 
    public void go(){ 
     A a = new A(); 
     System.out.println(a.protectedInt); // got printed 
     C c = new C(); 
     System.out.println(c.protectedInt); // got printed as well 
    } 
} 

di fuori del pacchetto in cui viene dichiarato il membro protetto, l'accesso è permesso se e solo se dal codice che è responsabile per l'attuazione di tale oggetto. In questo caso, C è responsabile dell'implementazione di tale oggetto, in modo che possa accedere al protetto.

package package2; 

public class C extends A{ 
    public void go(){ 
     A a = new A(); 
     System.out.println(a.protectedInt); // compiler complains 
     C c = new C(); 
     System.out.println(c.protectedInt); // got printed 
    } 
}