在Java中,
final
修改的引用类型的变量无法更改为引用任何其他对象final
修改的基本类型的变量不能更改为具有不同的值我在Does `final` means a field is not mutable?
问了那个问题 C#中的readonly
是否也对值类型和引用类型的变量进行相同的区分?
感谢。
答案 0 :(得分:3)
当用作变量的修饰符时,C#中的readonly
等同于Java的final
,因此它们对于各自语言中的值类型和引用类型的行为方式完全相同。
您只能初始化一次最终变量一次。这与是否可以修改对象状态无关。
readonly
关键字是您只能在字段上使用的修饰符。给定一个使用readonly
修饰符声明的变量,声明引入的字段的任何赋值只能作为声明的一部分或在同一个类的构造函数中出现。
Readonly
修饰符可防止更改字段。因此,不允许任何后来改变它们的企图。
答案 1 :(得分:1)
在Java中,
- 由final修改的引用类型的变量不能更改为引用任何其他对象
- 由final修改的基本类型的变量不能更改为具有不同的值
C#中的readonly是否也对值类型和引用类型的变量进行相同的区分?
大多数情况都是如此,是的。在离开构造函数后,final
和readonly
字段都不会被修改:可能不会将引用类型字段指定为指向其他对象,并且可能不会为值类型字段分配不同的值。但那不是全部。
虽然Java的final
和C#的readonly
修饰符主要用于同一目的,但您应该注意一些差异。
Java中的final
字段必须一次,使用内联字段初始值设定项,或者在每个构造函数 [1] 中进行赋值。 C#中的readonly
字段只能在内联或构造函数中初始化,但对其分配的次数没有限制;它可能被分配一次,不止一次,或从不分配。
价值类型的readonly
字段与参考类型之间存在细微的行为差异。当值类型字段标记为readonly
时,对该字段的任何访问都会导致复制。这可以防止您对字段本身执行任何可能的变异操作,从而有效地使其内部不可变。例如:
struct TestStruct {
public int Count;
public int Increment() { return ++Count; }
}
class MutableTest {
TestStruct s;
public void Test() {
Console.WriteLine(s.Increment());
}
}
class ImmutableTest {
readonly TestStruct s;
public void Test() {
Console.WriteLine(s.Increment());
}
}
如果您声明MutableTest
并再次调用Test()
,则会看到它打印1
,然后是2
。对ImmutableTest
个实例执行相同操作后,您会再次看到1
然后1
。
但是,请注意,Java没有用户定义的值类型的概念:Java中的所有值类型都是不可变原语,因此将原始字段声明为final
不会也不会影响" internal& #34;这种可变性。
两个修饰符都不会影响引用类型的内部可变性,例如,添加final
或readonly
修饰符本身不会阻止您修改目标对象的字段或属性,也不会阻止你调用可能会改变对象的方法。
与readonly
不同,final
修饰符可以与static
组合以定义编译时常量。如果static final
字段具有原始值或String
值,并且其内联初始值设定项是编译时常量表达式,则编译器可以使用基础常量值替换对它的任何引用。在这种情况下,实际上不会读取该字段。使用const
关键字可以在C#中实现相同的目标;使用readonly
无法完成。
值得注意的是,readonly
字段可以通过反射进行修改。这有效地绕过了仅在对象构造期间分配readonly
字段的要求。在Java中也是如此:任何反映修改final
字段的尝试都会触发异常。
最后,在Java中,形式化方法参数和局部变量可以标记为final
。这严格来说是一种语言级功能,它对生成的字节码 [2] 没有影响。必须为final
变量(如字段)分配一次。对于局部变量或形式参数,C#与readonly
或final
无效。
[1] 或者,可以在实例初始值设定项块中分配一次final
字段。但是,这些很少使用,并且使用实例初始值设定项等同于将块的内容添加到每个实例构造函数的开头。
[2] 从技术上讲,在某些情况下,形式参数的final
指定可以记录在元数据表中,但方法体内的字节码是不受影响。子>
答案 2 :(得分:0)
readonly
不区分引用类型或值类型。 readonly
只是意味着无法在字段初始值设定项或构造函数之外更改存储在变量中的值。
是什么让您认为有必要区分价值和参考类型?变量是值的占位符,无论其类型如何。 该值是或代表什么是另一个故事。