Java - 开发人员实例化对象时自动添加方法调用

时间:2017-07-11 13:20:50

标签: java method-call try-with-resources

我想知道开发人员是否有可能编写一个类,以便当其他开发人员实例化上述类的对象时,对类的特定方法的调用会被添加到他的代码中。

让我更具体一点。假设我创建了一个名为A的类,其结构如下:

public class A {

    public A() {
        // Some instantiations
    }

    // Code class

    // Method that always should be added
    public void method() {
        // Code
    }
}

我将此类包装到一个包中,其他一些开发人员在一个新对象中实例化类A。当他这样做时,在实例化之后立即添加对method()的调用,可能在其上方有注释:

// Code
A myA = new A();
// Do some operations on A

// You should always wrap up with a call on method
myA.method();

// Code

这只是为了告知开发人员不要忘记在他的代码中的特定位置调用它。

我之所以这样问是因为我创建了一个包含排队机制的类,该机制将在大型项目中使用,也可以在将来的项目中使用。我需要强制每个未来的开发人员在他的代码末尾引用一个名为close()的方法,以终止与排队系统的连接。如果他忘记这样做(并且他/她很可能这样做),那么连接就会打开,给整个项目带来巨大的开销。

如果没有办法实现这一点(据我所知,我想不出任何事情),在Oracle的标准JDK中不包含这样的东西背后的逻辑是什么?我可以想一下JDK自己的库可以从中受益的例子(例如,当你写完文件时关闭PrintWriter),所以我不认为这是我对Java的一个误解原理

更新

因为我觉得我不小心开始了一场火焰战......

我确实认为一个好的API是以像自动这样的程序编写的。实例化一个对象/调用一个方法,其余的都是自动完成的。但就我而言,我需要像C ++的析构函数那样:强制或其他方式警告开发人员关闭与他创建的排队系统的连接。

更新2

遗憾的是,该项目是用不支持lambda函数的JDK 7编写的。

更新3

事实证明我的假设是正确的,并且没有可以利用的标准Java功能(除了lambda函数之外)。我是否可以在其他开发人员的课程中添加至少一个警告,他忘了关闭连接?

4 个答案:

答案 0 :(得分:4)

您应该利用Java7中引入的try-with-resouce功能。

您上面提到的课程public class A implements AutoClosable { public void close() { // Do closing } } 应该实现界面AutoClosable,然后:

A

使用try(A a = new A()) { // Do something } 的实例应该在try-with资源块中发生:

close

这确保在到达try块结束后调用A方法。

最后,至少eclipse编译器可以将try-with-resource块中的{{1}}标记为遗忘。

答案 1 :(得分:3)

您可能希望实现的是一种“使用”模式,您只需在您的类上公开一个公共方法,该方法将为您的对象加入“使用策略”,同时为您提供作者完全控制权过度实例化和破坏资源对象。

考虑这个资源类:

public class ExpensiveResource {
  private ExpensiveResource() {} // private so only we can get an instance

  public void destroy() { // a method we always want to call after we're done
    <...>
  }

  <...more operations with resource here...>

  // This is the only actual entry point where anyone can access instances of your resource.
  // As you can see, destroy() is always called no matter what.
  public static void use(UsageStrategy strategy) {
    ExpensiveResource resource = new ExpensiveResource();
    try {
      strategy.useResource(resource);
    }
    finally {
      resource.destroy();
    }
  }

  public static interface UsageStrategy extends Consumer<ExpensiveResource> {
    @Override
    default void accept(ExpensiveResource arg0) {
      useResource(arg0);
    }

    void useResource(ExpensiveResource resource);
  }
}

任何想要使用你资源的人都需要这样称呼它:

ExpensiveResource.use(resource -> {
  var a = resource.operation1();
  resource.operation2();
  resource.operation3(a);
  <... etc. ...>
});

如果您仍在使用Java7,那么您需要它才能创建一个匿名类:

ExpensiveResource.use(new UsageStrategy() {
  public void useResource(ExpensiveResource resource) {
    resource.operation1();
    <... etc. ...>
  }
});

由于样板语法,它的优雅程度要低得多,但基本思路是一样的,只要升级就可以开始享受Java8带来的好处。

注意我从上面的java.util.function.Consumer扩展了UsageStrategy.Java 7将不会有这个类,但您可以删除extendsdefault方法)。

答案 2 :(得分:0)

你在这里走错了兔子洞。含义:良好的API易于正确使用,并且难以以错误的方式使用。

如果您希望new A()后跟一些doSomething(),则解决方案如下:

  • 将该构造函数设为私有
  • 将一个静态辅助方法放入A中

这样:

public static A makeA() {
   A result = new A();
   doSomething();
   return result;
}

或类似的东西。换句话说:不要争取复杂的,非标准的,肮脏的,看起来很糟糕的解决方法。相反:不可能做错事。

答案 3 :(得分:0)

我知道任何IDE都没有这样的功能,但大多数都有插件。你可以编写自己的插件来实现它。

其他选项是重新设计你的API

class Main {
    public static void main(String[] arg) {

        String res = QueueService.doWithQueue(q -> q.someMethod());

    }
}

class QueueService {
    public static <T> T doWithQueue(DoWithQueue<T> m) {
        MyQueue myQueue = new MyQueue();
        T t = m.method(myQueue);
        myQueue.close();
        return t;
    }
}

interface DoWithQueue<T> {
    T method(MyQueue m);
}

class MyQueue {
    public void close() {
    }

    public String someMethod() {
        return "something";
    }
}

不要以MyQueue

的方式创建QueueService