Java 基础概述(中)
异常机制
异常概述
- 异常:在 Java 中,程序执行当中发生的不正常的情况称为异常(语法和逻辑的错误不算异常)
- 异常分类:
Error
和Exception
异常的体系结构
java.lang.Throwable
:所有异常的超类Error
:错误,一般不进行处理Exception
:异常,可以进行处理- 运行时异常
RuntimeException
,也称为非受检异常ArithmeticException
ClassCastException
IllegalArgumentException
IndexOutOfBoundException
NoSuchElementException
NullPointException
- 编译时异常,也称为受检异常
IOException
ClassNotFoundException
CloneNotSupportedException
- 运行时异常
异常的处理机制
try-catch-finally
try
:用于选定捕获异常的范围,将可能出现异常的代码放在 try 语句块中catch
:用于对异常对象的处理,可以存在一个或者多个 catch 语句- catch 的异常类型如果存在父子类关系,则子类需要声明在上面
getMessage()
方法用于获取异常信息,返回字符串printStackTrace()
方法用于输出异常类名和异常信息,以及异常出现在程序当中的位置
finally
:作为异常处理机制的统一出口- 不管 try 中的代码是否发生异常,catch 语句是否执行,catch 中是否有 return,finally 中的代码都将被执行
- 主要用于回收 try 中打开的物理资源(数据库连接、网络连接、磁盘文件等)
throws
throws
抛出异常也是 Java 处理异常的一种方式,若一个方法导致一个异常但不对异常进行处理,则必须在方法的声明中抛出这个异常,供调用者进行处理- 抛出异常的规则:
- 不受检异常可以不用
throws
声明 - 受检异常要么用
throws
抛出,要么进行try-catch
处理 - 子类重写的方法不能抛出比父类被重写方法范围更大的异常类型
- 不受检异常可以不用
自定义异常
- 自定义异常只需要继承
Exception
类即可 - 自定义异常在使用时通过
throw
抛出 - 自定义异常做重要的是异常类的名字,当异常出现时,通过名字即可判断异常类型
基本类库
包装类
- 每种基本数据类型都有对应的包装类
- 所有包装类都是抽象类
Number
的子类 - 包装类的应用:
- 实现包装类与基本数据类型之间的相互转换:基本类型–>包装类称为装箱,反之称为拆箱(Java 1.5 之后可以自动拆箱装箱)
- 字符串与基本类型之间的转换
- 借助包装类的
valueOf()
或parseXXX()
方法转换成对应的基本类型 - 借助包装类的
toString()
转换为字符串
- 借助包装类的
Math 类
Math
java.lang.Math
提供了一系列的静态方法用于科学计算,其方法参数和返回值一般为double
类型Math
的方法都被定义为static
形式,可以通过类直接调用
- 常用函数
Math.abs()
:求绝对值Math.ceil()
:向上取整Math.floor()
:向下取整Math.max()
:求两数中的最大数Math.min()
:求两数中的最小数Math.sqrt()
:开平方根Math.pow()
:求某数的任意次方,抛出ArithmeticException
处理溢出异常Math.round()
:double
类型四舍五入为long
类型
Math
包下的高精度类BigInteger
类,表示不可变的任意精度的整数,内部使用一个int[]
来模拟一个非常大的证书BigDecomal
类,支持不可变的、任意精度的符号十进制定点数,一般用于金额计算等精度较高的场景
Random
的使用java.long.Math,Random
:返回double
值,该值大于等于0.0小于1.0 ,即取值范围为[0.0, 1.0)java.util.Random
:创建 Random 对象并通过nextInt()/nextLong()
等取随机值
日期时间类
java.util.Date
Date
类用于封装当前的日期和时间,精确到毫秒- 无参构造器
Date()
:可以获得本地当前时间 - 有参构造器
Date(long date)
:参数为从 1970 年开始的毫秒数 - 常用方法:
after()/before(Date date)
:判断两个时间的早晚,返回 boolean 类型compareTo(Date anotherDate)
:比较两个时间的顺序,返回 int 类型getTime()/setTime(long date)
:获取当前时间
java.text.SimpleDateFormat
- 用来格式化和解析日期的具体类
- 允许日期转文本或者文本转日期
- 无参构造器/有参构造器
SimpleDateFormat("输出格式")
:定义标准日期输出格式 - 常用方法:
format(Date date)
:按照实例化对象时的输出格式输出日期,返回 String 类型parse(String dateStr)
:解析指定的日期并按实例化时的格式输出
java.util.Calendar
Calendar
是一个抽象基类,用于完成日期字段之间相互操作的功能- 通过
Calendar.getInstance()
方法进行实例化 - 通过
get(int field)
方法来获得想要的时间信息,如YEAR
/MONTH
/DAY_OFWEEK
/HOUR_OF_DAY
/MINUTE
System 类
java.lang.System
System
类代表系统,系统级的很多属性和控制方法都放置在该类的内部- 该类的构造器被
private
修饰,故无法创建该类的对象,但是其内部的成员变量和成员方法都是static
的,可以直接通过类进行调用 System
内含三个成员变量in/out/err
,分别代表标准输入流、标准输出流和标准错误输出流
- 常用方法:
currentTimeMilis()
:返回当前的计算机时间(毫秒数)exit(int status)
:退出程序,其中 status 为 0 代表正常退出,非 0 代表异常退出gc()
:请求系统进行垃圾回收,具体是否会受取决于垃圾回收算法以及系统执行的情况getProperth(String key)
:获取系统中属性名为 key 的属性所对应的值
String 类
String
- 是一个
final
类,代表不可变的字符序列,不可被继承 String
对象的字符内容是存储在一个字符数组value[]
中的- 注意
String s1 = "test"
与String s2 = new String("test")
的区别!前者存储在常量池,后者存储在堆内存
- 是一个
String
的基本使用- 常量与常量的拼接结果在常量池,且常量池中不会存在相同的内容
- 拼接中只要有一个是变量,则结果存储在堆中
- 可以使用
intern()
方法手工将字符存入字符串常量池
String
常用方法- 基本操作
int length()
:返回字符串长度int indexOf(String str)
:返回指定子字符串在此字符串中第一次出现处的索引int lastIndexOf(String str)
:返回指定子字符串在此字符串中最后一次出现处的索引char charAt(int index)
:返回某索引处的字符
- 转化操作
char[] toCharArray()
:转换为一个字符数组static String valueOf(int i)
:基本数据类型转换为字符串String toLowerCase()
:将所有字符转换为小写String toUpperCase()
:将所有字符转换为大写
- 替换与去除
String replace(char oldChar, char newChar)
:用新字符替换字符串中所有的旧字符String trim()
:返回字符串的副本,忽略前后的空格
- 截取与分割
String[] split(String regex)
:根据正则表达式的匹配拆分此字符String substring(int beginIndex, int endIndex)
:截取从起始索引到终止索引的子字符串
- 判断
boolean endsWith(String suffix)
:判断字符串是否以指定后缀结束boolean startsWith(String prefix)
:判断字符串是否以指定前缀开始boolean contains(CharSequence s)
:判断是否包含指定的 char 序列boolean matches(String regex)
:判断是否匹配给定的正则表达式boolean equalsIgnoreCase(String anotherString)
:判断字符串内容是否相同(忽略大小写)
- 基本操作
StringBuffer 和 StringBuilder
- 三者的区别
String
:不可变字符序列StringBuffer
:可变字符序列,效率低,线程安全StringBuilder
:可变字符序列,效率高,线程不安全
- 常用方法
append(xxx)
:字符串拼接delete(int start, int end)
:删除指定位置的内容replace(int start, int end, String str)
:将 [start, end) 位置替换为 strinsert(int offset, xxx)
:在指定的位置插入xxxreverse()
:反转当前字符序列
Java 集合
Java 集合可以分为 Collection
和Map
两种:
Coleection
:单列数据,定义了一组存取对象的集合List
:元素有序、不可重复的集合Set
:元素无序、不可重复的集合
Map
:双列数据,保存具有映射关系的“key-value”对的集合
Iterator 接口
Collection
接口继承了Iterator
接口,所有Collection
集合都有iterator()
方法,可以实现一个迭代器对象。每一次调用该方法都将获得一个全新的迭代器对象,默认游标在第一个元素之前- 常用方法:
boolean hasNext()
:判断是否存在下一个元素next()
:返回集合中的元素(调用该方法之前必须调用hasNext()
方法进行检测,否则可能抛出NoSuchElemengException
异常)default void remove()
:遍历中删除元素(遍历删除调用迭代器的方法,而不是集合对象的remove()
;如果还未调用next
或者在上一次调用next
之后已经调用了remove
再次调用remove
都将产生IllegalStateException
异常)
- JDK 5 提供了
foreach
遍历Collection
,底层就是调用iterator
完成操作
Collection 接口
Collection
接口是List
、Set
以及Queue
的父接口- 常用方法:
add(Object obj)
/addAll(Collection coll)
:添加元素int size()
:获取元素个数void clear()
:清空元素boolean isEmpty()
:是否为空集合boolean contains(Object obj)
:是否包含某个元素boolean remove(Object obj)
:删除boolean retainALL(Coolection c)
:取交集boolean equals(Object obj)
:集合是否相等Object[] toArray()
:转数组iterator()
:获取迭代器
List 接口
ArrayList
- 是一个变长的数组,能够自动扩展大小
- 线程不安全的,多线程访问一个
ArrayList
集合时,需要手动保证集合的同步性 - 可以存放
null
- 查询速度快,但是插入和删除数据较慢(因为需要移动很多数据)
LinkedList
- 是一个双向链表,内部没有声明数组,而是维护了
Node
类型的first
和last
用于记录首末元素 - 是线程不安全的
- 可以存放
null
- 插入和删除效率高,查询速度慢
Vector
- 一个古老的集合,基本操作与
ArrayList
相同 - 线程安全的
- 访问效率低,不建议使用
Set 接口
HashSet
- 无序,不能保证元素的排列顺序,无索引
- 集合元素可以为
null
- 线程不安全的
- 对于存放在
Set
中的对象,对应的类一定要重写equals()
和hashCode(Object obj)
方法,以实现对象相等的规则。即相等的对象必须有相等的散列码。
LinkedHashSet
HashSet
的子类- 元素存放有序:根据元素的
HashCode
值来决定元素的存储位置,同时使用双向链表维护元素的次序 - 其插入性能略低于
HashSet
,但在迭代访问元素时具有很好的性能
TreeSet
- 元素存放有序
- 有两种元素排序方法:自然排序和定制排序
- 将一个对象添加到
TreeSet
中时必须实现Comparable
接口,以调用集合元素的compareTo(Object obj')
方法来比较元素的大小,进行排序
Map 接口
- 用于存放具有映射关系的数据:
key-value
key
采用Set
存放,因此不允许重复,常用String
作为“键”- 常用方法:
Object put(Object key, Object value)
:添加Object remove(Object key)
:删除Object get(Object key)
:获取值int size()
:获取长度boolean contains(Object key)
:判断是否包含 keyboolean isEmpty()
:判断是否为空Set keySet()
:获取所有的 key 集合Collection values()
:获取所有 values 集合Set entrySet()
:获取所有 key-value 对的集合
HashMap
- 允许使用 null 作为键或者值
- 所有 key 构成的集合是
Set
,是无序不可重复的;所有 value 构成的集合是Collection
,是无序可重复的;所有 key-value 对(即 entry)构成的集合是Set
,无序不可重复 HashMap
通过equals
和hashCode()
判断两个 key 是否相等;通过equals()
判断两个 value 是否相等- 存储结构:jdk 7 采用“数组 + 链表”;jdk 8 采用“数组 + 链表 + 红黑树”
LinkedHashMap
- 是
HashMap
的子类,在HashMap
存储结构的基础上,使用双向链表来记录元素添加的顺序 - 与
LinkedHashSet
类似,LinkedHashMap
可以维护键值对的插入顺序
TreeMap
- 可以保证所有的键值对处于有序状态,底层使用红黑树存储数据结构
TreeMap
通过compareTo()
或者compare()
方法是否返回 0 判断 key 是否相等- 两种元素的排序方法:
- 自然排序:存入的 key 必须实现
Comparable
接口 - 定制排序:创建
TreeMap
时,需要传入一个Comparator
对象,该对象负责对存入的所有 key 进行排序
- 自然排序:存入的 key 必须实现
HashTable
HashTable
实现原理与HashMap
基本相同,底层使用哈希表结构,查询速度快,键值对无序- 不同于
HashMap
,HashTable
是线程安全的;且HashTable
不允许null
作为 key
Properties
Properties
是HashTable
的子类,用于处理属性文件- 属性文件中的 key 和 value 一般为 String 类型,故
Properties
的 key 和 value 都是 String 类型 - 存取数据,使用
setProperty(String key, String value)
和getProperty(String key)
Collections 工具类
Collections
是一个操作集合的工具类,提供了一系列的静态方法对集合元素进行排序、查询和修改等操作- 常用方法:
- 排序操作
sort(List)
:按照自然规则对元素进行排序sort(List, Comparator)
:根据Comparator
定义的规则对元素进行排序reverse(List)
:反转元素swap(List, int, int)
:将指定集合 i 与 j 处的元素对调
- 查找替换
Object max(Collection)
:按照自然规则返回集合中的最大元素,min()
同理Object max(Collection, Comparator)
:按照定制规则返回集合中的最大元素,min()
同理int frequency(Collection, Object)
:返回指定集合中指定元素出现的次数void copy(List dest, List src)
:将 src 中的内容复制到 destboolean replaceAll(List list, Object oldVal, Object newVal)
:使用新值替换 List 对象所有的旧值
- 同步控制
synchronizedXxx()
:可以将指定的集合包装为线程同步的集合,解决多线程并发访问的安全问题
- 排序操作