通常情况下,用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对象转换为二进制数据...
对于类中包含的transient和static修饰的成员变量,它们不会参与序列化过程,因为transient变量表示临时状态,static变量表示类级别的状态,不依赖于对象实例。 四、序列化过程 1. 创建ObjectOutputStream实例,如`...
- ** transient 关键字**:如果某个字段不需要序列化,可以使用`transient`关键字修饰。序列化时,这些字段会被忽略。 - **readObject() 和 writeObject()** 方法:可以覆盖这两个方法来自定义序列化和反序列化的...
在Java编程语言中,`transient`是一个非常重要的关键字,它与对象持久化和序列化密切相关。当一个字段被声明为`transient`时,它表明该字段的值不会随着对象的序列化而保存。这通常用于那些不希望或者不需要在序列化...
只要一个类实现了`Serializable`接口,Java的默认序列化机制就会自动处理该类的所有实例变量(除了被`transient`关键字修饰的和`static`修饰的成员)。在示例代码中,`Student`类实现了`Serializable`接口,因此它的...
下面的代码展示了如何在序列化和反序列化过程中使用`transient`关键字。当`User`对象被序列化并写入文件,然后从文件中读取并反序列化时,`passwd`字段的值不会被保存和恢复。 ```java import java.io.*; public ...
但是,`age`字段被`transient`修饰,因此在序列化和反序列化过程中,`age`的值不会被保存和恢复。 **注意点** 1. `transient`变量在反序列化后不会被初始化,需要手动设置其初始值。 2. `transient`变量不会参与...
在Java编程语言中,序列化是一个重要的特性,它允许我们将对象的状态转换为字节流,以便存储或在网络中传输。这个过程称为对象的序列化,而反...通过以上知识点,你应该能更好地理解和实现Java对象的序列化和反序列化。
但需要注意的是,并非类的所有成员变量都会被序列化,`transient`和`static`修饰的成员变量不会参与序列化过程,因为它们不属于对象实例的状态。 序列化的过程通常涉及以下步骤: 1. 实现Serializable接口:在需要...
transient 访问修饰符告诉编译器,在类对象序列化时,此变量不需要持久保存。 volatile 访问修饰符 volatile 访问修饰符指出可能有多个线程修改此变量,要求编译器优化以保证对此变量的修改能够被正确的处理。 ...
在Java编程语言中,序列化是一个关键的概念,它允许我们将对象...在实践中,需要注意`Serializable`接口的实现、`serialVersionUID`的管理以及`transient`关键字的使用,以确保对象在序列化和反序列化过程中行为正确。
介绍:static 修饰词可以用来修饰类、方法、字段和初始化函数。static 修饰的成员属于类,而不是实例,static 方法可以被类名直接调用。static 字段是类字段,无论该字段所在的类创建了多少实例,该字段只存在一个...
- **transient**:不参与序列化过程的变量,当对象序列化时,transient变量的值不会被保存。 5. 类的成员方法特性修饰符: - **final**:方法不能被子类覆盖。 - **abstract**:声明抽象方法,没有方法体,必须...
当对象被序列化时,带有transient修饰符的变量不会包含在序列化的数据中。 7. **native**:原生修饰符,表示方法的实现是用其他语言(如C或C++)完成的,通过JNI(Java Native Interface)进行调用。 在IntelliJ ...
需要注意的是,transient 关键字只能用来修饰变量,不能用来修饰方法或类。同时,transient 关键字也不能用来修饰 static 变量,因为 static 变量是属于类的,而不是对象的。 transient 关键字是一个非常有用的工具...
- `transient`:序列化时忽略此变量,通常用于性能优化。 - `volatile`:指示变量可能被多个线程修改,要求编译器进行优化以确保正确处理。 5. **方法的访问修饰符** - `public`:任何类都可以调用。 - `...
- **示例03**:明确了`transient`和`volatile`只能用于修饰变量,而`private`、`protected`和`final`可以用于修饰方法。 - **示例04**:指出了`private`和`protected`不能用于修饰顶层类,而`public`和`final`可以。...
- 在序列化和反序列化时,需要特别注意`transient`变量的处理。由于这些变量在反序列化时不恢复,所以通常需要在反序列化后手动设置它们的值,或者提供一个替代机制来重新计算这些值。 - `transient`变量不能是...