Level 1 | Level 2 | Level 3 | Level 4 | Level 5 | Level 6 | Level 7 | Level 8 | Level 9 | Level 10 | Level 11 |
---|---|---|---|---|---|---|---|---|---|---|
Java基础 | 面向对象(OOP) | 封装(抽象) | 类 | 普通类 | 组合(has-a) | 组合的形式 | 使用某个类的一个对象 | |||
将该类的一个对象置于某个新类中 | 如果组合是动态发生的,称为聚合 | |||||||||
UML表示: | ||||||||||
枚举 | ||||||||||
内部类 | 内部类 | 语法 | .new:类名+.new创建内部类的对象 | |||||||
.this:类名+.this得到外部类的对象 | ||||||||||
特征 | 不能通过引用外部类的名字方式创建,仅能通过外部类的对象创建内部类对象 | |||||||||
不能包含static方法和static字段 | ||||||||||
不管嵌套多少层,都可以访问外围类的所有成员 | ||||||||||
内部类可以由多个实例,每个实例拥有自己爹状态信息 | ||||||||||
单个外围类中,可以让多个内部类以不同方式实现同一个接口或继承同一个类 | ||||||||||
嵌套类(静态内部类) | 语法 | 可以通过外部new 外部类名 + 嵌套类名方式创建对象 | ||||||||
类用static关键字修饰 | ||||||||||
特征 | 不能从嵌套类对象中访问非晶态外围类的对象 | |||||||||
可以包含static方法和属性 | ||||||||||
嵌套类可以作为接口的一部分,作为接口的嵌套类 | ||||||||||
创建嵌套类对象时,不需要依赖于外围类对象的创建 | ||||||||||
局部内部类 | 特征 | 存在于方法体内或作用域内,仅方法或作用域中可以访问 | ||||||||
语法 | 局部内部类不能有访问说明符,因为它只在作用域中生效 | |||||||||
并不是说,作用域中的局部内部类是在作用域满足条件时候才被创建的,它在编译时,作为类被编译过了 | ||||||||||
匿名内部类 | 语法 | new + 需要向上转型成的类的类名+( )+ { +方法体 + } + ; | ||||||||
特征 | 生成的匿名内部类,是创建时指定的类型的导出类或接口实现 | |||||||||
匿名内部类需要使用外部定义的对象,需要参数引用是final的 | ||||||||||
通过实例初始化方式,创建匿名内部类的对象 | ||||||||||
只能实现一个接口 | ||||||||||
共有特性 | 通过外部对象默认的引用,链接到了外部对象,因此可以访问外部类的所有成员 | |||||||||
内部类相对于外部类独立存在 | ||||||||||
内部类的继承,需要在构造器中指定通过外围类对象调用super()方法 | ||||||||||
在外围类的继承关系中内部类不能被覆盖,子类中与基类中同名的内部类是独立的两个类 | ||||||||||
可以指定子类中的内部类继承基类中的内部类,这样,内部类的方法可以被覆盖,支持向上转型 | ||||||||||
内部类编译后也会生成.class文件,它的命名规则是:外围类名字+ $ +内部类名字,匿名内部类是通过编译器简单的产生一个数字作为其标识符 | ||||||||||
闭包 | 一个可调用的对象,记录了一些信息,这些信息来自于创建它的作用域 | |||||||||
回调 | ||||||||||
接口 | 特征 | 接口同样需要访问权限修饰,如果不给定访问权限的限定,默认只有包访问权限 | ||||||||
接口中也包含域,但都是隐式的static和final的 | ||||||||||
接口中的方法,默认是public的 | ||||||||||
接口可以多重继承(一个实现类,去实现多个接口,也可以定义一个新的接口,去继承多个接口) | ||||||||||
接口的适配 | ||||||||||
接口嵌套 | 类内部嵌套的private接口,只能交由拥有权使用它的对象使用 | |||||||||
接口之间可以嵌套,并且接口的规则被严格执行 | ||||||||||
实现某个接口时,并不需要实现此接口内部嵌套的接口 | ||||||||||
private接口不能在定义它的类之外被实现 | ||||||||||
default方法 | default方法可以有方法体 | |||||||||
如果A类实现接口B,B中含有default方法,A类会继承B方法 | ||||||||||
如果A类同时实现接口B和C,在B和C中都定义了default方法f(),在A中需要重写方法f() | ||||||||||
如果A类继承B类,B类实现接口C,C中定义了default方法f(),B中也存在方法f(),A类继承B类中的方法 | ||||||||||
抽象类 | 抽象方法 | |||||||||
接口与抽象类 | 相同点 | |||||||||
不同点 | ||||||||||
继承(is-a) | 概念 | 源类(超类、基类、父类) | ||||||||
副本(导出类、继承类、子类) | ||||||||||
UML表示: | ||||||||||
单根继承:Object | ||||||||||
特性 | 子类使用默认构造器初始化,会默认先调用基类的默认构造器初始化基类 | |||||||||
通过带参数构造器初始化子类,需要显式地调用父类带参数的构造器初始化基类,否则只会调用默认的构造器初始化基类 | ||||||||||
由于存在继承与组合同时使用的情况,在调用一些自定义的清理方法时,需要注意执行顺序,应该与构造顺序相反 | ||||||||||
在继承关系中,方法的重载不会被屏蔽,符合访问权限的情况下,重载方法仍可以正常调用 | ||||||||||
重载与覆盖 | 重载 | |||||||||
覆盖 | ||||||||||
多态(后期绑定、动态绑定) | 向上转型:将导出类看作是它的基类的过程 | 继承 | ||||||||
接口 | ||||||||||
绑定 | 前期绑定 | |||||||||
后期绑定(动态绑定、运行时绑定) | final(private)关键字修饰的方法,关闭动态绑定 | |||||||||
静态方法(静态域)是在编译期就解析的,因此也不具有多态性 | ||||||||||
构造器的调用顺序 | 将分配给对象的存储空间初始化成二进制零,引用对象,一般初始化为null | |||||||||
调用基类的构造器 | ||||||||||
按照声明的顺序调用成员变量的初始化方法 | ||||||||||
调用导出类的构造器主体 | ||||||||||
因为构造器在多态形态下的不稳定性,需要尽量依照如下准则: | ||||||||||
用尽可能简单的方法,使对象进入正常状态,如果可以的话,避免调用其他方法,在构造器中唯一可以安全调用的那些方法使基类中的final(private)方法。 | ||||||||||
协变返回类型 | ||||||||||
多态的表现形式 | 方法的重载 | |||||||||
继承结构中方法的覆盖 | ||||||||||
接口的不同实现 | ||||||||||
抽象方法的不同实现 | ||||||||||
类型识别与泛型 | 向下转型 | |||||||||
类型识别 | RTTI(RunTime Type Identification) | Class对象 | 特性 | 类加载器:所有的类都是在对其第一次使用时,动态加载到JVM中的,当程序创建第一个对类的静态成员的引用时,就会加载这个类。 | ||||||
一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象 | ||||||||||
获取class对象引用的方式 | Class.forName(String arg) (arg必须传递类的全限定名) | |||||||||
如果已经拥有了一个类的对象,可以调用obj.getClass()方法 | ||||||||||
使用类字面常量获取class对象,Integer.class | ||||||||||
对比 | 使用Class.forName()方法生成class对象,会直接完成类加载的三个步骤 | |||||||||
使用类字面常量生成class对象,一开始不会初始化,直到第一次使用类的静态域,类才会初始化(使用static final 的编译期常量,不会对类进行初始化,但如果static final 修饰的引用,指向的是一个表达式,这个静态变量被使用时,类就会被初始化) | ||||||||||
生成class的步骤 | 加载:类加载器查找字节码,从这些字节码中生成一个Class对象 | |||||||||
链接:对类的字节码进行一些验证,为静态域分配存储空间,并且如果必须的话,解析这个类创建的对其他类的所有引用 | ||||||||||
初始化:如果该类有超类,则对其初始化。执行当前类的静态初始化器和静态初始化块 | ||||||||||
常用方法 | forName(String arg) 获取class对象 | |||||||||
getName() 产生全限定类名 | ||||||||||
getSimpleName() 产生不包含包名的类名 | ||||||||||
getCanonicalName() 产生全限定类名 | ||||||||||
isInterface() 判断是否是接口 | ||||||||||
getSuperclass() 查询其直接基类,返回基类的class对象,可以借此查询完整的继承结构 | ||||||||||
newInstance() 实现虚拟构造器,在不知道具体类型的前提下,正确创建当前类的对象 | ||||||||||
Class对象的比较 | instantsof | |||||||||
Class.isInstance() | ||||||||||
结果相同 | 保持了类型的概念,即继承结构下的向上转型 | |||||||||
equals | ||||||||||
== | ||||||||||
结果相同 | 未考虑继承,只是比较当前引用指向的对象是否相等 | |||||||||
泛化使用class引用 | 通过使用泛型语法,可以让编译器强制执行额外的类型检查 | |||||||||
将泛型语法用于Class对象,newInstance()方法,在某种程度上,返回的是对象的确切类型,而并非Object。但如果需要泛化的类型是超类,由于编译器只能允许泛化表达式,去表示“某个类,是另一个确切类的超类”,即Class super A> ,由于这种含糊性,这时候上述的确切的类型,就无法获得,而只能通过Object类的引用指向它 | ||||||||||
RTTI形式 | 传统的类型转换,RTTI确保类型转换的的正确性 | |||||||||
代表对象类型的Class对象,通过查询Class对象可获取运行时所需的信息 | ||||||||||
instanceof关键字,判断对象是否是某个特定类型的实例 | ||||||||||
反射 | 与RTTI的区别 | RTTI想要知道某个对象的确切类型,这个类型在编译时必须已知,即.class文件对于JVM必须是可获取的,编译器在编译时打开和检查.class文件 | ||||||||
对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件 | ||||||||||
类库 | Field | get() | ||||||||
set() | ||||||||||
getFilds() | ||||||||||
Method | invoke() | |||||||||
getMethods() | ||||||||||
Constructor | newInstance() | |||||||||
getConstructors() | ||||||||||
反射使类中的信息都透明了。(后门) | ||||||||||
代理 | 一般代理 | |||||||||
动态代理 | Proxy.newProxyInstanc() 创建动态代理 | 参数 | 类加载器:可以从已经被加载的对象中获取其类加载器 | |||||||
大力实现的接口列表(不是类或抽象类) | ||||||||||
InvocationHandler接口的一个实现 | ||||||||||
invoke()方法 | 代理对象 | |||||||||
要执行的方法对象 | ||||||||||
请求参数 | ||||||||||
空对象 | 声明一个Null接口 | |||||||||
使用嵌套类(空对象是单例的),实现Null接口,定义空对象 | ||||||||||
泛型 | 基础概念 | 泛型(目的):希望类或方法能够具最广泛的表达能力 | ||||||||
参数化类型:将具体的类型参数化,将类型定义为参数形式(类型形参),在使用/调用时传递具体类型(类型实参) | ||||||||||
元组:将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许读取其中的元素,但不允许向其中存放新的对象(数据传送对象、信使)。 | ||||||||||
类型参数推断 | ||||||||||
边界:对象进入和离开方法的地点 | ||||||||||
基本语法 | 泛型类 | |||||||||
泛型接口 | ||||||||||
泛型方法 | 将参数列表置于返回值之前 | |||||||||
泛型方法如果需要显式的指明类型,静态方法必须要加上类名,非静态方法必须使用this.关键字,例如:New. |
||||||||||
匿名内部类 | ||||||||||
特性 | 基本类型无法作为泛型参数,通过自动拆箱装箱可以实现基本类型的泛型参数传递 | |||||||||
类型推断只对赋值操作有效 | ||||||||||
擦除 | 在泛型代码内部无法获得任何有关泛型参数的类型信息 | |||||||||
泛型类型参数将擦除到它的第一个边界 | ||||||||||
泛型类型只有在静态类型检查期间才会出现(即在编译期,完成对传递进来的参数的额外类型检查,对返回的参数进行相关的转型,自动转型到边界类型,而后进行擦除),这一切都在边界处完成 | ||||||||||
擦除的补偿:(引入类型标签) | 使用T参数表示泛型,无法通过new创建对象 | 原因 | 擦除,不知道T的真实类型 | |||||||
编译器无法验证T是否具有无参构造器 | ||||||||||
替代方法 | 传递工厂对象,使用工厂对象创建新的实例(警惕那些不具有默认构造器的类,比如Integer) | |||||||||
模版方法设计模式,通过子类创建对象 | ||||||||||
泛型数组 | 通过普通方式,仅可以声明引用,无法创建一个泛型数组,因为擦除过后,编译器认为数组是Object类型的,而数组的特殊性,会导致在运行时,通过向下转型,会抛出异常 | |||||||||
如果将泛型数组中的元素单独拿出来转型,是可以成功的 | ||||||||||
产生正确类型的泛型数组,可以通过引入类型标签,Class |
||||||||||
边界 | 使用无界泛型参数可以调用的方法,只能是Object中存在的方法 | |||||||||
通配符 | 一些约定俗成的表示方法 | ?:一般表示不确定的Java类型 | ||||||||
T:一般表示一个具体的Java类型 | ||||||||||
K,V:代表键值对表示Key,Value | ||||||||||
E:一般表示Element | ||||||||||
extends(上界/子类型通配符) | 此泛型持有的对象类型,只能是上界本身以及上界类型的导出类 | |||||||||
? extends A & B | ||||||||||
使用了子类型通配符,不能传递类型参数给泛型参数,因为编译器无法知道传递的是哪一个子类型(如 T extends A, 编译器只知道T 应该传递近来的是A的导出类,但不知道具体是哪一个导出类,可能是B,也可能是C,因此,当声明一个对象后,向其中进行赋值操作时,可能同时传递B或者C,如果调用合法,会导致泛型类同时持有两种类型,导致类型不安全),但是可以 声明A a 的引用去获取对象,因为无论如何得到的对象,都是A的导出类。或这通过向下转型,将T对象的引用指向该对象 | ||||||||||
super(下界/超类型通配符) | 即此泛型持有的对象类型,只能为下界或下界类型的基类 | |||||||||
可以向使用超类通配符声明的对象的方法中,传递类型参数给泛型类型,但这是违反静态类型安全的(因为,通过T super A 表示T 是A的导出类,规定了下界是A,因此向泛型中传递A的子类都是合法的),但是无法从中获取任何泛型类型的返回值(比如,T super A ,只知道T是A的基类,无法明确是哪个基类,直接通过T 的引用指向得到的对象,类型不安全)可以通过Object类型声明的引用去获取该对象 | ||||||||||
无界通配符 | 几种通配符方法,传递不同参数的不同处理方式 | |||||||||
捕获转换 | ||||||||||
几个问题 | 基本类型不能作为类型参数 | Java的自动拆箱装箱可以使用包装类实现,但自动拆箱装箱无法应用于数组 | ||||||||
如果自动拆箱装箱出现性能问题,就需要专门适配基本类型的容器版本(如:Org.apache.commons.collections.primitives | ||||||||||
一个类无法实现一个泛型接口的两种变体,由于擦除的原因,最终展现出来的两种变体,实际上是具有相同的类型信息的 | ||||||||||
传递泛型类型的参数的方法无法被重载,擦除的原因,重载后的两个方法,参数签名相同,因此无法编译 | ||||||||||
基类劫持接口,即基类实现了泛型接口,子类也实现泛型接口时,向其中传递进新的泛型类型参数,将无法工作,除非传递进去的泛型类型参数与基类传递进去的一致 | ||||||||||
其他 | 引申概念及实现 | 自限定类型 | 古怪的循环泛型:父类用子类替代其参数,泛型基类变成了一种其所有导出类的公共功能模版 | |||||||
自限定:强制泛型当作自己的边界参数来使用,强制要求正在定义的类当作参数传递给基类,可以保证类型参数必须与正在定义的类相同,自限定限制只能作用于继承关系 | ||||||||||
意义 | 产生协变参数类型 | |||||||||
特性 | 非泛型方法中,参数类型不能随子类型发生变化 | |||||||||
混型 | 使用接口产生混型效果 | |||||||||
使用装饰器模式 | ||||||||||
与动态代理混合,通过动态代理,申城的类的动态类型将会是已经混入的组合类型 | ||||||||||
潜在类型机制 | 反射 | |||||||||
适配器仿真潜在类型机制 | ||||||||||
子主题 | ||||||||||
将函数对象用作策略 | 函数式编程的前身? | |||||||||
容器 | 容器结构 | Iterable(顶层接口) | Collection(独立元素的序列) | List | ArrayList | 数据结构:数组 | ||||
特点 | 优势 | 擅长随机访问元素 | ||||||||
劣势 | 在List中间插入和移除元素较慢 | |||||||||
特殊方法 | ||||||||||
LinkedList | 数据结构:双向链表 | |||||||||
特点 | 子主题 | |||||||||
特殊方法 | getFirst() == element()(Queue中定义的方法):返回列表的头,但不移除,列表为空时抛出异常 | |||||||||
peek(),方法类似于getFirst(),但是在列表为空时,返回null | ||||||||||
removeFirst() == remove() (Queue中定义)移除并返回列表的头,列表为空时,抛出异常 | ||||||||||
poll()方法类似于removeFirst(),列表为空时,返回null | ||||||||||
addFirst()在列表头添加元素 | ||||||||||
add() == offer() == addLast(),在列表尾端添加元素 | ||||||||||
removeLast(),移除并返回列表的最后一个元素 | ||||||||||
可以被当作栈来使用(后进先出的容器 LIFO) | getFirst()、addFirst()、removeFirst(),模拟栈当中对元素的操作 | |||||||||
Set | HashSet | 数据结构:HashMap | ||||||||
特点 | 散列排布 | |||||||||
插入的元素必须实现hashcode()方法 | ||||||||||
LinkedHashSet | 数据结构 | 继承自HashSet,相同的数据结构 | ||||||||
特点 | 维护插入的元素的顺序 | |||||||||
插入的元素必须实现hashcode()方法 | ||||||||||
SortedSet | TreeSet | 数据结构 | HashMap | |||||||
特点 | 元素有序排列(按照自然排序或自定义排序规则) | |||||||||
插入的元素必须实现Comparable接口,当加入未实现该接口的元素对象,会抛出异常 | ||||||||||
特殊方法 | Object first() 返回容器中的第一个元素 | |||||||||
Object last() 返回容器中的最后一个元素 | ||||||||||
Comparator comparator() 返回当前Set使用的Comparator | ||||||||||
SortedSet subSet(forElement toElement), 返回Set子集,从fromElement(包含)到toElement(不包含) | ||||||||||
SortedSet head(toElement) , 生成此Set子集,由小于toElement的元素组成 | ||||||||||
SortedSet tailSet(fromElement) 生成Set子集,由大于或等于fromElement的元素组成 | ||||||||||
加入Set的元素必须定义equals()方法确保对象的唯一性 | ||||||||||
Queue(先进先出的容器 FIFO) | 接口方法 | offer(),允许的情况下,将元素插入到队尾,或者返回false | ||||||||
peek(),队列为空时,返回null | ||||||||||
element(),队列为空时,抛出异常 | ||||||||||
不移除的情况下返回队头 | ||||||||||
poll(),队列为空时,返回null | ||||||||||
remove(),队列为空时,抛出异常 | ||||||||||
移除并返回队头 | ||||||||||
实现 | PriorityQueue(优先级队列) | 数据结构 | 数组 | |||||||
特点 | 通过comparable接口控制优先级 | |||||||||
LinkedList | ||||||||||
他们之间的差异在于排序方式 | ||||||||||
还有一些并发情况下使用的队列 | ||||||||||
Map(映射表) | HashMap | 数据结构 | 数组(桶位)+ 链表 + 红黑树 | |||||||
特点 | 散列存储,查询更快 | |||||||||
负载因子:0.75 | ||||||||||
桶长度:16 | ||||||||||
LinkedHashMap | 数据结构 | 数组(桶位)+ 链表 + 红黑树 | ||||||||
特点 | 取得键值对的顺序是其插入顺序,或者是最近最少使用的(LRU)顺序 | |||||||||
迭代时更快,访问仅比HashMap慢一些 | ||||||||||
SortedMap | TreeMap | 数据结构 | 数组(桶位) + 红黑树 | |||||||
特点 | 查看键或键值对,它会被排序,顺序取决于Comparable 或Comparator | |||||||||
特殊方法 | subMap | |||||||||
WeakHashMap | 弱键映射,允许释放映射所指向的对象 | |||||||||
ConcurrentHashMap | 线程安全的map | |||||||||
IdentityHashMap | 使用== 替换equals()对键的比较的散列表映射,专门为解决特殊问题设计的 | |||||||||
那些发挥重要作用的抽象类 | AbstractCollection | |||||||||
AbstractList | ||||||||||
AbstractSet | ||||||||||
AbstractMap | ||||||||||
提供了该容器的部分实现 | ||||||||||
可选操作 | 定义:即在容器的具体类型中未选择实现的一些方法,这些方法的调用一般会抛出UnsupportedOperationException | |||||||||
例子,比如通过Arrays.asList生成的固定尺寸的列表,任何可能引起扩容操作的方法在这里均不可用,可以说是可选择的 | ||||||||||
原理:面向对象中,对接口的实现,或者继承,一般来说,应该遵守去复用或者实现父类中的方法,通过多态机制,可以调用具体类型中应该调用的方法。然而,有时候,接口模板中,定义的方法,并不是很符合所有使用场景,或不符合当前类的某些特性,但可能又需要覆盖/复用父类中的大部分方法,防止代码重复,或者遵守接口制约。因此选择空的实现,或者选择抛出异常(类库中更常用)的方式,让这个方法,在当前这个类中,不可操作。 | ||||||||||
意义:防止接口爆炸 | ||||||||||
散列码 | equals() | 条件 | 自反性 | |||||||
对称性 | ||||||||||
传递性 | ||||||||||
一致性 | ||||||||||
对于任何不是null的x,x.equals(null),一定返回false | ||||||||||
hashcode() | 书写散列性更好的hashcode()方法,应该充分考虑各个域,对每个域计算一个散列码 | |||||||||
规则 | boolean c=(f ? 0 : 1) | |||||||||
byte、char、short、int c = (int) f | ||||||||||
long c = (int) (f ^(f>>>32)) | ||||||||||
float c = Float.floatToIntBits(f); | ||||||||||
double long l = Double.doubleToLongBits(f); | ||||||||||
c = (int)(l^(l>>>32)); | ||||||||||
Object c = f.hashCode(); | ||||||||||
数组 对每个元素应用上述规则 | ||||||||||
惯例:result = 37 * result + c | ||||||||||
Java1.0/1.1的容器 | Vector类和Enumeration接口 | |||||||||
HashTable | ||||||||||
Stack | ||||||||||
BitSet | ||||||||||
工具 | Collections | fill(list,object),用来填充list,但是只能替换list当中已经存在的元素,不能添加新元素 | ||||||||
nCopies(count,object),使用对象,填充list | ||||||||||
其他方法可以参考Java编程思想第四版P512 | ||||||||||
Arrays | Arrays.asList() | 有时候需要通过显式的类型参数说明,指定需要创建的List类型,如:Arrays.asList(array),表示指定生成的list的类型参数为A | ||||||||
该方法会生成一个在Arrays中内置的ArrayList类,底层数据结构是数组,不支持扩容操作,因此如果有意图使容器大小发生改变的操作,就会抛出异常 | ||||||||||
equals(),比较两个数组是否相等 | ||||||||||
deepEquals(),用于多维数组 | ||||||||||
fill(),填充数组 | ||||||||||
sort(),排序数组,对于没有实现Comparable或者没有传递Comparator的类,调用会抛出异常 | ||||||||||
binarySearch(),在已经排序的数组中查找元素 | ||||||||||
复制数组:System.arraycopy() (效率比for循环更高) | ||||||||||
Comparable | 实现此接口中的compareTo()方法,相等返回0,当前对象小于参数返回负数,当前对象大于参数返回正数 | |||||||||
Comparator | 可以单独创建类去实现这个接口的compare()方法,然后将这个comparator对象传递给Arrays.sort()方法 | |||||||||
数组 | 特点 | 效率 | 对于随机访问,数组比其他数据结构底层支持的容器效率更高,因为数组是简单的线性序列,数组的每个元素均为一个引用,指向具体的内存地址,内存地址中又指向真实对象的实际内存地址 | |||||||
对于弹性数组数据结构,严格的尺寸,又可以避免弹性扩容带来的额外开销 | ||||||||||
类型 | 泛型之前,数组是最好的持有具体类型的方式 | |||||||||
保存基本类型的能力 | 数组可以保存基本类型,而容器不行,容器必须通过自动拆箱装箱来实现基本数据类型的保存,自动包装机制很便捷,数组唯一优势的一点就是在这过程中,效率比自动包装机制更高一些 | |||||||||
数组是一级对象,数组标识符其实是一个引用,指向堆中创建的一个真实对象,这个对象泳衣保存指向其他对象的引用 | ||||||||||
数组初始化方法 | 声明数组变量,创建一个数组的引用,在使用之前,进行初始化 | |||||||||
使用new 去初始化数组,元素均为默认值 | ||||||||||
声明数组变量,初始化后,逐个给元素赋值 | ||||||||||
使用聚集初始化语法 | ||||||||||
多维数组 | 数组嵌套,即上一层数组中的元素,由下一层数组组成 | |||||||||
粗糙数组:每一个对象列表的长度都不相同 | ||||||||||
迭代器 | 概念:轻量级对象,可以遍历并选择序列中的对象,而客户端程序员不必知道或关心该序列底层结构 | |||||||||
主要结构 | 在容器中组合Iterator接口 | 接口中含有一些遍历所必须的方法 | next() | |||||||
hasNext() | ||||||||||
remove() | ||||||||||
在容器的具体类型中,实现迭代器以及迭代器方法 | ||||||||||
除Iterator外,List容器中采用Iterator的子类ListIterator | ||||||||||
意义:统一了容器的访问方式,可以不用通过获取size,然后构建循环,就可以完成容器的遍历 | ||||||||||
问题:Iterator只能够向前移动,而ListIterator可以完成双向移动,并且可以通过set()方法,替换它访问过的最后一个元素 | ||||||||||
Java I/O 系统 | File类(既可以代表一个文件名称,又可以代表一根目录下的一组文件名称) | 方法列表 | list() 返回一个字符数组,由文件名构成) | |||||||
list(FilenameFilter filter) 返回字符数组,由filter实现过滤(回调accept()函数实现) | ||||||||||
listFiles(FilenameFilter filter)返回file的数组 | ||||||||||
FilenameFilter接口 | accept(File dir,String name) 接收一个目录和文件名称,用来匹配文件名 | |||||||||
输入、输出流(基于字节的流) | InputStream | 结构 | ByteArrayInputStream | 缓冲区,字节将从中取出 | ||||||
StringBufferInputStream | 字符串,底层实现实际使用StringBuffer作为一种数据源,已弃用 | |||||||||
FileInputStream | 字符串,表示文件名,文件或FileDescriptor对象 | |||||||||
PipedInputStream | 多线程中的数据源 | |||||||||
SquenceInputStream | 两个InputStream或一个容纳InputStream对象的容器Enumeration | |||||||||
FilterInputStream(装饰器的提供类) | DataInputStream | 包含用于读取基本类型数据的全部接口 | ||||||||
BufferedInputStream | 可以指定缓冲区大小(可选的) | |||||||||
LineNumberInputStream | 仅增加了行号 | |||||||||
pushbackInputStream | 通常作为编译器的扫描器 | |||||||||
数据源 | 字节数组 | |||||||||
String对象 | ||||||||||
文件 | ||||||||||
“管道” | ||||||||||
一个由其他种类的流组成的序列 | ||||||||||
OutputStream | 结构 | ByteArrayOutputStream | 缓冲区初始化尺寸(可选),用于指定数据的目的地 | |||||||
FileOutputStream | 字符串表示文件名或FileDescriptor对象 | |||||||||
PipedOutStream | 指定用于多线程的数据的目的地 | |||||||||
FilterOutputStream | DataOutputStream | 包含用于基本数据类型写入的全部接口 | ||||||||
PrintStream | 可以用boolean表示是否在每次打印时清空缓冲区(可选) | |||||||||
区别 | DataOutputStream与PrintStream的区别:DataOutputStream是将数据读取到流种,然后写到指定位置,PrintStream带有打印功能,目的是为了可视化输出 | |||||||||
BufferedOutputStream | 可指定缓冲区大小(可选) | |||||||||
输入、输出流(基于字符的流) | 设计目的 | 处理字符集(国际化) | ||||||||
Reader | FileReader | -> FileInputStream | ||||||||
StringReader | -> StringBufferInputStream(已弃用) | |||||||||
CharArrayReader | -> ByteArrayInputStream | |||||||||
PipedReader | -> PipedInputStream | |||||||||
FilterReader | -> FilterInputStream | BufferedReader | BufferedInputStream | |||||||
LineNumberReader | LineNumberInpStream(已弃用) | |||||||||
StreamTokenizer | 使用接受Reader的构造器 | |||||||||
PushbackReader | -> PushbackInputStream | |||||||||
如果不需要使用readLine()方法,那么首选应该使用DataInputStream,用作读取基本数据类型的接口适配器,否则应该使用BufferedReader | ||||||||||
Writer | FileWriter | -> FileOutputStream | ||||||||
StringWriter | -> 无对应类 | |||||||||
CharArrayWriter | -> ByteArrayOutputStream | |||||||||
PipedWriter | -> PipedOutputStream | |||||||||
FilterWriter | -> FilterOutputStream | BufferedWriter | -> BufferedOutputStream | |||||||
PrintWriter | -> PrintOutputStream | 为了容易过渡到PrintWriter,提供了既能接受Writer的构造器,又提供了能接受OutputStream的构造器,并且,两个类的格式化接口相同 | ||||||||
基于字节流与基于字符流结合使用 | 适配器 | InputStreamReader | 将InputStream转成Reader | |||||||
OutputStreamWriter | 将OutputStream转成Writer | |||||||||
自我独立的类:RandomAccessFile | 特征 | 适用于由大小已知的记录构成的文件,所以可以使用seek()方法,移动位置,然后进行读取或写入 | ||||||||
只实现了DataInput和DataOutput接口,因此是自我独立的,直接从Object类派生而来 | ||||||||||
工作方式类似于将DataInputStream和DataOutputStream类的方法结合起来,并添加了一些其他方法 | ||||||||||
方法列表 | seek(),从文件某处移动到另一处 | |||||||||
getFilePointer()获取当前所在文件的位置 | ||||||||||
length()获取文件最大长度 | ||||||||||
构造器接受 r、w、rw等,控制文件读写权限 | ||||||||||
普通I/O的使用 | 常用的组合方式 | 输入 | 缓冲方式读取字节 | FileReader | ||||||
CharArrayReader | ||||||||||
StringReader | ||||||||||
读取到内容后生成Reader,将文件流传递给BufferedReader,通过readLine()方法 !=null 来判断文件是否读取完毕。 | ||||||||||
内存输入 | 通过其它方式将内容生成Reader加载到内存中,通过StringReader等类,使用read()方法,通过read() != -1,判断内容是否读取完 | |||||||||
格式化内存输入 | 通过DataInputStream进行读取,在DataInputStream中可以通过构造方法插入其他类型的InputStream,并且应该使用available()方法来判定文件是否读取完毕,readByte()方法,因为是一个字节一个字节的读取字符,因此输出的结果都有实际意义,无法判定是否读取完毕 | |||||||||
available()是在没有阻塞的情况下所能读取的字节数,对于文件可能意味着整个文件,但是对于不同类型的流,实际可能并非如此,使用需谨慎 | ||||||||||
输出 | 基本的文件输出 | 通常实用FileWriter与文件建立联系,生成Writer,然后使用BufferedWriter进行包装(缓冲输出,主要提高性能)通过不同的包装器进行包装后输出内容到文件 | ||||||||
文本文件输出的快捷方式 | 可以利用PrintWriter中的构造方法简化文件输出建立连接的方式,直接通过new PrintWriter(String filename)方式,得到该Writer。 | |||||||||
存储和恢复数据 | 一般使用DataOutputStream输出数据,生成可用于恢复的文件,用DataInputStream进行读取恢复文件,但是需要注意的是,要么文件的格式固定,要么不通数据类型之前有标记可以识别,否则,可能无法用准确的类型读取方法进行数据的读取。字符串类型,应该首选使用UTF-8格式进行存储和读取 | |||||||||
读写随机访问文件 | ||||||||||
文件读写实用工具 | 简化文件的读写,简化二进制文件读写 | |||||||||
标准I/O | System.in | 重定向in,setIn(InputStream) | ||||||||
System.out | 通过PrintWriter构造器,可以接收System.out流,将其转换为Writer。并且使用自动刷新控制是否允许自动刷新 | |||||||||
重定向out,setOut(OutputStream) | ||||||||||
System.err | 重定向Err,setErr(OutputStream) | |||||||||
进程控制 | ProcessBuilder接收命令字符串数组,通过start(),启用,执行各指令,执行结果通过process对象接收。 | |||||||||
Process对象可以通过getInputStream()方法获取结果流 | ||||||||||
Process对象可以通过geteErrorStream()获取执行失败的流 | ||||||||||
NIO | 结构 | 通道 | FileChannel | 从缓冲器获得数据,向缓冲器发送数据 | in.transferTo(0,in.size(),out) | |||||
out.transferFrom(in,0,in.size) | ||||||||||
将输入与输出的FileChannel进行连接 | ||||||||||
缓冲器 | ByteBuffer | wrap()将已存在的字节数组包装到ByteBuffer中,称之为数组支持的ByteBuffer | ||||||||
allocate()只读访问,显示地使用该静态方法分配ByteBuffer | ||||||||||
allocateDirect()产生一个与操作系统有更高耦合性的直接缓冲器,但是这种分配开支会很大,并且具体性能也会随着操作系统的不通而不通 | ||||||||||
如果我们执行了fileChannel的read()方法,必须调用ByteBuffer的flip()方法,让它做好让别人取数据的准备 | ||||||||||
如果想要进一步执行read()操作,ByteBuffer必须调用clear()方法,来为每个read()作准备。 | ||||||||||
旧的I/O系统 | 面向字节 | FileInputStream | ||||||||
FileOutputStream | ||||||||||
RandomAccessFile | ||||||||||
都有一个getChannel()方法来获取FileChannel | ||||||||||
面向字符 | 无法通过Reader或者 Writer得到FileChannel | |||||||||
可以通过java.nio.channels.Channels类,生成Reader或Writer | ||||||||||
转换数据 | ||||||||||
获取基本类型 | ||||||||||
视图缓冲器 | ||||||||||
用缓冲器操作数据 | ||||||||||
性能 | ||||||||||
文件加锁 | ||||||||||
对映射文件的部分加锁 | ||||||||||
文件压缩 | 压缩类 | |||||||||
压缩格式 | ||||||||||
Java档案文件 | ||||||||||
对象序列化 | 对象序列化与反序列化 | |||||||||
XML | ||||||||||
Preferences | ||||||||||
并发 | ||||||||||
异常 | ||||||||||
字符串 | ||||||||||
注解 | ||||||||||
设计模式 | 策略模式 | |||||||||
适配器模式 | ||||||||||
工厂方法设计模式 | ||||||||||
迭代器模式 | ||||||||||
模板方法 | ||||||||||
命令模式 | ||||||||||
装饰器模式 | ||||||||||
享元模式 | ||||||||||
JVM | 类加载机制 | |||||||||
垃圾回收 | ||||||||||
Java内存模型 | ||||||||||
基础语法 | 对象 | 对象:我们将问题空间中的元素及其在解空间中的表示称为对象 | ||||||||
创建与存储 | ||||||||||
8种基本数据类型 | byte(1字节)-> Byte | |||||||||
short(2字节)-> Short | ||||||||||
int(4字节)-> Integer | ||||||||||
long(8字节)-> Long | ||||||||||
double(8字节) -> Double | ||||||||||
float(4字节) ->Float | ||||||||||
boolean -> Boolean | ||||||||||
char(2字节) -> Character | ||||||||||
作用域 | ||||||||||
类 | ||||||||||
方法、参数、返回值 | ||||||||||
import | ||||||||||
static关键字 | ||||||||||
注释与嵌入式文档 | ||||||||||
操作符 | ||||||||||
控制执行流程 | ||||||||||
初始化与清理 | ||||||||||
访问控制权限 | private 私有的,仅对象内部可访问 | |||||||||
protected 子类可访问父类中的protected属性和方法 | ||||||||||
public 公开的,任何人可以访问 | ||||||||||
default 默认的访问权限(包访问权限,仅在同一个package下可访问 | ||||||||||
新特性 | ||||||||||
final | 数据 | 使用场景 | 永不改变的编译时常量 | |||||||
运行时被初始化,但不希望被改变的值 | ||||||||||
特征 | 若final关键字修饰的是基本数据类型,代表该变量的值不可改变,若final关键词修饰的是对象,代表初始化以后,该引用只能指向该对象地址,不能指向其他对象,但是对象本身是可以被改变的 | |||||||||
可以声明final变量,但不给定其初始的域,但使用该引用(变量)之前必须先对其初始化 | ||||||||||
使用声明的方式,将参数列表指定为final,表示当前方法无法改变变量的值或对象的引用 | ||||||||||
方法 | 使用场景 | 方法锁定,以防任何继承类修改它的含义 | ||||||||
早期,用于对执行效率的优化(在栈中执行代码,取得返回值,消除调用的开销),现在基本上是通过虚拟机来实现这类性能的优化,而且使用final不一定可以带来性能上的优化 | ||||||||||
private与final关键字:private访问权限的变量或方法,都是隐含final关键字修饰作用的 | ||||||||||
类 | final关键字修饰的类,不允许被继承,因此,类中的属性无法被覆盖,所以类中的属性与方法也相应的带有final的属性 | |||||||||
接口 | 接口中定义的域不能是空final,但可以被 |
非常量化表达式初始化,这些域不属于接
口的一部分,它们的值存储在该接口的静
态存储区域 | | | | | | | |