开发者

statics inside inner classes : serialVersionUID

I'm trying to develop my personal library classes but have been running into a roadblock. My utilities class consists of static methods and constants, and several public inner classes for various data structures and subutilities. These classes are NOT static nested classes, they are intended to be instanced, hold data, etc.

The problem is like any data class I want to make it serializable. That in turn means I want to set the serialVersionUID (even though I use my own versioning methods), and that of course cant be done because you cannot have a static variable in an inner class.

Is there a way around this? Does the parent class have to hold the UID (even though it's effectively static). At the moment I'm starting to consider turning my Utilities class into a set of classes, and giving up on the idea of a single import utility class. It is turning into an increasingly big set of utilities though.

K.Barad JDK1.6 u23

edit: quick example code.

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;
    }

    }
}

the inner class throws up warnings, and a fairly relevant one, but since it cannot take static fields I cannot add public static final long serialVersionUID

edit: Ok, so a line like public static final long ll = 1; is fine. The matter is what I really want to do is have: public static final Date version = new Date(111 , 01 , 04 ); public static final long serialVersionUID = version.getTime();

This works in a top level class开发者_运维技巧, but in an inner classes comes up with: "The field version cannot be declared static; static fields can only be declared in static or top level types"

Dates are for me the most practical way of storing a meaningful and incremental version tracking system which is comparable and can be split into major and minor parts. Does anyone know what about the Date object is causing the trouble;

Closed:

It seems there was some misunderstanding on my part on how a static class behaves, and that this is the solution to the problem. I'll probably (eventually) split the classes, but for now this is the most sensible solution. Thanks all who answered


This

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

looks fine to my IDE (IntelliJ 9). However, without the final it complains indeed.

Since a UUID is supposed to be constant, I guess final should be OK for you (and in fact even recommended).

Update

Copying your example inner class into my IDE and adding a static final int to it is also entirely OK, no complaints whatsoever from the compiler.

Update2

However, adding the final qualifier to the Date object does indeed produce an error! You're vindicated :-)

But when I try it with String, no problem. Could this be because primitives and String are immutable, while Date is not?

Update3

No. BigDecimal also fails. I'm out of theories :-(

Update4

Google is my friend :-) It turns out you need to declare your inner class static, then everything is fine and dandy: all the above mentioned static fields compile. From the code excerpt you show, it seems that there is really no reason for your inner class to be nonstatic, so I guess this solution should be fine for you.


Sounds like there is no reason for those classes to be inner classes of a utility-class. A more understandable design would to let the become classes of their own. Since they are public and there for I guess they are designed to be used outside your package.

Don't worry about large imports, they are handled automatically by Eclipse. Also if you have a large amount of imports it's an indication that the class is having a wide responsibility and should perhaps be splitted. I'm guessing that typically other classes will only use a few of your utility-classes.


In your sample it should be no problem to make TupleComp static - it is not dependent (does not need) an instance of the outer instance.
The class being static means that its instances are not a member of the outer class. That is, the nested instances does not implicitly receive a pointer to the outer one. Each instance of the nested (static) instance still will have its own data (different with every instance).
Try this:

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;
        }
    }
}

Test:

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: the equals method was wrong: was comparing elem2 and elem3 with elem1!


you cannot have a static variable in an inner class

That's completely wrong! you can. But only 'final'- thats what serialVersionUID should be.

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;

    };
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜