`
837062099
  • 浏览: 112644 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

如何序列化transient和static修饰的变量

阅读更多
通常情况下,用transient和static修饰的变量是不能被序列化的,但是通过在序列化的类中写writeObject(ObjectOutputStream stream)和readObject(ObjectInputStream stream)方法,可以实现序列化。

有人说static的变量为什么不能序列化,因为static的变量可能被改变。
static final的常量可以被序列化。

package demo.serializable.advance;

import java.io.*;

public class OverrideSerial implements Serializable {

	private static final long serialVersionUID = -1608783310676957433L;
	
	private static int count; // 用于计算OverrideSerial对象的数目
	private static final int MAX_COUNT = 1000;
	private String name;
	private transient String password = "origin";

	static {
		System.out.println("调用OverrideSerial类的静态代码块 ");
	}

	public OverrideSerial() {
		System.out.println("调用OverrideSerial类的不带参数的构造方法 ");
		count++;
	}

	public OverrideSerial(String name, String password) {
		System.out.println("调用OverrideSerial类的带参数的构造方法 ");
		this.name = name;
		this.password = password;
		count++;
	}

	/**
	 * 加密数组,将buff数组中的每个字节的每一位取反 例如13的二进制为00001101,取反后为11110010
	 */
	private byte[] change(byte[] buff) {
		for (int i = 0; i < buff.length; i++) {
			int b = 0;
			for (int j = 0; j < 8; j++) {
				int bit = (buff[i] >> j & 1) == 0 ? 1 : 0;
				b += (1 << j) * bit;
			}
			buff[i] = (byte) b;
		}
		return buff;
	}

	private void writeObject(ObjectOutputStream stream) throws IOException {
		stream.defaultWriteObject(); // 先按默认方式序列化
		stream.writeObject(change(password.getBytes()));
		stream.writeInt(count);
	}

	private void readObject(ObjectInputStream stream) throws IOException,
			ClassNotFoundException {
		stream.defaultReadObject(); // 先按默认方式反序列化
		byte[] buff = (byte[]) stream.readObject();
		password = new String(change(buff));
		count = stream.readInt();
	}

	public String toString() {
		return "count= " + count + "   MAX_COUNT= " + MAX_COUNT + "   name= "
				+ name + "   password= " + password;
	}

	public static void main(String[] args) throws IOException,
			ClassNotFoundException {

		FileOutputStream fos = new FileOutputStream("/OverrideSerial.txt");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		OverrideSerial osInput1 = new OverrideSerial("leo1","akiy1231");
		OverrideSerial osInput2 = new OverrideSerial("leo2","akiy1232");
		OverrideSerial osInput3 = new OverrideSerial("leo3","akiy1233");
		oos.writeObject(osInput1);
		oos.writeObject(osInput2);
		oos.writeObject(osInput3);
		oos.flush();
		oos.close();
		
		count =100;
		osInput1.name="change";
		
		FileInputStream fis = new FileInputStream("/OverrideSerial.txt");
		ObjectInputStream ois = new ObjectInputStream(fis);
		OverrideSerial osOutput1 = (OverrideSerial) ois.readObject();
		System.out.println(osOutput1.toString());
		OverrideSerial osOutput2 = (OverrideSerial) ois.readObject();
		System.out.println(osOutput2.toString());
		OverrideSerial osOutput3 = (OverrideSerial) ois.readObject();
		System.out.println(osOutput3.toString());
	}
	
}


关于defaultWriteObject(),是jdk内部的类,即把非静态和非transient的变量序列化。
 
 /**
     * Write the non-static and non-transient fields of the current class to
     * this stream.  This may only be called from the writeObject method of the
     * class being serialized. It will throw the NotActiveException if it is
     * called otherwise.
     *
     * @throws	IOException if I/O errors occur while writing to the underlying
     * 		<code>OutputStream</code>
     */
public void defaultWriteObject() throws IOException {
		if (curObj == null || curDesc == null) {
			throw new NotActiveException("not in call to writeObject");
		}
		bout.setBlockDataMode(false);
		defaultWriteFields(curObj, curDesc);
		bout.setBlockDataMode(true);
	}
   
分享到:
评论

相关推荐

    深入理解Java虚拟机-Java内存区域透彻分析(序列化、反序列化概念及其使用场景+实现序列化的方式+transient关键字)

    今天,我们将深入理解Java虚拟机-Java内存区域透彻分析,探讨序列化和反序列化的概念及其使用场景,实现序列化的方式,以及transient关键字的作用。 序列化和反序列化的概念 序列化是指将Java对象转换为二进制数据...

    java自动序列化

    对于类中包含的transient和static修饰的成员变量,它们不会参与序列化过程,因为transient变量表示临时状态,static变量表示类级别的状态,不依赖于对象实例。 四、序列化过程 1. 创建ObjectOutputStream实例,如`...

    java serializable 序列化与反序列化

    - ** transient 关键字**:如果某个字段不需要序列化,可以使用`transient`关键字修饰。序列化时,这些字段会被忽略。 - **readObject() 和 writeObject()** 方法:可以覆盖这两个方法来自定义序列化和反序列化的...

    java关键字transient

    在Java编程语言中,`transient`是一个非常重要的关键字,它与对象持久化和序列化密切相关。当一个字段被声明为`transient`时,它表明该字段的值不会随着对象的序列化而保存。这通常用于那些不希望或者不需要在序列化...

    java基础 对象序列化

    这种方法提供了更高级别的控制,允许开发者决定哪些数据应该被序列化,以及如何序列化和反序列化数据。 #### 使用transient关键字保护数据 `transient`关键字用于标记那些不应被序列化的变量。当一个字段被声明为`...

    java序列化方式Java系列2021.pdf

    只要一个类实现了`Serializable`接口,Java的默认序列化机制就会自动处理该类的所有实例变量(除了被`transient`关键字修饰的和`static`修饰的成员)。在示例代码中,`Student`类实现了`Serializable`接口,因此它的...

    Java transient关键字使用小记

    下面的代码展示了如何在序列化和反序列化过程中使用`transient`关键字。当`User`对象被序列化并写入文件,然后从文件中读取并反序列化时,`passwd`字段的值不会被保存和恢复。 ```java import java.io.*; public ...

    Java修饰符总结

    然而,`transient`和`volatile`只适用于实例变量,它们分别用于序列化过程中的忽略和多线程环境下的变量管理。 #### 结论 Java修饰符的灵活运用是构建高质量、高效率应用程序的关键。掌握每种修饰符的特性和适用...

    Java之transient关键字.Java

    但是,`age`字段被`transient`修饰,因此在序列化和反序列化过程中,`age`的值不会被保存和恢复。 **注意点** 1. `transient`变量在反序列化后不会被初始化,需要手动设置其初始值。 2. `transient`变量不会参与...

    java对象实现序列化

    在Java编程语言中,序列化是一个重要的特性,它允许我们将对象的状态转换为字节流,以便存储或在网络中传输。这个过程称为对象的序列化,而反...通过以上知识点,你应该能更好地理解和实现Java对象的序列化和反序列化。

    Java对象序列化

    但需要注意的是,并非类的所有成员变量都会被序列化,`transient`和`static`修饰的成员变量不会参与序列化过程,因为它们不属于对象实例的状态。 序列化的过程通常涉及以下步骤: 1. 实现Serializable接口:在需要...

    Java访问修饰符

    transient 访问修饰符告诉编译器,在类对象序列化时,此变量不需要持久保存。 volatile 访问修饰符 volatile 访问修饰符指出可能有多个线程修改此变量,要求编译器优化以保证对此变量的修改能够被正确的处理。 ...

    知识整理和序列化

    在Java编程语言中,序列化是一个关键的概念,它允许我们将对象...在实践中,需要注意`Serializable`接口的实现、`serialVersionUID`的管理以及`transient`关键字的使用,以确保对象在序列化和反序列化过程中行为正确。

    Java编程中常用修饰词使用方法

    介绍:static 修饰词可以用来修饰类、方法、字段和初始化函数。static 修饰的成员属于类,而不是实例,static 方法可以被类名直接调用。static 字段是类字段,无论该字段所在的类创建了多少实例,该字段只存在一个...

    java修饰符介绍

    - **transient**:不参与序列化过程的变量,当对象序列化时,transient变量的值不会被保存。 5. 类的成员方法特性修饰符: - **final**:方法不能被子类覆盖。 - **abstract**:声明抽象方法,没有方法体,必须...

    Java修饰符demo

    当对象被序列化时,带有transient修饰符的变量不会包含在序列化的数据中。 7. **native**:原生修饰符,表示方法的实现是用其他语言(如C或C++)完成的,通过JNI(Java Native Interface)进行调用。 在IntelliJ ...

    Java transient关键字原理解析

    需要注意的是,transient 关键字只能用来修饰变量,不能用来修饰方法或类。同时,transient 关键字也不能用来修饰 static 变量,因为 static 变量是属于类的,而不是对象的。 transient 关键字是一个非常有用的工具...

    关于Java中各种修饰符与访问修饰符的说明

    - `transient`:序列化时忽略此变量,通常用于性能优化。 - `volatile`:指示变量可能被多个线程修改,要求编译器进行优化以确保正确处理。 5. **方法的访问修饰符** - `public`:任何类都可以调用。 - `...

    SCJP java基础修饰符

    - **示例03**:明确了`transient`和`volatile`只能用于修饰变量,而`private`、`protected`和`final`可以用于修饰方法。 - **示例04**:指出了`private`和`protected`不能用于修饰顶层类,而`public`和`final`可以。...

    Java transient 关键字详解及实例代码

    - 在序列化和反序列化时,需要特别注意`transient`变量的处理。由于这些变量在反序列化时不恢复,所以通常需要在反序列化后手动设置它们的值,或者提供一个替代机制来重新计算这些值。 - `transient`变量不能是...

Global site tag (gtag.js) - Google Analytics