为什么不是所有最终变量默认都是静态的?
Why aren't all final variables static by default?
为什么 在 非静态上下文 中需要 final
变量?编译器是否自动将 static
分配给所有 final
个变量?
编辑:我知道 static
和 final
之间的区别,我想问的是是否有任何情况下您需要 final int x
而不是 static final int x
.当您无法修改 x
时,为什么在每个实例中都需要它的副本?
因为 字段 的 类 final
.
很有意义
实际上,这应该是您默认要做的。如果您有充分的理由稍后更改它们的值,您只需要在您的字段上放置 final
关键字。
推理很简单:您希望编译器在您忘记初始化字段时告诉您。除此之外:您甚至可以在那里或在构造函数中初始化您的字段。因为这样您就可以确定在所有其他代码中,所有字段都已正确初始化。
换句话说:您想研究一下为什么 immutability 被视为 阳性 属性 of 类!
关键字final
用于在构造时允许只赋值一次。
public class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}
Person p = new Person("a");
p.name = "newName"; // COMPILE ERROR name is marked as "final" thus can not be changed.
when you would need final int x instead of static final int x?
考虑这些 类:
public class OriginConstants {
// static final fields allows to access constants via class accessor i. e. OriginConstants.x (no need to create instance)
public static final int x = 0;
public static final int y = 0;
}
public class ImmutablePoint {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class MutablePoint {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
使用示例
// create immutable point shifted from coordinate system origin by 5
ImmutablePoint ip = new ImmutablePoint(OriginConstants.x + 5, OriginConstants.y + 5);
// updating point coordinate by 10
ip.x += 10; // COMPILE ERROR
ip.y += 10; // COMPILE ERROR
// we cannot modify final fields, but we can create new instance with shifted coordinates
ImmutablePoint shiftedIp = new ImmutablePoint(ip.x + 10, ip.y + 10);
// create mutable point shifted from coordinate system origin by 5
MutablePoint mp = new MutablePoint(OriginConstants.x + 5, OriginConstants.y + 5);
// updating point coordinate by 10
ip.x += 10; // OK
ip.y += 10; // OK
对于一些不能及时改变的坐标,我会使用不可变点。假设,我们有 canvas,高度 = 100,宽度 = 100。我们可以按如下方式创建辅助常量点:
public class Canvas {
public static final int HEIGHT = 100;
public static final int WIDTH = 100;
// anchor points
public static final ImmutablePoint topLeft = new ImmutablePoint(0,0);
public static final ImmutablePoint topRight = new ImmutablePoint(Canvas.WIDTH, 0);
public static final ImmutablePoint bottomLeft = new ImmutablePoint(0, Canvas.HEIGHT);
public static final ImmutablePoint bottomRight = new ImmutablePoint(Canvas.WIDTH, Canavas.HEIGHT);
}
这样我们就可以确定,topLeft
总是 0,0 并且不会被错误更改。
final 变量的重要用法在 immutable objects 中。不可变对象是创建和初始化一次,然后永远不会改变的对象。
您可以有许多此类对象的实例,因此静态字段没有意义。但由于这些对象是不可变的,因此必须将所有字段设置为最终字段。
简单不可变的示例 class:
class User {
private final String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
static
意味着您不必拥有 class 的实例即可使用该变量。
例如Math.PI
,你不需要实例化Math
class来使用PI
的值,因此它是静态的。它必须是常量,所以它也是最终的。
如果你没有 final
only,这意味着变量应该是那个实例的常量。 class一旦初始化,就是最终的,不能更改。如果您希望在不必实例化 class.
的情况下使用常量,请添加 static
这样做是为了防止方法修改对象实例中的状态。它们被称为不可变对象,通常会简化您的编程,因为它们会简化您的测试场景。
这里回答得很好:
What is meant by immutable?
在你的例子中,你会做这样的事情:
public class Person {
public final String name;
public Person(String name) {
this.name = name;
}
public Person rename(String name) {
return new Person(name)
}
}
为什么 在 非静态上下文 中需要 final
变量?编译器是否自动将 static
分配给所有 final
个变量?
编辑:我知道 static
和 final
之间的区别,我想问的是是否有任何情况下您需要 final int x
而不是 static final int x
.当您无法修改 x
时,为什么在每个实例中都需要它的副本?
因为 字段 的 类 final
.
实际上,这应该是您默认要做的。如果您有充分的理由稍后更改它们的值,您只需要在您的字段上放置 final
关键字。
推理很简单:您希望编译器在您忘记初始化字段时告诉您。除此之外:您甚至可以在那里或在构造函数中初始化您的字段。因为这样您就可以确定在所有其他代码中,所有字段都已正确初始化。
换句话说:您想研究一下为什么 immutability 被视为 阳性 属性 of 类!
关键字final
用于在构造时允许只赋值一次。
public class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}
Person p = new Person("a");
p.name = "newName"; // COMPILE ERROR name is marked as "final" thus can not be changed.
when you would need final int x instead of static final int x?
考虑这些 类:
public class OriginConstants {
// static final fields allows to access constants via class accessor i. e. OriginConstants.x (no need to create instance)
public static final int x = 0;
public static final int y = 0;
}
public class ImmutablePoint {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class MutablePoint {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
使用示例
// create immutable point shifted from coordinate system origin by 5
ImmutablePoint ip = new ImmutablePoint(OriginConstants.x + 5, OriginConstants.y + 5);
// updating point coordinate by 10
ip.x += 10; // COMPILE ERROR
ip.y += 10; // COMPILE ERROR
// we cannot modify final fields, but we can create new instance with shifted coordinates
ImmutablePoint shiftedIp = new ImmutablePoint(ip.x + 10, ip.y + 10);
// create mutable point shifted from coordinate system origin by 5
MutablePoint mp = new MutablePoint(OriginConstants.x + 5, OriginConstants.y + 5);
// updating point coordinate by 10
ip.x += 10; // OK
ip.y += 10; // OK
对于一些不能及时改变的坐标,我会使用不可变点。假设,我们有 canvas,高度 = 100,宽度 = 100。我们可以按如下方式创建辅助常量点:
public class Canvas {
public static final int HEIGHT = 100;
public static final int WIDTH = 100;
// anchor points
public static final ImmutablePoint topLeft = new ImmutablePoint(0,0);
public static final ImmutablePoint topRight = new ImmutablePoint(Canvas.WIDTH, 0);
public static final ImmutablePoint bottomLeft = new ImmutablePoint(0, Canvas.HEIGHT);
public static final ImmutablePoint bottomRight = new ImmutablePoint(Canvas.WIDTH, Canavas.HEIGHT);
}
这样我们就可以确定,topLeft
总是 0,0 并且不会被错误更改。
final 变量的重要用法在 immutable objects 中。不可变对象是创建和初始化一次,然后永远不会改变的对象。 您可以有许多此类对象的实例,因此静态字段没有意义。但由于这些对象是不可变的,因此必须将所有字段设置为最终字段。
简单不可变的示例 class:
class User {
private final String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
static
意味着您不必拥有 class 的实例即可使用该变量。
例如Math.PI
,你不需要实例化Math
class来使用PI
的值,因此它是静态的。它必须是常量,所以它也是最终的。
如果你没有 final
only,这意味着变量应该是那个实例的常量。 class一旦初始化,就是最终的,不能更改。如果您希望在不必实例化 class.
static
这样做是为了防止方法修改对象实例中的状态。它们被称为不可变对象,通常会简化您的编程,因为它们会简化您的测试场景。
这里回答得很好: What is meant by immutable?
在你的例子中,你会做这样的事情:
public class Person {
public final String name;
public Person(String name) {
this.name = name;
}
public Person rename(String name) {
return new Person(name)
}
}