java语言学习(7)

第十一章

异常(Exception)

  • 异常的概念

  • 异常体系图!!!

  • 常见的异常

  • 异常处理!!!

  • 自定义异常

  • throw和throws的对比

将该代码块选中

快捷键ctrl + alt + t

然后选择try-catch

异常

异常介绍

基本概念:Java语言中,将程序执行中发生的不正常情况称为异常(开发过程中的语法错误和逻辑错误不是异常)

执行过程中所发生的异常可分为两类

  • Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误,资源耗尽等严重情况

  • Exception:其他因变成错误而偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。比如:空指针的访问,试图读取不存在的文件,网络连接中断等。

    • 运行时异常(有默认的处理机制)

    • 编译时异常

异常体系图

体现了继承和实现关系
在这里插入图片描述

  • 运行时异常

    • 编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常

    • java.lang.RuntimeException类及它的子类都是运行时异常

    • 对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响

  • 编译时异常

    • 要求必须处置的异常

常见运行时异常

  • NullPointerException空指针异常

  • ArithmeticException实现运算异常

  • ArrayIndexOutOfBoundsException数组下届标越界异常

  • ClassCastException类型转换异常

  • NumberFormatException数字格式不正确异常

常见的编译异常

  • SQLException//操作数据库时,查询表可能发生异常

  • IOException//操作文件时发生异常

  • FileNotFoundException//当操作一个不存在的文件时发生异常

  • ClassNotFoundException//加载类找不到时的异常

  • EOFException//操作文件,到文件的末尾发生异常

  • IllegalArguementException//参数异常

异常处理

  • try -catch - finally

    • 程序员在代码中捕获发生的异常,自行处理
    //程序如下
    
    try{
        代码可能有异常
    }catch(Exception e){
        //捕获异常
        //系统将异常封装成Exception对象e,传递给catch
        //得到异常对象后,程序员自己处理
        //注意:如果没有发生异常catch代码块不执行
    }finally{
        //不管try代码块是否有异常发生,最终都要执行finally
        //通常将释放资源的代码,放在finally
    }
    
    //注:没有finally,语法是允许
  • throws

    • 将发生的异常抛出,交给调用这来处理,最顶级的处理者就是JVM

    • JVM处理异常

      • 输出异常

      • 退出程序

在这里插入图片描述

注意事项

  • try - catch

    • 如果异常发生了,则异常发生后面的代码不会执行,直接进入catch块

    • 如果异常没有发生发生,则顺序执行try的代码块,不会进入catch

    • 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等),则使用finally()

    • 可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前。(比如:Exception在后,NullPointerException在前)如果发生异常,只会匹配一个catch

    • 允许使用try - finally 配合使用。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑

    //try - catch 的使用实例
    public class data01 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int a;
            while(true){
                try {
                    System.out.println("请输入一个数字");
                    a = Integer.parseInt(scanner.nextLine());
                    System.out.println("输入成功");
                    break;
                } catch (NumberFormatException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }

异常处理

  • throws

    • 如果一个方法中的语句执行时可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应现实的声明抛出异常,表明该方法将不对这些异常处理,而由该方法的调用着负责处理

    • 在方法声明中throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类

    public class data01 {
        public static void main(String[] args) {
    
        }
    
        public void f2() throws Exception{
            //throws 抛出异常 放调用f2的调用者 处理
            //throws 后面的异常类型可以是方法中参数的异常类型,也可以是它的父类
            //throws 关键字后可以是 异常列表,即可以抛出多个异常
            FileInputStream fis = new FileInputStream("d://aa.txt");
    
        }
    }

细节

  • 对于编译异常,程序必须处理

  • 运行异常,程序中如果没有处理,默认就是throws的方式处理

  • 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型与父类抛出的异常一致,或是父类抛出异常的类型的子类型

  • 在throws过程中,如果由方法try-catch,就相当于处理异常,就不必throws

在这里插入图片描述

自定义异常

概念:当程序出现某些“错误”,但该错误没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该类错误信息

步骤

  • 自定义异常类名(程序员自己写)继承Exception或RuntimeException

  • 如果继承Exception,属于编译异常

  • 如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)

    //写一个自定义异常
    //一般情况下,我们自定义是继承RuntimeExcception
    //即把自定义异常做成运行异常,好处是我们可以使用默认处理机制
    public class data01 {
        public static void main(String[] args) {
            int age = 10;
            if(!(age >= 18 && age <= 125)){
                throw new AgeException("年龄范围错误");
            }
        }
    }
    
    class AgeException extends RuntimeException {
        public AgeException(String message) {
            super(message);
        }
    }

throw和throws的区别

在这里插入图片描述

常用类

  • String

  • StringBuffer

  • StringBuilder

  • Math

  • Data,Calendar,LocalDate

  • System

  • Arrays

  • BigInteger BigDecimal

String,StringBuffer,StringBuilder

包装类(wrapper)

  1. 针对八种基本数据类型相应的引用类型–包装类

  2. 有了类的特点,就可以调用类中的方法

在这里插入图片描述

接口的实现和关系的继承

在这里插入图片描述

在这里插入图片描述

包装类和基本数据的转换

* jdk5前是手动装箱和拆箱的方式
  
  * 装箱:基本类型->包装类型

    //手动装箱
    int n1 = 10;
    Integer a1 = new Integer(n1);
    Integer a2 = Interger.valueOf(n1);
    
    
    //手动拆箱
    int i = a1.intValue();
    
    
    //jdk5之后就可以自动装箱和自动拆箱了
    //底层还是调用手动装箱
    int n2 = 200;
    Integer a3 = n2;
    //自动拆箱
    
    int n3 = a3;
  • jdk5以后是自动装箱和拆箱

  • 自动装箱底层调用的是valueOf方法,比如Integer.valueOf()

包装类型和String相互转换

    Integer i = 100;
    //方式1
    String str1 = i + "";
    //方式2
    String str2 = i.toString();
    //方式3
    String str2 = String.valueof(i);
    
    
    
    //打String转换成包装类
    String str4 = "12345";
    Interger i2 = Interger.parseInt(str4);
    Interger i3 = new Integer(str4);//用构造器

常用的一些方法

在这里插入图片描述

String类

  • 理解:String对象用于保存字符串,也就是一组字符序列

  • 字符串常量对象是用双引号括起来的字符序列

  • 字符串的字符使用Unicode字符编码,一个字符占两个字节

  • String类常用构造器

    String s1 = new String();
    String s2 = new String(String original);
    String s3 = new String(char[]a);
    String s4 = new String(char[]a,int startIndex,int count);

  • String实现了接口 Serializable(String 可以串行化:可以网络传输)

  • String实现了接口Comparable(说明String对象可以比较大小)

  • String 是final类,它不能被其他的类继承

  • String 有属性 private final char value[];用于存放字符串内容

  • 注意:value是一个final类型,不可以修改(它指向的地址不可修改,但是单个字符内容是可以变化的)

  • 补充:final修饰数组时的知识

    public class data01{
        public static void main(String[] args) {
            final char[] m = {'a','b'};
            for(char arr:m){
                System.out.println(arr);
            }
            m[0] = 'l';
            for(char arr:m){
                System.out.println(arr);
            }
            //这里的final 是指不能改变数组指向的空间
            //但是数组内部的元素可以修改
        }
    }

String的创建

  • 直接赋值

    • 先从常量池查看是否有赋值对象的数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址
  • 调用构造器

    • 先在堆中创建空间,里面维护了value属性,指向常量池的赋值对象空间。如果常量池没有该对象,重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址

在这里插入图片描述

补充:intern方法(如果池中已经包含一个等于此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则将此String对象添加到池中,并返回此String对象的引用)

b.intern()方法最终返回的是常量池的地址

字符串特性

String a = "hello";
String b = "abe";
String c = a + b;


//问:上面这段代码创建了几个对象
//答:3个

String的常用方法

说明:String类是保存字符串常量的。每次更新都需要重新开辟空间,效率低,因此java设计者还提供了StringBuilder和 StringBuffer 来争强String的功能,并提高效率

  • equals

    • 区分大小写,判断内容是否相等
  • equalslgnoreCase

    • 忽略大小写的判断内容是否相等
  • length

    • 获取字符的个数,字符串的长度
  • indxOf

    • 或许字符在字符串中第一次出现的索引,索引从0开始,如果找不到,返回-1
  • lastIndeOf

    • 最后出现的位置,获取字符在字符串中最后异常出现的索引
  • substring

    • 截取指定范围的字串
  • trim

    • 去前后空格
  • charAt

    • 获取某索引处的字符,注意不能使用Str[index] 这种方式
  • toUpperCase

  • toLowerCase

  • concat

    • 拼接字符串
  • replace

    • 替换字符串中的字符
  • split

    • 分割字符串,对于某些分割字符

    • 比如以逗号为标准,进行分割,返回数组

    • 注意转义字符

  • compareTo

    • 比较两个字符串的大小

    • 两个字符串的长度不等时,会返回长度差

    • 相等时,返回Ascii码值的差值

  • toCharArray

    • 转换成字符数组
  • format

    • 格式字符串,%s字符串 %c字符%d整%f浮点型

StringBuffer类

介绍:该类代表可变的字符序列,可以对字符串内容进行增删,很多方法与String相同,但StringBuffer是可变长度的,StringBuffer是一个容器

它的父类AbstractStringBuilder 有属性 char[] value, 不是final ,该value 数组存放字符串的空间是堆空间,StringBuffer 是一个final类,不能被继承

  • String 和 StringBuffer 的对比

    • String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率低//private final char value[];

    • StringBuffer 保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用更新地址,效率高 // char[] value; 放在堆

StringBuffer的构造器

  • StringBuffer()

    • 构造一个其中不带字符的字符串缓冲区,其初始容量为16分字符
  • StringBuffer(int capacity)

    • 构造一个不带字符,但具有指定初始容量的字符串缓冲区,即堆char[] 带下进行指定
  • StringBuffer(String string)

    • 构造一个字符串缓冲区。并将其尼尔初始化为指定的字符串内容

    • 大小为:字符串的大小加16

StringBuffer和String之间的相互转换

    public class data01{
        public static void main(String[] args) {
            //感受String 和 StringBuffer 之间的转换
            String a = "Dog";
            //方式一,直接传参
            StringBuffer stringBuffer = new StringBuffer(a);
            //方式二,使用append方法
            StringBuffer stringBuffer1 = new StringBuffer();
            stringBuffer1.append(a);
            System.out.println(stringBuffer);
            System.out.println(stringBuffer1);
    
            StringBuffer b = new StringBuffer("good");
            //方式一:直接传参
            String b1 = new String(b);
            //方式二:使用toString方法
            String b2 = b.toString();
            System.out.println(b1);
            System.out.println(b2);
        }
    }

StringBuffer的常用方法

  • append

  • delet(start,end)

  • replace(start,end,string)

    • 将start ----end 间的内容替换掉,不含end
  • indexOf

    • c查找子串在字符串第1次出现的索引,如果找不到就返回-1
  • inser(start,string)

    • 在索引位置插入string,原来为start的内容自动后移
  • length

StringBuilder类

基本介绍:一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步(StringBuilder不是线程安全)。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数现实中,它比StringBuffer要快

在StringBuilder 上的主要操作是append和insert方法,可重载这些方法,以接受任意类型的数据

  • StringBuilder 继承 AbstractStringBuilder 类

  • 实现了Serializable ,说明StringBuilder对象是可以串行化(对象可以网络传输,可以保存到文件)

  • StringBuilder是final类,不能被继承

  • StringBuilder 对象字符序列仍然存放在其父类AbstractStingBuilder 的 char[] value; 因此,字符序列在堆中

  • StringBuilder的方法 ,没有做互斥的处理,即没有synchronized 关键字,因此在单线程的情况下使用StringBuilder

比较String,StringBuffer,StringBuilder

  • String:不可变字符序列,效率低,但复用率高

  • StringBufffer:可变字符序列,效率较高(增删),线程安全

  • StringBuilder:可变字符序列,效率最高,线程不安全

使用原则

  • 如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder

  • 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder

  • 如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer

  • 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息

Math类

  • abs

    • 绝对值
  • pow

    • 求幂
  • ceil

    • 向上取整
  • floor

    • 向下取整
  • round

    • 四舍五入
  • sqrt

    • 求开方
  • random

    • 求随机数
  • max

    • 求两个数的最大值
  • min

    • 求两个数的最小值

Arrays类

  • toString

    • Arrats.toString(arr)

    • 返回数组的字符串形式

  • sort

    • 自然排序sort(arr)

    • 定制排序 传入两个参数

      • 排序数组

      • 实现Comparator接口的匿名内部类,要求实现 compare方法

    //自定义实现sort
    public class data01 {
        public static void main(String[] args) {
            Book[] book = new Book[5];
            book[0] = new Book(23,"好人");
            book[1] = new Book(39.9,"猪猪");
            book[2] = new Book(15.3,"狗子");
            book[3] = new Book(99.9,"one");
            book[4] = new Book(74.2,"数学");
            Arrays.sort(book,new Comparator<Book>() {
                @Override
                public int compare(Book o1, Book o2) {
                    double tmp = o1.getPrice()-o2.getPrice();
                    if(tmp>0) return 1;
                    if(tmp<0) return -1;
                    return 0;
                }
            });
            for(Book m: book) {
                m.f();
            }
    
        }
    }
    
    class Book{
        public Book(double price, String name) {
            this.price = price;
            this.name = name;
        }
    
        double price;
        String name;
    
        public void f(){
            System.out.println(price);
        }
    
        public double getPrice() {
            return price;
        }
    }
  • binarySearch

    • 通过二分搜索法镜像查找,要求必须排好

    • int index = Arrays.binarySeach(arr,3);

    • 如果数组中不存在该元素,就返回 -(low +1)

    • 注:low是因该存在的地方

  • copyOf

    • 数组元素的复制

    • Integer[] num = Arrays.copyOf(arr,arr.length);

    • 如果拷贝的length大于原数组的长度,就会增加null

    • 如果小于,就会抛出异常

  • fill

    • 数组元素的填充

    • 使用第二个参数,来替换原数组的所有元素

  • equals

    • 比较两个数组元素的内容是否完全一致

    • 如果完全一样,就返回真

  • asList

    • 将数组转换成List

System

  • exit

    • 退出当前程序

    • exit(0)

    • 这里的0代表状态,0----代表正常状态

  • arraycopy:

    • 复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组
    int[] src = {1,2,3};
    int dest = new int[3];
    System.arraycopy(src,0,dest,0,3);
    //五个参数的意义
    //第一个参数    原数组
    //第二个参数    原数组的那一索引开始拷贝
    //第三个参数    目标数组
    //第四个参数    拷贝到目标数组的哪一个位置
    //第五个参数    拷贝多少个数据
  • currentTimeMillens

    • 返回当前的时间距离 1970 -1-1的毫秒数
  • gc

    • 运行垃圾回收机制

BigInteger 和 BigDecimal

应用场景:

BigInteger:适合保存比较大的整型

BigDecimal:适合保存精度更高的浮点数

BigInteger:存较大的数据适合,用双引号引起来

注:进行加减乘除的时候,需要使用相应的方法,不能直接进行 + - * /

  • add

  • subtract

  • multiply

  • divide

注:使用BigDecimal时,使用除法可能会出现异常(除不尽)

解决方案:在调用divide 的时,指定精度

BigDecimal.divide(bigDecimal2,BigDecimal.ROUND_CEILING)

Data,Calendar,LocalData

  • 第一代日期Data

    • 精确到毫秒,代表特定的瞬间

    • SimpleDataFormat:格式和解析日期的类

    • SimpleDateFormat:格式化和解析日期的根据类,它允许进行格式化(日期->文本),解析(文本->日期)和规范

  • 第一代

  • 第一种

    • Data d1 = new Date();

    • 获取当前的时间,默认输出的是国外的格式,通常需要对时间进行一个转换

    • SimpleDateFormat sdf = new SimpledateFormat("yyyy年MM月dd日 hh:mm:ss E“)

    • 这里的格式使用的字母是规定好的

    在这里插入图片描述

    • String format = sdf.format(d1);
  • 第二种

    • Data d2 = new Data(long);
  • 第三种

    • 可以把一个格式化的String转成对于的Date

    • 输出时,默认是国外的格式

    • 在转化格式时,使用的格式需要和String的格式一样,否则会抛出转换异常

      String s = “1997年01月01日 10:20:30 星期一”;
      Date parse = sdf.parse(s);
      System.out.println(“parse=” + parse);

Canlender(第二代)

Calendar类是一个抽象类,他为特定瞬间与一组诸如 年月日时 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法

  • Calendar是一个抽象类,并且构造器是private

  • 可以通过getInstance()来获取实例

  • 提供大量的方法和字段提供程序员

  • Calendar没有提供对于的格式化的类,因此需要程序员自己组合来输出

  • 需要24小时进制来获取时间,将Calendar.HOUR----> Calendar.HOUR_OF_DAY

    Calendar c = Calendar.getInstance();
    //创建日历信息
    //注:每一个时间信息需要我们自己组合
    
    System.out.println("月" + c.get(Calendar.YEAR);
    //so on

前两代日期类的不足分析

JDK 1.0 中包含一个java.util.Data类,但是它的大多数方法已经在JDK 1.1 引入 Calendar 类之后被弃用了。而Calendar也存在问题是:

  • 可变性:向日期和时间这样的类应该是不可变的

  • 偏移性:Date中的年份是从1900开始的,而月份都是从0开始

  • 格式化:格式化只对Date有用,Calendar 则不行

  • 此外,他们线程不安全

  • 不能处理润秒(每隔两天,多出1s)

第三类(日期类)

  • LocalDate(年月日)

  • LocalTime(时分秒)

  • LocalDateTime(年月日时分秒)

第三类是在JDK8加入的

格式化
在这里插入图片描述

Instant(时间戳)

在这里插入图片描述

写在后面的话

看到很多小伙伴,在leetcode里坚持刷了一个学期的题目,羡慕之情。羡慕他们真的能坚持做成一件事情,羡慕他们学到了一些具体的东西。我呢!?这一章学的很模糊,前面的异常处理大概是听懂了,但我不知道这东西能在代码中如何使用。后面的8大类的一些方法,感觉就是一些死记硬背的东西,多用就熟练后,自然能记得。

哎!谈不上迷茫,东西要学的还很多。只是快到年底了,蓦然回首,微微有些感概罢了!!!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值