Smail_的gravatar头像
Smail_ 2017-01-10 08:28:45
再看《Java核心技术卷一》

大学毕业半年后,发现在大学期间没有好好学习Java基础,也没有学的特别扎实!特此补课!

第一次读Java核心技术是在大一,懵懵懂懂,晕晕乎乎的读了一遍,没搞清楚个所以然来。现在也算是个半吊子的Java程序员了吧,所以买了最新版的Java核心技术回来再看一遍。

全书以JDK8为讲解原型展开。

下面是我记下的笔记,边看边记的,主要记录的是我以前所未知的基础知识要点和技巧。

1.在Java接口声明中,没有将方法声明为public,这是因为在接口中的所有方法都自动地是public。不过,在实现接口时,必须把方法声明为public;否则,编译器将认为这个方法的访问属性是包可见性,即类的默认访问属性,之后编译器就会给出试图提供更严格的访问权限的警告信息。

2.提示:Comparable接口中的compareTo方法将返回一个整型数值。如果两个对象不相等,则返回一个正值或者一个负值。在对两个整数域进行比较时,这点非常有用。例如,假设每个雇员都有一个唯一整数id,并希望根据ID对雇员进行重新排序,那么就可以返回id-other.id。如果第一个ID小于另一个ID,则返回一个负值;如果两个ID相等,则返回0;否则,返回一个正值。但有一点需要注意:整数的范围不能过大,以避免造成减法运算的溢出。如果能够确信ID为非负整数,或者它们的绝对值不会超过(Integer.MAX_VALUE-1)/2,就不会出现问题。否则,调用静态Integer.compare方法。当然,这里的相减技巧不适用于浮点值。因为在salary和other.salary很接近但又不相等的时候,它们的差经过四舍五入后有可能变成0。x<y时,Double.compare(x,y)调用会返回-1;如果x>y则返回1。

3.在Java SE 8中,允许在接口中增加静态方法。理论上讲,没有任何理由认为这是不合法的。只是这有违于将接口作为抽象规范的初衷。目前为止,通常的做法都是将静态方法放在伴随类中。在标准库中,你会看到成对出现的接口和实用工具类,如Collection/Collections或Path/Paths。在Java API中,你会看到很多接口都有相应的伴随类,这个伴随类中实现了相应接口的部分或所有方法,如Collection/AbstractCollection或MouseListener/MouseAdapter。在Java SE 8中,这个技术已经过时。现在可以直接在接口中实现方法。

4. 只讨论了两个接口的命名冲突,现在来考虑另一种情况,一个类扩展了一个超类,同时实现了一个接口,并从超类和接口继承了相同的方法,在这种情况下,只会考虑超类方法,接口的所有默认方法都会被忽略。这正是“类优先”规则。

5.千万不要让一个默认方法重新定义Object类中的某个方法。例如,不能为toString或equals定义默认方法,尽管对于List之类的接口这可能很有吸引力。由于“类优先”规则,这样的方法绝对无法超越Object.toString或Objects.equals。
6.Cloneable接口是Java提供的一组标记接口(tagging interface)之一。(有些程序员称之为记号接口(marker interface))。应该记得,Comparable等接口的通常用途是确保一个类实现一个或一组特定的方法。标记接口不包含任何方法;它唯一的作用就是允许在类型查询中使用instanceof。

建议自己的程序中不要使用标记接口。

即使clone的默认(浅拷贝)实现能够满足要求,还是需要实现Cloneable接口,将clone重新定义为public,再调用super.clone()。

7.在Java中,对lambda表达式所能做的也只是能转换为函数式接口。在其他支持函数字面量的程序设计语言中,可以声明函数类型(如(String,String)->int)、声明这些类型的变量,还可以使用变量保存函数表达式。不过,Java设计者还是决定保持我们熟悉的接口概念,没有为Java语言增加函数类型。甚至不能把lambda表达式赋给类型为Object的变量,Object不是一个函数式接口。

8.表达式System.out::println是一个方法引用(method reference),它等价于lambda表达式x->System.out.println(x)。

再看《Java核心技术卷一》

9.lambda要用::操作符分隔方法名与对象或类名。主要有3种情况:
·object::instanceMethod
·Class::staticMethod
·Class::instanceMethod
在前2种情况中,方法引用等价于提供方法参数的lambda表达式。前面已经提到,System.out::println等价于x->System.out.println(x)。类似地,Math::pow等价于(x,y)->Math.pow(x,y)。
对于第3种情况,第1个参数会成为方法的目标。例如,String::compareToIgnoreCase等同于(x,y)->x.compareToIgnoreCase(y)。

10.lambda可以在方法引用中使用this参数。例如,this::equals等同于x->this.equals(x)。使用super也是合法的。

11.使用lambda表达式的重点是延迟执行(deferred execution)。毕竟,如果想要立即执行代码,完全可以直接执行,而无需把它包装在一个lambda表达式中。之所以希望以后再执行代码,这有很多原因,如:
·在一个单独的线程中运行代码;
·多次运行代码;
·在算法的适当位置运行代码(例如,排序中的比较操作);
·发生某种情况时执行代码(如,点击了一个按钮,数据到达,等等);
·只在必要时才运行代码。

边看边记,陆续更新,看完为止!


打赏
最近浏览
Ma2020  LV6 2021年3月10日
test202020  LV1 2020年4月17日
cherishlee138928  LV8 2018年11月27日
rainscloud  LV2 2018年11月22日
java菜  LV1 2018年11月5日
tfh123456  LV1 2018年10月24日
付修立  LV4 2018年8月31日
shuiyuanfeifei 2018年8月21日
暂无贡献等级
低调人  LV38 2018年5月24日
a6165165  LV2 2018年3月23日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友