Scala's Try
rất hữu ích. Tôi muốn sử dụng mẫu đó, nhưng đăng nhập tất cả các ngoại lệ. Tôi có thể làm cái này như thế nào?Scala - Thử đăng xuất ngoại lệ
Trả lời
Xác định helper sau:
import scala.util.{Try, Failure}
def LogTry[A](computation: => A): Try[A] = {
Try(computation) recoverWith {
case e: Throwable =>
log(e)
new Failure(e)
}
}
Sau đó, bạn có thể sử dụng nó như là bạn sẽ sử dụng Try
, nhưng bất kỳ ngoại lệ sẽ được đăng nhập thông qua log(e)
.
Sẽ thử. BTW, để phù hợp Hãy thử mã nguồn https://github.com/scala/scala/blob/v2.11.1/src/library/scala/util/Try.scala#L192, không nên chỉ bắt các ngoại lệ phi NonFatal? – SRobertJames
@SRobertJames - Không, bởi vì nó đã chỉ bắt được ngoại lệ NonFatal, do đó, chỉ có những người để phục hồi từ. Trừ khi bạn có nghĩa là: tôi có thể đăng nhập tất cả các ngoại lệ từ Hãy thử _bao gồm những ngoại lệ mà nó không thể bắt_không? Thế thì câu trả lời là không; bạn phải chèn mã đăng nhập tùy chỉnh của riêng mình. –
Giải pháp này sẽ không phát ra quá trình ghi nếu 'Throwable' là! NonFatal. – chaotic3quilibrium
Bạn có thể tinh chỉnh nó thậm chí còn tiếp tục sử dụng ngầm lớp
def someMethod[A](f: => A): Try[A] = Try(f)
implicit class LogTry[A](res: Try[A]) {
def log() = res match {
case Success(s) => println("Success :) " + s); res
case Failure(f) => println("Failure :(" + f); res
}
}
Bây giờ bạn có thể gọi someMethod
và theo yêu cầu kết quả của nó log
như thế này:
scala> someMethod(1/0).log
Failure :(java.lang.ArithmeticException:/by zero
và
scala> someMethod(1).log
Success :) 1
Trong số khóa học println
phương pháp bên trong tiềm ẩn clas s có thể được thay thế bằng bất kỳ đăng nhập nào bạn muốn.
Bạn đã sử dụng thuật ngữ "ngoại lệ" không rõ ràng. (java.lang.)Throwable
là gốc của bất kỳ thứ gì có thể được đặt sau cụm từ throw
. java.lang.Exception
là một trong hai hậu duệ của Throwable
(số khác là java.lang.Error
). Hơn nữa làm cho điều này mơ hồ là java.lang.RuntimeException
, hậu duệ của Exception
, có thể là nơi bạn chủ yếu muốn dành thời gian đăng nhập của mình (trừ khi bạn đang thực hiện khung ứng dụng cấp thấp hơn hoặc triển khai trình điều khiển phần cứng).
Giả sử bạn đang muốn đăng nhập theo nghĩa đen TẤT CẢ các trường hợp của Throwable, sau đó bạn sẽ cần một cái gì đó như thế này (không khuyến khích):
def logAtThrowable(f: => A): Try[A] =
try
Try(f) match {
case failure @ Failure(throwable) =>
log(s"Failure: {throwable.getMessage}")
failure
case success @ _ =>
//uncomment out the next line if you want to also log Success-es
//log(s"Success: {throwable.getMessage}")
success
}
catch throwable: Throwable => {
//!NonFatal pathway
log(s"Failure: {throwable.getMessage}")
throw throwable
}
Các bên ngoài try/catch
là cần thiết để nắm bắt tất cả các Throwable
trường hợp đó được lọc đi bởi scala.util.control.NonFatal
trong khối try
/catch
của Try
.
Điều đó nói rằng ... có quy tắc Java/JVM: bạn nên never define a catch clause at the resolution of Throwable (một lần nữa, trừ khi bạn đang thực hiện khung ứng dụng cấp thấp hơn hoặc triển khai trình điều khiển phần cứng).
Theo ý định của quy tắc này, bạn sẽ cần thu hẹp số Throwable
để bạn chỉ ghi nhật ký phát ra ở cấp độ hạt mịn hơn, nói điều gì đó tinh tế hơn, như java.lang.RuntimeException
. Nếu vậy, các mã sẽ trông như thế này (đề nghị):
def logAtRuntimeException(f: => A): Try[A] =
Try(f) match {
case failure @ Failure(throwable) =>
throwable match {
case runtimeException: RuntimeException =>
log(s"Failure: {runtimeException.getMessage}")
}
failure
case success @ _ =>
success
}
Trong cả hai đoạn mã trên, bạn sẽ nhận thấy rằng tôi đã sử dụng match
như trái ngược với .recoverWith
. Điều này nhằm tạo điều kiện dễ dàng khi thêm lại throw
hoạt động. Nó chỉ ra rằng tất cả các phương pháp trên Try
là chính họ cũng được bao bọc với các khối try
/catch
. Điều này có nghĩa rằng nếu bạn muốn đăng nhập những Throwable
và sau đó tái throw
nó, nếu bạn đang sử dụng một trong những Try
phương pháp như recoverWith
, tái throw
là ngay lập tức recaught và đặt vào một Failure
do đó hoàn toàn phá hoại giá trị của việc tái cố ý throw
.Bằng cách sử dụng match
, lại throw
được đảm bảo thành công vì vẫn còn bên ngoài bất kỳ phương thức nào trong số Try
.
Nếu bạn muốn xem thêm các lỗ thỏ xung quanh khu vực cụ thể này, tôi đã tạo một blog post of my own exploration.
- 1. Scala: Predicate không giữ ngoại lệ
- 2. Các loại ngoại lệ trong Scala
- 3. Ngoại lệ tiêu chuẩn Scala là gì?
- 4. xuất phát từ std :: ngoại lệ
- 5. Khi nào cần đăng nhập ngoại lệ?
- 6. Đăng ký nhà xuất bản ở Scala
- 7. Có `thử ... ngoại trừ Ngoại lệ như e` nắm bắt mọi ngoại lệ có thể?
- 8. Ghi ngoại lệ cụ thể bằng cách thử ... ngoại trừ
- 9. Elmah không đăng nhập ngoại lệ
- 10. Xử lý ngoại lệ ASP.NET/Đăng nhập
- 11. boost :: python Xuất ngoại lệ tùy chỉnh
- 12. Log4Net - Chỉ đăng xuất stacktrace ngoại lệ cho một số tệp nhất định
- 13. Ngoại lệ 4.0 ngoại lệ khi chạy thử nghiệm đơn vị
- 14. Đăng ký Kênh Bot: Ngoại lệ loại 'Microsoft.AppRegPortal.Providers.Graph.GraphException'
- 15. Tùy chỉnh thử/bắt mẫu mã dựa trên ngoại lệ
- 16. Chức năng gọi lại mẫu thử nuốt các ngoại lệ
- 17. Làm thế nào để đăng nhập ngoại lệ trong JavaScript
- 18. một ngoại lệ diễn viên từ xa scala
- 19. Scala - Bắt một ngoại lệ trong một bản đồ
- 20. Rethrow UncaughtExceptionHandler Ngoại lệ sau khi đăng nhập
- 21. Thử lại sau khi ngoại lệ trong Groovy
- 22. Không thử/cuối cùng bỏ qua ngoại lệ?
- 23. Thử/bắt đơn giản không sử dụng ngoại lệ
- 24. Ném ngoại lệ trong khối Thử nghiệm PHP
- 25. Confused về thử/trừ trường hợp ngoại lệ tùy chỉnh
- 26. Mọi ngoại lệ đều có thử bắt buộc không?
- 27. NUnit: thử nghiệm với KHÔNG mong đợi ngoại lệ
- 28. Java - Cách thực hiện Thử của Python Trừ Ngoại lệ
- 29. JAVA + thử bắt (FileNotFoundException e) sẽ bắt (Ngoại lệ e)?
- 30. Hãy thử không bắt ngoại lệ trong chức năng DllImport
Tôi sẽ quay lại và viết câu trả lời chính thức sau. Tuy nhiên, đây là một bài đăng trên blog mà tôi vừa hoàn thành giải quyết vấn đề này (và những người khác có liên quan): http://fromjavatoscala.blogspot.com/2016/09/rethinking-scalautiltry.html – chaotic3quilibrium