56.md 9.7 KB
Newer Older
W
wizardforcel 已提交
1
# 瞬态与静态变量 Java
W
init  
wizardforcel 已提交
2 3 4 5 6 7 8 9 10 11 12

> 原文: [https://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/](https://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/)

在这里,我将向您展示静态和瞬态之间的区别。 无论如何,这两件事在范围上是完全不同的,但是人们经常会问我这个问题。 在本文的这篇文章中,我将尝试对其进行解释。 在之前的文章中,您可以在此处单击[(第一部分)](https://javabeginnerstutorial.com/core-java-tutorial/java-serialization-concept-example/ "Java serialization concept and Example"),在此处单击[以获取(第二部分)](https://javabeginnerstutorial.com/core-java-tutorial/java-serialization-concept-example-part-ii/ "Java serialization concept and Example Part II")

## 静态变量

静态变量属于一个类,而不属于任何单个实例。 序列化的概念与对象的当前状态有关。 仅与类的特定实例关联的数据被序列化,因此静态成员字段在序列化过程中将被忽略。

## 瞬态变量

W
wizardforcel 已提交
13
如果您不想保存变量的状态,请在序列化时使用。 您必须将该变量标记为`Transient`。 环境将知道应忽略此变量,并且不会保存相同的值。
W
init  
wizardforcel 已提交
14 15 16 17 18 19 20

> 即使概念是完全不同的,并且不进行储蓄的原因也不同,人们仍然对两者的存在感到困惑。 与这两种情况一样,变量值将不会保存。

## 两者之间的区别

源代码:注意每个代码更改。

W
wizardforcel 已提交
21
`Employee.java`
W
init  
wizardforcel 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

```java
package com.jbt;

import java.io.Serializable;

public class Employee extends superEmployee {
	public String firstName;
	private static final long serialVersionUID = 5462223600l;
}

class superEmployee implements Serializable{
	public String lastName;
	static  String companyName;
	transient  String address;
	static transient String companyCEO;
} 
```

W
wizardforcel 已提交
41
`SerializaitonClass.java`
W
init  
wizardforcel 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

```java
package com.jbt;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializaitonClass {

	public static void main(String[] args) {
		Employee emp = new Employee();
		emp.firstName = "Vivekanand";
		emp.lastName = "Gautam";
		emp.companyName = "JBT";
		//Below part needs to be removed in case address field is made final
		emp.address = "MUM";
		emp.companyCEO = "ME CEO";

		try {
			FileOutputStream fileOut = new FileOutputStream("./employee.txt");
			ObjectOutputStream out = new ObjectOutputStream(fileOut);
			out.writeObject(emp);
			out.close();
			fileOut.close();
			System.out.printf("Serialized data is saved in ./employee.txt file");
		} catch (IOException i) {
			i.printStackTrace();
		}
	}
} 
```

W
wizardforcel 已提交
75
`DeserializationClass.java`
W
init  
wizardforcel 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

```java
package com.jbt;

import java.io.*;

public class DeserializationClass {
	public static void main(String[] args) {
		Employee emp = null;
		try {
			FileInputStream fileIn = new FileInputStream("./employee.txt");
			ObjectInputStream in = new ObjectInputStream(fileIn);
			emp = (Employee) in.readObject();
			in.close();
			fileIn.close();
		} catch (IOException i) {
			i.printStackTrace();
			return;
		} catch (ClassNotFoundException c) {
			System.out.println("Employee class not found");
			c.printStackTrace();
			return;
		}
		System.out.println("Deserializing Employee...");
		System.out.println("First Name of Employee: " + emp.firstName);
		System.out.println("Last Name of Employee: " + emp.lastName);
		System.out.println("Company Name: "+emp.companyName);
		System.out.println("Company CEO: "+emp.companyCEO);
		System.out.println("Company Address: "+emp.address);
	}
} 
```

W
wizardforcel 已提交
109
首先执行“`SerializaitonClass`”,您将获得以下输出。
W
init  
wizardforcel 已提交
110 111 112 113 114

```java
Serialized data is saved in ./employee.txt file 
```

W
wizardforcel 已提交
115
其次,执行“`DeserializationClass`”,您将获得以下输出
W
init  
wizardforcel 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129

```java
Deserializing Employee...
First Name of Employee: Vivekanand
Last Name of Employee: Gautam
Company Name: null
Company CEO: null
Company Address: null 
```

从输出中可以看到,只有姓氏值被保存。 静态和瞬态变量值均未保存。

现在,我将稍作更改代码,看看会发生什么。

W
wizardforcel 已提交
130
`Employee.java`
W
init  
wizardforcel 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

```java
package com.jbt;

import java.io.Serializable;

public class Employee extends superEmployee {
	public String firstName;
	private static final long serialVersionUID = 5462223600l;
}

class superEmployee implements Serializable {
	public String lastName;
	/*
	 * Here i am providing the value of company name,companyCEO and address
	 * while defining these variables.
	 */
	static String companyName = "TATA";
	transient String address = "DEL";
	static transient String companyCEO = "Jayshree";
} 
```

再次执行相同的代码并查看输出

```java
Deserializing Employee...
First Name of Employee: Vivekanand
Last Name of Employee: Gautam
Company Name: TATA
Company CEO: Jayshree
Company Address: null 
```

W
wizardforcel 已提交
165
非常仔细地查看输出。 此处已保存`companyName``companyCEO`的值,但未保存地址的值。 另外,检查这些变量的保存值。
W
init  
wizardforcel 已提交
166

W
wizardforcel 已提交
167 168 169 170
```java
Company Name: TATA
Company CEO: Jayshree
```
W
init  
wizardforcel 已提交
171

W
wizardforcel 已提交
172
在这两种情况下,此处存储的`case`值均来自类(`Employee`类),而不是对象(`emp`对象)。 此外,即使是临时变量,也会保存`companyCEO`变量值。 因为`static`修饰符会更改此变量的行为。
W
init  
wizardforcel 已提交
173

W
wizardforcel 已提交
174
## 重点
W
init  
wizardforcel 已提交
175 176 177

1.  静态变量无法序列化。
2.  在反序列化时,如果在基类的初始化过程中提供了相同的值,则可用于静态变量。
W
wizardforcel 已提交
178
    *   这并不意味着静态变量将被序列化。 这仅意味着静态变量将使用相同的值初始化,并在加载类时分配(在这种情况下为`TATA`)。 如果之前未加载类(新 JVM)。 请注意示例代码。
W
wizardforcel 已提交
179
    *   如果类已经在 JVM 中加载并且静态变量值已更改,那么将显示更改后的值。
W
init  
wizardforcel 已提交
180 181 182 183 184 185
3.  如果将变量定义为“静态”和“瞬态”,则静态修饰符将控制变量的行为,而不是瞬态。
    *   静态和瞬态是不同的。 在某些情况下,它们的行为看起来相同,但并非总是如此。 如果在加载类时为变量分配了一个值,则在反序列化类时该值将分配给静态变量,而不是瞬时的。 因此,如果您同时使用这两个修饰符和变量,那么从某种意义上来说,我要说的是静态将优先于瞬态。
4.  瞬态变量值将不会保存。 同样,在反序列化过程中不能为其分配任何值。 这与静态行为不同。

## 最终修饰符对序列化的影响

W
wizardforcel 已提交
186
要查看`Final`修饰符的效果,我再次更改`Employee`类的代码。
W
init  
wizardforcel 已提交
187

W
wizardforcel 已提交
188
`Employee.java`
W
init  
wizardforcel 已提交
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

```java
package com.jbt;

import java.io.Serializable;

public class Employee extends superEmployee {
	public String firstName;
	private static final long serialVersionUID = 5462223600l;
}

class superEmployee implements Serializable {
	public String lastName;
	/*
	 * Here i am providing the value of company name,companyCEO and address
	 * while defining these variables.
	 * I am making address as final here
	 */
	static String companyName = "TATA";
	transient final String address = "DEL";
	static transient String companyCEO = "Jayshree";
} 
```

再次执行代码,看看区别。 上面代码的输出将是

```java
Deserializing Employee...
First Name of Employee: Vivekanand
Last Name of Employee: Gautam
Company Name: TATA
Company CEO: Jayshree
Company Address: DEL 
```

如您所见,序列化过程中还保存了地址字段,因为它现在是最终的。

## 界面和最终

W
wizardforcel 已提交
228
我看到了一种情况,您可以序列化未序列化的接口内部的变量。
W
init  
wizardforcel 已提交
229

W
wizardforcel 已提交
230
`Employee.java`
W
init  
wizardforcel 已提交
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259

```java
package com.jbt;

import java.io.Serializable;

public class Employee extends superEmployee implements variableConstant{
	public String firstName;
	private static final long serialVersionUID = 5462223600l;
}

class superEmployee implements Serializable {
	public String lastName;
	/*
	 * Here i am providing the value of company name,companyCEO and address
	 * while defining these variables.
	 * I am making address as final here
	 */
	static String companyName = "TATA";
	transient final String address = "DEL";
	static transient String companyCEO = "Jayshree";
}

interface variableConstant  {
	public static final String education = "MCA";

} 
```

W
wizardforcel 已提交
260
`DeserializationClass.java`
W
init  
wizardforcel 已提交
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310

```java
package com.jbt;

import java.io.*;

public class DeserializationClass {
	public static void main(String[] args) {
		Employee emp = null;
		try {
			FileInputStream fileIn = new FileInputStream("./employee.txt");
			ObjectInputStream in = new ObjectInputStream(fileIn);
			emp = (Employee) in.readObject();
			in.close();
			fileIn.close();
		} catch (IOException i) {
			i.printStackTrace();
			return;
		} catch (ClassNotFoundException c) {
			System.out.println("Employee class not found");
			c.printStackTrace();
			return;
		}
		System.out.println("Deserializing Employee...");
		System.out.println("First Name of Employee: " + emp.firstName);
		System.out.println("Last Name of Employee: " + emp.lastName);
		System.out.println("Company Name: "+emp.companyName);
		System.out.println("Company CEO: "+emp.companyCEO);
		System.out.println("Company Address: "+emp.address);
		System.out.println("Education: "+emp.education);
	}
} 
```

执行以上代码,然后查看输出。

```java
Deserializing Employee...
First Name of Employee: Vivekanand
Last Name of Employee: Gautam
Company Name: TATA
Company CEO: Jayshree
Company Address: DEL
Education: MCA 
```

在这里,您可以看到教育的价值得以保存。 此值是接口的一部分。 但是由于这是恒定的,因此在序列化时将其保存。

I think I have covered all possible scenarios. Do let me know in case any particular scenario is not covered in this article. Feel free to say me hi,  if you like this article. And yes I didn’t qualify for the interview. 😛