2015062806 - EffactiveJava笔记 - 第41条 慎用重载(2)
2015-06-28 11:55
295 查看
----->02.基本类型和包装类导致的重载问题
java1.5之前,所有基本类型根本不同于所有的引用类型,但是引入自动拆箱和装箱,导致了真正的麻烦.
import java.util.*;
public class SetList {
publicstatic void main(String[] args) {
Set<Integer>set = new TreeSet<Integer>();
List<Integer>list = new ArrayList<Integer>();
/*-3, -2, -1, 0, 1, 2 */
for(int i = -3; i < 3; i++) {
set.add(i);
list.add(i);
}
for(int i = 0; i < 3; i++) {
set.remove(i);
list.remove(i);
}
System.err.println(set+ " " + list);
}
}
程序把-3到2之间的整数添加到排列好的集合和列表中,然后在集合和列表中进行3次remove操作.
代码意图从集合和列表中删除0, 1, 2,而打印出[-3,-2,-1] [-3,-2,-1]
实际结果从集合中实现既定目标,列表中删除奇数位置数据,打印出[-3,-2,-1] [-2,0,2]
为什么会出现这种情况呢?
实际情况是set.remove(i)调用选择重写方法remove(E),E是集合元素类型.将i从int自动装箱到Integer中,这是期待的行为,因此陈旭不会从集合中去除正值.[重写的方法是boolean remove(Object o);]
list.remove(i)调用的是重载的remove(i),在方法定义中可以看出remove(int index),i表示的是索引值,而不是具体的数据对象.
[E remove(int index); boolean remove(Object o);]
[-3, -2, -1, 0, 1, 2]删除数据后就是[-2, 0, 2]
如何解决这个问题呢?
就是将int数字,变成Integer对象,从而选择boolean remove(Object o),即:list.remove(Integer.valueOf(i));
类比开始部分CollectionClassifier中的问题出现,原因在于,java1.5之前List接口只有remove(Object),而没有remove(int),在java1.5后泛型和自动装箱拆箱,破坏了List接口中的remove方法.
[个人总结,方法重载之所以会出现很多问题,可能的原因:是因为期待运行时调用的方法并没有实现,实现的是编译时调用的方法;是因为重载的方法参数类型存在继承或者实现关系导致的.]
[本节后半部分翻译有问题,不准确;同时翻译的和本节没啥关系的感觉,很生硬地插播广告一般!]
总结慎用重载:
1.”能够重载”并不意味着就”应该重载”方法.
2.对于多个具有参数个数相同的方法来说,应该避免重载方法
3.构造方法,多个参数个数相同的构造方法进行重载谨慎使用.避免以下情况,同一参数只需经过类型转换就可以被传递给不同的重载方法.
4.如果不能避免同一参数只需经过类型转换就可以被传递给不同的重载方法的情况(通常是改造类和接口),那么就要保证:当传入同样的参数,所有的重载方法的行为保持一致.
[重载方法调用是在编译时,而不是运行时;
相同参数个数的重载方法,对应位置的参数尽可能不要存在继承或者实现关系;
相同参数个数的重载方法,对应位置的参数存在继承或者实现关系,那么保证重载方法的行为一致]
java1.5之前,所有基本类型根本不同于所有的引用类型,但是引入自动拆箱和装箱,导致了真正的麻烦.
import java.util.*;
public class SetList {
publicstatic void main(String[] args) {
Set<Integer>set = new TreeSet<Integer>();
List<Integer>list = new ArrayList<Integer>();
/*-3, -2, -1, 0, 1, 2 */
for(int i = -3; i < 3; i++) {
set.add(i);
list.add(i);
}
for(int i = 0; i < 3; i++) {
set.remove(i);
list.remove(i);
}
System.err.println(set+ " " + list);
}
}
程序把-3到2之间的整数添加到排列好的集合和列表中,然后在集合和列表中进行3次remove操作.
代码意图从集合和列表中删除0, 1, 2,而打印出[-3,-2,-1] [-3,-2,-1]
实际结果从集合中实现既定目标,列表中删除奇数位置数据,打印出[-3,-2,-1] [-2,0,2]
为什么会出现这种情况呢?
实际情况是set.remove(i)调用选择重写方法remove(E),E是集合元素类型.将i从int自动装箱到Integer中,这是期待的行为,因此陈旭不会从集合中去除正值.[重写的方法是boolean remove(Object o);]
list.remove(i)调用的是重载的remove(i),在方法定义中可以看出remove(int index),i表示的是索引值,而不是具体的数据对象.
[E remove(int index); boolean remove(Object o);]
[-3, -2, -1, 0, 1, 2]删除数据后就是[-2, 0, 2]
如何解决这个问题呢?
就是将int数字,变成Integer对象,从而选择boolean remove(Object o),即:list.remove(Integer.valueOf(i));
类比开始部分CollectionClassifier中的问题出现,原因在于,java1.5之前List接口只有remove(Object),而没有remove(int),在java1.5后泛型和自动装箱拆箱,破坏了List接口中的remove方法.
[个人总结,方法重载之所以会出现很多问题,可能的原因:是因为期待运行时调用的方法并没有实现,实现的是编译时调用的方法;是因为重载的方法参数类型存在继承或者实现关系导致的.]
[本节后半部分翻译有问题,不准确;同时翻译的和本节没啥关系的感觉,很生硬地插播广告一般!]
总结慎用重载:
1.”能够重载”并不意味着就”应该重载”方法.
2.对于多个具有参数个数相同的方法来说,应该避免重载方法
3.构造方法,多个参数个数相同的构造方法进行重载谨慎使用.避免以下情况,同一参数只需经过类型转换就可以被传递给不同的重载方法.
4.如果不能避免同一参数只需经过类型转换就可以被传递给不同的重载方法的情况(通常是改造类和接口),那么就要保证:当传入同样的参数,所有的重载方法的行为保持一致.
[重载方法调用是在编译时,而不是运行时;
相同参数个数的重载方法,对应位置的参数尽可能不要存在继承或者实现关系;
相同参数个数的重载方法,对应位置的参数存在继承或者实现关系,那么保证重载方法的行为一致]
相关文章推荐
- Java数组备忘录
- java.util.logging.Logger使用详解
- LeetCode_61---Rotate List
- ubuntu中安装jdk配置环境变量
- 项目报错:Cannot find class file for javax/servlet/ServletException
- Java读书笔记一(异常处理)
- Spring配置web.xml的<servlet>标签
- 【Java进阶】单例模式详解
- spring整合struts小结
- Java-J2SE学习笔记-树状展现文件结构
- MyEclipse 启动报错:'Building workspace' has encountered a problem解决方法
- Java 无法导入javax.annotation.Resource
- Java 内存分配、对象生命周期与垃圾回收
- MyEclipse+Struts2登录验证(含工程源码)
- Java线程同步
- Spring配置web.xml中<listener>标签(ContextLoaderListener类解析)解析
- Java报错系列――java.util.Date/java.sql.Date/java.sql.Timestamp
- java中遇到过的String的一些特性
- Struts框架刷新验证之基于xml配置方式
- Java知多少(106)程序与数据库连接