Heim  >  Artikel  >  类库下载  >  Java-Serialisierung Serialisierbar

Java-Serialisierung Serialisierbar

高洛峰
高洛峰Original
2017-03-18 11:35:493088Durchsuche

Java-Serialisierung Serialisierbar

Der Serialisierungsprozess von Java ist wie folgt:

Java-Serialisierung Serialisierbar

Der Deserialisierungsprozess von Java ist wie folgt:

Java-Serialisierung Serialisierbar

Hinweis: Nicht alle Klassen müssen serialisiert werden. Es gibt zwei Hauptgründe

1) Sicherheitsprobleme. Bei einigen Klassen in Java handelt es sich um sensible Klassen, und die Offenlegung der Objektdaten dieser Art nach außen ist einfach. Daher kann die Sicherheit dieser Daten nicht gewährleistet werden Das Objekt wird nicht serialisiert.

2) Ressourcenprobleme. Objekte können mithilfe serialisierter Byteströme erstellt werden, und diese Erstellung ist nicht eingeschränkt. Manchmal kann die Erstellung zu vieler Objekte zu großen Ressourcenproblemen führen, sodass solche Objekte nicht für die Serialisierung geeignet sind.

Serializable

Serializable ist eine von Java bereitgestellte Serialisierungsschnittstelle. Es handelt sich um eine leere Schnittstelle, die Standard-Serialisierungs- und Deserialisierungsoperationen für Objekte bereitstellt.

Serialisierungsprozess:

Person p = new Person("name","id");
        File file = new File("cache.txt");
        FileOutputStream output = new FileOutputStream(file);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(output);
        objectOutputStream.writeObject(p);
        output.close();
        objectOutputStream.close();

Deserialisierungsprozess:

File file = new File("cache.txt");
        FileInputStream input= new FileInputStream(file);
        ObjectInputStream objectInputStream = new ObjectInputStream(input);
        Person p = (Person)objectInputStream.readObject();
        System.out.println(p.getName()+"---"+p.getId());
        input.close();
        objectInputStream.close();

Klassenmitglieder, die serialisiert werden müssen

Wann Beim Serialisieren eines Objekts müssen nicht alle Mitglieder in binäre Bytesequenzen konvertiert werden, da einige unnötige Mitglieder nicht serialisiert werden müssen, um Speicher- oder Übertragungsraum zu sparen und die Serialisierungseffizienz zu verbessern. Dazu gehören:

Statische Variablen. Da statische Variablen zu den Attributen der Klasse und nicht zu einer bestimmten Instanz gehören, ist während der Serialisierung keine Serialisierung erforderlich. Sie können die statische Mitgliedsreferenz der Klasse direkt abrufen.

Methode. Eine Methode ist nur eine Reihe von Operationen. Die Methode hängt nicht vom Objekt ab und die Operationen unterscheiden sich nicht je nach Objekt. Während der Deserialisierung können die Methodeninformationen auch direkt von der Klasse abgerufen werden.

Serialisierung der Vererbungsbeziehung

Wenn die übergeordnete Klasse Serializable implementiert, wird die untergeordnete Klasse serialisiert und die übergeordnete Klasse wird ebenfalls serialisiert. Wenn eine Klasse serialisiert wird, die Serializable implementiert, wird auch ihre Referenzklasse serialisiert. Wenn die Referenzklasse die Serializable-Schnittstelle nicht implementiert, löst die JVM java.io.NotSerializableExeception aus.

Wenn zu diesem Zeitpunkt die Person-Klasse serialisiert ist, wird gleichzeitig auch die Tool-Klasse serialisiert Zeit. Wenn die Tool-Klasse die Serializable-Schnittstelle nicht implementiert, wird eine Ausnahme ausgelöst.

Sensible Daten schützen:

Nachdem eine Klasse mit einer Serialisierungskennung hinzugefügt wurde, werden alle Attributinformationen des Klassenobjekts serialisiert und dann lokal gespeichert oder darüber übertragen Netzwerk. Manchmal handelt es sich bei einigen Feldern im Objekt um vertrauliche Informationen, die nicht offengelegt werden sollten. Wenn es außerdem serialisiert ist, kann es leicht geknackt werden, was zu Sicherheitsrisiken führt, beispielsweise bei häufig verwendeten Passwortfeldern.
class Person implements Serializable{
    private String name;
    private Tool tool = new Tool();
}

class Tool implements Serializable{
    
}

Java stellt ein Schlüsselwort transient bereit, bei dem es sich um das Schlüsselwort transient handelt. Dieses Schlüsselwort deaktiviert die Serialisierung des Felds, sodass geschützte Informationen durch die Serialisierung nicht offengelegt werden.

Serialisierungs-ID

Stellen Sie sich dieses Szenario vor: Beide Enden übertragen serialisierte Objekte über das Netzwerk. Aus irgendeinem Grund wird die von beiden Enden verwendete Version der Klasse geändert. Anders ausgedrückt: Nehmen Sie an, dass aus der Klasse des Empfängers mehrere Felder entfernt wurden. Wenn der Sender den serialisierten Bytestrom des Objekts an den Empfänger sendet, kann dieser nicht analysiert werden, da in der Klasse des Empfängers mehrere Felder fehlen.

Java erfordert, dass Klassen, die die Serialisierungsschnittstelle implementieren, ein statisches Attribut serialVersionUID deklarieren müssen. Wenn kein solches Attribut vorhanden ist, deklariert die JVM das Attribut automatisch und weist dem Attribut einen Wert zu (unterschiedliche Werte werden angezeigt). zugewiesen, wenn sich die Klasse ändert) ). Der Wert dieses Attributs ist eindeutig und wird zur Identifizierung verschiedener Serialisierungsklassen verwendet. Nur wenn die Serialisierungskennung der Klasse genau gleich ist, führt Java Deserialisierungsarbeiten durch. Dies ist die Rolle der Serialisierungskennung.

Für das oben genannte Szenario weist die JVM unter der Annahme, dass die serialVersionUID nicht manuell deklariert wird, der serialVersionUID in den vom Sender und vom Empfänger verwendeten Klassen unterschiedliche Werte zu und die Deserialisierung schlägt fehl. Wenn Sie serialVersionUID manuell einen Wert zuweisen, kann die Deserialisierung auch dann erfolgreich sein, wenn sich die Felder der Klasse ändern.

Benutzerdefinierte Serialisierungsstrategie

Benutzerdefinierte Serialisierungsstrategie

Java bietet einen effektiven Mechanismus, der Serialisierung und Deserialisierung ermöglicht. Wenn Sie benutzerdefinierte Methoden für die entsprechende Verarbeitung verwenden. Nachdem sich die Übertragungsparteien auf die Serialisierungsstrategie geeinigt haben, müssen sie nur noch eine Reihe von Methoden zur zu übertragenden Serialisierungsklasse hinzufügen, um diese Reihe von Strategien zu implementieren. Während der Serialisierung werden diese angegebenen Methoden automatisch zur Serialisierung und Deserialisierung aufgerufen. Die Methode ist wie folgt:

1) private void writeObject(ObjectOutputSteam out) throws IOException 

  在方法的内部有重要的代码:out.defaultWriteObject()    //将对象数据以默认方式写入到输出流中

     2)private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException

  同样的,此方法内部也有相似代码:in.defaultReadObject();  //以默认方式从输入流中恢复对象

这两个方法的作用分别是将特定的对象写入到输出流中以及从输入流中恢复特定的对象,通过这两个方法,用户即可实现自定义的序列化。当在实现Serializable接口的类中写了上面两个方法之后,序列化或反序列化该类时则会通过反射来调用这两个方法,从而实现自定义序列化。

限制序列化对象的数量     

我们看下面的单例模式:

public class Singleton implements Serializable {

    private volatile static Singleton mInstance;
    private Singleton() {
    }

    public static Singleton getInstance() {
        if (mInstance == null) {
            synchronized (Singleton.class) {
                if (mInstance == null) {
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }
}

此时通过反序列化获取实例,则单例模式会失效。那该如何解决这个问题呢?

  Java有一种机制,可以让我们在序列化和反序列化时,可以根据自己的需要,写入或读取指定的实例。使用这种机制,需要在实现Serializable接口的类中添加两个方法:

    private Object readResolve()   //如果用户在序列化类中添加了该方法,则在进行反序列化时,使用该方法返回的对象,作为反序列化对象。

    private Object writeReplace()   //如果用户在序列化类中添加了该方法,则在进行序列化时,序列化该类返回的对象。

再看使用了该机制的单例模式:

public class Singleton implements Serializable {

    private volatile static Singleton mInstance;
    private Singleton() {
    }

    public static Singleton getInstance() {
        if (mInstance == null) {
            synchronized (Singleton.class) {
                if (mInstance == null) {
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }

    private Object readResolve() {
        return getInstance();
    }

    private Object writeReplace() {
        return getInstance();
    }
}

 此时的通过反序列化得到的对象也是同一个,即单例模式依然有效!

相关文章:

Java序列化Serializable和Externalizable区别的示例代码

java 序列化对象 serializable 读写数据的实例

php—Serializable接口

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn