1. ¿Cuál es el mecanismo de reflexión?
En pocas palabras, el mecanismo de reflexión significa que el programa puede obtener su propia información mientras se ejecuta. En Java, siempre que se proporcione el nombre de la clase, toda la información sobre la clase se puede obtener a través del mecanismo de reflexión.
2. ¿Dónde se utiliza el mecanismo de reflexión?
A veces, hemos usado algunos conocimientos, pero no sabemos cuál es la terminología profesional. Cuando recién aprendimos jdbc, usamos una línea de código, Class.forName ("com.mysql.jdbc.Driver.class"). newInstance(); Pero en ese momento, solo sabía que esa línea de código generaba una instancia de objeto controlador y no conocía su significado específico. Después de escuchar la lección sobre el mecanismo de reflexión, me di cuenta de que esto es reflexión. Hoy en día, muchos marcos abiertos utilizan el mecanismo de reflexión y Struts se implementa mediante el mecanismo de reflexión.
3. Ventajas y desventajas del mecanismo de reflexión
¿Por qué utilizar el mecanismo de reflexión? ¿No es suficiente crear objetos directamente? Esto implica los conceptos de dinámico y estático.
Compilación estática: el tipo se determina en el momento de la compilación y el objeto se vincula, es decir, se pasa.
Compilación dinámica: determine el tipo y vincule el objeto en tiempo de ejecución. La compilación dinámica maximiza la flexibilidad de Java, incorpora aplicaciones polimórficas y reduce el acoplamiento entre clases.
En una palabra, la ventaja del mecanismo de reflexión es que puede crear objetos dinámicamente y compilarlos, lo que muestra una gran flexibilidad. Especialmente en el desarrollo de J2EE, su flexibilidad es muy obvia. Por ejemplo, para un software a gran escala, es imposible diseñarlo perfectamente de una sola vez. Después de compilar y lanzar el programa, cuando descubrimos que ciertas funciones necesitan actualizarse, no podemos pedirle al usuario que desinstale la anterior. uno y luego reinstálelo en la nueva versión; si este es el caso, este software definitivamente no será utilizado por muchas personas. Si es estático, es necesario volver a compilar todo el programa una vez para realizar la actualización de la función. Si utiliza el mecanismo de reflexión, no es necesario desinstalarlo, solo es necesario crearlo y compilarlo dinámicamente en tiempo de ejecución para realizar la función.
Su desventaja es su impacto en el rendimiento. Usar la reflexión es básicamente una operación interpretada en la que podemos decirle a la JVM lo que queremos hacer y cumple con nuestros requisitos. Este tipo de operaciones son siempre más lentas que simplemente realizar la misma operación directamente.
4. ¿Qué información se puede obtener utilizando el mecanismo de reflexión?
En una palabra, puede obtener cualquier información que haya en la clase, pero el requisito previo es conocer el nombre de la clase; de lo contrario, no habrá más información. Primero, el objeto Clase debe crearse en función del nombre completo de la clase. clase entrante.
Class c=Class.forName("className"); Nota: className debe ser el nombre completo, es decir, debe incluir el nombre del paquete, por ejemplo, cn.netjava.pojo.UserInfo;
Objeto obj=c.newInstance();//Crear una instancia del objeto
Bien, una vez que tienes un objeto, todo es fácil de manejar. Puedes obtener la información que quieras.
Cómo conseguir el constructor
Constructor getConstructor(Class[] params)//Obtiene el constructor público de acuerdo con los parámetros especificados
Constructor[] getConstructors()//Obtener todos los constructores públicos
Constructor getDeclaredConstructor(Class[] params)//Obtiene constructores públicos y no públicos basados en parámetros especificados
Constructor[] getDeclaredConstructors()//Obtener todos los constructores públicos
Obtener método de método de clase
Método getMethod (nombre de cadena, parámetros de clase []), obtiene el método según el nombre del método y el tipo de parámetro
Método[] getMethods()//Obtener todos los métodos públicos
Método getDeclaredMethod(String name, Class[] params)// Según el nombre del método y el tipo de parámetro, obtiene métodos públicos y no públicos
Método[] getDeclaredMethods()//Obtener todos los métodos públicos y no públicos
Cómo obtener atributos en una clase
Campo getField (nombre de cadena) // Obtenga la variable pública correspondiente según el nombre de la variable
Field[] getFields()//Obtiene todos los métodos públicos de la clase
Campo getDeclaredField (nombre de cadena) // Obtener variables públicas y no públicas según el nombre del método
Field[] getDeclaredFields()//Obtiene todos los métodos públicos y no públicos de la clase
Estos son los más utilizados. Si los conoces, todo lo demás será fácil de manejar...
5. ¿Qué se puede hacer con el mecanismo de reflexión?
Cuando comencé a usar jdbc, sentí ganas de vomitar cuando escribí para acceder a la base de datos. Había ocho tablas y cada tabla tenía operaciones de adición, eliminación, modificación y búsqueda. Mecanismo de reflexión, así que escribí sobre diferentes Cree diferentes clases DAO en la tabla, lo que no solo acelera el desarrollo, sino que también hace que el código sea redundante. Lo más terrible es que se ven casi iguales y luego los copia y modifica directamente. Debido a que es fácil cometer varios errores de bajo nivel (mayúsculas y minúsculas, una más o falta una letra...), un error puede llevar mucho tiempo encontrarlo.
Con el mecanismo de reflexión de Java, todo es fácil de manejar. Solo necesita escribir una clase dao con cuatro métodos, agregar, eliminar, modificar y consultar, y no es necesario crear uno. clase dao para cada tabla. El mecanismo de reflexión automáticamente hará el resto por nosotros, ese es su beneficio. Para decirlo sin rodeos, el mecanismo de reflexión está diseñado para ayudarnos a hacer cosas repetitivas y regulares, por lo que muchos programas que generan código automáticamente ahora usan el mecanismo de reflexión para completarlo, siempre que ingrese los parámetros relevantes de acuerdo con las reglas, bajo. Los programadores de nivel son lentos. Los lentos fueron eliminados, ¿por qué? Como no es necesario escribir código, cualquiera puede desarrollarlo, entonces, ¿por qué lo hacen los programadores? Entonces solo tenemos una salida, y es trabajar duro y trabajar más duro, convertirnos en programadores senior, especializarnos en desarrollar software estúpido y dejar que otros programadores se hagan a un lado y se calmen, jaja ~
6. Ejemplo de uso del mecanismo de reflexión para agregar y verificar datos de la base de datos
Principio básico: al guardar datos, saque todos los valores de atributos de los objetos que deben guardarse y luego junte la declaración SQL para la consulta y empaquete todos los datos consultados en un objeto Java.
Reglas del juego: como dice el refrán, no hay nada sin reglas. Especialmente para los programas, solo pueden hacer cosas con reglas. Bien, establezcamos las reglas primero.
1) Cada objeto de tabla en la base de datos tiene una clase pojo y cada campo de la tabla corresponde a un atributo de la clase pojo. Además, el nombre de la clase pojo es el mismo que el nombre de la tabla, y el nombre del atributo y el nombre del campo son los mismos. No importa el caso, porque la base de datos generalmente no distingue entre mayúsculas y minúsculas.
2) Agregue un conjunto estándar y obtenga métodos para cada atributo en la clase pojo.
Con las reglas del juego, comencemos a jugar.
1. Primero, hay una tabla en la base de datos. Suponga que el nombre de la base de datos es: blogsystem y el nombre de la tabla es userinfo. Como se muestra en la imagen:
2. Cree la clase pojo correspondiente:
Copie el código de código de la siguiente manera:
paquete cn.netjava.pojo;
información de usuario de clase pública {
identificación interna privada;
nombre de cadena privada;
contraseña de cadena privada;
edad privada;
@Anular
cadena pública toString() {
devolver "UserInfo [id=" + id + ", nombre=" + nombre + ", pwd=" + pwd + ", edad="
+ edad + "]";
}
público int getId() {
identificación de devolución;
}
setId vacío público (int id) {
this.id = identificación;
}
cadena pública getName() {
nombre de retorno;
}
setName público vacío (nombre de cadena) {
this.nombre = nombre;
}
cadena pública getPwd() {
devolver contraseña;
}
setPwd público vacío (contraseña de cadena) {
this.pwd = contraseña;
}
público int getAge() {
edad de retorno;
}
setAge público vacío (int edad) {
this.age = edad;
}
}
2. Escriba una clase de fábrica para obtener la conexión a la base de datos:
Copie el código de código de la siguiente manera:
paquete cn.netjava.factory;
importar java.sql.Conexión;
importar java.sql.DriverManager;
clase pública Connect2DBFactory {
Conexión estática pública getDBConnection() {
Conexión de conexión = nula;
intentar {
Class.forName("com.mysql.jdbc.Driver");
URL de cadena = "jdbc:mysql://localhost:3306/blogsystem";
Usuario de cadena = "raíz";
Contraseña de cadena = "netjava";
conexión = DriverManager.getConnection(url, usuario, contraseña);
} captura (Excepción e) {
e.printStackTrace();
}
conexión de retorno;
}
}
3. La diversión comienza escribiendo la clase dao que opera la base de datos.
Copie el código de código de la siguiente manera:
paquete cn.netjava.session;
importar java.lang.reflect.Field;
importar java.lang.reflect.Method;
importar java.sql.Conexión;
importar java.sql.PreparedStatement;
importar java.sql.ResultSet;
importar java.sql.SQLException;
importar java.sql.Statement;
importar java.util.ArrayList;
importar java.util.List;
importar cn.netjava.factory.Connect2DBFactory;
importar cn.netjava.pojo.UserInfo;
clase pública NetJavaSession {
/**
* Analiza la declaración SQL que guarda el objeto.
*
* objeto @param
*: Objeto que necesita ser guardado
* @return: sentencia sql para guardar el objeto
*/
cadena estática pública getSaveObjectSql (objeto objeto) {
//Definir una cadena sql
Cadena sql = "insertar en";
//Obtiene la clase del objeto
Clase c = object.getClass();
//Obtiene todos los métodos del objeto
Método[] métodos = c.getMethods();
// Obtener todas las propiedades del objeto
Campo[] campos = c.getFields();
//Obtiene el nombre de la clase de objeto
Cadena cName = c.getName();
// Analiza el nombre de la tabla a partir del nombre de la clase
Cadena nombreTabla = cName.substring(cName.lastIndexOf(".") + 1,
cNombre.longitud());
sql += nombreTabla + "(";
Lista<Cadena> mList = nueva ArrayList<Cadena>();
Lista vList = nueva ArrayList();
para (Método método: métodos) {
Cadena mName = método.getName();
if (mName.startsWith("get") && !mName.startsWith("getClass")) {
Cadena nombre del campo = mName.substring(3, mName.length());
mList.add(nombre del campo);
System.out.println("Nombre de campo----->" + nombre de campo);
intentar {
Valor del objeto = método.invoke(objeto, nulo);
System.out.println("El valor devuelto por el método de ejecución: " + valor);
si (valor instancia de cadena) {
vList.add("/"" + valor + "/"");
System.out.println("Valor de campo------>" + valor);
} demás {
vList.add(valor);
}
} captura (Excepción e) {
e.printStackTrace();
}
}
}
para (int i = 0; i < mList.size(); i++) {
si (i < mList.size() - 1) {
sql += mList.get(i) + ",";
} demás {
sql += mList.get(i) + ") valores(";
}
}
para (int i = 0; i < vList.size(); i++) {
si (i < vList.size() - 1) {
sql += vList.get(i) + ",";
} demás {
sql += vList.get(i) + ")";
}
}
devolver sql;
}
Lista estática pública getDatasFromDB (String tableName, int Id) {
devolver nulo;
}
/**
* Guardar el objeto en la base de datos.
*
* objeto @param
*: Objeto que necesita ser guardado
* @return: El resultado de la ejecución del método; 1: indica éxito, 0: indica fracaso;
*/
public int saveObject(Objeto objeto) {
Conexión con = Connect2DBFactory.getDBConnection();
Cadena sql = getSaveObjectSql(objeto);
intentar {
// Declaración declaración=(Declaración) con.createStatement();
PreparedStatement psmt = con.prepareStatement(sql);
psmt.executeUpdate();
devolver 1;
} captura (SQLException e) {
e.printStackTrace();
devolver 0;
}
}
/**
* Obtener el objeto de la base de datos.
*
* @param arg0
*: La clase a la que pertenece el objeto.
* @identificación del parámetro
*: identificación del objeto
* @return: el objeto a encontrar
*/
Objeto público getObject (String className, int Id) {
//Obtiene el nombre de la tabla
String tableName = className.substring(className.lastIndexOf(".") + 1,
nombredeclase.longitud());
//Crear objeto de clase basado en el nombre de la clase
Clase c = nula;
intentar {
c = Class.forName(nombredeclase);
} captura (ClassNotFoundException e1) {
e1.printStackTrace();
}
// Reúne la instrucción SQL de consulta
String sql = "seleccionar * de " + nombreTabla + " donde Id=" + Id;
System.out.println("Buscar sentencia sql: " + sql);
// Obtener enlace de base de datos
Conexión con = Connect2DBFactory.getDBConnection();
//Crea una instancia de la clase
Objeto obj = nulo;
intentar {
Declaración stm = con.createStatement();
// Obtener el conjunto de resultados devuelto ejecutando la declaración de búsqueda
Conjunto de resultados establecido = stm.executeQuery(sql);
// Obtener la matriz del método del objeto.
Método[] métodos = c.getMethods();
// recorre el conjunto de resultados
mientras (set.siguiente()) {
obj = c.nuevaInstancia();
//Métodos para atravesar objetos
para (Método método: métodos) {
Cadena nombre del método = método.getName();
// Si el método del objeto comienza con set
if (nombremétodo.startsWith("conjunto")) {
// Obtener el nombre del campo en la tabla de datos según el nombre del método
Cadena nombreColumna = nombremétodo.subcadena(3,
nombredelmétodo.longitud());
// Obtener el tipo de parámetro del método
Clase[] parmts = método.getParameterTypes();
si (parmts[0] == Cadena.clase) {
// Si el parámetro es de tipo String, obtenemos el valor correspondiente del conjunto de resultados según el nombre de la columna y ejecutamos el método set
método.invoke(obj, set.getString(nombredecolumna));
}
si (parmts[0] == int.clase) {
método.invoke(obj, set.getInt(nombredecolumna));
}
}
}
}
} captura (Excepción e) {
e.printStackTrace();
}
objeto de retorno;
}
}
4. ¿Qué tal el efecto de iniciar la prueba?
Copie el código de código de la siguiente manera:
paquete cn.netjava.tester;
importar cn.netjava.pojo.UserInfo;
importar cn.netjava.session.NetJavaSession;
Probador de clase pública {
público estático vacío principal (String args []) {
//Obtener el objeto NetJavaSession
Sesión NetJavaSession = nueva NetJavaSession();
//Crear un objeto UserInfo
UserInfo usuario = nueva UserInfo();
//Establece las propiedades del objeto
usuario.setId(6988);
usuario.setAge(44);
usuario.setPwd("contraseña");
usuario.setName("campeón");
//Guardar el objeto en la base de datos.
Cadena sql = session.getSaveObjectSql(usuario);
System.out.println("Declaración SQL para guardar el objeto: " + sql);
//Buscar objeto
UserInfo userInfo = (UserInfo) sesión.getObject(
"cn.netjava.pojo.UserInfo", 6988);
System.out.println("Información obtenida: " + información de usuario);
}
}
5. Resultados impresos:
7. Resumamos
En general, el mecanismo de reflexión de Java es algo muy útil. Puede resolver muchas cosas muertas porque el mecanismo de reflexión es muy flexible y no necesitamos dedicar demasiado tiempo a escribir operaciones en lugar de utilizar el código de la base de datos. el método dedica más tiempo a las funciones lógicas del proyecto, lo que puede reducir en gran medida el tiempo de desarrollo y hacer que el código sea más legible. Muchos marcos de código abierto existentes utilizan mecanismos de reflexión. Solo necesitan configurar archivos y luego llamar a sus métodos de acuerdo con las reglas.