[Java] aplicación y análisis de palabras clave estáticas

1. El propósito de la palabra clave estática

Hay un pasaje de este tipo en la página P86 de "Pensamiento de programación en Java":

"Un método estático es un método sin esto. No puedes llamar a un método no estático dentro de un método estático, y viceversa. Y puedes llamar al método estático solo a través de la clase sin crear ningún objeto. Esto es en realidad El objetivo principal del método estático ".

Aunque este pasaje solo ilustra las características especiales del método estático, puede ver la función básica de la palabra clave estática. En resumen, una descripción de una oración es:

Es conveniente llamar (método / variable) sin crear un objeto.

Obviamente, el método o variable modificada por la palabra clave estática no necesita depender del objeto para acceder, siempre que la clase esté cargada, se puede acceder a ella a través del nombre de la clase.

Static se puede utilizar para modificar los métodos de miembro y las variables de miembro de una clase.Además, puede escribir bloques de código estático para optimizar el rendimiento del programa.

1) método estático

Los métodos estáticos generalmente se denominan métodos estáticos. Debido a que los métodos estáticos no dependen de ningún objeto al que se acceda, no existe esto para los métodos estáticos, porque no está adjunto a ningún objeto. Como no hay ningún objeto, no se puede mencionar. esto afuera. Y debido a esta característica, no se puede acceder a las variables miembro no estáticas y a los métodos miembro no estáticos de la clase en métodos estáticos, porque los métodos / variables miembros no estáticos deben depender de objetos específicos para poder ser llamados.

Pero debe tenerse en cuenta que, aunque no se puede acceder a métodos de miembros no estáticos y variables de miembros no estáticos en métodos estáticos, se puede acceder a métodos / variables de miembros estáticos en métodos de miembros no estáticos.

Inserte la descripción de la imagen aquí

2) variable estática

Las variables estáticas también se denominan variables estáticas. La diferencia entre las variables estáticas y las variables no estáticas es que las variables estáticas son compartidas por todos los objetos, y solo hay una copia en la memoria, que se inicializará si y solo cuando la clase se cargue por primera vez. Las variables no estáticas son propiedad del objeto y se inicializan cuando se crea el objeto. Hay múltiples copias, y las copias propiedad de cada objeto no se afectan entre sí.

El orden de inicialización de las variables miembro estáticas se inicializa en el orden definido.

3) bloque de código estático

Otra función clave de la palabra clave estática es formar bloques de código estático para optimizar el rendimiento del programa. El bloque estático se puede colocar en cualquier lugar de la clase y puede haber varios bloques estáticos en la clase. Cuando la clase se carga por primera vez, cada bloque estático se ejecutará en el orden del bloque estático y solo se ejecutará una vez.

Resumen de las características del bloque de código estático:

  • Cuando esta clase se usa por primera vez, el bloque de código estático se ejecuta solo una vez;
  • El contenido estático siempre tiene prioridad sobre el contenido no estático, por lo que los bloques de código estático se ejecutan antes que los métodos de construcción;
  • Uso típico de bloques de código estático: para asignar valores a variables miembro estáticas a la vez.

La razón por la que el bloque estático se puede usar para optimizar el rendimiento del programa es por sus características: solo se ejecutará una vez cuando se cargue la clase. Veamos un ejemplo:

class Person{
    
    
    private Date birthDate;
     
    public Person(Date birthDate) {
    
    
        this.birthDate = birthDate;
    }
     
    boolean isBornBoomer() {
    
    
        Date startDate = Date.valueOf("1946");
        Date endDate = Date.valueOf("1964");
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

isBornBoomer se usa para determinar si esta persona nació entre 1946 y 1964, y cada vez que se llama a isBornBoomer, se generan dos objetos, startDate y birthDate, lo que resulta en una pérdida de espacio. Sería más eficiente si se cambiara a esto:

class Person{
    
    
    private Date birthDate;
    private static Date startDate,endDate;
    static{
    
    
        startDate = Date.valueOf("1946");
        endDate = Date.valueOf("1964");
    }
     
    public Person(Date birthDate) {
    
    
        this.birthDate = birthDate;
    }
     
    boolean isBornBoomer() {
    
    
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

Por lo tanto, en muchos casos, algunas operaciones de inicialización que solo deben realizarse una vez se colocan en el bloque de código estático.

4) La diferencia entre variables estáticas y variables miembro ordinarias

Hay cuatro diferencias principales entre las variables estáticas y las variables miembro ordinarias:

Diferencia 1: Pertenencia diferente. Las variables estáticas pertenecen a una clase, no solo a cualquier objeto; las variables miembro ordinarias pertenecen a un objeto

Diferencia 2: el área de almacenamiento es diferente. Las variables estáticas se encuentran en el área de método; las variables de miembro ordinarias se encuentran en el área del montón.

Diferencia 3: El ciclo de vida es diferente. El ciclo de vida de una variable estática es el mismo que el ciclo de vida de una clase; el ciclo de vida de una variable miembro ordinaria y el objeto al que pertenece es el mismo.

Diferencia 4: cuando el objeto es serializado (serializable), las variables estáticas serán excluidas (porque las variables estáticas pertenecen a la clase, no al objeto)

5) ¿Qué significan juntos estático y final?

Static final se utiliza para modificar variables miembro y métodos miembro, que pueden entenderse simplemente como "constantes globales".

   对于变量,表示一旦给值就不可修改,并且通过类名可以访问。

Para los métodos, significa que no se puede anular y se puede acceder directamente a través del nombre de la clase.

Preste especial atención a un problema:

Por ejemplo, las constantes modificadas por static y final, la instancia en sí no se puede cambiar, pero por ejemplo, las variables de algunos tipos de contenedor (por ejemplo, ArrayList, HashMap), la variable del contenedor en sí no se puede cambiar, pero los objetos almacenados en el contenedor se pueden modificar. Esto se usa mucho en programación.

El malentendido de la palabra clave estática

1. ¿La palabra clave estática cambiará los derechos de acceso de los miembros de la clase?

Algunos amigos principiantes confundirán la función de la palabra clave estática en java con la palabra clave estática en C / C ++. Solo hay una cosa para recordar aquí: a diferencia de static en C / C ++, la palabra clave static en Java no afecta el alcance de las variables o métodos. En Java, las únicas palabras clave que pueden afectar los permisos de acceso son privado, público y protegido (incluidos los permisos de acceso a paquetes). Mira el siguiente ejemplo para entender:

2. ¿Puede acceder a las variables miembro estáticas a través de esto?

Aunque no existe esto para los métodos estáticos, ¿se puede acceder a las variables miembro estáticas a través de esto en métodos no estáticos? Primero mire el siguiente ejemplo, ¿cuál es el resultado de este código?

public class Main {
    
      
    static int value = 33;
 
    public static void main(String[] args) throws Exception{
    
    
        new Main().printValue();
    }
 
    private void printValue(){
    
    
        int value = 3;
        System.out.println(this.value);
    }
}

Este examina principalmente la comprensión del equipo este y estático. ¿Qué significa esto? esto representa el objeto actual, entonces si se llama a printValue a través de new Main (), el objeto actual es el objeto generado a través de new Main (). El objeto disfruta de la variable estática, por lo que el valor de this.value en printValue es sin duda 33. El valor dentro del método printValue es una variable local, es imposible asociarlo con esto en absoluto, por lo que el resultado de salida es 33. Recuerde siempre una cosa aquí: aunque las variables miembro estáticas son independientes de los objetos, no significa que no se pueda acceder a ellas a través de objetos. Se puede acceder a todos los métodos estáticos y variables estáticas a través de objetos (siempre que los permisos de acceso sean suficientes).

3. ¿Puede la estática actuar sobre las variables locales?

En C / C ++, la estática puede abarcar variables locales, pero recuerde que en Java: la estática no puede modificar las variables locales. No preguntes por qué, esta es la regla de la sintaxis de Java.

3. Preguntas habituales en las entrevistas escritas

A continuación se enumeran algunas preguntas sobre palabras clave estáticas que se encuentran con frecuencia en la prueba escrita de la entrevista; solo como referencia, deje un mensaje a continuación si tiene algo que agregar.

1. ¿Cuál es el resultado del siguiente código?

public class Test extends Base{
    
    
 
    static{
    
    
        System.out.println("test static");
    }
     
    public Test(){
    
    
        System.out.println("test constructor");
    }
     
    public static void main(String[] args) {
    
    
        new Test();
    }
}
 
class Base{
    
    
     
    static{
    
    
        System.out.println("base static");
    }
     
    public Base(){
    
    
        System.out.println("base constructor");
    }
}

Salida:

base static
test static
base constructor
test constructor

En cuanto a por qué este es el resultado, no lo analicemos primero. Primero pensemos en el proceso de ejecución específico de este código. Al comienzo de la ejecución, primero debemos encontrar el método principal, porque el método principal es el punto de entrada del programa, pero antes de que se ejecute el método principal, debe La clase Test se carga primero, y cuando se carga la clase Test, se encuentra que la clase Test hereda de la clase Base, por lo que irá a cargar primero la clase Base. Cuando se carga la clase Base, se encuentra un bloque estático y se ejecuta el bloque estático. Una vez cargada la clase Base, continúe cargando la clase Test y, a continuación, busque que hay un bloque estático en la clase Test y ejecute el bloque estático. Después de cargar las clases requeridas, se ejecuta el método principal. Al ejecutar new Test () en el método principal, primero llamará al constructor de la clase principal y luego llamará a su propio constructor. Por lo tanto, aparece el resultado de salida anterior.

2. ¿Cuál es el resultado de este código?

public class Test {
    
    
    Person person = new Person("Test");
    static{
    
    
        System.out.println("test static");
    }
     
    public Test() {
    
    
        System.out.println("test constructor");
    }
     
    public static void main(String[] args) {
    
    
        new MyClass();
    }
}
 
class Person{
    
    
    static{
    
    
        System.out.println("person static");
    }
    public Person(String str) {
    
    
        System.out.println("person "+str);
    }
}
 
 
class MyClass extends Test {
    
    
    Person person = new Person("MyClass");
    static{
    
    
        System.out.println("myclass static");
    }
     
    public MyClass() {
    
    
        System.out.println("myclass constructor");
    }
}

Salida:

test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

De manera similar, pensemos en el proceso de ejecución específico de este código. Cargue la clase de prueba primero, de modo que se ejecute el bloque estático en la clase de prueba. Luego ejecute new MyClass (), y la clase MyClass aún no se ha cargado, por lo que la clase MyClass debe cargarse. Al cargar la clase MyClass, se encuentra que la clase MyClass hereda de la clase Test, pero debido a que se cargó la clase Test, solo es necesario cargar la clase MyClass y se ejecutará el bloque estático en la clase MyClass. Después de la carga, el objeto se genera a través del constructor. Cuando se genera el objeto, las variables miembro de la clase padre deben inicializarse, por lo que Person person = new Person () en Test se ejecutará y la clase Person aún no se ha cargado, por lo que la clase Person se cargará y ejecutará en la clase Person. El bloque estático de la clase principal se ejecuta, y la inicialización de la clase principal se completa, y luego se inicializa a sí mismo, por lo que ejecutará Person person = new Person () en MyClass, y finalmente ejecutará el constructor de MyClass.

3. ¿Cuál es el resultado de este código?

public class Test {
    
    
     
    static{
    
    
        System.out.println("test static 1");
    }
    public static void main(String[] args) {
    
    
         
    }
     
    static{
    
    
        System.out.println("test static 2");
    }
}

Salida:

test static 1
test static 2

Aunque no hay ninguna declaración en el método principal, seguirá apareciendo porque las razones se han descrito anteriormente. Además, el bloque estático puede aparecer en cualquier lugar de la clase (siempre que no esté dentro del método, recuerde que ningún método funcionará), y la ejecución se ejecuta en el orden del bloque estático.

Para ser visto:
https://zhuanlan.zhihu.com/p/70110497
https://www.cnblogs.com/dolphin0520/p/10651845.html

Supongo que te gusta

Origin blog.csdn.net/qq_30885821/article/details/109329277
Recomendado
Clasificación