2014-05-16 12 views
6

डीबगिंग उद्देश्यों मैं (है, हालांकि यह भी अन्य लैम्ब्डा भाव के लिए दिलचस्प होगा Predicate एस के लिए विशेष रूप से) जावा 8. में लैम्ब्डा अभिव्यक्ति की स्ट्रिंग अभ्यावेदन बनाने के लिए कोशिश कर रहा हूँ मेरा विचार कुछ इस तरह होगा के लिए :बनाना स्ट्रिंग प्रतिनिधित्व

public class Whatever { 

    private static <T> String predicateToString(Predicate<T> predicate) { 
     String representation = ... // do magic 
     return representation; 
    } 

    public static void main(String[] args) { 
     System.out.println(Whatever.<Integer>predicateToString(i -> i % 2 == 0)); 
    } 

} 

और उत्पादन i -> i % 2 == 0 (या कुछ और तार्किक बराबर) होगा। toString() विधि कोई मदद नहीं प्रतीत होती है, आउटपुट com.something.Whatever$$Lambda$1/[email protected] जैसा कुछ है (जो मुझे लगता है कि toString() को ओवरराइड नहीं किया गया है)।

मुझे यकीन नहीं है कि ऐसा कुछ भी संभव है, उदाहरण के लिए प्रतिबिंब के साथ, मैं निश्चित रूप से अब तक कुछ भी नहीं ढूंढ पाया है। कोई विचार?

+0

डीबगिंग उद्देश्यों? क्या आप सिर्फ स्रोत को नहीं देख सकते? –

+2

कि एक decompiler की आवश्यकता होगी। – SLaks

+0

@SotiriosDelimanolis बेशक मैं हमेशा स्रोत को देख सकता हूं। लेकिन प्रिंट करने योग्य प्रतिनिधित्व भी अच्छा होगा। – blalasaadri

उत्तर

13

सरल बात मैं एक "नाम विधेय" है कि अपने विधेय एक नाम या विवरण, मूल रूप से कुछ भी है कि के रूप में एक toString उपयोगी होगा देता है पैदा कर रही है के साथ आ सकता है:

public class NamedPredicate<T> implements Predicate<T> { 
    private final String name; 
    private final Predicate<T> predicate; 

    public NamedPredicate(String name, Predicate<T> predicate) { 
     this.name = name; 
     this.predicate = predicate; 
    } 

    @Override 
    public boolean test(T t) { 
     return predicate.test(t); 
    } 

    @Override 
    public String toString() { 
     return name; 
    } 

    public static void main(String... args) { 
     Predicate<Integer> isEven = new NamedPredicate<>("isEven", i -> i % 2 == 0); 
     System.out.println(isEven); // prints isEven 
    } 
} 

यकीनन दे रही है अपने विधेय नाम

Stream.of(1, 2, 3, 4) 
     .filter(isEven) 
     .forEach(System.out::println); 

एक अजनबी विचार विधेय, यानी की एक "संरचनात्मक" विवरण का निर्धारण करने के लिए कुछ दिया inp के लिए उत्पादन होता है क्या हो सकता है: या इस तरह वर्णन कोड जहाँ आप उन्हें थोड़ा आसान का उपयोग यह भी समझने की बनाता है संघ राज्य क्षेत्रों? स्पष्ट रूप से यह सबसे अच्छा काम करेगा जब इनपुट सेट सीमित और छोटा होगा (उदाहरण के लिए एनम्स, बूलियन या कुछ अन्य प्रतिबंधित सेट के लिए), लेकिन मुझे लगता है कि आप पूर्णांक के लिए "यादृच्छिक" पूर्णांक के छोटे सेट को भी आजमा सकते हैं:

private static Map<Boolean, List<Integer>> testPredicate(Predicate<Integer> predicate) { 
    return Stream.of(-35, -3, 2, 5, 17, 29, 30, 460) 
      .collect(Collectors.partitioningBy(predicate)); 
} 

isEven के लिए, यह {false=[-35, -3, 5, 17, 29], true=[2, 30, 460]} जैसा कुछ वापस लौटाएगा, जो मुझे लगता है कि मैन्युअल रूप से उन्हें विवरण देने की तुलना में यह स्पष्ट रूप से स्पष्ट नहीं है, लेकिन यह संभवतः उन भविष्यवाणियों के लिए उपयोगी है जो आपके नियंत्रण में नहीं हैं।

+0

हालांकि यह काम करना चाहिए, लैम्ब्डा अभिव्यक्ति वाक्यविन्यास की सुंदरता आंशिक रूप से यहां खो गई है क्योंकि रैपर ऑब्जेक्ट 'नामांकित प्रिंटर' को 'नए' ऑपरेटर के साथ बनाया जाना है। – blalasaadri

+0

@blalasaadri सच। मुझे लगता है कि आप 'स्थिर' और '<>' जैसे कुछ स्थिरता को छुपा सकते हैं, इसके बजाए स्थिर कारखाना विधि बनाकर देखें (उदाहरण के लिए सभी अमरूद संग्रह कारखाने के तरीके)।मैंने इस तथ्य के बाद किसी भी भविष्यवाणी से प्रकार का विवरण निर्धारित करने के लिए एक और विचार भी जोड़ा - मुझे यकीन नहीं है कि यह उपयोगी है, लेकिन फिर भी अन्वेषण करना दिलचस्प हो सकता है! – andersschuller

+0

एक फैक्ट्री विधि स्थिति को बेहतर बनाएगी, निश्चित रूप से। अभी भी आदर्श नहीं है लेकिन अभिव्यक्ति निकालने के एक प्रोग्रामिक तरीके की कमी में यह शायद सबसे सुंदर समाधान है। – blalasaadri

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