我想知道开发人员是否有可能编写一个类,以便当其他开发人员实例化上述类的对象时,对类的特定方法的调用会被添加到他的代码中。
让我更具体一点。假设我创建了一个名为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函数之外)。我是否可以在其他开发人员的课程中添加至少一个警告,他忘了关闭连接?
答案 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将不会有这个类,但您可以删除extends
和default
方法)。
答案 2 :(得分:0)
你在这里走错了兔子洞。含义:良好的API易于正确使用,并且难以以错误的方式使用。
如果您希望new A()
后跟一些doSomething()
,则解决方案如下:
这样:
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