Java 瞬态与静态变量

原文: https://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/

在这里,我将向您展示静态和瞬态之间的区别。 无论如何,这两件事在范围上是完全不同的,但是人们经常会问我这个问题。 在本文的这篇文章中,我将尝试对其进行解释。 在之前的文章中,您可以在此处单击(第一部分),在此处单击以获取(第二部分)

静态变量

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

瞬态变量

如果您不想保存变量的状态,请在序列化时使用。 您必须将该变量标记为Transient。 环境将知道应忽略此变量,并且不会保存相同的值。

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

两者之间的区别

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

Employee.java

  1. package com.jbt;
  2. import java.io.Serializable;
  3. public class Employee extends superEmployee {
  4. public String firstName;
  5. private static final long serialVersionUID = 5462223600l;
  6. }
  7. class superEmployee implements Serializable{
  8. public String lastName;
  9. static String companyName;
  10. transient String address;
  11. static transient String companyCEO;
  12. }

SerializaitonClass.java

  1. package com.jbt;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;
  4. import java.io.ObjectOutputStream;
  5. public class SerializaitonClass {
  6. public static void main(String[] args) {
  7. Employee emp = new Employee();
  8. emp.firstName = "Vivekanand";
  9. emp.lastName = "Gautam";
  10. emp.companyName = "JBT";
  11. //Below part needs to be removed in case address field is made final
  12. emp.address = "MUM";
  13. emp.companyCEO = "ME CEO";
  14. try {
  15. FileOutputStream fileOut = new FileOutputStream("./employee.txt");
  16. ObjectOutputStream out = new ObjectOutputStream(fileOut);
  17. out.writeObject(emp);
  18. out.close();
  19. fileOut.close();
  20. System.out.printf("Serialized data is saved in ./employee.txt file");
  21. } catch (IOException i) {
  22. i.printStackTrace();
  23. }
  24. }
  25. }

DeserializationClass.java

  1. package com.jbt;
  2. import java.io.*;
  3. public class DeserializationClass {
  4. public static void main(String[] args) {
  5. Employee emp = null;
  6. try {
  7. FileInputStream fileIn = new FileInputStream("./employee.txt");
  8. ObjectInputStream in = new ObjectInputStream(fileIn);
  9. emp = (Employee) in.readObject();
  10. in.close();
  11. fileIn.close();
  12. } catch (IOException i) {
  13. i.printStackTrace();
  14. return;
  15. } catch (ClassNotFoundException c) {
  16. System.out.println("Employee class not found");
  17. c.printStackTrace();
  18. return;
  19. }
  20. System.out.println("Deserializing Employee...");
  21. System.out.println("First Name of Employee: " + emp.firstName);
  22. System.out.println("Last Name of Employee: " + emp.lastName);
  23. System.out.println("Company Name: "+emp.companyName);
  24. System.out.println("Company CEO: "+emp.companyCEO);
  25. System.out.println("Company Address: "+emp.address);
  26. }
  27. }

首先执行“SerializaitonClass”,您将获得以下输出。

  1. Serialized data is saved in ./employee.txt file

其次,执行“DeserializationClass”,您将获得以下输出

  1. Deserializing Employee...
  2. First Name of Employee: Vivekanand
  3. Last Name of Employee: Gautam
  4. Company Name: null
  5. Company CEO: null
  6. Company Address: null

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

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

Employee.java

  1. package com.jbt;
  2. import java.io.Serializable;
  3. public class Employee extends superEmployee {
  4. public String firstName;
  5. private static final long serialVersionUID = 5462223600l;
  6. }
  7. class superEmployee implements Serializable {
  8. public String lastName;
  9. /*
  10. * Here i am providing the value of company name,companyCEO and address
  11. * while defining these variables.
  12. */
  13. static String companyName = "TATA";
  14. transient String address = "DEL";
  15. static transient String companyCEO = "Jayshree";
  16. }

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

  1. Deserializing Employee...
  2. First Name of Employee: Vivekanand
  3. Last Name of Employee: Gautam
  4. Company Name: TATA
  5. Company CEO: Jayshree
  6. Company Address: null

非常仔细地查看输出。 此处已保存companyNamecompanyCEO的值,但未保存地址的值。 另外,检查这些变量的保存值。

  1. Company Name: TATA
  2. Company CEO: Jayshree

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

重点

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

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

要查看Final修饰符的效果,我再次更改Employee类的代码。

Employee.java

  1. package com.jbt;
  2. import java.io.Serializable;
  3. public class Employee extends superEmployee {
  4. public String firstName;
  5. private static final long serialVersionUID = 5462223600l;
  6. }
  7. class superEmployee implements Serializable {
  8. public String lastName;
  9. /*
  10. * Here i am providing the value of company name,companyCEO and address
  11. * while defining these variables.
  12. * I am making address as final here
  13. */
  14. static String companyName = "TATA";
  15. transient final String address = "DEL";
  16. static transient String companyCEO = "Jayshree";
  17. }

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

  1. Deserializing Employee...
  2. First Name of Employee: Vivekanand
  3. Last Name of Employee: Gautam
  4. Company Name: TATA
  5. Company CEO: Jayshree
  6. Company Address: DEL

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

接口和最终

我看到了一种情况,您可以序列化未序列化的接口内部的变量。

Employee.java

  1. package com.jbt;
  2. import java.io.Serializable;
  3. public class Employee extends superEmployee implements variableConstant{
  4. public String firstName;
  5. private static final long serialVersionUID = 5462223600l;
  6. }
  7. class superEmployee implements Serializable {
  8. public String lastName;
  9. /*
  10. * Here i am providing the value of company name,companyCEO and address
  11. * while defining these variables.
  12. * I am making address as final here
  13. */
  14. static String companyName = "TATA";
  15. transient final String address = "DEL";
  16. static transient String companyCEO = "Jayshree";
  17. }
  18. interface variableConstant {
  19. public static final String education = "MCA";
  20. }

DeserializationClass.java

  1. package com.jbt;
  2. import java.io.*;
  3. public class DeserializationClass {
  4. public static void main(String[] args) {
  5. Employee emp = null;
  6. try {
  7. FileInputStream fileIn = new FileInputStream("./employee.txt");
  8. ObjectInputStream in = new ObjectInputStream(fileIn);
  9. emp = (Employee) in.readObject();
  10. in.close();
  11. fileIn.close();
  12. } catch (IOException i) {
  13. i.printStackTrace();
  14. return;
  15. } catch (ClassNotFoundException c) {
  16. System.out.println("Employee class not found");
  17. c.printStackTrace();
  18. return;
  19. }
  20. System.out.println("Deserializing Employee...");
  21. System.out.println("First Name of Employee: " + emp.firstName);
  22. System.out.println("Last Name of Employee: " + emp.lastName);
  23. System.out.println("Company Name: "+emp.companyName);
  24. System.out.println("Company CEO: "+emp.companyCEO);
  25. System.out.println("Company Address: "+emp.address);
  26. System.out.println("Education: "+emp.education);
  27. }
  28. }

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

  1. Deserializing Employee...
  2. First Name of Employee: Vivekanand
  3. Last Name of Employee: Gautam
  4. Company Name: TATA
  5. Company CEO: Jayshree
  6. Company Address: DEL
  7. 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. 😛