2013-08-17 18 views
7

मैं एक परियोजना पर काम कर रहा हूं जो जावा फ़ाइलों को उत्पन्न करता है। मैं उपकरण के साथ वैकल्पिक रूप से serialVersionUID जोड़ने में सक्षम होना चाहता हूं।जावा में प्रोग्रामेटिक रूप से serialVersionUID कैसे उत्पन्न करें?

क्या यह करने का कोई तरीका है जब मैं जावा कोड उत्पन्न करता हूं, या मुझे यूआईडी मैन्युअल रूप से प्रदान करने के लिए टूल के उपयोगकर्ता से पूछने की आवश्यकता होगी? स्पष्ट होने के लिए, मैं इसे ग्रहण या serialver उपकरण के माध्यम से स्वचालित रूप से करने की कोशिश नहीं कर रहा हूं, लेकिन जावा के माध्यम से इसे करने के लिए इसे स्वचालित रूप से करने के लिए नहीं देख रहा हूं।

+0

शायद उत्पन्न होने वाले वर्ग के वर्ग के नाम का हैशकोड काम करेगा? –

+0

मैं इस तरह के बारे में सोच रहा था, सोच रहा हूं कि ऐसा करने का कोई तरीका है जो सीरियलवर टूल के बराबर है, यदि संभव हो तो। –

+0

निश्चित रूप से, आप इसे सीरियलवर टूल की तरह कर सकते हैं। बस अपनी 'serialVersionUID' पीढ़ी के पीछे तर्क ढूंढें। मैं अब तक कोई सफलता नहीं देख रहा हूं। –

उत्तर

7

serialver उपकरण स्रोत from OpenJDK का एक संस्करण उपलब्ध है। यह सब इस कॉल करने के लिए नीचे आता है:

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

JDK 6 में कम से कम इसे serialver उपकरण के साथ एक ही नंबर देता है।

2

उत्पन्न होने वाले वर्ग के वर्ग नाम के हैशकोड को आजमाएं।

हैशकोड के रूप में टक्कर हो सकती है क्योंकि हैशकोड अद्वितीय नहीं है, लेकिन उन टकराव सांख्यिकीय रूप से असंभव हैं।

Here's documentation कैसे serialVersionUID मान उत्पन्न होते हैं। मैं अनुमान लगाया था उससे कहीं अधिक जटिल।

इसकी जटिलता के कारण, मेरे पास या तो यूआईडी में उपयोगकर्ता का प्रकार होगा, या सिर्फ पूर्ण वर्ग नाम का एक सरल हैश का उपयोग करें।

3
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

@ जेफरी ...काफी चालाक +1 –

2

अपने उपकरण ब्रांड के नए कोड पैदा कर रहा है, तो आप इसे जिस तरह से serialver करता गणना करने के लिए किसी भी आवश्यकता नहीं है। बस 1, या -1, या जो कुछ भी आपको पसंद है उसका उपयोग करें।

+0

क्या आप समझा सकते हैं क्यों? क्या ऐसा इसलिए है क्योंकि यह एक नई कक्षा है? –

+1

@bn। चूंकि यह एक नई कक्षा है, इसके कोई मौजूदा क्रमिकरण नहीं हैं, इसलिए अनुकूल होने के लिए कुछ भी नहीं है। – EJP

1

यह एक पुराना धागा है, लेकिन मुझे लगता है, serialVersionUID अभी भी गर्म विषयों में से एक है।

जब मैंने जावा कोड लिखना शुरू किया, तो serlialVersionUID मेरे लिए वैरिएबल को अनन्य मान ढूंढना और असाइन करना बहुत मुश्किल था। थोड़ी देर के बाद, सरल दिनांक समय प्रारूप (yyyy-MM-ddTHH: mm: ss) ने मुझे यह विचार दिया: मैं वर्तमान दिनांक और समय से मूल्य क्यों नहीं उत्पन्न करूं?

तो, मैंने वर्तमान दिनांक और समय के अनुसार मूल्यों (मैन्युअल रूप से मैन्युअल रूप से) उत्पन्न करना शुरू कर दिया।

मान लें कि वर्तमान दिनांक और समय 01/09/2015 11:00 बजे है। मैं serialVersionUID को 201601091100L मान असाइन करेगा।

मुझे आशा है कि यह विचार आपको अपनी परियोजनाओं में और सुधार के लिए मदद करेगा।

+0

वैसे, दिनांक-समय तारों के लिए यह प्रारूप बहुत उपयोगी [आईएसओ 8601] (https://en.wikipedia.org/wiki/ISO_8601) मानक द्वारा परिभाषित किया गया है। हाइफ़न और कोलन वैकल्पिक हैं जैसा आपने दिखाया है, जिसे "मूल" भिन्नता कहा जाता है। [Java.time] (http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) जावा 8 में बनाया गया ढांचा और बाद में पार्सिंग में डिफ़ॉल्ट रूप से आईएसओ 8601 प्रारूपों का उपयोग करता है/दिनांक-समय मानों के स्ट्रिंग प्रस्तुतिकरण उत्पन्न करना। –

संबंधित मुद्दे