Skill

স্কালা এক্সেপশন হ্যান্ডলিং

স্কালা প্রোগ্রামিং (Scala Programming) - Computer Programming

295

স্কালা এক্সেপশন হ্যান্ডলিং একইভাবে কাজ করে যেমন অন্যান্য ভাষায়, অর্থাৎ এটি try, catch, finally ব্লক ব্যবহার করে। স্কালার এক্সেপশন হ্যান্ডলিং আপনাকে কোডের মধ্যে ঘটে যাওয়া অপ্রত্যাশিত ত্রুটিগুলি সঠিকভাবে ধরতে এবং তাদের উপযুক্ত সমাধান প্রদান করতে সহায়তা করে। স্কালায় এক্সেপশন হ্যান্ডলিং খুবই সহজ এবং পরিষ্কারভাবে ব্যবহার করা যায়।

স্কালায় এক্সেপশন হ্যান্ডলিংয়ের জন্য আপনি try, catch, এবং finally ব্লক ব্যবহার করতে পারেন।


১. try, catch, এবং finally ব্লক

  • try: যেখানে আপনি কোড লিখবেন যা এক্সেপশন তৈরি করতে পারে।
  • catch: এক্সেপশন ঘটলে, এই ব্লকটি সেই এক্সেপশন হ্যান্ডল করতে ব্যবহৃত হয়।
  • finally: এই ব্লকটি সবসময় রান হবে, এক্সেপশন ঘটুক বা না ঘটুক।

উদাহরণ:

object ExceptionHandlingExample {
  def divide(a: Int, b: Int): Int = {
    try {
      val result = a / b
      result
    } catch {
      case e: ArithmeticException => {
        println("Error: Division by zero!")
        0  // Return a default value in case of error
      }
      case e: Exception => {
        println("An unknown error occurred.")
        0
      }
    } finally {
      println("This will always execute, regardless of an exception.")
    }
  }

  def main(args: Array[String]): Unit = {
    println(divide(10, 0))  // Output: Error: Division by zero!
                            // Output: This will always execute, regardless of an exception.
                            // Output: 0
    println(divide(10, 2))  // Output: This will always execute, regardless of an exception.
                            // Output: 5
  }
}

এখানে:

  • try ব্লকটি a / b অপারেশনটি চেষ্টা করছে, যা বিভাজ্য শূন্য হলে একটি ArithmeticException তৈরি করতে পারে।
  • catch ব্লকে এই ত্রুটিটি ধরতে এবং একটি ডিফল্ট মান প্রদান করা হচ্ছে।
  • finally ব্লকটি সবসময় রান হবে, এমনকি এক্সেপশন ঘটুক বা না ঘটুক।

২. এক্সেপশন কাস্টমাইজেশন

স্কালায় আপনি নিজে কাস্টম এক্সেপশন তৈরি করতে পারেন। এটি Exception বা Throwable ক্লাসের একটি সাবক্লাস হিসাবে তৈরি করা হয়।

উদাহরণ:

// Define a custom exception class
class InsufficientFundsException(message: String) extends Exception(message)

object CustomExceptionExample {
  def withdraw(amount: Double, balance: Double): Double = {
    if (amount > balance) {
      throw new InsufficientFundsException("Insufficient funds to complete the transaction.")
    } else {
      balance - amount
    }
  }

  def main(args: Array[String]): Unit = {
    try {
      val newBalance = withdraw(1500, 1000)
      println(s"New balance: $newBalance")
    } catch {
      case e: InsufficientFundsException => println(e.getMessage)  // Catch the custom exception
    }
  }
}

এখানে:

  • InsufficientFundsException কাস্টম এক্সেপশন তৈরি করা হয়েছে, যা একটি মেসেজ নেয়।
  • withdraw মেথডে যদি ব্যালেন্সের চেয়ে বেশি অর্থ উত্তোলনের চেষ্টা করা হয়, তবে এই কাস্টম এক্সেপশন থ্রো করা হয়।

৩. Multiple catch Blocks

স্কালায় একাধিক এক্সেপশন টাইপকেও catch ব্লকে ধরতে পারেন। এই কাজটি match স্টাইলের স্যুইচ স্টেটমেন্টের মতো করা হয়।

উদাহরণ:

object MultipleCatchBlocksExample {
  def process(): Unit = {
    try {
      // Simulating two different types of exceptions
      val arr = Array(1, 2, 3)
      println(arr(5))  // ArrayIndexOutOfBoundsException
      val result = 10 / 0  // ArithmeticException
    } catch {
      case e: ArithmeticException => println("Caught ArithmeticException: Division by zero!")
      case e: ArrayIndexOutOfBoundsException => println("Caught ArrayIndexOutOfBoundsException: Invalid array index!")
      case e: Exception => println("Caught a general exception")
    }
  }

  def main(args: Array[String]): Unit = {
    process()
  }
}

এখানে:

  • একাধিক catch ব্লক ব্যবহৃত হয়েছে, যেখানে প্রতিটি এক্সেপশন টাইপ অনুযায়ী প্রক্রিয়া করা হচ্ছে।

৪. থ্রো (Throwing) এক্সেপশন

স্কালায় আপনি নিজের এক্সেপশনটি throw কিওয়ার্ড দিয়ে থ্রো করতে পারেন। এটি কাস্টম বা স্ট্যান্ডার্ড এক্সেপশন উভয়ের জন্য ব্যবহার করা যায়।

উদাহরণ:

object ThrowExceptionExample {
  def checkAge(age: Int): Unit = {
    if (age < 18) {
      throw new IllegalArgumentException("Age must be 18 or older.")
    } else {
      println("You are eligible.")
    }
  }

  def main(args: Array[String]): Unit = {
    try {
      checkAge(16)
    } catch {
      case e: IllegalArgumentException => println(s"Caught exception: ${e.getMessage}")
    }
  }
}

এখানে:

  • throw new IllegalArgumentException দিয়ে কাস্টম এক্সেপশন থ্রো করা হচ্ছে।

৫. ব্যবহারিক ক্ষেত্রে এক্সেপশন হ্যান্ডলিং

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

উদাহরণ (ফাইল পড়া):

import java.io._

object FileHandlingExample {
  def readFile(filePath: String): Unit = {
    try {
      val source = Source.fromFile(filePath)
      for (line <- source.getLines()) {
        println(line)
      }
      source.close()
    } catch {
      case e: FileNotFoundException => println(s"File not found: ${e.getMessage}")
      case e: IOException => println(s"Error reading file: ${e.getMessage}")
    }
  }

  def main(args: Array[String]): Unit = {
    readFile("nonexistentFile.txt")
  }
}

এখানে:

  • Source.fromFile ফাইল পড়তে ব্যবহৃত হয়, এবং যদি ফাইল না পাওয়া যায় তবে FileNotFoundException ক্যাচ করা হয়।

সারাংশ

স্কালার এক্সেপশন হ্যান্ডলিং খুবই শক্তিশালী এবং নমনীয়। এর মাধ্যমে আপনি try, catch, এবং finally ব্লক ব্যবহার করে এক্সেপশনকে ধরতে, হ্যান্ডেল করতে এবং প্রয়োজনীয় ব্যবস্থা নিতে পারেন। স্কালার কাস্টম এক্সেপশন তৈরির সুবিধাও দেয়, যা বিশেষ পরিস্থিতিতে ব্যবহৃত হতে পারে। এর সাহায্যে আপনি আপনার কোডের স্থিতিশীলতা এবং নিরাপত্তা বাড়াতে পারেন।

Content added By

স্কালায় try-catch ব্লক ব্যবহার করে আপনি প্রোগ্রামের এক্সসেপশন (exception) বা ত্রুটির পরিস্থিতি হ্যান্ডেল করতে পারেন। এটি কোডের নিরাপত্তা এবং স্থিরতা বজায় রাখতে সহায়তা করে, যাতে কোনো অপ্রত্যাশিত ত্রুটি ঘটলে প্রোগ্রামটি ক্র্যাশ না হয়ে নির্দিষ্ট ব্যবস্থাপনা করতে পারে।


১. স্কালায় try-catch ব্লক গঠন

স্কালায় try ব্লকটি কোডের সেই অংশে র‌্যাপ করা হয় যেখানে ত্রুটির সম্ভাবনা থাকে এবং catch ব্লকটি ত্রুটির ধরন অনুযায়ী সেই ত্রুটিকে হ্যান্ডেল করে।

try {
  // Code that may throw an exception
} catch {
  case e: ExceptionType => 
    // Handle the exception
}

উদাহরণ:

try {
  val result = 10 / 0  // This will throw an ArithmeticException
  println(result)
} catch {
  case e: ArithmeticException => println("Error: Division by zero!")
  case e: Exception => println("An unexpected error occurred: " + e.getMessage)
}

এখানে:

  • try ব্লকে একটি বিভাজন (division) অপারেশন আছে যা ArithmeticException সৃষ্টি করবে যদি ডিভাইড বাই জিরো হয়।
  • catch ব্লকে দুটি আলাদা এক্সসেপশন হ্যান্ডেল করা হচ্ছে: ArithmeticException এবং সাধারণ Exception

২. একাধিক এক্সসেপশন হ্যান্ডলিং

স্কালায় আপনি একাধিক catch ব্লক ব্যবহার করতে পারেন যাতে একাধিক এক্সসেপশন টাইপের জন্য আলাদা আলাদা হ্যান্ডলিং করা যায়।

try {
  // Code that may throw exceptions
} catch {
  case e: ArithmeticException => println("Arithmetic exception occurred")
  case e: NullPointerException => println("Null pointer exception occurred")
  case e: Exception => println("A general exception occurred")
}

এখানে:

  • ArithmeticException এবং NullPointerException আলাদা আলাদা হ্যান্ডলিং করা হয়েছে।
  • যদি কোনো অপরিচিত এক্সসেপশন ঘটে, তাহলে Exception হ্যান্ডলার চালু হবে।

৩. finally ব্লক

স্কালায় finally ব্লক ব্যবহার করা হয় যেকোনো ত্রুটি ঘটুক বা না ঘটুক, কোডের কিছু অংশ কার্যকরী করতে। এটি try-catch ব্লকের পরে থাকে এবং যেকোনো পরিস্থিতিতে চলমান থাকে।

try {
  val result = 10 / 2
  println("Result: " + result)
} catch {
  case e: ArithmeticException => println("Error: Division by zero!")
} finally {
  println("This will always run, regardless of exception")
}

এখানে:

  • finally ব্লকটি try বা catch ব্লকের পরে নির্বাহিত হয়।
  • এটি সাধারণত resources (যেমন ফাইল বা ডাটাবেস সংযোগ) বন্ধ করার জন্য ব্যবহৃত হয়।

৪. try-catch ব্লকের সাথে Option ব্যবহার

একটি সাধারণ প্যাটার্ন হল try-catch ব্লক ব্যবহার করে Option রিটার্ন করা, যাতে ত্রুটির ক্ষেত্রে None এবং সঠিক ফলাফলের জন্য Some রিটার্ন করা যায়।

def safeDivision(a: Int, b: Int): Option[Int] = {
  try {
    Some(a / b)
  } catch {
    case e: ArithmeticException => None
  }
}

println(safeDivision(10, 2))  // Output: Some(5)
println(safeDivision(10, 0))  // Output: None

এখানে:

  • safeDivision ফাংশনটি Option[Int] রিটার্ন করে, যেখানে সফল ডিভিশনের জন্য Some এবং ত্রুটির জন্য None ফেরত দেওয়া হয়।

৫. এক্সসেপশন প্রোপাগেশন (Exception Propagation)

যদি কোনো এক্সসেপশন try-catch ব্লকের মধ্যে হ্যান্ডেল না করা হয়, তবে এটি উপরের স্তরের কোডে প্রোপাগেট (propagate) হবে এবং সেই অংশে catch ব্লকটি দ্বারা হ্যান্ডেল করা হবে।

উদাহরণ:

def riskyMethod(): Unit = {
  try {
    throw new Exception("Something went wrong")
  } catch {
    case e: Exception => println("Caught in riskyMethod: " + e.getMessage)
  }
}

def callingMethod(): Unit = {
  try {
    riskyMethod()
  } catch {
    case e: Exception => println("Caught in callingMethod: " + e.getMessage)
  }
}

callingMethod()  // Output: Caught in riskyMethod: Something went wrong

এখানে:

  • riskyMethod ত্রুটি ঘটিয়ে সেটি নিজের মধ্যে হ্যান্ডেল করছে।
  • callingMethod তে যদি riskyMethod কোনো ত্রুটি না হ্যান্ডেল করে, তবে তা উপরের স্তরে প্রোপাগেট হবে এবং সেই স্তরে হ্যান্ডেল হবে।

সারাংশ

  • try-catch ব্লক: কোডের একটি অংশ যেখানে ত্রুটি বা এক্সসেপশন ঘটলে তা হ্যান্ডেল করা যায়।
  • catch: বিভিন্ন এক্সসেপশন হ্যান্ডলিংয়ের জন্য ব্যবহার করা হয়।
  • finally: কোড ব্লক যা try-catch ব্লকের পরে চলে এবং এটি যেকোনো পরিস্থিতিতে নির্বাহিত হয়।
  • এক্সসেপশন প্রোপাগেশন: যদি কোনো এক্সসেপশন try-catch ব্লকে হ্যান্ডেল না করা হয়, তবে সেটি উপরের স্তরে প্রোপাগেট হতে পারে।

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

Content added By

স্কালায় কাস্টম এক্সেপশন তৈরি করা সহজ এবং সরল। যখন আপনি একটি নির্দিষ্ট পরিস্থিতিতে একটি কাস্টম এক্সেপশন ব্যবহার করতে চান, তখন আপনি স্কালার Exception ক্লাস বা RuntimeException ক্লাসের একটি সাবক্লাস তৈরি করতে পারেন। এতে আপনার নিজের এক্সেপশন মেসেজ এবং কাস্টম আচরণ নির্ধারণ করা সম্ভব হয়।

এখানে কাস্টম এক্সেপশন তৈরি করার প্রক্রিয়া এবং উদাহরণ দেওয়া হলো।


১. কাস্টম এক্সেপশন তৈরি করা

স্কালায় কাস্টম এক্সেপশন তৈরি করতে আপনাকে একটি ক্লাস তৈরি করতে হবে যা Exception অথবা RuntimeException এর সাবক্লাস হিসেবে কাজ করবে। সাধারণত Exception ক্লাস ব্যবহার করা হয় যদি আপনি চেকড এক্সেপশন তৈরি করতে চান এবং RuntimeException ক্লাস ব্যবহার করা হয় যদি আপনি আনচেকড এক্সেপশন তৈরি করতে চান।

১.১ চেকড এক্সেপশন (Checked Exception)

Checked Exception হল এমন এক্সেপশন যেগুলি কম্পাইল টাইমে চেক করা হয় এবং মেথডের সিগনেচারে throws শব্দটি ব্যবহৃত হয়।

উদাহরণ:

// Creating a custom checked exception by extending Exception
class InvalidAgeException(message: String) extends Exception(message)

// Method that throws the custom exception
def checkAge(age: Int): Unit = {
  if (age < 0) {
    throw new InvalidAgeException("Age cannot be negative.")
  } else {
    println(s"Age is valid: $age")
  }
}

// Using the method
try {
  checkAge(-5)  // This will throw the InvalidAgeException
} catch {
  case e: InvalidAgeException => println(s"Caught exception: ${e.getMessage}")
}

এখানে, InvalidAgeException একটি কাস্টম এক্সেপশন তৈরি করেছে, যা Exception ক্লাস থেকে ইনহেরিট করা হয়েছে। যখন checkAge মেথডে বয়স নেতিবাচক হবে, তখন এটি এই কাস্টম এক্সেপশনটি থ্রো করবে।

১.২ আনচেকড এক্সেপশন (Unchecked Exception)

Unchecked Exception সাধারণত RuntimeException থেকে ইনহেরিট করা হয়। এই ধরনের এক্সেপশনগুলি কম্পাইল টাইমে চেক করা হয় না এবং সাধারণত যখন আপনি ফাংশনে অপ্রত্যাশিত অবস্থা পেয়ে থাকেন তখন এটি ব্যবহার করা হয়।

উদাহরণ:

// Creating a custom unchecked exception by extending RuntimeException
class InvalidAmountException(message: String) extends RuntimeException(message)

// Method that throws the custom exception
def processAmount(amount: Double): Unit = {
  if (amount < 0) {
    throw new InvalidAmountException("Amount cannot be negative.")
  } else {
    println(s"Processing amount: $amount")
  }
}

// Using the method
try {
  processAmount(-100)  // This will throw the InvalidAmountException
} catch {
  case e: InvalidAmountException => println(s"Caught exception: ${e.getMessage}")
}

এখানে InvalidAmountException একটি কাস্টম এক্সেপশন তৈরি করেছে, যা RuntimeException ক্লাস থেকে ইনহেরিট করা হয়েছে। যখন processAmount মেথডে মান নেতিবাচক হবে, তখন এটি এই কাস্টম এক্সেপশনটি থ্রো করবে।


২. কাস্টম এক্সেপশন তৈরির সময় অতিরিক্ত ফিচার যোগ করা

আপনি আপনার কাস্টম এক্সেপশনে অতিরিক্ত ফিচার যোগ করতে পারেন, যেমন স্ট্যাটিক মেথড, কাস্টম কন্সট্রাক্টর, বা নির্দিষ্ট ডিবাগিং তথ্য।

২.১ কাস্টম কন্সট্রাক্টর এবং স্ট্যাটিক মেথড

// Creating a custom exception with a custom constructor and static method
class InvalidOperationException(message: String, errorCode: Int) extends Exception(message) {
  // Adding an error code to the exception
  def getErrorCode: Int = errorCode
}

object InvalidOperationException {
  // A static method to create a new exception with a default error code
  def apply(message: String): InvalidOperationException = new InvalidOperationException(message, 1001)
}

// Method that throws the custom exception
def performOperation(value: Int): Unit = {
  if (value < 0) {
    throw InvalidOperationException("Operation failed due to invalid value")
  } else {
    println("Operation performed successfully!")
  }
}

// Using the method
try {
  performOperation(-5)  // This will throw the InvalidOperationException
} catch {
  case e: InvalidOperationException =>
    println(s"Caught exception: ${e.getMessage}, Error Code: ${e.getErrorCode}")
}

এখানে, InvalidOperationException ক্লাসে একটি কাস্টম কন্সট্রাক্টর এবং একটি getErrorCode মেথড যোগ করা হয়েছে। এছাড়া, apply মেথডের মাধ্যমে একটি নতুন এক্সেপশন তৈরি করা হয়েছে যা একটি ডিফল্ট এরর কোড নিয়ে আসে।


৩. এক্সেপশন হ্যান্ডলিং (Exception Handling)

স্কালায় এক্সেপশন হ্যান্ডলিং সাধারণভাবে try, catch, এবং finally ব্লক ব্যবহার করে করা হয়। একটি কাস্টম এক্সেপশন থ্রো করার পর, আপনি সেই এক্সেপশনটি কিপর্যন্ত হ্যান্ডল করবেন তা নির্ধারণ করতে পারেন।

৩.১ এক্সেপশন হ্যান্ডলিং উদাহরণ

// A simple method that may throw a custom exception
def divide(x: Int, y: Int): Int = {
  if (y == 0) {
    throw new ArithmeticException("Cannot divide by zero")
  }
  x / y
}

try {
  val result = divide(10, 0)
  println(s"Result: $result")
} catch {
  case e: ArithmeticException => println(s"Error: ${e.getMessage}")
} finally {
  println("This will always execute, whether an exception was thrown or not.")
}

এখানে, divide মেথডে ArithmeticException কাস্টম এক্সেপশন থ্রো করা হয়েছে এবং তা try-catch ব্লক দিয়ে হ্যান্ডল করা হয়েছে।


সারাংশ

  • কাস্টম এক্সেপশন তৈরি করার জন্য স্কালায় আপনি Exception বা RuntimeException ক্লাসকে ইনহেরিট করে নতুন এক্সেপশন তৈরি করতে পারেন।
  • চেকড এক্সেপশন সাধারণত Exception থেকে ইনহেরিট করা হয় এবং কম্পাইল টাইমে চেক করা হয়, যেখানে আনচেকড এক্সেপশন সাধারণত RuntimeException থেকে ইনহেরিট করা হয় এবং কম্পাইল টাইমে চেক করা হয় না।
  • আপনি কাস্টম এক্সেপশনে কাস্টম কন্সট্রাক্টর, স্ট্যাটিক মেথড, বা অতিরিক্ত তথ্য যেমন errorCode যোগ করতে পারেন।

এই কাস্টম এক্সেপশনগুলির মাধ্যমে আপনি আরো নির্দিষ্ট এবং শক্তিশালী এক্সেপশন হ্যান্ডলিং করতে পারবেন যা আপনার প্রোগ্রামের ত্রুটিগুলি আরো ভালভাবে পরিচালনা করতে সাহায্য করবে।

Content added By

স্কালা প্রোগ্রামিং ভাষায় finally ব্লক হল একটি বিশেষ ব্লক যা try-catch ব্লকের সাথে ব্যবহৃত হয়। finally ব্লকটি সাধারণত আপনার কোডে কিছু পরিস্কারক কাজ করার জন্য ব্যবহার করা হয়, যেমন রিসোর্স বন্ধ করা, ফাইল বন্ধ করা, নেটওয়ার্ক কানেকশন বন্ধ করা ইত্যাদি। finally ব্লকটি যেকোনো অবস্থায় (যতটুকু ধরুন, কোনও এক্সসেপশন ছুড়ে দেওয়া হলেও) অবশ্যই চলবে। অর্থাৎ, যদি কোনো এক্সসেপশন ধরা না-ও পড়ে, তবুও finally ব্লকটি সম্পাদিত হবে।


১. try-catch-finally ব্লক

স্কালায় try-catch-finally ব্লক ব্যবহৃত হয় exception handling-এর জন্য। এখানে finally ব্লকটি অবশ্যই এক্সসেপশন ঘটুক বা না ঘটুক, সর্বশেষে চালানো হয়।

উদাহরণ:

object FinallyExample {
  def main(args: Array[String]): Unit = {
    try {
      println("Inside try block")
      // Let's throw an exception
      val result = 10 / 0  // Division by zero will throw an exception
    } catch {
      case e: ArithmeticException => println("Caught an arithmetic exception!")
    } finally {
      println("This is the finally block. It always runs.")
    }
  }
}

এখানে:

  • try ব্লকটি কোডের সেই অংশ যা এক্সসেপশন ঘটতে পারে এমন কোড ধারণ করে। এখানে আমরা division by zero সমস্যা ঘটাচ্ছি।
  • catch ব্লকটি এক্সসেপশন ধরা এবং তার সাথে সম্পর্কিত কোড সম্পাদন করে। এখানে ArithmeticException ধরা হচ্ছে।
  • finally ব্লকটি যেকোনো অবস্থায় চলবে, অর্থাৎ এক্সসেপশন ঘটুক বা না ঘটুক। এই ব্লকটি সাধারণত রিসোর্স পরিস্কার করার জন্য ব্যবহৃত হয় (যেমন ফাইল বা ডাটাবেস কানেকশন বন্ধ করা)।

এখানে আউটপুট হবে:

Inside try block
Caught an arithmetic exception!
This is the finally block. It always runs.

২. finally ব্লক এবং রিসোর্স ক্লিনআপ

finally ব্লক সাধারণত রিসোর্স ক্লিনআপ করার জন্য ব্যবহৃত হয়, যেমন ফাইল, ডাটাবেস কানেকশন বা নেটওয়ার্ক কানেকশন বন্ধ করা।

উদাহরণ: ফাইল ক্লোজিং

import java.io._

object FileCleanupExample {
  def main(args: Array[String]): Unit = {
    val file = new File("sample.txt")
    val writer = new PrintWriter(file)

    try {
      writer.write("Hello, Scala!")
    } catch {
      case e: Exception => println(s"An error occurred: ${e.getMessage}")
    } finally {
      writer.close()  // Ensure the file is always closed
      println("File has been closed.")
    }
  }
}

এখানে:

  • try ব্লকে ফাইল লিখতে চেষ্টা করা হচ্ছে।
  • যদি কোনো এক্সসেপশন ঘটে (যেমন ফাইল লিখতে না পারলে), তাহলে catch ব্লক এক্সসেপশন ধরবে।
  • finally ব্লকে writer.close() ব্যবহৃত হচ্ছে যা নিশ্চিত করবে যে ফাইলটি বন্ধ হয়ে যাবে, এক্সসেপশন ঘটুক বা না ঘটুক।

৩. finally ব্লক এবং রিটার্ন স্টেটমেন্ট

একটি গুরুত্বপূর্ণ বিষয় হচ্ছে, finally ব্লকটি যখন রিটার্ন স্টেটমেন্টের সাথে ব্যবহৃত হয়, তখন finally ব্লকের কোড প্রথমে চালানো হয়, এবং এরপর রিটার্নের মান চলে আসে।

উদাহরণ:

object FinallyReturnExample {
  def testMethod(): Int = {
    try {
      println("Inside try block")
      return 10
    } catch {
      case e: Exception => println("Caught an exception")
    } finally {
      println("This is the finally block.")
      // Even if we return from the try block, finally will run
    }
  }

  def main(args: Array[String]): Unit = {
    val result = testMethod()
    println(s"Returned value: $result")
  }
}

এখানে:

  • testMethod() মেথডে আমরা try ব্লকে return 10 ব্যবহার করেছি, কিন্তু finally ব্লকটি তারপরেও চালানো হয়েছে।
  • আউটপুট হবে:
Inside try block
This is the finally block.
Returned value: 10

এখানে, finally ব্লক চলার পরেই রিটার্ন মানটি আসছে, এবং আমরা দেখতে পাচ্ছি যে finally কোডটি কখনোই বাদ যায় না।


৪. finally ব্লক এবং এক্সসেপশন

এক্সসেপশন যদি finally ব্লকেও ঘটতে থাকে, তবে তা try ব্লকের এক্সসেপশনকে ওভাররাইট করতে পারে না, কিন্তু finally ব্লকটি এক্সসেপশন সংক্রান্ত সমস্যার উপরও কাজ করতে পারে।

উদাহরণ: finally ব্লকে এক্সসেপশন

object FinallyExceptionExample {
  def main(args: Array[String]): Unit = {
    try {
      println("Inside try block")
      throw new Exception("An exception occurred in try block")
    } catch {
      case e: Exception => println(s"Exception caught: ${e.getMessage}")
    } finally {
      println("Inside finally block")
      throw new Exception("An exception occurred in finally block")  // This will throw an exception
    }
  }
}

এখানে:

  • try ব্লকে একটি এক্সসেপশন ঘটানো হয়েছে।
  • finally ব্লকে আরেকটি এক্সসেপশন ঘটানো হয়েছে, যা মূল এক্সসেপশনকে ওভাররাইট করবে না। আউটপুট হবে:
Inside try block
Exception caught: An exception occurred in try block
Inside finally block
Exception in thread "main" java.lang.Exception: An exception occurred in finally block

এখানে:

  • প্রথম এক্সসেপশনটি catch ব্লকে ধরা হয়েছে, কিন্তু দ্বিতীয় এক্সসেপশনটি finally ব্লকে ঘটেছে এবং এটি মেইন থ্রেডে চলে গেছে।

সারাংশ

  • finally ব্লক এমন একটি ব্লক যা try-catch ব্লকের পরে চলবে, এবং এটি যেকোনো পরিস্থিতিতে চালিত হয়, এক্সসেপশন ঘটুক বা না ঘটুক।
  • এটি সাধারণত রিসোর্স পরিস্কার বা ফাইল, নেটওয়ার্ক কানেকশন বন্ধ করার জন্য ব্যবহৃত হয়।
  • finally ব্লক ব্যবহারের সময় রিটার্ন স্টেটমেন্টও গুরুত্ব সহকারে পরিচালনা করা হয়, কারণ এটি নিশ্চিত করবে যে finally ব্লক আগে চলবে।
Content added By

এক্সেপশন চেইনিং হল একটি প্রক্রিয়া, যেখানে একটি এক্সেপশন (Exception) অন্য একটি এক্সেপশন দ্বারা ঘিরে বা "চেইন" হয়ে থাকে, অর্থাৎ এক্সেপশন হ্যান্ডলিং প্রক্রিয়াতে একাধিক এক্সেপশন একটি একে অপরকে অনুসরণ করে থাকে। এটি একটি ব্যবহারকারী-সংজ্ঞায়িত অবস্থানগত তথ্য (stack trace) বা কনটেক্সট ইনফরমেশন সহ একটি নতুন এক্সেপশন তৈরি করার জন্য ব্যবহৃত হয়, যা মূল এক্সেপশন (cause) এর কারণে ঘটেছে।

স্কালায় এক্সেপশন চেইনিং করা হয় মূল এক্সেপশন (cause) বা পূর্ববর্তী এক্সেপশনটিকে অন্তর্ভুক্ত করে, যাতে ডিবাগিং বা সমস্যা শনাক্তকরণ সহজ হয়।

১. এক্সেপশন চেইনিং কিভাবে কাজ করে?

একটি এক্সেপশনকে Throwable (যেমন, Exception, Error) হিসেবে চেইন করা হয়। যখন একটি নতুন এক্সেপশন তৈরি করা হয়, তখন আপনি পুরোনো এক্সেপশনটি cause হিসেবে প্রদান করতে পারেন।

স্কালায় এক্সেপশন চেইনিং করার জন্য আপনি throw কিওয়ার্ডের সাথে cause আর্গুমেন্ট ব্যবহার করতে পারেন। এটা পূর্ববর্তী এক্সেপশনটি নতুন এক্সেপশনের "কারণ" হিসেবে পাঠায়।


২. এক্সেপশন চেইনিং উদাহরণ

ধরা যাক, আমরা একটি ফাংশন লিখছি যা একটি নম্বরের ডিভাইডার হিসেবে কাজ করবে এবং তাতে কোনো এক্সেপশন ঘটলে সেই এক্সেপশন চেইন করা হবে।

object ExceptionChainingExample {
  def divide(x: Int, y: Int): Int = {
    if (y == 0) {
      throw new ArithmeticException("Division by zero")
    } else {
      x / y
    }
  }

  def calculate(x: Int, y: Int): Int = {
    try {
      divide(x, y)
    } catch {
      case e: ArithmeticException =>
        throw new Exception("Failed to calculate division", e)  // Chaining exception
    }
  }

  def main(args: Array[String]): Unit = {
    try {
      calculate(10, 0)
    } catch {
      case e: Exception =>
        println(s"Caught exception: ${e.getMessage}")
        println(s"Caused by: ${e.getCause.getMessage}")
    }
  }
}

এখানে:

  • divide ফাংশন: দুইটি সংখ্যা দিয়ে ডিভিশন করার চেষ্টা করে, তবে যদি y == 0 হয়, তাহলে ArithmeticException ছুড়ে ফেলা হয়।
  • calculate ফাংশন: divide ফাংশনটি কল করে এবং যদি কোনো এক্সেপশন ঘটে, তবে সেটিকে চেইন করে একটি নতুন এক্সেপশন (এটি Exception টাইপ) তৈরি করা হয়।
  • new Exception("Failed to calculate division", e): এখানে e হল পূর্ববর্তী এক্সেপশন (যেটি ArithmeticException), যা নতুন এক্সেপশনের কারণে হিসেবে চেইন করা হয়।

আউটপুট:

Caught exception: Failed to calculate division
Caused by: Division by zero

এখানে:

  • প্রথমে ArithmeticException ঘটছে, এবং সেটি নতুন Exception এর সাথে চেইন হয়ে যাচ্ছে। যখন সেই এক্সেপশনটি ক্যাচ করা হয়, তখন পূর্ববর্তী এক্সেপশনের তথ্য (যেমন, "Division by zero") পাওয়া যায়।

৩. এক্সেপশন চেইনিং এর সুবিধা

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

৪. এক্সেপশন চেইনিংয়ের সঠিক ব্যবহার

স্কালায় এক্সেপশন চেইনিং করার সময় কিছু মূল বিষয় মনে রাখা গুরুত্বপূর্ণ:

  1. getCause ব্যবহার করা:
    যখন আপনি নতুন এক্সেপশন তৈরি করেন এবং পূর্ববর্তী এক্সেপশন চেইন করেন, তখন getCause মেথড ব্যবহার করে আপনি মূল এক্সেপশনের তথ্য পেতে পারেন।

    উদাহরণ:

    val ex = new Exception("New exception", new ArithmeticException("Previous exception"))
    println(ex.getCause.getMessage)  // Output: Previous exception
  2. Throwable এবং Exception কাস্টমাইজেশন:
    যদি আপনি কাস্টম এক্সেপশন তৈরি করতে চান, তবে Throwable বা Exception ক্লাসের জন্য কাস্টম কন্সট্রাক্টর তৈরি করতে পারেন যা পূর্ববর্তী এক্সেপশনটিকে cause হিসেবে গ্রহণ করবে।

    উদাহরণ:

    class CustomException(message: String, cause: Throwable) extends Exception(message, cause)
    
    throw new CustomException("Something went wrong", new ArithmeticException("Division by zero"))

সারাংশ

  • এক্সেপশন চেইনিং স্কালায় এমন একটি প্রক্রিয়া যেখানে একটি এক্সেপশন আরেকটি এক্সেপশনের কারণে ঘটে এবং এই এক্সেপশন দুটি একে অপরের সাথে যুক্ত থাকে।
  • স্কালায় এক্সেপশন চেইনিং করতে, আপনি Exception অথবা Throwable কন্সট্রাক্টর ব্যবহার করে পূর্ববর্তী এক্সেপশনকে cause হিসেবে পাঠাতে পারেন।
  • এক্সেপশন চেইনিংয়ের মাধ্যমে ডিবাগিং এবং এrror ট্র্যাকিং আরও সহজ হয়।

এটি একটি শক্তিশালী কৌশল, যা স্কালায় এক্সেপশন হ্যান্ডলিংকে আরও নমনীয় এবং কার্যকরী করে তোলে।

Content added By
Promotion

Are you sure to start over?

Loading...