使用接口定义常量时,SonarLint会告警 Constants should not be defined in interfaces

Java - constants_成员变量

实例代码:

public interface WeixinConstants {
public static final String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
}

过去相关讨论

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface. There are several constant interfaces in the java platform libraries, such as java.io.ObjectStreamConstants. These interfaces should be regarded as anomalies and should not be emulated.

常量接口模式是对java接口的一种poor use。一个类内部的使用这些常量是一个实现细节。当一个类实现了该接口,那么这个接口就会成为该类公共API的一部分。这个类的内部实现细节不应该暴露给公共API。这个类是否实现了一个常量接口对于用户来说是无关紧要的。事实上,这种做法可能会混淆用户。更糟糕的是,它表现为一种义务:如果在未来的发行版中不需要再使用那些常量,但是为了兼容性该类还是需要实现这个接口。如果一个nonfinal类实现了一个常量接口,那么这个常量接口中定义的常量将会污染他的所有子类的的命名空间。在java平台的一些类库如java.io.ObjectStreamConstants中,也有很多这种常量接口。但是这些接口应该被看作是不合规范的,并且避免大家效仿这种做法。

interface中声明的成员变量为什么默认为final static的?

Interfaces are meant to give only specification. It can not contain any implementations. So To avoid implementing classes to change the specification, it is made final. Since Interface cannot be instantiated, they are made static to access the field using interface name.

所谓的接口就是一些协议,契约的定义,他不能够包含任何的实现。所以为了避免实现类去修改这个契约,所以他必须被声明为final,另外因为接口不能够被实例化,所以只有通过声明为static,才能使用接口名+字段的这样一种方式来访问该成员变量。

修改后的代码:

public final class WeixinConstants {
private WeixinConstants() {
// empty
}

public static final String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
}

补充说明:

  • class的类型为final,表示该类是不可以继承的;
  • 定义了一个私有的构造函数,避免实例化该类;
  • 常量的类型为public static final

实际使用常量

String wxResult = HttpClientUtil.doGet(WeixinConstants.WX_LOGIN_URL, param);


WeixinConstants.WX_LOGIN_URL 就是直接使用常量。

参考

1. ​​what-is-the-use-of-interface-constants?​