-
final作用于类上:表示该类不可被继承
某些类在设计的时候,可能出于安全的考虑,不希望被继承,例如String类。final类中的属性和方法可以是final或者非final,但是由于不能被继承,也就意味着final类中的方法都是final的,当然你也可以显式去指定。在《Effective Java》一书中,有句名言“design and document for inheritance or else prohibit it”,用我们的话来解读就是尽可能的将类设计成final的。在Kotlin中就是这么做的,一个类或者方法默认情况下都是final的,如果你要想类或者方法被子类继承或重写,你需要显式地使用open关键字。
-
final作用于方法上:表示该方法不能被重写
- final和abstract关键字能一起使用吗?答案是不能,因为它们所要表达的语法含义刚好是矛盾的,前者表示方法不能被重写,而后者表示该方法需要被子类去实现、去重写。
- private方法隐式地被声明成final.因为private方法在子类中是不可见的,当然也就不能被重写,自然而然也就是final的
-
final作用于类的属性上:表示该属性值不能被修改
- final属性可以在哪些地方被初始化?
- 如果修饰的是实例变量,那么可以在声明处、构造器以及实例代码块中进行初始化
- 如果修饰的是static变量,那么可以在声明处以及静态代码块中进行初始化
-
为什么Android开发的相关资料上都建议将常量定义成static final的?
当然目的是为了性能优化。但是并不是所有情况下都能起到性能优化的作用:当用来修饰基本数据类型或者是String类型(字面量的形式,非引用类型)时,是可以起到性能优化的作用的;当用来修饰引用类型时,起不到任何优化的作用。原因是由于:在编译期,对于static final修饰的基本数据类型域会在引用的地方直接替换成立即数,对应的字节码指令就是const/n(n表示几字节的常量);对于static final修饰的String类型(非引用)在引用处被常量池索引id所替代,它对应的字节码指令const-string;而对于static final修饰的引用类型,在访问处对应的字节指令为sget,sget指令相比较前两者,虚拟机在解释时要做的工作会更多,会更加繁重。
-
通过反射修改final修饰的域时,注意Android和Java中是不同的,在Android的Field类是用accessFlags字段来表示的,而在Java中的Field类是用modifiers字段来表示的。
-
在多线程环境中,将类中的属性声明为final时,有利于线程安全,因为何时何地,你对final属性的访问结果都是一致的
- final属性可以在哪些地方被初始化?
-
final作用于局部变量上:表示该属性值不能被修改
- Java8之前的语法要求:当在一个匿名内部类中访问外部的局部变量时,在Java8之前,是需要显式地将被访问的局部变量声明成final的,至于为什么大家可以看这篇文章。
- 编码习惯:我们在阅读某些框架源码时,经常在方法中对于成员域的访问时,都是先用一个局部变量来接收,之后对于成员域的访问都是使用这个局部变量的。这点很好理解,表示在这个方法里面对于成员域执行的是只读操作,这样在排查或者跟踪成员域的变化流程时,会很方便。而且在这种情况下,这个局部变量都会用final修饰,可能是为了强调这种只读性吧。
final关键字在Android和Java中使用总结
最新推荐文章于 2022-07-27 16:10:21 发布