国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

ホームページ Java &#&はじめる Javaでシリアル化する方法

Javaでシリアル化する方法

Nov 12, 2019 pm 05:44 PM
java 連載

Javaでシリアル化する方法

1. シリアル化と逆シリアル化

シリアル化: ヒープ メモリ內(nèi)の Java オブジェクト データを指します。何らかの方法でディスク ファイルにペアを作成するか、他のネットワーク ノードに渡します (ネットワーク送信)。このプロセスはシリアル化と呼ばれ、通常はデータ構(gòu)造またはオブジェクトをバイナリに変換するプロセスを指します。

即將對象轉(zhuǎn)化為二進(jìn)制,用于保存,或者網(wǎng)絡(luò)傳輸。

デシリアライゼーション: ディスク ファイル內(nèi)のオブジェクト データまたはネットワーク ノード上のオブジェクト データを Java オブジェクト モデルに復(fù)元するプロセス。つまり、シリアル化の過程で生成されたバイナリ文字列をデータ構(gòu)造またはオブジェクトに変換するプロセスです。

與序列化相反,將二進(jìn)制轉(zhuǎn)化成對象。

2. シリアル化の役割

① 保存したいメモリ內(nèi)のオブジェクトをファイルまたはデータベースに保存する場合;

② ソケットを使用してネットワーク上でオブジェクトを送信したい場合;

③ RMI 経由でオブジェクトを送信したい場合

一些應(yīng)用場景,涉及到將對象轉(zhuǎn)化成二進(jìn)制,序列化保證了能夠成功讀取到保存的對象。

3. Java シリアル化の実裝

オブジェクトのシリアル化を?qū)g現(xiàn)するための最も直接的な操作は、Serializable インターフェイスを?qū)g裝することです

IO ストリームでオブジェクトを使用しますストリームはシリアル化操作を?qū)g裝し、オブジェクトをファイルに保存して、それらを読み出すことができます。

最初にオブジェクトを作成し、Serializable インターフェイスを?qū)g裝します:

import java.io.Serializable;
public class User implements Serializable{
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    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;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}

オブジェクト ストリームを使用して、オブジェクトの保存と読み取りのためのツール クラスを作成します:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializeUtil {
    // 保存對象,序列化
    public static void saveObject(Object object) throws Exception {
        ObjectOutputStream out = null;
        FileOutputStream fout = null;
        try {
            fout = new FileOutputStream("D:/1.txt");
            out = new ObjectOutputStream(fout);
            out.writeObject(object);
        } finally {
            fout.close();
            out.close();
        }
    }
    // 讀取對象,反序列化
    public static Object readObject() throws Exception {
        ObjectInputStream in = null;
        FileInputStream fin = null;
        try {
            fin = new FileInputStream("D:/1.txt");
            in = new ObjectInputStream(fin);
            Object object = in.readObject();
            return object;
        } finally {
            fin.close();
            in.close();
        }
    }
}

テスト:

public class Main {
    public static void main(String[] args) {
        User user = new User();
        user.setName("旭旭寶寶");
        user.setAge(33);
        // 保存
        try {
            SerializeUtil.saveObject(user);
        } catch (Exception e) {
            System.out.println("保存時(shí)異常:" + e.getMessage());
        }
        // 讀取
        User userObject;
        try {
            userObject = (User) SerializeUtil.readObject();
            System.out.println(userObject);
        } catch (Exception e) {
            System.out.println("讀取時(shí)異常:" + e.getMessage());
        }
    }
}

テスト結(jié)果:

Javaでシリアル化する方法

ここでは、オブジェクトをファイルに保存し、読み出すことに成功しました。この時(shí)點(diǎn)でシリアル化インターフェイスを?qū)g裝しないと、例外が発生します。実裝された Serialiable インターフェイス コードをキャンセルします:

public class User {
    private String name;
    private int age;
    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;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}

Main メソッドを再度テストします:

Javaでシリアル化する方法

この時(shí)點(diǎn)でエラーが報(bào)告されていることがわかります。e を使用します。 .printStackTrace( );例外の詳細(xì)を表示します:

Javaでシリアル化する方法

不明なソースが表示されます。シリアル化されていないため、保存したり読み取ったりすることはできません。

4. シリアル化 ID の役割

ご覧のとおり、シリアル化するときに、シリアル化 ID である SerialVersionUID フィールドを追加します

private static final long serialVersionUID = 1L;

このシリアル化 ID は重要な役割を果たし、逆シリアル化が成功するかどうかを決定します。 Java のシリアル化メカニズムは、ランタイム クラスの SerialVersionUID を判斷することによってバージョンの一貫性を検証します。逆シリアル化中に、JVM は受信バイト ストリームの SerialVersionUID をローカル エンティティ クラスの SerialVersionUID と比較します。それらが同じである場合、それらは一貫しているとみなされ、そうしないと、シリアル化されたバージョンに一貫性がないという例外が報(bào)告されます。

即序列化ID是為了保證成功進(jìn)行反序列化

5. デフォルトのシリアル化 ID

「serialVersionUID」という名前の変數(shù)を明示的に定義せず、エンティティ クラスに long と入力すると、Java シリアル化メカニズムが自動(dòng)的にシリアル化バージョンの比較として、コンパイルされたクラスに基づいて SerialVersionUID を生成します。この場合、同じコンパイルで生成されたクラスのみが同じ SerialVersionUID を生成します。たとえば、クラスを作成するときに時(shí)間が経つと、要件の変更によりローカル クラスに他のフィールドを追加する必要が生じますが、このとき、デシリアライズ中に SerialVersionUID が不一致になり、デシリアライズが失敗します。では、どうすれば解決できるのでしょうか? 「serialVersionUID」変數(shù)をローカルクラスに追加するだけで、値は変更されず、シリアル化と逆シリアル化を?qū)g行できます。

如果沒有顯示指定serialVersionUID,會(huì)自動(dòng)生成一個(gè)。
只有同一次編譯生成的class才會(huì)生成相同的serialVersionUID。
但是如果出現(xiàn)需求變動(dòng),Bean類發(fā)生改變,則會(huì)導(dǎo)致反序列化失敗。為了不出現(xiàn)這類的問題,所以我們最好還是顯式的指定一個(gè)
serialVersionUID。

6. シリアル化に関するその他の問題

1. 靜的変數(shù)はシリアル化されません (靜的、一時(shí)的)

2. 親がクラスはシリアル化を?qū)g裝し、サブクラスは自動(dòng)的にシリアル化を?qū)g裝するため、Serializable インターフェイスを明示的に実裝する必要はありません。

3. オブジェクトのインスタンス変數(shù)が他のオブジェクトを參照する場合、オブジェクトがシリアル化されると、參照されるオブジェクトもシリアル化されます。

子類序列化時(shí):
如果父類沒有實(shí)現(xiàn)Serializable接口,沒有提供默認(rèn)構(gòu)造函數(shù),那么子類的序列化會(huì)出錯(cuò);
如果父類沒有實(shí)現(xiàn)Serializable接口,提供了默認(rèn)的構(gòu)造函數(shù),那么子類可以序列化,父類的成員變量不會(huì)被序列化。如果父類
實(shí)現(xiàn)了Serializable接口,則父類和子類都可以序列化。

7. より効率的なシリアル化フレームワークを使用する — Protostuff

実際、Java のネイティブ シリアル化メソッド (Serialable インターフェイスの実裝による) はそれほど効率的ではありません。最高ではありません。

シリアル化の効率を分析するためのプロジェクトが github にあります: https://github.com/eishay/jvm-serializers/wiki

Javaでシリアル化する方法

それを見てください。最もパフォーマンスが良いのは Google が開発した Colfer ですが、Colfer は使いにくいため、ほとんどの人が protostuff シリアル化フレームワークを使用しています。フレームワークを適用するには、2 つのライブラリ (コアとランタイム) を?qū)毪工氡匾ⅳ辘蓼埂?

①github アドレス: https://github.com/protostuff/protostuff

③Maven を使用する場合は、依存関係を追加します:

<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-core</artifactId>
  <version>1.5.9</version>
</dependency>
<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-core</artifactId>
  <version>1.5.9</version>
</dependency>

メイン コードを変更

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
public class Main {
    public static void main(String[] args) {
        User user = new User();
        user.setName("旭旭寶寶");
        user.setAge(33);
        Schema<User> schema = RuntimeSchema.getSchema(User.class);
        // 保存對象,序列化,轉(zhuǎn)化二進(jìn)制數(shù)據(jù)
        LinkedBuffer buffer = LinkedBuffer.allocate(512);
        final byte[] protostuff;
        try {
            protostuff = ProtobufIOUtil.toByteArray(user, schema, buffer);
        } finally {
            buffer.clear();
        }
        // 讀取對象,反序列化
        User userObject = schema.newMessage();
        ProtostuffIOUtil.mergeFrom(protostuff, userObject, schema);
        System.out.println(userObject);
    }
}

User クラスは Serializable インターフェイスを?qū)g裝していません

public class User {
    private String name;
    private int age;
    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;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}

テスト結(jié)果:

Javaでシリアル化する方法

若要要整合Redis使用,也可以寫成一個(gè)工具類:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
public class SerializeUtil {
    private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();
    @SuppressWarnings("unchecked")
    public static <T> byte[] serializer(T obj) {
        Class<T> clazz = (Class<T>) obj.getClass();
        Schema<T> schema = getSchema(clazz);
        return ProtobufIOUtil.toByteArray(obj, schema, LinkedBuffer.allocate(256));
    }
    public static <T> T deSerializer(byte[] bytes, Class<T> clazz) {
        T message;
        try {
            message = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        Schema<T> schema = getSchema(clazz);
        ProtobufIOUtil.mergeFrom(bytes, message, schema);
        return message;
    }
    @SuppressWarnings("unchecked")
    public static <T> Schema<T> getSchema(Class<T> clazz) {
        Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(clazz);
            if (schema != null) {
                cachedSchema.put(clazz, schema);
            }
        }
        return schema;
    }
}

這樣即使我們的User類就不用再實(shí)現(xiàn)Serialiable接口了,同樣可以進(jìn)行序列化,效率也更高。

php中文網(wǎng),大量的免費(fèi)Java入門教程,歡迎在線學(xué)習(xí)!

以上がJavaでシリアル化する方法の詳細(xì)內(nèi)容です。詳細(xì)については、PHP 中國語 Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當(dāng)する法的責(zé)任を負(fù)いません。盜作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

寫真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中國語版

SublimeText3 中國語版

中國語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強(qiáng)力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaのマップを反復(fù)する方法は? Javaのマップを反復(fù)する方法は? Jul 13, 2025 am 02:54 AM

Javaにはマップを通過する3つの一般的な方法があります。1。エントリセットを使用してキーと値を同時(shí)に取得します。これは、ほとんどのシナリオに適しています。 2。キーセットまたは値をそれぞれキーまたは値を通過する。 3. Java8のForeachを使用して、コード構(gòu)造を簡素化します。 EntrySetは、すべてのキー値ペアを含むセットを返し、各ループはキーと値に頻繁にアクセスするのに適したMap.entryオブジェクトを取得します。キーまたは値のみが必要な場合は、それぞれkeyset()またはvalues()を呼び出すことができます。または、キーを橫斷するときにmap.get(key)を介して値を取得できます。 Java 8はForeachを使用できます((key、value) - &gt

Javaの比較対Comparator Javaの比較対Comparator Jul 13, 2025 am 02:31 AM

Javaでは、Defaultのデフォルトソートルールを內(nèi)部的に定義するためにAcparableが使用され、コンパレータを使用して複數(shù)のソートロジックを外部から定義します。 1.Comparableは、クラス自體によって実裝されるインターフェイスです。比較()メソッドを書き換えることにより、自然な順序を定義します。弦や整數(shù)など、固定および最も一般的に使用されるソートメソッドを備えたクラスに適しています。 2。Comparatorは、同じクラスに複數(shù)の並べ替え方法が必要な狀況に適した、Compare()メソッドを介して実裝された外部定義の機(jī)能インターフェイスであり、クラスソースコードを変更できない、またはソートロジックが変更されることが多い場合があります。 2つの違いは、比較可能がソートロジックを定義するだけで、クラス自體を変更する必要があることですが、比較して

Javaのキャラクターエンコーディングの問題を処理する方法は? Javaのキャラクターエンコーディングの問題を処理する方法は? Jul 13, 2025 am 02:46 AM

Javaのキャラクターエンコーディングの問題に対処するために、重要なのは、各ステップで使用されるエンコードを明確に指定することです。 1.テキストを読み書きするときは常にエンコードを指定し、inputstreamreaderとoutputStreamWriterを使用し、明示的な文字セットを渡して、システムのデフォルトエンコードに依存しないようにします。 2.ネットワーク境界で文字列を処理するときに両端が一貫していることを確認(rèn)し、正しいコンテンツタイプのヘッダーを設(shè)定し、ライブラリでエンコードを明示的に指定します。 3. string.getBytes()およびNewString(byte [])を注意して使用し、プラットフォームの違いによって引き起こされるデータの破損を避けるために、常に手動(dòng)でstardantcharsets.utf_8を指定します。要するに、

ハッシュマップはJavaで內(nèi)部的にどのように機(jī)能しますか? ハッシュマップはJavaで內(nèi)部的にどのように機(jī)能しますか? Jul 15, 2025 am 03:10 AM

HashMapは、Javaのハッシュテーブルを介してキーと値のペアストレージを?qū)g裝し、そのコアはデータの位置をすばやく配置することにあります。 1.最初にキーのHashCode()メソッドを使用して、ハッシュ値を生成し、ビット操作を介して配列インデックスに変換します。 2。異なるオブジェクトは、同じハッシュ値を生成し、競合をもたらす場合があります。この時(shí)點(diǎn)で、ノードはリンクされたリストの形式で取り付けられています。 JDK8の後、リンクされたリストが長すぎ(デフォルトの長さ8)、効率を改善するために赤と黒の木に変換されます。 3.カスタムクラスをキーとして使用する場合、equals()およびhashcode()メソッドを書き直す必要があります。 4。ハッシュマップは容量を動(dòng)的に拡大します。要素の數(shù)が容量を超え、負(fù)荷係數(shù)(デフォルト0.75)を掛けた場合、拡張して再ハッシュします。 5。ハッシュマップはスレッドセーフではなく、マルチスレッドでconcuを使用する必要があります

JavaScriptデータ型:プリミティブ対參照 JavaScriptデータ型:プリミティブ対參照 Jul 13, 2025 am 02:43 AM

JavaScriptデータ型は、プリミティブタイプと參照タイプに分割されます。プリミティブタイプには、文字列、數(shù)字、ブール、ヌル、未定義、シンボルが含まれます。値は不変であり、コピーは値を割り當(dāng)てるときにコピーされるため、互いに影響を與えません。オブジェクト、配列、関數(shù)などの參照タイプはメモリアドレスを保存し、同じオブジェクトを指す変數(shù)は互いに影響します。 TypeofとInstanceOFを使用してタイプを決定できますが、TypeOfNullの歴史的な問題に注意してください。これらの2種類の違いを理解することは、より安定した信頼性の高いコードを書くのに役立ちます。

Javaの「靜的」キーワードは何ですか? Javaの「靜的」キーワードは何ですか? Jul 13, 2025 am 02:51 AM

Injava、thestatickeywordmeansameansmestotheclassit self、nottointances.staticvariablesaresharedacrossallinstancesは、Objedcreationを使用して、GlobalTrackingorconconstants.StaticMethododsodsodsoperateateClasslevel

c c Jul 15, 2025 am 01:30 AM

STD :: Chronoは、現(xiàn)在の時(shí)間の取得、実行時(shí)間の測定、操作時(shí)點(diǎn)と期間の測定、分析時(shí)間のフォーマットなど、時(shí)間の処理にCで使用されます。 1。STD:: Chrono :: System_Clock :: now()を使用して、現(xiàn)在の時(shí)間を取得します。 2。STD:: CHRONO :: STEADY_CLOCKを使用して実行時(shí)間を測定して単調(diào)さを確保し、DurateR_CASTを通じてミリ秒、秒、その他のユニットに変換します。 3。時(shí)點(diǎn)(Time_Point)と期間(期間)は相互運(yùn)用可能ですが、ユニットの互換性と時(shí)計(jì)エポック(エポック)に注意を払う必要があります

JavaのReentrantLockとは何ですか? JavaのReentrantLockとは何ですか? Jul 13, 2025 am 02:14 AM

ReentrantLockは、同期するよりもJavaでより柔軟なスレッドコントロールを提供します。 1.非ブロッキングの取得ロック(tryLock())、タイムアウト(TryLock(Longtimeout、TimeUnitunit))および割り込み可能な待機(jī)ロックを使用したロック取得をサポートします。 2。糸の飢erを避けるために公正なロックを許可します。 3.複數(shù)の條件変數(shù)をサポートして、より洗練された待機(jī)/通知メカニズムを?qū)g現(xiàn)します。 4.リソースの漏れを避けるために、ロックを手動(dòng)で解放する必要があります。 5.カスタム同期ツールや複雑な同時(shí)構(gòu)造など、高度な同期制御が必要なシナリオに適していますが、シンクロは単純な相互除外要件にはまだ推奨されています。

See all articles