锁定老帖子 主题:我发现了一个悖论
精华帖 (0) :: 良好帖 (9) :: 新手帖 (0) :: 隐藏帖 (6)
|
|
---|---|
作者 | 正文 |
发表时间:2011-08-22
最后修改:2011-08-23
今天,我发现了一个java的悖论。 在java.lang.Object类中,对于clone方法的注释描述中,有如下一段话: *The class <tt>Object</tt> does not itself implement the interface * <tt>Cloneable</tt>, so calling the <tt>clone</tt> method on an object * whose class is <tt>Object</tt> will result in throwing an * exception at run time. 这是一个本地化方法。 既然Object本身没有实现Cloneable接口,为啥要将Cloneable设计为标记接口,而又将clone方法放入Object类中呢? 为啥不向Runnable这样,里面写个方法clone呢。 像下面这样子: /* * @(#)Cloneable.java 1.17 05/11/17 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.lang; /** * A class implements the <code>Cloneable</code> interface to * indicate to the {@link java.lang.Object#clone()} method that it * is legal for that method to make a * field-for-field copy of instances of that class. * <p> * Invoking Object's clone method on an instance that does not implement the * <code>Cloneable</code> interface results in the exception * <code>CloneNotSupportedException</code> being thrown. * <p> * By convention, classes that implement this interface should override * <tt>Object.clone</tt> (which is protected) with a public method. * See {@link java.lang.Object#clone()} for details on overriding this * method. * <p> * Note that this interface does <i>not</i> contain the <tt>clone</tt> method. * Therefore, it is not possible to clone an object merely by virtue of the * fact that it implements this interface. Even if the clone method is invoked * reflectively, there is no guarantee that it will succeed. * * @author unascribed * @version 1.17, 11/17/05 * @see java.lang.CloneNotSupportedException * @see java.lang.Object#clone() * @since JDK1.0 */ public interface Cloneable<T> { /** * Blalala.. */ public T clone(); } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-08-22
object带的clone不是开发者自己实现的clone,所以跟clonable没有关系。
Runnable是需要用户自己实现的。 and 如果加个这么的接口, 你也该是 public Object clone(); 你clone不能void啊 |
|
返回顶楼 | |
发表时间:2011-08-23
Joshua Bloch提到过这个问题。
算是历史遗留问题吧。 |
|
返回顶楼 | |
发表时间:2011-08-23
H_eaven 写道 Joshua Bloch提到过这个问题。
算是历史遗留问题吧。 其实是小弟看了本坛的一篇帖子,也来学着多读代码。 首先就仔细读了Object类,发现了这个疑问。 没想到又被人在投隐藏。 |
|
返回顶楼 | |
发表时间:2011-08-23
隐藏很可怕吗?
|
|
返回顶楼 | |
发表时间:2011-08-23
jackra 写道 隐藏很可怕吗?
不可怕 但是对发帖者是一个不小的打击~ PS:为什么我不能投票 |
|
返回顶楼 | |
发表时间:2011-08-23
这个问题主要是不想让所有的对象都具有clone的能力,所以是Object的clone方法是protected,这样就无法实现Cloneable接口了,因为方法的访问权限不能被降低。
但是如果不在Object中实现默认的clone,那么像你说类似于Runable的,但用户无法实现Cloneable接口,因为clone是需要通过本地方法来实现copy。 当然可以提供一个Clone的Utils工具方法实现Clone,但在Object添加clone方法和实现Cloneable标记接口显得更加OO和自然一些。 |
|
返回顶楼 | |
发表时间:2011-08-23
fuliang 写道 这个问题主要是不想让所有的对象都具有clone的能力,所以是Object的clone方法是protected,这样就无法实现Cloneable接口了,因为方法的访问权限不能被降低。
但是如果不在Object中实现默认的clone,那么像你说类似于Runable的,但用户无法实现Cloneable接口,因为clone是需要通过本地方法来实现copy。 当然可以提供一个Clone的Utils工具方法实现Clone,但在Object添加clone方法和实现Cloneable标记接口显得更加OO和自然一些。 感谢讨论! 方法clone是protected修饰,protected是对本类、同包的类和子类可访问的,所以说clone方法是完全可以override的,因为java中所有的类和接口都是继承自Object类的。 对于clone这个本地方法做的事,确实如你所说,用接口去定义是无法直接实现copy功能,至少我不知道仅用java怎么去实现copy。但是是否可以通过一些方法,首先实例化一个同样的类实例,然后将原来实例的所有属性值进行copy呢,就像赋值语句那样?这样做可能在效率上或者安全方面比较欠缺。 对于更加OO的观点,我觉得对于这个问题来说,每个人有每个人的答案。 |
|
返回顶楼 | |
发表时间:2011-08-24
clone()是个本地方法,而接口里只能定义public abstract的方法,不能定义native方法。java.lang.Cloneable接口跟java.io.Serializable一样只是个标志接口。楼主说的对,对于OO的观点,每个人都有每个人的答案,我的观点是这样的:clone()放到Object类中,可选择性的让需要克隆的类实现Cloneable接口。克隆是每个对象都应该拥有的功能,而这个功能应该放到一个可实例化的类中,而Cloneable接口作为一个标志接口,相当于一个证件。举一个我觉得有点类似的例子,比如现实生活中“出国”一样,按理来说,众生平等,人人都可以拥有“出国”的想法和行动,但是在政策的制约下必须得有签证才行。比如定义一个接口是"拿到签证的人",一个类“人”,一个方法“出国()”.“出国()”应该定义到“人”这个类里更合适吧。
|
|
返回顶楼 | |
发表时间:2011-08-24
zhoujianghai 写道 clone()是个本地方法,而接口里只能定义public abstract的方法,不能定义native方法。java.lang.Cloneable接口跟java.io.Serializable一样只是个标志接口。楼主说的对,对于OO的观点,每个人都有每个人的答案,我的观点是这样的:clone()放到Object类中,可选择性的让需要克隆的类实现Cloneable接口。克隆是每个对象都应该拥有的功能,而这个功能应该放到一个可实例化的类中,而Cloneable接口作为一个标志接口,相当于一个证件。举一个我觉得有点类似的例子,比如现实生活中“出国”一样,按理来说,众生平等,人人都可以拥有“出国”的想法和行动,但是在政策的制约下必须得有签证才行。比如定义一个接口是"拿到签证的人",一个类“人”,一个方法“出国()”.“出国()”应该定义到“人”这个类里更合适吧。
这个例子举得很形象,深表赞同。 |
|
返回顶楼 | |