2013-08-17 20 views
7

Tôi đang làm việc trên một dự án tạo ra các tệp Java. Tôi muốn có thể tùy chọn thêm serialVersionUID như bạn làm với công cụ serialver.Làm thế nào để tạo serialVersionUID lập trình trong Java?

Có cách nào để làm điều này khi tôi tạo mã số Java hay tôi sẽ yêu cầu người dùng công cụ cung cấp UID theo cách thủ công? Để rõ ràng, tôi không muốn tự động thực hiện điều này thông qua Eclipse hoặc công cụ serialver, nhưng để thực hiện điều đó thông qua Java chính nó.

+0

Có lẽ mã băm của tên lớp của lớp đang được tạo sẽ hoạt động không? –

+0

Tôi đã suy nghĩ về một cái gì đó như thế, tự hỏi nếu có một cách để làm điều đó là tương đương với công cụ serialver mặc dù, nếu có thể. –

+0

Chắc chắn, bạn có thể làm điều đó giống như công cụ serialver hiện nó. Chỉ cần tìm logic đằng sau thế hệ 'serialVersionUID' của nó. Tôi đã tìm kiếm không thành công cho đến nay. –

Trả lời

7

Có phiên bản của nguồn công cụ serialver có sẵn from OpenJDK. Tất cả đều đến cuộc gọi này:

ObjectStreamClass c = ObjectStreamClass.lookup(MyClass.class); 
long serialID = c.getSerialVersionUID(); 
System.out.println(serialID); 

Trong JDK 6 ít nhất nó trả về cùng một số với công cụ serialver.

2

Hãy thử mã băm của tên lớp của lớp đang được tạo.

Có thể có sự va chạm như mã băm không phải là duy nhất, nhưng những va chạm đó không chắc chắn về mặt thống kê.

Here's documentation về cách giá trị serialVersionUID được tạo. Của nó phức tạp hơn nhiều so với tôi đã đoán.

Do tính phức tạp của nó, tôi muốn có loại người dùng trong UID hoặc chỉ sử dụng một băm đơn giản của tên lớp đầy đủ.

3

Từ ObjectStreamClass:

/** 
* Computes the default serial version UID value for the given class. 
*/ 
private static long computeDefaultSUID(Class<?> cl) { 
    if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl)) 
    { 
     return 0L; 
    } 

    try { 
     ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
     DataOutputStream dout = new DataOutputStream(bout); 

     dout.writeUTF(cl.getName()); 

     int classMods = cl.getModifiers() & 
      (Modifier.PUBLIC | Modifier.FINAL | 
      Modifier.INTERFACE | Modifier.ABSTRACT); 

     /* 
     * compensate for javac bug in which ABSTRACT bit was set for an 
     * interface only if the interface declared methods 
     */ 
     Method[] methods = cl.getDeclaredMethods(); 
     if ((classMods & Modifier.INTERFACE) != 0) { 
      classMods = (methods.length > 0) ? 
       (classMods | Modifier.ABSTRACT) : 
       (classMods & ~Modifier.ABSTRACT); 
     } 
     dout.writeInt(classMods); 

     if (!cl.isArray()) { 
      /* 
      * compensate for change in 1.2FCS in which 
      * Class.getInterfaces() was modified to return Cloneable and 
      * Serializable for array classes. 
      */ 
      Class<?>[] interfaces = cl.getInterfaces(); 
      String[] ifaceNames = new String[interfaces.length]; 
      for (int i = 0; i < interfaces.length; i++) { 
       ifaceNames[i] = interfaces[i].getName(); 
      } 
      Arrays.sort(ifaceNames); 
      for (int i = 0; i < ifaceNames.length; i++) { 
       dout.writeUTF(ifaceNames[i]); 
      } 
     } 

     Field[] fields = cl.getDeclaredFields(); 
     MemberSignature[] fieldSigs = new MemberSignature[fields.length]; 
     for (int i = 0; i < fields.length; i++) { 
      fieldSigs[i] = new MemberSignature(fields[i]); 
     } 
     Arrays.sort(fieldSigs, new Comparator<MemberSignature>() { 
      public int compare(MemberSignature ms1, MemberSignature ms2) { 
       return ms1.name.compareTo(ms2.name); 
      } 
     }); 
     for (int i = 0; i < fieldSigs.length; i++) { 
      MemberSignature sig = fieldSigs[i]; 
      int mods = sig.member.getModifiers() & 
       (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | 
       Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE | 
       Modifier.TRANSIENT); 
      if (((mods & Modifier.PRIVATE) == 0) || 
       ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) 
      { 
       dout.writeUTF(sig.name); 
       dout.writeInt(mods); 
       dout.writeUTF(sig.signature); 
      } 
     } 

     if (hasStaticInitializer(cl)) { 
      dout.writeUTF("<clinit>"); 
      dout.writeInt(Modifier.STATIC); 
      dout.writeUTF("()V"); 
     } 

     Constructor[] cons = cl.getDeclaredConstructors(); 
     MemberSignature[] consSigs = new MemberSignature[cons.length]; 
     for (int i = 0; i < cons.length; i++) { 
      consSigs[i] = new MemberSignature(cons[i]); 
     } 
     Arrays.sort(consSigs, new Comparator<MemberSignature>() { 
      public int compare(MemberSignature ms1, MemberSignature ms2) { 
       return ms1.signature.compareTo(ms2.signature); 
      } 
     }); 
     for (int i = 0; i < consSigs.length; i++) { 
      MemberSignature sig = consSigs[i]; 
      int mods = sig.member.getModifiers() & 
       (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | 
       Modifier.STATIC | Modifier.FINAL | 
       Modifier.SYNCHRONIZED | Modifier.NATIVE | 
       Modifier.ABSTRACT | Modifier.STRICT); 
      if ((mods & Modifier.PRIVATE) == 0) { 
       dout.writeUTF("<init>"); 
       dout.writeInt(mods); 
       dout.writeUTF(sig.signature.replace('/', '.')); 
      } 
     } 

     MemberSignature[] methSigs = new MemberSignature[methods.length]; 
     for (int i = 0; i < methods.length; i++) { 
      methSigs[i] = new MemberSignature(methods[i]); 
     } 
     Arrays.sort(methSigs, new Comparator<MemberSignature>() { 
      public int compare(MemberSignature ms1, MemberSignature ms2) { 
       int comp = ms1.name.compareTo(ms2.name); 
       if (comp == 0) { 
        comp = ms1.signature.compareTo(ms2.signature); 
       } 
       return comp; 
      } 
     }); 
     for (int i = 0; i < methSigs.length; i++) { 
      MemberSignature sig = methSigs[i]; 
      int mods = sig.member.getModifiers() & 
       (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | 
       Modifier.STATIC | Modifier.FINAL | 
       Modifier.SYNCHRONIZED | Modifier.NATIVE | 
       Modifier.ABSTRACT | Modifier.STRICT); 
      if ((mods & Modifier.PRIVATE) == 0) { 
       dout.writeUTF(sig.name); 
       dout.writeInt(mods); 
       dout.writeUTF(sig.signature.replace('/', '.')); 
      } 
     } 

     dout.flush(); 

     MessageDigest md = MessageDigest.getInstance("SHA"); 
     byte[] hashBytes = md.digest(bout.toByteArray()); 
     long hash = 0; 
     for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) { 
      hash = (hash << 8) | (hashBytes[i] & 0xFF); 
     } 
     return hash; 
    } catch (IOException ex) { 
     throw new InternalError(); 
    } catch (NoSuchAlgorithmException ex) { 
     throw new SecurityException(ex.getMessage()); 
    } 
} 
+0

@Jeffrey ...Khá Crafty +1 –

2

Nếu công cụ của bạn là tạo ra thương hiệu mã mới bạn không có bất kỳ cần phải tính toán nó theo cách serialver làm. Chỉ cần sử dụng 1, hoặc -1, hoặc bất cứ điều gì bạn thích.

+0

Bạn có thể giải thích lý do tại sao? Đây có phải vì nó là một lớp học mới? –

+1

@bn. Vì nó là một lớp mới, không có serialization hiện tại của nó, do đó, không có gì để tương thích. – EJP

1

Đây là một chủ đề cũ nhưng, tôi đoán, serialVersionUID vẫn là một trong những chủ đề nóng.

Khi tôi bắt đầu viết mã Java, quá khó để tìm và gán giá trị duy nhất cho biến số serlialVersionUID cho tôi. Sau một thời gian, định dạng ngày tháng đơn giản (yyyy-MM-ddTHH: mm: ss) đã cho tôi ý tưởng: Tại sao tôi không tạo giá trị từ ngày giờ hiện tại?

Vì vậy, tôi bắt đầu tạo các giá trị (tất nhiên theo cách thủ công) theo ngày giờ hiện tại.

Giả sử ngày và giờ hiện tại là 01/09/2015 11:00 chiều. Tôi sẽ gán giá trị 201601091100L cho serialVersionUID.

Tôi hy vọng ý tưởng này sẽ giúp bạn cải thiện thêm trong các dự án của bạn.

+0

Nhân tiện, định dạng cho chuỗi ngày giờ được xác định bởi tiêu chuẩn [ISO 8601] (https://en.wikipedia.org/wiki/ISO_8601) rất hữu ích. Các dấu gạch nối và dấu hai chấm là tùy chọn như bạn đã chỉ ra, được gọi là biến thể "cơ bản". Khung công tác [java.time] (http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) được xây dựng trong Java 8 và sau đó sử dụng định dạng ISO 8601 theo mặc định trong phân tích cú pháp/tạo ra các biểu diễn chuỗi các giá trị ngày-thời gian. –