一些摘记和总结
Top
- separate Interface from Implementation – decouple What from How
- primitive的Wrapper类没有无参的默认构造函数,所以不可使用
class.newInstance()
方法
JDK中的Final Imutable类
这里的final
是java的关键字,而Imutable
不是;
- 当
final
修饰类的时候,表示该类不能被继承 - 当
final
修饰对象引用的时候,表示该引用不能改变,即不能指向其他对象,但还是可以改变当前对象的状态 - 当
final
修饰primitive的时候,表示‘常量’
Imutable
,即不可改变,是一种状态,当说一个对象是Immutable
的时候,说明不能改变这个对象的状态
JDK中的String
,还有primitive
的包装类Wrapper
(Integer
, Long
, Character
…)都是final+Imutable
的
String
类和Wrapper
类都是Imutable
的,但二者的实现机制却不同
1. 对于`String`类,其实现`Imutable`是通过将成员变量修饰成`private`的(`private final char value[];`),之后不提供`set`方法==!
2. 对于`Wrapper`类,如`Integer`,其直接将成员变量修饰成`final`的(`private final int value;`)
至于为什么要将这些Imutable
的类修饰成Final
的,是因为Final
使得类不能被继承,这样也就避免了子类中添加修改类对象内容的方法,所以Immutable
类都要加上Final
Immutable
好处主要是线程安全,不用担心其他线程修改了当前对象
TODO 如何设计Immutable
类
- State of immutable object can not be modified after construction, any modification should result in new immutable object.
- All fields of Immutable class should be final.
- Object must be properly constructed i.e. object reference must not leak during construction process.
- Object should be final in order to restrict sub-class for altering immutability of parent class.
访问权限
两类权限:
- Class: public, 空(包权限)
- Class members: public, protected, 空(package access), private
子类可以放大继承方法的权限,反之不可,因为子类缩小继承方法权限没什么意思,因为可以通过upcast到父类获取这些权限
类加载顺序
三个原则:
- 先加载父类之后加载生成类
- 先加载类变量(和static块,按照顺序)之后加载构造函数
- 递归调用
1
,2
由此可见,构造函数其实是
Static
的
泛型Generic
- Add type parameter to class
- ensure compile-time safety
- Anything that needs the knowledge of the exact type at run-time will not work
java中泛型基于Erasure擦除机制,运行时,所有的泛型都被Erasure成原始类型,所以,所有涉及到运行是类型的方法都无效
异常Exception
一般异常的处理有两种机制:
- 终止Termination,认为抛出的异常无法恢复,这也是Java使用的异常处理机制
- 恢复Resumption,认为异常有补救措施,不throw,而调用补救函数
java中的异常包结构 TODO
受检异常:checked and enforced at compile time
如果不想让在catch自定义的异常,可以使其继承RuntimeException
Finnaly
try { ... }
catch(...) {...}
finnaly {...}
finnaly
的作用,Java中有GC垃圾自动回收机制,所以不需要在finally
中释放内存,但程序员仍然需要释放其他资源,如文件流,网络链接等
注意,finnaly
中的return
或throw
会覆盖try
语句中的…
类型检查
主要分两类:
- 静态类型检查(static type checking),即在编译时进行,需要变量声明后再使用,如:C(++),Java等
- 动态类型检查(dynamic type checking),即在运行时进行,变量直接使用,不用提前声明,如python,php
和其类似的一组概念是:
- 弱类型(Weak Type): 变量类型不确定,如php,c(++)(c中可以将一块内存做多种类型处理)
- 强类型(Strong Type): 变量的类型固定,不能随意转换,如python,Java
C(++)是介于强弱类型之间的语言,由于C(++)支持多种隐含类型转换,有人认为是弱类型语言;也有人认为,C(++)对不同数据类型的操作已有足够多的限制,算是强类型的
两组概念是独立的,如下表所示:
正交关系 | 动态类型检查 | 静态类型检查 |
---|---|---|
弱类型 | C(++) | php |
强类型 | Java | Python |
Class对象
每个类都有一个Class对象保存其类型信息,类加载器使用其创建对象,RTTI也是通过其获取对象类型信息
JVM第一次加载一个类时(使用类的静态成员,包括静态变量,构造方法),生成该类的Class对象
类加载器首先检查内存中(TODO 方法区?)是否含有某个类的Class对象,如果没有,则从该类的.class文件中读取并生成
程序可以通过下面几种方法获取类的Class对象:
Class.forName("MyClass")
myObj.getClass()
MyClass.class
(recommended)
System.out.format("%s = %s : %s\n", Boolean.class, boolean.class,
Boolean.class == boolean.class);
System.out.format("%s = %s : %s\n", Boolean.TYPE, boolean.class,
Boolean.TYPE == boolean.class);
反射 reflect
TODO 动态代理
IO 输入输出
- 标准输入输出 Standard I/O
Unix的设计理念,程序有单一的输入输出流
Java中,有System.in, System.out, System.err
- New IO 为了提高速度,增加了两个东西:TODO通道channels和缓冲buffers
并发多线程 multithreading
并发多线程有两种策略:
- preemptive抢占式多任务处理,java采用基于时间片的抢占机制,因此并发的线程数有上限,否则会产生饥饿
- cooperative 协作式多任务处理
TODO implement more
序列化 Serializable
TODO java.lang.Serializable是一个空接