Item 11: Override clone judiciously (审慎的)
CloneNotSupportedException
2) 某个类要实现clone()方法,那么所有它的超类必须服从 a fairly complex,unenforceable,and thinly
documented protocol(一个相当复杂的,不能强制实行的的并且很小文档的协议?) 由此得到一个语言之
外的机制:无需调用构造函数便可创建对象
3) java se 6.0 上的api说明(不解释)
Creates and returns a copy of this object. The precise meaning of “copy” may
depend on the class of the object. The general intent is that, for any object x,
the expression
x.clone() != x
will be true, and the expression
x.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is typically the
case that
x.clone().equals(x)
will be true, this is not an absolute requirement. Copying an object will typi-
cally entail creating a new instance of its class, but it may require copying of
internal data structures as well. No constructors are called.
4) No constructors are called这个要求太强了,一个行为良好的clone方法可以在其内部数据成员上调用构造
函数,来完成clone的功能,如果实现clone的这个类是final的,则可以直接调用构造函数来创建本类的对象.
这里解释一下,如果是非final的类,如果也这么搞的话,那么子类如果也提供一个clone()方法,在调用super
.clone()是就会返回一个超类的实例.这样x.clone().getClass() == x.getClass()就不是true了
5) if you override the clone method in a nonfinal class, you should
return an object obtained by invoking super.clone. If all of a class’s super-
classes obey this rule, then invoking super.clone will eventually invoke
Object’s clone method, creating an instance of the right class.
5) 作为1.6的发行版,并没有讲实现Cloneable接口应该承担的责任.
在实践中,一个实现了Cloneable的类应该提供一个合适的公有clone方法
但这必须在它的所有超类都提供了一个公有的,或者保护的.well behaved clone implementation的基础上才可能完成
6) 如果超类就是Object并且数据成员只有不变类型或primitive类型这样写就OK
注意以下用了5.0的新特性covariant return type
@Override public PhoneNumber clone() {
try {
return (PhoneNumber) super.clone();
} catch(CloneNotSupportedException e) {
throw new AssertionError(); // Can't happen
}
}
Object.clone()方法会返回正确的类型,所有数据成员的值会和原对象一样. 对于非primitive非不变类型的类型会和原对象共享同一引用(事实上不变类型也在共享同一引用,但那是没关系的)
有一些例外,如果一个字段代表序列号或其他unique ID,或者代表对象的创建时间,这就需要在clone()方法中做出修正,即使这些字段是primitive或不变类型
7) Stack是你自己写的一个普通类,elements是一个Object 数组
@Override public Stack clone() {
try {
Stack result = (Stack) super.clone();
result.elements = elements.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
As of release 1.5, calling clone on an array returns an array whose compile-time
type is the same as that of the array being cloned.
如果 elements是final,那么这段代码就有问题.事实上,如果想要实现clone有必要移除某些final修饰符
8) 一个HashTable,内部用数组实现,数组的每个元素要么是null,要指向一个单向链表,这个单向链表的每个元素是一个键值 对和指向下一个的引用.出于性能的考虑,它并不是java.util.LinkedList
public class HashTable implements Cloneable {
private Entry[] buckets = ...;
private static class Entry {
final Object key;
Object value;
Entry next;
Entry(Object key, Object value, Entry next) {
this.key = key;
this.value = value;
this.next = next;
}
// Recursively copy the linked list headed by this Entry //这里写得很帅气
Entry deepCopy() {
return new Entry(key, value,
next == null ? null : next.deepCopy());
}
}
@Override public HashTable clone() {
try {
HashTable result = (HashTable) super.clone();
result.buckets = new Entry[buckets.length];
for (int i = 0; i < buckets.length; i++)
if (buckets[i] != null)
result.buckets[i] = buckets[i].deepCopy(); //注意这里
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
... // Remainder omitted
}
这里因为那个deepCopy()方法是递归调用,对链表的每一个元素要消耗一个stack frame, 如果这个链表过长,可能会引起Stack overflow
将递归改成循环
Entry deepCopy() {
Entry result = new Entry(key, value, next);
for (Entry p = result; p.next != null; p = p.next)
p.next = new Entry(p.next.key, p.next.value, p.next.next);
return result;
}
8)7的一个替代办法是
@Override public HashTable clone() {
try {
HashTable result = (HashTable) super.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
然后先初始化buckets数组,再对于这个hashtable的所有元素,再put进去一次
9)clone()方法中不应调用任何非final的,并且会被子类覆写的方法.这是由于java的多态机制决定的,类似于构造函数的情况.因为子类的数据成员此时还没有初始化.所以8)中的put方法或许应该是私有的.
这是为了解决子类的clone方法调用super.clone()可能会出现的问题,如果本类是final的就不用这样担心了
10)如果本类覆写clone方法是为了便于在子类中决定是否子类中也覆写
it should be declared protected, it should be declared to throw CloneNotSupportedExcep-
tion, and the class should not implement Cloneable.
11)如果想写一个线程安全的clone()方法,加入synchronized关键字吧,防止正clone的对象正处于某种内部不一致状态,和此对象的其他改变状态的方法共享同一个锁
12)对于clone()方法的替代方案
提供一个用于复制的构造函数
public Yum(Yum yum);
或者一个静态工厂方法
public static Yum newInstance(Yum yum);
或者叫做conversion constructors and conversion factories有新的功能,即新对象可以和原对象的类型不同,但数据是一样的
allow the client to choose the implementation type of the copy rather than forcing the client
to accept the implementation type of the original. Suppose you have a HashSet s,
and you want to copy it as a TreeSet. The clone method can’t offer this function-
ality, but it’s easy with a conversion constructor: new TreeSet(s).
相关推荐
基于springboot+vue的摄影作品社区(项目源码)
基于springboot+vue的摄影作品社区(项目源码) 系统采用前后端分离的 B/S 架构。后端基于 Spring Boot 2.7.2 与 Java 1.8 构建,以 MyBatis-Plus 完成数据访问、PageHelper 实现分页,用 MySQL 8 存储业务数据;身份认证采用 Sa-Token 轻量级框架并整合 JWT 令牌,配合 Redis 实现图形验证码缓存与会话存储;前端使用 Vue 3 与 Naive UI 构建界面,由 Vite 完成构建,看板统计图表基于 ECharts 渲染。系统面向普通用户与管理员两类角色:用户端提供注册登录、作品上传与归档、多条件检索浏览、作品集管理、分类与标签管理、摄影圈专题、回收站、个人设置与公告查看等功能;管理端提供数据看板、用户管理与公告管理等功能。
Vue基于springboot的乡村生态旅游平台_k2864o48毕业设计源码数据库.zip
Vue基于springboot的乡村生态旅游平台_k2864o48毕业设计源码数据库
Python3 datetime时区避坑指南
原生datetime.now()获取本地时间,不带时区属性,属于 naive时间,跨服务器比对会报错。带时区时间使用datetime.astimezone,强制绑定东八区时区。禁止手动加减8小时修改时差,夏令时更新会导致时间错误。时间计算:timedelta直接实现天数、小时增减,无需手动换算秒数。字符串解析使用strptime,格式化使用strftime,格式符号严格区分大小写,%Y四位年份、%y两位年份极易写错。线上时间异常大多源于时区不统一。 yc.ahsalar.com qsvsnks.yihucx.com tongjiang.xilaohan.com lq.aasmile.com xj.banutech.net
前端开发基于history.js的HTML5与HTML4浏览器兼容方案:单页应用无刷新历史状态管理技术实现-jcbbroJ3l1792421687
内容概要:本文系统介绍了如何利用history.js实现单页应用(SPA)在HTML5c与HTML4浏览器间s草错发的无缝历史状态管理。通过封装原生History API并在不支持的浏览器中自动降级为哈希路由,history.js解决了因浏览器兼容性导致的后退按钮失效、URL混乱等问题。文章详细讲解了其核心机制,包括状态对象管理、自动模式切换(HTML5 pushState vs HTML4 哈希)、状态数据持久化以及针,对Safari、IE等浏\览器的兼容性修复方案,并提供了从入门到实战的完整示例,涵盖初始化、事,件监听、页面加载及性能优化技巧。;jcbbroJ3l1792421687 www.kfshiye.com www.wap.kfstjx.com www.kuaicai-mro.com lianyingjs.com www.kdd888.com
MATLAB实现了约束感知混合水波和灰狼优化,用于作物规划。.zip
1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。


Java SE
