如何在catch块中重复代码?

mri*_*z_p 34 java

我现在很难不在我正在研究的Java程序中重复自己.

说,我需要声明很多基本上按以下方式构造的方法:

public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
    EntityManager em = this.createEntityManager();

    EntityTransaction tx = null;
    try {

        /*
         * ... independent logic ...
         */

        tx = em.getTransaction();
    } catch (RuntimeException e) {
        if (tx != null && tx.isActive()) { 
            tx.rollback();
        }
        throw e;
    } finally {
        em.close();
    }

    return something;
}
Run Code Online (Sandbox Code Playgroud)

所有方法的方法体都需要包含用于资源管理的元素.

"独立逻辑"本身也会相当复杂,因此将try/catch语句放在一个单独的方法中并不会真正起作用.

我想避免重复此代码.在这些情况下应用哪些最佳实践?

nos*_*nos 35

创建一个界面:

public interface EntityManagerAction {
   public void execute(EntityManager em);
}
Run Code Online (Sandbox Code Playgroud)

和实用类:

public class EntityUtil {
  public static void executeWithEntityManager(EntityManagerAction action) {
    EntityManager em = someHowCreateEntityManager();

    EntityTransaction tx = null;
    try {
        action.execute(em);
        tx = em.getTransaction();
    } catch (RuntimeException e) {
        if (tx != null && tx.isActive()) { 
            tx.rollback();
        }
        throw e;
    } finally {
        em.close();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以在EntityUtil类中重复使用样板,并且您的代码变为:

public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
   Something something; 
   EntityUtil.executeWithEntityManager(new EntityManagerAction() {
        public void execute(EntityManager em ) {

        /*
         * ... independent logic ...
         */
         //use the passed in 'em' here.
        }
    });

    return something;
}
Run Code Online (Sandbox Code Playgroud)

另请参阅什么是"执行"成语?

  • 是的 - 情况确实如此 - 尽管该部分是原始代码的逐字记录 - 因此OP必须将其构建为实际需要的内容. (5认同)
  • OK-one glaring issue ...当发生任何异常时,tx将如何变为NULL?可能发生异常的最后一个地方是assignemnt em.getTransaction()如果抛出,em仍为null,如果不是你的try-block结束了o_O (2认同)

eth*_*far 8

如果所有finally子句都用于关闭Streams等(实现的任何东西AutoCloseable),则可以使用try-with-resources(如其中一条注释中所建议的)来删除该finally子句.

但是,如果您需要更通用的解决方案,并且Exceptionfinally子句中捕获了相同类型的s和相同类型的处理,则可以创建一个抽象类,例如:

abstract class SensitiveBlockHandler {
    public void handle() {
        try {
            doHandling();
        } catch (SomeException | AnotherException e) {
            // TODO: handle exceptions here ...
        } finally {
            // TODO: cleanup here ...
        }
    }

    protected abstract void doHandling();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建内部类来处理不同的情况,或者作为匿名类.代码应该类似于:

public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
    new SensitiveBlockHandler() {
        protected void doHandling() {
            /*
             * ... independent logic ...
             */
        }
    }.handle();

    return something;
}
Run Code Online (Sandbox Code Playgroud)