protegido
Hablemos sobre problemas de derechos de acceso protegidos. Vea el ejemplo 1 a continuación:
Test.java
clase myObject {} public class Test {public static void main (string [] args) {myObject obj = new myObject (); obj.clone (); // Error de compilación. }} El clon del método del objeto tipo no es visible.
Ya hemos entendido que Object.Clone () es un método protegido. Esto muestra que se puede acceder al método mediante subclases del mismo paquete (java.lang) e IT (java.lang.object). Aquí está la clase MyObject (la herencia predeterminada de java.lang.object).
Del mismo modo, la prueba también es una subclase de java.lang.object. Sin embargo, no se puede acceder al método protegido de otra subclase en una subclase, aunque las dos subclases heredan de la misma clase principal.
Veamos el ejemplo 2 nuevamente:
Test2.java
clase myObject2 {Protected Object clone () lanza ClonenotsupportedException {return super.clone (); }} public class test2 {public static void main (string [] args) lanza clonenotsupportedException {myObject2 obj = new myObject2 (); obj.clone (); // compilar OK. }} Aquí, anulamos el método Clone () de la clase principal en la clase MyObject2, llame al método Clone () en otra clase test2 y compilar y pasar.
La razón de la compilación es obvia. Cuando anula el método Clone () en la clase MyObject2, la clase MyObject2 y la clase Test2 están bajo el mismo paquete, por lo que este método protegido es visible para la clase Test2.
En este punto, recordamos las declaraciones en el Capítulo 2.2 en los artículos de copia poco profunda y profunda en Java, ② Sobrescribir el método Clone () de la clase base en la clase derivada y declararlo como público. Ahora entiendo la razón de esta oración (para habilitar otras clases para llamar al método Clone () de esta clase, después de sobrecargar, el atributo del método Clone () debe establecerse en público).
Echemos un vistazo al ejemplo 3:
Test3.java
Paquete 1Class myObject3 {Protected Object clone () lanza ClonenotsupportedException {return super.clone (); }} paquete 2Public Class test3 extiende myObject3 {public static void main (string args []) {myObject3 obj = new myObject3 (); obj.clone (); // Error de compilación. Test3 tobj = new test3 (); tobj.clone (); // complie ok. }} Aquí uso la clase Test3 para heredar myObject3. Tenga en cuenta que estas dos clases tienen paquetes diferentes, de lo contrario, es el caso del ejemplo 2. En la clase Test3, llame al método Clone () de la instancia TOBJ de la clase Test3 y compilar y pasar. Y también llamar al método clone () de la instancia obj de la clase myobject3 se llama, ¡y el error de compilación!
Resultados inesperados, ¿no se puede acceder al método protegido mediante clases hereditarias?
Debe estar claro que la clase test3 hereda la clase myObject3 (incluido su método de clon), por lo que puede llamar a su propio método de clon en clase test3. Sin embargo, el método protegido de la clase myObject3 es invisible para su test3 de subclase BUN diferente3.
Aquí hay otro pasaje de "Java en pocas palabras":
El acceso protegido requiere un poco más de trabajo. Supongamos que la clase A declara un campo X protegido y se extiende por una clase B, que se define en un paquete diferente (este último punto es importante). Clase B hereda el campo X protegido, y su código puede acceder a ese campo en la instancia actual de B o en cualquier otra instancia de B que el código pueda consultar. ¡Sin embargo, esto no significa que el código de la clase B pueda comenzar a leer los campos protegidos de instancias arbitrarias de A! Si un objeto es una instancia de A pero no es una instancia de B, sus campos obviamente no son heredados por B, y el Código de Clase B no puede leerlos.
Por cierto, muchos libros de Java en China generalmente se describen de esta manera al introducir permisos de acceso (varias formas y contenido consistente):
Control de acceso del método:
estático
1. Palabra clave estática (recuerda estos primero, luego léelo)
1) Los métodos estáticos y las variables estáticas son objetos que pertenecen a una determinada clase, pero no a una clase.
2) Las referencias a métodos estáticos y variables estáticas se hacen referencia directamente a través de los nombres de clases.
3) Los métodos no estatales y las variables de miembros no estatales no pueden llamarse en métodos estáticos. De lo contrario, está bien.
4) Las variables estáticas son similares a las variables globales en otros idiomas en algún programa, y se puede acceder fuera de la clase si no son privadas.
2. Cuando usar estática
Cuando creamos una instancia de una clase (objeto), generalmente usamos el nuevo método para que se cree el espacio de datos de esta clase y se pueda llamar a sus métodos.
Sin embargo, a veces esperamos que, aunque se puede crear una clase con N objetos (obviamente, el espacio de datos de estos N objetos es diferente), algunos de los datos de estos N objetos son los mismos, es decir, independientemente de cuántas instancias tenga la clase, los datos tienen una copia de memoria de estas instancias (ver Ejemplo 1). Este es el caso con variables estáticas.
Otro escenario es que desea que un método no esté asociado con ningún objeto de la clase que lo contenga. Es decir, este método se puede llamar incluso si el objeto no se crea. Un uso importante del método estático es llamarlo sin crear ningún objeto (ver Ejemplo 2). Este es el caso con un método estático.
También hay un uso especial en las clases internas. Por lo general, no se permite que una clase normal se declare estática, solo una clase interna puede hacerlo. En este momento, esta clase interna declarada como estática se puede usar directamente como una clase normal sin la necesidad de instalar una clase externa (ver Ejemplo 3). Este es el caso con las clases estáticas.
Ejemplo 1
clase pública tstatic {static int i; public tstatic () {i = 4; } public tstatic (int j) {i = j; } public static void main (string args []) {system.out.println (tstatic.i); Tstatic t = nuevo tstatic (5); // Declarar la referencia del objeto y instanciarla. En este momento i = 5 System.out.println (ti); Tstatic tt = new tstatic (); // Declarar la referencia del objeto y instanciarla. En este momento i = 4 System.out.println (ti); System.out.println (tt.i); System.out.println (ti); }}
resultado:
05444
La variable estática se crea cuando se carga la clase. Mientras exista la clase, existe la variable estática. Deben ser inicializados cuando se definen. En el ejemplo anterior, no se inicializa, por lo que se obtendrá el valor inicial predeterminado 0. La variable estática solo se puede inicializar una vez, y la variable estática solo acepta la última inicialización.
De hecho, esto sigue siendo un problema con múltiples instancias que comparten una variable estática.
Ejemplo 2
No declarado como estático
clase clase {int b; public void ex1 () {} classb classb {void ex2 () {int i; ClassA a = new ClassA (); i = AB; // aquí acceso a la variable de miembro b a.ex1 () a través de la referencia del objeto; // aquí acceso a la función miembro EX1 a través de la referencia del objeto}}}
Declarado como estático
clase classA {static int b; static void ex1 () {}} classb classb {void ex2 () {int i; i = classa.b; // aquí acceso a la variable de miembro b classa.ex1 () a través del nombre de clase; // aquí acceso a la función miembro EX1 a través del nombre de la clase}} Cuando se utilice métodos estáticos, tenga cuidado de que los métodos no estatales no se puedan llamar en métodos estáticos y variables de miembros no estáticos de referencia (esto o Super no se puede hacer referencia de ninguna manera en los métodos estáticos). La razón es muy simple. Para las cosas estáticas, cuando el JVM carga la clase, abre estos espacios estáticos en la memoria (por lo que puede referirse directamente a través del nombre de la clase), y en este momento, la clase donde los métodos y variables miembros no estatales se encuentran no se ha instanciado.
Entonces, si desea utilizar métodos y variables de miembros no estatales, puede instanciar directamente la clase donde el método o la variable miembro se encuentra en el método estático. Así es como lo hace Public Static Void Main.
Ejemplo 3
public class staticCls {public static void main (string [] args) {ourtercls.innerCls oi = new ourcls.innerCls (); // No hay necesidad de nuevos exteriores antes de esto}} class Outercls {public static class innercls {innercls () {system.out.println ("innercls"); }}}
resultado:
Interno
3. Inicialización estática
Las variables definidas por Static tendrán prioridad sobre cualquier otra variable no estática, independientemente del orden en que aparezcan. Se utiliza un bloque de código estático (seguido de un código) para realizar una inicialización de variable estática explícita. Este código solo se inicializará una vez y cuando la clase se cargue por primera vez. Vea el ejemplo a continuación.
valor de clase {static int c = 0; Valor () {c = 15; } Valor (int i) {c = i; } static void inc () {c ++; }} class Count {public static void prt (String s) {System.out.println (s); } Valor v = nuevo valor (10); valor estático v1, v2; static {prt ("en el bloque estático de las cal. v1 = nuevo valor (27); Prt ("En el bloque estático de las cal. v2 = nuevo valor (); Prt ("En el bloque estático de las cal. }} public class tstaticblock {public static void main (string [] args) {count ct = new Count (); Count.prt ("en la principal:"); Count.prt ("ct.c =" + ct.vc); Count.prt ("v1.c =" + count.v1.c + "v2.c =" + count.v2.c); Count.v1.inc (); Count.prt ("v1.c =" + count.v1.c + "v2.c =" + count.v2.c); Count.prt ("ct.c =" + ct.vc); }}
resultado:
En el bloque estático del recuento de calss v1.c = 0 v2.c = 0in el bloque estático del recuento de calss v1.c = 27 v2.c = 27 en el bloque estático del recuento de calss v1.c = 15 v2.c = 15 en el principal: ct.c = 10v1.c = 10 v2.c = 10v1.c = 11 v2.c = 11ct.c = 11
Ya sea V, V1 o V2, las variables de los miembros en las que operan son la misma variable estática c.
En el recuento de clases, V1 y V2 (valor estático V1, V2;), luego inicialice el bloque de código estático (estático {}) y finalmente inicialice V.