public WHATTOWRITEHERE test()
{
try
{
transaction.begin();
code which may trigger exception
transaction.commit();
return true;
}
catch (javax.script.ScriptException ex)
{
transaction.rollback();
return ex.getMessage();
}
}
上面的代码打算执行某些操作,如果可以,则返回true
如果没有(发生错误),则应返回此错误消息string
。它可以用Php但不能用Java
答案 0 :(得分:7)
您无法返回多种类型,但您可以重新设计,因此您不必这样做。一些可能性:
我建议选项1.您已经处理了异常,您可以看到它用于错误处理。没有理由在那里停止它,处理任何局部清理然后让它继续调用。
现在有些匆匆构建了一些例子,我回到键盘上,只是为了说明概念,不是详尽无遗或者必须逐字使用:
清理然后重新抛出:
public boolean test () throws javax.script.ScriptException {
try {
transaction.begin();
...
transaction.commit();
return true;
} catch (javax.script.ScriptException ex) {
transaction.rollback();
throw ex;
}
}
如果需要,清理然后重新抛出不同的异常类型:
public boolean test () throws MyGreatException {
try {
transaction.begin();
...
transaction.commit();
return true;
} catch (javax.script.ScriptException ex) {
transaction.rollback();
throw new MyGreatException(ex);
}
}
返回一个提供状态信息的对象(这只是一般概念的一个简单示例):
public class TransactionResult {
private final boolean failed;
private final String reason;
/** Construct a result that represents a successful transaction. */
public TransactionResult () {
failed = false;
reason = null;
}
/** Construct a result that represents a failed transaction with a reason. */
public TransactionResult (String failedReason) {
failed = true;
reason = failedReason;
}
public boolean isFailed () {
return failed;
}
public String getReason () {
return reason;
}
}
然后:
public TransactionResult test () {
TransactionResult result;
try {
transaction.begin();
...
transaction.commit();
result = new TransactionResult();
} catch (javax.script.ScriptException ex) {
transaction.rollback();
result = new TransactionResult(ex.getMessage());
}
return result;
}
等
答案 1 :(得分:3)
不要退货。回滚后只需re-throw the original exception。
public void test()
{
try
{
transaction.begin();
code which may trigger exception
transaction.commit();
}
catch (javax.script.ScriptException ex)
{
transaction.rollback();
throw ex; // re-throw the original exception
}
}
答案 2 :(得分:2)
如果你坚持,你可以返回Object
。在这种情况下,true将被自动装箱到Boolean.TRUE
。这当然不推荐,它会给调用者一些额外的麻烦,弄清楚返回的对象是String
还是Boolean
。更糟糕的是,调用者无法保证返回类型仅限于上述两种类型,但也应考虑到它可能是另一类。
更好的选择取决于具体情况,所以我可能无法告诉你什么是最好的。我想到了一些想法,但请不要不加批判地使用:(1)返回String
,并在成功时返回null
而不是true。 (2)设计自己的归级课程;例如,它可以同时包含布尔值和消息字符串。
答案 3 :(得分:2)
UGLY解决方法但是如果你真的想要这样做,你总是可以定义一个包装状态和错误消息的Helper类,但我更喜欢@JsonC的方法。
// Helper class
class Pair<First,Second>{
private First first;
private Second second;
Pair(First first,Second second){
this.first = first;
this.second = second;
}
public First getFirst(){ return this.first; }
public First getSecond(){ return this.second; }
}
// Function returning two types
public Pair<boolean,String> returnSomething(){
try {
return new Pair<boolean,String>(true,null);
}catch(Exception e){
return new Pair<boolean,String>(false,e.getMessage());
}
}
// Calling this method would look like this
Pair<String,boolean> result = returnSomething();
// Retrieve status
boolean status = result.getFirst();
// Retrieve error message (This is null if an exception was caught!)
String errorMessage = result.getSecond();
答案 4 :(得分:1)
例外不能出去,必须在这里处理。
我必须说这种限制只会使界面更难以使用。假设您要为调用者返回一些内容,以检查此方法中是否发生异常,而调用者无论如何都可以忽略返回的值。所以我想你想给调用者一些灵活性:如果可能的话,他/她不需要为最终结果而烦恼。但是使用异常方法,调用者仍然可以使用空(不推荐)catch子句。
例外是这里最好的方法。除非“外部”是不支持异常的环境。那么你别无选择,只能在Scala中提出类似Try
的内容。
答案 5 :(得分:1)
在您的情况下, 例外应该使用,而不是隐藏。这不是结果,而是一个错误。了解如何在事务中进行异常处理!
函数式编程粉丝将提倡类似Monad的结构,您可以在Java 8的Optional<T>
API中找到。
即。您可以返回Optional<String>
并在成功时将其取消(如果您没有return false
和return true
)。
为了清楚起见,最好使用自定义类来构建类似的东西:
interface Result {}
class BooleanResult implements Result {
boolean result;
public boolean getResult() { return result; }
}
class ErrorResult implements Result {
Exception cause;
public Exception getCause() { return cause; }
}
您可以使用Optional
值模拟null
(如果只有一个布尔结果)。成功后,返回null
。非空值表示错误。
String perform() {
try{
...
return null; // No error
} except(Exception e) { // bad code style
return e.getMessage(); // Pray this is never null
}
}
String err = perform();
if (err != null) { throw up; }
类似的API在旧C库中相当常见。除0之外的任何返回值都是错误代码。成功时,结果将写入方法调用中提供的指针。
您可以使用Object
。
public Object perform() {...}
Object o = perform();
if (o instanceof Boolean) { ...
这是20世纪80年代的编程风格。 这就是PHP所做的,所以它实际上 可能在Java中!它只是坏,因为它不是lpnger类型的安全。这是最糟糕的选择。
我在这个偏好中假设您尝试1.,3.,2.,4.,5。或者更好,只考虑选项1和3。
对于选项1.你真的应该学习如何使用try-with-resources。您的交易 是一种资源。
完成后,您的代码将如下所示:
try(Transaction a = connection.newTransaction()) {
doSomethingThatMayFail(a);
a.commit();
} // No except here, let try handle this properly
如果发生异常,Java将调用a.close()
甚至。然后它将向上抛出异常。酸性事务类应该有这样的代码来处理回滚:
public void close() {
if (!committed) rollback();
}
这是最优雅的和最短的和安全使用方法,因为Java确保调用close()
。 抛出异常,然后正确处理它。你在上面展示的代码是一个反模式,并且已知非常容易出错。
答案 6 :(得分:0)
如果您使用的是Java 8,则可以返回Optional<String>
。然后,如果代码成功,则返回一个空的Optional,如果出现故障,则返回一个可选的包装失败消息。