2015-07-29 18 views
10

मेरे एप्लिकेशन में मैं एक समस्या में भाग लेता हूं कि जब किसी क्लास में गेटर केवल इंटरफ़ेस (जावा 8 फीचर) में डिफॉल्ट होता है, तो जावा बीन्स प्रॉपर्टी नहीं होती है परिणाम। अर्थात। सामान्य विधि मंगलाचरण के लिए यह सिर्फ एक मानक पद्धति के रूप में, लेकिन "गुण" यह अचानक अलग ढंग से व्यवहार करती है के माध्यम से उपयोग करने के लिए काम करता है ...जावा 8 इंटरफ़ेस डिफ़ॉल्ट विधि प्रॉपर्टी घोषित नहीं करती है

यहाँ एक परीक्षण मामला है:

import java.beans.Introspector; 
import java.util.Arrays; 
import java.util.stream.Collectors; 
import org.apache.commons.beanutils.PropertyUtils; 

public class test 
{ 
    public static void main (String[] arguments) throws Exception 
    { 
     // Normal language-level invocation, works fine. 
     System.out.println (new Bean1().getFoo()); 
     System.out.println (new Bean2().getFoo()); 

     // Printing Java Beans properties; Bean2 doesn't have 'foo' property... 
     System.out.println (Arrays.stream (Introspector.getBeanInfo (Bean1.class).getPropertyDescriptors()) 
          .map ((property) -> property.getName()) 
          .collect (Collectors.joining (", "))); 
     System.out.println (Arrays.stream (Introspector.getBeanInfo (Bean2.class).getPropertyDescriptors()) 
          .map ((property) -> property.getName()) 
          .collect (Collectors.joining (", "))); 

     // First call behaves as expected, second dies with exception. 
     System.out.println (PropertyUtils.getProperty (new Bean1(), "foo")); 
     System.out.println (PropertyUtils.getProperty (new Bean2(), "foo")); 
    } 

    public interface Foo 
    { 
     default String getFoo() 
     { 
      return "default foo"; 
     } 
    } 

    public static class Bean1 implements Foo 
    { 
     @Override 
     public String getFoo() 
     { 
      return "special foo"; 
     } 
    } 

    public static class Bean2 implements Foo 
    { } 
} 

परिणाम:

special foo 
default foo 
class, foo 
class 
special foo 
Exception in thread "main" java.lang.NoSuchMethodException: Unknown property 'foo' on class 'class test$Bean2' 
     at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1257) 
     at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:808) 
     at org.apache.commons.beanutils.PropertyUtilsBean.getProperty(PropertyUtilsBean.java:884) 
     at org.apache.commons.beanutils.PropertyUtils.getProperty(PropertyUtils.java:464) 
     at test.main(test.java:21) 

प्रश्न: क्या मैं कुछ गलत करता हूं या जावा में यह एक बग है? क्या किसी भी समय बाद में "संपत्ति" के रूप में उन्हें एक्सेस करने की आवश्यकता हो सकती है, तो डिफॉल्ट विधियों (गेटर्स/सेटर्स के लिए) का उपयोग करने के अलावा कोई कामकाज नहीं है?

मैं हमेशा "सम्मेलन द्वारा गुणों" से नफरत करता हूं जो टूटने लगते हैं क्योंकि आप गलत तरीके से छींकते हैं।

+3

ऐसा लगता है कि यह [जेडीके -8071693] (https://bugs.openjdk.java.net/browse/JDK-8071693) द्वारा कवर किया गया है, अभी तक किसी भी जेडीके रिलीज में तय नहीं है। –

+0

हां, वास्तव में। आशा है कि वे इसे ठीक करें। – doublep

+0

मुझे इस बग द्वारा भी काट दिया गया है। ओपनजेडीके बग जावा 9 के लिए निर्धारित है जिसका मतलब है कि इसे कम से कम सितंबर 2016 तक तय करना होगा। इस बीच मैं उस वर्ग में एक प्रतिनिधि विधि तैयार करूंगा जिसकी संपत्ति की आवश्यकता है। –

उत्तर

2

यह वास्तव में बीन्स Introspector में एक गलत चूक है। यहाँ एक वैकल्पिक हल default तरीकों का उपयोग कर नहीं के अलावा अन्य है:

public static void main (String[] arguments) throws Exception { 
    testBean(new Bean1()); 
    System.out.println(); 
    testBean(new Bean2()); 
} 
static void testBean(Object bean) throws Exception { 
    PropertyDescriptor[] pd 
     = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 
    System.out.println(Arrays.stream(pd) 
     .map(PropertyDescriptor::getName).collect(Collectors.joining(", "))); 
    for(PropertyDescriptor p: pd) 
     System.out.println(p.getDisplayName()+": "+p.getReadMethod().invoke(bean)); 
} 
public interface Foo { 
    default String getFoo() { 
     return "default foo"; 
    } 
} 
public static class Bean1 implements Foo { 
    @Override 
    public String getFoo() { 
     return "special foo"; 
    } 
} 
public static class Bean2BeanInfo extends SimpleBeanInfo { 
    private final BeanInfo ifBeanInfo; 
    public Bean2BeanInfo() throws IntrospectionException { 
     ifBeanInfo=Introspector.getBeanInfo(Foo.class); 
    } 
    @Override 
    public BeanInfo[] getAdditionalBeanInfo() { 
     return new BeanInfo[]{ifBeanInfo}; 
    } 
} 
public static class Bean2 implements Foo { } 
class, foo 
class: class helper.PropTest$Bean1 
foo: special foo 
class, foo 
class: class helper.PropTest$Bean2 
foo: default foo 
+0

स्पष्ट रूप से, यह शुरू करने के लिए डिफ़ॉल्ट विधियों का उपयोग कभी भी अधिक असुविधाजनक नहीं है। – doublep

+1

हम्म, आपने कहा कि आप "सम्मेलन द्वारा गुण" से नफरत करते हैं, तो फिर एक स्पष्ट beaninfo के साथ समस्या क्या है? लेकिन वैसे भी, जावा 8 आपको एकल-लाइनर वाले फ़ंक्शन आधारित प्रॉपर्टी-जैसी ऑब्जेक्ट्स बनाने की अनुमति देता है, इसलिए मुझे इसके लिए प्रतिबिंब आधारित टूल का बिंदु नहीं दिखाई देता है। फिर भी, ओरेकल को ठीक करने के लिए प्रतीक्षा करने का एकमात्र विकल्प है ... – Holger

+0

होल्गर: मुझे स्पष्ट गुण चाहिए, लेकिन यदि जावा के लिए उनके लिए एक सन वाक्यविन्यास था, तो मौजूदा तंत्र के शीर्ष पर कुछ हैकिंग नहीं। आपकी विधि के साथ एक बड़ी समस्या यह है कि सब कुछ अलग-अलग स्थानों पर फैलता है, इसलिए आपके पास एक स्थान पर गेटर्स/सेटर्स हैं, बीन जानकारी कहीं और आदि। – doublep

0

एक त्वरित वैकल्पिक हल:

try { 
    return PropertyUtils.getProperty(bean, property); 
} 
catch (NoSuchMethodException e) { 
    String getMethod = "get" + property.substring(0, 1).toUpperCase() + property.substring(1); 
    return MethodUtils.invokeMethod(bean, getMethod, new Object[]{}); 
} 
+0

यह मेरे मामले में मदद नहीं करता है, क्योंकि मुझे गुणों की आवश्यकता है जावा ईएल से दृश्यमान। अर्थात। मैं उस स्थान को नियंत्रित नहीं करता जहां उन्हें पहुंचाया जाता है। – doublep

0

अगर मेरा जवाब उपयोगी होगा पता नहीं है, लेकिन मैं इसी तरह के हल वसंत से BeanUtils.getPropertyDescriptors(clazz) का उपयोग कर समस्या। यह डिफ़ॉल्ट तरीकों को समझता है।

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