【发布时间】:2010-11-22 14:08:02
【问题描述】:
C# 中 Java 的 final 等价于什么?
【问题讨论】:
-
类顶部的评论说“如果你覆盖这个类,你会被解雇!” (当然这是个玩笑:)
标签: c# access-modifiers reserved-words
C# 中 Java 的 final 等价于什么?
【问题讨论】:
标签: c# access-modifiers reserved-words
final 关键字在 Java 中有多种用法。它对应于 C# 中的 sealed 和 readonly 关键字,具体取决于使用它的上下文。
为了防止子类化(从定义的类继承):
Java
public final class MyFinalClass {...}
C#
public sealed class MyFinalClass {...}
防止覆盖virtual 方法。
Java
public class MyClass
{
public final void myFinalMethod() {...}
}
C#
public class MyClass : MyBaseClass
{
public sealed override void MyFinalMethod() {...}
}
正如 Joachim Sauer 所指出的,这两种语言之间的一个显着区别是 Java 默认将所有非静态方法标记为 virtual,而 C# 将它们标记为 sealed。因此,如果您想停止进一步覆盖基类中已显式标记为 virtual 的方法,则只需在 C# 中使用 sealed 关键字。
只允许一个变量被赋值一次:
Java
public final double pi = 3.14; // essentially a constant
C#
public readonly double pi = 3.14; // essentially a constant
附带说明,readonly 关键字的效果与 const 关键字的效果不同,readonly 表达式是在 runtime 而不是 compile-时间,因此允许任意表达式。
【讨论】:
readonly 成员变量可以在构造函数中修改:pastebin.com/AzqzYGiA
这取决于上下文。
final 类或方法,C# equivalent is sealed。final 字段,C# equivalent is readonly。final 局部变量或方法参数,没有直接的 C# 等效项。【讨论】:
For a final local variable or method parameter, there's no direct C# equivalent 一个巨大的区别。
const 只能用于值类型。据我所知,没有办法为本地引用类型创建一个有效的常量。
密封
【讨论】:
C# 常量使用 const 关键字声明编译时常量或使用 readonly 关键字声明运行时常量。常量的语义在 C# 和 Java 语言中是相同的。
【讨论】:
Java 类 final 和方法 final -> 密封。 Java 成员变量 final -> 运行时常量为只读,编译时常量为 const。
局部变量 final 和方法参数 final 没有等效项
【讨论】:
这里每个人都缺少的是 Java 对最终成员变量的明确赋值的保证。
对于具有最终成员变量 V 的类 C,通过 C 的每个构造函数的每个可能的执行路径都必须将 V 分配一次 - 未能分配 V 或分配 V 两次或更多次将导致错误。
C# 的 readonly 关键字没有这样的保证 - 编译器非常乐意让 readonly 成员不分配或允许您在构造函数中多次分配它们。
因此,final 和 readonly(至少就成员变量而言)绝对不等价 - final 更加严格。
【讨论】:
如前所述,sealed 等同于方法和类的final。
其他的就复杂了。
对于static final 字段,static readonly 是最接近的可能。它允许您在静态构造函数中初始化静态字段,这与 Java 中的静态初始化器非常相似。这适用于常量(基元和不可变对象)和对可变对象的常量引用。
const 修饰符与常量非常相似,但您不能在静态构造函数中设置它们。
在离开构造函数后不应重新分配的字段上,可以使用readonly。但它并不相等 - final 即使在构造函数或初始化程序中也需要一个赋值。
据我所知,final 局部变量没有 C# 等效项。如果您想知道为什么有人需要它:您可以在 if-else 之前声明一个变量,switch-case 左右。通过将其声明为 final,您可以强制它最多分配一次。
Java 局部变量通常需要在读取之前至少分配一次。除非分支在读取值之前跳出,否则最终变量只会分配一次。所有这些都是在编译时检查的。这需要行为良好的代码,错误余地较小。
总结起来,C# 没有直接等效于final。虽然 Java 缺少 C# 的一些不错的特性,但作为一个主要是 Java 程序员的我,看到 C# 未能提供同等功能的地方让我感到耳目一新。
【讨论】: