我真的很困惑:Java中的标准方法是仅在"异常"条件下抛出异常,而不是使用它们来表示迭代器结束.
示例:Effective Java,第57项("仅针对特殊情况使用例外")和JavaSpecialists新闻通讯162:
流量控制
我们永远不应该导致一个可以预防的例外.我已经看到代码而不是检查边界,假设数据是正确的,然后捕获RuntimeExceptions:
这是一个坏代码的例子(请不要像这样编码):
Run Code Online (Sandbox Code Playgroud)public class Antipattern1 { public static void main(String[] args) { try { int i = 0; while (true) { System.out.println(args[i++]); } } catch (ArrayIndexOutOfBoundsException e) { // we are done } } }
而在Python中使用这个习惯是标准的,例如StopIteration:
例外StopIteration
由迭代器的next()方法引发,表示没有其他值.这是从Exception而不是StandardError派生的,因为这在其正常应用程序中不被视为错误.
为什么它对Java不好但对Python有好处?
在java中,以下哪一种处理可能为空的引用的"接受"方式?请注意,空引用并不总是表示错误...
if (reference == null) {
//create new reference or whatever
}
else {
//do stuff here
}
Run Code Online (Sandbox Code Playgroud)
要么
try {
//do stuff here
}
catch (NullPointerException e) {
//create new reference or whatever
}
Run Code Online (Sandbox Code Playgroud) 我有一个公共构造函数,它接受一个参数(int age)来创建一个对象.我想检查传递的参数是否合法,例如年龄不能为负.如果它是非法的,那么就不要创建对象/实例.如果合法,没问题.
我只能想到一种方法 -
使构造函数私有化.使用参数(int age)创建一个静态方法来执行所有检查,如果传递非法值,则返回null.如果您传递合法值,则创建一个对象并返回其引用.这样做还有其他办法吗?也许来自构造函数本身?
编辑: 我想到了上述方法的一个问题.出于显而易见的原因,工厂方法/对象创建器方法只能是静态方法.如果工厂方法必须访问成员变量(进行一些检查)来创建对象,会发生什么?然后,我们将被迫使该成员变量静态.在所有情况下这可能都不合适.
是否有意义 ?
我有一个具有以下签名的方法:
public Optional<String> doSomething() {
...
}
Run Code Online (Sandbox Code Playgroud)
如果我得到一个空的,Optional我想重试这个方法,只有在 3 次后才返回空的Optional。
我查看并找到了Retryablespring 注释,但它似乎只适用于异常。
如果可能的话,我想为此使用一个库,并避免:
这假设我们不调用.printstacktrace方法 - 只是抛出和捕获.
我们正在考虑这种性能瓶颈.
如果声明,我们目前有以下化合物......
if ((billingRemoteService == null)
|| billingRemoteService.getServiceHeader() == null
|| !"00".equals(billingRemoteService.getServiceHeader().getStatusCode())
|| (billingRemoteService.getServiceBody() == null)
|| (billingRemoteService.getServiceBody().getServiceResponse() == null)
|| (billingRemoteService.getServiceBody().getServiceResponse().getCustomersList() == null)
|| (billingRemoteService.getServiceBody().getServiceResponse().getCustomersList().getCustomersList() == null)
|| (billingRemoteService.getServiceBody().getServiceResponse().getCustomersList().getCustomersList().get(0) == null)
|| (billingRemoteService.getServiceBody().getServiceResponse().getCustomersList().getCustomersList().get(0).getBillAccountInfo() == null)
|| (billingRemoteService.getServiceBody().getServiceResponse().getCustomersList().getCustomersList().get(0).getBillAccountInfo().getEcpdId() == null)) {
throw new WebservicesException("Failed to get information for Account Number " + accountNo);
}
return billingRemoteService.getServiceBody().getServiceResponse().getCustomersList().getCustomersList().get(0);
Run Code Online (Sandbox Code Playgroud)
这不能简化为......
try {
//Check to be sure there is an EpcdId.
(billingRemoteService.getServiceBody().getServiceResponse().getCustomersList().getCustomersList().get(0).getBillAccountInfo().getEcpdId();
return billingRemoteService.getServiceBody().getServiceResponse().getCustomersList().getCustomersList().get(0);
} catch (NullPointerException npe) {
throw new WebservicesException("Failed to get information …Run Code Online (Sandbox Code Playgroud) 我有一个Factory方法,它从ID调用返回一个对象.
模拟代码:
public static Object getById(String id) {
Object o = CRUD.doRecovery(Class, id);
if(o == null) {
printLogMessage("recovery by ID returned Null: " + id);
// would really like to show only a few lines of stack trace.
}
return o;
}
Run Code Online (Sandbox Code Playgroud)
如何只显示堆栈跟踪的前N行(所以我知道方法的调用者)而不将整个堆栈跟踪转储到日志上或者必须依赖外部库?
确保两个选项之间执行的时间更短的成本:
A:
if(something!=null){
...
}else{
//log
}
Run Code Online (Sandbox Code Playgroud)
要么:
B:
try{
something.getField();...
}catch(Exception e){
//log
}
Run Code Online (Sandbox Code Playgroud) 我总是在错误的背景下看到Throwable/Exception.但是我可以想到扩展一个Throwablejust来打破一堆递归方法调用会非常好的情况.比如说,您试图通过递归搜索的方式在树中查找并返回一些对象.一旦你发现它粘在一些Carrier extends Throwable并抛出它,并在调用递归方法的方法中捕获它.
正面:您不必担心递归调用的返回逻辑; 既然你找到了你需要的东西,为什么还要担心如何将这个引用备份到方法堆栈中.
否定:您有一个不需要的堆栈跟踪.该try/catch块也变得违反直觉.
这是一个愚蠢的简单用法:
public class ThrowableDriver {
public static void main(String[] args) {
ThrowableTester tt = new ThrowableTester();
try {
tt.rec();
} catch (TestThrowable e) {
System.out.print("All good\n");
}
}
}
public class TestThrowable extends Throwable {
}
public class ThrowableTester {
int i=0;
void rec() throws TestThrowable {
if(i == 10) throw new TestThrowable();
i++;
rec();
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,是否有更好的方法来达到同样的目的?另外,以这种方式做事有什么不妥之处吗?
可以通过__LINE__Ruby或Perl 获取当前行号.例如:
print "filename: #{__FILE__}, line: #{__LINE__}"
Run Code Online (Sandbox Code Playgroud)
Groovy中是否有相同的功能?
java ×9
exception ×4
coding-style ×1
groovy ×1
if-statement ×1
jvm ×1
performance ×1
python ×1
spring ×1
spring-retry ×1
stack ×1
stack-trace ×1
throw ×1
throwable ×1
try-catch ×1