Non sono stato in una situazione in cui un errore del compilatore causato da queste parole chiave mi avrebbe salvato da un bug.
Non è tanto per salvare gli autori delle applicazioni dai bug quanto per consentire agli autori delle biblioteche di decidere quali parti della loro implementazione si stanno impegnando a mantenere.
Se ho una biblioteca
class C {
public void foo() { ... }
private void fooHelper() { /* lots of complex code */ }
}
Potrei voler sostituire foo
l'implementazione e possibilmente cambiare fooHelper
in modo radicale. Se un gruppo di persone ha deciso di utilizzare fooHelper
nonostante tutti gli avvisi nella mia documentazione, allora potrei non essere in grado di farlo.
private
consente agli autori di biblioteche di suddividere le biblioteche in metodi di dimensioni gestibili (e private
classi di supporto) senza il timore che saranno costretti a conservare quei dettagli interni per anni.
Cosa renderebbe utile per il compilatore imporre il nascondere le informazioni?
In una nota a margine, in Java private
non viene applicato dal compilatore, ma dal verificatore bytecode Java .
La riflessione può scavalcare questo meccanismo? Cosa renderebbe utile per il compilatore imporre il nascondere le informazioni?
In Java, non solo la riflessione può sovrascrivere questo meccanismo. Esistono due tipi di private
in Java. Il tipo di private
ciò impedisce a una classe esterna di accedere ai private
membri di un'altra classe esterna che viene verificata dal verificatore bytecode, ma è anche private
usata da una classe interna tramite un metodo di accesso sintetico pacchetto-privato come in
public class C {
private int i = 42;
public class B {
public void incr() { ++i; }
}
}
Poiché la classe B
(realmente denominata C$B
) utilizza i
, il compilatore crea un metodo B
di accesso sintetico che consente di accedere C.i
in un modo che supera il verificatore bytecode. Sfortunatamente, poiché ClassLoader
ti permette di creare una classe da a byte[]
, è abbastanza semplice arrivare ai privati che si C
sono esposti alle classi interne creando una nuova classe nel C
pacchetto che è possibile seC
il vaso non è stato sigillato.
Una corretta private
applicazione richiede il coordinamento tra i classloader, il verificatore di bytecode e la politica di sicurezza che può impedire l'accesso riflessivo ai privati.
Può essere usato per proteggere l'attacco di uno stato segreto di una classe?
Sì. La "decomposizione sicura" è possibile quando i programmatori possono collaborare preservando al contempo le proprietà di sicurezza dei loro moduli - Non devo fidarmi dell'autore di un altro modulo di codice per non violare le proprietà di sicurezza del mio modulo.
Linguaggi di funzionalità dell'oggetto come Joe-E utilizzano il nascondimento delle informazioni e altri mezzi per rendere possibile la decomposizione sicura:
Joe-E è un sottoinsieme del linguaggio di programmazione Java progettato per supportare la programmazione sicura in base alla disciplina della capacità dell'oggetto. Joe-E ha lo scopo di facilitare la costruzione di sistemi sicuri, nonché di facilitare le revisioni di sicurezza dei sistemi costruiti in Joe-E.
Il documento collegato da quella pagina fornisce un esempio di come l' private
applicazione rende possibile la decomposizione sicura.
Fornire incapsulamento sicuro.
Figura 1. Una funzione di registrazione solo append.
public final class Log {
private final StringBuilder content;
public Log() {
content = new StringBuilder();
}
public void write(String s) {
content.append(s);
}
}
Si consideri la Fig. 1, che illustra come si potrebbe costruire una funzione di log di sola aggiunta. A condizione che il resto del programma sia scritto in Joe-E, un revisore del codice può essere certo che le voci del registro possono essere solo aggiunte e non possono essere modificate o rimosse. Questa recensione è pratica perché richiede solo l'ispezione della Log
classe e non richiede la revisione di nessun altro codice. Di conseguenza, la verifica di questa proprietà richiede solo un ragionamento locale sul codice di registrazione.