2017-06-26 9 views
5

मेरे पास एक सामान्य जावा इंटरफ़ेस Id<T> एक विधि T getId() और एक वर्ग MyClass है जो Id<Long> लागू करता है। जब मैं जावा प्रतिबिंब का उपयोग कर MyClass पर घोषित विधियों का निरीक्षण करता हूं, तो मुझे दो विधियां दिखाई देती हैं: एक वापसी प्रकार Long, और एक वापसी प्रकार Object के साथ। दूसरी विधि कहां से आती है और मैं इसे कैसे हटा सकता हूं?जेनेरिक जावा इंटरफ़ेस को कार्यान्वित करना अतिरिक्त विधि

package mypackage; 

import java.lang.reflect.Method; 

public class MainClass { 
    public static void main(String[] args) { 
     for (Method method : MyClass.class.getDeclaredMethods()) { 
      System.out.println(method); 
     } 
     // prints out two lines 
     // public java.lang.Long mypackage.MyClass.getId() <-- ok 
     // public java.lang.Object mypackage.MyClass.getId() <-- not ok 
    } 
} 

interface Id<T> { 
    T getId(); 
} 

class MyClass implements Id<Long> { 
    @Override 
    public Long getId() { 
     return new Long(0); 
    }; 
} 
+0

रिटर्नटाइप 'लांग' के साथ एक विधि में आप एक आदिम' लम्बा 'भी वापस कर सकते हैं उदा। 'वापसी 0 एल;'। यह एक 'लांग' के लिए autoboxed होगा। आपके प्रश्न का उत्तर नहीं, लेकिन शायद आपको पता नहीं था। –

उत्तर

3

दूसरी विधि synthetic bridge विधि है, तो आप इसे method.isSynthetic() या method.isBridge() से देख सकते हैं। आप इसे हटा नहीं सकते हैं, लेकिन यदि आप इसे घोषित विधियों की सूची में देखना नहीं चाहते हैं, तो बस उन सभी विधियों को जांचें जिनके पास isBridge() == false है।

संकलन के दौरान जेनेरिक कक्षाओं में सिंथेटिक पुल विधियों को स्वचालित रूप से जोड़ा जाता है। आप कृत्रिम तरीकों here के बारे में अधिक पढ़ सकते हैं।

for (Method method : MyClass.class.getDeclaredMethods()) { 
    System.out.println("Method: " + method); 
    System.out.println("synthetic: " + method.isSynthetic()); 
    System.out.println("bridge: " + method.isBridge()); 
} 

// 1 
//Method: public java.lang.Long Main$MyClass.getId() 
//synthetic: false 
//bridge: false 
// 2 
//Method: public java.lang.Object Main$MyClass.getId() 
//synthetic: true 
//bridge: true 
1

आप javap -c MyClass द्वारा संकलित तरीकों पा सकते हैं:

Compiled from "Test.java" 
class MyClass implements Id<java.lang.Long> { 
    MyClass(); 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

    public java.lang.Long getId(); 
    Code: 
     0: new   #2     // class java/lang/Long 
     3: dup 
     4: lconst_0 
     5: invokespecial #3     // Method java/lang/Long."<init>":(J)V 
     8: areturn 

    public java.lang.Object getId(); 
    Code: 
     0: aload_0 
     1: invokevirtual #4     // Method getId:()Ljava/lang/Long; 
     4: areturn 
} 

तुम वहाँ getId के लिए तरीकों, एक वापसी प्रकारLongimplementation के रूप में है और एक अन्य वापसी कर रहे हैं देख सकते हैं टाइपObject प्रकार है (यह Long getId विधि का आह्वान कर रहा है)।

वापसी प्रकारObjectविधि जब कोई Long getId विधि के लिए सामान्य प्रकार और पुल निर्दिष्ट से निपटने के लिए है। उदाहरण:

Id<Long> id = new Id<Long>() { 
     @Override 
     public Long getId() { 
      return null; 
     } 
    }; 
    Long id1 = id.getId(); 

ऊपर कोड के रूप में झलकी हम Long प्रकार के साथ Id गुमनाम वर्ग को लागू कर सकते हैं। लेकिन समस्या यह है हम भी Id गुमनाम वर्ग को लागू कर सकते हैं की तरह बिना चर में सामान्य प्रकार निर्दिष्ट करें:

Id id = new Id<Long>() { 
     @Override 
     public Long getId() { 
      return null; 
     } 
    }; 
    Object id1 = id.getId(); 

इसलिए अभी संकलक सामान्य प्रकार चर id के लिए अनुमान नहीं लगा सकता, जब id.getId() यह प्रकार लौटने है Object टाइप वैरिएबल, इसका मतलब है कि यह इस विधि को public java.lang.Object getId(); और public java.lang.Long getId(); विधि से पुल कर रहा है।

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