Answers:
首先,我推荐这篇文章:Java:何时创建最终类
如果他们这样做了,他们什么时候使用它,以便我可以更好地理解它并知道何时使用它。
一个final
类就是一个不能扩展的类。
(这并不意味着所有对该类对象的引用都将如同声明为一样起作用final
。)
当将一个类声明为final有用时,请参见此问题的答案:
如果Java是面向对象的,并且您声明了一个类
final
,它是否会停止具有对象特征的类的想法?
从某种意义上说是的。
通过将一个类标记为final,可以禁用该部分代码的强大而灵活的语言功能。有些类然而,不应该(在某些情况下可以不)被设计充分继承考虑的一个好办法。在这些情况下,将类标记为最终类是有意义的,即使它限制了OOP。(但是请记住,最后一堂课仍然可以扩展另一个非最后一课。)
在Java中,带final
修饰符的项目无法更改!
这包括最终类,最终变量和最终方法:
final
不能修改带有修饰符的项!” 的说法过于明确,实际上并不完全正确。正如Grady Booch所说,“一个对象具有状态,行为和身份”。尽管一旦将对象的引用标记为最终对象,我们就无法更改其身份,但我们确实有机会通过向其非字段分配新值(当然,只要它具有它们)来更改其状态final
。计划获得Oracle Java认证(例如1Z0-808等)应牢记这一点,因为考试方面可能对此有疑问...
由于安全原因,当您要阻止类的继承时,final很重要。这使您可以确保正在运行的代码不会被某人覆盖。
另一种情况是优化:我似乎记得Java编译器内联了一些来自最终类的函数调用。因此,如果您调用a.x()
并声明了a final
,我们将在编译时知道代码将是什么并且可以内联到调用函数中。我不知道这是否真的完成,但最终还是有可能的。
最好的例子是
公共最后一堂课String
这是一个不变的类,不能扩展。当然,不只是使班级的决赛变得一成不变。
相关阅读:鲍勃·马丁(Bob Martin)的《开闭原则》。
关键语录:
软件实体(类,模块,功能等)应为扩展打开,但为修改而关闭。
该final
关键字是在Java中执行这个手段,无论是在方法或类上使用。
final
将类关闭以进行扩展而不是打开吗?还是我从字面上看呢?
final
如果您希望关闭实现代码以进行修改而打开以通过继承进行扩展,则在类/方法声明上使用on毫无意义。
关键字final
本身表示某些东西是最终的,不应以任何方式进行修改。如果标记了一个类final
,则不能扩展或子类化。但是问题是为什么我们要标记一个班级final
?IMO有多种原因:
我听说打标课final
提高了效率,但坦率地说,我找不到这种论点有多大意义。
如果Java是面向对象的,并且您将类声明为final,它是否会停止具有对象特征的类的想法?
也许是的,但有时这是预期的目的。有时,我们这样做是通过牺牲此类的扩展能力来获得更大的安全性等好处。但是如果需要的话,最后一堂课仍然可以扩展一堂课。
final class
添加新方法时可以避免破坏公共API
假设您在Base
课程的版本1中执行以下操作:
public class Base {}
客户执行以下操作:
class Derived extends Base {
public int method() { return 1; }
}
然后,如果要在版本2中添加一个method
方法到Base
:
class Base {
public String method() { return null; }
}
它将破坏客户端代码。
如果我们final class Base
改用了该客户端,则该客户端将无法继承,并且添加方法也不会破坏该API。
解决最终课程问题:
有两种方法可以使班级进入决赛。第一种是在类声明中使用关键字final:
public final class SomeClass {
// . . . Class contents
}
使类最终化的第二种方法是将其所有构造函数声明为私有:
public class SomeClass {
public final static SOME_INSTANCE = new SomeClass(5);
private SomeClass(final int value) {
}
如果将其标记为final,则可以省去麻烦,如果发现它确实是final,以演示一下此Test类。乍一看。
public class Test{
private Test(Class beanClass, Class stopClass, int flags)
throws Exception{
// . . . snip . . .
}
}
不幸的是,由于该类的唯一构造函数是私有的,因此无法扩展该类。对于Test类,没有理由该类应该是最终的。Test类是隐式最终类如何引起问题的一个很好的例子。
因此,当您通过将类的构造函数设为私有来隐式地使类为final时,应将其标记为final。
是的,出于安全或速度方面的原因,有时您可能需要这样做。它也在C ++中完成。它可能不是这适用于计划,但对于moreso框架。 http://www.glenmccl.com/perfj_025.htm
在java中final关键字用于以下场合。
在Java中,final变量无法重新分配,final类不能扩展,并且final方法不能覆盖。
Android Looper类是一个很好的实际例子。 http://developer.android.com/reference/android/os/Looper.html
Looper类提供某些功能,这些功能不应被任何其他类覆盖。因此,这里没有子类。
假设您有一个Employee
具有方法的类greet
。greet
调用该方法时,仅打印Hello everyone!
。所以这是预期行为的greet
方法
public class Employee {
void greet() {
System.out.println("Hello everyone!");
}
}
现在,让GrumpyEmployee
子类Employee
和重写greet
方法如下所示。
public class GrumpyEmployee extends Employee {
@Override
void greet() {
System.out.println("Get lost!");
}
}
现在在下面的代码中查看该sayHello
方法。它以Employee
instance作为参数,并调用greet方法,希望它会说Hello everyone!
但我们得到的是Get lost!
。行为上的变化是由于Employee grumpyEmployee = new GrumpyEmployee();
public class TestFinal {
static Employee grumpyEmployee = new GrumpyEmployee();
public static void main(String[] args) {
TestFinal testFinal = new TestFinal();
testFinal.sayHello(grumpyEmployee);
}
private void sayHello(Employee employee) {
employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
}
}
如果这种情况可以避免,Employee
上课,final
。试想一下,如果未将String
Class声明为,那么厚脸皮的程序员可能会造成多大的混乱final
。
对象定向与继承无关,它与封装有关。继承破坏了封装。
在许多情况下,宣布班级决赛很有意义。代表“价值”(例如颜色或金额)的任何对象都是最终的。他们自己站着。
如果要编写库,请使类为最终类,除非您明确缩进来派生它们。否则,人们可能会派生您的类并覆盖方法,从而破坏您的假设/不变式。这也可能涉及安全性。
Joshua Bloch在“ Effective Java”中建议显式设计继承或禁止继承,他指出进行继承设计并不那么容易。