Preguntas sobre la serialización de Java que realmente hacen?

introducción

Cuando los datos persistentes objetos que rara vez se utiliza la serialización de Java, pero el uso de bases de datos y otras formas de lograr. Pero en mi opinión, la serialización de Java es un elemento muy importante, no sólo puede salvar objetos serializados a la persistencia de disco, también puede ser transmitida a través de la red. En la entrevista habitual ellas, pieza serializada de contenido se habla a menudo.

Cuando se trata de serialización, puede saber que la clase implementa la interfaz Serializable se puede lograr el objetivo de la serialización, pero vio las preguntas cara sobre la secuencia de los ignorantes que buscan a menudo forzados.

1) ¿Qué se puede serializar y la interfaz de interfaces externas puede ser la diferencia entre eso?

2) Cuando serializado, no desea que ciertos miembros de la serializado? ¿Cómo lograr?

3) ¿Cuál es el serialVersionUID? Si no se define una serialVersionUID, ¿qué pasará?

De hecho, no estamos de repente se encuentran todavía hay muchas dudas sobre estos temas? En este artículo se hará un resumen de algunas de la serialización de Java de preguntas y respuestas frecuentes para pasar la prueba y demostración.

La pregunta: ¿Cuál es la serialización de Java?

Serializar el objeto se va a cambiar se pueden guardar en el disco o enviados a otros procesos que se ejecutan en formato binario máquina virtual Java a través de la red , y puede restaurar el estado de la deserialización objeto. La serialización de Java API proporciona un mecanismo estándar para los desarrolladores: mediante la implementación de las interfaces java.io.Serializable o java.io.Externalizable, ObjectInputStream y ObjectOutputStream objeto de proceso de serialización. Java.io.Externalizable luego implementar la interfaz, los programadores de Java son libres de elegir sobre la base de la estructura de clases estándar o secuencia de su formato binario auto-definido, que generalmente se considera la mejor práctica ya que el formato de archivo binario serializado se convierten en Clase parte de la salida de la API, el paquete de Java puede destruir la propiedad privada visible y paquete.

Serialización al final lo que es el uso?

Implementar java.io.Serializable.

categorías definidas por el usuario:

class User implements Serializable {
	private String username;
    private String passwd;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
}
复制代码

Nos serialización de objetos, txt archivos almacenados por ObjectOutputStream, a continuación, leer el archivo txt por ObjectInputStream, anti-secuencia en el objeto Usuario.

public class TestSerialize {

    public static void main(String[] args) {

        User user = new User();
        user.setUsername("hengheng");
        user.setPasswd("123456");

        System.out.println("read before Serializable: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());

        try {
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("/Users/admin/Desktop/test/user.txt"));
            os.writeObject(user); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "/Users/admin/Desktop/test/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();

            System.out.println("\nread after Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
复制代码

Los resultados son los siguientes:

序列化前数据: 
username: hengheng
password: 123456

序列化后数据: 
username: hengheng
password: 123456
复制代码

Aquí, probablemente sabemos lo que está serializado.

Segundo problema: la serialización, que no quiere ciertos miembros de la serialización, la forma de lograr?

Respuesta: Los miembros declarados como estática o transitoria, no se puede serializar la serialización de Java.

  • Las variables estáticas : añadir la palabra clave static.
  • las variables transitorias: además transitoria de palabras clave.

Vamos a tratar de declarar una variable como transitorio.

class User implements Serializable {
    private String username;
    private transient String passwd;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
复制代码

Antes de que el campo de contraseña más una transitoria plazo de palabras clave. El resultado:

序列化前数据: 
username: hengheng
password: 123456

序列化后数据: 
username: hengheng
password: null
复制代码

Se encontró mediante la ejecución de la contraseña no es de serie, para alcanzar nuestra meta.

Pruebe antes de que el nombre de usuario más estática de palabras clave.

class User implements Serializable {
    private static String username;
    private transient String passwd;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
复制代码

El resultado:

序列化前数据: 
username: hengheng
password: 123456

序列化后数据: 
username: hengheng
password: null
复制代码

Hemos encontrado que los resultados operativos y las expectativas no son los mismos, y normalmente se deben convertirse en hijo de nombre de usuario nulo. ¿Qué lo causa?

La razón es la siguiente: el valor del valor JVM nombre de usuario deserializado estática variable de clase corriente correspondiente variable estática, en lugar de la deserializado derivada.

Vamos a lo demuestran:

public class TestSerialize {

    public static void main(String[] args) {

        User user = new User();
        user.setUsername("hengheng");
        user.setPasswd("123456");

        System.out.println("序列化前数据: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());

        try {
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("/Users/admin/Desktop/test/user.txt"));
            os.writeObject(user); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        User.username = "小明";
        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "/Users/admin/Desktop/test/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();

            System.out.println("\n序列化后数据: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class User implements Serializable {
    public static String username;
    private transient String passwd;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
}
复制代码

Antes de deserialización el valor de las variables estáticas nombre de usuario ha cambiado a "Bob".

User.username = "小明";
复制代码

Ejecutarlo de nuevo:

序列化前数据: 
username: hengheng
password: 123456

序列化后数据: 
username: 小明
password: null
复制代码

Efectivamente, nombre aquí es el valor de la variable estática JVM, no el valor obtenido por la deserialización.

Tercera pregunta: serialVersionUID lo que es el uso?

A menudo personalizar un serialVersionUID en clase:

private static final long serialVersionUID = 8294180014912103005L
复制代码

El serialVersionUID ¿para qué sirve? Si no se establece, entonces lo que serán las consecuencias?

serialVersionUID es una final larga Identificación de tipo estático privado, cuando se imprime en el objeto, por lo general es el código objeto hash. serialVersionUID puede definir su propio, puede generar ellos mismos.

Consecuencias no especifican serialVersionUID es: Al añadir o modificar la clase en cualquier campo, la clase serializada no se recuperará porque el viejo y el nuevo objeto serializado clase generada serialVersionUID será diferente. proceso de serialización de Java depende de la secuencia correcta de estado de recuperación de objetos, y provocó java.io.InvalidClassException excepciones de clase no válida en el caso de un objeto serializado no coincide con la versión de serie.

Por ejemplo vamos a entender:

Nosotros previamente guardados se conservan archivo serializado sin cambios, y luego modificar la clase de usuario.

class User implements Serializable {
    public static String username;
    private transient String passwd;
    private String age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
复制代码

La adición de una edad de la propiedad, entonces una sola escritura otra deserializado Método:

public static void main(String[] args) {
        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "/Users/admin/Desktop/test/user.txt"));
            User user = (User) is.readObject(); // 从流中读取User的数据
            is.close();

            System.out.println("\n修改User类之后的数据: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
复制代码

Aquí Insertar imagen Descripción

Error, encontramos serialVersionUID después serialVersionUID y los cambios realizados antes de la clase de usuario generada no es lo mismo (porque es a través de la generación de hash código objeto), a excepción InvalidClassException llevado.

serialVersionUID personalizado:

class User implements Serializable {
    private static final long serialVersionUID = 4348344328769804325L;

    public static String username;
    private transient String passwd;
    private String age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
复制代码

Prueba esto:

序列化前数据: 
username: hengheng
password: 123456

序列化后数据: 
username: 小明
password: null
复制代码

Resultados de operación sin errores, personalizado, de modo general, se requiere serialVersionUID.

Pregunta 4: ¿Puedo personalizar el proceso de serialización?

La respuesta por supuesto es posible.

Antes de presentar la segunda forma de serialización:

interfaz Externalizable implementado, entonces anular los métodos writeExternal () y readExternal (), que pueden ser de serialización personalizado.

Por ejemplo, tratamos de poner la variable a los transitorios.

public class ExternalizableTest implements Externalizable {

    private transient String content = "我是被transient修饰的变量哦";

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(content);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        content = (String) in.readObject();
    }

    public static void main(String[] args) throws Exception {

        ExternalizableTest et = new ExternalizableTest();
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                new File("test")));
        out.writeObject(et);

        ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                "test")));
        et = (ExternalizableTest) in.readObject();
        System.out.println(et.content);

        out.close();
        in.close();
    }
}
复制代码

El resultado:

我是被transient修饰的变量哦
复制代码

Implementado aquí es la interfaz Externalizable, no puede haber serialización automática, es necesario especificar manualmente las variables a ser serializados en el método writeExternal, independientemente de si la modificación transitoria.

A través de esta introducción, no estamos tenemos una mayor comprensión de la serialización de Java?

Autor: Yang Hyong

Fuente: Instituto de Tecnología de CreditEase

Supongo que te gusta

Origin juejin.im/post/5e671a07f265da574727a0d8
Recomendado
Clasificación