如何在java中创建自定义编译器警告?
我正在寻找类似于实现java.lang.AutoCloseable接口的东西,其中会生成一个编译器警告,指示如何在java中创建自定义编译器警告?,java,concurrency,semaphore,compiler-warnings,Java,Concurrency,Semaphore,Compiler Warnings,我正在寻找类似于实现java.lang.AutoCloseable接口的东西,其中会生成一个编译器警告,指示资源泄漏:“xxxx”从未关闭 这个用例在java中的同步集合的包装器中。包装器有一个内部信号量来防止并发修改集合 它允许对集合进行原子操作,在这种情况下,信号量是在内部获取和释放的。它还允许从外部获取锁,从而提供一个唯一的密钥,可以使用该密钥对集合执行操作。必须在“交易”结束时释放密钥 我的目标是在同一方法中获取锁而不是释放锁时创建编译器警告,以防止死锁。也可接受可防止出现这种情况的替代
资源泄漏:“xxxx”从未关闭
这个用例在java中的同步集合的包装器中。包装器有一个内部信号量来防止并发修改集合
它允许对集合进行原子操作,在这种情况下,信号量是在内部获取和释放的。它还允许从外部获取锁,从而提供一个唯一的密钥,可以使用该密钥对集合执行操作。必须在“交易”结束时释放密钥
我的目标是在同一方法中获取锁而不是释放锁时创建编译器警告,以防止死锁。也可接受可防止出现这种情况的替代设计解决方案
这是一个有趣的小问题,因此我非常感谢您对它的深入了解。为了创建编译器警告,您需要扩展Eclipse编译器
另一种解决方案是在软件质量分析系统中创建自定义检查,如Teamscale或SonarQube。自定义检查对代码执行静态分析(通常基于富含语义信息的抽象语法树),并在检测到可疑代码时产生问题。这些问题显示在质量分析系统的用户界面上。Eclipse插件允许在Eclipse中集成系统,以便也可以在那里列出问题。为了创建编译器警告,您需要扩展Eclipse编译器
另一种解决方案是在软件质量分析系统中创建自定义检查,如Teamscale或SonarQube。自定义检查对代码执行静态分析(通常基于富含语义信息的抽象语法树),并在检测到可疑代码时产生问题。这些问题显示在质量分析系统的用户界面上。Eclipse插件允许在Eclipse中集成系统,这样问题也可以列在那里。如您所说
也可接受可防止出现这种情况的替代设计解决方案
这就是:作为替代设计解决方案,使用函数式编程
与其找出错误,为什么不首先阻止错误的发生
由于缺乏源代码,我对您的代码做了一些假设:
Semaphore
是向SynchronizedCollection
提供信号量的类(或接口)
Semaphore
提供了两种方法get()
和release()
你实际上面临的问题是国家责任的问题。导致时间耦合的状态变化<代码>获取()
和发布()
必须按顺序调用。您可以使用函数式编程中的元素作为替代设计
信号灯当前看起来如下所示:
public class Sempahore {
// ...
public void obtain() {
// Lock code
}
public void release() {
// Release code
}
}
semaphore.obtain();
// Code protected by the Sempahore.
semaphore.release();
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V> void protect(final Callable<V> c) throws Exception {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
semaphore.protect(() -> {
// Code protected by the Semaphore.
});
public interface ProtectedCode<V,E> {
V call() throws E;
}
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V, E> void protect(final ProtectedCode<V, E> c) throws E {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
信号灯
用户当前的外观如下:
public class Sempahore {
// ...
public void obtain() {
// Lock code
}
public void release() {
// Release code
}
}
semaphore.obtain();
// Code protected by the Sempahore.
semaphore.release();
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V> void protect(final Callable<V> c) throws Exception {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
semaphore.protect(() -> {
// Code protected by the Semaphore.
});
public interface ProtectedCode<V,E> {
V call() throws E;
}
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V, E> void protect(final ProtectedCode<V, E> c) throws E {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
解决方案是将get()
和release()
组合到一个函数中,该函数将要保护的代码作为其参数。这种技术也被称为传递一个块,或者更正式地称为一个高阶函数——一个将另一个函数作为参数或返回另一个函数的函数
Java也有函数指针,不是直接的,而是通过接口引用间接的。自Java 8以来,只有一个抽象方法的接口甚至被称为Functional interface,Java 8为此提供了可选的注释@Functional interface
因此,您的类Sempahore
可以如下所示:
public class Sempahore {
// ...
public void obtain() {
// Lock code
}
public void release() {
// Release code
}
}
semaphore.obtain();
// Code protected by the Sempahore.
semaphore.release();
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V> void protect(final Callable<V> c) throws Exception {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
semaphore.protect(() -> {
// Code protected by the Semaphore.
});
public interface ProtectedCode<V,E> {
V call() throws E;
}
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V, E> void protect(final ProtectedCode<V, E> c) throws E {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
关于这个解决方案的怪癖
Java在这个上下文中有一个方面非常糟糕:异常处理。对于函数式编程,迫切需要解决这个问题,但Oracle没有。我仍然希望使用Java9,但这并不能帮助像Java.util.stream
这样已经存在于野外的破API。Java8仍然维护已检查异常的句柄或声明规则,但函数式编程没有很好地考虑到这一点
有几种解决方法:
- 如果不需要返回值,请使用
Runnable
- 使用您自己的
Callable
接口,该接口为异常声明一个类型参数
我打赌使用Runnable
是直截了当的,不言自明的,因此我不会详细说明
使用您自己版本的Callable
界面如下所示:
public class Sempahore {
// ...
public void obtain() {
// Lock code
}
public void release() {
// Release code
}
}
semaphore.obtain();
// Code protected by the Sempahore.
semaphore.release();
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V> void protect(final Callable<V> c) throws Exception {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
semaphore.protect(() -> {
// Code protected by the Semaphore.
});
public interface ProtectedCode<V,E> {
V call() throws E;
}
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V, E> void protect(final ProtectedCode<V, E> c) throws E {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
公共接口受保护的代码{
V call()抛出E;
}
公共类信号量{
// ...
私有无效获取(){
//锁码
}
私人无效释放(){
//发布代码
}
公共无效保护(最终保护代码c)抛出E{
获得();
试一试{
返回c.call();
}最后{
释放();
}
}
}
现在,只要类型参数E
的有限类型推断(因为它只能反映一种类型,而不是一个类型集)在编译器中产生合理的结果,就不需要处理异常
如果您想对用户非常友好,实际上可以提供三种protect
方法:
公共无效保护(最终可运行r)
public V protect(最终可调用c)引发异常
public V protect(最终保护代码c)抛出E
正如你所说的
替代品