2015-11-18 16 views
5

में कोशिश किए बिना लैम्ब्डा में अपवाद को संभालना, जहां तक ​​मुझे पता है, लैम्बडा द्वारा लागू अपूर्ण विधि को throws पर हस्ताक्षर में नहीं किया गया है, तो लैम्ब्डा में अपवाद को अपनाने में कोई भी संभाल नहीं सकता है।लैम्ब्डा

मुझे निम्नलिखित कोड का सामना करना पड़ा, यह काम करता है। openStream()IOException को संभालने की मांग क्यों नहीं करता है? मैं tryWithResources में try-catch देख सकता हूं लेकिन मुझे इसके पीछे तंत्र को समझ में नहीं आता है।

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Collection; 
import java.util.Map; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ConcurrentSkipListMap; 
import java.util.function.Function; 
import java.util.function.Supplier; 

public class Main { 

    public static <AUTOCLOSEABLE extends AutoCloseable, OUTPUT> Supplier<OUTPUT> tryWithResources(
      Callable<AUTOCLOSEABLE> callable, Function<AUTOCLOSEABLE, Supplier<OUTPUT>> function, 
      Supplier<OUTPUT> defaultSupplier) { 
     return() -> { 
      try (AUTOCLOSEABLE autoCloseable = callable.call()) { 
       return function.apply(autoCloseable).get(); 
      } catch (Throwable throwable) { 
       return defaultSupplier.get(); 
      } 
     }; 
    } 

    public static <INPUT, OUTPUT> Function<INPUT, OUTPUT> function(Supplier<OUTPUT> supplier) { 
     return i -> supplier.get(); 
    } 

    public static void main(String... args) { 
     Map<String, Collection<String>> anagrams = new ConcurrentSkipListMap<>(); 
     int count = tryWithResources(
       () -> new BufferedReader(new InputStreamReader(
         new URL("http://www.puzzlers.org/pub/wordlists/unixdict.txt").openStream())), 
       reader ->() -> reader.lines().parallel().mapToInt(word -> { 
        char[] chars = word.toCharArray(); 
        Arrays.parallelSort(chars); 
        String key = Arrays.toString(chars); 
        Collection<String> collection = anagrams.computeIfAbsent(key, function(ArrayList::new)); 
        collection.add(word); 
        return collection.size(); 
       }).max().orElse(0),() -> 0).get(); 
     anagrams.values().stream().filter(ana -> ana.size() >= count).forEach((list) -> { 
      for (String s : list) 
       System.out.print(s + " "); 
      System.out.println(); 
     }); 
    } 
} 

उत्तर

8

मैं मुख्य भाग को अपने उदाहरण सरल बना दिया है:

public static void main(String[] args) { 
    withCallable(() -> new URL("url").openStream()); // compiles 
    withSupplier(() -> new URL("url").openStream()); // does not compile 
} 

public static <T> void withCallable(Callable<T> callable) { } 

public static <T> void withSupplier(Supplier<T> callable) { } 

आप इस के साथ प्रयास करें, तो आप उस withCallable ठीक संकलन होगा देखेंगे लेकिन वह withSupplier संकलन नहीं करता है; भले ही लैम्ब्डा अभिव्यक्ति दोनों कार्यात्मक इंटरफेस के हस्ताक्षर के साथ संगत है।

इसका कारण यह है कि Callable इंटरफ़ेस की कार्यात्मक विधि, जो call() है, throws Exception अपने हस्ताक्षर में घोषित करती है। Supplier.get() नहीं करता है।

JLS section 11.2.3 का हवाला देते हुए:

यह एक संकलन समय त्रुटि है अगर एक लैम्ब्डा शरीर कुछ अपवाद वर्ग ई फेंक कर सकते हैं जब ई एक जाँच अपवाद वर्ग है और ई कुछ वर्ग में घोषित की एक उपवर्ग नहीं है लैम्ब्डा अभिव्यक्ति द्वारा लक्षित फ़ंक्शन प्रकार का फेंकता खंड।

1

जहाँ तक मुझे पता है, एक लैम्ब्डा में फेंक दिया अपवाद नहीं संभाल सकता सार विधि लैम्ब्डा द्वारा कार्यान्वित नहीं है उसके हस्ताक्षर में फेंकता है तो।

एक कामकाज है, जिसे sneaky throw के नाम से जाना जाता है; कार्यात्मक सहायकों के बिना यहां simpler example

कुछ स्थिर सहायक कार्यों कि गैर फेंकने वाले जो चाल में अपने फेंक हस्ताक्षर बारी होने से rethrowing अपवाद जाँच में संकलक आप

.stream().map(uncheckedFunc(this::throwingFunction)).forEach(...)

में

.stream().map(x -> { 
    try { 
    return this.throwingFunction(x) 
    } catch(Exception e) { 
    throw new RuntimeException(e); 
    } 
}).forEach(...) 

बदल सकते हैं बिना एक सामान्य रनटाइम अपवाद में अपवाद लपेटना।

+1

लेकिन यह सवाल यहां नहीं है। यह एक टिप्पणी है। – Tunaki

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