java常量应用在哪里?该怎么实现?

TheDisguiser 2020-08-31 21:45:24 java常见问答 4356

常量的应用是java的基础内容之一,能够熟练的使用常量是java学习的必须,下面就跟小编一起来看看java中常量的应用。

常量,我们可以把它理解为一种特殊的变量,这种变量,它的值被设定后,在程序运行过程当中是不允许改变的。

常量语法:final 常量名 = 值;

例:

使用fianl关键字 常量名 值

final String a1 = "道具卡";

final double a2 = 15.6;

在java程序里使用常量可以有效提高代码的可维护性。例如,在一般项目开发时,我们需要指定用户的性别,此时可以定义一个性别常量,赋值为 "男"或”女”,在需要指定用户性别的地方直接调用此常量即可,避免了由于用户的不规范赋值导致程序出错的情况。

PS:常量名通常使用大写字符。

因为在Inteface中默认常量就是static final 的,所以许多人就因此其认为它是存放常量的最佳地方,但在effective java中就提过,不建议使用常量接口,其中一个原因就是:代码编译问题

我们来看个简单例子,有一个interface A,一个class B,代码如下:

//file A.java
public interface A
{
    String name = "bright";
}
//file B.java
public class B
{
    public static void main(String[] args)
    {
        System.out.println("Class A's name = " + A.name);
    }
}
非常简单吧, 下面我们来编译A.java和B.java。
运行, 输入java B, 显然结果如下:
Class A 's name = bright
我们现在修改A.java如下:
//file A.java
public interface A
{
    String name = "bright sea";
}
编译A.java后重新运行B class, 输入java B, 注意: 结果如下
Class A 's name = bright
为什么不是 "Class A's name = bright sea"?
让我们使用jdk提供的反编译工具javap反编译B.class看个究竟, 输入: javap - c B, 结果如下:
Compiled from B.java
public class B extends java.lang.Object
{
    public B();
    public static void main(java.lang.String[]);
}
Method B()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
   4 return
Method void main(java.lang.String[])
   0 getstatic # 2 < Field java.io.PrintStream out >
    3 ldc #3 <String "Class A's name = bright ">
5 invokevirtual #4 <Method void println(java.lang.String)>
   8 return
注意到标号3的代码了吗?由于引用了一个static final 的字段,编译器已经将interface A中name的内容编译进了class B中,而不是对interface A中的name的引用。因此除非我们重新编译class B,interface A中name发生的变化无法在class B中反映。如果这样去做那么java的动态优势就消失殆尽。
解决方案,有两种解决方法。
第一种方法是不再使用常量,将所需字段放入class中声明,并去掉final修饰符。但这种方法存在一定的风险,由于不再是常量着因而在系统运行时有可能被其他类修改其值而发生错误,也就违背了我们设置它为常量的初衷,因而不推荐使用。
第二种方法,将常量放入class中声明,使用class方法来得到此常量的值。为了保持对此常量引用的简单性,我们可以使用一个静态方法。我们将A.java和B.java修改如下:
//file A.java
public class A{
private static final String name = "bright";
public static String getName()
{
    return name;
}
}
//file B.java
public class B
{
    public static void main(String[] args)
    {
        System.out.println("Class A's name = " + A.getName());
    }
}
同样我们编译A.java和B.java。 运行class B, 输入java B, 显然结果如下:
Class A 's name = bright
现在我们修改A.java如下:
//file A.java
public class A
{
    private static final String name = "bright";
    public static String getName()
    {
        return name;
    }
}
我们再次编译A.java后重新运行B class, 输入java B: 结果如下
Class A 's name = bright sea
终于得到了我们想要的结果, 我们可以再次反编译B.class看看class B的改变, 输入:
javap - c B, 结果如下:
Compiled from B.java
public class B extends java.lang.Object
{
    public B();
    public static void main(java.lang.String[]);
}
Method B()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
   4 return
Method void main(java.lang.String[])
   0 getstatic # 2 < Field java.io.PrintStream out >
    3 new #3 <Class java.lang.StringBuffer>
   6 dup
   7 invokespecial # 4 < Method java.lang.StringBuffer() >
    10 ldc #5 <String "Class A's name = ">
12 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)>
  15 invokestatic # 7 < Method java.lang.String getName() >
    18 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)>
  21 invokevirtual # 8 < Method java.lang.String toString() >
    24 invokevirtual #9 <Method void println(java.lang.String)>
  27 return
注意标号10至15行的代码,class B中已经变为对A class的getName()方法的引用,当常量name的值改变时我们只需对class A中的常量做修改并重新编译,无需编译整个项目工程我们就能改变整个应用对此常量的引用,即保持了java动态优势又保持了我们使用常量的初衷,因而方法二是一个最佳解决方案。

以上就是本篇文章的所有内容,小伙伴们知道怎么使用常量了吗?更多编程常见问题欢迎关注我们了解详情。

推荐阅读:

java常量定义有哪些方法?如何实现?