目录
26.说说final类型的类如何扩展?
27.final方法可以被重载吗?
28.父类的final方法能不能被子类重写?
29.说说基本类型的final域重排序规则?
30.说说final的原理?
26.说说final类型的类如何扩展?
比如String是final类型,我们想写个MyString复用所有String中方法,同时增加一个新的toMyString()方法,应该如何做?
外观模式:
27.final方法可以被重载吗?
我们知道父类的final方法是不能够被子类重写的,那么final方法可以被重载吗?
答案是可以的,下面代码是正确的。
28.父类的final方法能不能被子类重写?
不可以
29.说说基本类型的final域重排序规则?
先看一段示例代码:
假设线程A在执行write()方法,线程B执行reader()方法。
写final域重排序规则
写final域的重排序规则禁止对final域的写重排序到构造函数之外,这个规则的实现主要包括了两个方面:
JMM禁止编译器把final的写重排序到构造函数之外;
编译器会在final域写之后,构造函数return之前,插入一个storestore屏障。这个屏障可以禁止处理器把final域的写重排序到构造函数之外。
我们再来分析writer方法,虽然只有一行代码,但实际上做了两件事情:
1.构造了一个FinalDemo对象;
2.把这个对象赋值给成员变量finalDemo;
读final域重排序规则
读final域重排序规则为:
在一个线程中,初次读对象引用和初次读该对象包含的final域,JMM会禁止这两个操作的重排序。(注意,这个规则仅仅是针对处理器),处理器会在读final域操作的前面插入一个LocalLoad屏障。实际上,读对象的引用和读该对象的final域存在间接依赖性,一般处理器不会重排序这两个操作。但是有一些处理器会重排序,因此,这条禁止重排序规则就是针对这些处理器而设定的。
read()方法主要包含了三个操作:
初次读引用变量finalDemo;
处理读引用变量finalDemo的普通域a;
初次读引用变量finalDemo的final域b;
30.说说final的原理?
写final域会要求编译器在final域写之后,构造函数返回前插入一个StoreStore屏障。
读final域的重排序规则会要求编译器在读final域的操作前插入一个LoadLoad屏障。
PS:很有意思的是,如果以X86处理为例,X86不会写-写重排序,所以StoreStore屏障可以省略。由于不会对有间接依赖性的操作重排序,所以在X86处理器中,读final域需要LoadLoad屏障也会被省略掉。也就是说,以X86为例的话,对final域的读/写的内存屏障都会被省略!具体是否插入还是得看是什么处理器。