基础概念
·♂· Java源文件结构
Java 程序的执行步骤:.java源文件,先编译 -> .class(与平台无关的字节码文件) -> 后解释,通过 JVM -> 特定平台的机器码。
package packageName;
import | import static packageName;
public classDefinition | interfaceDefinition | EnumDefinition {}
classDefinition | interfaceDefinition | EnumDefinition {}
注:一个源文件中只能有一个public类,否则编译器找不到应该执行的main方法,但是一个源文件中可以有多个非public类。一个源文件中也只能有一个public接口。一个源文件中也只能有一个public枚举类。
- 垃圾回收
只负责在合适时间回收堆内存中处于不可达状态的对象。强制(建议)进行垃圾回收方法:
[1]. System.gc() / runFinalization();
[2]. Runtime.getRuntime.gc() / runFinalization();
finalize:默认机制,Object 类的实例方法:
protected void finalize() throws Throwable
虚引用
主要用于追踪对象被垃圾回收的状态。虚引用必须与引用队列联合使用。
- JAR包 :Java 档案文件,Java Archive File。
[1]. 压缩,加快加载速度;
[2]. 包封装,安全,可移植;
- Java类库
[修饰符] class 类名
{
初始化块;成员变量;构造器;方法;内部类;
}
[1]. Scanner 类
基于正则表达式的文本扫描器:输入流、文件、字符串。
[2]. System/Runtime 类
与程序的运行平台/运行时环境交互:环境变量、系统属性以及文件加载、垃圾回收和资源清理。
System.identityHashCode(Object obj):根据指定对象的地址精确计算到的hashCode值,identityHashCode值唯一标识对象。
Java 程序和 Runtime 实例一对一,getRuntime() 获取。Runtime 类可以单独启动一个进程运行操作系统的命令:rt.exec("命令");
[3]. String/Math 类
[4]. Random/ThreadLocalRandom 类
减少多线程资源竞争,保证线程安全行性,静态 current() 方法获取 ThreadLocalRandom 对象。
Random rand = new Random(System.currentTimeMillis());
[5]. BigDecimal 类
解决 double 类型精度丢失问题、精确计算浮点数,创建方法:
· 基于 String 的构造器创建:new BigDecimal(String str);
· 以 double 参数创建:BigDecimal.valueOf(double value);
[6]. Date/Calender 类
Date 类不推荐使用。Calender 类是抽象类,静态方法 getInstance() 获取 Calender 对象,Calender 支持较好的容错性。注意,其 set() 方法有延迟修改的性质,可以避免触发多次不必要的计算。
[7]. 其他常用方法
· MessageFormat:格式化字符串;
· NumberFormat:格式化数字;
· (Simple)DateFormat:格式化时间、日期;
=> DateTimeFormatter 格式器类:格式化日期时间、字符串解析;
·♂· 继承 Inheritance ~ 多态 Polymorphism ~ 组合
类单继承,extends,Java类只能有一个直接父类。java.lang.Object类是所有类的父类。接口多实现,implements。
- java.lang.Object
[1]. Class<?> getClass():返回对象的运行时类;
[2]. protected object clone():高效、(浅)复制得到实例对象的副本;
class MyObj implements Cloneable
{
public MyObj clone(){
return (MyObj)super.clone();
}
}
Objects 工具类:空指针安全的
[1]. Objects.requireNonNull(obj):对方法的形参作输入校验;
- protected ~ final
protected允许子类重写父类方法,但不允许其他类访问,final是不允许子类重写父类方法。
final
[1]. 变量不可变,方法不可重写,类不能被继承;
[2]. 定义宏变量;
不可变类
该类的对象创建后,对象的实例变量不可变。注意,包含引用类型成员变量的不可变类需要提供保护措施。
[1]. private final 成员变量;
[2]. 带参的构造器初始化[1]的成员变量,仅提供getter()方法;
- this ~ super
this 是调用同一个类中重载的构造器,super 是调用父类的构造器。
- 构造器 ~ 初始化块
对Java对象执行指定的初始化操作,初始化块在创建Java对象时隐式执行且在构造器之前。初始化块没有名字标识,修饰符只能为static,静态初始化块先于普通初始化块执行。
- instanceof ~ (type)
objA instanceof classB,判断引用类型对象objA是否是classB类或是其子类、实现类的实例。objA 的编译时类型要么是classB,要么与classB有父子继承关系,否则编译错误。 在强制类型转换(type)之前,先进行instanceof判断,避免出现ClassCastException异常。类似 C# 中的 is 运算符。
if(objA instanceof classB)
classB objB = (classB)objA;
- 组合 ~ 继承
类的2种复用机制,组合是把旧类对象作为新类的(private)成员变量进行整合用于实现新类的功能,继承是(is-a)关系,组合是(has-a)关系;两者开销仅差一个private成员变量。
- abstract ~ final ~ static ~ private
abstract类只能被继承,abstract方法必须由子类重写。
[1]. abstract不能与final同时修饰类或方法;
[2]. abstract不能与static同时修饰方法,但可以同时修饰内部类;
[3]. abstract不能与private同时修饰方法;
- 接口 ~ 抽象类
抽象类:abstract,多个类的模板,模板模式;
接口:interface,多个类应遵守的公共行为规范,面向接口耦合和通信;
[1]. 成员变量:静态常量,默认 public static final ;
[2]. 方法:抽象方法,默认 public abstract,同时Java8允许在接口里定义默认方法(default)和类方法(static);
[3]. 内部类,内部接口,内部枚举,默认 public static;
·♂· 内部类
外部类:作用域是同一个包内(包访问权限)和任何位置(公共访问权限,public);
内部类:作用域是同一个类(private)、同一个包(包访问权限)、父子类(protected)和任何位置(公共访问权限,public);
内部类不能被外部类的子类重写(类的限定名肯定不同)。
- - 非静态内部类
实例相关,非静态内部类对象里保存外部类对象的引用,依存于外部类对象;非静态内部类里不能定义静态成员(至于为什么,可以考虑类的加载过程,并参考 http://bbs.csdn.net/topics/90510249);
外部类访问内部类:(new innerClass()).innerVar;
非静态内部类的构造器必须通过外部类对象调用;非静态内部类的子类的对象也依存于外部类对象;
- - 静态内部类
static,类相关,静态内部类对象保存外部类的引用,依存于外部类;接口的内部类默认是 public static;
外部类访问内部类:[1]. (new innerStaticClass()).innerVar;[2]. innerStaticClass.innerStaticVar;
静态内部类的构造器通过外部类调用;
- 匿名内部类
匿名内部类不能重复使用,必须继承一个父类或实现一个接口。被匿名内部类访问的局部变量默认是 final。最常用的创建匿名内部类的情况是需要创建某个只有抽象方法的接口类型的对象。
·♂· Lambda 表达式
Java8 引入 Lamba 表达式升级简化匿名内部类、匿名方法,允许创建函数式接口的实例。Lambda 表达式的目标类型能且必须是明确的函数式接口,函数式接口只能声明一个抽象方法。
[1]. 创建临时对象; [2]. 赋值;
格式:(形参列表)->{代码块/方法体}
- - 方法引用 ~ 构造器引用
当方法体只有一条代码时,可以用方法引用和构造器引用替代 Lambda 表达式。
格式:类名::类方法/实例方法/new
本质:利用简洁的语法创建函数式接口的实例! 关于匿名内部类和 Lamba 表达式的异同自行百度。
·♂· 枚举
枚举类显式继承 java.lang.Enum 类,java.lang.Enum 类实现了 java.lang.Comparable 和 java.lang.Serializable 两个接口;非抽象枚举类默认 final 修饰,即不能派生子类;枚举类的构造器默认 private 修饰;枚举类的实例默认 public static final 修饰;
1. public static <T extends Enum<T>> T valueOf(Class<T> enumType, string name)
静态方法,用于返回指定枚举类中指定名称的枚举值,以枚举类 SeasonEnum 为例:
- SeasonEnum se = Enum.valueOf(SeasonEnum.class, "SPRING" );
- SeasonEnum se = SeasonEnum.valueOf( "SPRING" );
2. 返回枚举常量名称、索引值
- SeasonEnum.SPRING;
- SeasonEnum.SPRING.name();
- SeasonEnum.SPRING.toString();
- SeasonEnum.SPRING.ordinal(); // 索引值
3. 抽象枚举类
枚举类中利用 abstract 定义抽象方法,枚举类默认修饰为 abstract,同时每个枚举值必须显式实现抽象方法。
·♂· Java 集合
Java 集合分为 List、Set、Map、Queue 四种体系,接口 Collection 和 Map 是 Java 集合框架的根接口,List、 Set 和 Queue 接口派生于 Collection 接口。非类型安全,以 Object 类型存储,需要强制类型转换。
Collection
- Iterator iterator():用于遍历集合元素;
- Object[] toArray():集合转化为数组;
- void removeIf(Predicate filter):批量删除满足条件的元素,入参为 Lambda 表达式;
- Stream stream(Predicate filter):返回集合对象对应的 Stream 对象;(Stream 编程,利用 Stream 对象的聚集操作简化对集合的操作),几个流式 API:
[I]. filter(Predicate predicate):入参为 Lambda 表达式,过滤 Stream 对象中不符合条件的元素;
[II]. toArray():将流 Stream 对象转换为数组;
[III]. forEach(Consumer action):入参为 Lambda 表达式,遍历流 Stream 对象中的元素;
· List:有序、可重复
线性表接口,提供索引访问、插入、删除、替换。额外方法,入参均可为 Lambda 表达式:
· void sort(Comparator c);
· void replaceAll(UnaryOperator operator);
· ListIterator listIterator();
其中,ListIterator 接口继承于 Iterator 接口,增加了前向迭代功能,专用于操作 List。
[1]. ArrayList - Vector
List 接口的实现类,基于数组,封装了一个允许动态再分配的 Object[] 数组。ArrayList 非线程安全,Vector 线程安全,性能低于 ArrayList。继承于 Vector 类的 Stack 子类也是线程安全的。推荐 Object get(int index) 随机访问元素。
[2]. LinkedList
类 LinkedList 既实现 List 接口,也实现 Deque 接口,基于链表。推荐 Iterator 迭代器随机访问元素。
小结:性能 ArrayList > LinkedList。
· Queue:队列集合
提供 offer() 和 poll() 入队和出队。
[1]. Deque -> ArrayDeque
接口 Deque 继承于 Queue 接口,代表"双端队列",可以作为"栈"使用。
· Iterator descendingIterator();逆向迭代双端队列。
类 ArrayDeque 既实现 Deque接口,也实现 List 接口,可以作为"栈"使用,基于数组。
[2]. PriorityQueue
优先级队列,不允许 null 值。排序功能、元素非FIFO,排序方法参见 TreeSet。
· Set:无序、不可重复
[1]. HashSet -> LinkedHashSet
HashSet 是 Set 接口的实现类,非线程安全。按 Hash 算法 存储元素(根据元素的 hashCode 值计算存储位置),元素值可以为null,存取和查找速度快。2 个 HashSet 元素相等的充要条件:
obj1.hashCode()==obj2.hashCode() && obj1.equals()==obj2.equals();
注:为保证 HashSet 功能的实现,hashCode() 和 equals() 方法是否重写需要保持同步。
~> LinkedHashSet
HashSet 的子类。利用链表维护元素的插入顺序,性能略低于 HashSet。
[2]. SortSet -> TreeSet
TreeSet 是 SortedSet 接口的实现类。按 红黑树 的数据结构有序存储同类型元素:
· 自然排序:默认,实现类必须实现 Comparable 接口的 int compareTo(Object obj) 方法。
· 定制排序:实现类必须关联 Comparator 接口的 int compare(T t1, T t2) 方法。
2 个 TreeSet 元素相等的充要条件:
0 == this.compareTo(obj) // 自然排序
0 == (Comparator对象 | Lambda表达式).compare(t1,t2) // 定制排序
注:为保证 TreeSet 功能的实现,自然排序中 compareTo() 和 equals() 方法须保持同步。
~> SortedSet
SortedSet 接口继承自 Set 接口。
[3]. EnumSet
枚举类型元素的有序集合类,以枚举值在 Enum 类中的定义顺序决定集合中元素的顺序,元素不允许为null。Enum 对象在内部以 位向量 的形式存储,紧凑高效、占用内存小、运行效率好。
EnumSet es = EnumSet.Allof/noneOf(Season.class);
小结:EnumSet 是所有 Set 实现类中性能最好的,性能 HashSet > TreeSet。HashSet、TreeSet、EnumSet 均线程不安全。
Map:映射集合
关系一对一, Map 的 key 值集合是 Set,value 集合是 List,Map 提供 Entry 内部类封装 key-value对,通过 get(Object key)/remove(Object key) 获取和删除元素。
· HashMap - Hashtable -> LinkedHashMap
HashMap 非线程安全、key和value 允许为 null,Hashtable 线程安全,key和value 不允许为 null,性能 HashMap > Hashtable。2 个 key 值相等的充要条件:
obj1.hashCode()==obj2.hashCode() && obj1.equals()==obj2.equals();
2 个 value 相等的充要条件:
obj1.equals()==obj2.equals();
注:为保证 HashMap-Hashtable 功能实现,hashCode()和equals()方法是否重写需保持同步。
~> LinkedHashMap:
HashMap 的子类。利用双向链表维护元素的插入顺序,性能略低于 HashSMap。
~> Properties:
Hashtable 的子类,key和value 均为 String 类型的 Map,store()和load() 存储和加载 属性文件。
· SortedMap -> TreeMap
类 TreeMap 是 SortedMap 接口的实现类。按 红黑树 有序存储同类型元素:参考 TreeSet。
· EnumMap
内部以数组形式保存,紧凑高效,key 值不能为 null,必须与枚举类关联。
小结:性能 HashMap > TreeMap,EnumMap 性能最好。
Iterator:迭代器,必须依附于 Collection 对象。
- boolean hasNext():
- Object next():
- void remove():用于删除集合里 next() 方法上一次返回的元素;
- void forEachRemaining(Consumer action):利用 Lambda 表达式遍历集合元素;
注:Iterator 迭代器采用 fast-fail 快速失败机制,迭代 Collection 集合时,集合元素不能被修改,否则立即抛出 ConcurrentModificationException 异常。
Collections:集合工具类。
[1]. 排序、查找、替换等
- void sort/reverse/swap/shuffle/retate(List list): 排序/反转/交换/随机排序/旋转
- int binarySearch(List list, Object key):二分查找
- void fill(List list, Object obj):元素填充
- boolean replaceAll(List list, Object oldObj, Object newObj):元素替换
[2]. 同步控制
提供 synchronizedXxx() 方法将指定集合包装程线程同步的集合,解决多线程并发访问集合时的线程安全问题。
·♂· 泛型 Generic
类型安全检查,避免引起 ClassCastException 异常。以泛型List为例,类型通配符 List<?> 可以表示各种泛型List的父类,设定类型通配符的上限 List<? extends 父类> 限制其只表示某一类泛型List的父类,注意使用了类型通配符的集合不允许添加元素。通配符用于支持灵活的子类化。
Java 不支持泛型数组。
参考
[1]. 泛型知识点总结;
[2]. Java总结篇系列:Java泛型;
·♂· 异常
Java 的异常机制主要依赖于 try,catch,finally,throw,throws 五个关键字。其中,finally 用于回收在 try 块中打开的 物理资源,throw 用于自行抛出异常的 实例,throws 用于方法签名中声明该方法可能抛出异常、并由上一级调用者处理该异常。Java 的非正常情况有 2 类:Error 和 Exception,均继承于 Throwale 类。
Runtime 异常(运行时异常),RuntimeException 类及其子类的实例,灵活易用。
异常处理方式
· 在出现异常的方法中显式捕获异常并处理,方法的调用者不会捕获到异常;
· 在方法签名中用 throws 声明抛出异常,异常捕获之后交由调用者处理该异常;
优点
· 正常业务代码和异常处理代码分离
· 程序容错性,健壮、易维护;
· 提供多异常捕获功能;
使用注意
· 异常处理结构 try 块是必须的,catch 和 finally 块可选但必须至少二选一;
· finally 块总会执行,除非 try 或 catch 块中调用了 System.exit(1); 退出虚拟机;
· 子类异常在前,父类异常在后,即先处理小异常,后处理大异常;
自定义异常 :自定义异常类需要提供 2 个构造器。
public class MyException extends Exception | RuntimeException
{
public MyException(){}
public MyException(String msg){
this.super(msg);
}
public MyException(Throwable t){ // 支持异常的链式处理
this.super(t);
}
}
异常链 :链式处理
捕获 1 个异常后接着抛出另一个异常,同时把原始异常的信息保存下来的机制。
·♂· 图形用户界面编程 (了解即可)
GUI(Graphic User Interface)编程,图形界面组件库(AWT + Swing)+ 事件处理机制。
· AWT,抽象窗口工具集,Abstract Window Toolkit。 基本的窗口框架,重量级组件、依赖底层平台;
· Swing,轻量级组件,100% Java 实现,跨平台性能好。采用 MVC 设计模式,实现 GUI 组件的显示逻辑和数据逻辑的分离,灵活性好;
·♂· MySQL - JDBC
关于 MySQL 的基础,请参考 MySQL 初识 - sqh;
关于 JDBC 的基础,请参考 JDBC 初识 - sqh;
·♂· 注解
Annotation,接口,封装元数据,修饰程序元素、提供为其设置元数据的方法,允许在源文件中嵌入补充信息,类似 C# 中的特性。程序通过反射能获取指定元素的 Annotation 对象、进而提取注解中的元数据。Java 8 支持重复注解,需要 @Repeatable 修饰。访问和处理 Annotation 的工具为 APT,Annotation Processing Tool,对源代码文件进行检测,执行严格的代码检查。
- java.lang 包下的基本 Annotation:
· @Override:限定子类必须重写父类的方法,只能修饰方法;
· @Deprecated:标记已过时;
· @Suppress Warnings:抑制编译器警告;
· @Safe Varargs:专用于抑制堆污染 Heap pollution 警告;
· @FunctionalInterface:函数式接口声明,要求接口只能包含一个抽象方法,只能修饰接口;
- java.lang.annotation 包下的 元Annotation:
· @Retention:指定 Annotation 的生命周期;
RetentionPolicy.RUNTIME:
编译器将 Annotation 记录在 .class 文件中,运行时可以通过 JVM 或反射获取 Annotation 信息;
· @Target:指定 Annotation 修饰的目标程序元素,所有程序元素的父接口为 AnnotatedElement;
· @Documented:指示被修饰的 Annotation 接口将被 javadoc 工具提取成文档;
· @Inherited:Annotation 具有父子继承性;
自定义 Annotation:默认继承 Annotation 接口
public @interface AnnotationName{...}
其中,Annotation 定义中,成员变量必须以无形参方法的形式定义,可以用 default 指定初始值。
AnnotatedElement 接口:用于提取 Annotation 信息,实例方法
- getAnnotation(xxx):获取程序元素上的指定注解;
- getAnnotations(): 获取程序元素上的所有注解;
- isAnnotationPresent(xxx)():判断程序元素上是否存在指定注解;
·♂· I/O
具体参考 Java 输入输出体系学习 - sqh;
·♂· 多线程
具体参考 Java 多线程学习 - sqh;
·♂· 网络编程
具体参考 Java 网络编程学习 - sqh;
·♂· 易混淆点
- == ~ equals()
==:值相等、两个引用是否指向同一(内存)对象;
equals():Object默认提供的equals()方法等效于 ==,实际中按需重写;
- 直接量 “hello” ~ new String(“hello”)
“hello” 是编译时常量,常量池管理之,在常量池中存在且唯一;new String(“hello”) 是运行时先用常量池管理 “hello” 直接量,再构造一个新的String对象存在堆中,实际上一共产生了2个 “hello” 字符串对象。
- 构造器 ~ valueOf()
new 构造器创建全新对象,valueOf创建全新对象并缓存。