第一章 异常与异常处理
1.1 异常简介
有异于常态,和正常的情况不一样,有错误出现
阻止当前的方法或作用域
异常的始祖: Throwable
Throwable
Error 程序错误导致崩溃
虚拟机错误
线程死锁Exception 编码、环境、用户操作出现问题
RunTimeException 非检查异常(JVM 自动捕获抛出)
NullPointerException
ArrayIndexOutOfBoundsException
ClassCastException
ArithmeticException检查异常 (手工处理)
IOException
SQLException
others…
1.2 使用try-catch-finally 处理异常
注意处理多个异常时的顺序,先子类,后父类
try-catch 处理异常后,需要用finally 来执行善后工作,例如关闭文件,断开网络或数据库连接
1.3 Java中的异常抛出
throw : 将产生的异常抛出(动作)
throws: 声明将要抛出何种异常 (声明)
public void 方法名(参数列表) throws 异常列表 {
//调用会抛出异常的方法;
//或者是直接使用 throw new Exception(); 来抛出异常
}
例如,创建一个方法divide,其中当除数为0时会抛出异常
public void divide(int a, int b) throws Exception {
if(b == 0) {
throw new Exception("两数相除,除数不能为0!");
} else {
System.out.println("两数相除,结果为:" + a/b);
}
调用1: 可以捕获并处理该异常:
public void compute() {
/**
* 省略其他代码
* */
try {
divide(5,0);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
调用2: 不能处理异常,将其抛出至上级调用,让上级来处理
public void compute() throws Exception {
/*
* 省略其他代码
* /
divide(5,0);
}
Java 标准类异常
自定义异常
class 自定义异常类 extends 异常类型 {
}
可继承于Java 类库中意思相近的异常类型,或是直接继承于所有异常的基类:Exception类。
简单的自定义一个异常:
package com.imooc.test;
public class DrunkException extends Exception {
// 由于下面已经定义一个有参的构造函数,所以系统不会为我们自动生成一个无参的构造函数
//但我们一般需要无参的构造函数,所以自己添加一个
public DruckException() {
}
//定义一个带字符串的构造器
public DrunckException(String message) {
//调用基类的构造方法即可
super(message);
}
Java 中的异常链
ChainTest类:
package com.imooc.test
public class ChainTest {
/**
* test1(): 抛出“喝大了”异常
* test2(): 调用test1(), 捕获“喝大了”异常。
* 并且把test2() 包装成运行时异常,继续抛出
* main方法中,调用test2() 方法,尝试捕获test2()方法抛出的异常
* /
public static void main(String[] args){
//创建ChainTest 的一个实例
ChianTest ct = new ChainTest();
try {
ct.test();
} catch (Exception e) {
e.printStackTrace();
}
}
//抛出新的异常,所以在test1 后面声明要抛出异常
//没添加throws DrunkException 会报错
public void test1() throws DrunkException {
//调用含参构造器
throw new DrunkException("喝车别开酒");
}
public void test2() {
try {
//没有try-catch 处理时会报错,因为test1()会抛出异常
test1();
} catch (DrunkException e) {
RunTimeException newExc =
new RunTimeException("司机一滴酒,亲人泪两行~~");
newExc.initCause(e);
throw newExc;
}
}
}
运行结果:
另外一种更加简便的异常链使用方法,只需更改test2()方法
public void test2() {
try {
//没有try-catch 处理时会报错,因为test1()会抛出异常
test1();
} catch (DrunkException e) {
//直接把捕获到的异常e 传递进去
RunTimeException newExc =
new RunTimeException(e);
//newExc.initCause(e);
throw newExc;
}
}
运行后结果:
Java 异常经验总结
- 处理运行时异常,采用逻辑去合理规避,同时辅助try-catch处理
- 在多重catch块后,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切记只是简单的调用printStackTrace() 去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源
第二章 认识Java中的字符串
什么是Java中的字符串
在Java中,字符串被作为String 类型的对象处理
String 类位于 java.lang 包中。 默认情况下,该包被自动导入所有的程序。
创建String对象的方法
//创建一个字符串对象imooc,名为s1
String s1 = "imooc";
//创建一个空字符串对象,名为s2
String s2 = new String();
//创建一个字符串对象imooc,名为s3
String s3 = new String("imooc");
2.2 Java中字符串的不变性
String对象创建后不能被修改,是不可变的;
所谓的修改其实是创建了新的对象,所指向的内存空间不同。
String s1 = "imooc";
String s2 = "imooc";
String s3 = new String("imooc");
String s4 = new String("imooc");
//多次出现的字符常量,Java编译程序只创建一个,所以返回true
System.out.println(s1 == s2);
//s1 和 s3 是不同的对象,返回false
System.out.println(s1 == s3);
//s3和s4是不同的对象,返回false
System.out.println(s3 == s4);
//字符串s1被修改,指向新的内存空间
s1 = "Welcome to " + s1;
//输出 Welcome to immoc
System.out.println(s1);
解析:
1、String s1 = “imooc”声明了一个字符串对象,s1存放了到字符串对象的引用。如图:
然后通过 s1 = “Welcome to ” + s1;
改变了字符串s1,其实质是创建了新的字符串对象,变量s1指向了新创建的字符串对象,如下图
2、一旦一个字符串在内存中创建,则这个字符将不可改变。
想要创建一个可以改变内容的字符串,可以使用StringBuilder 和 StringBuffer类。
3、 每次new一个字符串就是产生一个新的对象,即使两个字符串的内容相同,使用”==“比较时结果为false。但是利用比较内容的方法equals()才返回true。
2.3 Java中String类的常用方法
String 类提供了许多用来处理字符串的方法:
- 获取字符串长度
- 对字符串进行截取
- 将字符串转换为大写或小写
- 字符串分割等
String 类常用方法:
友情提示:
1. 字符串 str 中字符的索引从0开始,范围为 0 到 str.length()-1
2. 使用 indexOf 进行字符或字符串查找时,如果匹配返回位置索引;如果没有匹配结果,返回 -1
3. 使用 substring(beginIndex , endIndex) 进行字符串截取时,包括 beginIndex 位置的字符,不包括 endIndex 位置的字符
4. ==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象
equals(): 比较存储在两个字符串对象中的内容是否一致
Ps: 字节是计算机存储信息的基本单位,1 个字节等于 8 位, gbk 编码中 1 个汉字字符存储需要 2 个字节,1 个英文字符存储需要 1 个字节。所以我们看到上面的程序运行结果中,每个汉字对应两个字节值,如“学”对应 “-47 -89” ,而英文字母 “J” 对应 “74” 。同时,我们还发现汉字对应的字节值为负数,原因在于每个字节是 8 位,最大值不能超过 127,而汉字转换为字节后超过 127,如果超过就会溢出,以负数的形式显示
认识 Java 中的 StringBuilder 类
在Java中,除了可以使用 String 类来存储字符串,还可以使用 StringBuilder 类或 StringBuffer 类存储字符串
String 类具有是不可变性
String str = "hello";
//输出 hello world
System.out.println(str + " world");
//输出 hello
System.out.println(str);
从运行结果中我们可以看到,程序运行时会额外创建一个对象,保存 “helloworld”。当频繁操作字符串时,就会额外产生很多临时变量。使用 StringBuilder 或 StringBuffer 就可以避免这个问题。
StringBuilder 和StringBuffer ,它们基本相似,不同之处,
StringBuffer 是线程安全的,
StringBuilder 则没有实现线程安全功能,所以性能略高。
因此一般情况下,如果需要创建一个内容可变的字符串对象,应优先考虑使用 StringBuilder 类。
StringBuilder 类常用方法:
示例1:
运行结果:
字符串长度: 14
插入前: hello imooc520
插入后: hello imooc!520
示例2:
第三章 Java 中必须了解的常用类
Java中的包装类
相信各位小伙伴们对基本数据类型都非常熟悉,例如 int、float、double、boolean、char 等。基本数据类型是不具备对象的特性的,比如基本类型不能调用方法、功能简单。。。,为了让基本数据类型也具备对象的特性, Java 为每个基本数据类型都提供了一个包装类,这样我们就可以像操作对象那样来操作基本数据类型。
基本类型和包装类之间的对应关系:
基本类型 | 对应的包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
包装类主要提供了两大类方法
- 将本类型和其他基本类型进行转换的方法
- 将字符串和本类型及包装类互相转换的方法
Integer 包装类的构造方法:
Integer包装类的常用方法:
Java中基本类型和包装类之间的转换
以 Integer 为例(其他几个包装类的操作雷同哦):
基本类型和包装类之间经常需要互相转换,JDK 1.5 引入了自动装箱和拆箱的机制。使得包装类和基本类型之间的转换就更加轻松便利了。
装箱: 基本类型 ==> 包装类
int i = 10; //定义一个int基本类型
Integer x = new Integer(i); //手动装箱
Integer y = i; //自动装箱
拆箱: 包装类==> 基本类型的值
Integer j = new Integer(8); //定义一个Integer包装类对象,值为8
int m = j.intValue(); //手动拆箱为int类型
int n = j; // 自动拆箱为int类型
Java 中基本类型和字符串之间的转换
在程序开发中,我们经常需要在基本类型和字符串之间进行转换。
- 基本类型 ==> 字符串 有三种方法:
1. 使用包装类的 toString() 方法
2. 使用String类的 valueOf() 方法
3. 用一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串
// 将基本类型转换为 字符串
int c = 10;
String str1 = Integer.toString(c);
String str2 = String.valueOf(c);
String str3 = c + "";
- 字符串 ==> 基本类型 有两种方法
- 调用包装类的parseXxx 静态方法
- 调用包装类的valueOf() 方法转换为基本类型的包装类,会自动装箱
//将字符串转换为基本类型
String str = "8";
int d = Integer.parseInt(str);
int e = Integer.valueO(str);
PS:其他基本类型与字符串的相互转化这里不再一一列出,方法都类似
使用Date 和SimpleDateFormat类表示时间
在程序开发中,经常需要处理日期和时间的相关数据 ,这时我们就可以使用java.util包中的Date类。
Date 类的最主要作用就是获取当前时间:
Date d = new Date(); //使用默认的构造方法创建Date对象
System.out.println(d); //输出Date对象
使用Date类的默认无参构造方法创建的对象就代表当前时间。
输出结果为:
Mon Aug 10 09:22:30 CST 2015
//CST China Standard Time
当我们要把时间按照一定格式显示时,就要使用java.text包中的SimpleDateFormat类了。
SimpleDateFormat类可以将日期转换为指定格式的文本,也可以将文本转换为日期。
- 使用format()方法将日期转换为指定格式的文本
//创建Date对象,表示当前时间
Date d = new Date();
//创建SimpleDateFormat对象,确定目标格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//调用format方法,格式化时间,转换为指定格式字符串
String today = sdf.format(d);
// 输出转换后的字符串,结果是: 2015-08-10 17:17:17
System.out.println(today);
代码中的“yyyy-MM-dd HH:mm:ss”为预定义字符串。
- 使用 parse()方法将文本转换为日期
//创建日期格式字符串
String day = "2015年08月10日 17:17:17"
//创建SimpleDateFormat对象,指定字符串的日期格式
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//调用 parse() 方法,将字符串转换为日期
Date date df.parse(day);
// 输出转换后的时间: Mon Aug 10 09:22:30 CST 2015
System.out.println(date);
Calendar 类的应用
Date类最主要的作用就是获取当前时间,同时这个类里面也具有设置时间以及一些其他功能,但是由于本身设计的问题,这些方法受到众多批评,不建议使用。
推荐使用Calendar类进行时间和日期的处理。
java.util.Calendar 是一个抽象类,可以通过调用getInstance() 静态方法 获取一个Calendar对象,此对象已由当前日期时间初始化,即默认代表当前时间。
Calendar c = Calendar.getInstance();
获取Calendar 年月日以及时间信息的方法:
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1; //0表示1月
int day = c.get(Calendar.DAY_OF_MONTH);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
Calendar 类提供了getTime() 方法,用来获取Date对象,完成Calendar 和 Date的转换。
Calendar 类还可以通过getTimeInMillis() 方法 获取此Calendar 的时间值,一毫秒为单位。
Calendar c = Calendar.getInstance();
Date date = c.getTime(); //将calendar 对象转换为Date 对象
Long time = c.getTimeInMillis(); 获取当前毫秒数
System.out.println(date);
System.out.print(time);
运行结果:
Wed Jun 11 11:26:59 CST 2014
1402457219381
使用Math类操作数据
Math 类位于 java.lang包中,包含用于执行基本数学运算的方法。
Math类的所有方法都是静态方法,所以使用该类的方法时,可以直接使用
类名.方法名 来直接调用。
常用方法:
返回值 | 方法名 | 解释 |
---|---|---|
long | round() | 返回四舍五入后的整数 |
double | floor() | 返回小于参数的最大整数 |
double | ceil() | 返回大于参数的最小整数 |
double | random() | 返回[0,1)之间的随机浮点数 |
示例:
double a = 12.81;
int b = (int) a; //去掉小数部分: 12
long c = Math.round(a); //13
double d = Math.floor(a); // 12.0
double e = Math.ceil(a); // 13.0
double x = Math.random(a); //0.42585849456602687
int y = (int)(Math.random(a) * 99); //45
第四章 Java 中的集合框架
4.1 Java中的集合框架概述
集合概述: Java 中的集合类,是一种工具类。就像是容器,存储任意数量的具有共同属性的对象。
集合的作用
- 在类的内部,对数据进行组织;
- 简单而快速的搜索大量的条目;
- 有的集合接口,提供了一系列排列有序的元素,并且可以在序列中间快速的插入或删除有关元素;
- 有的集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型的。
为什么选择集合而不选择数组:
1. 数组的长度固定,集合长度可变;
2. 数组只能通过下标访问元素,类型是固定的; 而 有的集合可以通过任意类型查找所映射的具体对象。
Java 集合框架体系结构:
- Collection (直接存储对象)
- List 序列 :有序,可重复
- ArrayList 数组序列 //常用
- LinkedList 链表
- Queue 队列 : 有序,可重复
- LinkedList 链表
- Set 集 : 无序,不可重复
- HashSet 哈希集 //常用
- Map (内部映射 Entry < Key,Value>)
-
-HashMap 哈希表 //常用
4.2 Collection 接口、子接口以及实现类
Collection 接口
- 是List、Queue和Set接口的父接口
- 定义了可用于操作List,Queue和Set 的方法 —增删改查
List接口及其实现类ArrayList
- List是元素有序并且可以重复的集合,被称为序列;
- List可以精确的控制每个元素的插入位置,或删除某个位置的元素;
- ArrayList 数组序列,是List的一个重要实现类;
- ArrayList 底层是由数组实现的。
注意:
- 对象存入集合都会忽略其原有的类型,都变成Object类型。从集合中取出对象时需要类型转换。
集合遍历
List : get 方法,forEach,Iterator
Set : forEach,Iterator
Set不能用get(), 因为Set为无序的
每次遍历Set集合得到的顺序不相同。
ForEach
Iterator
get() 方法
List中set(index,Object) 方法
List中删除方法
泛型
在集合可以存储任意类型的对象(对象的引用)。
- 把某个对象放入集合是,会直接忽略其类型,直接当做Object类型。
泛型规定了某个集合只能存储特定类型及其子类型的元素。
- 会在编译期间进行类型检查
- 可以直接按指定类型获取集合中的对象
- 存储除指定类型及其子类型外的对象,程序会报错。
泛型集合中的限定类型不能是基本类型,但可以通过使用它们的包装类限定允许存入的基本类型。
int –> Integer
long –> Long
boolean –> Boolean
Set 接口及其实现类 HashSet
- Set 是元素无序,并且不可重复的,称为集
- HashSet
- Set 中没有 set() 方法来修改某个元素
Set中添加对象,无论添加多少次,最终只会保留该对象第一次添加的那一个引用。
Set中可以添加null 对象
Map和HashMap
Map 接口提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够根据key快速找到value。
- Map中的键值对以Entry类型的对象实例形式存在。
- key不能重复,value可以重复
- 每个键最多只能映射到一个值。
- Map提供了分别返回key值集合,value值集合以及Entry集合的方法,可以用来遍历
- Map支持泛型 Map<K,V>
HashMap
- HashMap 是Map的一个重要实现类,也是最常用的一个,基于哈希表实现
- HashMap中的Entry 对象时无序排列的,遍历时得到的顺序不一样。
- Key值和value值都可以为null,但是一个 HashMap 最多只能有一个null的key值。
Arrays 工具类
包含操作数组的各种静态方法
Collections 工具类
java.util.Collections
提供静态方法操作集合的对象,也是Java集合框架的成员
最常用的是Collections.sort() 方法
Comparable & Comparator
Comparable 接口 — 可比较的 – 默认的比较规则
- 实现该接口表示:这个类的实例可以比较大小,可以进行自然排序
- 定义了默认的比较规则
- 其实现类需要实现compareTo() 方法
public int comparaTo(T t) { }
- compareTo() 方法返回正数表示大于,返回负数表示小于,返回0表示等于。
Comparator 接口 — 比较工具接口 – 临时的比较规则
- 用于实现临时比较规则,而不是默认比较规则
- 其实现类需要实现compare() 方法
public int compare(T t1, T t2) { }
- Comparator 和 Comparable 都是Java集合框架的成员。
- 可以将Comparator 传递给 sort方法。
Java 集合框架
- Collection接口
- Collections 工具类
- Map 接口
- Compatator 接口
- Comparable 接口