En la reflexión de Java, ¿por qué se recomienda obtener Class.forName () para la clase?

1. Tres formas de obtener objetos de clase en la reflexión de Java

En la reflexión de Java, la entrada de la reflexión es la clase, y hay tres formas de obtener la clase.

  1. Class.class;
  2. Class.forName ();
  3. Object.getClass ()

Comprensión simple de los tres

  1. La forma de Class.class hará que la JVM use el cargador de clases para cargar la clase en la memoria (siempre que la clase no se haya cargado en la memoria), sin realizar la inicialización de la clase y devolver el objeto Class.
  2. La forma de Class.forName () cargará la clase y hará la inicialización estática de la clase y devolverá el objeto Class.
  3. La forma de object.getClass inicializará estáticamente y no inicializará estáticamente la clase, y devolverá el objeto Class de la clase a la que el objeto realmente se refiere en tiempo de ejecución (porque la referencia del objeto hijo puede asignarse a la variable de referencia de el objeto padre) pertenece.

La inicialización estática se refiere a la inicialización cuando se carga la clase, y la inicialización no estática es la inicialización cuando se inicializa el nuevo objeto.

En los tres casos, cuando se genera el objeto Class, se juzgará si esta clase se ha cargado en la memoria.

Nota: El manejo de excepciones solo se realiza cuando se usa Class.forName (), porque Class.forName () necesita cargar la ruta de clases para evitar la situación en la que no se puede encontrar.

Dos, análisis del código fuente de Class.forName

Class.forName (String className); el código fuente de este método es

@CallerSensitive
public static Class<?> forName(String className) throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

Class.forName () llama al método forName0. El segundo parámetro de forName0 se establece en verdadero de forma predeterminada. Este parámetro representa si se inicializa la clase cargada. Establecer en verdadero para inicializar la clase, lo que significa que el bloque de código estático en la clase así como la asignación de constantes estáticas y otras operaciones.

Se puede ver claramente que el método Class.forName () se implementa realmente llamando a ClassLoader.

ClassLoader sigue el modelo de delegación parental y llama al cargador de clases que inicia el cargador de clases. La función implementada es "obtener un flujo de bytes binarios que describa esta clase a través del nombre completo de una clase" y luego colocar el flujo binario en la JVM después de obtener el flujo binario.

3. ¿Por qué se recomienda obtener Class.forName () para la clase?

Class.forName (), creo que cuando lo encontramos por primera vez, la mayor parte fue cuando estábamos aprendiendo JDBC.

Cuando se usa JDBC, el método Class.forName () generalmente se usa para cargar el controlador de conexión de la base de datos. Esto se debe a que en la especificación JDBC se requiere claramente que la clase Driver (controlador de base de datos) se registre en DriverManager.

Tome el controlador MySQL como ejemplo para explicar:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {  

    static {  
        try {  
            java.sql.DriverManager.registerDriver(new Driver());  
        } catch (SQLException E) {  
            throw new RuntimeException("Can't register driver!");  
        }  
    } 
    ... 
}

Se puede ver en el código fuente que la operación de registro del controlador en DriverManager está escrita en un bloque de código estático, por lo que Class.forName () se usa al escribir JDBC.

Class.forName () es una forma de destruir el mecanismo de delegación principal cuando se carga el controlador de la base de datos. Se carga una clase de terceros a través de Application ClassLoader y no se utiliza el cargador principal Bootstrap ClassLoad.

En una palabra, la razón más importante por la que se recomienda utilizar el método Class.forName () para obtener una Class es que el método Class.forName () realiza la inicialización estática de la clase (el método Class.class no realiza la inicialización estática de la clase; el método object.getClass () aunque también se realiza la inicialización estática, pero se necesita un nuevo objeto, lo cual no es muy conveniente).

 

 

referencia:

Hable brevemente sobre su comprensión de Class.forName (), Class.class y getClass () en Java.

En la reflexión de Java, la diferencia entre Class.forName y ClassLoader

Supongo que te gusta

Origin blog.csdn.net/guorui_java/article/details/114433677
Recomendado
Clasificación