No he estado en una situación en la que un error del compilador causado por estas palabras clave me hubiera salvado de un error.
No es tanto para salvar a los autores de aplicaciones de los errores como para permitir que los autores de la biblioteca decidan qué partes de su implementación se comprometen a mantener.
Si tengo una biblioteca
class C {
public void foo() { ... }
private void fooHelper() { /* lots of complex code */ }
}
Es posible que desee reemplazar foo
la implementación y posiblemente cambiar fooHelper
de manera radical. Si un grupo de personas ha decidido usarlo a fooHelper
pesar de todas las advertencias en mi documentación, es posible que no pueda hacerlo.
private
permite a los autores de bibliotecas dividir las bibliotecas en métodos de tamaño manejable (y private
clases auxiliares) sin temor a que se vean obligados a mantener esos detalles internos durante años.
¿Qué haría que valiera la pena para el compilador forzar el ocultamiento de información?
En una nota al margen, en Java private
no se aplica por el compilador, sino por el verificador de bytecode de Java .
¿Puede la reflexión anular este mecanismo? ¿Qué haría que valiera la pena para el compilador forzar el ocultamiento de información?
En Java, no solo la reflexión puede anular este mecanismo. Hay dos tipos de private
en Java. El tipo de private
eso evita que una clase externa acceda a los private
miembros de otra clase externa que es verificada por el verificador de bytecode, pero también private
es utilizada por una clase interna a través de un método de acceso sintético privado de paquete como en
public class C {
private int i = 42;
public class B {
public void incr() { ++i; }
}
}
Como la clase B
(realmente llamada C$B
) usa i
, el compilador crea un método B
de acceso sintético que permite acceder C.i
de una manera que supera el verificador de bytecode. Desafortunadamente, dado ClassLoader
que le permite crear una clase a partir de una byte[]
, es bastante sencillo llegar a las partes privadas que se C
han expuesto a las clases internas creando una nueva clase en C
el paquete que es posible si C
el jar no se ha sellado.
La private
aplicación adecuada requiere coordinación entre los cargadores de clases, el verificador de bytecode y la política de seguridad que puede evitar el acceso reflexivo a los privados.
¿Se puede usar para asegurar que el estado secreto de una clase no sea atacado?
Si. La "descomposición segura" es posible cuando los programadores pueden colaborar mientras cada uno preserva las propiedades de seguridad de sus módulos. No tengo que confiar en el autor de otro módulo de código para no violar las propiedades de seguridad de mi módulo.
Los lenguajes de Capacidades de Objetos como Joe-E usan la ocultación de información y otros medios para hacer posible la descomposición segura:
Joe-E es un subconjunto del lenguaje de programación Java diseñado para admitir una programación segura de acuerdo con la disciplina de capacidad de objeto. Joe-E está destinado a facilitar la construcción de sistemas seguros, así como a facilitar las revisiones de seguridad de los sistemas construidos en Joe-E.
El documento vinculado desde esa página ofrece un ejemplo de cómo la private
aplicación hace posible la descomposición segura.
Proporcionando encapsulación segura.
Figura 1. Una instalación de registro de solo agregar.
public final class Log {
private final StringBuilder content;
public Log() {
content = new StringBuilder();
}
public void write(String s) {
content.append(s);
}
}
Considere la figura 1, que ilustra cómo se podría construir una instalación de registro de solo agregar. Siempre que el resto del programa esté escrito en Joe-E, un revisor de código puede estar seguro de que las entradas de registro solo se pueden agregar y no se pueden modificar o eliminar. Esta revisión es práctica porque solo requiere la inspección de la Log
clase y no requiere la revisión de ningún otro código. En consecuencia, verificar esta propiedad solo requiere un razonamiento local sobre el código de registro.