如何在Scala中創建自定義異常並將其延伸到Exception
類中,並在發生異常時將其拋出並捕獲它們。scala中的自定義異常
例如在Java中:
class CustomeException extends Exception {
public final static String _FAIL_TO_INSERT = "FAIL_TO_INSERT";
}
如何在Scala中創建自定義異常並將其延伸到Exception
類中,並在發生異常時將其拋出並捕獲它們。scala中的自定義異常
例如在Java中:
class CustomeException extends Exception {
public final static String _FAIL_TO_INSERT = "FAIL_TO_INSERT";
}
final case class CustomException(private val message: String = "",
private val cause: Throwable = None.orNull)
extends Exception(message, cause)
剛剛嘗試捕獲:
try {
throw new CustomException("optional")
} catch {
case c: CustomException =>
c.printStackTrace
}
你這樣定義
case class CustomException(s: String) extends Exception(s)
您的自定義異常,你可以把你的例外,像這個:
try{
...
} catch{
case x:Exception => throw new CustomException("whatever")
}
您可能希望創建一個密封的特點:
sealed trait MyException {
self: Throwable => //This is called self annotations and you can use "self" or "dog" or whatever you want, it requires from those who extend this trait, to also extend a Throwable or a subclass of it.
val: message: String
val: details: JsValue
}
然後你可以有很多case class
ES,因爲你需要延長不僅Exception
但你的新特點。
case class CustomeException(message: String) extends Exception(message) with MyException {
override val details: JsValue = Json.obj("message" -> message, "etc" -> "Anything else")
}
現在,使用Scala是朝着一個功能更強大的編程風格走的整點,它會使你的應用程序更多的併發,所以如果你需要使用新的自定義異常,你可能想嘗試像這樣的:
def myExampleMethod(s: Option[String]): Future[Boolean] = {
Try(
s match {
case Some(text) =>
text.lenght compareTo 5 match {
case 1 => true
case _ => false
}
case _ => throw CustomeException("Was expecting some txt")
}
)
match {
case Success(bool) => Future.success(bool)
case Failure(e) => Future.failed(e)
}
它不必被密封,但是如果您需要模式匹配例外,它可以幫助編譯器。我喜歡這個答案,因爲這個特質本身沒有擴展這個例外,但需要那些使用特質的人來擴展它。這樣做的好處是,因爲scala需要使用特定的構造函數進行擴展,所以對於這種解決方案,您並不僅僅是一個異常所具有的構造函數之一。 – caeus
我認爲在'val:'中有一個不必要的':'有一個錯字。我無法編輯問題,因爲顯然_建議的編輯隊列已滿。 – botchniaque
爲了反映所有從Exception我會實現與下面的模式自定義異常的原始構造函數:
class CustomException(msg: String) extends Exception(msg) {
def this(msg: String, cause: Throwable) = {
this(msg)
initCause(cause)
}
def this(cause: Throwable) = {
this(Option(cause).map(_.toString).orNull)
initCause(cause)
}
def this() = {
this(null: String)
}
}
這可以也可以在前面的答案中提到的特質來實現。在這種情況下,我只是不創建單獨的類:
trait SomeException { self: Throwable =>
def someDetail: SomeDetail
}
然後,投擲時:
throw new Exception(...) with SomeException {
override val someDetail = ...
}
和匹配時:
try {
...
} catch {
case ex: Throwable with SomeException =>
ex.getCause
ex.getMessage
ex.someDetail
}
這裏的好處是,你是不是堅持父異常的任何特定構造函數。
或多或少的東西。
感謝Jacek的幫助。 – Nilesh
class MyException(message: String) extends Exception(message) {
def this(message: String, cause: Throwable) {
this(message)
initCause(cause)
}
def this(cause: Throwable) {
this(Option(cause).map(_.toString).orNull, cause)
}
def this() {
this(null: String)
}
}
這與@Jacek L.的答案几乎相同。我只是想爲這個答案背後的動機增加更多的意見。
爲什麼這麼多構造函數?
Throwable
寫的是一種有趣的方式。它有4個構造函數 - 忽略與boolean
切換的構造函數 - 它們每個與null
的行爲有點不同,並且這些差異只能由多個構造函數維護。
它會被清潔了一下,如果斯卡拉將允許通過super
調用父類的構造函數,但它不會:(
爲什麼不案例類?
null
的行爲是不可能的;具體而言,def this()
和def this(message: String)
將不得不將cause
設置爲null
,而最初它被設置爲this
。toString
不會被覆蓋。getMessage
和getCause
公開可用。對這些添加另一個參考是多餘的。equals
將被覆蓋,將表現不同。 new Exception("m") == new Exception("m") // false
new CaseException("m") == new CaseException("m") // true
如果一個期望訪問該消息並通過模式匹配的原因,可以簡單地實現unapply
方法:
object MyException {
def unapply(e: MyException): Option[(String,Throwable)] = Some((e.getMessage, e.getCause))
}
對不起,我沒有意思是降低這一點,我只是想刪除upvote。 – caeus
我實際上避免使用案例類。 'toString'已經實現,而'equals'將被覆蓋,並且行爲與其他異常不同('Exception'使用默認的'Object.equals')。此外,公共訪問消息和原因已經可以通過'getMessage'和'getCause'獲得。如果你想要模式匹配,實現'unapply'方法。 –
異常並非設計爲映射中的關鍵,您爲什麼要比較異常?方法toString返回與Exception相同的結果(你測試了嗎?)。我將改變消息的可見性並導致私密以隱藏細節。 –