Java 重构调用引发异常的其他方法的方法
我有几个(超过20个)方法(Java 重构调用引发异常的其他方法的方法,java,refactoring,Java,Refactoring,我有几个(超过20个)方法(getXXX())在调用时可能会抛出异常(一个notcalculatedeexception) 在另一种方法中,我需要访问这些方法给出的结果。目前,我有一个可怕的代码,它看起来像: public void myMethod() { StringBuffer sb = new StringBuffer(); // Get 'foo' result... sb.append("foo = "); try { sb.appen
getXXX()
)在调用时可能会抛出异常(一个notcalculatedeexception
)
在另一种方法中,我需要访问这些方法给出的结果。目前,我有一个可怕的代码,它看起来像:
public void myMethod() {
StringBuffer sb = new StringBuffer();
// Get 'foo' result...
sb.append("foo = ");
try {
sb.append(getFoo());
} catch (NotCalculatedException nce) {
sb.append("not calculated.");
}
// Get 'bar' result...
sb.append("\nbar = ");
try {
sb.append(getBar());
} catch (NotCalculatedException nce) {
sb.append("not calculated.");
}
...
}
在不修改getXXX
方法的情况下(因此它们必须保持抛出的NotCalculatedException
),如何重构/简化myMethod()
,使其看起来更好
请注意,此项目仍在使用Java 1.4:(
编辑 我无法将所有
getXXX()
方法放入try{…}
块中,因为如果一个方法抛出NotCalculatedException
,StringBuffer将不完整
public void myMethod() {
StringBuffer sb = new StringBuffer();
try {
sb.append("foo = ");
sb.append(getFoo());
sb.append("\nbar = ");
sb.append(getBar());
} catch (NotCalculatedException nce) {
sb.append("not calculated.");
}
...
}
换句话说,如果getFoo()
抛出一个notcalculatedeexception
,我希望有这种输出:
foo = not calculated
bar = xxx
...
如果我将所有内容放在一个try{…}
中,我将得到我不想得到的输出:
foo = not calculated
你可以将“foo”、“bar”等存储在一个数组中。围绕它们循环,打印每一个,然后使用反射来查找/调用相应的getFoo(),getBar()。我承认这不好
有关详细信息,请参见对象
编辑:或者,使用包围该对象的每个getXXX()方法调用并捕获异常。对于每个
getXXX
可以添加一个getxxordefault()
来包装异常,并返回getXXX
或“未计算”的值
appendThing(sb, "foo = ", new GetValue() { public Object get() {
return getFoo();
}});
appendThing(sb, "bar = ", new GetValue() { public Object get() {
return getBar();
}});
或者…使用反射
public Object getValueOrDefault(String methodName) {
try {
// 1 . Find methodName
// 2 . Invoke methodName
} catch() {
return "not calculated.";
}
}
但是我想我还是更喜欢第一个选项。您可以使用Execute-Around习惯用法。不幸的是,Java语法很冗长,所以在简单的情况下,这并不是一个很好的选择。假设
NotCalculatedException
是一个不可更改的例外
appendThing(sb, "foo = ", new GetValue() { public Object get() {
return getFoo();
}});
appendThing(sb, "bar = ", new GetValue() { public Object get() {
return getBar();
}});
另一种丑陋的方法是将循环和开关结合起来:
int property = 0;
lp: for (;;) {
String name = null; // Ugh.
try {
final Object value;
switch (property) {
case 0: name= "foo"; value = getFoo(); break;
case 1: name= "bar"; value = getBar(); break;
default: break lp;
}
++property;
sb.append(name).append(" = ").append(value).append('\n');
} catch (NotCalculatedException exc) {
sb.append(name).append(" = ").append("not calculated.\n");
}
}
或者,每个参数都有一个枚举和一个开关。只是不要使用反射!我的建议是更多的代码,但提高了myMethod的可读性:
public void myMethod() {
StringBuilder resultBilder = new StringBuilder();
resultBuilder.append("foo=");
appendFooResult(resultBuilder);
resultBuilder.append("\nbar=");
appendBarResult(resultBuilder);
...
}
private void appendFooResult(StringBuilder builder) {
String fooResult = null;
try {
fooResult = getFoo();
} catch (NotCalculatedException nce) {
fooResult = "not calculated.";
}
builder.append(fooResult);
}
private void appendBarResult(StringBuilder builder) {
String barResult = null;
try {
barResult = getBar();
} catch (NotCalculatedException nce) {
barResult = "not calculated.";
}
builder.append(barResult);
}
似乎Java没有像C#那样的开箱即用的委托,但Google向我展示了这一点
public static PrintProperty(JavaDelegateWithAName del, StringBuilder collector)
{
try
{
collector.append( del.Name+ " = " );
collector.append( del.Target.Invoke() );
}
catch(NotCalculatedException nce)
{ collector.append("NotCalculated"); }
}
…主要
foreach(JavaDelegateWithAName entry in collectionOfNamedJavaDelegates)
SomeUtilityClass.PrintProperty(entry, sb);
我认为您应该让代码保持原样。它很详细,但很容易判断它的功能,并且它的行为正确。我认为您不应该使用NotCalculatedException来控制逻辑 但是我有一些想法
是的,我考虑过使用反射,但我真的不喜欢这个解决方案(在这种情况下)…为什么评论反射?这是一个风格问题,还是有一个它不起作用的原因?(我知道我建议使用反射,我承认它不好,但我相信它会起作用)反射很好地表明正在发生非常非常错误的事情。第一个选项看起来非常糟糕,除非Lambdas到达Java。如果您的团队中有代码格式化标准(并且他们可能使用IDE默认值)。反射本身也不错,问题是Java语言没有具有良好语法的强类型化方法(C#中的delegate)。方法不应该像delegate那样。或者,使用bruno的建议,将try/catch移到cover方法中,这看起来更好+1,为了美观起见,没有必要过多地阐述一些东西。IMO,这是个坏主意。不要使用对象,使用存储getFoo()返回的包装器和代码(枚举/整数/布尔值)这表明检索是否顺利。我只使用Object,因为我不知道getFoo或getBar的返回类型是什么。即便如此,为什么要进行向下投票?使用反射方法,您可以使用公共注释标记所有要调用的方法,然后编写一些工具来迭代这些标记的方法,调用它们并捕获t他是例外,有点像