আমি জাভা 8 টি স্ট্রিমের মধ্যে থেকে চেক করা ব্যতিক্রমগুলি কীভাবে ফেলে দিতে পারি?


287

আমি জাভা 8 স্ট্রিম / ল্যাম্বডাসের ভিতরে থেকে চেক করা ব্যতিক্রমগুলি কীভাবে ফেলে দিতে পারি?

অন্য কথায়, আমি এই সংকলনের মতো কোড তৈরি করতে চাই:

public List<Class> getClasses() throws ClassNotFoundException {     

    List<Class> classes = 
        Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
              .map(className -> Class.forName(className))
              .collect(Collectors.toList());                  
    return classes;
    }

এই কোডটি সংকলন করে না, যেহেতু Class.forName()উপরে পদ্ধতিটি নিক্ষেপ করা হয় ClassNotFoundException, যা পরীক্ষা করা হয়।

দয়া করে মনে রাখবেন আমি চেক করা ব্যতিক্রমটিকে রানটাইম ব্যতিক্রমের মধ্যে মোড়াতে চাই না এবং তার পরিবর্তে মোড়ানো চেক করা ব্যতিক্রমটি ফেলে দিতে চাই না। আমি চেক করা ব্যতিক্রম নিজেই ছুঁড়ে ফেলতে চাই এবং স্ট্রিমে কুরুচিপূর্ণ try/ যোগ না করেই ফেলতে চাইcatches


42
সংক্ষিপ্ত উত্তরটি হল, ব্যাতিক্রম সম্পর্কিত নিয়ম ভঙ্গ না করে আপনি পারবেন না। আপনি অবশ্যই প্রতারণা করতে পারেন, এবং অন্যরা কীভাবে আনন্দের সাথে আপনাকে প্রদর্শন করবে, তবে সচেতন হন যে এটি প্রতারণা করছে এবং এই জাতীয় প্রতারণা প্রায়ই আপনাকে কামড়ানোর জন্য ফিরে আসে। আপনি ব্যতিক্রম ধরা এবং এটি মোকাবেলা করা উচিত। আপনি যদি এটি মোড়ানো করতে চান এবং তারপরে চেক করা ব্যতিক্রমটি পুনর্নির্মাণ করতে চান তবে আপনি নিরাপদে এটি করতে পারেন।
ব্রায়ান গয়েটজ

35
@ ব্রায়ান, আমাকে কীভাবে প্রতারণা করতে হবে তা বলার জন্য আমার অন্যের দরকার নেই, আমি কীভাবে নিজেকে প্রতারণা করতে জানি এবং নীচের উত্তরে আমার প্রতারণার পদ্ধতি পোস্ট করেছে, যা আপনি হ্রাস করেছেন। আমি জানি আপনি জাভা আলোচনায় জড়িত রয়েছেন যে সিদ্ধান্ত নিয়েছিলেন যে স্ট্রিমগুলিতে চেক করা ব্যতিক্রমগুলি মোকাবিলা করার কোনও ভাল উপায় ছিল না, সুতরাং আমি আশ্চর্য হয়েছি যে আপনি আমার এই প্রশ্নটি লক্ষ্য করেছেন, তবে আমি আপনার উত্তর শুনে হতাশ হয়েছি যা কেবল বলে "এটি এই ভাল নয় ", এর কোনও কারণ নেই এবং তারপরে আবার কেউ চেষ্টা করে / ক্যাচ করে।
মার্জ

22
@ ব্রায়ান, স্পষ্টতই, বাস্তবে যখন লোকেরা স্টেটমেন্টের জন্য উত্তরাধিকারকে রিফ্যাক্টর করার চেষ্টা করে, তাদের অর্ধেকটি স্রোতে রূপান্তরিত হয় তবে বাকি অর্ধেক তারা রিফ্যাক্টরিং ছেড়ে দেয়, কারণ কেউ এই চেষ্টা / ক্যাচ যুক্ত করতে চায় না। তারা কোডটি পড়ার পক্ষে অনেক বেশি রেন্ডার করে, অবশ্যই বিবৃতি-সংক্রান্ত মূল বক্তব্যের চেয়ে বেশি। উপরের আমার কোড উদাহরণে, যতক্ষণ না আপনি "ক্লাসনটফাউন্ডএক্সসেপশন" বজায় রাখেন, আমি বাইরের কোডের সাথে কোনও পার্থক্য দেখি না। আপনি দয়া করে আমাকে এমন কিছু বাস্তব জীবনের উদাহরণ দিতে পারেন যেখানে ব্যতিক্রম সম্পর্কিত নিয়মগুলি ভেঙে যায়?
মার্চজি

10
রেকর্ডার পদ্ধতি রচনাগুলি যা চেক না করা ব্যতিক্রমগুলিকে মোড়ক করে "কোড বিশৃঙ্খলা" আপত্তি সম্বোধন করে এবং টাইপ সিস্টেমটি ভঙ্গ করে না। এখানে যে উত্তরটি একটি চেক করা ব্যতিক্রমের "স্নিগ্ধ নিক্ষেপ" অবলম্বন করে তা টাইপ সিস্টেমটি ভেঙে দেয়, কারণ কলিং কোডটি চেক করা ব্যতিক্রম আশা করে না (ধরতে দেওয়া হবে না)।
ব্রায়ান গয়েটজ 21

14
এটি কোড বিশৃঙ্খলা আপত্তিটিকে সম্বোধন করে না কারণ তারপরে মূল ব্যতিক্রম আনারপ্যাক্ট এবং পুনর্বিবেচনার জন্য আপনার প্রবাহের চারপাশে দ্বিতীয় চেষ্টা / ধরা দরকার। বিপরীতে, আপনি যদি চেক করা ব্যতিক্রমটি ছুঁড়ে ফেলে থাকেন তবে আপনার কেবল throws ClassNotFoundExceptionস্ট্রিমটি থাকা পদ্ধতি ঘোষণার মধ্যে থাকা দরকার, যাতে কলিং কোডটি আশা করে এবং চেক করা ব্যতিক্রমটি ধরতে দেয়।
মার্চজি

উত্তর:


250

আপনার প্রশ্নের সহজ উত্তর: আপনি পারবেন না, অন্তত সরাসরি না। এবং এটি আপনার দোষ নয়। ওরাকল এটিকে গণ্ডগোল করেছে। তারা চেক করা ব্যতিক্রমগুলির ধারণাকে আঁকড়ে ধরেছিল, তবে কার্যকরী ইন্টারফেস, স্ট্রিমস, ল্যাম্বদা ইত্যাদি ডিজাইনের সময় অবিচ্ছিন্নভাবে চেক করা ব্যতিক্রমগুলির যত্ন নিতে ভুলে গিয়েছিল That's রবার্ট সি মার্টিনের মতো বিশেষজ্ঞের মিলকে যারা পরীক্ষিত ব্যতিক্রমগুলি ব্যর্থ পরীক্ষা বলে অভিহিত করে।

আমার মতে, এই একটি বিশাল বাগ মধ্যে এপিআই এবং একটি ক্ষুদ্র বাগ ভাষা স্পেসিফিকেশন

এপিআই-এ বাগটি হ'ল এটি চেক করা ব্যতিক্রমগুলি ফরোয়ার্ড করার জন্য কোনও সুবিধা সরবরাহ করে না যেখানে এটি কার্যকরী প্রোগ্রামিংয়ের জন্য প্রকৃতপক্ষে এক ভয়ঙ্কর ধারণা তৈরি করে। আমি নীচে যেমন প্রদর্শিত করব, এই জাতীয় সুবিধা সহজেই সম্ভব হত।

ভাষার স্পেসিফিকেশনের বাগটি হ'ল এটি কোনও ধরণের পরামিতি কেবলমাত্র এক প্রকারের পরিবর্তে প্রকারের তালিকা নির্ধারণ করতে দেয় না যতক্ষণ না টাইপ পরামিতি কেবল এমন পরিস্থিতিতে ব্যবহার করা হয় যেখানে প্রকারের তালিকা অনুমোদিত ( throwsধারা)।

জাভা প্রোগ্রামার হিসাবে আমাদের প্রত্যাশাটি নিম্নলিখিত কোডটি সংকলন করা উচিত:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class CheckedStream {
    // List variant to demonstrate what we actually had before refactoring.
    public List<Class> getClasses(final List<String> names) throws ClassNotFoundException {
        final List<Class> classes = new ArrayList<>();
        for (final String name : names)
            classes.add(Class.forName(name));
        return classes;
    }

    // The Stream function which we want to compile.
    public Stream<Class> getClasses(final Stream<String> names) throws ClassNotFoundException {
        return names.map(Class::forName);
    }
}

তবে এটি দেয়:

cher@armor1:~/playground/Java/checkedStream$ javac CheckedStream.java 
CheckedStream.java:13: error: incompatible thrown types ClassNotFoundException in method reference
        return names.map(Class::forName);
                         ^
1 error

পথ যা কার্মিক ইন্টারফেসগুলি সংজ্ঞায়িত করা হয় বর্তমানে ব্যতিক্রম ফরওয়ার্ডিং থেকে কম্পাইলার বাধা দেয় - কোন ঘোষণা যা বলতে হবে Stream.map()যে যদি Function.apply() throws E, Stream.map() throws Eহিসাবে ভাল।

যা অনুপস্থিত তা হ'ল চেক করা ব্যতিক্রমগুলির মধ্য দিয়ে যাওয়ার জন্য এক ধরণের পরামিতির ঘোষণা। নিম্নলিখিত কোডটি দেখায় যে কীভাবে এই জাতীয় পাস-থ্রো টাইপ প্যারামিটারটি বর্তমান সিনট্যাক্সের সাহায্যে ঘোষিত হতে পারে। চিহ্নিত লাইনটিতে বিশেষ কেস বাদে, যা নীচে আলোচিত একটি সীমা, এই কোডটি সংকলন করে এবং প্রত্যাশার সাথে আচরণ করে।

import java.io.IOException;
interface Function<T, R, E extends Throwable> {
    // Declare you throw E, whatever that is.
    R apply(T t) throws E;
}   

interface Stream<T> {
    // Pass through E, whatever mapper defined for E.
    <R, E extends Throwable> Stream<R> map(Function<? super T, ? extends R, E> mapper) throws E;
}   

class Main {
    public static void main(final String... args) throws ClassNotFoundException {
        final Stream<String> s = null;

        // Works: E is ClassNotFoundException.
        s.map(Class::forName);

        // Works: E is RuntimeException (probably).
        s.map(Main::convertClass);

        // Works: E is ClassNotFoundException.
        s.map(Main::throwSome);

        // Doesn't work: E is Exception.
        s.map(Main::throwSomeMore);  // error: unreported exception Exception; must be caught or declared to be thrown
    }   

    public static Class convertClass(final String s) {
        return Main.class;
    }   

    static class FooException extends ClassNotFoundException {}

    static class BarException extends ClassNotFoundException {}

    public static Class throwSome(final String s) throws FooException, BarException {
        throw new FooException();
    }   

    public static Class throwSomeMore(final String s) throws ClassNotFoundException, IOException  {
        throw new FooException();
    }   
}   

ক্ষেত্রে throwSomeMoreআমরা IOExceptionমিস হয়ে যাওয়া দেখতে চাই , তবে এটি আসলে মিস হয় না Exception

এটি নিখুঁত নয় কারণ টাইপ অনুমানটি একক প্রকারের সন্ধান করছে বলে মনে হয়, এমনকি ব্যতিক্রমগুলির ক্ষেত্রেও। কারণ টাইপ অনুমান একটি একক টাইপ প্রয়োজন, Eএকটি সাধারণ থেকে সমাধান করতে প্রয়োজন superএর ClassNotFoundExceptionএবং IOException, যা Exception

টাইপ অনুমানের সংজ্ঞাটির জন্য একটি ঝাঁকুনি প্রয়োজন যাতে সংকলক একাধিক প্রকারের সন্ধান করতে পারে যেখানে টাইপ পরামিতি ব্যবহার করা হয় যেখানে টাইপের একটি তালিকা অনুমোদিত ( throwsধারা) রয়েছে। তারপরে সংকলক দ্বারা বর্ণিত ব্যতিক্রম প্রকারটি throwsরেফারেন্স পদ্ধতিটির চেক করা ব্যতিক্রমগুলির মূল ঘোষণার মতো নির্দিষ্ট হবে , একক ক্যাচ-অল সুপার টাইপ নয়।

খারাপ খবরটি হ'ল এর অর্থ হ'ল ওরাকল এটিকে গোলযোগ করেছেন। অবশ্যই তারা ব্যবহারকারী-ভূমি কোডটি ভাঙবে না, তবে বিদ্যমান কার্যকরী ইন্টারফেসগুলিতে ব্যতিক্রম ধরণের পরামিতিগুলি প্রবর্তন করা সমস্ত ইউজার-ল্যান্ড কোডের সংকলনকে স্পষ্টভাবে ব্যবহার করবে। এটি ঠিক করতে তাদের কিছু নতুন সিনট্যাক্স চিনির উদ্ভাবন করতে হবে।

সবচেয়ে খারাপ খবরটি হ'ল এই বিষয়টি ইতিমধ্যে ২০১০ সালে ব্রায়ান গোয়েজ আলোচিত ছিলেন https://blogs.oracle.com/briangoetz/entry/exception_transpender_in_java (নতুন লিঙ্ক: http://mail.openjdk.java.net/pipermail/lambda -দেব / ২০১০-জুন / 001484 এইচটিএমএল ) তবে আমি অবহিত করেছি যে এই তদন্তটি শেষ পর্যন্ত বেরিয়ে আসে নি, এবং অরাকল-এ এখনকার কোনও কাজ নেই যা আমি জানি যে চেক করা ব্যতিক্রম এবং ল্যাম্বডাসের মধ্যে মিথস্ক্রিয়া প্রশমিত করতে হবে।


16
মজাদার. আমি বিশ্বাস করি যে কিছু লোক সহজ সমান্তরাল কোডের অনুমতি দেওয়ার জন্য স্ট্রিমের প্রশংসা করেন, আবার কেউ কেউ ক্লিনার কোডের অনুমতি দেওয়ার জন্য। ব্রায়ান গোয়েট স্পষ্টতই সমান্তরালতা সম্পর্কে বেশি যত্নশীল ছিলেন (যেহেতু তিনি অনুশীলনে জাভা কনকুরન્સી রচনা করেছিলেন), যখন রবার্ট মার্টিন ক্লিন কোড সম্পর্কে বেশি যত্নশীল (যেহেতু তিনি ক্লিন কোড বইটি লিখেছিলেন)। সমান্তরালতার জন্য মূল্য দিতে বয়লারপ্লেট ট্রাই / ক্যাচগুলি একটি সামান্য দাম, সুতরাং এতে অবাক হওয়ার কিছু নেই যে স্রোতের অভ্যন্তরে পরীক্ষিত ব্যতিক্রমগুলি ব্যবহার করে ব্রায়ান গোয়েটজ হতবাক হন না। এছাড়াও রবার্ট মার্টিন যেহেতু বিশৃঙ্খলা যুক্ত করার সাথে সাথে চেক ব্যতিক্রমগুলি ঘৃণা করে তাতে অবাক হওয়ার কিছু নেই।
মার্জ

5
আমি পূর্বাভাস দিচ্ছি যে কয়েক বছরের মধ্যে, স্ট্রিমের অভ্যন্তরে পরীক্ষিত ব্যতিক্রমগুলি মোকাবেলা করতে অসুবিধা এই দুটি ফলাফলের মধ্যে একটির দিকে পরিচালিত করবে: লোকেরা কেবল চেক করা ব্যতিক্রমগুলি ব্যবহার করা বন্ধ করবে, বা প্রত্যেকেই আমি পোস্ট করা পোস্টের মতো কিছুটা হ্যাক ব্যবহার শুরু করবে আমার UtilException উত্তর। আমি বাজাতে চাই জাভা -8 স্ট্রিমগুলি চেক করা ব্যতিক্রমগুলির কফিনের শেষ পেরেক, চেক করা ব্যতিক্রমগুলি জেডিকে-র অংশ বলে মনে হয় না। যদিও আমি ব্যবসায়ের কোডে (কিছু নির্দিষ্ট ব্যবহারের ক্ষেত্রে) চেক করা ব্যতিক্রমগুলি পছন্দ করি এবং ব্যবহার করি, তবে আমি রানডটাইমের বর্ধিত সমস্ত সাধারণ জেডিকে ব্যতিক্রম পছন্দ করতাম।
মার্চজি

9
@ উনিহেডো সমস্যাটি রয়ে গেছে যে কার্যকরী ইন্টারফেসগুলি ব্যতিক্রমগুলি এগিয়ে দেয় না। ল্যাম্বদার অভ্যন্তরে আমার try-catchব্লকটি লাগবে , এবং এটি কেবল কোনও ধারণা রাখে না। যত তাড়াতাড়ি ল্যাম্বডায় কোনও উপায়ে ব্যবহার করা হয়, উদাহরণস্বরূপ , সমস্যা আছে। মূলত, যে পদ্ধতিগুলি যাচাই করা ব্যতিক্রমগুলি ফেলে দেয় সেগুলি (দুর্বল!) ডিজাইন দ্বারা সরাসরি কার্যকরী ইন্টারফেস হিসাবে ফাংশনাল প্রোগ্রামিংয়ে অংশ নেওয়া থেকে বাদ দেওয়া হয়েছে। Class.forNamenames.forEach(Class::forName)
ক্রিশ্চিয়ান হুজার

26
@ ক্রিশ্চিয়ান হুজার "ব্যতিক্রম স্বচ্ছতা" অন্বেষণ কেবল এটাই ছিল - একটি এক্সপ্লোরেশন (যা বিজিজিএ প্রস্তাবনায় উত্পন্ন হয়েছিল)। গভীর বিশ্লেষণের পরে, আমরা এটি মান এবং জটিলতার একটি ভারসাম্য ভারসাম্য সরবরাহ করতে পেরেছি এবং এর কিছু গুরুতর সমস্যা রয়েছে (অন্যদের মধ্যে অনির্ধারিত অনুক্রমের সমস্যা দেখা দিয়েছে, এবং "ক্যাচ এক্স" অনুভূত ছিল)) ভাষার ধারণাটি অত্যন্ত সাধারণ that প্রতিশ্রুতিবদ্ধ - এমনকি "সুস্পষ্ট" বলে মনে হচ্ছে - তবে গভীর অনুসন্ধানের পরেও ত্রুটিযুক্ত হতে দেখা গেল। এটি এই ক্ষেত্রে অন্যতম ছিল।
ব্রায়ান গয়েটজ

13
@ ব্রায়ানগোয়েটস আপনি উল্লেখ করেছেন যে অনস্বীকার্য অনুমান সমস্যা সম্পর্কে কিছু জনসাধারণের তথ্য পাওয়া যায়? আমি কৌতূহলী এবং এটি বুঝতে চাই।
খ্রিস্টান হুজার

169

এই LambdaExceptionUtilসহায়ক শ্রেণিটি আপনাকে জাভা স্ট্রিমগুলিতে কোনও পরীক্ষিত ব্যতিক্রমগুলি এর মতো ব্যবহার করতে দেয়:

Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
      .map(rethrowFunction(Class::forName))
      .collect(Collectors.toList());

নোট Class::forNameনিক্ষেপ ClassNotFoundException, যা চেক করা হয় । স্ট্রিমটি নিজেও ছুঁড়ে দেয় ClassNotFoundExceptionএবং কিছু মোড়ানো চেক করা ব্যতিক্রম নয় NOT

public final class LambdaExceptionUtil {

@FunctionalInterface
public interface Consumer_WithExceptions<T, E extends Exception> {
    void accept(T t) throws E;
    }

@FunctionalInterface
public interface BiConsumer_WithExceptions<T, U, E extends Exception> {
    void accept(T t, U u) throws E;
    }

@FunctionalInterface
public interface Function_WithExceptions<T, R, E extends Exception> {
    R apply(T t) throws E;
    }

@FunctionalInterface
public interface Supplier_WithExceptions<T, E extends Exception> {
    T get() throws E;
    }

@FunctionalInterface
public interface Runnable_WithExceptions<E extends Exception> {
    void run() throws E;
    }

/** .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name)))); or .forEach(rethrowConsumer(ClassNameUtil::println)); */
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) throws E {
    return t -> {
        try { consumer.accept(t); }
        catch (Exception exception) { throwAsUnchecked(exception); }
        };
    }

public static <T, U, E extends Exception> BiConsumer<T, U> rethrowBiConsumer(BiConsumer_WithExceptions<T, U, E> biConsumer) throws E {
    return (t, u) -> {
        try { biConsumer.accept(t, u); }
        catch (Exception exception) { throwAsUnchecked(exception); }
        };
    }

/** .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName)) */
public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E {
    return t -> {
        try { return function.apply(t); }
        catch (Exception exception) { throwAsUnchecked(exception); return null; }
        };
    }

/** rethrowSupplier(() -> new StringJoiner(new String(new byte[]{77, 97, 114, 107}, "UTF-8"))), */
public static <T, E extends Exception> Supplier<T> rethrowSupplier(Supplier_WithExceptions<T, E> function) throws E {
    return () -> {
        try { return function.get(); }
        catch (Exception exception) { throwAsUnchecked(exception); return null; }
        };
    }

/** uncheck(() -> Class.forName("xxx")); */
public static void uncheck(Runnable_WithExceptions t)
    {
    try { t.run(); }
    catch (Exception exception) { throwAsUnchecked(exception); }
    }

/** uncheck(() -> Class.forName("xxx")); */
public static <R, E extends Exception> R uncheck(Supplier_WithExceptions<R, E> supplier)
    {
    try { return supplier.get(); }
    catch (Exception exception) { throwAsUnchecked(exception); return null; }
    }

/** uncheck(Class::forName, "xxx"); */
public static <T, R, E extends Exception> R uncheck(Function_WithExceptions<T, R, E> function, T t) {
    try { return function.apply(t); }
    catch (Exception exception) { throwAsUnchecked(exception); return null; }
    }

@SuppressWarnings ("unchecked")
private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E { throw (E)exception; }

}

এটি কীভাবে ব্যবহার করবেন সে সম্পর্কে আরও অনেক উদাহরণ (স্থিতিশীলভাবে আমদানির পরে LambdaExceptionUtil):

@Test
public void test_Consumer_with_checked_exceptions() throws IllegalAccessException {
    Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
          .forEach(rethrowConsumer(className -> System.out.println(Class.forName(className))));

    Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
          .forEach(rethrowConsumer(System.out::println));
    }

@Test
public void test_Function_with_checked_exceptions() throws ClassNotFoundException {
    List<Class> classes1
          = Stream.of("Object", "Integer", "String")
                  .map(rethrowFunction(className -> Class.forName("java.lang." + className)))
                  .collect(Collectors.toList());

    List<Class> classes2
          = Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
                  .map(rethrowFunction(Class::forName))
                  .collect(Collectors.toList());
    }

@Test
public void test_Supplier_with_checked_exceptions() throws ClassNotFoundException {
    Collector.of(
          rethrowSupplier(() -> new StringJoiner(new String(new byte[]{77, 97, 114, 107}, "UTF-8"))),
          StringJoiner::add, StringJoiner::merge, StringJoiner::toString);
    }

@Test    
public void test_uncheck_exception_thrown_by_method() {
    Class clazz1 = uncheck(() -> Class.forName("java.lang.String"));

    Class clazz2 = uncheck(Class::forName, "java.lang.String");
    }

@Test (expected = ClassNotFoundException.class)
public void test_if_correct_exception_is_still_thrown_by_method() {
    Class clazz3 = uncheck(Class::forName, "INVALID");
    }    

উল্লেখ্য 1:rethrow পদ্ধতি LambdaExceptionUtilউপরে বর্গ ভয় ছাড়াই ব্যবহার করা যেতে পারে, এবং যে কোনো পরিস্থিতি ব্যবহার করার জন্য ঠিক আছে । ব্যবহারকারী @ পাওলোককে একটি বড় ধন্যবাদ যিনি সর্বশেষ সমস্যার সমাধান করতে সহায়তা করেছেন: এখন সংকলকটি আপনাকে থ্রো ক্লজ এবং সমস্ত কিছু যুক্ত করতে বলবে যেন আপনি জাভা 8 স্ট্রিমগুলিতে চেক করা ব্যতিক্রমগুলি স্থানীয়ভাবে ছুঁড়ে ফেলতে পারেন।


উল্লেখ্য 2:uncheck পদ্ধতি LambdaExceptionUtilউপরে বর্গ বোনাস পদ্ধতি আছে, এবং নিরাপদে তাদের ক্লাস থেকে সরিয়ে ফেলা হতে পারে আপনি তাদের ব্যবহার করতে না চান। আপনি যদি এগুলি ব্যবহার করেন, তবে নীচের ব্যবহারের ক্ষেত্রে, সুবিধা / অসুবিধাগুলি এবং সীমাবদ্ধতাগুলি বোঝার আগে যত্ন সহকারে এটি করুন:

You আপনি uncheckযদি এমন কোনও পদ্ধতি কল করছেন যা আপনি আক্ষরিক অর্থে এটির ব্যতিক্রমটিকে ছুঁড়ে ফেলতে পারবেন না আপনি সেই পদ্ধতিগুলি ব্যবহার করতে পারেন । উদাহরণস্বরূপ: নতুন স্ট্রিং (বাইটআরআর, "ইউটিএফ -8") অসমর্থিত এনকোডিংএক্সেপশন ছুড়েছে, তবে ইউটিএফ -8 সর্বদা উপস্থিত থাকার জন্য জাভা স্পেস দ্বারা গ্যারান্টিযুক্ত। এখানে, থ্রো ডিক্লেয়ারেশন একটি উপদ্রব এবং এটি ন্যূনতম বয়লারপ্লেট দিয়ে চুপ করার কোনও সমাধান স্বাগত:String text = uncheck(() -> new String(byteArr, "UTF-8"));

You আপনি uncheckযদি এমন কঠোর ইন্টারফেস প্রয়োগ করছেন যেখানে আপনার কাছে থ্রো ডিক্লেয়ারেশন যুক্ত করার বিকল্প নেই তবে আপনি সেই পদ্ধতিগুলি ব্যবহার করতে পারেন এবং তারপরেও ব্যতিক্রম ছোঁড়া পুরোপুরি উপযুক্ত। এটি ছুঁড়ে ফেলার বিশেষত্ব অর্জনের জন্য কেবল ব্যতিক্রমকে মুড়িয়ে ফেলার ফলস্বরূপ ব্যতিক্রমগুলি স্ট্যাকট্রেসে ফল দেয় যা আসলে কী ভুল হয়েছে সম্পর্কে কোনও তথ্য অবদান রাখে না। একটি ভাল উদাহরণ রান্নেবল.আরুন (), যা কোনও পরীক্ষিত ব্যতিক্রম ছুঁড়ে না ফেলে।

uncheckCase যে কোনও ক্ষেত্রে, যদি আপনি পদ্ধতিগুলি ব্যবহার করার সিদ্ধান্ত নেন , ছোঁড়া ছাড়াই চেক করা ব্যতিক্রম ছোঁড়ার এই 2 পরিণতি সম্পর্কে অবগত হন: 1) কলিং-কোড নামটি ধরে রাখতে সক্ষম হবে না (যদি আপনি চেষ্টা করেন তবে সংকলক বলবেন: ব্যতিক্রমটি কখনও চেষ্টা করার অনুরোধের শৃঙ্খলে ফেলে দেওয়া হয় না)। এটি বুদবুদ হয়ে উঠবে এবং সম্ভবত কিছু "ক্যাচ এক্সেপশন" বা "ক্যাচ থ্রোয়েবল" দ্বারা মূল প্রোগ্রামটির লুপে ধরা পড়বে, যা আপনি যাইহোক চান তা হতে পারে। 2) এটি সর্বনিম্ন আশ্চর্যের নীতি লঙ্ঘন করে: RuntimeExceptionসমস্ত সম্ভাব্য ব্যতিক্রম ধরা গ্যারান্টি দিতে সক্ষম হবার পক্ষে এটি আর যথেষ্ট হবে না । এই কারণে, আমি বিশ্বাস করি এটি ফ্রেমওয়ার্ক কোডে করা উচিত নয়, তবে কেবলমাত্র এমন ব্যবসায়িক কোডে যা আপনি সম্পূর্ণরূপে নিয়ন্ত্রণ করেন।


4
আমি অনুভব করি যে এই উত্তরটি অন্যায়ভাবে হ্রাস পেয়েছে। কোড কাজ করে। চেক করা ব্যতিক্রমগুলি নিক্ষেপ বা ডিল করার কথা রয়েছে। আপনি যদি এগুলি ছুঁড়ে ফেলতে চান তবে কেবল স্ট্রিম রয়েছে এমন পদ্ধতিতে "থ্রো ক্লজ" রাখুন। তবে আপনি যদি কেবল মোড়ানো এবং পুনর্বিবেচনা করে তাদের সাথে ডিল করতে চান তবে আমার ধারণা, আমি ব্যতিক্রমগুলি "আনকােক" করতে উপরের কোডটি ব্যবহার করতে পছন্দ করি এবং সেগুলি নিজেই বুদবুদ করতে দিন। আমি যে পার্থক্য সম্পর্কে সচেতন তা হ'ল বুদ্বুদ্ব ব্যতিক্রম রানটাইম এক্সেকশনকে বাড়িয়ে দেবে না। আমি জানি যে শুদ্ধবাদীরা এটি পছন্দ করবে না, তবে এই "অনিবার্যভাবে কাউকে কামড়ানোর জন্য ফিরে আসবে"? সম্ভবত মনে হয় না।
মার্জ

4
@ ক্রিশ্চিয়ান হুজার, ডাউনভোটারের সাথে সত্য কথা বলতে, আমি "সুবিধাগুলি, অসুবিধাগুলি এবং সীমাবদ্ধতা" ব্যাখ্যা যুক্ত করার আগে তিনি পূর্ববর্তী সংস্করণটিকে হ্রাস করেছিলেন। সুতরাং সম্ভবত এটি সময় প্রাপ্য ছিল। অন্তত পরিণতিগুলি বোঝার এবং ব্যাখ্যা করার চেষ্টা না করে আপনি কাউকে কীভাবে নিয়ম ভাঙতে শেখাতে পারবেন না। আমি এই প্রশ্নটি পোস্ট করার মূল কারণটি ছিল আমার উত্তরগুলির অসুবিধার জন্য প্রতিক্রিয়া পাওয়া। আমি এই প্রতিক্রিয়াটি এখানেই পেয়েছি না তবে প্রোগ্রামার্স.স্ট্যাকেক্সেঞ্জিজের অন্য একটি প্রশ্ন থেকে পেয়েছি। তারপরে আমি এখানে ফিরে এসে আমার উত্তর আপডেট করেছি।
মার্চজি

16
আমি downvoted শুধুমাত্র কারণ এই উত্সাহ দেয় অচল কোড । এটি একটি কুরুচিপূর্ণ হ্যাক, যদিও একটি চতুর, এবং আমি এই উত্তরটি কখনই দরকারী খুঁজে পাব না। এটি আবার ভাষাটির আর একটি "ব্যবহার করবেন না"।
ইউনিহীড্রন

12
@ উনিহেড্রো কিন্তু কেন তা অভাবনীয় হয়ে উঠল? আমি দেখতে পাচ্ছি না কেন। কোন উদাহরণ?
মার্কস

2
আমার মতে @SuppressWarnings ("unchecked")সংকলক কৌতুক সম্পূর্ণ গ্রহণযোগ্য নয়।
থোরবজর্ন রাভন অ্যান্ডারসন

26

আপনি নিরাপদে এটি করতে পারবেন না। আপনি প্রতারণা করতে পারেন, তবে তারপরে আপনার প্রোগ্রামটি নষ্ট হয়ে গেছে এবং এটি অনিবার্যভাবে কাউকে কামড়ানোর জন্য ফিরে আসবে (এটি আপনার হওয়া উচিত তবে প্রায়ই আমাদের প্রতারণা অন্য কারও উপর উড়িয়ে দেয়))

এটি করার জন্য এখানে কিছুটা নিরাপদ উপায় (তবে আমি এখনও এটির প্রস্তাব দিই না))

class WrappedException extends RuntimeException {
    Throwable cause;

    WrappedException(Throwable cause) { this.cause = cause; }
}

static WrappedException throwWrapped(Throwable t) {
    throw new WrappedException(t);
}

try 
    source.stream()
          .filter(e -> { ... try { ... } catch (IOException e) { throwWrapped(e); } ... })
          ...
}
catch (WrappedException w) {
    throw (IOException) w.cause;
}

এখানে, আপনি যা করছেন তা ল্যাম্বডায় ব্যতিক্রম ধরা, প্রবাহের পাইপলাইনের বাইরে একটি সংকেত নিক্ষেপ করে যা ইঙ্গিত দেয় যে গণনা ব্যতিক্রমীভাবে ব্যর্থ হয়েছিল, সংকেতটি ধরা, এবং সেই সংকেতটিকে অন্তর্নিহিত ব্যতিক্রম ছুঁড়ে ফেলার জন্য অভিনয় করা। মূলটি হ'ল আপনি সর্বদা সিন্থেটিক ব্যতিক্রম ধরছেন, ব্যতিক্রমটি ছড়িয়ে দেওয়া হয়েছে তা ঘোষণা না করেই কোনও পরীক্ষিত ব্যতিক্রম ফাঁস হওয়ার অনুমতি দেওয়ার চেয়ে।


18
শুধু একটা প্রশ্ন; নকশার সিদ্ধান্ত কী ছিল যার ফলে লাম্বদা তাদের প্রসঙ্গে চেক ব্যতিক্রমগুলি প্রচার করতে সক্ষম হয়নি? নোট করুন যে আমি বুঝতে পারি যে ফাংশনাল ইন্টারফেস যেমন Functionইত্যাদিতে throwsকিছুই থাকে না ; আমি উৎসুক.
fge

4
যে throw w.cause;কম্পাইলার অভিযোগ যে পদ্ধতি ছোঁড়ার কিংবা ধরা না করে নি Throwable? সুতরাং, সম্ভবত সেখানে একটি কাস্ট IOExceptionপ্রয়োজন হবে। তদ্ব্যতীত, ল্যাম্বদা যদি একাধিক প্রকারের পরীক্ষিত ব্যতিক্রম ছুঁড়ে দেয়, তবে instanceofযাচাই করা ব্যতিক্রমটি যাচাই করা হয়েছে তা যাচাই করার জন্য ক্যাচের শরীরটি কয়েকটি চেক (বা অনুরূপ উদ্দেশ্যযুক্ত অন্য কোনও কিছু) দিয়ে কিছুটা কুশ্রী হয়ে উঠবে ।
ভিক্টর স্টাফুসা

10
@ শাটেন এর একটি কারণ হ'ল আপনি ডব্লুইইকে ধরা ভুলে যেতে পারেন এবং তারপরে একটি অদ্ভুত ব্যতিক্রম (যার সাথে কীভাবে ডিল করতে হয় তা কেউ জানেন না) ফুটে উঠবে। (আপনি হয়ত বলতে পারেন "তবে আপনি ব্যতিক্রমটি ধরা পড়েছেন তাই এটি নিরাপদ" "এই খেলনা উদাহরণে। তবে প্রতিবার আমি দেখেছি যে কোনও কোডবেস এই পদ্ধতির অবলম্বন করেছে, শেষ পর্যন্ত কেউ ভুলে যায় ex ব্যতিক্রম উপেক্ষা করার প্রলোভনের কোনও সীমা নেই। এটিকে নিরাপদে ব্যবহার করা নির্দিষ্ট (ব্যবহার সাইট, ব্যতিক্রম) সংমিশ্রনের সাথে সুনির্দিষ্ট। এটি একাধিক ব্যতিক্রম বা অযৌক্তিক ব্যবহারগুলিতে ভাল স্কেল করে না।
ব্রায়ান গোয়েট

2
@ যুড্যাটিকাস আমি আপনার সাথে একমত বলেছিলেন, আপনি কি আরও বেশি করে মোড়ানো পছন্দ করেন (উপরে দেখানো হিসাবে, "ভুলে যাওয়ার" ঝুঁকি বাড়ানো) বা কেবল 4 চতুর ইন্টারফেস তৈরি করুন এবং ল্যাম্বডাস ডাব্লু / ও র্যাপিং ব্যবহার করুন, যেমন স্ট্যাকওভারফ্লো . com /a/30974991/ 2365724 তে দেখানো হয়েছে ? ধন্যবাদ
পাওলোক

10
সত্যই, এই সমাধানটি কেবল সম্পূর্ণ অকার্যকর। আমি ভেবেছিলাম স্ট্রিমগুলির বিন্দুটি ছিল বয়লারপ্লেট হ্রাস করা, এটি বাড়ানো নয় not
wvdz

24

আপনি পারেন!

@ মার্কস এর প্রসারিত করা UtilExceptionএবং throw Eযেখানে প্রয়োজন সেখানে যুক্ত করা : এইভাবে সংকলকটি আপনাকে থ্রো ক্লজ এবং সমস্ত কিছু যুক্ত করতে বলবে যেন আপনি জাভা 8 এর স্ট্রিমগুলিতে চেক করা ব্যতিক্রমগুলি স্থানীয়ভাবে ছুঁড়ে ফেলতে পারেন ।

নির্দেশাবলী: কেবল LambdaExceptionUtilআপনার আইডিইতে অনুলিপি / আটকান এবং তারপরে নিচের মত দেখানো হিসাবে এটি ব্যবহার করুন LambdaExceptionUtilTest

public final class LambdaExceptionUtil {

    @FunctionalInterface
    public interface Consumer_WithExceptions<T, E extends Exception> {
        void accept(T t) throws E;
    }

    @FunctionalInterface
    public interface Function_WithExceptions<T, R, E extends Exception> {
        R apply(T t) throws E;
    }

    /**
     * .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name))));
     */
    public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) throws E {
        return t -> {
            try {
                consumer.accept(t);
            } catch (Exception exception) {
                throwActualException(exception);
            }
        };
    }

    /**
     * .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
     */
    public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E  {
        return t -> {
            try {
                return function.apply(t);
            } catch (Exception exception) {
                throwActualException(exception);
                return null;
            }
        };
    }

    @SuppressWarnings("unchecked")
    private static <E extends Exception> void throwActualException(Exception exception) throws E {
        throw (E) exception;
    }

}

ব্যবহার এবং আচরণ দেখানোর জন্য কিছু পরীক্ষা:

public class LambdaExceptionUtilTest {

    @Test(expected = MyTestException.class)
    public void testConsumer() throws MyTestException {
        Stream.of((String)null).forEach(rethrowConsumer(s -> checkValue(s)));
    }

    private void checkValue(String value) throws MyTestException {
        if(value==null) {
            throw new MyTestException();
        }
    }

    private class MyTestException extends Exception { }

    @Test
    public void testConsumerRaisingExceptionInTheMiddle() {
        MyLongAccumulator accumulator = new MyLongAccumulator();
        try {
            Stream.of(2L, 3L, 4L, null, 5L).forEach(rethrowConsumer(s -> accumulator.add(s)));
            fail();
        } catch (MyTestException e) {
            assertEquals(9L, accumulator.acc);
        }
    }

    private class MyLongAccumulator {
        private long acc = 0;
        public void add(Long value) throws MyTestException {
            if(value==null) {
                throw new MyTestException();
            }
            acc += value;
        }
    }

    @Test
    public void testFunction() throws MyTestException {
        List<Integer> sizes = Stream.of("ciao", "hello").<Integer>map(rethrowFunction(s -> transform(s))).collect(toList());
        assertEquals(2, sizes.size());
        assertEquals(4, sizes.get(0).intValue());
        assertEquals(5, sizes.get(1).intValue());
    }

    private Integer transform(String value) throws MyTestException {
        if(value==null) {
            throw new MyTestException();
        }
        return value.length();
    }

    @Test(expected = MyTestException.class)
    public void testFunctionRaisingException() throws MyTestException {
        Stream.of("ciao", null, "hello").<Integer>map(rethrowFunction(s -> transform(s))).collect(toList());
    }

}

1
দুঃখিত @ সেথেরন আপনি ঠিক বলেছেন, ঠিক <Integer>আগে যোগ করুন map। আসলে, জাভা সংকলক Integerরিটার্নের ধরণের অনুমান করতে পারে না । অন্য সব কিছু সঠিক হওয়া উচিত।
পাওলোক

1
এটি আমার পক্ষে কাজ করেছে। এটি ব্যতিক্রম পরিচালনা করা প্রয়োগ করে মার্কস এর উত্তরকে নিখুঁত করেছে made
স্কাইচান

1
উপরের ইস্যুটির সমাধান: এই কনজিউমার <থিংটাইপ> এক্সপ্রেশন = রিথ্রো কনসুমার ((থিংটাইপ জিনিস) -> জিনিস কোডলোন ()) এর মতো ভেরিয়েবল ঘোষণা করুন; তারপরে অভ্যন্তরীণ পূর্বাভাসের ভিতরে সেই অভিব্যক্তিটি ব্যবহার করুন।
স্কাইচান

1
@ স্কিচান: যেহেতু এই পরিবর্তিত নতুন সংস্করণে আপনি আর কোনও ব্যাতিক্রমকে দমন করছেন না, তাই অনুগ্রহ পদ্ধতিতে এটি সম্ভবত খানিকটা বেশি কঠিন। ব্রায়ান গয়েটসের নীচে কিছু মন্তব্যে "ব্যতিক্রমী স্বচ্ছতা" সম্পর্কে কথা বলেছেন যা "অনির্বচনীয় অনুমানের সমস্যাগুলির" দিকে পরিচালিত করে।
মার্জজি

3
খুব সুন্দর. একমাত্র দুর্ভাগ্যজনক বিষয়টি হ'ল একাধিক পরীক্ষিত ব্যতিক্রম ছুঁড়ে এমন পদ্ধতিতে পুরোপুরি কাজ করে না। এক্ষেত্রে সংকলক আপনাকে একটি সাধারণ সুপারটাইপ ধরায়, যেমন Exception
wvdz

12

কেবলমাত্র NoException (আমার প্রকল্প), JOOλ এর চেক না করা , নিক্ষেপকারী- ল্যাম্বডাস , নিক্ষেপযোগ্য ইন্টারফেস বা কোনও ব্যবহার করুন ভুল পাস ব্যবহার করুন

// NoException
stream.map(Exceptions.sneak().function(Class::forName));

// jOOλ
stream.map(Unchecked.function(Class::forName));

// throwing-lambdas
stream.map(Throwing.function(Class::forName).sneakyThrow());

// Throwable interfaces
stream.map(FunctionWithThrowable.aFunctionThatUnsafelyThrowsUnchecked(Class::forName));

// Faux Pas
stream.map(FauxPas.throwingFunction(Class::forName));

7

আমি একটি গ্রন্থাগার লিখেছিলাম যা আপনাকে চেক করা ব্যতিক্রম ছোঁড়ার অনুমতি দেওয়ার জন্য স্ট্রিম এপিআই বাড়িয়েছে। এটি ব্রায়ান গয়েটজের কৌশল ব্যবহার করে।

আপনার কোড হয়ে যাবে

public List<Class> getClasses() throws ClassNotFoundException {     
    Stream<String> classNames = 
        Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String");

    return ThrowingStream.of(classNames, ClassNotFoundException.class)
               .map(Class::forName)
               .collect(Collectors.toList());
}

7

এই উত্তরটি 17 টির মতো, তবে মোড়কের ব্যতিক্রম সংজ্ঞা এড়ানো:

List test = new ArrayList();
        try {
            test.forEach(obj -> {

                //let say some functionality throws an exception
                try {
                    throw new IOException("test");
                }
                catch(Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
        catch (RuntimeException re) {
            if(re.getCause() instanceof IOException) {
                //do your logic for catching checked
            }
            else 
                throw re; // it might be that there is real runtime exception
        }

1
এটি একটি সহজ এবং কার্যকর সমাধান।
লিন ডব্লু

2
এটি ওপ ঠিক যেমনটি চায় নি: ল্যাম্বডায় ব্লক চেষ্টা করে। ফিউটারমোর, এটি কেবল ততক্ষণ প্রত্যাশিত হিসাবে কাজ করবে যতক্ষণ না ট্রাই ব্লকের বাইরে অন্য কোনও কোড রানটাইম এক্সসেপশনে কোনও আইওএক্সেপশন মোড়ায় না। এটি এড়াতে, একটি কাস্টম র্যাপার-রানটাইম এক্সসেপশন (ব্যক্তিগত অভ্যন্তর শ্রেণীর হিসাবে সংজ্ঞায়িত) ব্যবহার করা যেতে পারে।
মাল্টে হার্টভিগ

5

তুমি পার না.

তবে আপনি আমার যে কোনও একটি প্রকল্পের দিকে নজর রাখতে চাইতে পারেন যা আপনাকে এই জাতীয় "নিক্ষেপকারী ল্যাম্বডাস" আরও সহজেই হেরফের করতে দেয়।

আপনার ক্ষেত্রে, আপনি এটি করতে সক্ষম হবেন:

import static com.github.fge.lambdas.functions.Functions.wrap;

final ThrowingFunction<String, Class<?>> f = wrap(Class::forName);

List<Class> classes =
    Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
          .map(f.orThrow(MyException.class))
          .collect(Collectors.toList());

এবং ধরা MyException

এটি একটি উদাহরণ। আর একটি উদাহরণ আপনি .orReturn()কিছু ডিফল্ট মান করতে পারে ।

মনে রাখবেন যে এটি এখনও চলছে একটি কাজ, আরও বেশি কাজ আসছে। আরও ভাল নাম, আরও বৈশিষ্ট্য ইত্যাদি


2
তবে, আপনি যদি মূল পরীক্ষিত ব্যতিক্রমটি ছুঁড়ে ফেলতে চান তবে আপনাকে প্রবাহের চারপাশে চেষ্টা / ধরতে হবে, এটি মোড়ক করতে হবে, যা এখনও ভয়াবহ! আপনি এই ধারণাটি পছন্দ করেন যে আপনি চাইলে একটি চেক করা ব্যতিক্রম ছুঁড়ে ফেলতে পারেন এবং আপনি যদি চান তবে আপনি স্ট্রিমের একটি ডিফল্ট মান ফিরিয়ে দিতে পারেন, তবে আমার মনে .orThrowChecked()হয় আপনার প্রকল্পে এমন কোনও পদ্ধতি যুক্ত করা উচিত যা পরীক্ষিত ব্যতিক্রম নিজেই ছুঁড়ে ফেলার অনুমতি দেয় । দয়া করে UtilExceptionএই পৃষ্ঠায় আমার উত্তরটি দেখুন এবং আপনার প্রকল্পে এই তৃতীয় সম্ভাবনা যুক্ত করার ধারণাটি আপনার পছন্দ হয়েছে কিনা তা দেখুন।
মার্চজি

"তবে, যদি আপনি মূল পরীক্ষিত ব্যতিক্রমটি ছুঁড়তে চান তবে আপনাকে প্রবাহের চারপাশে চেষ্টা / ধরতে হবে, এটি মোড়ক করতে হবে, যা এখনও ভয়াবহ!" <- হ্যাঁ তবে আপনার কোনও বিকল্প নেই। লাম্বদাস তাদের প্রসঙ্গে চেক ব্যতিক্রমগুলি প্রচার করতে পারে না , এটি একটি নকশা "সিদ্ধান্ত" (আমি এটিকে ত্রুটি হিসাবে দেখি, ব্যক্তিগতভাবে, কিন্তু ওওয়েল)
fge

আপনার ধারণা হিসাবে, আমি এটি খুব ভালভাবে অনুসরণ করি না, দুঃখিত; সর্বোপরি আপনি এখনও যাচাই না করা হিসাবে ছুঁড়ে ফেলেছেন, তাই আমি কী করি তার থেকে এটি কীভাবে আলাদা? (এটি ছাড়া আমার কাছে আলাদা ইন্টারফেস রয়েছে)
fge

যাইহোক, আপনি প্রকল্পে অবদান স্বাগত! এছাড়াও, আপনি লক্ষ্য করেছি যে Streamকার্যকরী AutoCloseable?
fge

আমাকে আপনাকে এটি জিজ্ঞাসা করতে দিন: আপনার MyExceptionউপরেরটি কি চেক করা ব্যতিক্রম হওয়া দরকার?
মার্চজি

3

উন্নত সমাধানের উপরে মন্তব্যের সংক্ষিপ্তসার হ'ল এপিআই এর মতো বিল্ডার সাথে চেক করা ফাংশনগুলির জন্য একটি বিশেষ মোড়ক ব্যবহার করা যা পুনরুদ্ধার, পুনর্বিবেচনা এবং সরবরাহ সরবরাহ করে।

Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
          .map(Try.<String, Class<?>>safe(Class::forName)
                  .handle(System.out::println)
                  .unsafe())
          .collect(toList());

নীচে কোড এটি গ্রাহক, সরবরাহকারী এবং ফাংশন ইন্টারফেসের জন্য প্রদর্শিত করে। এটি সহজেই প্রসারিত করা যেতে পারে। এই উদাহরণের জন্য কিছু সর্বজনীন কীওয়ার্ড মুছে ফেলা হয়েছে।

ক্লাস ট্রাই ক্লায়েন্ট কোডের জন্য শেষ পয়েন্ট। নিরাপদ পদ্ধতিগুলির প্রতিটি ফাংশনের ধরণের জন্য স্বতন্ত্র নাম থাকতে পারে। চেকড কনসুমার , চেকডসপ্লায়ার এবং চেকড ফাংশনটি লাইব ফাংশনগুলির অ্যানালগগুলি যাচাই করে যা চেষ্টা করে স্বতন্ত্রভাবে ব্যবহার করা যায়

কিছু পরীক্ষিত ফাংশনে ব্যতিক্রমগুলি পরিচালনা করার জন্য ইন্টারফেস হ'ল চেকডবিল্ডার । পূর্ববর্তী ব্যর্থ হলে orTry অন্য একই ধরণের ফাংশন সম্পাদন করতে দেয়। হ্যান্ডেল ব্যতিক্রম ফিল্টারিং সহ ব্যতিক্রম হ্যান্ডলিং সরবরাহ করে। হ্যান্ডলারের ক্রমটি গুরুত্বপূর্ণ। অনিরাপদ পদ্ধতিগুলিকে হ্রাস করুন এবং এক্সিকিউশন শৃঙ্খলে পুনরায় পুনর্বিবেচনার শেষ ব্যতিক্রম। পদ্ধতিগুলি হ্রাস করুন বা সমস্ত ফাংশন ব্যর্থ হলে অরলেস এবং ওলিজগেট বিকল্প বিকল্পের মতো বিকল্প মানটি ফিরিয়ে আনুন । এছাড়াও পদ্ধতি দমন আছেচেকডব্রেপার চেকডবিল্ডারের সাধারণ প্রয়োগ।

final class Try {

    public static <T> CheckedBuilder<Supplier<T>, CheckedSupplier<T>, T> 
        safe(CheckedSupplier<T> supplier) {
        return new CheckedWrapper<>(supplier, 
                (current, next, handler, orResult) -> () -> {
            try { return current.get(); } catch (Exception ex) {
                handler.accept(ex);
                return next.isPresent() ? next.get().get() : orResult.apply(ex);
            }
        });
    }

    public static <T> Supplier<T> unsafe(CheckedSupplier<T> supplier) {
        return supplier;
    }

    public static <T> CheckedBuilder<Consumer<T>, CheckedConsumer<T>, Void> 
        safe(CheckedConsumer<T> consumer) {
        return new CheckedWrapper<>(consumer, 
                (current, next, handler, orResult) -> t -> {
            try { current.accept(t); } catch (Exception ex) {
                handler.accept(ex);
                if (next.isPresent()) {
                    next.get().accept(t);
                } else {
                    orResult.apply(ex);
                }
            }
        });
    }

    public static <T> Consumer<T> unsafe(CheckedConsumer<T> consumer) {
        return consumer;
    }

    public static <T, R> CheckedBuilder<Function<T, R>, CheckedFunction<T, R>, R> 
        safe(CheckedFunction<T, R> function) {
        return new CheckedWrapper<>(function, 
                (current, next, handler, orResult) -> t -> {
            try { return current.applyUnsafe(t); } catch (Exception ex) {
                handler.accept(ex);
                return next.isPresent() ? next.get().apply(t) : orResult.apply(ex);
            }
        });
    }

    public static <T, R> Function<T, R> unsafe(CheckedFunction<T, R> function) {
        return function;
    }

    @SuppressWarnings ("unchecked")
    static <T, E extends Throwable> T throwAsUnchecked(Throwable exception) throws E { 
        throw (E) exception; 
    }
}

@FunctionalInterface interface CheckedConsumer<T> extends Consumer<T> {
    void acceptUnsafe(T t) throws Exception;
    @Override default void accept(T t) {
        try { acceptUnsafe(t); } catch (Exception ex) {
            Try.throwAsUnchecked(ex);
        }
    }
}

@FunctionalInterface interface CheckedFunction<T, R> extends Function<T, R> {
    R applyUnsafe(T t) throws Exception;
    @Override default R apply(T t) {
        try { return applyUnsafe(t); } catch (Exception ex) {
            return Try.throwAsUnchecked(ex);
        }
    }
}

@FunctionalInterface interface CheckedSupplier<T> extends Supplier<T> {
    T getUnsafe() throws Exception;
    @Override default T get() {
        try { return getUnsafe(); } catch (Exception ex) {
            return Try.throwAsUnchecked(ex);
        }
    }
}

interface ReduceFunction<TSafe, TUnsafe, R> {
    TSafe wrap(TUnsafe current, Optional<TSafe> next, 
            Consumer<Throwable> handler, Function<Throwable, R> orResult);
}

interface CheckedBuilder<TSafe, TUnsafe, R> {
    CheckedBuilder<TSafe, TUnsafe, R> orTry(TUnsafe next);

    CheckedBuilder<TSafe, TUnsafe, R> handle(Consumer<Throwable> handler);

    <E extends Throwable> CheckedBuilder<TSafe, TUnsafe, R> handle(
            Class<E> exceptionType, Consumer<E> handler);

    CheckedBuilder<TSafe, TUnsafe, R> handleLast(Consumer<Throwable> handler);

    <E extends Throwable> CheckedBuilder<TSafe, TUnsafe, R> handleLast(
            Class<E> exceptionType, Consumer<? super E> handler);

    TSafe unsafe();
    TSafe rethrow(Function<Throwable, Exception> transformer);
    TSafe suppress();
    TSafe orElse(R value);
    TSafe orElseGet(Supplier<R> valueProvider);
}

final class CheckedWrapper<TSafe, TUnsafe, R> 
        implements CheckedBuilder<TSafe, TUnsafe, R> {

    private final TUnsafe function;
    private final ReduceFunction<TSafe, TUnsafe, R> reduceFunction;

    private final CheckedWrapper<TSafe, TUnsafe, R> root;
    private CheckedWrapper<TSafe, TUnsafe, R> next;

    private Consumer<Throwable> handlers = ex -> { };
    private Consumer<Throwable> lastHandlers = ex -> { };

    CheckedWrapper(TUnsafe function, 
            ReduceFunction<TSafe, TUnsafe, R> reduceFunction) {
        this.function = function;
        this.reduceFunction = reduceFunction;
        this.root = this;
    }

    private CheckedWrapper(TUnsafe function, 
            CheckedWrapper<TSafe, TUnsafe, R> prev) {
        this.function = function;
        this.reduceFunction = prev.reduceFunction;
        this.root = prev.root;
        prev.next = this;
    }

    @Override public CheckedBuilder<TSafe, TUnsafe, R> orTry(TUnsafe next) {
        return new CheckedWrapper<>(next, this);
    }

    @Override public CheckedBuilder<TSafe, TUnsafe, R> handle(
            Consumer<Throwable> handler) {
        handlers = handlers.andThen(handler);
        return this;
    }

    @Override public <E extends Throwable> CheckedBuilder<TSafe, TUnsafe, R> 
        handle(Class<E> exceptionType, Consumer<E> handler) {
        handlers = handlers.andThen(ex -> {
            if (exceptionType.isInstance(ex)) {
                handler.accept(exceptionType.cast(ex));
            }
        });
        return this;
    }

    @Override public CheckedBuilder<TSafe, TUnsafe, R> handleLast(
            Consumer<Throwable> handler) {
        lastHandlers = lastHandlers.andThen(handler);
        return this;
    }

    @Override public <E extends Throwable> CheckedBuilder<TSafe, TUnsafe, R> 
        handleLast(Class<E> exceptionType, Consumer<? super E> handler) {
        lastHandlers = lastHandlers.andThen(ex -> {
            if (exceptionType.isInstance(ex)) {
                handler.accept(exceptionType.cast(ex));
            }
        });
        return this;
    }

    @Override public TSafe unsafe() {
        return root.reduce(ex -> Try.throwAsUnchecked(ex));
    }

    @Override
    public TSafe rethrow(Function<Throwable, Exception> transformer) {
        return root.reduce(ex -> Try.throwAsUnchecked(transformer.apply(ex)));
    }

    @Override public TSafe suppress() {
        return root.reduce(ex -> null);
    }

    @Override public TSafe orElse(R value) {
        return root.reduce(ex -> value);
    }

    @Override public TSafe orElseGet(Supplier<R> valueProvider) {
        Objects.requireNonNull(valueProvider);
        return root.reduce(ex -> valueProvider.get());
    }

    private TSafe reduce(Function<Throwable, R> orResult) {
        return reduceFunction.wrap(function, 
                Optional.ofNullable(next).map(p -> p.reduce(orResult)), 
                this::handle, orResult);
    }

    private void handle(Throwable ex) {
        for (CheckedWrapper<TSafe, TUnsafe, R> current = this; 
                current != null; 
                current = current.next) {
            current.handlers.accept(ex);
        }
        lastHandlers.accept(ex);
    }
}

3

টিএল; ডিআর সবেমাত্র লোমবকের ব্যবহার করুন@SneakyThrows

ক্রিশ্চিয়ান হুজার ইতিমধ্যে বিশদটি ব্যাখ্যা করেছেন যে জাভা-র সীমাবদ্ধতার কারণে কেন একটি স্ট্রিম থেকে চেক করা ব্যতিক্রম ছোঁড়া, কঠোরভাবে বলা যায় না।

কিছু অন্যান্য উত্তর ভাষার সীমাবদ্ধতা ঘুরে দেখার কৌশলগুলি ব্যাখ্যা করেছে তবে "পরীক্ষিত ব্যতিক্রম নিজেই নিক্ষেপ করে এবং প্রবাহে কুৎসিত প্রচেষ্টা / ক্যাচগুলি যোগ না করে" নিক্ষেপ করার প্রয়োজনীয়তা পূরণ করতে সক্ষম হয়েছে , তাদের কয়েকটিকে দশকের জন্য অতিরিক্ত অতিরিক্ত লাইন প্রয়োজন বয়লারপ্লেট এর।

আমি এটি করার জন্য আরেকটি বিকল্প হাইলাইট করতে যাচ্ছি যে আইএমএইচও অন্য সকলের তুলনায় অনেক পরিষ্কার: লম্বোকের @SneakyThrows। অন্যান্য উত্তর দিয়ে যাওয়ার সময় এটি উল্লেখ করা হয়েছে তবে অনেক অপ্রয়োজনীয় বিবরণে কিছুটা দাফন করা হয়েছিল।

ফলাফলযুক্ত কোডটি এত সহজ:

public List<Class> getClasses() throws ClassNotFoundException {
    List<Class> classes =
        Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
                .map(className -> getClass(className))
                .collect(Collectors.toList());
    return classes;
}

@SneakyThrows                                 // <= this is the only new code
private Class<?> getClass(String className) {
    return Class.forName(className);
}

আমাদের কেবলমাত্র একটি Extract Methodরিফ্যাক্টরিং (আইডিই দ্বারা সম্পন্ন) এবং এর জন্য একটি অতিরিক্ত লাইন দরকার @SneakyThrows। টীকাগুলি সমস্ত বয়লারপ্লেট যুক্ত করার বিষয়টি নিশ্চিত করে যাতে আপনি আপনার চেক করা ব্যতিক্রমটিকে কোনও মোড়কে না রেখে এবং RuntimeExceptionএটি স্পষ্টভাবে ঘোষণা করার প্রয়োজন ছাড়াই ফেলে দিতে পারেন তা নিশ্চিত করে ।


4
লম্বোকের ব্যবহার নিরুৎসাহিত করা উচিত।
ড্রাগস

2

আপনি চেক না করা ব্যতিক্রমগুলি মোড়ানোর জন্য একটি মোড়ক পদ্ধতিও লিখতে পারেন, এবং এমনকি অন্য কার্যকরী ইন্টারফেসের প্রতিনিধিত্বকারী অতিরিক্ত প্যারামিটার সহ মোড়ককে বাড়িয়ে তুলতে পারেন (একই রিটার্ন টাইপের আর সহ )। এই ক্ষেত্রে আপনি কোনও ফাংশন পাস করতে পারেন যা কার্যকর হবে এবং ব্যতিক্রমের ক্ষেত্রে ফিরে আসবে। নীচে উদাহরণ দেখুন:

private void run() {
    List<String> list = Stream.of(1, 2, 3, 4).map(wrapper(i ->
            String.valueOf(++i / 0), i -> String.valueOf(++i))).collect(Collectors.toList());
    System.out.println(list.toString());
}

private <T, R, E extends Exception> Function<T, R> wrapper(ThrowingFunction<T, R, E> function, 
Function<T, R> onException) {
    return i -> {
        try {
            return function.apply(i);
        } catch (ArithmeticException e) {
            System.out.println("Exception: " + i);
            return onException.apply(i);
        } catch (Exception e) {
            System.out.println("Other: " + i);
            return onException.apply(i);
        }
    };
}

@FunctionalInterface
interface ThrowingFunction<T, R, E extends Exception> {
    R apply(T t) throws E;
}

2

আসল সমস্যার জন্য এখানে একটি ভিন্ন দৃষ্টিভঙ্গি বা সমাধান is এখানে আমি দেখাই যে আমাদের একটি কোড লিখতে একটি বিকল্প রয়েছে যা ব্যতিক্রম ছুঁড়ে ফেলা হলে কেসগুলি সনাক্ত এবং পরিচালনা করার বিকল্পের সাথে মানগুলির একটি বৈধ উপসেটটি প্রসেস করবে।

    @Test
    public void getClasses() {

        String[] classNames = {"java.lang.Object", "java.lang.Integer", "java.lang.Foo"};
        List<Class> classes =
                Stream.of(classNames)
                        .map(className -> {
                            try {
                                return Class.forName(className);
                            } catch (ClassNotFoundException e) {
                                // log the error
                                return null;
                            }
                        })
                        .filter(c -> c != null)
                        .collect(Collectors.toList());

        if (classes.size() != classNames.length) {
            // add your error handling here if needed or process only the resulting list
            System.out.println("Did not process all class names");
        }

        classes.forEach(System.out::println);
    }

1

আমি উপরের মন্তব্যগুলির সাথে একমত হয়েছি, স্ট্রিম.ম্যাপ ব্যবহারে আপনি ফাংশন বাস্তবায়নের মধ্যে সীমাবদ্ধ যা ব্যতিক্রম ছুঁড়ে না।

তবে আপনি নিজের ফাংশনাল ইন্টারফেসটি তৈরি করতে পারেন যা নীচের মতো ছুঁড়েছে ..

@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
  void accept(T instance) throws X;
}

তারপরে নীচে প্রদর্শিত হিসাবে ল্যাম্বডাস বা রেফারেন্স ব্যবহার করে এটি বাস্তবায়ন করুন।

import java.io.FileWriter;
import java.io.IOException;

//lambda expressions and the execute around method (EAM) pattern to
//manage resources

public class FileWriterEAM  {
  private final FileWriter writer;

  private FileWriterEAM(final String fileName) throws IOException {
    writer = new FileWriter(fileName);
  }
  private void close() throws IOException {
    System.out.println("close called automatically...");
    writer.close();
  }
  public void writeStuff(final String message) throws IOException {
    writer.write(message);
  }
  //...

  public static void use(final String fileName, final UseInstance<FileWriterEAM, IOException> block) throws IOException {

    final FileWriterEAM writerEAM = new FileWriterEAM(fileName);    
    try {
      block.accept(writerEAM);
    } finally {
      writerEAM.close();
    }
  }

  public static void main(final String[] args) throws IOException {

    FileWriterEAM.use("eam.txt", writerEAM -> writerEAM.writeStuff("sweet"));

    FileWriterEAM.use("eam2.txt", writerEAM -> {
        writerEAM.writeStuff("how");
        writerEAM.writeStuff("sweet");      
      });

    FileWriterEAM.use("eam3.txt", FileWriterEAM::writeIt);     

  }


 void writeIt() throws IOException{
     this.writeStuff("How ");
     this.writeStuff("sweet ");
     this.writeStuff("it is");

 }

}

1

কোনও mapঅপারেশনের মাধ্যমে ছুঁড়ে দেওয়া যায় এমন চেক করা ব্যতিক্রমগুলি পরিচালনা করার একমাত্র অন্তর্নিহিত উপায় হ'ল এটিকে এর মধ্যে আবদ্ধ করা CompletableFuture। ( Optionalযদি আপনার ব্যতিক্রমটি সংরক্ষণের প্রয়োজন না হয় তবে এটি একটি সহজ বিকল্প These) এই ক্লাসগুলির উদ্দেশ্য আপনাকে ক্রিয়ামূলক উপায়ে आकस्मिक ক্রিয়াকলাপ উপস্থাপন করার অনুমতি দেবে।

বেশ কিছু দ্বি-তুচ্ছ সাহায্যকারী পদ্ধতির প্রয়োজন, তবে আপনি তুলনামূলকভাবে সংক্ষিপ্ত কোডে পৌঁছে যেতে পারেন, তবুও এটি স্পষ্ট করে দেখিয়েছেন যে আপনার স্ট্রিমের ফলাফলটি mapসফলভাবে সম্পন্ন হওয়া অপারেশনটিতে তাত্পর্যপূর্ণ । এটি দেখতে কেমন দেখাচ্ছে তা এখানে:

    CompletableFuture<List<Class<?>>> classes =
            Stream.of("java.lang.String", "java.lang.Integer", "java.lang.Double")
                  .map(MonadUtils.applyOrDie(Class::forName))
                  .map(cfc -> cfc.thenApply(Class::getSuperclass))
                  .collect(MonadUtils.cfCollector(ArrayList::new,
                                                  List::add,
                                                  (List<Class<?>> l1, List<Class<?>> l2) -> { l1.addAll(l2); return l1; },
                                                  x -> x));
    classes.thenAccept(System.out::println)
           .exceptionally(t -> { System.out.println("unable to get class: " + t); return null; });

এটি নিম্নলিখিত আউটপুট উত্পাদন করে:

[class java.lang.Object, class java.lang.Number, class java.lang.Number]

applyOrDieপদ্ধতি লাগে Functionমধ্যে যে একটি ব্যতিক্রম ছোঁড়ার, এবং এটি পরিবর্তন করে একটি Functionকরে আয় ইতিমধ্যেই সম্পন্ন CompletableFuture- হয়, মূল ফাংশনের ফলাফল নিয়ে স্বাভাবিকভাবে সম্পন্ন বা নিক্ষিপ্ত বাদে অত্যন্ত সম্পন্ন করেন।

দ্বিতীয় mapঅপারেশনটি বোঝায় যে আপনি এখন Stream<CompletableFuture<T>>কেবল একটি এর পরিবর্তে একটি পেয়েছেন Stream<T>CompletableFutureযদি প্রবাহের অপারেশন সফল হয় তবে কেবল এই অপারেশনটি সম্পাদন করার যত্ন নেয়। এপিআই এই ব্যাখ্যাটি দেয় তবে তুলনামূলকভাবে ব্যথাহীন থাকে।

যতক্ষণ না আপনি এই collectপর্যায়ে পৌঁছান, তা। এখানেই আমাদের একটি দুর্দান্ত উল্লেখযোগ্য সহায়ক পদ্ধতি প্রয়োজন। আমরা "লিফট" একটি স্বাভাবিক সংগ্রহ অপারেশন (এই ক্ষেত্রে, করতে চান toList()"ভিতরে") CompletableFuture- cfCollector()দেয় আমাদের কি যে ব্যবহার করে একটি supplier, accumulator, combiner, এবং finisherএ সম্পর্কে এ সব কিছু জানেন প্রয়োজন হবে না CompletableFuture

সহায়ক ক্লাসগুলি আমার MonadUtilsক্লাসে গিটহাবের সন্ধান করতে পারে যা এখনও অনেক কাজ চলছে।


1

সম্ভবত, একটি ভাল এবং আরও কার্যকরী উপায় ব্যতিক্রমগুলি মোড়ানো এবং সেগুলি প্রবাহে আরও প্রচার করা। কটাক্ষপাত চেষ্টা ধরণ Vavr উদাহরণস্বরূপ।

উদাহরণ:

interface CheckedFunction<I, O> {
    O apply(I i) throws Exception; }

static <I, O> Function<I, O> unchecked(CheckedFunction<I, O> f) {
    return i -> {
        try {
            return f.apply(i);
        } catch(Exception ex) {

            throw new RuntimeException(ex);
        }
    } }

fileNamesToRead.map(unchecked(file -> Files.readAllLines(file)))

অথবা

@SuppressWarnings("unchecked")
private static <T, E extends Exception> T throwUnchecked(Exception e) throws E {
    throw (E) e;
}

static <I, O> Function<I, O> unchecked(CheckedFunction<I, O> f) {
    return arg -> {
        try {
            return f.apply(arg);
        } catch(Exception ex) {
            return throwUnchecked(ex);
        }
    };
}

2 য় বাস্তবায়ন একটিতে ব্যতিক্রম মোড়ানো এড়ানো RuntimeExceptionthrowUncheckedকাজ করে কারণ প্রায় সবসময় সমস্ত জেনেরিক ব্যতিক্রম জাভাতে চেক না করা হিসাবে বিবেচিত হয়।


1

আমি এই জাতীয় মোড়ক ব্যতিক্রম ব্যবহার করি:

public class CheckedExceptionWrapper extends RuntimeException {
    ...
    public <T extends Exception> CheckedExceptionWrapper rethrow() throws T {
        throw (T) getCause();
    }
}

এটি স্ট্যাটিক্যালি এই ব্যতিক্রমগুলি পরিচালনা করতে হবে:

void method() throws IOException, ServletException {
    try { 
        list.stream().forEach(object -> {
            ...
            throw new CheckedExceptionWrapper(e);
            ...            
        });
    } catch (CheckedExceptionWrapper e){
        e.<IOException>rethrow();
        e.<ServletExcepion>rethrow();
    }
}

এটি অনলাইন চেষ্টা করুন!

যদিও প্রথম rethrow()কল করার সময় ব্যতিক্রম যাইহোক পুনরায় নিক্ষেপ করা হবে (ওহ, জাভা জেনেরিকস ...), এই উপায়টি সম্ভাব্য ব্যতিক্রমগুলির একটি কঠোর পরিসংখ্যান সংজ্ঞা পেতে দেয় (তাদের এটিকে ঘোষণা করার প্রয়োজন হয় throws)। এবং না instanceofবা কিছু প্রয়োজন হয় না।


-1

আমি মনে করি এই পদ্ধতিটি সঠিক:

public List<Class> getClasses() throws ClassNotFoundException {
    List<Class> classes;
    try {
        classes = Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String").map(className -> {
            try {
                return Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new UndeclaredThrowableException(e);
            }
        }).collect(Collectors.toList());
    } catch (UndeclaredThrowableException e) {
        if (e.getCause() instanceof ClassNotFoundException) {
            throw (ClassNotFoundException) e.getCause();
        } else {
            // this should never happen
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
    return classes;
}

ভিতরে চেক করা ব্যতিক্রম মোড়ানো Callableএকটি UndeclaredThrowableException(এই ব্যতিক্রম জন্য ব্যবহারের ক্ষেত্রে যে) এবং বাইরে unwrapping।

হ্যাঁ, আমি এটি কুরুচিপূর্ণ বলে মনে করি এবং আমি এই ক্ষেত্রে ল্যাম্বডাস ব্যবহারের বিরুদ্ধে পরামর্শ দেব এবং কেবল একটি ভাল পুরাতন লুপে ফিরে যাব, যদি না আপনি একটি সমান্তরাল স্ট্রিমের সাথে কাজ করছেন এবং প্যারালাইলেজেশন একটি উদ্দেশ্যমূলক সুবিধা নিয়ে আসে যা কোডের অপঠনযোগ্যতার ন্যায্যতা প্রমাণ করে।

অন্য অনেকে যেমন উল্লেখ করেছেন, এই পরিস্থিতির সমাধান রয়েছে এবং আমি আশা করি যে এর মধ্যে একটি এটি জাভাের ভবিষ্যতের সংস্করণে পরিণত করবে।


1
(1) ইতিমধ্যে বেশ কয়েকটি উত্তর এর উদাহরণ দেখায়, সুতরাং আপনার উত্তরটি ইতিমধ্যে আচ্ছাদিত নয় এমন প্রশ্নোত্তরের সাথে কী যুক্ত হবে? এর মতো সদৃশ উত্তরগুলি পোস্ট করা কেবল সাইটে বিশৃঙ্খলা যুক্ত করে। (২) ওপি বিশেষত বলেছে যে তারা এটি করতে চায় না। "দয়া করে মনে রাখবেন যে আমি রানটাইম ব্যতিক্রমের মধ্যে চেক করা ব্যতিক্রমটি মোড়ানো করতে চাই না এবং তার পরিবর্তে মোড়ানো চেক করা ব্যতিক্রমটি ফেলে দিতে চাই না।"
রেডিওডেফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.