【effective Java读书笔记】方法(二)
来源:互联网 发布:基本遗传算法 编辑:程序博客网 时间:2024/05/20 00:38
【effective Java读书笔记】方法(二)
前言:
越发喜欢写读书笔记了,写完之后,后续的工作中,平时写代码,就会比较深刻的记起来,“原来这个地方可以这么用”。
《第40条至41条》
正文:
一、谨慎设计方法签名,其中值得一提的是:避免过长的参数列表。
对了,话说方法签名应该很熟悉吧:参数类型、参数个数、参数顺序。
避免过长的参数列表的三种方法:
1、方法分解成多个方法;
书中举例:在子列表中查找元素的第一个索引和最后一个索引。(java.util.List接口)
public class ListApply {public static void main(String[] args) {List<String> strs = new ArrayList<>();// TODO 提供数据for (int i = 0; i < 20; i++) {strs.add("test"+i);}List<String> subStrs= strs.subList(3, 13);System.out.println(subStrs.indexOf(subStrs.get(0)));System.out.println(subStrs.lastIndexOf(subStrs.get(subStrs.size()-1)));}}
执行结果:
0
9
原本提供这样一个方法需要三个参数,子列表、子列表第一个索引、子列表的最后一个索引。
第8行,List接口提供subList方法,获得子列表;第9行,根据
subStrs.get(0)
获取第一个对象,通过indexOf方法获得第一个对象出现的第一次的index;第10行,根据
subStrs.get(subStrs.size()-1))
获取最后一个对象,通过lastIndexOf获取最后一个对象出现的最后一次的index;2、创建辅助类;
辅助类,顾名思义,就是用来作为辅助工具的类。
举个例子:
public class HelpClass {public static class Help{public static int add(int x,int y){return x+y;};public static int min(int x,int y){return x-y;};}public static void main(String[] args) {int x =3;int y =2;System.out.println("3+2=?");System.out.println(HelpClass.Help.add(x, y));System.out.println("3-2=?");System.out.println(HelpClass.Help.min(x, y));}}执行结果:
3+2=?
5
3-2=?
1
其中:Help就是辅助类,原本一个这样的计算,需要传递三个入参:第一个数,第二个数,算数操作符。
现在添加辅助类后,只需要添加两个入参。(以上代码用枚举写更佳)
枚举代码改进如下:(使用起来是否更佳优雅,具体为什么这么写,有什么优点,看我这篇文章吧)
public class HelpClass {public static enum Opre{ADD("+"){@Overridepublic int apply(int x, int y) {return x+y;}},MIN("-"){@Overridepublic int apply(int x, int y) {return x-y;}};public final String oper;Opre(String oper) {this.oper = oper;}public abstract int apply(int x,int y);}public static void main(String[] args) {int x =3;int y =2;System.out.println("3+2=?");System.out.println(HelpClass.Opre.ADD.apply(x, y));System.out.println("3-2=?");System.out.println(HelpClass.Opre.MIN.apply(x, y));}}
3、从对象构建到方法调用都采用Build模式。
直接举例:
public class User {private String name;private String addr;private int age;public String getName() {return name;}public String getAddr() {return addr;}public int getAge() {return age;}@Overridepublic String toString() {return "User [name=" + name + ", addr=" + addr + ", age=" + age + "]";}public static class Builder{private User user = new User();public Builder setName(String name){user.name = name;return this;}public Builder setAddr(String addr){user.addr = addr;return this;}public Builder setAge(int age){user.age = age;return this;}public User build(){return user;}}}使用如下:
public class Test {@org.junit.Testpublic void test() {Builder builder = new Builder();User user =builder.setName("bear").setAge(14).setAddr("beijing").build();System.out.println(user);}}执行结果如下:
User [name=bear, addr=beijing, age=14]
当然这个方法显著的减少了参数。使用起来也比较方便。二、慎用重载
关键点出来的就是重载和覆盖的区别:书中提及“对于重载方法的选择是静态的,对于覆盖方法的选择是动态的”。
1、先看一个书中重载的例子:
public class OverRideTest {public static String classify(Set<?> s){return "Set";}public static String classify(List<?> lst){return "List";}public static String classify(Collection<?> c){return "Collection";}public static void main(String[] args) {Collection<?>[] collections = {new HashSet<String>(),new ArrayList<String>(),new HashMap<String,String>().values()};for (Collection<?> c:collections) {System.out.println(classify(c));}}}乍看之下,有点懵!这结果是不是应该Set,List,Collection;
而实际结果呢?
Collection
Collection
Collection
原因其实很简单,重载嘛,挑选最合适的。public static String classify(Collection<?> c){return "Collection";}
而且重载方法调用是在编译时决定的。那么一旦选定就不能改了。无异议是否?
2、再看一个覆盖的例子:
代码如下
public class Test2 {public static void main(String[] args) {Wine[] wines = { new Wine(), new RedWine(), new YellowWine() };for (Wine wine : wines) {System.out.println(wine.name());}}}class Wine {String name() {return "wine";}}class RedWine extends Wine {String name() {return "RedWine";}}class YellowWine extends Wine {String name() {return "YellowWine";}}
执行结果:
wine
RedWine
YellowWine
3、慎用重载的例子:
书中这个例子显得很是经典:
public class SetList {public static void main(String[] args) {Set<Integer> set = new TreeSet<>();List<Integer> list = new ArrayList<Integer>();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.out.println(set + "" + list);}}看上去以为结果会是
[-3, -2, -1]
[-3, -2, -1]
实际结果却是:[-3, -2, -1][-2, 0, 2]
原因是什么?第一个Set与我们预期相同。Set添加和删除都会先装箱,再添加删除。第二个List添加时装箱,但是删除的时候重载了,导致remove第几个位置的,而不是删除某个指定的对象。
- 【effective Java读书笔记】方法(二)
- Effective Java 读书笔记(二)
- Effective Java读书笔记(二)
- effective java读书笔记 (二)
- Effective Java读书笔记(二):方法、通用程序设计
- Effective Java读书笔记二
- effective java读书笔记二
- 《Effective Java》读书笔记二
- Effective java 读书笔记( 二 )
- 《effective java》读书笔记--(二)
- 【effective java读书笔记】泛型(二)
- 【effective java读书笔记】通用程序设计(二)
- 【读书笔记】《Effective Java》(6)--方法
- 【effective Java读书笔记】方法(一)
- 【effective Java读书笔记】方法(三)
- Effective Java 读书笔记(六):方法
- 《Effective java》读书笔记之二
- 《Effective java》读书笔记之二
- 后缀自动机————入门
- CentOS 7系统中JDK的安装与配置
- Google Play Service中安全检测API的使用说明
- 一个YUV开源工程
- Vim命令合集
- 【effective Java读书笔记】方法(二)
- 一个程序员的Java和C++学习之路(整理)
- C#中对sqlserver进行增删改查
- 【立体视觉】世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的关系
- 写作建议
- 淘宝羽毛球拍统计,这种球拍最受欢迎
- U盘文件夹变成应用程序
- Leetcode : 25. Reverse Nodes in k-Group
- js的并行加载与顺序执行