[英]In ABAP, what is the equivalent of Java's finally keyword?
在 Java 中, finally
关键字用于执行代码(与异常一起使用 - try..catch
语句),无论是否抛出异常(来源)。
例如:
try {
// this code might throw an exception
riskyCall();
// this code will only run if no exception was thrown above
mainProgram();
}
finally {
// this code will always run
cleanUp();
}
ABAP 中是否有等效的功能? 如果没有,实现相同功能的惯用方式是什么?
我知道 ABAP 有一个CLEANUP
关键字,但这似乎只有在抛出异常时才会执行。
我进行了实验,发现以下可能的解决方案。 不幸的是,我想不出没有代码重复的任何解决方案。
METHOD risky_method.
TRY.
WRITE 'code before...'.
IF lv_error_condition = abap_true.
RAISE EXCEPTION TYPE cx_foo.
ENDIF.
WRITE 'Main program...'.
WRITE 'Cleanup...'.
CLEANUP.
WRITE 'Cleanup...'.
ENDTRY.
ENDMETHOD.
METHOD outer_scope.
TRY.
risky_method( ).
CATCH cx_foo INTO DATA(lx_foo).
WRITE 'Caught the error!'.
ENDTRY.
ENDMETHOD.
对于lv_error_condition
等于abap_false
的情况,执行方法outer_scope
的 output 为:
code before... Main program... Cleanup...
对于lv_error_condition
等于abap_true
的情况,output 是:
code before... Cleanup... Caught the error!
此解决方案的优点是清理始终运行。 它的缺点是需要一些代码重复,因为清理需要编写两次。 如果清理被打包到一个方法中,那么这并不是大量的代码重复。 :-/
ABAP 没有与 Java finally
块完全相同的等价物。
有一个TRY
... CLEANUP
结构乍一看很相似,但实际上工作方式却大不相同:
METHOD buggy_method.
TRY.
WRITE 'code before the error...'.
RAISE EXCEPTION TYPE cx_foo.
WRITE 'This line will not get executed.'.
CLEANUP.
WRITE 'Cleanup...'.
ENDTRY.
ENDMETHOD.
" ...on an outer scope...
TRY.
buggy_method( ).
CATCH cx_foo INTO DATA(lx_foo).
WRITE 'Caught the error!'.
ENDTRY.
输出: code before the error... Cleanup... Caught the error!
然而,清理块并不总是*被执行。 它仅在出现异常时执行,并且该异常未由同一TRY
块中的CATCH
处理。 这个想法是将它用于清理,当异常由外部级别的TRY
块处理时应该发生。 因此,无论您是否有错误,它对于您想要运行的代码都没有用。 它仅对您要在 try 块无法自行处理的错误的情况下运行的代码有用。
涵盖 Java finally
块的一些用例的另一个特性是可恢复异常:
" In the class definiton
METHODS buggy_method RAISING RESUMABLE(cx_foo).
" In the class implementation:
METHOD buggy_method.
WRITE 'code before the error...'.
RAISE RESUMABLE EXCEPTION TYPE cx_foo.
WRITE 'code after the error....'.
ENDMETHOD.
" Somewhere else:
TRY.
buggy_method( ).
CATCH BEFORE UNWIND cx_foo INTO DATA(lx_foo).
WRITE 'Caught the error!'.
RESUME.
ENDTRY.
输出: code before the error... Caught the error! code after the error....
code before the error... Caught the error! code after the error....
CATCH
块末尾的RESUME
关键字导致在异常为RAISE RESUMABLE
d 后立即继续执行。 因此,当您想确保即使在发生错误的情况下也能执行方法的结尾时,这可能就是您正在寻找的语法。
* 是的,我知道有一些奇特的边缘情况,其中 Java 中的 finally 块没有被执行。 这些在这里无关紧要。
一位同事给了我解决方案。 避免代码重复的技巧,同时仍然允许异常向上传播,是根本不使用CLEANUP
关键字,而是:
CX_ROOT
(捕获所有可能的异常,而不仅仅是您期望的异常!)finally
风格的清理代码IS BOUND
查看是否引发异常,如果是,则重新引发下面是一个例子:
METHOD risky_method.
TRY.
WRITE 'code before...'.
IF lv_error_condition = abap_true.
RAISE EXCEPTION TYPE cx_foo.
ENDIF.
WRITE 'Main program...'.
CATCH cx_root INTO DATA(lx_root).
ENDTRY.
WRITE 'Cleanup...'.
IF lx_root IS BOUND.
RAISE lx_root.
ENDIF.
ENDMETHOD.
METHOD outer_scope.
TRY.
risky_method( ).
CATCH cx_foo INTO DATA(lx_foo).
WRITE 'Caught the error!'.
ENDTRY.
ENDMETHOD.
对于lv_error_condition
等于abap_false
的情况,输出为:
code before... Main program... Cleanup...
对于lv_error_condition
等于abap_true
的情况,输出为:
code before... Cleanup... Caught the error!
据我所知,根本没有真正的等价物。 例如,如果 ABAP 知道 finally,我会期望这个
TRY.
RETURN.
FINALLY.
WRITE / 'Finally'.
ENDTRY.
写出“终于”这个词。 ABAP 程序有很多情况,这肯定是有用的。 最常见的入队之一需要相应的出队,但它也可以是打开/关闭数据集对。
此代码仅输出“尝试”。
尝试。 写/“尝试”。 返回。 WRITE /'返回后'。 清理。 写/'清理'。 结束。 写/'尝试后'。
因此,如果您想运行该清理代码,您将被迫离开您的例程。 或者您编写冗余代码:
OPEN DATASET iv_file IN TEXT MODE ENCODING UTF-8.
TRY.
" ... write something to file
IF do_more IS INITIAL.
CLOSE DATASET iv_file.
RETURN.
ENDIF.
" ... write more to file ...
CLEANUP.
CLOSE DATASET iv_file.
ENDTRY.
CLOSE DATASET iv_file.
解决方案通常是以这样的形式编写冗余代码。 但是,假设这会在将数据写入文件时使事物入队和出队。 然后,您可能必须在某些点调用出列和关闭数据集,或者仅在另一点调用关闭数据集。 如果它发生变化,将其放入单独的方法或表单例程中并不好。
我最初来自帕斯卡方面(从学生时代)并最终在那里学习。 它经常被使用,因为基于 pascal 的语言不使用垃圾收集器,当你不再需要它时,你总是必须确保自己释放 object。 所以那里的免费意味着总是运行(当然只要程序仍然运行)。 你宁愿不用担心那里关闭文件之类的事情,因为 <ou 完成后立即释放它,析构函数将在 Free 上调用并为你完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.