Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 重构调用引发异常的其他方法的方法_Java_Refactoring - Fatal编程技术网

Java 重构调用引发异常的其他方法的方法

Java 重构调用引发异常的其他方法的方法,java,refactoring,Java,Refactoring,我有几个(超过20个)方法(getXXX())在调用时可能会抛出异常(一个notcalculatedeexception) 在另一种方法中,我需要访问这些方法给出的结果。目前,我有一个可怕的代码,它看起来像: public void myMethod() { StringBuffer sb = new StringBuffer(); // Get 'foo' result... sb.append("foo = "); try { sb.appen

我有几个(超过20个)方法(
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来控制逻辑

但是我有一些想法

  • 你需要另一个getter方法

    sb.追加(这个getFoo(“未计算”)

  • 创建hasValue方法

    sb.append(hasFoo()?this.getFoo():“未计算”)

  • 创建泛型getter方法

    sb.追加(此.getValueByName(“foo”))


  • 是的,我考虑过使用反射,但我真的不喜欢这个解决方案(在这种情况下)…为什么评论反射?这是一个风格问题,还是有一个它不起作用的原因?(我知道我建议使用反射,我承认它不好,但我相信它会起作用)反射很好地表明正在发生非常非常错误的事情。第一个选项看起来非常糟糕,除非Lambdas到达Java。如果您的团队中有代码格式化标准(并且他们可能使用IDE默认值)。反射本身也不错,问题是Java语言没有具有良好语法的强类型化方法(C#中的delegate)。方法不应该像delegate那样。或者,使用bruno的建议,将try/catch移到cover方法中,这看起来更好+1,为了美观起见,没有必要过多地阐述一些东西。IMO,这是个坏主意。不要使用对象,使用存储getFoo()返回的包装器和代码(枚举/整数/布尔值)这表明检索是否顺利。我只使用Object,因为我不知道getFoo或getBar的返回类型是什么。即便如此,为什么要进行向下投票?使用反射方法,您可以使用公共注释标记所有要调用的方法,然后编写一些工具来迭代这些标记的方法,调用它们并捕获t他是例外,有点像