Java中"最后一课"的意义何在?

new*_*bie 528 java final

我正在读一本关于Java的书,它说你可以把全班宣布为final.我想不出任何我会用它的地方.

我刚接触编程,我想知道程序员是否真的在他们的程序中使用它.如果他们这样做,他们何时使用它,以便我能更好地理解它并知道何时使用它.

如果Java是面向对象的,并且你声明了一个类final,那么它是否会阻止具有对象特征的类的想法?

aio*_*obe 493

如果他们这样做,他们何时使用它,以便我能更好地理解它并知道何时使用它.

final类是仅仅是一个类不能扩展.

(这并不意味着对类的对象的所有引用都将被视为声明为final.)

如果将一个类声明为final是有用的,请参阅此问题的答案:

如果Java是面向对象的,并且你声明了一个类final,那么它是否会阻止具有对象特征的类的想法?

在某种意义上是的.

通过将类标记为final,您可以为该部分代码禁用该语言的强大而灵活的功能.有些类然而,不应该(在某些情况下可以不)被设计充分继承考虑的一个好办法.在这些情况下,将类标记为final是有意义的,即使它限制了OOP.(但请记住,最终的课程仍然可以扩展另一个非最终课程.)


相关文章:Java:何时创建最终类

  • 为了补充答案,Effective Java的原则之一是支持组合而不是继承.使用final关键字也有助于强制执行该原则. (34认同)
  • @MRA如果我创建一个接受String作为参数的方法,我认为它是不可变的,因为字符串是.因此,我知道我可以安全地调用String对象上的任何方法,而不是更改传递的String.如果我要扩展String,并更改substring的实现以更改实际的String,那么您期望不可变的String对象不再是不可变的. (24认同)
  • "你这样做主要是为了提高效率和安全性." 我经常听到这句话(甚至维基百科也说过这一点),但我仍然不明白这一论点背后的原因.有人关心如何解释一个非最终的java.lang.String如何最终导致低效或不安全? (9认同)
  • @Cruncher为什么不将子字符串设置为“final”并让字符串保持开放状态以便扩展?这符合肖恩·帕特里克·弗洛伊德帖子中提到的“开闭原则”。 (4认同)
  • @Sortofabeginner 一旦你说你希望所有 String 方法和字段都是最终的,这样你就可以创建一些具有附加功能的类......此时你不妨创建一个具有字符串和创建对该字符串进行操作的方法。 (2认同)

and*_*qee 176

在Java中,具有final修饰符的项目无法更改!

这包括最终类,最终变量和最终方法:

  • 任何其他类都不能扩展最终类
  • 最终变量不能重新分配另一个值
  • 最终方法无法覆盖

  • 实际问题是_why_,而不是_what_. (31认同)
  • 声明,"在Java中,带有`final`修饰符的项目无法更改!",过于绝对,实际上并不完全正确.正如Grady Booch所说,"一个对象具有状态,行为和身份".虽然我们无法在其引用标记为final后更改对象的标识,但我们确实有机会通过为其非`final`字段分配新值来更改其**状态**(当然,提供它如果有人计划获得Oracle Java认证(例如1Z0-808等),请记住这一点,因为考试中可能存在这方面的问题...... (7认同)
  • 不赞成投票。这不能回答问题。 (3认同)

Sha*_*sky 30

出于安全原因,当您想要阻止类的继承时,final的一个重要场景.这允许您确保您正在运行的代码不能被某人覆盖.

另一种情况是优化:我似乎记得Java编译器在最终类中内联了一些函数调用.所以,如果你调用a.x()a和声明final,我们在编译时知道代码是什么,并且可以内联到调用函数中.我不知道这是否真的已经完成,但最终有可能.

  • 内联通常仅在运行时由即时编译器完成.它也没有最终的工作,但JIT编译器还有一些工作要做,以确保没有扩展类(或者这些扩展类不接触这种方法). (7认同)

小智 21

最好的例子是

public final class String

这是一个不可变的类,无法扩展.当然,不仅仅是让类最终成为不可变的.


biz*_*lop 15

如果将类层次结构想象为树(就像在Java中一样),抽象类只能是分支,而最终类只能是叶子.既不属于这些类别的类也可以是分支和叶子.

这里没有违反OO原则,最终只是提供了一个很好的对称性.

实际上,如果您希望对象是不可变的,或者您正在编写API,那么您希望使用final,以向API的用户发出该类不是用于扩展的信号.


Sea*_*oyd 15

相关阅读:Bob Martin 的开放原则.

关键报价:

软件实体(类,模块,函数等)应该对Extension进行打开,但对于Modification是关闭的.

final关键字是在Java中执行这个手段,无论是在方法或类上使用.

  • 在OCP中,"修改"是指修改源代码,"扩展"是指实现继承.因此,如果您希望关闭实现代码以进行修改但是通过继承打开扩展,则在类/方法声明中使用`final`是没有意义的. (25认同)
  • @Sean:没有声明它是'final`使得课程因为扩展而不是开放而关闭?或者我是否太过字面意思? (6认同)
  • @Goran全球申请决赛,是的.关键是有选择地在你不想修改的地方申请决赛(当然也可以为扩展提供良好的钩子) (4认同)

i_a*_*ero 11

关键字final本身意味着某些东西是最终的,不应该以任何方式进行修改.如果某个类如果标记final则则不能扩展或分类.但问题是我们为什么要上课final?IMO有各种原因:

  1. 标准化:某些类执行标准函数,并不打算进行修改,例如执行与字符串操作或数学函数等相关的各种函数的类.
  2. 安全原因:有时我们会编写执行各种身份验证和密码相关功能的类,我们不希望其他任何人更改它们.

我听说标记课final提高了效率,但坦率地说,我发现这个论点不太重要.

如果Java是面向对象的,并且你声明了一个类final,那么它是否会阻止类具有对象特征的想法?

也许是的,但有时这是预期的目的.有时我们通过牺牲这个类的扩展能力来实现更大的安全性等.但是如果需要的话,最终的类仍然可以扩展一个类.

另外,我们应该更喜欢组合而不是继承,final关键字实际上有助于实施这一原则.


Jua*_*nZe 7

final 类是不能扩展的类。也可以将方法声明为 final 以指示不能被子类覆盖。

如果您编写 API 或库并希望避免被扩展以改变基本行为,则防止类被子类化可能特别有用。


Ben*_* Wu 6

当你上课"最后"时要小心.因为如果你想为最后一个类编写单元测试,你不能继承这个最终类,以便使用Michael C. Feathers的书"有效地使用遗留代码"中描述的依赖性破坏技术"子类和覆盖方法". .在这本书中,Feathers说,"说真的,很容易相信密封和最终是一个错误的错误,他们应该永远不会被添加到编程语言中.但真正的错误在于我们.当我们直接依赖我们无法控制的图书馆,我们只是在寻找麻烦."


小智 6

在 java final 关键字用于以下场合。

  1. 最终变量
  2. 最终方法
  3. 期末班

在 Java 中,final 变量不能重新分配,final 类不能扩展,final 方法不能覆盖。


Esk*_*sko 5

如果标记了类final,则意味着类的结构不能被外部的任何东西修改.这是最明显的,当你进行传统的多态继承时,基本上class B extends A只是不起作用.它基本上是一种保护代码某些部分(扩展)的方法.

为了澄清,标记类final不会将其字段标记为final,因此不会保护对象属性,而是保护实际的类结构.


mel*_*ngs 5

解决最终类问题:

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

public final class SomeClass {
  //  . . . Class contents
}
Run Code Online (Sandbox Code Playgroud)

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

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }
Run Code Online (Sandbox Code Playgroud)

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

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}
Run Code Online (Sandbox Code Playgroud)

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

所以当你通过使它的构造函数私有来隐式地使类最终时,你应该将它标记为final.


Cir*_*四事件 5

final class 可以避免在添加新方法时破坏公共API

假设您在Base课程的第1版中执行以下操作:

public class Base {}
Run Code Online (Sandbox Code Playgroud)

和客户做:

class Derived extends Base {
    public int method() { return 1; }
}
Run Code Online (Sandbox Code Playgroud)

然后,如果在版本2中您想要添加method方法Base:

class Base {
    public String method() { return null; }
}
Run Code Online (Sandbox Code Playgroud)

它会破坏客户端代码.

如果我们使用了final class Base,那么客户端将无法继承,并且添加方法不会破坏API.