Java - 开发者实例化对象时自动添加方法调用
Java - Auto add method call when developer instantiates an object
我想知道开发人员是否可以编写 class 以便当其他开发人员实例化上述 class 的对象时,调用 class 的特定方法=59=] 被添加到他的代码中。
让我更具体一点。假设我创建了一个名为 A
的 class,其结构如下:
public class A {
public A() {
// Some instantiations
}
// Code class
// Method that always should be added
public void method() {
// Code
}
}
我将这个 class 包装到一个包中,其他一些开发人员在一个新对象中实例化 class 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
这只是为了通知开发人员不要忘记在他的代码中的特定位置调用它。
我问这个问题的原因是因为我创建了一个 class,其中包含一个将在大型项目以及未来项目中使用的排队机制。我需要强制每个未来的开发人员在他的代码末尾引用一个名为 close()
的方法,以终止与排队系统的连接。如果他忘记这样做(并且 he/she 这样做的可能性很高),连接将打开,给整个项目增加巨大的开销。
如果没有办法实现它(据我所知,我想不出任何东西),那么 Oracle 在标准 JDK 中不包含这样的东西背后的逻辑是什么?我可以想到可以从中受益的 JDK 自己的库的示例(例如,当您完成写入文件时关闭 PrintWriter
),所以我不认为这是一个我这边对 Java 的原则有误解。
更新
因为我想我不小心点燃了火焰war...
我确实认为一个好的 API 是以这样的方式编写的 自动 。实例化一个 object/call 方法,其余的自动完成。但是对于我的情况,我需要像 C++ 的析构函数这样的东西:一种强制或以其他方式 warn 开发人员关闭与他创建的排队系统的连接的方法。
更新 2
不幸的是,该项目是用 JDK 7 编写的,不支持 lambda 函数。
更新 3
事实证明我的假设是正确的,并且没有可以利用的标准 Java 功能(除了 lambda 函数之外)。我可以在其他开发人员忘记关闭连接的 class 上至少添加一个 warning 吗?
你走错了路。意思是:好的API很容易被正确使用,很难被错误使用。
如果您希望 new A()
后跟一些 doSomething()
,那么解决方案如下:
- 将该构造函数设为私有
- 将静态辅助方法放入 A 中执行
这个:
public static A makeA() {
A result = new A();
doSomething();
return result;
}
或类似的东西。换句话说:不要争取复杂的、非标准的、看起来脏兮兮的变通办法。相反:让不可能做错事。
我所知道的 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
您可能想要实现的是一种 "Use with" 模式,您只在 class 上公开一个 public 方法,它将接受 "Use strategy"对于您的对象,同时作为作者,您可以完全控制资源对象的实例化和销毁。
考虑此资源 class:
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,您需要做的就是创建一个匿名的 class:
ExpensiveResource.use(new UsageStrategy() {
public void useResource(ExpensiveResource resource) {
resource.operation1();
<... etc. ...>
}
});
由于样板语法,它远没有那么优雅,但基本思想是一样的,升级后即可开始享受 Java8 的好处。
(注意 我从上面的 java.util.function.Consumer
扩展了 UsageStrategy。Java 7 不会有这个 class,但你可以删除extends
和 default
一种方法)。
您应该利用 Java7 中引入的 try-with-resouce 功能。
您前面提到的 class A
应该实现接口 AutoClosable 然后:
public class A implements AutoClosable {
public void close() {
// Do closing
}
}
使用 A
的实例应该发生在 try-with 资源块中:
try(A a = new A()) {
// Do something
}
这确保了 close
方法在到达 try 块的末尾后被调用。
最后,至少 eclipse 编译器可以将忘记在 try-with-resource 块中使用 A
标记为错误。
我想知道开发人员是否可以编写 class 以便当其他开发人员实例化上述 class 的对象时,调用 class 的特定方法=59=] 被添加到他的代码中。
让我更具体一点。假设我创建了一个名为 A
的 class,其结构如下:
public class A {
public A() {
// Some instantiations
}
// Code class
// Method that always should be added
public void method() {
// Code
}
}
我将这个 class 包装到一个包中,其他一些开发人员在一个新对象中实例化 class 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
这只是为了通知开发人员不要忘记在他的代码中的特定位置调用它。
我问这个问题的原因是因为我创建了一个 class,其中包含一个将在大型项目以及未来项目中使用的排队机制。我需要强制每个未来的开发人员在他的代码末尾引用一个名为 close()
的方法,以终止与排队系统的连接。如果他忘记这样做(并且 he/she 这样做的可能性很高),连接将打开,给整个项目增加巨大的开销。
如果没有办法实现它(据我所知,我想不出任何东西),那么 Oracle 在标准 JDK 中不包含这样的东西背后的逻辑是什么?我可以想到可以从中受益的 JDK 自己的库的示例(例如,当您完成写入文件时关闭 PrintWriter
),所以我不认为这是一个我这边对 Java 的原则有误解。
更新
因为我想我不小心点燃了火焰war...
我确实认为一个好的 API 是以这样的方式编写的 自动 。实例化一个 object/call 方法,其余的自动完成。但是对于我的情况,我需要像 C++ 的析构函数这样的东西:一种强制或以其他方式 warn 开发人员关闭与他创建的排队系统的连接的方法。
更新 2
不幸的是,该项目是用 JDK 7 编写的,不支持 lambda 函数。
更新 3
事实证明我的假设是正确的,并且没有可以利用的标准 Java 功能(除了 lambda 函数之外)。我可以在其他开发人员忘记关闭连接的 class 上至少添加一个 warning 吗?
你走错了路。意思是:好的API很容易被正确使用,很难被错误使用。
如果您希望 new A()
后跟一些 doSomething()
,那么解决方案如下:
- 将该构造函数设为私有
- 将静态辅助方法放入 A 中执行
这个:
public static A makeA() {
A result = new A();
doSomething();
return result;
}
或类似的东西。换句话说:不要争取复杂的、非标准的、看起来脏兮兮的变通办法。相反:让不可能做错事。
我所知道的 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
您可能想要实现的是一种 "Use with" 模式,您只在 class 上公开一个 public 方法,它将接受 "Use strategy"对于您的对象,同时作为作者,您可以完全控制资源对象的实例化和销毁。
考虑此资源 class:
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,您需要做的就是创建一个匿名的 class:
ExpensiveResource.use(new UsageStrategy() {
public void useResource(ExpensiveResource resource) {
resource.operation1();
<... etc. ...>
}
});
由于样板语法,它远没有那么优雅,但基本思想是一样的,升级后即可开始享受 Java8 的好处。
(注意 我从上面的 java.util.function.Consumer
扩展了 UsageStrategy。Java 7 不会有这个 class,但你可以删除extends
和 default
一种方法)。
您应该利用 Java7 中引入的 try-with-resouce 功能。
您前面提到的 class A
应该实现接口 AutoClosable 然后:
public class A implements AutoClosable {
public void close() {
// Do closing
}
}
使用 A
的实例应该发生在 try-with 资源块中:
try(A a = new A()) {
// Do something
}
这确保了 close
方法在到达 try 块的末尾后被调用。
最后,至少 eclipse 编译器可以将忘记在 try-with-resource 块中使用 A
标记为错误。