জাভাতে শেষ অবধি ব্লক থেকে ফিরছেন


177

আমি সম্প্রতি অবাক হয়ে গিয়েছিলাম যে জাভাতে শেষ অবধি ব্লকটিতে রিটার্ন স্টেটমেন্ট পাওয়া সম্ভব।

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

সুতরাং, আমার প্রশ্ন হ'ল, কেউ কি আমাকে উদাহরণ দিতে পারে যেখানে শেষ অবধি কোনও রিটার্ন স্টেটমেন্ট (বা অন্যান্য ফ্লো কন্ট্রোল) আরও ভাল / আরও পঠনযোগ্য কোড উত্পাদন করে?

উত্তর:


90

আপনার দেওয়া উদাহরণগুলি শেষ পর্যন্ত প্রবাহ-নিয়ন্ত্রণ ব্যবহার না করার যথেষ্ট কারণ ।

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


5
অবশ্যই। আমি অনুমান করি যে কেউ যদি আমাকে ভাল দিকের জন্য কিছু সত্যিই বাধ্যমূলক উদাহরণ দিতে পারে তবে আমি জিজ্ঞাসা করছি।
ম্যাট শ্যাপার্ড

দাওসে ম্যাটশেপার্ড, আমি প্রায়শই একটি প্রশ্নের শেষের
ব্লেক

148

বছরখানেক আগে যে বাগটিটি ঘটেছিল তা খুঁজে বের করার জন্য আমার খুব কষ্টের সময় ছিল। কোডটি এমন কিছু ছিল:

Object problemMethod() {
    Object rtn = null;
    try {
        rtn = somethingThatThrewAnException();
    }
    finally {
        doSomeCleanup();
        return rtn;
    }
}

যা ঘটেছিল তা ব্যতিক্রমটি অন্য কোনও কোডে ফেলে দেওয়া হয়েছিল। এটি ধরা পড়ে এবং লগইন করা হয়েছিল এবং পদ্ধতিটির মধ্যে পুনর্বিবেচনা করা হচ্ছে somethingThatThrewAnException()। তবে ব্যতিক্রমটি অতীতে প্রচার করা হয়নি problemMethod()। এটি দেখার দীর্ঘ সময় পরে আমরা অবশেষে এটি রিটার্ন পদ্ধতিতে সন্ধান করি। শেষ অবধি রিটার্ন পদ্ধতিটি মূলত ট্রাই ব্লকে যে ব্যতিক্রম ঘটেছিল তা ধরা না পড়লেও প্রচার প্রচার থেকে বিরত ছিল।

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


তাহলে কোথায় রিটার্ন দেওয়া উচিত?
পার্সিকার

@ পার্সার আমি চেষ্টা করার পরে কিছু বলার পরেই বলব থ্রিট্রইউ এক্সেক্সশন () চেষ্টা ব্লকের ভিতরে
টিয়াগো সিপার্ট

@ পার্সার, ?? শেষ পর্যন্ত এটি কেবল স্বাভাবিকভাবেই করুন।
পেসারিয়ার

21

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

ব্যতিক্রমগুলি অবশেষে ব্লকগুলি থেকে ছুঁড়ে দেওয়া যেতে পারে, তবে সেক্ষেত্রে প্রদর্শিত আচরণটি অবশ্যই আপনি যা চান তা অবশ্যই।


13

নিয়ন্ত্রণ কাঠামো যুক্ত করা এবং অবশেষে}} ব্লকগুলিতে রিটার্ন যুক্ত হ'ল কার্যত সমস্ত বিকাশ ভাষায় ছড়িয়ে ছিটিয়ে থাকা অপব্যবহারগুলি "আপনি কেবল পারেন" এর অন্য একটি উদাহরণ। জেসন এটি সহজেই রক্ষণাবেক্ষণের দুঃস্বপ্নে পরিণত হতে পারে এমন পরামর্শ দেওয়ার ক্ষেত্রে সঠিক ছিল - ফাংশনগুলি থেকে আগাম রিটার্নের বিরুদ্ধে যুক্তি "লেট রিটার্ন" এর ক্ষেত্রে আরও বেশি প্রয়োগ হয়।

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

ফাংশনটির রিটার্নকে প্রভাবিত করে এমন কোনও কিছুই চেষ্টা {} ব্লকের মধ্যে থাকা উচিত। এমনকি যদি আপনার এমন কোনও পদ্ধতি ছিল যার মাধ্যমে আপনি কোনও বাহ্যিক অবস্থা পরীক্ষা করেছেন, সময় সাপেক্ষে অপারেশন করেছেন, তবে সেই অবস্থাটি অবৈধ হয়ে যাওয়ার পরে আবার পরীক্ষা করে দেখুন, আপনি এখনও চেষ্টা করবেন inside} এর ভিতরে দ্বিতীয় চেকটি - যদি এটি শেষ পর্যন্ত বসে থাকে {{ এবং দীর্ঘ অপারেশন ব্যর্থ হয়েছে, আপনি তারপরে অযথা দ্বিতীয় বার সেই অবস্থাটি পরীক্ষা করবেন।


6

একটি সাধারণ গ্রোভী পরীক্ষা:

public class Instance {

  List<String> runningThreads = new ArrayList<String>()

  void test(boolean returnInFinally) {

    println "\ntest(returnInFinally: $returnInFinally)"
    println "--------------------------------------------------------------------------"
    println "before execute"
    String result = execute(returnInFinally, false)
    println "after execute -> result: " + result
    println "--------------------------------------------------------------------------"

    println "before execute"
    try {
      result = execute(returnInFinally, true)
      println "after execute -> result: " + result
    } catch (Exception ex) {
      println "execute threw exception: " + ex.getMessage()
    }  
    println "--------------------------------------------------------------------------\n"

  }

  String execute(boolean returnInFinally, boolean throwError) {
      String thread = Thread.currentThread().getName()
      println "...execute(returnInFinally: $returnInFinally, throwError: $throwError) - thread: $thread"
      runningThreads.add(thread)
      try {
        if (throwError) {
          println "...error in execute, throw exception"
          throw new Exception("as you liked :-)")
        }
        println "...return 'OK' from execute"
        return "OK"
      } finally {
        println "...pass finally block"
        if (returnInFinally) return "return value from FINALLY ^^"
        // runningThreads.remove(thread)
      }
  }
}

Instance instance = new Instance()
instance.test(false)
instance.test(true)

আউটপুট:

test(returnInFinally: false)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: OK
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
execute threw exception: as you liked :-)
-----------------------------------------------------------------------------


test(returnInFinally: true)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------

প্রশ্ন:

আমার জন্য একটি আকর্ষণীয় বিষয়টি ছিল গ্রোভী কীভাবে অন্তর্নিহিত রিটার্নগুলির সাথে আচরণ করে see গ্রোভিতে কোনও পদ্ধতিটি শেষে "মান" শেষে (মান ছাড়া) ছেড়ে দেওয়া সম্ভব। আপনি কী মনে করেন, যদি আপনি শেষের বিবৃতিতে চলমান Treads.remove (..) লাইনটিকে অসম্পূর্ণ করেন - তবে এটি কি নিয়মিত ফেরতের মান ("ঠিক আছে") ওভাররাইট করে এবং ব্যতিক্রমটি কভার করবে ?!


0

কোনও finallyব্লকের ভিতরে থেকে ফিরে আসার কারণে exceptionsহারিয়ে যাওয়ার কারণ হবে ।

শেষ অবধি ব্লকের অভ্যন্তরে রিটার্নের বিবৃতি এমন কোনও ব্যতিক্রম ঘটায় যা চেষ্টা বা ক্যাচ ব্লকে ফেলে দেওয়া হতে পারে।

মতে জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন:

যদি অন্য কোনও কারণে আর চেষ্টা করে ব্লকটি কার্যকর করা হঠাৎ করে সম্পূর্ণ হয় তবে শেষ অবধি ব্লকটি কার্যকর করা হয় এবং তারপরে একটি বিকল্প রয়েছে:

   If the finally block completes normally, then the try statement
   completes  abruptly for reason R.

   If the finally block completes abruptly for reason S, then the try
   statement  completes abruptly for reason S (and reason R is
   discarded).

দ্রষ্টব্য: জেএলএস 14.17 অনুসারে - একটি রিটার্ন বিবৃতি সর্বদা হঠাৎ করেই সম্পূর্ণ হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.