EFFECTIVE JAVA 类和接口
第十六条:复合优先于继承
//这是一个不好的类---执行的结果 addCount = 4(addAll的实现依赖于HashSet的add方法,InstrumentHashSet方法重写了add方法有执行了addCount++)
public class InstrumentHashSet<E> extends HashSet<E> {
private int addCount = 0 ;
@Override
public boolean add(E e) {
System.out.println("子类添加 ");
addCount++;
return super.add(e);
}
@Override
public boolean addAll(Collection<? extends E> c) {
addCount+= c.size();
System.out.println("添加所有 ");
return super.addAll(c);
}
public static void main(String[] args) {
InstrumentHashSet s = new InstrumentHashSet<String>();
s.addAll(Arrays.asList("1","2"));
System.out.println(s.addCount);
}
}
//wrapper class --- use composition in place of inheritance 因为每一个InstrumentedSet 实例都把另一个Set实例包装起来了,所以InstrumentedSet类被称为包装类(这正是Decorator模式)---注意这不是委托(delegation)除非包装对象把自身传递给被包装对象
public class InstrumentedSet<E> extends ForwardingSet<E> {
private int addCount = 0 ;
/**
* 描述: 构造方法
* @param s
*/
public InstrumentedSet(Set<E> s) {
super(s);
}
@Override
public boolean add(E e) {
System.out.println("我执行了InstrumentedSet 的add");
addCount++;
return super.add(e);
}
@Override
public boolean addAll(Collection<? extends E> c) {
System.out.println("执行 addAll c.size= " + c.size() +" count = "+ addCount);
addCount += c.size();
return super.addAll(c);
}
public int getAddcount(){
return addCount;
}
public static void main(String[] args) {
HashSet<Integer> s = new HashSet<Integer>();
s.add(1);
s.add(2);
HashSet<Integer> s1 = new HashSet<Integer>();
s1.add(3);
s1.add(4);
InstrumentedSet is = new InstrumentedSet<Integer>(s);
// is.add(3);
is.addAll(s1);
System.out.println(is.getAddcount());
}
}
//forwarding class 里面的转发方法称为转发方法(forwarding method) 这样得到的类非常的稳固,它不依赖于现有类的实现细节,即使现有的类添加了新的方法,也不会影响新的类
public class ForwardingSet<E> implements Set<E> {
private Set<E> s ;
/**
* 描述: 构造方法
*/
public ForwardingSet(Set<E> s) {
System.out.println("初始化s,类型:"+s.getClass());
this.s = s;
}
@Override
public int size() {
return s.size();
}
@Override
public boolean isEmpty() {
return s.isEmpty();
}
@Override
public boolean contains(Object o) {
return s.contains(o);
}
@Override
public Iterator<E> iterator() {
return s.iterator();
}
@Override
public Object[] toArray() {
return s.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return s.toArray(a);
}
@Override
public boolean add(E e) {
System.out.println("我执行了ForwardingSet 的add");
return s.add(e);
}
@Override
public boolean remove(Object o) {
return s.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return s.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
System.out.println("我执行了addAll");
return s.addAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return s.retainAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return s.removeAll(c);
}
@Override
public void clear() {
s.clear();
}
}
测试中的addAll方法实际上走的是HashSet的add方法
EFFECTIVE JAVA 类和接口的更多相关文章
- 要创建一个EJB,必须要至少编写哪些Java类和接口?
要创建一个EJB,必须要至少编写哪些Java类和接口? A. 定义远程(或业务)接口 B. 定义本地接口 C. 定义Bean接口 D. 编写Bean的实现 解答:ABC
- java类,接口浅谈
一般类,抽象类,接口的使用场景: 类;共同的特征和行为的抽取和封装 接口:标准,规范(功能的扩展) 需要对某个类进行功能的扩展,就让某个类实现这个接口,抽取出来称为接口 内部类: ...
- [Java] 类和接口的初始化步骤 - 继承方面
类和接口在初始化化时,处理继承层级的方法不一样. 类继承的初始化:通过引用 static 字段,触发某个类的初始化,则声明该字段的类,以及该类的父类被初始化. 接口继承的初始化:通过引用 static ...
- 和我一起学Effective Java之类和接口
类和接口 使类和成员的可访问性最小 信息隐藏(information hiding)/封装(encapsulation):隐藏模块内部数据和其他实现细节,通过API和其他模块通信,不知道其他模块的内部 ...
- Java 类、接口的API
本章节收集的类/接口API有: Object类,枚举,包装类,接口Comparable,类Arrays,Thread类,System类,Math,BigInteger,Random,日期时间,异常 O ...
- <<Effective Java>>之Comparable接口的实现约定
对于BigDecimal类在HashSet和TreeSet中 new BigDecimal("1.00") new BigDecimal("1.0") 在Has ...
- 10-01 Java 类,抽象类,接口的综合小练习--运动员和教练
运动员和教练的案例分析 运动运和教练的案例 代码实现 /* 教练和运动员案例 乒乓球运动员和篮球运动员. 乒乓球教练和篮球教练. 为了出国交流,跟乒乓球相关的人员都需要学习英语. 请用所学知识: 分析 ...
- Java常用类、接口关系图谱
呕心沥血画出此图,希望在使用Java类.接口时捋顺其关系,从而更好的组织程序逻辑---请看图 Object分出来的类都是其子类 Iterable接口分出的也是子接口 从继承关系分析,其父类实现的接口子 ...
- Java类的加载、链接和初始化
一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样 ...
随机推荐
- session和xsrf
1.pip install pycket 2.pip install redis 防止xsrf攻击只需在模板form标签加入: {% module xsrf_form_html() %} <!D ...
- 配置wpa_supplicant调试wifi linux下命令行连接wifi
调试wpa_supplicant先读一下对应的README.txt文件.根据README.txt修改编译配置. wpa_supplicant需要打开以下开关进行编译CONFIG_DRIVER_NL80 ...
- python的位运算
# &: 都是1,才为1,否则为零 # |: 都是0,才为0,否则为1 # ^: 相同为0,相异为1 a = bin(20) b = bin(16) print(a) # 0b10100 pr ...
- Django简单设置cookies和session
一.Cookie cookie及特点 Cookie是由服务器(网站)生成的,存储在浏览器端的 键值对数据(通常经过加密) 在响应请求时,服务器会把生成 Cookie数据 发给浏览器,浏览器会自动保存( ...
- JAVA线程池调优
在JAVA中,线程可以使用定制的代码来管理,应用也可以利用线程池.在使用线程池时,有一个因素非常关键:调节线程池的大小对获得最好的性能至关重要.线程池的性能会随线程池大小这一基本选择而有所不同 ...
- Openstack ceilometer
https://www.cnblogs.com/liguangsunls/p/6879879.html
- 服务器IIS禁止通过IP访问
之前发布的网站,只是配置端口信息,IP都选择的是*,所以一直没有考虑IP能访问的事情. 现在有个需求,就是只能通过域名访问,不能通过IP访问,那么做法就是给这个主机名添加上解析的域名,IP自然就失效了
- Python的扩展接口[1] -> 串口通信
串口通信 / Serial Communication 1 串口简介 / Serial Introduction 串行接口(Serial Interface)简称串口,通常为COM接口,数据发送方式为 ...
- 新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)- 勤奋的杨老师(最长递增子序列)
链接:https://www.nowcoder.com/acm/contest/116/C来源:牛客网 题目描述 杨老师认为他的学习能力曲线是一个拱形.勤奋的他根据时间的先后顺序罗列了一个学习清单,共 ...
- 树链剖分【p1505】[国家集训队]旅游
Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间 ...