2015-03-31 7 views
10

प्रति Erasure of Generic Types पर जावा प्रलेखन के रूप में,जावा जेनेरिक्स प्रकार मिटाना बाइट कोड

निम्नलिखित सामान्य वर्ग है कि एक अकेले लिंक्ड सूची में एक नोड का प्रतिनिधित्व करता है पर विचार करें:

public class Node<T> { 

    private T data; 
    private Node<T> next; 

    public Node(T data, Node<T> next) } 
     this.data = data; 
     this.next = next; 
    } 

    public T getData() { return data; } 
    // ... 
} 

क्योंकि प्रकार पैरामीटर टी

public class Node { 

    private Object data; 
    private Node next; 

    public Node(Object data, Node next) { 
     this.data = data; 
     this.next = next; 
    } 

    public Object getData() { return data; } 
    // ... 
} 
: असीम है, जावा कम्पाइलर वस्तु साथ यह बदल देता है

लेकिन जावा 1.7.0_11 के साथ संकलन के बाद, जब मैंने इसे किसी भी डिकंपेलर के साथ खोला तो मैं उसी कोड को स्रोत कोड जैसा देख सकता हूं।

public class Node<T> 
{ 
    private T data; 
    private Node<T> next; 

    public Node(T paramT, Node<T> paramNode) 
    { 
    this.data = paramT; 
    this.next = paramNode; 
    } 

    public T getData() 
    { 
    return this.data; 
    } 
} 

यदि टाइप-एरर संकलन पर लागू होता है तो बाइट कोड में ऊपर दिखाए गए जेनेरिक जानकारी नहीं होनी चाहिए। कृपया मुझे स्पष्ट करें।

नोट: मैं एक decompiler के रूप में JD-GUI उपयोग कर रहा हूँ अभी भी, बाईटकोड में सहेजा गया है वर्ग के सदस्यों के हस्ताक्षर जानकारी में विशेष रूप से बाइट कोड

+0

आप अपने decompiler के लिए लिंक को ठीक कर सकता है? –

+2

एक प्रकार के सामान्य होने के बीच एक अंतर है, और ठोस जेनेरिक प्रकार को जानने में सक्षम होना। –

+1

मिटा _objects_ की सामान्य प्रकार की जानकारी मिटा देता है, नहीं _types._ –

उत्तर

3

जेनेरिक प्रकार की जानकारी का विश्लेषण करने के लिए।

उदाहरण के लिए, को क्रियान्वित करने javap -verbose Node.class पैदावार:

... 
LocalVariableTypeTable: 
     Start Length Slot Name Signature 
      0  5  0 this Ltest/Node<TT;>; 

this section from the JVM specification देखें:

हस्ताक्षर एनकोड घोषणाओं जावा प्रोग्रामिंग भाषा में लिखा है कि जावा वर्चुअल मशीन के प्रकार प्रणाली के बाहर प्रकार का उपयोग करें । वे प्रतिबिंब और डिबगिंग का समर्थन करते हैं, साथ ही संकलन जब केवल कक्षा फाइलें उपलब्ध होती हैं।

एक जावा कंपाइलर को किसी वर्ग, इंटरफ़ेस, कन्स्ट्रक्टर, विधि या फ़ील्ड के लिए हस्ताक्षर उत्सर्जित करना चाहिए जिसका घोषणा प्रकार चर या पैरामीटरयुक्त प्रकारों का उपयोग करती है। विशेष रूप से, एक जावा संकलक फेंकना चाहिए:

  • किसी भी वर्ग या इंटरफ़ेस घोषणा है जो या तो सामान्य है, या एक सुपर क्लास या superinterface, या दोनों के रूप में एक पैरामिट्रीकृत प्रकार है के लिए एक वर्ग हस्ताक्षर।

  • कोई भी तरीका या निर्माता घोषणा के लिए एक विधि हस्ताक्षर है जो या तो सामान्य है, या एक प्रकार चर या वापसी प्रकार या एक औपचारिक पैरामीटर प्रकार रूप पैरामिट्रीकृत प्रकार है, या एक खंड फेंकता में एक प्रकार चर है, या इसका कोई संयोजन

5

बाईटकोड इस तरह के सामान्य प्रकार के (या चर नाम) के रूप में कोड में ही, के बारे में मेटा जानकारी शामिल है - यह यह JVM द्वारा useable है मतलब यह नहीं है।

अपने वर्ग के disassembled बाईटकोड नीचे की तरह दिखता है (यदि आप इसे javap -c Node.class साथ देख सकते हैं):

public class Node<T> { 
    public Node(T, Node<T>); 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: aload_0 
     5: aload_1 
     6: putfield  #2     // Field data:Ljava/lang/Object; 
     9: aload_0 
     10: aload_2 
     11: putfield  #3     // Field next:LNode; 
     14: return 

    public T getData(); 
    Code: 
     0: aload_0 
     1: getfield  #2     // Field data:Ljava/lang/Object; 
     4: areturn 
} 

आपको लगता है कि तरीकों और तर्क सामान्य प्रकार के होते हैं देख सकते हैं लेकिन कोड में ही अपेक्षा के अनुरूप वस्तु को संदर्भित करता है मिटाने की प्रक्रिया के कारण।

3

तथ्य यह है कि कक्षा सामान्य है। उदाहरण के लिए, रनटाइम पर आप

Node.class.getTypeParameters() 

कोड का अगला बिट "टी" वापस कर सकता है।

(new Node<Integer>()).getClass().getTypeParameters()[0].getName() 

आप रनटाइम पर टाइप पैरामीटर का मान नहीं प्राप्त कर सकते हैं, लेकिन JVM जानता है कि वे वहां हैं।

जब आप एक उदाहरण बनाते हैं तो त्रुटि खेल में आती है।

Node<Integer> node = new Node<Integer>(1, null); 
Integer i = node.getData(); 

हो जाता है

Node node = new Node(1, null); 
Integer i = (Integer)node.getData(); 

जेनेरिक कक्षाओं हमेशा सामान्य हैं। लेकिन उदाहरणों में उनके अंदर सामान्य प्रकार की जानकारी नहीं है। संकलक सत्यापित करता है कि आपने जो भी किया है वह सामान्य प्रकार से सहमत है और फिर सम्मिलित करता है।

0

हर कोई,

मुझे आशा है कि यह decompiler समस्या केवल अर्थात जद-जीयूआई है।

मैं अलग decompiler के साथ खुला जब अर्थात JDecompiler, मैं कर सकते हैं इस प्रकार की उम्मीद Bytecode देखने के लिए सक्षम:

public class Node { 

      private Object data; 
      private Node next; 

      public Node(Object obj, Node node) { 
/* 7*/  data = obj; 
/* 8*/  next = node; 
      } 

      public Object getData() { 
/* 12*/  return data; 
      } 
} 
संबंधित मुद्दे