GVKun编程网logo

这是什么意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段?

20

本文将分享这是什么意思:可序列化的类没有声明一个静态的最终serialVersionUID字段?的详细内容,此外,我们还将为大家带来关于Android:如果我将serialVersionUID添加到旧

本文将分享这是什么意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段?的详细内容,此外,我们还将为大家带来关于Android:如果我将serialVersionUID添加到旧的可序列化对象会怎样?、ArrayList中字段serialVersionUID和序列化的学习、idea 实现序列化 Serializable 接口,提示生成 serialVersionUID、java – 为什么serialVersionUID字段存在?的相关知识,希望对你有所帮助。

本文目录一览:

这是什么意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段?

这是什么意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段?

我有标题中给出的警告信息。我想了解并删除它。我已经找到了关于这个问题的一些答案,但由于技术术语过多,我不理解这些答案。能不能用简单的话来解释这个问题?

PS我知道OOP是什么。我知道什么是对象、类、方法、字段和实例化。

PPS 如果有人需要我的代码,它就在这里:

import java.awt.*;import javax.swing.*;public class HelloWorldSwing extends JFrame {        JTextArea m_resultArea = new JTextArea(6, 30);        //====================================================== constructor        public HelloWorldSwing() {            //... Set initial text, scrolling, and border.            m_resultArea.setText("Enter more text to see scrollbars");            JScrollPane scrollingArea = new JScrollPane(m_resultArea);            scrollingArea.setBorder(BorderFactory.createEmptyBorder(10,5,10,5));            // Get the content pane, set layout, add to center            Container content = this.getContentPane();            content.setLayout(new BorderLayout());            content.add(scrollingArea, BorderLayout.CENTER);            this.pack();        }        public static void createAndViewJFrame() {            JFrame win = new HelloWorldSwing();            win.setTitle("TextAreaDemo");            win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            win.setVisible(true);        }        //============================================================= main        public static void main(String[] args) {            SwingUtilities.invokeLater(new Runnable(){                public void run(){                    createAndViewJFrame();                }            });        }}

答案1

小编典典

从javadoc:

序列化运行时将版本号与每个可序列化类相关联,称为 a
serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已为该对象加载了与序列化兼容的类。如果接收者为对象加载了一个serialVersionUID与相应发送者的类不同的类,那么反序列化将产生一个InvalidClassException.
一个可序列化的类可以通过声明一个必须是静态的、最终的和 long
类型serialVersionUID的字段来显式声明自己的:"serialVersionUID"

您可以将 IDE 配置为:

  • 忽略这一点,而不是发出警告。
  • 自动生成一个id

根据您的附加问题“可能是所讨论的警告消息是我的 GUI 应用程序冻结的原因吗?”:

不,不可能。仅当您在类已更改的不同位置(或时间)对对象进行序列化和反序列化时,它才会导致问题,并且不会导致冻结,而是在InvalidClassException.

Android:如果我将serialVersionUID添加到旧的可序列化对象会怎样?

Android:如果我将serialVersionUID添加到旧的可序列化对象会怎样?

如果您获取一个从未明确指定serialVersionUID的旧可序列化对象,然后将serialVersionUID添加到该对象,会发生什么?在我看来,下一次由最终用户更新应用程序时,它将尝试反序列化磁盘中的数据,发现serialVersionUID不匹配,用服务器/
db /中的新数据覆盖数据,然后再执行此操作很好。我对这个假设是否正确?在执行此操作时,我是否还要警惕其他问题?

private class X implements serializable {...private static final long serialVersionUID = 0L;

答案1

小编典典
  1. 如果您给它提供的值与serialver现在在类上运行该工具所显示的值相同,则什么也不会发生。
  2. 如果您赋予它不同的值,则包括该类的现有串行流的进一步反序列化将失败,并带有InvalidClassException

在我看来,下次由最终用户更新应用程序时,它将尝试反序列化光盘中的数据

正确。

找出serialVersionUID不匹配

仅当它确实不匹配时。如果您遵循上述建议,则它将匹配。

用服务器/数据库/任何地方的新数据覆盖数据

不正确 往上看。

然后你就没事了。

没有。

我对这个假设是否正确?

没有。

ArrayList中字段serialVersionUID和序列化的学习

ArrayList中字段serialVersionUID和序列化的学习

一个类的二进制字节序列转为java对象,也就是反序列化时,JVM会把传进来的二进制字节流中的serialVersionUID和本地相应的实体或对象的serialVersionUID进行比较,如果相同,则认为两个类是一致的,可以进行反序列化,否则就会出现版本不一致的反序列化异常。

添加private static final long 类型的字段serialVersionUID,格式如下:

文件中的方法和属性为该类自动生成一个serialVersionUID。只要该类的属性和方法不改变,则serialVersionUID不会改变。

方法和属性敏感,只要类中的属性or方法发生改变,则再次编译的class文件对应的serialVersionUID会与之前生成的不一致。如果之前生成的java实例已经被导入到磁盘进行了存储,那么被反序列化时,会出现异常。

显示定义的serialVersionUID一直不会改变,则不会出现上述异常。

class TestSeriable implements Externalizable {
public transient String name;
public String pwd;
public int age;

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getPwd() {
    return pwd;
}

public void setPwd(String pwd) {
    this.pwd = pwd;
}
public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}
//序列化对象
@Override
public void writeExternal(ObjectOutput out) throws IOException {
    out.writeObject(name);
    out.writeObject(pwd);
    out.writeInt(age);
}

//反序列化对象
@Override
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException {
    name=(String)in.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();
    pwd=(String)in.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();
    age=in.readInt();
}
//被序列化的类:必有<a href="https://www.jb51.cc/tag/publiclei/" target="_blank">public类</a>型的无参构造器。因反序列化时,先<a href="https://www.jb51.cc/tag/diaoyong/" target="_blank">调用</a>此<a href="https://www.jb51.cc/tag/fangfa/" target="_blank">方法</a>实例化<a href="https://www.jb51.cc/tag/yige/" target="_blank">一个</a>类,再<a href="https://www.jb51.cc/tag/diaoyong/" target="_blank">调用</a>readExternal<a href="https://www.jb51.cc/tag/fangfa/" target="_blank">方法</a>读取<a href="https://www.jb51.cc/tag/shuxing/" target="_blank">属性</a>值。
public TestSeriable(){
}

}

public class Main {
public static void main(String[] args) throws Exception{
//Scanner scanner=new Scanner(system.in);//在线笔试
TestSeriable ts=new TestSeriable();
ts.setName("cxh");
ts.setPwd("123456");
ts.setAge(3);
//序列化
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test"));
out.writeObject(ts);

    //反序列化
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("test"));
    ts = (TestSeriable)in.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();

    //<a href="https://www.jb51.cc/tag/shuchu/" target="_blank">输出</a>:
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("name:"+ts.name);
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("pwd:"+ts.pwd);
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("age:"+ts.age);

    //<a href="https://www.jb51.cc/tag/guanbi/" target="_blank">关闭</a>连接
    out.close();
    in.close();
}

}


<span>输出结果:
<code><span>name:cxh
pwd:123456
age:3

Process finished with exit code 0


<span>

生成serialVersionUID ,只要类的属性和方法不改变,则导出字节码就可以被反序列化

class TestSeriable implements Serializable {
private static final long serialVersionUID=1L;
private String name;
private int age;
private transient String pwd;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public String getPwd() {
    return pwd;
}

public void setPwd(String pwd) {
    this.pwd = pwd;
}

}

public class Main {
public static void main(String[] args) throws Exception{
//Scanner scanner=new Scanner(system.in);//在线笔试
TestSeriable test=new TestSeriable();
test.setAge(27);
test.setName("cxh");
test.setPwd("123456");

    ObjectOutputStream  oos=new ObjectOutputStream(new FileOutputStream("file.txt"));
    oos.writeObject(test);
    oos.close();

    ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file.txt"));
    TestSeriable ts=(TestSeriable) ois.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();//rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject返回final类型的Object对象,需要强制转化
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my name:"+ts.getName());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my age:"+ts.getAge());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my pwd:"+ts.getPwd());


}

}


<span>
输出结果:

Process finished with exit code 0

<span>

方法发生改变,则原来导出的字节码不能被反序列化。

添加字段school。

class TestSeriable implements Serializable {
private String name;
private int age;
private transient String pwd;

private String school;//新增字段

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public String getPwd() {
    return pwd;
}

public void setPwd(String pwd) {
    this.pwd = pwd;
}
public String getSchool() {
    return school;
}

public void setSchool(String school) {
    this.school = school;
}

}

public class Main {
public static void main(String[] args) throws Exception{
//Scanner scanner=new Scanner(system.in);//在线笔试
TestSeriable test=new TestSeriable();
test.setAge(27);
test.setName("cxh");
test.setPwd("123456");

// ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("file.txt"));
// oos.writeObject(test);
// oos.close();

    ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file.txt"));
    TestSeriable ts=(TestSeriable) ois.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();//rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject返回final类型的Object对象,需要强制转化
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my name:"+ts.getName());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my age:"+ts.getAge());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my pwd:"+ts.getPwd());


}

}


<span>报错信息:

dobject0(ObjectInputStream.java:1535)
    at java.io.ObjectInputStream.readobject(ObjectInputStream.java:422)
    at Main.main(Main.java:58)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Process finished with exit code 1


<span>

属性或者方法发生更改后,仍然能进行反序列化。

class TestSeriable implements Serializable {
private static final long serialVersionUID=1L;
private String name;
private int age;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}
public static long getSerialVersionUIDs() {
    return serialVersionUIDs;
}

}

public class Main {
public static void main(String[] args) throws Exception{
//Scanner scanner=new Scanner(system.in);//在线笔试
TestSeriable test=new TestSeriable();
test.setAge(27);
test.setName("cxh");

    ObjectOutputStream  oos=new ObjectOutputStream(new FileOutputStream("file1.txt"));
    oos.writeObject(test);
    oos.close();

    ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file1.txt"));
    TestSeriable ts=(TestSeriable) ois.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();//rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject返回final类型的Object对象,需要强制转化
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my name:"+ts.getName());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my age:"+ts.getAge());
}

}

输出结果:

Process finished with exit code 0

<span>

class TestSeriable implements Serializable {
private static final long serialVersionUID=1L;
private String name;
private int age;
private String address;//新增字段

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}
//新增<a href="https://www.jb51.cc/tag/fangfa/" target="_blank">方法</a>
public String getAddress() {
    return address;
}
public void setAddress(String address) {
    this.address = address;
}

}

public class Main {
public static void main(String[] args) throws Exception{
//Scanner scanner=new Scanner(system.in);//在线笔试
TestSeriable test=new TestSeriable();
test.setAge(27);
test.setName("cxh");

    ObjectOutputStream  oos=new ObjectOutputStream(new FileOutputStream("file.txt"));
    oos.writeObject(test);
    oos.close();

    ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file.txt"));
    TestSeriable ts=(TestSeriable) ois.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();//rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject返回final类型的Object对象,需要强制转化
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my name:"+ts.getName());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my age:"+ts.getAge());
}

}


<span>
输出结果:

Process finished with exit code 0

<span>

一个变量为static修饰后,不管是否被transient修饰,均不能被序列化。

class TestSeriable implements Serializable {
private static final long serialVersionUID=1L;
private String name;
private int age;
private static String address;//更改类型为static字段

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}
//新增<a href="https://www.jb51.cc/tag/fangfa/" target="_blank">方法</a>
public String getAddress() {
    return address;
}
public void setAddress(String address) {
    this.address = address;
}

}

public class Main {
public static void main(String[] args) throws Exception{
//Scanner scanner=new Scanner(system.in);//在线笔试
TestSeriable test=new TestSeriable();
test.setAge(27);
test.setName("cxh");
test.setAddress("海淀");

    ObjectOutputStream  oos=new ObjectOutputStream(new FileOutputStream("file.txt"));
    oos.writeObject(test);
    oos.close();

// ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file.txt"));
// TestSeriable ts=(TestSeriable) ois.readobject();//readobject返回final类型的Object对象,需要强制转化
// System.out.println("my name:"+ts.getName());
// System.out.println("my age:"+ts.getAge());
// System.out.println("my address:"+ts.getAddress());
}
}

class TestSeriable implements Serializable {
private static final long serialVersionUID=1L;
private String name;
private int age;
private static String address;//更改类型为static字段

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}
//新增<a href="https://www.jb51.cc/tag/fangfa/" target="_blank">方法</a>
public String getAddress() {
    return address;
}
public void setAddress(String address) {
    this.address = address;
}

}

public class Main {
public static void main(String[] args) throws Exception{
//Scanner scanner=new Scanner(system.in);//在线笔试
// TestSeriable test=new TestSeriable();
// test.setAge(27);
// test.setName("cxh");
// test.setAddress("海淀");
//
// ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("file.txt"));
// oos.writeObject(test);
// oos.close();

    ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file.txt"));
    TestSeriable ts=(TestSeriable) ois.rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject();//rea<a href="https://www.jb51.cc/tag/dob/" target="_blank">dob</a>ject返回final类型的Object对象,需要强制转化
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my name:"+ts.getName());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my age:"+ts.getAge());
    Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank">stem</a>.out.println("my address:"+ts.getAddress());
}

}


<span>
输出结果:

Process finished with exit code 0

<span>

idea 实现序列化 Serializable 接口,提示生成 serialVersionUID

idea 实现序列化 Serializable 接口,提示生成 serialVersionUID

首先 Ctrl+Alt+S,打开系统设置。 选择如下选项:

在所选中的选项中,打上勾即可。

提示:

java – 为什么serialVersionUID字段存在?

java – 为什么serialVersionUID字段存在?

它让我对Serializable接口的推出感到困惑,为什么我必须将这个字段合并到我的所有类中.我知道这个接口需要一个唯一的标识符来标记类,但为什么它们不能在运行时生成它.例如,他们可以使用完全限定类名的MD5哈希或者用于处理罕见事件中的重复项的类似方法来生成它(也就是说,我确定,当被要求生成id时,eclipse会做什么).

所以我要问的是(这篇文章不仅仅是对标准库的咆哮)究竟是如何使用框架化序列化字段的?

我想知道的原因是因为我将尝试创建一个Aspect(使用AspectJ或其他语言),它将使用MD5哈希添加serialVersionUID字段,并且能够以API可接受的方式处理冲突.

如果我能让它发挥作用,我会发布结果.

解决方法

不需要具有serialVersionUID字段.如果您不提供,Java将根据您的类的字段和方法生成一个.

您可能希望指定serialVersionUID的原因是为了防止在更改方法时更改值,这不会影响序列化二进制文件.考虑班级:

public class Person implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
}

没有指定serialVersionUID.如果你运行serialver Person它返回:

Person:    static final long serialVersionUID = 3793453319058452486L;

现在您决定添加一个方法,但保持字段相同.

public class Person implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
    public Object foo() {
        return "bar";
    }
}

序列化二进制文件仍与旧版本完全兼容,但serialVersionUID不同:

Person:    static final long serialVersionUID = -6188734029437600310L;

使用不同的serialVersionUID,反序列化将导致serialVersionUID不匹配错误.解决方法是通过将其设置为任何值(我将其设置为1L)并在字段更改时更改它来声明您自己的serialVersionUID.

另请参阅此related question “What is a serialVersionUID and why should I use it?”以获得更详细的讨论.

关于这是什么意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段?的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Android:如果我将serialVersionUID添加到旧的可序列化对象会怎样?、ArrayList中字段serialVersionUID和序列化的学习、idea 实现序列化 Serializable 接口,提示生成 serialVersionUID、java – 为什么serialVersionUID字段存在?等相关内容,可以在本站寻找。

本文标签: