异常
1.1异常概述
1.1.1程序中的异常
(1)尝试通过if-else处理异常问题
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1=0;
if(in.hasNextInt()) {//如果输入的被除数是整数
num1=in.nextInt();
}else { //如果输入的被除数不是整数
System.err.println("输入的被除数不是整数,程序退出!");
System.exit(1);
}
System.out.print("请输入除数:");
int num2=0;
if(in.hasNextInt()) {//如果输入的除数是整数
num2=in.nextInt();
if(0==num2) { //如果输入的除数是0
System.err.println("输入的除数是0,程序退出!");
System.exit(1);
}
}else { //如果输入的除数不是整数
System.err.println("输入的除数不是整数,程序退出!");
System.exit(1);
}
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
System.out.println("感谢使用本程序!");
}
1.1.2什么是异常
异常:异常就是在程序的运行过程中所发生的不正常的事情,如所需文件找不到、网络连接不通或中断、算术运算出错(如被零除)、类型转换。
1.2异常的处理
1.2.1什么是异常处理
异常处理:异常处理机制就像我们对平时可能遇到的意外情况,预先想好了一些处理的办法,也就是说在程序执行代码的时候,万一发生异常,程序会按照预定的处理方法对异常进行处理,异常处理完毕后继续运行。程序出现异常的默认处理方式:一旦程序出现异常,程序将会立刻结束。
Java的异常处理通过五个关键字来实现的:try、catch、finally、throw和throws。
1.2.2try-catch块
/**
*使用try-catch进行异常处理
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
try {
int num1 =in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
System.out.println("感谢使用本程序!");
}catch (Exception e){
System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为0.");
e.printStackTrace();
}
}
(1)如果try块中语句正常执行完毕,不会发生异常,那么catch块中的所有语句都将会被忽略。
(2)如果try块中语句执行中遇到异常,并且这个异常与catch中声明的异常类型相匹配,那么try块中的所有语句都将会被忽略,而相应的catch块将会执行。
1.2.3try-catch-finally块
/**
*使用try-catch-finally进行异常处理
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
try {
int num1 =in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt(); System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
}catch(Exception e) {
System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为0.");
e.printStackTrace();
}finally {
System.out.println("感谢使用本次程序!");
}
}
(1)无论是否发生异常,finally块的代码总能被执行。
(2)如果try块中语句正常执行完毕,不会发生异常,那么catch块中的所有语句都将会被忽略。
(3)如果try块中语句执行中遇到异常,并且这个异常与catch中声明的异常类型相匹配,那么try块中的所有语句都将会被忽略,而相应的catch块将会执行。
(4)try-catch-finally结构中try块是必需的,catch和finally块为可选,但两者至少须出现其中之一。
(5)finally唯一不执行的情况:在异常处理代码中执行System.exit(1)。将退出Java虚拟机。
1.2.4多重catch块
/**
*使用多重catch进行异常处理
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
try {
int num1 =in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
} catch (InputMismatchException e) {
System.err.println("被除数和除数必须是整数");
}catch (ArithmeticException e){
System.err.println("除数不能为0");
}catch(Exception e) {
System.err.println("其他未知异常!");
}finally {
System.out.println("感谢使用本次程序!");
}
}
(1)使用多重catch块时,catch块的排列顺序必须是从子类到父类,最后一般是Exception类。
1.2.5声明异常——throws
Java通过关键字throws声明某个方法可能抛出各种异常,throws可以声明多个异常,之间用逗号隔开。
/**
* 通过try-catch捕获并处理异常
* @param args
*/
public static void main(String[] args) {
try {
divide();
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为0.");
e.printStackTrace();
}
}
///**
// * 通过throws继续声明异常
// */
//public static void main(String[] args) throws Exception{
// divide();
//}
/**
* 输入被除数和除数,计算商并输出
*/
public static void divide() throws Exception{
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 =in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
}
1.2.6常见的异常类型
异常 | 说明 |
---|---|
Exception | 异常层次结构的根类 |
ArithmeticException | 算术错误情形,如以零作除数 |
ArrayIndexOutOfBoundsException | 数组越界 |
NullPointerException | 尝试访问null对象成员 |
ClassNotFoundException | 不能加载所需的类 |
InputMismatchException | 欲得到的数据类型与实际输入的类型不匹配 |
IllegalArgumentException | 方法接收到非法参数 |
ClassCastException | 对象强制类型转换出错 |
NumberFormatException | 数字格式转换异常 |
1.3抛出异常
1.3.1抛出异常——throw
private String name="";//姓名
private int age=0;//年龄
private String sex="男";//性别
/**
设置性别
*/
public void setSex(String sex) throws Exception{
if("男".equals(sex)||"女".equals(sex)) {
this.sex=sex;
}else {
throw new Exception("性别必须是男或女!");
}
}
/**
设置年龄
*/
public void setAge(int age) throws Exception{
if(age>=1&&age<=100) {
this.age=age;
}else {
throw new Exception("年龄必须在1~100之间!");
}
}
/**
输出信息
*/
public void print() {
System.out.println(this.name+" ("+this.sex+","+this.age+"岁)");
}
/**
* 捕获异常
*2020年3月19日 上午10:38:41
*/
public static void main(String[] args) {
Person person = new Person();
try {
person.setSex("男");
person.setAge(120);
person.print();
} catch (Exception e) {
e.printStackTrace();
}
}
1.3.2异常的分类
Throwable类:所有的异常类型都是Throwable的子类,它的两个子类即Error和Exception。
Error类:表示仅靠程序本身无法修复的严重错误。
Exception类:有Java应用程序抛出和处理的非严重错误。
运行时异常:即程序在运行时所出现的错误。
Checked异常(非运行时异常):除了运行时异常外的其他由Exception继承来的异常。程序必须捕获或声明抛出异常。
1.4开源日志记录工具log4j
1.4.1日志的分类
(1)SQL日志:记录系统执行的SQL语句。
(2)异常日志:记录系统运行中发生的异常事件。
(3)业务日志:记录系统运行过程。
1.4.2如何使用log4j记录日志
(1)在项目中加入log4j所使用的JAR文件。
(2)创建log4j.properties文件。
(3)编写log4j.properties文件,配置日志信息。
1.4.3log4j配置文件
//设置Looger输出级别和输出目的地
log4j.rootLogge=info,stdout.logfile
//把日志信息输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.AimpleLayout
//把日志信息输出到jait.log
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=jbit.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}
%l %F %p %m%n
(1)各个输出级别:
fatal>error>warn>info>debug
(2)Log4j中最常用的Layout有以下三种:
HTMLLayout:格式化日志输出为HTML表格
SimpleLayout:以一种非常简单的方式格式化日志输出,它输出级别Level,然后跟着一个破折号“——”,最后是日志信息
PatternLayout:根据指定的转换模式格式化日志输出,从而支持丰富多样的输出格式。需要配置layout.ConversionPattern属性,若没有配置该属性,则使用默认的转换模式
(3)转换模式ConversionPattern:
%d:用来设置输出日志的日期和时间,默认格式为ISO8601。也可以在其后指定格式。
%m:用来输出代码中指定的消息。
%n:用来输出一个回车换行符
%I:用来输出日志时间的发生位置,包括类名、发生的线程,以及在代码中的行数。
%p:用来输出优先级,及debug、info、warn、error、fatal等。
%F:用来输出文件名。
%M:用来输出方法名。
集合框架
1.1集合框架的概述
1.1.1Java集合框架包含内容
集合框架:集合框架是为表示和操作集合而规定的一种统一的标准体系结构,集合框架都包含三大块内容:对外的接口,接口的实现和对集合运算的算法。
(1)接口:表示集合的抽象数据类型
(2)实现:集合框架中接口的具体实现
(3)算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算的方法;如:查询、排序
java集合中的的两大类接口:Collection和Map
(1)Collection:Collection 接口存储一组不唯一,无序的对象
(2)List:List 接口继承Collection 接口,存储一组不唯一(允许重复),有序(以插入的次序来放置元素,不会重写排列)的对象
(3)Set:Set 接口继承Collection 接口,存储一组唯一(不允许重复),无序的对象
(4)Map:Map接口存储一组键值对象,提供key到value的映射,Map中的Key不要求有序、不允许重复。value同样不要求有序,但允许重复 (5)Iterator(迭代器):接口是负责定义访问和遍历元素的接口
1.2List接口
List接口:常用的类:ArrayList和LinkedList(附加: Vector类:Vector集合类的使用(线程安全具有同步性),Stack类
常用方法 | 说明 |
---|---|
Object remove(int index ) | 从列表中删除指定位置元素,起始索引位置从0开始 |
boolean remove(Object o ) | 从列表中删除元素 |
boolean add(Object o) | 在类表末尾顺序添加元素,其实索引位置从0开始 |
void add(int index,Object o) | 在指定的索引位置添加元素,原索引位置及其后面的元素一次后移 注意:新添加元素的索引位置必须介于0和列表中的元素个数 |
int size() | 返回列表中的元素个数 |
Object get(int index) | 返回指定索引位 |
boolean contains(Object o ) | 判断列表中是否存在指定元素 |
1.2.1ArrayList集合类
(1)ArrayList集合类对数组进行了封装,实现了长度可变的数组,存储数据的方式和数组相同,都是在内存中分配连续的空间
-
添加数据: add()方法
-
取下标 :get(index i)
-
区别C#
-
C# Java 获取长度 count()方法 Size()方法 删除指定项 删除指定下标:RemoveAt() 删除指定值:Remove() 删除值跟删除下标:都是用remove方法,通过参数类型区分
public static void main(String[] args) {
// 1.创建4个狗狗对象
Dog ououDog=new Dog("欧欧","雪纳瑞");
Dog yayaDog=new Dog("亚亚","拉布拉多");
Dog meimeiDog=new Dog("美美","雪纳瑞");
Dog feifeiDog=new Dog("菲菲","拉布拉多");
//2.创建ArrayList集合对象并把4个狗狗对象放入其中
List dogs=new ArrayList();
dogs.add(ououDog);
dogs.add(yayaDog);
dogs.add(meimeiDog);
dogs.add(2,feifeiDog);//添加feifeiDog导指定位置
//3.输出集合中狗狗的数量
System.out.println("共计有:"+dogs.size()+"条狗狗.");
//4.遍历集合显示各条狗狗的信息
System.out.println("分别是:");
for (int i = 0; i < dogs.size(); i++) {
Dog dog=(Dog) dogs.get(i);
System.out.println(dog.getName()+"\t"+dog.getType());
}
}
1.2.2 LinkedList集合类
(2)LinkedList:采用链表存储方式。它提供了额外的addFirst(),addLast(),removeFirst()和removeLast()等方法;这些方法使得该集合可被当作堆栈(stack)或列(queue)
常用方法:
方法名 | 说明 |
---|---|
void addFirst(Object o) | 在列表的首部添加元素 |
void addLast(Object o) | 在列表的末尾添加元素 |
Object getFirst() | 返回列表中的第一个元素 |
Object getLast() | 返回列表中的最后一个元素 |
Object removeFirst() | 删除并返回列表中的第一个元素 |
Object removeLast() | 删除并返回列表中的最后一个元素 |
public static void main(String[] args) {
//1、创建4个狗狗对象
Dog ououDog = new Dog("欧欧","雪纳瑞");
Dog yayaDog = new Dog("亚亚","拉布拉多");
Dog meimeiDog = new Dog("美美","雪纳瑞");
Dog feifeiDog = new Dog("菲菲","拉布拉多");
//2、创建LinkedList集合对象并把多个狗狗对象放入其中
LinkedList dogs = new LinkedList();
dogs.add(ououDog);
dogs.add(yayaDog);
dogs.addLast(meimeiDog);
dogs.addFirst(feifeiDog);
//3、查看集合中第一条狗狗的昵称
Dog dogFirst = (Dog)dogs.getFirst();
System.out.println("第一条狗狗的昵称是:"+dogFirst.getName());
//4、查看集合中最后一条狗狗的昵称
Dog dogLast = (Dog)dogs.getLast();
System.out.println("第一条狗狗的昵称是:"+dogLast.getName());
//5、删除集合中第一条狗狗和最后一条狗狗
dogs.removeFirst();
dogs.removeLast();
//6、显示删除部分狗狗后的集合中各条狗狗的信息
System.out.println("\n输出部分狗狗后还有"+dogs.size()+"条狗狗");
System.out.println("分别是:");
for (int i = 0; i < dogs.size(); i++) {
Dog dog = (Dog)dogs.get(i);
System.out.println(dog.getName()+"\t"+dog.getStrain());
}
}
1.3Map接口
Map接口存储一组键值对象,提供key到value的映射,Map中的Key不要求有序、不允许重复。value同样不要求有序,但允许重复
常用方法
方法名 | 说明 |
---|---|
Object put(Object key, Object val) | 以“键-值对”的方式进行存储注意:键必须是唯一的,值可以重复,如果试图添加重复的键 |
Object get (Object key) | 注意:键必须是唯一的,值可以重复,如果试图添加重复的键 |
Object remove (Object key) | 删除由指定的键映射的“键-值对” |
Boolean isEmpty() | 若不存在键值对关系,则返回true |
int size() | 返回元素个数(返回此映射中的键-值映射关系数。) |
Set keySet () | 返回键的集合 |
Collection values () | 返回值的集合 |
boolean containsKey (Object key) | 如果存在由指定的键映射的“键-值对”,返回true |
void clear() | 从此映射中移除所有映射关系 |
1.3.1HashMap集合类
public static void main(String[] args) {
//1、使用HashMap存储多组国家英文简称和中文全称的"键-值对"
Map countries = new HashMap();
countries.put("CN", "中华人民共和国");
countries.put("RU", "俄罗斯联邦");
countries.put("FR", "法兰西共和国");
countries.put("US", "美利坚合众国");
//2、显示"CN"对应国家的中文全称
String country = (String)countries.get("CN");
System.out.println("CN对应的国家是:"+country);
//3、显示集合中元素个数
System.out.println("Map中共有"+countries.size()+"组数据");
//4、两次判断Map中是否存在"FR"键
System.out.println("Map中包含FR的key吗?"+countries.containsKey("FR"));
countries.remove("FR");
System.out.println("Map中包含FR的key吗?"+countries.containsKey("FR"));
//5、分别显示键集、值集和键-值对集
System.out.println(countries.keySet());
System.out.println(countries.values());
System.out.println(countries);
//6、清空HasMap并判断
countries.clear();
if(countries.isEmpty()) {
System.out.println("已经清空Map中的数据!");
}
}
1.4迭代器Interator
1.4.1使用Interator遍历集合类
通过迭代器Iterator实现遍历:
获取Iterator :Collection 接口的iterator()方法
Iterator的方法:
boolean hasNext():判断是否存在另一个可访问的元素
Object next():返回要访问的下一个元素
(1)遍历List
public static void main(String[] args) {
//1、创建4个狗狗对象
Dog ououDog = new Dog("欧欧","雪纳瑞");
Dog yayaDog = new Dog("亚亚","拉布拉多");
Dog meimeiDog = new Dog("美美","雪纳瑞");
Dog feifeiDog = new Dog("菲菲","拉布拉多");
//2、创建Map集合对象并把过个狗狗对象放入其中
Map dogMap = new HashMap();
dogMap.put(ououDog.getName(),ououDog);
dogMap.put(yayaDog.getName(),yayaDog);
dogMap.put(meimeiDog.getName(),meimeiDog);
dogMap.put(feifeiDog.getName(),feifeiDog);
//3、通过迭代器依次输出集合中所有狗狗的信息
System.out.println("使用Iterator遍历,所有狗狗的昵称品种分别是:");
Set keys = dogMap.keySet();//取出所有key的集合
Iterator it = keys.iterator();//获取Iterator对象
while(it.hasNext()) {
String key = (String)it.next();//取出key
Dog dog = (Dog)dogMap.get(key);//根据key取出对应的值
System.out.println(key+"\t"+dog.getStrain());
}
}
1.5泛型集合
(1)测试List应用泛型
public static void main(String[] args) {
//1、创建4个狗狗对象
Dog ououDog = new Dog("欧欧","雪纳瑞");
Dog yayaDog = new Dog("亚亚","拉布拉多");
Dog meimeiDog = new Dog("美美","雪纳瑞");
Dog feifeiDog = new Dog("菲菲","拉布拉多");
//2、创建ArrayList集合对象并把多个狗狗对象放入其中
List<Dog> dogs = new ArrayList<Dog>();//标记元素类型
dogs.add(ououDog);
dogs.add(yayaDog);
dogs.add(meimeiDog);
dogs.add(2,feifeiDog);//添加feifeiDog到指定位置
//3、显示第三个元素信息
Dog dog3 = dogs.get(2);//无须类型强制转换
System.out.println("第三条狗狗信息如下:");
System.out.println(dog3.getName()+"\t"+dog3.getStrain());
//4、使用foreach语句遍历dogs对象
System.out.println("\n所以狗狗的信息如下:");
for (Dog dog:dogs) {
System.out.println(dog.getName()+"\t"+dog.getStrain());
}
}
(2)测试对Map应用泛型
public static void main(String[] args) {
//1、创建4个狗狗对象
Dog ououDog = new Dog("欧欧","雪纳瑞");
Dog yayaDog = new Dog("亚亚","拉布拉多");
Dog meimeiDog = new Dog("美美","雪纳瑞");
Dog feifeiDog = new Dog("菲菲","拉布拉多");
//2、创建Map集合对象并把多个狗狗对象放入其中
Map<String,Dog> dogMap = new HashMap<String,Dog>();
dogMap.put(ououDog.getName(), ououDog);
dogMap.put(yayaDog.getName(), yayaDog);
dogMap.put(meimeiDog.getName(), meimeiDog);
dogMap.put(feifeiDog.getName(), feifeiDog);
//3、通过迭代器依次输出集合中所有狗狗信息
System.out.println("使用Iterator遍历,所有狗狗的昵称和品种分别是:");
Set<String> keys = dogMap.keySet();//取出所有key的集合
Iterator<String> it =keys.iterator();
while(it.hasNext()) {
String key =it.next();//取出key
Dog dog = dogMap.get(key);//根据key取出相应的值
System.out.println(key+"\t"+dog.getStrain());
}
}
使用泛型集合在创建集合对象是指定中元素的类型,在从集合取出元素是无须进行类型强制转换,避免了ClassCastException异常。