Saltar al contenido

¿Cuál es la diferencia entre “Class.forName ()” y “Class.forName (). NewInstance ()”?

Solución:

Quizás un ejemplo que demuestre cómo se utilizan ambos métodos le ayudará a comprender mejor las cosas. Entonces, considere la siguiente clase:

package test;

public class Demo {

    public Demo() {
        System.out.println("Hi!");
    }

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("test.Demo");
        Demo demo = (Demo) clazz.newInstance();
    }
}

Como se explica en su javadoc, llamando Class.forName(String) devuelve el Class objeto asociado con la clase o interfaz con el nombre de cadena dado es decir, vuelve test.Demo.class que se ve afectado por clazz variable de tipo Class.

Entonces, llamando clazz.newInstance() crea una nueva instancia de la clase representada por este Class objeto. La clase es instanciada como por un new expresión con una lista de argumentos vacía. En otras palabras, esto es realmente equivalente a un new Demo() y devuelve una nueva instancia de Demo.

Y ejecutando esto Demo class por lo tanto imprime la siguiente salida:

Hi!

La gran diferencia con lo tradicional new es eso newInstance permite crear una instancia de una clase que no conoce hasta el tiempo de ejecución, lo que hace que su código sea más dinámico.

Un ejemplo típico es la API de JDBC que carga, en tiempo de ejecución, el controlador exacto necesario para realizar el trabajo. Los contenedores EJB, los contenedores Servlet son otros buenos ejemplos: utilizan la carga dinámica en tiempo de ejecución para cargar y crear componentes que no conocen nada antes del tiempo de ejecución.

En realidad, si desea ir más allá, eche un vistazo al artículo de Ted Neward Understanding Class.forName () que estaba parafraseando en el párrafo anterior.

EDITAR (respondiendo a una pregunta del OP publicada como comentario): El caso de los controladores JDBC es un poco especial. Como se explica en el capítulo DriverManager de Introducción a la API de JDBC:

(…) A Driver La clase se carga y, por lo tanto, se registra automáticamente con el DriverManager, de una de estas dos formas:

  1. llamando al método Class.forName. Esto carga explícitamente la clase de controlador. Dado que no depende de ninguna configuración externa, esta forma de cargar un controlador es la recomendada para usar el DriverManager
    estructura. El siguiente código carga la clase acme.db.Driver:

    Class.forName("acme.db.Driver");
    

    Si acme.db.Driver se ha escrito para que cargarlo haga que se cree una instancia y también llame
    DriverManager.registerDriver con esa instancia como parámetro
    (como debería hacer), entonces está en el
    DriverManagerlista de controladores y disponible para crear una conexión.

  2. (…)

En ambos casos, es responsabilidad del recién cargado Driver class para registrarse llamando DriverManager.registerDriver. Como se mencionó, esto debe hacerse automáticamente cuando se carga la clase.

Para registrarse durante la inicialización, el controlador JDBC normalmente usa un bloque de inicialización estático como este:

package acme.db;

public class Driver {

    static {
        java.sql.DriverManager.registerDriver(new Driver());
    }

    ...
}

Vocación Class.forName("acme.db.Driver") provoca la inicialización del acme.db.Driver class y, por tanto, la ejecución del bloque de inicialización estático. Y Class.forName("acme.db.Driver") de hecho “creará” una instancia, pero esto es solo una consecuencia de cómo se implementan (buenos) los controladores JDBC.

Como nota al margen, mencionaría que todo esto ya no es necesario con JDBC 4.0 (agregado como paquete predeterminado desde Java 7) y la nueva función de carga automática de los controladores JDBC 4.0. Consulte las mejoras de JDBC 4.0 en Java SE 6.

Class.forName () le da el objeto de clase, que es útil para la reflexión. Los métodos que tiene este objeto son definidos por Java, no por el programador que escribe la clase. Son los mismos para todas las clases. Llamar a newInstance () en eso le da una instancia de esa clase (es decir, llamar Class.forName("ExampleClass").newInstance() es equivalente a llamar new ExampleClass()), en el que puede llamar a los métodos que define la clase, acceder a los campos visibles, etc.

En el mundo JDBC, el normal práctica (según la API de JDBC) es que utilice Class#forName() para cargar un controlador JDBC. El controlador JDBC debe registrarse a sí mismo en DriverManager dentro de un bloque estático:

package com.dbvendor.jdbc;

import java.sql.Driver;
import java.sql.DriverManager;

public class MyDriver implements Driver {

    static {
        DriverManager.registerDriver(new MyDriver());
    }

    public MyDriver() {
        //
    }

}

Invocando Class#forName() ejecutará todos los inicializadores estáticos. De esta manera el DriverManager puede encontrar el controlador asociado entre los controladores registrados por URL de conexión durante getConnection() que aproximadamente se parece a lo siguiente:

public static Connection getConnection(String url) throws SQLException {
    for (Driver driver : registeredDrivers) {
        if (driver.acceptsURL(url)) {
            return driver.connect(url);
        }
    }
    throw new SQLException("No suitable driver");
}

Pero también hubo calesa Controladores JDBC, comenzando con el org.gjt.mm.mysql.Driver como ejemplo bien conocido, que se registra incorrectamente dentro de la Constructor en lugar de un bloque estático:

package com.dbvendor.jdbc;

import java.sql.Driver;
import java.sql.DriverManager;

public class BadDriver implements Driver {

    public BadDriver() {
        DriverManager.registerDriver(this);
    }

}

La única forma de hacer que funcione dinámicamente es llamar newInstance() ¡después! De lo contrario, se encontrará a primera vista con una inexplicable “SQLException: no hay un controlador adecuado”. Una vez más, esta es una insecto en el controlador JDBC, no en su propio código. Hoy en día, ningún controlador JDBC debería contener este error. Entonces puedes (y deberías) dejar el newInstance() lejos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *