我见过很多人们编写public static final String mystring = ...
然后只使用一个值的代码。
为什么他们必须这样做?为什么他们必须在final
使用之前初始化值?
更新
好的,谢谢大家的回答,我理解这些键的含义(公共静态最终)。我不明白的是为什么人们会使用它,即使常量只会在一个地方并且只在同一个类中使用。为什么要宣布它?为什么我们不只使用变量?
final
表示变量的值不会改变 - 换句话说,一个常量,其值在声明后无法修改。
public final static String
当你想创建一个时使用String
:
static
:不需要使用它的实例),即final
),例如,当您想要定义一个String
可用于该类的所有实例以及使用该类的其他对象的常量时,并且例子:
public final static String MY_CONSTANT = "SomeValue";
// ... in some other code, possibly in another object, use the constant:
if (input.equals(MyClass.MY_CONSTANT)
相似地:
public static final int ERROR_CODE = 127;
不需要使用,但它可以final
防止常量在程序执行期间被无意更改,并用作变量是否为常量的指示符。
即使该常量仅在当前类和/或仅在一个地方使用(读取),最好将所有常量声明为final
:它更清晰,并且在代码的生命周期中,该常量可能最终被用于不止一处。
此外,使用final
可以允许实现执行一些优化,例如通过内联使用常量的实际值。
最后请注意,这final
只会从原始类型中生成真正的常量值,并且String
是不可变的。应用于final
对象(例如 a HashMap
)将使引用不可变,但对象的状态不可变:例如可以更改对象的数据成员,可以更改数组元素,可以操作和更改集合。
final ..它是一个关键字,用于使字符串保持不变。您不能更改该字符串的值。看下面的例子:
public class StringTest {
static final String str = "Hello";
public static void main(String args[]) {
// str = "world"; // gives error
System.out.println(str); // called without the help of an object
System.out.println(StringTest.str);// called with class name
}
}
谢谢
关键字final表示该值是恒定的(不能更改)。它类似于 C 中的 const。
您可以将静态视为具有范围的全局变量。这基本上意味着,如果您为一个对象更改它,它将像全局变量一样对所有对象进行更改(受范围限制)。
希望能帮助到你。
static
意味着该对象只会被创建一次,并且没有包含它的实例对象。当您拥有类的所有对象通用且永远不会改变的东西时,最好使用您编写的方式。它甚至可以在根本不创建对象的情况下使用。
通常最好在您期望的时候使用 final ,final
这样编译器就会强制执行该规则并且您肯定知道。static
如果所有对象的值相同,则确保您不会浪费内存来创建许多相同的东西。
final
表示该值一旦设置就不能更改。 static
允许您设置该值,并且该值对于使用它的类的所有实例都是相同的。此外,您可以访问没有public static
类实例的字符串的值。
public使其可以跨其他类访问。您可以在不实例化类或使用任何对象的情况下使用它。
静态使其在所有类实例中具有统一的值。如果所有对象的值都相同,它可以确保您不会浪费内存来创建许多相同的东西。
final使其值不可修改。这是一个“常量”值,在所有类实例中都是相同的,不能修改。
您不必使用final
,但它向final
其他所有人(包括编译器)表明这是一个常量,这是它的好习惯。
为什么即使常量只在一个地方并且只在同一个类中使用,人们也会这样做:因为在许多情况下它仍然有意义。例如,如果您知道它在程序运行期间将是最终的,但您打算稍后更改该值并重新编译(更容易找到),并且以后可能会更频繁地使用它。它还在突出和组合的地方向其他程序员告知程序流程中的核心价值。
不幸的是,其他答案遗漏的一个方面是,使用组合public final
需要非常小心,特别是如果其他类或包将使用您的类(可以假设,因为它是public
)。
原因如下:
final
,所以编译器会在编译期间将该字段内联到任何读取该字段的编译单元中。到现在为止还挺好。public
,编译器也会将此值内联到任何其他编译单元中。这意味着使用该字段的其他类。后果是什么?
想象一下你有这个:
class Foo {
public static final String VERSION = "1.0";
}
class Bar {
public static void main(String[] args) {
System.out.println("I am using version " + Foo.VERSION);
}
}
编译运行后Bar
得到:
I am using version 1.0
现在,您改进Foo
并将版本更改为“1.1”。重新编译后Foo
,你运行Bar
并得到这个错误的输出:
I am using version 1.0
发生这种情况,因为VERSION
是声明final
的,所以它的实际值已经在Bar
第一次编译运行期间内联。因此,要让public static final ...
字段示例在实际更改声明的内容后正确传播final
(您撒谎!;),您需要使用它重新编译每个类。
我已经看过几次了,很难调试。
如果你的意思是一个可能在你的程序的更高版本中改变final
的常量,一个更好的解决方案是:
class Foo {
private static String version = "1.0";
public static final String getVersion() {
return version;
}
}
这样做的性能损失可以忽略不计,因为 JIT 代码生成器将在运行时内联它。
通常用于定义常量,您可以在许多地方重用它们,使其成为单点更改,在单个类中使用或跨包共享。使变量最终避免意外更改。
为什么人们在类中使用常量而不是变量?
可读性和可维护性,
在你的代码中有一些像 40.023 这样的数字并不能说明这个数字代表什么,所以我们用大写的单词替换它,比如“USER_AGE_YEARS”。稍后当我们查看代码时,很清楚该数字代表什么。
为什么我们不只使用变量?好吧,如果我们知道这个数字会改变,但如果它的某个数字不会改变,比如 3.14159.. 我们会确定它是最终的。
但是如果它不是像字符串这样的数字呢?在这种情况下,它主要是为了可维护性,如果您在代码中多次使用字符串(并且它不会在运行时更改),那么将它作为类顶部的最终字符串很方便。这样当你想改变它时,只有一个地方可以改变它而不是很多。
例如,如果您的代码中有一条错误消息多次打印,则最终 String ERROR_MESSAGE = "Something go bad." 更容易维护,如果您想将其从“出现问题”更改。到“为时已晚,吉姆他已经死了”,您只需要更改那一行,而不是您将使用该评论的所有地方。
public
使其可以跨其他类访问。
static
使其在所有类实例中具有统一的值。
final
使其成为不可修改的值。所以基本上它是一个“常量”值,在所有类实例中都是相同的,并且不能修改。关于您的关注“我不明白的是为什么人们使用它,即使常量只在一个地方并且只在同一个类中使用。为什么要声明它?为什么我们不只使用变量?” 我想说,因为它是一个公共字段,所以常量值也可以使用 ClassName.value 在其他类的其他地方使用。例如:一个名为 Math 的类可能将 PI 作为最终的静态 long 值,可以作为 Math.PI 访问。
这是一种标准/最佳实践。已经有列出场景的答案,但是对于您的第二个问题:
为什么他们必须这样做?为什么他们必须在使用之前将值初始化为最终值?
声明时初始化的公共常量和字段应该是“静态最终”,而不仅仅是“最终”
以下是它应该是这样的一些原因:
将公共常量设置为 final 而不是 static final 会导致为类的每个实例复制其值,从而无用地增加执行应用程序所需的内存量。
此外,当非公共的 final 字段也不是静态的时,这意味着不同的实例可以具有不同的值。但是,由于final字段的行为,在其声明中初始化非静态 final 字段会强制每个实例具有相同的值。
这与代码的语义有关。通过命名将其分配给具有有意义名称的变量的值(即使它仅在一个地方使用),您就可以赋予它意义。当有人阅读代码时,该人将知道该值的含义。
通常,在代码中使用常量值不是一个好习惯。想象一个充满字符串、整数等值的代码。一段时间后,没有人会知道这些常数是什么。当值在多个地方使用时,值中的拼写错误也可能成为问题。
我想这些都是清楚的解释。但是,让我通过给出一个 java inbuild 示例来澄清它。
在 java 中,大多数人会使用 System.out.println()
system是一个类,out是一个 PrintStream 类。
所以 java 说的是我将负责 out 对象(PrintStream)的初始化,并在 System 类中将初始化保持为我自己的私有。
public final class System {
public final static PrintStream out = null;
//Some initialization done by system class which cannot be changed as it is final.
}
您只需静态访问println方法,而不用担心它的初始化。