在c#中,什么相当于Java's final ?

在c#中,什么相当于Java的final ?

335328 次浏览

final关键字在Java中有几种用法。它对应c#中的sealedreadonly关键字,这取决于使用它的上下文。

防止子类化(从已定义的类继承):

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表达式在运行时而不是编译时处求值,因此允许任意表达式。

这取决于上下文。

密封

http://en.csharp-online.net/CSharp_FAQ:_What_are_the_differences_between_CSharp_and_Java_constant_declarations

c#常量使用const关键字声明编译时常量,使用readonly关键字声明运行时常量。在c#和Java语言中,常量的语义是相同的。

Java类final和方法final ->密封。 Java成员变量final ->为运行时常量的readonly,编译时常量的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之前声明一个变量,切换实例等等。通过声明它为final,可以强制它最多被赋值一次。

    一般来说,Java局部变量在读取之前至少需要赋值一次。除非分支在值读取之前跳出,否则最终变量只被赋值一次。所有这些都是在编译时检查的。这需要行为良好的代码和更少的错误容错性。

综上所述,c#没有与final直接对应的东西。虽然Java缺少c#的一些不错的特性,但作为一个Java程序员,看到c#在哪些方面没有提供相应的特性,让我感到耳目一新。