Java异常和集合框架

Java异常和集合框架

异常

什么是异常,异常就是在程序运行过程中出现错误的情况,一旦出现异常,程序将会立刻结束,在Java中异常有以下几种分类:

  1. 编译异常:语法错误,不能运行,在编译阶段就报错。
  2. 运行异常:能正常运行,但是运行报错。
  3. 逻辑异常:结果错误,能正常编译,能正常运行,但是结果错误,与预期的结果不一样。

异常类型结构

异常类型结构分类:
Java异常和集合框架_第1张图片

  1. Throwable类:所有异常类型都是Throwable类的子类,它派生了两个子类,Error和Exception
  2. Error类:表示仅靠程序本身无法恢复的严重错误。
  3. Exception类:由Java应用程序抛出和处理的非验证错误,程序本身可以处理的异常。
  4. RuntimeException类:运行时异常,Exception的子类。
  5. 非运行时异常:Exception类的子类,除了RuntimeException类及其子类的所有Exception类的子类。

列举我们在Java程序中常见的运行时异常类型:

异常 说明
InputMismatchException 输入类型不匹配异常
NullPointException 空指针异常
ArrayIndexOutOfBoundsException 数组下标越界异常
StringIndexOutOfBoundsException 字符串下标越界异常
ArithmeticException 算数异常
NumberFormatException 转换异常
FileNotFoundException 文件找不到异常
classNotFoundException 类文件找不到异常

异常的捕获和处理

在Java中异常的处理手段有:

  1. try…catch…finally
  2. throw…throws…

try:监控可能发生错误的代码。

catch:捕获异常

finally:不管是否发生异常,finally中的代码一定会执行

这三个中两两配合使用,也可以一起使用,其中try是必须有的,catch和finally可以选其一,catch可以有多个,finally最多一个。

语法如下:

try{
    //可能出现异常的代码块
}catch(InputMismatchException e){
    //当产生InputMismatchException异常时的处理措施
}catch(Exception){
    //当产生Exception异常时的处理措施
}finally{
    //无论是否捕获到异常都必须执行的代码
}

注意

  1. 当写了多个catch的时候,最多只能匹配其中的一个异常类型,并且只会执行该catch块的代码。
  2. catch中的异常类型,应该是从上到下,从子类到父类(先子类异常,在父类异常)。

throw:抛出异常,用于方法体内部,用来抛出一个异常,如果抛出了运行时异常,在方法名小括号后要声明方法可能抛出的异常类型。

throws:声明异常,用于方法声明部分,用来声明方法抛出的异常类型。

例如:

public void a() throws Exception{	//声明抛出的异常类型
    throw new Exception("抛出的异常对象")
}

注意:一旦在方法体抛出了异常,且声明了异常,在方法调用时一定要处理异常或者重新抛出。

日志记录

日志工具:log4j

日志的分类:

  1. SQL日志:记录系统执行的SQL语句。
  2. 异常日志:记录系统运行中发生的异常事件
  3. 业务日志:记录系统运行过程。

如何使用log4j:

  1. 下载log4j的jar文件。
  2. 百度搜索相应软件导入jar包的流程。
  3. 创建编写log4j.properties文件,该文件专门用来配置日志信息。
  4. 接下来就可以使用Logger类,注意导包的包名,要相匹配。

配置文件信息

配置文件个例:

### \u8BBE\u7F6ELogger\u8F93\u51FA\u7EA7\u522B\u548C\u8F93\u51FA\u76EE\u7684\u5730  ###
log4j.rootLogger=debug, stdout,logfile

### \u628A\u65E5\u5FD7\u4FE1\u606F\u8F93\u51FA\u5230\u63A7\u5236\u53F0  ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout

### \u628A\u65E5\u5FD7\u4FE1\u606F\u8F93\u51FA\u5230\u6587\u4EF6\uFF1Ajbit.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.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}%l %F %p %m%n

1.输出级别

log4j.rootLogger = debug,stdout,logfile

debug:指的是日志记录器的输出等级,主要的有:

  1. fatal:指出严重的错误事件将导致应用程序的退出
  2. error:指出虽然发生错误事件,但仍然不影响系统的继续运行
  3. warn:表明出现潜在错误的情形
  4. info:在粗粒度级别上指明消息,强调应用程序的运行过程
  5. debug:指出细粒度信息事件,对调试应用程序是非常有帮助的

优先级:

fatal > error > warn > info > debug

2. 输出目的地Appender

log4j.rootLogger = debug,stdout,logfile

stdout、logfile指的是日志输出目的地的名字

log4j允许记录日志到多个输出目的地,一个输出目的地被称为一个Appender,常用的Appender有以下两种:

  1. ConsoleAppender:输出日志事件到控制台。通过Target属性配置输出到System.out或System.err,默认的目标是System.out
  2. FileAppender:输出日志事件到一个文件。通过File属性配置文件的路径及名称

3.日志布局类型Layout

Appender必须使用一个与之相关联的布局类型Layout,用来指定它的输出样式,log4j中最常用的Layout有以下三种:

  1. HTMLLayout:格式化日志输出为HTML表格
  2. SimpleLayout:以一种非常简单的方式格式化日志输出。
  3. PatternLayout:根据指定的转换模式格式化日志输出,需要配置layout.ConversionPattern属性,若没有配置,则使用默认配置。

4.转换模式ConversionPattern

配置layout.ConversionPattern属性,常用配置参数及含义如下:

  1. %d:用来设置输出日志的日期和时间,默认格式为ISO8601,也可以在其后指定格式,比如%d{yyyy-MM-dd HH:mm:ss},输出格式类似于2020-03-23 22:12:22
  2. %m:用来输出代码中指定的消息
  3. %n:用来输出一个回车换行符
  4. %l:用来输出日志事件的发生未知,包括类名、发生的线程、以及在代码中的行数
  5. %p:用来输出优先级
  6. %F:用来输出文件名
  7. %M:用来输出方法名

集合框架

Java集合框架为我们提供了一套性能优良、使用方便的接口和类,它们都位于java.util包中。

集合框架是为了表现和操作集合而规定的一种统一的标准系结构。

集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法

Java集合框架简图:

Java异常和集合框架_第2张图片

  1. 接口:表示集合抽象数据类型,简图中以虚线框表示
  2. 实现:集合框架中接口的具体实现,简图中以实线框表示
  3. 算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算方法

在Java集合框架中的两大类接口:Collection和Map,Collection又有两个子接口: List和Set,所以通常说Java集合框架共有三大类接口: List ,Set和Map。它们的共同点:都是集合接口,都可以用来存储很多对象。它们的区别如下:

  1. Collection接口存储一组不唯一 ( 允许重复)、无序的对象。
  2. Set接口继承Collection接口,存储一组唯一(不允许重复)、无序的对象。
  3. List接口继承Collection接口,存储一组不唯一(允许重复)、有序(以元素插入的次序来放置元素,不会重新排列)的对象。
  4. Map接口存储一组成对的键-值对象, 提供key (键)到value (值)的映射。Map中的key不要求有序,不允许重复。value 同样不要求有序,但允许重复。
  5. Iterator接口是负责定义访问和遍历元素的接口。

List接口

实现List接口的常用类有ArrayList和LinkedList。

ArrayList 对数组进行了封装,实现了长度可变的数组。ArrayList 存储数据的方式和数组相都是在内存中分配连续的空间,它的优点在于遍历元素和随机访问元素的效率比较局。LinkedList采用链表存储方式,优点在于插入、删除元素时效率比较高。Vector操作类似ArrayList,但是Vector线程是安全的。

List接口中定义的各种常用方法(也是ArrayList的各种常用方法):

方法名称 说明
boolean add(Object o) 在列表末尾顺序添加元素,起始索引位置从0开始
void add(int index,Object o) 在指定的索引位置添加元素,原索引位置及其后面的元素依次后移注意:新添加元素的索引位置必须介于0和列表中元素个数之间
int size( ) 返回列表中的元素个数
Object get(int index) 返回指定索引位置处的元素,注意:取出的元素是Object类型,使用前需要进行强制类型转换
boolean contains(Object o) 判断列表中是否存在指定元素
Object remove(int index) 从列表中删除指定位置元素,起始索引位置从0开始

LinkedList的一些特殊方法:

方法名称 说明
void addFirst(Object o) 在列表的首部添加元素
void addLast(Object o) 在列表的末尾添加元素
Object getFirst( ) 返回列表中的第一个元素
Object getLast( ) 返回列表中的最后一个元素
Object removeFirst( ) 删除并返回列表中的第一个元素
Object removeLast( ) 删除并返回列表中的最后一 个元素

Map接口

Map接口存储一组成对的键值对象,提供key (键)到value (值)的映射,Map中的key不要求有序,不允许重复。value 同样不要求有序,但允许重复。使用这种方式存储数据的优点是查询指定元素效率高。

Map的实现类:

  1. HashMap
  2. HashTable
  3. ConcurrentMap
  4. TreeMap

Map的常用方法:

方法名称 说明
Object put(Object key, Object value) 以“键-值对”的方式进行存储,以“键-值对”的方式进行存储,以“键-值对”的方式进行存储
Object get (Object key) 根据键返回相关联的值,若不存在指定的键,则返回null
Object remove (Object key) 删除指定的键映射的“键值对”
int size( ) 返回元素个数
Set keySet( ) 返回键的集合
Collection values( ) 返回值的集合
boolean containsKey (Object key) 若存在指定的键映射的“键值对”,则返回true
boolean isEmpty( ) 若不存在键值映射关系,则返回true
void clear( ) 从此映射中移除所有映射关系

Hashtable和HashMap的区别:

  1. Hashtable继承自Dictionary 类,而HashMap实现了Map接口。
  2. Hashtable是线程安全的,HashMap 重速度、轻安全,是线程非安全的,所以当运行到多线程环境中时,需要程序员自己管理线程的同步问题。
  3. Hashtable不允许null值(key 和value都不允许),HashMap允许nl值(key 和value都允许)。

ConcurrentMap:操作类似HashMap,线程安全,实现安全的方式比hashtable更优良。

TreeMap:会自动对key进行排序,不能以null为key和value。

Set接口

类似List,无序(不按添加顺序排列),唯一不重复。

实现类:

  1. HashSet:不能通过下标取值,因为他是无序的。
  2. TreeSet:以树形结构图存储,自动排序,从小到大的排序。

迭代器Iterator

所有集合接口和类都没有提供相应的遍历方法,而是把遍历交给迭代器lerator 完成。Iterator为集合而生,专门实现集合的遍历。它隐藏了各种集合实现类的内部细节,提供了遍历集合的统一编程接口。

Cllection接口的teratr( )方法返回个leratar然后通过leratar 接口的两个方法即可方便地实现遍历。

  1. boleon hasNext().判断是否存在另一个可访问的元素。
  2. Object next( ):返回要访问的下一个元素。

如:

//1.创建多个狗狗对象
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);
    System.out.println(key + "\t" + dog.getStrain());
}

泛型集合

使用泛型集合在创建集合对象时指定集合中元素的类型,从集合中取出元素时无须进行类型强制转换,并且如果把非指定类型对象放入集合,会出现编译错误。

List泛型如:

//1.创建多个狗狗对象
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);
//dogs.add("hello");    //出现编译错误,元素类型不是Dog
/*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());
}

Map泛型如:

 //1.创建多个狗狗对象
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();
Iterator<String> it = keys.iterator();
while(it.hasNext()){
    String key = it.next();
    Dog dog = dogMap.get(key);
    System.out.println(key + "\t" + dog.getStrain());
}
//        for (String key:keys){
//            Dog dog = dogMap.get(key);
//            System.out.println(key + "\t" + dog.getStrain());
//        }

注意:泛型中使用基本数据类型,要使用包装类。

tor it = keys.iterator();
while(it.hasNext()){
String key = it.next();
Dog dog = dogMap.get(key);
System.out.println(key + “\t” + dog.getStrain());
}
// for (String key:keys){
// Dog dog = dogMap.get(key);
// System.out.println(key + “\t” + dog.getStrain());
// }


**注意**:泛型中使用基本数据类型,要使用包装类。

Java中共有八个包装类: Byte、Short. Integer. Long. Float、 Double、Boolean、 Character。

你可能感兴趣的:(Java异常和集合框架)