はじめに
いくつかの時間のjavaの真理を学んだ友人を伝えるためにはtransient
、この基本的なキーワードを使用していないか、まだ非常に奇妙ですが、transient
Javaでのキーワードは、不可欠な役割を果たしてきました!あなたが言及したと言う場合は言及されたときに、私が最も可能性の高い場所はIOストリームフローオブジェクトだと思います(とも呼ばれる直列化ストリーム)!
私は多くの人々は彼がキーワード満たされるまで、この気に最初に会ったブロガー覚えているだろうと信じてtransient
読むときJDKソースにキーワードを。でJavaを学習するプロセスではtransient
その役割から、実際の不可分では珍しいキーワードの原因:transient
主な役割は、特定のキーワードを作ることである過渡主要メンバー属性変数がシリアライズされていない変更されます。学習過程でめったに通常、実際の開発では、シリアル化操作を使用する理由、実際にはそれもあります!シリアライズに関しては、私は白い靴がたくさんつまずいたかは特定の概念ではありませんが、これはものではありません信じて、以下のブロガーは明らかに、あなたが今までに(少しのようなルックスを忘れることを保証するためにシリアライズされたものを覚えているでしょう誇張、少しインストールされたB、演奏する感覚)
@
1.何をシリアライズされましたか?
直列化といえば、別のコンセプトのデシリアライズが続いた、白い靴はそう、直列化復元が順番に連載されているため、同等のシーケンスをデシリアライズさを覚えて覚えて、慌てる必要はありませんブロガーは自分の州で混乱概念のシーケンスを、覚えておくことをお勧め。
用語は、一連の定義しました:
Javaはオブジェクトのシリアル化メカニズムを提供します。オブジェクトは、バイトシーケンス、オブジェクトデータを含むバイト配列で表されることができ、オブジェクトの種類は、オブジェクト情報に格納された属性。ファイルに書き込まれたバイトのシーケンスの後、ファイルは、永続オブジェクトに格納された情報に対応します。逆に、バイトシーケンスがまた、ファイルの後ろから読んで並べ替えることができ、それがデシリアライズされます。オブジェクトに格納されたデータオブジェクト、データ・タイプおよびオブジェクトは、メモリ内のオブジェクトを作成するために使用することができます。
Ichunシーケンスの定義:
シリアライズ:バイト- >オブジェクト
実際に、私は上記の結論はあなたがライン上で私の言葉を、専門用語の定義への直接参照を理解し、マークした後、それを理解していない場合は、覚えていることである要約、私を殺すしてください(私は演奏は、単に天才であるM)
図は、シリアル化を理解する:
何を?あなたはバイトであるのか分からないのですか?知っている記事名でちょうど見て-実際に、私IOは、安心の記事を連載で紹介してきた絶対に非常に詳しくストリーム-
ショーの中で最も完全な歴史の最も詳細なチュートリアルIOはホワイトが理解できる、ストリーム!
2.なぜシリアライズ?
1から概念の順序を述べ、その後、コンセプトを知って、私たちは、あなたがシリアル化したい理由を知っている必要があります。
私は栗を与えるあなたがシリアライズしたい理由、ブロガーの話をする前に:
あなたは食べ物を買うために街に行くと同じように、一般的な操作が出し料理を調理するために家に行く時まで、包むためにビニール袋です。シリアライズとデシリアライズの最もなどの一連の作業!
Javaオブジェクトのシリアル化は、バイトの前記配列にバイト配列にオブジェクトを参照し、オブジェクトのシーケンスの後、オブジェクトのデータ情報が含まれているファイルまたはデータベースに書き込まれてもよい、または以下のために使用することができるネットワーク伝送私たちが使用している場合、一般的に、キャッシュキャッシュ(十分なメモリ容量がないハードディスクにローカルに格納されていてもよい)、またはリモートコールRPC(ネットワーク伝送)を、私たちはしばしば私たちのエンティティクラスの実装を取得する必要があるインターフェイスを、目的はそれができるようにすることです連載。 Serializable
- 開発プロセスでは過渡的に使用するキーワードを栗を変更:
ユーザーは、いくつかのパスワードやその他の情報を持っている場合は、セキュリティ上の理由から、私たちは情報に対応する変数がtransientキーワードを追加することができ、ネットワーク運用に送信する必要はありません。言い換えれば、この分野のライフサイクルは、呼び出し元のメモリに持続性にディスクに書き込まれることはありませんが存在します。
- 開発プロセスの間、過渡必要としないキーワード修正栗:
1、クラスフィールドの値が他のフィールドに基づいて導出されてもよいです。
2、フィールドをシリアル化したくなかった、特定のビジネスニーズ、見て。
木材や他のBEは、それがシリアル化され、なぜ私はあなたが今まで疑問に思ったのか分からないのですか?実際には、主にストレージ・スペースを節約するためです。オプティマイザ!
PS:私は前に見て覚えて
HashMap
、ソースコード、私はフィールドがされている見つかったtransient
変更が、私はそれが理にかなっていると思いますが、何の意味がないので、modCountは、主に(HashMapのが変更されたかどうかを判断するために使用され、このmodCountフィールドをシリアル化する必要はありません。プットのように、動作時間を削除modCount
インクリメントします)、この変数のため、スタートは任意の値にすることができ、もちろん、アウトデシリアライズ0(新発売される、すべての時間外クローンまたはクローン)は0でありますその値を永続化する必要はありません。
もちろん、究極の目標は、直列化するために非直列化されて、なぜそれ一連のJavaオブジェクトの元、またはそれ以外に復元、食料品の買い物のような安全な家の便宜のために最後に包まれたビニール袋で、その後、ビニール袋を取り外しバイトのシーケンスは、Javaオブジェクトをリストアするシリアライズように、このプロセスはデシリアライズされます。
3、一過性の使用のシーケンス
1は、シリアライズされたオブジェクトのクラスを実行する必要がある、あなたはシリアルインタフェースを実装する必要があります。Java.lang.Serializableインターフェース:(マーカーインタフェース、何の抽象メソッドはありませんが)、Javaクラスは、次のような、インタフェースのほとんどに実装されているString
、Integer
など、スローされます、どのような状態の直列化または直列化復元をすることはありませんこのタイプのインタフェースを実装していないNotSerializableException
例外を。
現在のオブジェクトがあれば2、ボトム層は決定するSerializable
だけシリアル化を行うには許可され、例えば、Java(登録商標)は、オブジェクトinstanceof Serializable
決定されます。
3、Javaでオブジェクトのストリームを使用するObjectOutputStream
シリアル化と完全にObjectInputStream
非直列化の流れ
== ObjectOutputStreamの:()==方法シリアライゼーションのwriteObjectによって行わ
==のObjectInputStream:()にreadObjectによって==直列化復元を作る方法
4、クラスのすべてのプロパティは、シリアライズ可能である必要があります。プロパティをシリアル化する必要がない場合、そのプロパティは使用して、過渡的にマークされなければならないtransient
キーワードの変更を。
まあそれも流れてObjectOutputStream、以下の操作コードのシーケンスの様々な事例分析を直列化オブジェクトのストリームと呼ばれる操作、に関与していることが確かにバイトストリームによるものです!
ここでは、私は本当に強く、宜春市は読者や友人のブログを見て、逃げるために、ノックの上にコピーを持参することを忘れないでくださいまたは過去に実行してみてくださいお勧めします特に白い靴、私を信じて!あなたは別の収穫を持っている必要があります。宜春市の個人的な経験、時々遅い速いです、時間の無駄を考えてはいけません!
3.1、シリアライズシリアライズの実装はありません
package TransientTest;
import java.io.*;
class UserInfo { //================================注意这里没有实现Serializable接口
private String name;
private transient String password;
public UserInfo(String name,String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) {
UserInfo userInfo=new UserInfo("老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt"));
output.writeObject(new UserInfo("老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
業績
3.2、シリアル化の実装シリアライズ
私たちは実装を追加するときに表示される項目を見つけるでしょうSerializableを実行しuserinfo.txt
たコンテンツファイルはこれである:
実際には、これがない焦点で、焦点は、操作のシーケンス成功です!
3.3ここで、通常の配列
package TransientTest;
import java.io.*;
class UserInfo implements Serializable{ //第一步实现Serializable接口
private String name;
private String password;//都是普通属性==============================
public UserInfo(String name,String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) throws ClassNotFoundException {
UserInfo userInfo=new UserInfo("程序员老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt")); //第二步开始序列化操作
output.writeObject(new UserInfo("程序员老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream input=new ObjectInputStream(new FileInputStream("userinfo.txt"));//第三步开始反序列化操作
Object o = input.readObject();//ObjectInputStream的readObject方法会抛出ClassNotFoundException
System.out.println("序列化之后信息:"+o);
} catch (IOException e) {
e.printStackTrace();
}
}
}
結果:
序列化之前信息:UserInfo{name='程序员老王', password='123'}
序列化之后信息:UserInfo{name='程序员老王', password='123'}
3.4、過渡シリアライズケース
package TransientTest;
import java.io.*;
class UserInfo implements Serializable{ //第一步实现Serializable接口
private String name;
private transient String password; //特别注意:属性由transient关键字修饰===========
public UserInfo(String name,String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) throws ClassNotFoundException {
UserInfo userInfo=new UserInfo("程序员老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt")); //第二步开始序列化操作
output.writeObject(new UserInfo("程序员老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream input=new ObjectInputStream(new FileInputStream("userinfo.txt"));//第三步开始反序列化操作
Object o = input.readObject();//ObjectInputStream的readObject方法会抛出ClassNotFoundException
System.out.println("序列化之后信息:"+o);
} catch (IOException e) {
e.printStackTrace();
}
}
}
結果:
序列化之前信息:UserInfo{name='程序员老王', password='123'}
序列化之后信息:UserInfo{name='程序员老王', password='null'}
結果には特に注意、既定値のプロパティの過渡的な変更を加えることnull
!int型のプロパティの過渡変更した場合、それはその後、シリアライズされた値でなければなりません0である、もちろん、あなたはそれが言うことができるか、試してみることができますか?説明がマークされているtransient
オブジェクトがシリアライズされたときに属性が保存されません(変数やない永続的な)
3.5、静的な状況がシリアライズ
package TransientTest;
import java.io.*;
class UserInfo implements Serializable{ //第一步实现Serializable接口
private String name;
private static String password; //特别注意:属性由static关键字修饰==============
public UserInfo(String name, String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) throws ClassNotFoundException {
UserInfo userInfo=new UserInfo("程序员老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt")); //第二步开始序列化操作
output.writeObject(new UserInfo("程序员老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream input=new ObjectInputStream(new FileInputStream("userinfo.txt"));//第三步开始反序列化操作
Object o = input.readObject();//ObjectInputStream的readObject方法会抛出ClassNotFoundException
System.out.println("序列化之后信息:"+o);
} catch (IOException e) {
e.printStackTrace();
}
}
}
結果:
序列化之前信息:UserInfo{name='程序员老王', password='123'}
序列化之后信息:UserInfo{name='程序员老王', password='123'}
この時間は、あなたが誤っている静的な変更も連載されていると信じていますが、それは真実ではない、実際には、ここでは混乱するのは簡単です!明らかにアウトnull
(デフォルト値)連載ではない、デフォルト値になりますが、明らかに存在しない説明することができ、なぜ私たちが言っているんstatic
それをシリアル化されないのだろうか?
实际上,反序列化后类中static型变量name的值实际上是当前JVM中对应static变量的值,这个值是JVM中的并不是反序列化得出的。也就是说被static修饰的变量并没有参与序列化!但是咱也不能口说无凭啊,是的,那我们就来看两个程序对比一下就明白了!
第一个程序:这是一个没有被static修饰的name属性程序:
package Thread;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class UserInfo implements Serializable {
private String name;
private transient String psw;
public UserInfo(String name, String psw) {
this.name = name;
this.psw = psw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
public String toString() {
return "name=" + name + ", psw=" + psw;
}
}
public class TestTransient {
public static void main(String[] args) {
UserInfo userInfo = new UserInfo("程序员老过", "456");
System.out.println(userInfo);
try {
// 序列化,被设置为transient的属性没有被序列化
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
o.writeObject(userInfo);
o.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
try {
//在反序列化之前改变name的值 =================================注意这里的代码
userInfo.setName("程序员老改");
// 重新读取内容
ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
UserInfo readUserInfo = (UserInfo) in.readObject();
//读取后psw的内容为null
System.out.println(readUserInfo.toString());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
运行结果:
name=程序员老过, psw=456
name=程序员老过, psw=null
从程序运行结果中可以看出,在反序列化之前试着改变name的值为程序员老改,结果是没有成功的!
第二个程序:这是一个被static修饰的name属性程序:
package Thread;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class UserInfo implements Serializable {
private static final long serialVersionUID = 996890129747019948L;
private static String name;
private transient String psw;
public UserInfo(String name, String psw) {
this.name = name;
this.psw = psw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
public String toString() {
return "name=" + name + ", psw=" + psw;
}
}
public class TestTransient {
public static void main(String[] args) {
UserInfo userInfo = new UserInfo("程序员老过", "456");
System.out.println(userInfo);
try {
// 序列化,被设置为transient的属性没有被序列化
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
o.writeObject(userInfo);
o.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
try {
//在反序列化之前改变name的值
userInfo.setName("程序员老改");
// 重新读取内容
ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
UserInfo readUserInfo = (UserInfo) in.readObject();
//读取后psw的内容为null
System.out.println(readUserInfo.toString());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
运行结果:
name=程序员老过, psw=456
name=程序员老改, psw=null
从程序运行结果中可以看出,在反序列化之前试着改变name的值为程序员老改,结果是成功的!现在对比一下两个程序是不是就很清晰了?
static关键字修饰的成员属性优于非静态成员属性加载到内存中,同时静态也优于对象进入到内存中,被static修饰的成员变量不能被序列化,序列化的都是对象,静态变量不是对象状态的一部分,因此它不参与序列化。所以将静态变量声明为transient变量是没有用处的。因此,反序列化后类中static型变量name的值实际上是当前JVM中对应static变量的值,这个值是JVM中的并不是反序列化得出的。
如果对static关键字还是不太清楚理解的童鞋可以参考这篇文章,应该算是不错的:深入理解static关键字
3.6、final序列化情况
对于final关键字来讲,final变量将直接通过值参与序列化,至于代码程序我就不再贴出来了,大家可以试着用final修饰验证一下!
主要注意的是final 和transient可以同时修饰同一个变量,结果也是一样的,对transient没有影响,这里主要提一下,希望各位以后在开发中遇到这些情况不会满头雾水!
4、java类中serialVersionUID作用
既然提到了transient关键字就不得不提到序列化,既然提到了序列化,就不得不提到serialVersionUID
了,它是啥呢?基本上有序列化就会存在这个serialVersionUID。
serialVersionUID
适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID
来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID
与本地相应实体类的serialVersionUID
进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException
,在开发中有时候可写可不写,建议最好还是写上比较好。
5、transient关键字小结
1、变量被transient修饰,变量将不会被序列化
2、transient关键字只能修饰变量,而不能修饰方法和类。
3、被static关键字修饰的变量不参与序列化,一个静态static变量不管是否被transient修饰,均不能被序列化。
4、final变量值参与序列化,final transient同时修饰变量,final不会影响transient,一样不会参与序列化
第二点需要注意的是:本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口
第三点需要注意的是:反序列化后类中static型变量的值实际上是当前JVM中对应static变量的值,这个值是JVM中的并不是反序列化得出的。
结语:被transient关键字修饰导致不被序列化,其优点是可以节省存储空间。优化程序!随之而来的是会导致被transient修饰的字段会重新计算,初始化!
如果本文对你有一点点帮助,那么请点个赞呗,谢谢~
若有不足或者不正之处,欢迎指正批评,感激不尽!如果有疑问欢迎留言,绝对第一时间回复!
最後に、技術、憧れの技術を議論するために私達の注意に公共の宜春番号を、歓迎し、技術の追求は、良いポットは友達がああ来ていると述べました...