Java 常量实用程序类中的Final关键字

Java 常量实用程序类中的Final关键字,java,performance,class,constants,final,Java,Performance,Class,Constants,Final,是性能上的任何差异和/或我们在使用final关键字和常量实用程序类时可以获得的任何其他好处。[此类仅包含静态最终字段和专用构造函数,以避免创建对象] public class ActionConstants { private ActionConstants() // Prevents instantiation { } public static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\\s]+";

是性能上的任何差异和/或我们在使用final关键字和常量实用程序类时可以获得的任何其他好处。[此类仅包含静态最终字段和专用构造函数,以避免创建对象]

public class ActionConstants {
    private ActionConstants()  // Prevents instantiation
    {   }

    public static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\\s]+";    
    public static final String VALIDPHONENUMBER = "\\d{10}";
    ...
    ...
}
唯一不同的是阶级是最终的

 public final class ActionConstants {
    private ActionConstants()  // Prevents instantiation
    {   }

    public static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\\s]+";    
    public static final String VALIDPHONENUMBER = "\\d{10}";
    ...
    ...
}

我想知道,使用final有什么好处,为常量定义类的正确方法是什么。

没有好处。它不会改变任何有关
静态final
属性的内容

当一个类成为final时,编译器可以利用它来实现可重写的方法(静态方法最多不能被重写,它们将那些静态方法隐藏在继承的类中)

由于类是final,编译器知道它的任何方法都不能被重写。因此,它可以计算不需要生成多态性代码的情况(即,根据运行时的对象实例查找覆盖方法的正确“版本”的代码)。因此,优化是可能的

如果您想使类真正独一无二,可以使用以下方法:

public enum ActionConstants {

    INSTANCE;

    public static final int cte1 = 33;
    public static final int cte2 = 34;

}

如果您对类实例根本不感兴趣,只需将所有常量放在一个接口中。

这并没有真正的好处,但它确实强化了您的期望,即没有任何东西扩展您的类。例如,从长远来看,这可能会使您更容易在代码中搜索常量的所有用法,因为它们将被保证为XXX.abc,而不是YYY扩展XXX的YYY.abc。

您应该避免使用“常量类”。这意味着一个坏迹象。将常量放在与它们一起操作的类中。避免使用公共常量。这应该是一个例外,而不是一个正常的做法。

如果您希望提高性能,最好预先编译您的模式,如

public static final Pattern VALIDFIRSTLASTNAME = Pattern.compile("[A-Za-z0-9.\\s]+");    
public static final Pattern VALIDPHONENUMBER = Pattern.compile("\\d{10}");

与使用正则表达式的成本相比,使用final或not是非常小的。

将类用于常量是不常见的。在大多数情况下,使用接口。这可以通过
ActionConstants访问。VALIDFIRSTLASTNAME

public interface ActionConstants {
  static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\\s]+";    
  static final String VALIDPHONENUMBER = "\\d{10}";
  ...
}
由于Java5,您还可以使用枚举。枚举可以具有成员或扩展功能

第二个示例使用了一个简单的成员(如果您有不同的常量类型,这里使用的是通用方法,否则您也可以使用
字符串
成员):


这两个版本都允许使用静态导入。

这通常是更好的做法,但并不总是这样。在某些情况下,有些股票常数并不属于使用它们的任何一个类。你能提供一个例子吗?想想数学常数,例如,你不想在你使用它们的每一个地方都定义它们。我提到过,该规则有一些例外。但regexp模式并非如此。不确定是否需要
实例。我会有一个没有实例的枚举。通常“接口应该只用于定义类型。它们不应该用于导出常量。”@Peter Lawrey您需要为枚举提供至少一个值,我称之为我的实例,但它可以是任何值…@JVerstry,它说您至少需要一个值吗?您是否尝试过删除该实例并仅放置
 @ JVersty,有些人会考虑没有实例的枚举。实际上,使用接口定义常量被认为是一种反模式@Helper方法,我同意,但我看不出在哪里提到接口看起来对这个答案投了反对票,这个方法有什么问题吗。
public enum ActionConstants {

  FIRSTLASTNAME("[A-Za-z0-9.\\s]+"),
  PHONENUMBER("\\d{10}");

  private final Object value;

  private ActionConstants(Object value) {
    this.value= value;
  }

  @SuppressWarnings("unchecked")
  public <T> T getValue() {
    return (T)value;
  }

}

String value = ActionConstants.FIRSTLASTNAME.getValue();
public enum ActionConstants {

  FIRSTLASTNAME("[A-Za-z0-9.\\s]+"),
  PHONENUMBER("\\d{10}");

  private final Pattern pattern;

  private ActionConstants(String pattern) {
    this.pattern = Pattern.compile(pattern);
  }

  public void isValid(String value) {
    return pattern.matcher(value).matches();
  }

}