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


172

ধরুন আমার ক্লাস এবং একটা পদ্ধতি আছে

class A {
  void foo() throws Exception() {
    ...
  }
}

এখন আমি এই জাতীয় Aস্ট্রিমের মাধ্যমে দেওয়া প্রতিটি উদাহরণের জন্য ফোওকে কল করতে চাই:

void bar() throws Exception {
  Stream<A> as = ...
  as.forEach(a -> a.foo());
}

প্রশ্ন: আমি কীভাবে ব্যতিক্রমটি সঠিকভাবে পরিচালনা করব? কোডটি আমার মেশিনে সংকলন করে না কারণ foo () দ্বারা নিক্ষেপ করা সম্ভব ব্যতিক্রমগুলি আমি পরিচালনা করি না। throws Exceptionএর barএখানে বেহুদা মনে করা হয়। কেন এমন?



উত্তর:


141

আপনাকে আপনার পদ্ধতি কলটি অন্য একটিতে মোড়াতে হবে, যেখানে আপনি পরীক্ষিত ব্যতিক্রমগুলি ছুঁড়ে না ফেলে । আপনি এখনও এমন কোনও কিছু ফেলে দিতে পারেন যা একটি সাবক্লাস RuntimeException

একটি সাধারণ মোড়ক আইডিয়ম হ'ল কিছু:

private void safeFoo(final A a) {
    try {
        a.foo();
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

(Supertype ব্যতিক্রম Exceptionহয় শুধুমাত্র , উদাহরণস্বরূপ হিসেবে ব্যবহৃত এটা নিজেকে ধরা চেষ্টা না)

তারপর আপনার সাথে কল করতে পারেন: as.forEach(this::safeFoo)


1
আপনি যদি এটি একটি মোড়কের পদ্ধতি হতে চান তবে আমি এটি স্থির ঘোষণা করব। এটি 'এটি' থেকে কিছু ব্যবহার করে না।
aalku

206
আমাদের দেশীয় ব্যতিক্রমগুলি ব্যবহার না করে আমাদের এটি করা দুঃখজনক .... ওহ জাভা, এটি দেয় এবং তারপরে সরে যায়
এরিচ

1
@Stephan এই উত্তরটি মোছা হয়েছে, কিন্তু তা এখানে এখনও পাওয়া আছে: stackoverflow.com/a/27661562/309308
মাইকেল Mrozek

3
এটি তাত্ক্ষণিকভাবে আমার সংস্থায় কোড পর্যালোচনা ব্যর্থ হবে: আমাদের চেক করা ব্যতিক্রম ছোঁড়ার অনুমতি নেই।
স্টিলিওস অ্যাডামেন্টিডিস

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

35

আপনি চান আপনার সব ডাকা হয়, তাহলে foo, এবং আপনি ব্যতিক্রম সঞ্চারিত হিসাবে (মোড়ানো ছাড়া) হয় পছন্দ করা, এছাড়াও আপনি শুধু জাভার ব্যবহার করতে পারেন forলুপ পরিবর্তে (কিছু সঙ্গে একটি Iterable মধ্যে স্ট্রিম ফিরানোর পরে কপট ):

for (A a : (Iterable<A>) as::iterator) {
   a.foo();
}

এটি অন্ততপক্ষে আমার JUnit পরীক্ষাগুলিতে আমি কী করি, যেখানে আমি আমার চেক করা ব্যতিক্রমগুলি মোড়ানোর সমস্যায় পড়তে চাই না (এবং প্রকৃতপক্ষে মোড়ক ছাড়ানো মূল পরীক্ষাগুলি ছুঁড়ে দেওয়ার জন্য আমার পরীক্ষাগুলি পছন্দ করে)


16

এই প্রশ্নটি কিছুটা পুরানো হতে পারে তবে আমি মনে করি যে এখানে "সঠিক" উত্তরটি কেবলমাত্র একটি উপায় যা কিছু পরে আপনার কোডে লুকানো ইস্যুগুলিকে নিয়ে যেতে পারে। এমনকি যদি কিছুটা বিতর্ক হয় তবে একটি কারণে চেক করা ব্যতিক্রমগুলি বিদ্যমান।

আমার মতে আপনি দেখতে পাবেন সবচেয়ে মার্জিত উপায়টি মিশা এখানে দিয়েছিলেন জাভা 8 স্ট্রিমিতে কেবল "ফিউচার" এর ক্রিয়া সম্পাদন করে সমষ্টিগত রানটাইম ব্যতিক্রম । সুতরাং আপনি সমস্ত কার্যকরী অংশ পরিচালনা করতে পারেন এবং একক হিসাবে ব্যতিক্রম ব্যতীত সংগ্রহ করতে পারেন। অন্যথায় আপনি তাদের একটি তালিকাতে সংগ্রহ করতে পারেন এবং পরে তাদের প্রক্রিয়া করতে পারেন।

বেনজি ওয়েবারের অনুরূপ পন্থা এসেছে । তিনি কাজের অংশ এবং কাজের অংশগুলি সংগ্রহ না করার জন্য নিজস্ব ধরণের তৈরি করার পরামর্শ দেন।

ইনপুট মান এবং আউটপুট মানগুলির মধ্যে একটি সাধারণ ম্যাপিং আপনি কী পেতে চান তার উপর নির্ভর করে ব্যতিক্রমগুলিও আপনার জন্য কাজ করতে পারে।

যদি আপনি এই কোনও উপায় পছন্দ না করেন তবে অন্তত একটি নিজস্ব ব্যতিক্রম (আসল ব্যতিক্রমের উপর নির্ভর করে) ব্যবহার বিবেচনা করুন।


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

2
আপনি তাদেরকে কোন স্তরে ধরতে চান তা চয়ন করতে সক্ষম হওয়া উচিত এবং এটির সাথে গণ্ডগোল। স্ট্রিম এপিআই আপনাকে চূড়ান্ত অপারেশন (সংগ্রহের মতো) অবধি ব্যতিক্রম বহন করে এবং সেখানে কোনও হ্যান্ডলারের সাহায্যে পরিচালনা করা বা অন্যথায় নিক্ষেপ করা উচিত। stream.map(Streams.passException(x->mightThrowException(x))).catch(e->whatToDo(e)).collect(...)। এটি ব্যতিক্রমগুলি আশা করে এবং আপনাকে ফিউচারগুলির মতো তাদের পরিচালনা করতে দেয়।
aalku

10

আমি গুগল পেয়ারা থ্রোয়েবাল ক্লাস ব্যবহার করার পরামর্শ দিই

বংশ বিস্তার ( নিক্ষেপযোগ্য নিক্ষেপযোগ্য)

যদি এটি রানটাইম এক্সেকশন বা ত্রুটির উদাহরণ হিসাবে হয় তবে অন্যথায় শেষ অবলম্বন হিসাবে এটি রানটাইম এক্সেকসেপ্টে আবৃত করে প্রচার করে * **

void bar() {
    Stream<A> as = ...
    as.forEach(a -> {
        try {
            a.foo()
        } catch(Exception e) {
            throw Throwables.propagate(e);
        }
    });
}

হালনাগাদ:

এখন এটি অবচিত ব্যবহারের জন্য:

void bar() {
    Stream<A> as = ...
    as.forEach(a -> {
        try {
            a.foo()
        } catch(Exception e) {
            Throwables.throwIfUnchecked(e);
            throw new RuntimeException(e);
        }
    });
}

4
এই পদ্ধতিটি অবচয় করা হয়েছিল (দুর্ভাগ্যক্রমে)।
রবার্ট ভান

9

আপনি এইভাবে ব্যতিক্রমগুলি মোড়ানো এবং মোড়ক করতে পারেন।

class A {
    void foo() throws Exception {
        throw new Exception();
    }
};

interface Task {
    void run() throws Exception;
}

static class TaskException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    public TaskException(Exception e) {
        super(e);
    }
}

void bar() throws Exception {
      Stream<A> as = Stream.generate(()->new A());
      try {
        as.forEach(a -> wrapException(() -> a.foo())); // or a::foo instead of () -> a.foo()
    } catch (TaskException e) {
        throw (Exception)e.getCause();
    }
}

static void wrapException(Task task) {
    try {
        task.run();
    } catch (Exception e) {
        throw new TaskException(e);
    }
}

9

আপনি নিম্নলিখিতগুলির মধ্যে একটি করতে চাইতে পারেন:

  • চেক করা ব্যতিক্রম প্রচার করুন,
  • এটি মোড়ানো এবং চেক করা ব্যতিক্রম প্রচার করুন, বা
  • ব্যতিক্রম ধরুন এবং প্রচার বন্ধ করুন।

বেশ কয়েকটি লাইব্রেরি আপনাকে সহজেই তা করতে দেয়। নীচের উদাহরণটি আমার NoException লাইব্রেরি ব্যবহার করে লেখা হয়েছে ।

// Propagate checked exception
as.forEach(Exceptions.sneak().consumer(A::foo));

// Wrap and propagate unchecked exception
as.forEach(Exceptions.wrap().consumer(A::foo));
as.forEach(Exceptions.wrap(MyUncheckedException::new).consumer(A::foo));

// Catch the exception and stop propagation (using logging handler for example)
as.forEach(Exceptions.log().consumer(Exceptions.sneak().consumer(A::foo)));

লাইব্রেরিতে ভালো চাকরি! আমি অনুরূপ কিছু লিখতে চলেছিলাম।
জ্যাস্পার ডি ভ্রিজ

2

আরও পঠনযোগ্য উপায়:

class A {
  void foo() throws MyException() {
    ...
  }
}

RuntimeExceptionএটি অতীত করার জন্য এটি কেবল একটিতে লুকানforEach()

  void bar() throws MyException {
      Stream<A> as = ...
      try {
          as.forEach(a -> {
              try {
                  a.foo();
              } catch(MyException e) {
                  throw new RuntimeException(e);
              }
          });
      } catch(RuntimeException e) {
          throw (MyException) e.getCause();
      }
  }

যদিও এই মুহুর্তে আমি কারও কাছে ধরে রাখব না যদি তারা বলে যে স্রোতগুলি এড়িয়ে চলুন এবং লুপের জন্য যান, তবে:

  • আপনি আপনার স্ট্রিম ব্যবহার করে তৈরি করছেন না Collection.stream(), অর্থাত লুপের জন্য সরাসরি ফরোয়ার্ড ট্রান্সলেশন নয়।
  • আপনি ব্যবহার করার চেষ্টা করছেন parallelstream()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.