私は Java に最も精通していますが、Java の基本的な知識はあまりありません。たとえば、transient キーワードはこれまで使用したことがなかったので、その機能が何なのかわかりませんでした。今日の筆記試験で、「以上」に関する質問を見つけたので、一時的なキーワードの使用方法を整理して、本題に取り掛かりました~~~それでは、さっそく始めましょう:
オブジェクトが Serilizable インターフェイスを実装している限り、オブジェクトはシリアル化できることは誰もが知っています。Java のこのシリアル化モードは、開発者に特定のシリアル化について心配する必要がありません。クラスが Serilizable インターフェイスを実装している限り、このクラスのすべてのプロパティとメソッドは自動的にシリアル化されます。
しかし、実際の開発プロセスでは、このクラスの一部の属性はシリアル化する必要がありますが、他の属性はシリアル化する必要がありません。たとえば、ユーザーが何らかの機密情報を持っている場合などです。パスワード、銀行カード番号など)、セキュリティ上の理由から、ネットワーク操作中に送信されたくない場合(主にシリアル化操作が含まれ、ローカルのシリアル化キャッシュも適用されます)、この情報に対応する変数を一時的なキーワード。つまり、このフィールドのライフサイクルは呼び出し元のメモリ内にのみ存在し、永続化のためにディスクに書き込まれることはありません。
つまり、Java の transient キーワードは、Serilizable インターフェイスを実装し、オブジェクトをシリアル化する必要のないプロパティの前にキーワード transient を追加するだけで便利です。指定された目的地へ。
サンプル コードは次のとおりです:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * @description 使用transient关键字不序列化某个变量 * 注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致 * * @author Alexia * @date 2013-10-15 */ public class TransientTest { public static void main(String[] args) { User user = new User(); user.setUsername("Alexia"); 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("C:/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( "C:/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(); } } } class User implements Serializable { private static final long serialVersionUID = 8294180014912103005L; 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; } }
出力は次のとおりです:
read before Serializable: username: Alexia password: 123456 read after Serializable: username: Alexia password: null
パスワード フィールドは null で、逆シリアル化中にファイルから情報がまったく取得されないことを示します。
1) 変数が一時的に変更されると、その変数はオブジェクトの永続化の一部ではなくなり、シリアル化後は変数の内容にアクセスできなくなります。
2) transient キーワードは変数のみを変更できますが、メソッドやクラスは変更できません。ローカル変数は transient キーワードでは変更できないことに注意してください。変数がユーザー定義のクラス変数の場合、クラスは Serializable インターフェイスを実装する必要があります。
3) transient キーワードによって変更された変数はシリアル化できなくなりました。transient によって変更されたかどうかに関係なく、静的変数はシリアル化できなくなりました。
3 番目の点は、User クラスのユーザー名フィールドの前に static キーワードを追加した後、プログラムの実行結果が変化しないことが判明したため、一部の人は混乱するかもしれません。つまり、静的ユーザー名も「Alexia」として読み取られます。これは3番目の点と矛盾しませんか?これは実際に当てはまります。3 番目の点は確かに当てはまります (静的変数は、非シリアル化の後、クラス内の静的変数 username の値は、対応する静的変数の値になります)。現在の JVM では、この値は逆シリアル化ではなく JVM から派生します。さて、以下で証明してみましょう:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * @description 使用transient关键字不序列化某个变量 * 注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致 * * @author Alexia * @date 2013-10-15 */ public class TransientTest { public static void main(String[] args) { User user = new User(); user.setUsername("Alexia"); 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("C:/user.txt")); os.writeObject(user); // 将User对象写进文件 os.flush(); os.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { // 在反序列化之前改变username的值 User.username = "jmwang"; ObjectInputStream is = new ObjectInputStream(new FileInputStream( "C:/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(); } } } class User implements Serializable { private static final long serialVersionUID = 8294180014912103005L; 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; } }
実行結果は次のとおりです:
read before Serializable: username: Alexia password: 123456 read after Serializable: username: jmwang password: null
これは、逆シリアル化後のクラスの静的変数 username の値が、現在の JVM の対応する静的変数の値であることを示しています。これは、シリアル化時の値 Alexia ではなく、変更された jmwang の値です。
次の例を考えてみましょう:
import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; /** * @descripiton Externalizable接口的使用 * * @author Alexia * @date 2013-10-15 * */ 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(); } }
content 変数はシリアル化されますか?はい、実行結果は次のようになります:
是的,我将会被序列化,不管我是否被transient关键字修饰
これは、transient キーワードによって変更された後はクラス変数をシリアル化できないという意味ではないでしょうか?
Java では、Serializable インターフェイスが実装されている場合は、すべてのシリアル化が自動的に実行されます。自動シリアル化のためには何もする必要はありません。 writeExternal メソッドでシリアル化する変数を手動で指定します。これは、一時的に変更されるかどうかとは関係ありません。したがって、2 番目の例では、null ではなく、変数 content の初期化された内容が出力されます。
上記は Java 一時キーワードの使用法をまとめたものです。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。