La última colección de preguntas de entrevistas de JAVA (5)

reflexión

57. ¿Qué es la reflexión?

La reflexión se refiere principalmente a la capacidad de un programa para acceder, detectar y modificar su propio estado o comportamiento.

Reflexión de Java:

En el entorno de ejecución de Java, para cualquier clase, ¿puede saber qué atributos y métodos tiene la clase? Para cualquier objeto, ¿se puede llamar a cualquiera de sus métodos?

El mecanismo de reflexión de Java proporciona principalmente las siguientes funciones:

  • Juzgue la clase a la que pertenece cualquier objeto en tiempo de ejecución.

  • Construya un objeto de cualquier clase en tiempo de ejecución.

  • Juzgue las variables miembro y los métodos de cualquier clase en tiempo de ejecución.

  • Llame a cualquier método de objeto en tiempo de ejecución.

58. ¿Qué es la serialización de Java? ¿En qué circunstancias necesita la serialización?

En pocas palabras, es guardar el estado de varios objetos en la memoria (es decir, variables de instancia, no métodos) y leer el estado del objeto guardado. Aunque puede usar sus propios métodos para guardar estados de objetos, Java le proporciona un mecanismo para guardar estados de objetos que deberían ser mejores que los suyos, es decir, la serialización.

En qué circunstancias es necesario serializar:

a) Cuando desee guardar el estado del objeto en la memoria en un archivo o base de datos;
b) Cuando desee utilizar sockets para transferir objetos en la red;
c) Cuando desee transferir objetos a través de RMI ;

59. ¿Qué es un agente dinámico? Cuales son las aplicaciones?

Proxy dinámico:

Cuando desee agregar algún procesamiento adicional a un método en una clase que implementa una determinada interfaz. Por ejemplo, agregar registros, agregar transacciones, etc. Puede crear un proxy para esta clase, por lo que el nombre sugiere es crear una nueva clase. Esta clase no solo contiene las funciones del método de clase original, sino que también agrega una nueva clase con procesamiento adicional sobre la base original. Esta clase de proxy no está bien definida, se genera dinámicamente. Tiene el significado de desacoplamiento, flexibilidad y gran escalabilidad.

Aplicación de agente dinámico:

  • Primavera 的 AOP

  • Agregar asuntos

  • Agregar permisos

  • Agregar registro

60. ¿Cómo implementar un proxy dinámico?

Primero, se debe definir una interfaz y una clase de procesamiento InvocationHandler (pasando el objeto de la clase que implementa la interfaz). Existe otra clase de herramienta Proxy (es costumbre llamarla clase de proxy, porque llamar a su newInstance () puede generar un objeto proxy, de hecho, es solo una clase de herramienta que genera un objeto proxy). Usando el InvocationHandler, empalmando el código fuente de la clase de proxy, compilándolo para generar el código binario de la clase de proxy, cargándolo con el cargador y creando una instancia para generar el objeto de proxy, y finalmente regresando.


Copia de objeto

61. ¿Por qué utilizar la clonación?

Si desea procesar un objeto, pero también desea conservar los datos originales para la siguiente operación, debe clonar. El clon en el lenguaje Java es para la instancia de la clase.

62. ¿Cómo implementar la clonación de objetos?

Hay dos maneras:

1) Implementar la interfaz Cloneable y reescribir el método clone () en la clase Object;

2) Realice la interfaz serializable, realice el clon a través de la serialización y deserialización del objeto, que puede realizar el clon profundo real, el código es el siguiente:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class MyUtil {
    
    

    private MyUtil() {
    
    
        throw new AssertionError();
    }

    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj) throws Exception {
    
    
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(obj);

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        return (T) ois.readObject();

        // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
    }
}

Aquí está el código de prueba:


import java.io.Serializable;

/**
 * 人类
 * @author nnngu
 *
 */
class Person implements Serializable {
    
    
    private static final long serialVersionUID = -9102017020286042305L;

    private String name;    // 姓名
    private int age;        // 年龄
    private Car car;        // 座驾

    public Person(String name, int age, Car car) {
    
    
        this.name = name;
        this.age = age;
        this.car = car;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public Car getCar() {
    
    
        return car;
    }

    public void setCar(Car car) {
    
    
        this.car = car;
    }

    @Override
    public String toString() {
    
    
        return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
    }

}
/**
 * 小汽车类
 * @author nnngu
 *
 */
class Car implements Serializable {
    
    
    private static final long serialVersionUID = -5713945027627603702L;

    private String brand;       // 品牌
    private int maxSpeed;       // 最高时速

    public Car(String brand, int maxSpeed) {
    
    
        this.brand = brand;
        this.maxSpeed = maxSpeed;
    }

    public String getBrand() {
    
    
        return brand;
    }

    public void setBrand(String brand) {
    
    
        this.brand = brand;
    }

    public int getMaxSpeed() {
    
    
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
    
    
        this.maxSpeed = maxSpeed;
    }

    @Override
    public String toString() {
    
    
        return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]";
    }

}
class CloneTest {
    
    

    public static void main(String[] args) {
    
    
        try {
    
    
            Person p1 = new Person("郭靖", 33, new Car("Benz", 300));
            Person p2 = MyUtil.clone(p1);   // 深度克隆
            p2.getCar().setBrand("BYD");
            // 修改克隆的Person对象p2关联的汽车对象的品牌属性
            // 原来的Person对象p1关联的汽车不会受到任何影响
            // 因为在克隆Person对象时其关联的汽车对象也被克隆了
            System.out.println(p1);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
}

Nota: La clonación basada en la serialización y deserialización no es solo una clonación profunda, sino que, lo que es más importante, a través de la restricción genérica, puede verificar si el objeto que se va a clonar admite la serialización. Esta verificación la realiza el compilador, no en. Se lanza una excepción en tiempo de ejecución. Esta solución es obviamente mejor que usar el método de clonación de la clase Object para clonar un objeto. Siempre es mejor exponer el problema en tiempo de compilación que dejar el problema en tiempo de ejecución.

63. ¿Cuál es la diferencia entre copia profunda y copia superficial?

  • La copia superficial simplemente copia la dirección de referencia del objeto, y los dos objetos apuntan a la misma dirección de memoria, por lo que si se modifica algún valor, el otro valor cambiará en consecuencia. Esta es una copia superficial (por ejemplo: asignar ())

  • La copia profunda es copiar el objeto y el valor, dos objetos modifican cualquier valor del otro valor no cambiará, esto es una copia profunda (por ejemplo: JSON.parse () y JSON.stringify (), pero este método no puede copiar la función Tipos de)

Supongo que te gusta

Origin blog.csdn.net/weixin_42120561/article/details/114695345
Recomendado
Clasificación