J2SE中的序默认序列化_MySQL
J2SE
要保存的也被保存了下来。一般情况下,我们仅仅需要保存逻辑数据就可以了。不需要保存的数据我们可以用关键字transient标出。
以下是一个例子:
import java.io.*;
public class Serial implements Serializable {
int company_id;
String company_addr;
transient boolean company_flag;
}
则company_flag字段将不会参与序列化与反序列化,但同时你也增加了为他初始值的责任。这也是序列化常常导致的问题之一。因为序列化相当于一个只接受数据流的public构造函数,这种对象构造方法是语言之外的。但他仍然是一种形式上的构造函数。如若你的类不能够通过其他方面来保证初始化,则你需要额外的提供readObject方法,首先正常的反序列化,然后对transient标示的字段进行初始化。
在不适合的时候,使用java默认的序列化行为可能会带来速度上的影响,最糟糕的情况是,可能导致溢出。在某些数据结构的实现中,经常会充斥着各种的循环引用,而java的默认序列化行为,并不了解你的对象结构,其结果就是java试图通过一种昂贵的“图遍历”来保存对象状态。可想而知,不但慢而且可能溢出。这时候你就要提供自己的readObject,来代替默认的行为。
兼容性问题
兼容性历来是复杂而麻烦的问题。
不要兼容性:
首先来看看如果我们的目的是不要兼容性,应该注意哪些。不要兼容性的场合很多,比如war3每当版本升级就不能够读取以前的replays。
兼容也就是版本控制,java通过一个名为UID(stream unique identifier)来控制,这个UID是隐式的,它通过类名,方法名等诸多因素经过计算而得,理论上是一一映射的关系,也就是唯一的。如果UID不一样的话,就无法实现反序列化了,并且将会得到InvalidClassException。
当我们要人为的产生一个新的版本(实现并没有改动),而抛弃以前的版本的话,可以通过显式的声名UID来实现:
private static final long serialVersionUID=????;
你可以编造一个版本号,但注意不要重复。这样在反序列化的时候老版本将得到InvalidClassException,我们可以在老版本的地方捕捉这个异常,并提示用户升级的新的版本。
当改动不大时,保持兼容性(向下兼容性的一个特例):
有时候你的类增加了一些无关紧要的非私有方法,而逻辑字段并不改变的时候,你当然希望老版本和新版本保持兼容性,方法同样是通过显式的声名UID来实现。下面我们验证一下。
老版本:
import java.io.*;
public class Serial implements Serializable {
int company_id;
String company_addr;
public Serial1(int company_id, String company_addr) {
this.company_id = company_id;
this.company_addr = company_addr;
}
public String toString() {
return "DATA: "+company_id+" "+
company_addr;
}
}
新版本
import java.io.*;
public class Serial implements Serializable {
int company_id;
String company_addr;
public Serial1(int company_id, String company_addr) {
this.company_id = company_id;
this.company_addr = company_addr;
}
public String toString() {
return "DATA: "+company_id+" "+ company_addr;
}
public void todo(){}//无关紧要的方法
}
首先将老版本序列化,然后用新版本读出,发生错误:
java.io.InvalidClassException: Serial.Serial1; local class incompatible: stream classdesc serialVersionUID = 762508508425139227, local class serialVersionUID = 1187169935661445676
接下来我们加入显式的声名UID:
private static final long serialVersionUID=762508508425139227l;
再次运行,顺利地产生新对象
DATA: 1001 com1
如何保持向上兼容性:
向上兼容性是指老的版本能够读取新的版本序列化的数据流。常常出现在我们的服务器的数据更新了,仍然希望老的客户端能够支持反序列化新的数据流,直到其更新到新的版本。可以说,这是半自动的事情。
跟一般的讲,因为在java中serialVersionUID是唯一控制着能否反序列化成功的标志,只要这个值不一样,就无法反序列化成功。但只要这个值相同,无论如何都将反序列化,在这个过程中,对于向上兼容性,新数据流中的多余的内容将会被忽略;对于向下兼容性而言,旧的数据流中所包含的所有内容都将会被恢复,新版本的类中没有涉及到的部分将保持默认值。利用这一特性,可以说,只要我们认为的保持serialVersionUID不变,向上兼容性是自动实现的。
当然,一但我们将新版本中的老的内容拿掉,情况就不同了,即使UID保持不变,会引发异常。正是因为这一点,我们要牢记一个类一旦实现了序列化又要保持向上下兼容性,就不可以随随便便的修改了!!!
测试也证明了这一点,有兴趣的读者可以自己试一试。
如何保持向下兼容性:
一如上文所指出的,你会想当然的认为只要保持serialVersionUID不变,向下兼容性是自动实现的。但实际上,向下兼容要复杂一些。这是因为,我们必须要对那些没有初始化的字段负责。要保证它们能被使用。
所以必须要利用
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException{
in.defaultReadObject();//先反序列化对象
if(ver=5552){
//以前的版本5552
…初始化其他字段
}else if(ver=5550){
//以前的版本5550
…初始化其他字段
}else{
//太老的版本不支持
throw new InvalidClassException();
}
}
细心的读者会注意到要保证in.defaultReadObject();能够顺利执行,就必须要求serialVersionUID保持一致,所以这里的ver不能够利用serialVersionUID了。这里的ver是一个我们预先安插好的final long ver=xxxx;并且它不能够被transient修饰。所以保持向下的兼容性至少有三点要求:
1.serialVersionUID保持一致
2.预先安插好我们自己的版本识别标志的final long ver=xxxx;
3.保证初始化所有的域
讨论一下兼容性策略:
到这里我们可以看到要保持向下的兼容性很麻烦。而且随着版本数目的增加。维护会变得困难而繁琐。讨论什么样的程序应该使用怎么样的兼容性序列化策略已经超出本文的范畴,但是对于一个游戏的存盘功能,和对于一个字处理软件的文档的兼容性的要求肯定不同。对于rpg游戏的存盘功能,一般要求能够保持向下兼容,这里如果使用java序列化的方法,则可根据以上分析的三点进行准备。对于这样的情况使用对象序列化方法还是可以应付的。对于一个字处理软件的文档的兼容性要求颇高,一般情况下的策略都是要求良好的向下兼容性,和尽可能的向上兼容性。则一般不会使用对象序列化技术,一个精心设计的文档结构,更能解决问题。
数据一致性问题、约束问题
要知道序列化是另一种形式上的“public构造函数”,但他仅仅构造起对象,而不作任何的检查,这样人很不舒服,所以必要的检查是必须的,这利用了readObject()
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException{
in.defaultReadObject();//先反序列化对象
…进行检查与初始化
}
出于结构化的考虑,通常使用一个名为initialize的函数,负责检查与初始化,如果失败抛出异常。要保持检查与初始化是很容易被忘记的,这常常导致问题。另一个问题在于当父类没有加入readObject()的时候,子类很容易忘记要调用对应的initialize函数。这仿佛回到了当初为什么要引入构造函数的问题,原因就是防止子类忘记调用初始化函数引发各种问题。所以,如果要保持数据一致性,一定要加入readObject()。
安全问题
安全性的话题超出了本文的范畴,但是你应该要知道,有可能一个攻击者会对你的类准备一个恶意的数据流企图生成一个错误的类。当你需要确保你的对象数据安全的话,你一般可以利用上面的方法来检查,并初始化,但对于某些引用不好检查。解决方法就是对重要的部件进行保护性拷贝。这里推荐一个好方法,它不用保护性拷贝个别的域,而是直接保护性拷贝整个对象。这就是:
Object readResolve() throws ObjectStreamException;
这个方法的用途就是,他会紧接着readObject()调用。它将会利用返回的对象代替原来反序列化的对象。也就是原来readObject()反序列化的对象将会被立即的丢弃。
Object readResolve() throws ObjectStreamException{
return new Serial2(this.xxx1,this.xxx2);// xxx1、xxx2是刚刚反序列化得来的,这是一种保护性拷贝
}
这样的话虽然在时间上有所浪费,但是对于特别的重要而安全的类,可以使用这种方法。如果数据一致性问题、约束问题通过逐一检查来解决很麻烦,也可以利用这种方法,但要考虑好成本,和注意下面的局限性。 利用readResolve()有一个明显的缺点,就是当父类实现了readResolve(),子类将变得无丛下手。如果一个保护的或者是公有的父类的readResolve()存在,并且子类也没有改写它,将会使得子类反序列化的时候最终得到一个父类的对象,这既不是我们要得结果,也不容易发现这种错误。而让子类重写readResolve()无疑是一个负担。也就是说对于要继承的类而言,实现readResolve()来保护类不是一个好方法。我们只能利用第一种方法写一个保护性的readObject()。
所以我的建议是:一般情况下,只有对于final的类采用readResolve()来进行保护。

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Untuk mengemas kini versi curl di bawah Linux, anda boleh mengikuti langkah di bawah: Semak versi curl semasa: Pertama, anda perlu menentukan versi curl yang dipasang dalam sistem semasa. Buka terminal dan laksanakan arahan berikut: curl --version Perintah ini akan memaparkan maklumat versi curl semasa. Sahkan versi curl tersedia: Sebelum mengemas kini curl, anda perlu mengesahkan versi terkini yang tersedia. Anda boleh melawati tapak web rasmi curl (curl.haxx.se) atau sumber perisian yang berkaitan untuk mencari versi terkini curl. Muat turun kod sumber curl: Menggunakan curl atau penyemak imbas, muat turun fail kod sumber untuk versi curl pilihan anda (biasanya .tar.gz atau .tar.bz2

Selesai dalam satu minit: Cara mengemas kini versi pip, contoh kod khusus diperlukan Dengan perkembangan pesat Python, pip telah menjadi alat standard untuk pengurusan pakej Python. Walau bagaimanapun, seiring dengan berlalunya masa, versi pip sentiasa dikemas kini Untuk dapat menggunakan ciri terkini dan memperbaiki kemungkinan kelemahan keselamatan, adalah sangat penting untuk mengemas kini versi pip. Artikel ini akan menerangkan cara mengemas kini pip dengan cepat dalam satu minit dan memberikan contoh kod khusus. Pertama, kita perlu membuka tetingkap baris arahan. Dalam sistem Windows, anda boleh menggunakan

Menyemak versi sistem pengendalian Kylin dan versi kernel Dalam sistem pengendalian Kirin, mengetahui cara menyemak versi sistem dan versi kernel adalah asas untuk pengurusan dan penyelenggaraan sistem. Kaedah 1 untuk menyemak versi sistem pengendalian Kylin: Gunakan fail /etc/.kyinfo Untuk menyemak versi sistem pengendalian Kylin, anda boleh menyemak fail /etc/.kyinfo. Fail ini mengandungi maklumat versi sistem pengendalian. Jalankan arahan berikut: cat/etc/.kyinfo Perintah ini akan memaparkan maklumat versi terperinci sistem pengendalian. Kaedah 2: Gunakan fail /etc/issue Cara lain untuk menyemak versi sistem pengendalian adalah dengan melihat fail /etc/issue. Fail ini juga menyediakan maklumat versi, tetapi mungkin tidak sebaik fail .kyinfo

Maksud dan perbezaan versi PHP NTS PHP ialah bahasa skrip sebelah pelayan yang popular yang digunakan secara meluas dalam bidang pembangunan web. Terdapat dua versi utama PHP: ThreadSafe(TS) dan Non-ThreadSafe(NTS). Di laman web rasmi PHP, kita boleh melihat dua versi muat turun PHP yang berbeza, iaitu PHPNTS dan PHPTS. Jadi, apakah maksud NTS versi PHP? Apakah perbezaan antara versi TS? Seterusnya,

Cara menyemak versi Oracle yang dipasang dengan mudah memerlukan contoh kod khusus Sebagai perisian yang digunakan secara meluas dalam sistem pengurusan pangkalan data peringkat perusahaan, pangkalan data Oracle mempunyai banyak versi dan kaedah pemasangan yang berbeza. Dalam kerja harian kami, kami sering perlu menyemak versi pangkalan data Oracle yang dipasang untuk operasi dan penyelenggaraan yang sepadan. Artikel ini akan memperkenalkan cara menyemak versi Oracle yang dipasang dengan mudah dan memberikan contoh kod tertentu. Kaedah 1: Melalui pertanyaan SQL dalam pangkalan data Oracle, kita boleh

Mengenai Llama3, keputusan ujian baharu telah dikeluarkan - komuniti penilaian model besar LMSYS mengeluarkan senarai kedudukan model besar Llama3 menduduki tempat kelima, dan terikat untuk tempat pertama dengan GPT-4 dalam kategori Bahasa Inggeris. Gambar ini berbeza daripada Penanda Aras yang lain Senarai ini berdasarkan pertempuran satu lawan satu antara model, dan penilai dari seluruh rangkaian membuat cadangan dan skor mereka sendiri. Pada akhirnya, Llama3 menduduki tempat kelima dalam senarai, diikuti oleh tiga versi GPT-4 dan Claude3 Super Cup Opus yang berbeza. Dalam senarai tunggal Inggeris, Llama3 mengatasi Claude dan terikat dengan GPT-4. Mengenai keputusan ini, ketua saintis Meta LeCun sangat gembira, tweet semula dan

Mengapa Python begitu popular? Sebabnya mudah: ia mudah dipelajari, mudah digunakan dan cepat digunakan, menjadikannya sesuai untuk pemula. Tidak kira apa projek itu, selagi ia melibatkan pengaturcaraan, Python selalunya menjadi pilihan pertama saya. Selain itu, anda tidak perlu berpegang kepada sistem Linux, Windows juga boleh menyokongnya dengan baik. Saya telah memasang Python pada sistem pengendalian Windows 11 saya dan saya sering menggunakannya untuk menulis program dan menjalankan kod. Memasang Python pada Windows adalah sangat mudah Seterusnya saya akan berkongsi dua kaedah pemasangan biasa. Pilih versi Python yang sesuai. Python menyediakan berbilang versi Sangat penting untuk memilih versi yang sesuai Ini berkaitan dengan keserasian dan kefungsian program: versi semasa termasuk Python2 dan

Antara muka DP adalah kabel antara muka yang penting dalam komputer Apabila menggunakan komputer, ramai pengguna ingin mengetahui sama ada antara muka DP adalah 1.2 atau 1.4, mereka hanya perlu menyemaknya dalam GPU-Z. Cara menentukan sama ada antara muka dp ialah 1.2 atau 1.4: 1. Mula-mula, pilih "Lanjutan" dalam GPU-Z. 2. Lihat "Monitor1" dalam "General" di bawah "Advanced", anda boleh melihat dua item "LinkRate (semasa)" dan "Lanes (semasa)". 3. Akhir sekali, jika 8.1Gbps×4 dipaparkan, ia bermakna versi DP1.3 atau lebih tinggi, biasanya DP1.4 Jika 5.4Gbps×4, maka
