内部类中的静态:serialVersionUID

时间:2011-02-04 09:58:49

标签: java serialization static inner-classes

我正在尝试开发我的个人图书馆课程,但一直遇到障碍。我的实用程序类包含静态方法和常量,以及用于各种数据结构和子实用程序的几个公共内部类。这些类不是静态嵌套类,它们用于实例化,保存数据等。

问题就像我想让它可序列化的任何数据类一样。这反过来意味着我想设置serialVersionUID(即使我使用自己的版本控制方法),当然这是因为你不能在内部类中有一个静态变量。

有解决方法吗?父类是否必须保留UID(即使它实际上是静态的)。目前我开始考虑将我的Utilities类转换为一组类,并放弃单个导入实用程序类的想法。它现在变成了越来越大的公用事业。

K.Barad JDK1.6 u23

编辑:快速示例代码。

public class UtilDummy {
    public static final Date version = new Date(111,01,04);

    public static final int SUCCESS = 0;
    public static final int READ_FAIL = -1;


    public class TupleComp<E1 extends Serializable, E2 extends Serializable, E3 extends Serializable>
        implements Cloneable, Serializable {
    /** version : Date object for the version of this class */
    public final Date version = new Date(111, 01, 04);
    public E1    elem1   = null;
    public E2    elem2   = null;
    public E3    elem3   = null;

    public TupleComp() {
    }

    public TupleComp(E1 elem1, E2 elem2, E3 elem3) {
        this.elem1 = elem1;
        this.elem2 = elem2;
        this.elem3 = elem3;
    }

    @Override
    public TupleComp<E1, E2, E3> clone() {
        return new TupleComp<E1, E2, E3>(elem1, elem2, elem3);
    }

    public boolean equals(TupleComp<E1, E2, E3> target) {
        boolean out = true;
        out &= (elem1 == null ? target.elem1 == null : elem1.equals(target.elem1));
        out &= (elem2 == null ? target.elem2 == null : elem1.equals(target.elem2));
        out &= (elem3 == null ? target.elem3 == null : elem1.equals(target.elem3));
        return out;
    }

    }
}

内部类会抛出警告,并且是一个相当相关的警告,但由于它不能采用静态字段,所以无法添加公共静态最终的long serialVersionUID

修改: 好的,所以像public static final long ll = 1这样的行;很好。问题是我真正想做的事情是: public static final日期版​​本=新日期(111,01,04); public static final long serialVersionUID = version.getTime();

这适用于顶级类,但在内部类中提出:“字段版本不能声明为静态;静态字段只能在静态或顶级类型中声明”

对我而言,日期是存储有意义的增量版本跟踪系统的最实用方法,该系统具有可比性,可分为主要部分和次要部分。有谁知道Date对象导致了什么问题;

我似乎对静态类的行为方式存在一些误解,这是问题的解决方案。我可能(最终)拆分类,但是现在这是最明智的解决方案。谢谢所有回答

的人

4 个答案:

答案 0 :(得分:3)

class MyClass {
    class Inner {
        static final int x = 1;
    }
}

我的IDE(IntelliJ 9)看起来很好。但是,如果没有final它就会抱怨。

由于UUID应该是不变的,我猜final对你来说应该没问题(实际上甚至是推荐的)。

更新

将示例内部类复制到我的IDE并向其添加static final int也完全没问题,编译器也没有任何抱怨。

UPDATE2

但是,将final限定符添加到Date对象确实会产生错误!你被证明是正确的: - )

但是当我用String尝试时,没问题。这可能是因为原语和String是不可变的,而Date不是吗?

UPDATE3

没有。 BigDecimal也失败了。我没有理论: - (

UPDATE4

Google is my friend :-)结果是你需要声明你的内部类static ,然后一切都很好和花花公子:所有上面提到的静态字段都编译。从您显示的代码摘录中看来,您的内部类似乎没有理由是非静态的,所以我想这个解决方案对您来说应该没问题。

答案 1 :(得分:2)

听起来这些类没有理由成为实用程序类的内部类。一个更容易理解的设计就是让它们成为自己的类。因为它们是公开的,因此我猜它们的设计是在你的包装之外使用。

不要担心大量导入,它们由Eclipse自动处理。此外,如果您有大量的进口,则表明该类具有广泛的责任,并且可能应该被拆分。我猜通常其他类只会使用你的一些实用程序类。

答案 2 :(得分:1)

在您的示例中,使TupleComp为静态应该没有问题 - 它不依赖(不需要)外部实例的实例。
该类是静态的意味着它的实例不是外部类的成员。也就是说,嵌套实例不会隐式接收指向外部实例的指针。嵌套(静态)实例的每个实例仍将拥有自己的数据(与每个实例不同) 试试这个:

public class UtilDummy {

    public static final Date version = new Date(111,01,04);

    public static final int SUCCESS = 0;
    public static final int READ_FAIL = -1;


    public static class TupleComp<E1 extends Serializable, E2 extends Serializable, E3 extends Serializable>
    implements Cloneable, Serializable {
        private static final long serialVersionUID = 1L;
        /** version : Date object for the version of this class */
        public final static Date version = new Date(111, 01, 04);
        public E1    elem1   = null;
        public E2    elem2   = null;
        public E3    elem3   = null;

        public TupleComp() {
        }

        public TupleComp(E1 elem1, E2 elem2, E3 elem3) {
            this.elem1 = elem1;
            this.elem2 = elem2;
            this.elem3 = elem3;
        }

        @Override
        public TupleComp<E1, E2, E3> clone() {
            return new TupleComp<E1, E2, E3>(elem1, elem2, elem3);
        }

        public boolean equals(TupleComp<E1, E2, E3> target) {
            boolean out = true;
            out &= (elem1 == null ? target.elem1 == null : elem1.equals(target.elem1));
            out &= (elem2 == null ? target.elem2 == null : elem2.equals(target.elem2));
            out &= (elem3 == null ? target.elem3 == null : elem3.equals(target.elem3));
            return out;
        }
    }
}

测试:

public class Test {

    public static void main(String[] args) {
        UtilDummy.TupleComp<String, String, String> t1 = new UtilDummy.TupleComp<String, String, String>("a", "b", "c");
        UtilDummy.TupleComp<String, String, String> t2 = new UtilDummy.TupleComp<String, String, String>("a", "b", "c");
        UtilDummy.TupleComp<String, String, String> t3 = new UtilDummy.TupleComp<String, String, String>("1", "2", "3");
        System.out.println(t1.equals(t2));  // true
        System.out.println(t1.equals(t3));  // false !
    }
}  

BTW:等于方法错误:将elem2elem3elem1进行比较!

答案 3 :(得分:0)

  

你不能在内部类中有一个静态变量

那是完全错的!您可以。但只有'final' - 这就是serialVersionUID应该是什么。

package my;

import java.io.Serializable;

class InnerSVUIDTest {
    class A implements Serializable{
        private static final long serialVersionUID = -8981530002081262605L;
    }

    Serializable bshit = new Serializable (){
        private static final long serialVersionUID = -1655811639867903884L;

    };
}