何时在课前使用“final”关键字?

时间:2013-06-21 05:53:30

标签: java

我知道当在Class之前使用final关键字时,Class不能被另一个Class继承。

但我从未在Java Coding中看到它的实际用法,除了不可变类。

在哪种情况下,确实需要在Class之前使用final关键字?

它不会降低Java语言的可重用性吗?

5 个答案:

答案 0 :(得分:2)

final类无法进行子类化。这样做是出于安全和效率的原因。 Java API中的一些类是final,例如java.lang.System。有时,安全性和不变性比重用性更重要。

根据IBM developerWorks article

  

常见的看法是,声明类或方法最终使编译器更容易内联方法调用,但这种看法是不正确的(或者至少,被夸大了)。

     

最终的类和方法在编程时会带来很大的不便 - 它们限制了重用现有代码和扩展现有类功能的选择。虽然有时候一个班级是有充分理由的,例如强制执行不变性,但使用final的好处应该超过不便之处。性能增强几乎总是破坏良好的面向对象设计原则的一个坏理由,当性能提升很小或不存在时,这确实是一个糟糕的权衡。

另请阅读此Open Closed Principle

  

软件实体(类,模块,函数等)应该打开用于扩展,但关闭用于修改。

答案 1 :(得分:2)

最终类不能继承。因此,如果您希望没有人可以继承您的课程,那么您可以将其声明为最终课程。所以你已经回答了自己的问题。所以主要用途是

  1. 不可变类型
  2. 如果你不想让某人延长课程时间。
  3. 两者都是出于安全考虑而使用的。通过使用关键类来保护您的系统不被更改。这不是一个理由吗?

答案 2 :(得分:1)

final 关键字可以与类一起使用以提供安全性。我们可以以 String 为例。 String类是 immutable 以及最终的,以增强java中文件处理的安全性。

  

虽然,性能也是一个原因(假设您已经知道维护内部字符串池,以确保多次使用相同的String对象而不必多次创建/重新声明它),但String在Java中变为不可变的主要原因是“安全性”。惊讶吗?让我们理解为什么。

     

假设您需要打开一个安全文件,要求用户对自己进行身份验证。假设有两个用户名为“user1”和“user2”,他们分别拥有自己的密码文件“password1”和“password2”。显然'user2'不应该访问'password1'文件。

     

我们知道Java中的文件名是使用字符串指定的。即使您创建了一个“文件”对象,也只能将该文件的名称作为字符串传递,并将该字符串作为其成员之一保存在File对象中。

     

如果String是可变的,'user1'可能已经使用他的凭据登录,然后以某种方式可以设法将其密码文件名(String对象)的名称从'password1'更改为'password2',然后JVM实际放置本机OS系统调用打开文件。这将允许'user1'打开user2的密码文件。可以理解,这会导致Java中存在严重的安全漏洞。我知道有很多'可以在这里,但你肯定会同意它会打开一扇门,允许开发人员有意或无意地搞乱许多资源的安全性。

     

在Strings不可变的情况下,JVM可以确保相应File对象的文件名实例成员将继续指向同一个未更改的“filename”String对象。无论如何,作为File类中的'final'的'filename'实例成员不能被修改为指向任何其他String对象,指定除预期文件之外的任何其他文件(即,用于创建File对象的文件)。

可在此处找到更多信息Source A Source B

答案 3 :(得分:-1)

我研究这个,我在Hardcore Java上看到了这个,出版商:O'Reilly ISBN:0-596-00568-7

为什么要为类标记最终:

有两种方法可以让课程最终成功。第一种是在类声明中使用关键字final:

public final class SomeClass {
  //  . . . Class contents
}

使类最终成功的第二种方法是将其所有构造函数声明为private:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

如果发现它确实是最终版本,那么将它标记为最终可以省去麻烦,以展示这个Test类。乍一看看起来很公开。

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

不幸的是,由于该类的唯一构造函数是私有的,因此无法扩展此类。对于Test类,没有理由认为该类应该是final。 Test类是隐式final类如何导致问题的一个很好的例子。

因此,当您通过使其构造函数为私有来隐式地使类成为最终时,您应该将其标记为最终。

答案 4 :(得分:-3)

final类无法进行子类化。即使它有一些缺点,这对提高安全性也是必要的。

E.g。班级java.lang.Stringfinal。因此,您不能将String作为子类,并且可以确保String参数永远不是执行某些有害操作的子类(例如,在某处发送String)。