大学毕业半年后,发现在大学期间没有好好学习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)。
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表达式中。之所以希望以后再执行代码,这有很多原因,如:
·在一个单独的线程中运行代码;
·多次运行代码;
·在算法的适当位置运行代码(例如,排序中的比较操作);
·发生某种情况时执行代码(如,点击了一个按钮,数据到达,等等);
·只在必要时才运行代码。
边看边记,陆续更新,看完为止!