[英]local variable cannot be defined as final due to catching exception while initializing it
I usually like to declare my local variables as final but I see repeating patterns where I cannot do this when I have to handle an exception during its initialization. 我通常喜欢将局部变量声明为final,但是我看到重复的模式,当我必须在初始化期间处理异常时无法执行此操作。
For ex I have this code: 对于前我有这段代码:
final Client myClient = library.getClient("service");
//do a bunch of steps with myClient
But I end up modifying it very often like this: 但是我最终经常像这样修改它:
Client myClient = null;
try {
myClient = library.getClient("service");
} catch (someException ex) {
// handle
throw ex;
}
// do stuff with myClient
I do not want to add the catch after I do all the stuff as it becomes a bit unreadable as it is towards the end. 在我完成所有工作之后,我不想添加捕获,因为随着即将结束,它变得有点难以理解。 So is there a better way to do this?
那么,有没有更好的方法呢?
You can put the try/catch in a separate method: 您可以将try / catch放在单独的方法中:
. . .
final Client myClient = getClient();
private Client getClient() {
try {
return library.getClient("service");
catch (someException ex) {
// handle
return null;
}
}
If it doesn't make sense for the processing to continue in the method that calls getClient()
, then the other option is to declare it to throw the exception and get rid of the try/catch block. 如果在调用
getClient()
的方法中继续进行处理没有意义,那么另一种选择是声明它引发异常并摆脱try / catch块。
Put the code in the constructor: 将代码放入构造函数中:
final Client myClient;
public MyClass() throws SomeException {
myClient = library.getClient("service");
}
For that particular case, you can use a blank final : 对于特定情况,您可以使用空白的final :
final Client myClient; // Note the lack of initialization here!
try {
myClient = library.getClient("service");
} catch (someException ex) {
// handle
throw ex;
}
// do stuff with myClient
You don't have to initialize a final variable when you declare it, as long as it's initialized exactly once on each code path where it might end up being used. 您不必在声明最终变量时就对其进行初始化,只要在可能最终使用它的每个代码路径上对它进行了一次初始化即可。
This only works if your catch
block terminates the method (via return
or another throw
) — you can't assign some other fallback value to myClient
, because it might've been assigned in the try
block already, violating the single-initialization rule. 仅当
catch
块终止该方法(通过return
或另一个throw
)时,此方法才有效-您无法将其他后备值分配给myClient
,因为它可能已经在try
块中分配了,这违反了单一初始化规则。
Blank finals are also useful for initializing something in different ways depending on a condition: 空白的final还可用于根据条件以不同的方式初始化某些东西:
final Client myClient;
if (someCondition) {
myClient = foo();
}
else {
myClient = bar();
}
// do stuff with myClient
Sure, there are at least two trivial options: 当然,至少有两个简单的选择:
RuntimeException
s and decide when/if you want to handle it. RuntimeException
并确定何时/是否要处理它。 Both have advantages and disadvantages. 两者都有优点和缺点。
you could split the different parts of your code in methods and hand over the myClient as a final var... you could also add all the code in one try an catch block and throw and handle different exceptions. 您可以在方法中拆分代码的不同部分,并将myClient作为最终变量移交...您还可以将所有代码添加到一个try catch块中,并抛出并处理不同的异常。 this is just possible, if you do not need the var in the exception-part... global vars could be also a solution, but not a nice one... there is a ground role.
如果您不需要在异常部分使用var,这是有可能的...全局vars也可以是一种解决方案,但不是一个很好的解决方案。 if you can't read your code, split it in methods and classes
如果无法阅读代码,则将其拆分为方法和类
As an alternative to wrapping the getClient
code (mentioned elsewhere), you can wrap the doStuff
code: 作为包装
getClient
代码(在其他地方提到)的替代方法,可以包装doStuff
代码:
try {
doStuff( library.getClient("service") );
} catch (someException ex) {
// handle
throw ex;
}
public void doStuff(final Client myClient) {
// do stuff
}
Or you could combine both approaches: 或者,您可以将两种方法结合起来:
try {
doStuff( getClient() );
} catch (someException ex) {
// handle
throw ex;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.