[求解]为什么要设计final类和方法?

Dan1980 2005-03-03 09:31:41
我们知道final方法不能被覆盖, final类不能被继承, 因而类中所有的方法都不能被覆盖. 总而言之, 设计final类和方法就是防止方法被子类覆盖. 但实际应用中, 使用final类有什么好处呢? 我一直没搞清楚. 一般说到final类都是会提到java.lang包中的一些基本类, 比如String. 那么假设String类不是final的, 里面的方法也可以被覆盖, 那么我们可以编译并运行下面的代码:

public class MyString extends String {
public int length() {
return 0; //错误地覆盖了length()方法
}
}

假设上面的代码可以编译, 那么错误的length()方法也只存在于MyString中啊, 对父类String没有任何影响, 其他程序员还是一样可以正常使用String类啊, 这样用到底有什么害处呢? 不解.....
...全文
172 点赞 收藏 15
写回复
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
Dan1980 2005-03-03
to iwanghao(mice):

我说是final类和final方法, 不是final变量! 你的论述没有答到问题上.
回复
Dan1980 2005-03-03
to 楼上二位:

我说是final类和final方法, 不是final变量! 你们都没有答到问题上.

至于效率问题,Thinkng in JAVA中说到,final的引入有两个作用:设计和效率,final对于效率上的影响并不是十分明显,所以应该更多地从设计上考虑使用final.

to mor(天蓝,天蓝):
谢谢!原来Effective JAVA中说到了,回去翻翻。老早买了这本书,一直没心思细看。
回复
congbailing_914 2005-03-03
final的作用其实很简单的,就是安全性!
final类就是有一个最小类!
回复
rower203 2005-03-03
final的定义是为了执行效率。
回复
iwanghao 2005-03-03
final的一个用途是用来定义成个程序中不会变化的量。
比如像定义一个固定大小为10的Array,就可以用:
private final int ARRSIZE = 10;
private arr[] myArray = new arr[ARRSIZE];
还有比如像用重力,直接定义后可以直接用字母调用了。
一般的规则是final的定义名称要全部大写!
回复
mor 2005-03-03
http://community.csdn.net/Expert/topic/3804/3804457.xml?temp=.3036157
回复
mor 2005-03-03
to Dan1980(String someGoodAdvices):
如你所说,如果String类不是final的,你用了MyString继承了String,那么其他程序员在调用String类当然不会有什么影响,可能发生问题的是你的MyString。

面向对象的一个基本原则就是封装,把一项功能封装到一个类的方法中,调用这个方法的程序员不必关心这个方法的具体实现,只需知道输入和输出就可以了。但是继承是会破坏封装的,主要是在自用模式(self-use)下,发生继承时,程序员不但要了解父类的API,同时也必须了解这些功能的实现。你可以去看《Effective Java》的第15条,Bloch是Java语言的设计师之一,他很详细的解释了这个问题。我们可以看看他举的例子:java.util.AbstractCollection的rebove(Object o)方法:
public boolean remove(Object o) {
Iterator e = iterator();
……
}
它调用了自己的另一个方法iterator(),这样如果你在子类里覆盖了iterator()方法,会对remove(Object o)方法造成不明后果的影响,这样AbstractCollection的设计者必须在文档里详细的说明方法是如何实现的(破坏了封装),而继承类的开发人员必须去研究父类的实现,如果没有源码,还必须做很复杂的测试,以判断覆盖方法会不会对父类的其他方法造成何种的影响。

所以从面向对象的设计角度来说,如果不是专门为了继承而设计的类,就最好设成final的。当然在实际的应用中可能要考虑到方方面面,也许不能那么教条的去实现OO,但是必须写好详细的文档,并且要精心的设计父类。
回复
Dan1980 2005-03-03
自己up
回复
Dan1980 2005-03-03
to mor(天蓝,天蓝):
父类中一个方法调用另一个方法的情况有什么不同么? 能否举列说明?

to ChDw(米):
似乎有些明白了, 你的意思是不是说MyString可能改变一个String? 也就是说, 程序可能把一个错误的子类对象当作父类对象来对待?
回复
ChDw 2005-03-03
通常final的定义是为了安全、确定这些原因做的

很简单,String是一个Final类,因为它创建好以后不允许做任何的修改!
MyString myss = new MyString("AA");
String ss = myss;
hashmap.put(ss, obj);
myss.addsubstring("cc");

这样一来,在Hashmap中的ss的值就发生改变了,以后再hashmap.get("AA");就不再可能再获得了
这样就变得无法得知后果了
回复
mor 2005-03-03
如果父类中有自引用呢?就是一个方法调用自己的另一个方法
回复
Dan1980 2005-03-03
up
回复
Hodex 2005-03-03
Effective JAVA 不错,得反复研究,最好看看设计模式
回复
knight_yl 2005-03-03
up
回复
Dan1980 2005-03-03
up
回复
发动态
发帖子
Java SE
创建于2007-09-28

6.1w+

社区成员

Java 2 Standard Edition
申请成为版主
社区公告
暂无公告