在Java中使用final类
我正在读一本关于Java的书,它说,你可以宣布整个class级是final
。 我想不出什么地方可以用这个。
我只是新的编程,我想知道如果程序员真的在他们的程序中使用它 。 如果他们这样做,他们什么时候使用它,所以我可以更好地理解它,知道什么时候使用它。
如果Java是面向对象的,并且你声明了一个类的final
,那么它不会阻止类具有对象特性的想法吗?
如果他们这样做,他们什么时候使用它,所以我可以更好地理解它,知道何时使用它。
final
堂课只是一个不能扩展的课程。
(这并不意味着所有对类的对象的引用都会像被声明为final
。
如果在这个问题的答案中包含了最终声明的类是有用的:
- 在Java中禁止inheritance的好理由?
如果Java是面向对象的,并且你声明了一个类的
final
,那么它不会阻止类具有对象特性的想法吗?
在某种意义上是的。
通过将类标记为final,可以禁用该代码部分的语言的强大而灵活的function。 但是,某些类别不应该(并且在某些情况下不能)被devise为以良好的方式考虑子类别。 在这些情况下,将class级标记为最终class级是有意义的,尽pipe它限制了面向对象。 (不过要记住,最后一堂课还可以延续另一个非最终课。)
相关文章: Java:何时创build最终的类
在Java中,具有final
修饰符的项目不能更改!
这包括最终的类,最终variables和最终的方法:
- 最后一堂课不能被任何其他课程延伸
- 最后一个variables不能被重新分配给另一个值
- 最后的方法不能被覆盖
出于安全原因,当你想阻止类的inheritance时,final是重要的一个场景。 这使您可以确保您正在运行的代码不能被某人覆盖 。
另一个场景是优化:我似乎记得,Java编译器内嵌了来自最终类的一些函数调用。 所以,如果你调用ax()
和a被声明为final
,我们就知道在编译时代码是什么,并且可以内联到调用函数中。 我不知道这是否实际完成,但最终是可能的。
最好的例子是
public final class String
这是一个不可变的类,不能扩展。 当然,除了让课堂最终成为一成不变之外,
如果将类层次结构想象为树(就像在Java中一样),抽象类只能是分支,而最终类只能是叶子。 属于这两个类别的类都可以是分支和叶子。
这里没有违反面向对象的原则,最后只是提供了一个很好的对称性。
在实践中,如果你希望你的对象是不可变的,或者如果你正在编写一个API,就要使用final来向API的用户表明这个类只是不打算扩展。
相关阅读:鲍勃·马丁的开放式原则 。
重要报价:
软件实体(类,模块,函数等)应该为扩展打开,但为修改而closures。
final
关键字是在Java中执行这个操作的方法,无论是在方法上还是在类上使用。
如果这个类是final
标记,这意味着这个类的结构不能被任何外部的东西修改。 这里最明显的是当你做传统的多态inheritance时,基本上class B extends A
就是行不通的。 这基本上是一种保护代码的某些部分(以扩展)的方法 。
为了澄清,标记类final
并不标记它的字段为final
,因此不保护对象的属性,而是实际的类结构。
当你做“最后”的课时要小心。 因为如果你想为最后一个类编写一个unit testing,你不能为这个最后一个类inheritance子类,以便使用Michael C. Feathers的书“Working Withly Legacy Code”中描述的依赖断开技术“Subclass and Override Method” 。 在这本书中,Feathers说:“认真地说,很容易相信密封和最终是错误的错误,它们不应该被添加到编程语言中,但真正的错误在于我们,当我们直接依赖那些不在我们控制范围内的图书馆,我们只是在寻求麻烦。“
解决最终的问题:
有两种方法可以进行课堂决赛。 首先是在类声明中使用关键字final:
public final class SomeClass { // . . . Class contents }
做出类最后的第二种方法是将其所有构造函数声明为私有的:
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,当你隐式地做一个类的最终使它的构造函数是私有的。
关键字final
本身意味着某些事情是最终的,不应该以任何方式进行修改。 如果一个class如果有final
标记,则不能延长或分类。 但是问题是为什么我们要上课呢? 国际海事组织有各种原因:
- 标准化:一些类执行标准函数,而不是被修改,例如执行与string操作或math函数相关的各种函数的类。
- 安全原因 :有时我们编写的类会执行各种authentication和密码相关的function,我们不希望它们被其他人改变。
我听说标记课final
提高了效率,但坦率地说,我无法find这个论据来承担很多的重量。
如果Java是面向对象的,并且你声明了一个类的最后一个,那么它不会阻止类具有对象特性的想法吗?
也许是的,但有时这是预期的目的。 有时我们这样做是为了通过牺牲这个类的能力来扩大安全等更大的好处。 但是如果需要的话,最后一堂课仍然可以扩展一堂课。
在一个侧面说明,我们应该更喜欢组合而不是inheritance,并且final
关键字实际上有助于执行这个原则。
是的,有时你可能会想要这个,无论是出于安全或速度的原因。 它也在C ++中完成。 这可能不适用于程序,但更适用于框架。 http://www.glenmccl.com/perfj_025.htm
最后一堂课是一个不能扩展的课程。 也可以将方法声明为final来指示不能被子类覆盖。
如果您编写API或库,并且希望避免被扩展来改变基本行为,那么防止该类被子类化可能特别有用。
保持一个class最后的一个好处:
string类保持最终,以便没有人可以重写它的方法和改变function。 例如,没有人可以改变length()方法的function。 它总会返回一个string的长度。
这个类的开发人员不想改变这个类的function,所以他把它保留下来。
当你添加新的方法时, final class
可以避免打破公共API 。
假设在你的Base
类的第一版上你做了:
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
,那么客户端将无法inheritance,并且方法添加不会破坏API。
末class不能延长。 所以如果你想要一个类以某种方式行为,而不是某个人重写方法(可能效率更低,代码更恶意),那么你可以把整个类声明为最终的或者特定的方法,而你不想改变。
由于声明一个类并不妨碍一个类被实例化,这并不意味着它会阻止该类具有对象的特性。 只是你必须坚持这个方法,就像他们在课堂上宣布的那样。
把FINAL看作是“行末” – 那个家伙不能再生产后代了。 所以当你这样看的时候,你会遇到很多现实世界的场景,需要你给class级标记一个“行尾”标记。 这是域驱动devise – 如果您的域名要求给定的实体(类)不能创build子类,然后将其标记为最终。
我应该注意到,没有任何东西阻止你inheritance“应该被标记为final”类。 但是这通常被归类为“inheritance的滥用”,因为大多数情况下,您希望从类中的基类inheritance一些函数。
最好的办法是看看这个领域,让它决定你的devise决定。
如上所述,如果你不想改变方法的function,那么你可以声明它是最终的。
示例:用于下载/上传的应用程序服务器文件path,基于偏移量拆分string,可将这些方法声明为Final,以便这些方法函数不会被更改。 如果你想在一个单独的类中使用这样的最终方法,那么将该类定义为Final类。 所以Final类将有所有的最终方法,Final方法可以在非final类中声明和定义。
Android Looper类是一个很好的实例。 http://developer.android.com/reference/android/os/Looper.html
Looper类提供了某些不被任何其他类覆盖的function。 因此,这里没有子类。
如果你把任何课程作为最终的,你不能扩展它。
final class Bike{} class Honda1 extends Bike{ void run(){System.out.println("running safely with 100kmph");} public static void main(String args[]){ Honda1 honda= new Honda(); honda.run(); } } Output:Compile Time Error
面向对象不是关于inheritance,而是关于封装。 而inheritance则打破封装。
宣布一个类决赛在很多情况下是非常有意义的。 代表“颜色”或“金钱”等“价值”的任何对象都可能是最终的。 他们自立。
如果你正在编写库,除非你明确地将它们缩写为派生类,否则使你的类成为最终的。 否则,人们可能会派生你的类和重写方法,打破你的假设/不variables。 这也可能有安全隐患。
“有效的Java”中的Joshua Blochbuild议明确地deviseinheritance或禁止它,他指出为inheritancedevise并不那么容易。