Visibilità privata o predefinita per i membri "file-private"?

1

Ho una classe come questa

public final class Outer {
    static final class Inner {
        /* Used in the package. */
        void f() {...}

        /* Used in Outer. */
        WHATEVER void g() {...}

        /* Used in Inner only. */
        private void h() {...}
    }
}

In Java, ogni membro definito nello stesso file può accedere a tutti gli altri membri (*), quindi g potrebbe essere private . L'alternativa è la visibilità predefinita.

L'ovvio vantaggio di private è che è la visibilità minima possibile. Usandolo puoi essere certo che non ci sono utenti di g al di fuori del file.

Ci sono anche degli svantaggi:

Poiché tale accesso è consentito da Java ma non dalla JVM, viene creato un metodo bridge, che viene quindi visualizzato in stacktraces e nel debugger. Inoltre, rallentano il programma, ma questo è trascurabile in quanto di solito si inline comunque.

Ciò che mi turba di più è che con g è private , non riesco a vedere se è destinato ad essere usato al di fuori di Inner o se è "veramente privato" (come h ).

Le mie domande sono

  • qual è la procedura migliore?
  • c'è un'annotazione per un caso del genere (e viene riconosciuto da uno strumento)?
  • come si comportano le altre lingue?

(*) Come affermato nella risposta di Timothy Truckle, questo è vero solo supponendo che non impacchettiate altre classi non pubbliche nello stesso file (cosa che praticamente nessuno fa da quando le classi nidificate sono state introdotte in Java 1.1).

    
posta maaartinus 10.06.2017 - 21:00
fonte

2 risposte

4

Solo per i rcords:

In Java, every member defined in the same file can access every other member,

Questa affermazione è sbagliata così com'è.

È vero (e probabilmente lo hai inteso) solo per classi interne .

Ma puoi definire diverse classi all'interno dello stesso file (dove solo una può essere public , le altre devono essere pacchetto privato

E questa potrebbe essere la soluzione per il tuo problema: sposta la classe Inner fuori dalla classe Outer all'interno dello stesso file:

public final class Outer {
  public void somMethod(){
    new Inner().f(); // OK
    new Inner().h(); // compile error
  }
}
static final class Inner {
    /* Used in the package. */
    void f() {...}

    /* Used in Outer. */
    void g() {...}

    /* Used in Inner only. */
    private void h() {...}
}

Ma Java non ha possibilità di limitare l'accesso a "solo nello stesso file".

    
risposta data 10.06.2017 - 23:20
fonte
2

In Java le classi esterne hanno pieno accesso a tutti gli elementi delle Classi Interiori così come tutte le classi interne hanno pieno accesso all'elemento delle classi esterne.

I modificatori di accesso diventano importanti quando si deriva da una classe interna

public class Outer {

    static class A {
        void f() {}

        public void g() {}

        private void h() {}

    }

    static  class B extends A {

        public void g() {
            f(); // OK 
            h(); // Compiler error 
        }
    }
}

O quando provi ad accedere agli elementi della classe Inner dall'esterno di Outer

public class Foo {
   public static void main(String ... args) {
       new Outer.A().f(); // OK if in the same package  
       new Outer.A().g(); // OK
       new Outer.A().h(); // Compiler error.
   }
}

Se vuoi assicurarti che la tua classe esterna possa solo accedere a elementi / metodi "pubblici" della tua classe interna, definisci un'interfaccia.

public class Outer {
    private interface MySuperInterface {
         void g();
    }

    static class A implements MySuperInterface {
        public void g();

    }

    void foo() {
        MySuperInterface x = new A();
        x.g();
    }

}

Questi vincoli di architettura possono essere applicati da strumenti / framework come Java Modeling Language (JML) o OVal

    
risposta data 11.06.2017 - 12:43
fonte

Leggi altre domande sui tag