Java笔记(韩顺平Java基础12-14章)

第12章 异常-Exception

异常介绍

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

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

    1)Error(错误):java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError【栈溢出】和OOM(out of memory),Error是严重错误,程序会崩溃
    2)Exception:其它因编译错误或偶然的外在因素导致的一般性问题,可以使用针对的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception分为两大类:运行时异常[程序运行时,发生的异常]和编译时异常[编程时,编译器检查出的异常]。

  • 异常体系图
    在这里插入图片描述

  • 异常体系图的小结
    1.异常分为两大类,运行时异常和编译时异常
    2.运行时异常,编译器检查不出来。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常
    3.对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响
    4.编译时异常,是编译器要求必须处置的异常。

  • 常见的运行时异常
    1)NullPointerException空指针异常
    当应用程序试图在需要对象的地方使用null时,抛出该异常
    2)ArithmeticException数字运算异常
    当出现异常的运算条件时,抛出该异常(整数除以零)
    3)ArrayIndexOutOfBoundsException数组下标越界异常
    用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引
    4)ClassCastException类型转换异常
    当试图将对象强制转换为不是实例的子类时,抛出该异常。
    5)NumberFormatException数字格式不正确异常
    当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出异常=>使用异常我们可以确保输入是满足条件数字

编译异常

  • 介绍
    编译异常是指编译期间,就必须处理的异常,否则代码不能通过编译。

-常见的编译异常
√SQLException //操作数据库时,查询表可能发生异常
√IOException //操作文件时,发生的异常
√FileNotFoundException //当操作一个不存在的文件时,发生异常
√ClassNotFoundException //加载类,而该类不存在时,异常
√EOFException //操作文件,到文件末尾,发生异常
√IlleglArguementException //参数异常

异常处理

  • 基本介绍
    异常处理就是当异常发生时,对异常处理的方式

  • 异常处理的方式
    1)try- catch-finally
    程序员在代码中捕获发生的异常,自行处理
    2)throws
    将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM

  • 示意图
    在这里插入图片描述
    在这里插入图片描述

try-catch异常处理

  • try-catch方式处理异常说明

1)Java提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个try…catch块
2)基本语法

try{
   
	//可疑代码
	//将异常生成对应的异常对象,传递给catch块
}catch(异常){
   
	//对异常处理
}
//如果没有finally,语法是可以通过的
  • try- catch方式处理异常
    1)如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
    2)如果异常没有发生,则顺序执行try的代码块,不会进入到catch
    3)如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)
    则使用如下代码-finally{}
    4)可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointException在前),如果发生异常,只会匹配一个catch
    5)可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑
try{
   
//代码...
}
finally{
   	//总是执行
}
  • try- catch- finally执行顺序小结
    1)如果没有出现异常,则执行try块中所有语句,不执行catch块中语句,如果有finally里面的语句
    2)如果出现异常,则try块中异常发生后,try块剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally里面的语句!

  • try-catch异常处理案例
    要求:如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止

实现代码:

package com.hspedu.try_;

import java.util.Scanner;

public class TryCatchExercise04 {
   
    public static void main(String[] args) {
   

        //如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止
        //思路
        //1.创建Scanner对象
        //2.使用无限循环,去接收一个输入
        //3.然后将该输入的值,转成一个int
        //4.如果在转换时,抛出异常,说明输入的内容不是一个可以转成int的内容
        //5.如果没有抛出异常,则break 该循环
        Scanner scanner = new Scanner(System.in);
        int num = 0;
        String inputStr = "";
        while(true){
   
            System.out.println("请输入一个整数:");
            inputStr = scanner.next();
            try {
   
                num = Integer.parseInt(inputStr);   //这里是可能抛出异常
                break;
            } catch (NumberFormatException e) {
   
                System.out.println("你输入的不是一个整数:");
            }
        }

        System.out.println("你输入的值是=" + num);
    }
}

throws异常处理

  • 基本介绍
    1)如果一个方法(中语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
    2)在方法声明中用throws语句可以声明抛出异常的列表(即多个异常),throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

  • 注意事项和使用细节
    1)对于编译异常,程序中必须处理,比如try-catch或者throws
    2)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
    3)子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
    4)在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws

自定义异常

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

  • 自定义异常的步骤
    1)定义类:自定义异常类名(程序员自己写)继承Exception或RuntimeException
    2)如果继承Exception,属于编译异常
    3)如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)

补充:
1.一般情况下,我们自定义异常是继承RuntimeException
2.即把自定义异常做成运行时异常,好处是,我们可以使用默认的处理机制

throw 和 throws 的区别

  • 一览表
    在这里插入图片描述

第13章 常用类

包装类(Wrapper)

1)针对八种基本数据类型相应的引用类型–包装类
2)有了类的特点,就可以调用类中的方法
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 包装类和基本数据的转换
    1)jdk5前的手动装箱和拆箱方式,装箱:基本类型->包装类型,反之,拆箱
    2)jdk5以后(含jdk5)的自动装箱和拆箱方式
    3)自动装箱底层调用的是valueOf方法,比如Integer.valueOf()
    4)其他包装类的用法类似,不一一举例
public class Integer01 {
   
    public static void main(String[] args) {
   
        //演示int <--> Integer 的装箱和拆箱
        //jdk5前是手动装箱和拆箱
        //手动装箱
        int n1 = 100;
        Integer integer = new Integer(n1);
        Integer integer1 = Integer.valueOf(n1);

        //手动拆箱
        //Integer -> int
        int i = integer.intValue();

        //jdk5后,就可以自动装箱和自动拆箱
        int n2 = 200;
        //自动装箱 int -> Integer
        Integer integer2 = n2;     //底层使用的是 Integer.valueOf(n2)
        //自动拆箱 Integer -> int
        int n3 = integer2;  //底层仍然使用的是 intValue()方法
    }
}

包装类类型和String类型的相互转换

public class WrapperVSString {
   
    public static void main(String[] args) {
   
        //包装类(Integer) -> String
        Integer i = 100;
        //方式1
        String str1 = i + "";
        //方式2
        String str2 = i.toString();
        //方式3
        String str3 = String.valueOf(i);

        //String -> 包装类(Integer)
        String str4 = "12345";
        Integer i2 = Integer.parseInt(str4);      //使用到自动装箱
        Integer i3 = new Integer(str4);     //构造器

        System.out.println("ok~~");
    }
}

Integer类和Character类的常用方法

public class WrapperMethod {
   
    public static void main(String[] args) {
   
        System.out.println(Integer.MIN_VALUE); //返回最小值
        System.out.println(Integer.MAX_VALUE);//返回最大值

        System.out.println(Character.isDigit('a'));//判断是不是数字
        System.out.println(Character.isLetter('a'));//判断是不是字母
        System.out.println(Character.isUpperCase('a'));//判断是不是大写
        System.out.println(Character.isLowerCase('a'));//判断是不是小写

        System.out.println(Character.isWhitespace('a'));//判断是不是空格
        System.out.println(Character.toUpperCase('a'));//转成大写
        System.out.println(Character.toLowerCase('A'));//转成小写
    }
}

Integer类面试题

题中System.out.println输出了什么
1.

public class WrapperExercise02 {
   
    public static void main(String[] args) {
   
        Integer i = new Integer(1);
        Integer j = new Integer(1);
        System.out.println(i == j);  //False
        //所以,这里主要是看范围 -128 ~ 127 就是直接返回
        /*
        //1. 如果i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回
        //2. 如果不在 -128~127,就直接 new Integer(i)
        //源码:
         public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
         */
        Integer m = 1; //底层 Integer.valueOf(1); -> 阅读源码
        Integer n = 1;//底层 Integer.valueOf(1);
        System.out.println(m == n); //T
        //所以,这里主要是看范围 -128 ~ 127 就是直接返回
        //,否则,就new Integer(xx);
        Integer x = 128;//底层Integer.valueOf(1);
        Integer y = 128;//底层Integer.valueOf(1);
        System.out.println(x == y);//False
    }
}
public class WrapperExercise03 {
   
        public static void main(String[] args) {
   
            //示例一
            Integer i1 = new Integer(127);
            Integer i2 = new Integer(127);
            System.out.println(i1 == i2);//F
            //示例二
            Integer i3 = new Integer(128);
            Integer i4 = new Integer(128);
            System.out.println(i3 == i4);//F

            //示例三
            Integer i5 = 127;//底层Integer.valueOf(127)
            Integer i6 = 127;//-128~127
            System.out.println(i5 == i6); //T
            //示例四
            Integer i7 = 128;
            Integer i8 = 128;
            System.out.println(i7 == i8);//F
            //示例五
            Integer i9 = 127; //Integer.valueOf(127)
            Integer i10 = new Integer(127);
            System.out.println(i9 == i10);//F

            //示例六
            Integer i11=127;
            int i12=127;
            //只有有基本数据类型,判断的是
            //值是否相同
            System.out.println(i11==i12); //T
            //示例七
            Integer i13=128;
            int i14=128;
            System.out.println(i13==i14);//T


        }
}

String类

  • String类的理解和创建对象
  1. String对象用于保存字符串,也就是一组字符序列
  2. 字符串常量对象是用双引号括起的字符序列。例如:“你好”、“12.97”、"boy"等
  3. 字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节。
  4. 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)
    在这里插入图片描述
  5. String 类实现了接口 Serializable【String 可以串行化:可以在网络传输】,接口 Comparable [String 对象可以比较大小]
  6. String 是 final类 ,不能被其他的类继承
  7. String 有属性 private final char value[];用于存放字符串内容
  8. 一定要注意: value 是一个final类型, 不可以修改(需要理解):即value不能指向新的地址,但是单个字符内容是可以变化
  • 创建String对象的两种方式
    1)方式一:直接赋值 String s = “hspedu”;
    2)方式二:调用构造器String s = new String(“hspedu”);

  • 两种创建String对象的区别
    1.方式一:先从常量池查看是否有"hsp"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址
    2.方式二:现在堆中创建空间,里面维护了value属性,指向常量池的hsp空间。如果常量池没有"hsp",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
    3.两种方式的内存分布图
    在这里插入图片描述
    实例1:

public class StringExercise01 {
   
    public static void main(String[] args) {
   
        String a = "abc";
        String b = "abc";
        System.out.println(a.equals(b));    //T
        System.out.println(a == b);     //T
    }
}

在这里插入图片描述
实例2:

public class StringExercise03 {
   
    public static void main(String[] args) {
   
        String a = "hsp"; //a 指向 常量池的 “hsp”
        String b =new String("hsp");//b 指向堆中对象
        System.out.println(a.equals(b)); //T
        System.out.println(a==b); //F
        //b.intern() 方法返回常量池地址
        System.out.println(a==b.intern()); //T //intern方法自己先查看API
        System.out.println(b==b.intern()); //F
    }
}

在这里插入图片描述

  • 知识点:
    当调用intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此对象的引用
    解读:b.intern()方法最终返回的是常量池的地址(对象)

实例3:

public class StringExercise05 {
   
    public static void main(String[] args) {
   
        Person p1 = new Person();
        p1.name = "hspedu";
        Person p2 = new Person();
        p2.name = "hspedu";


        System.out.println(p1.name.equals(p2.name));//比较内容: True
        System.out.println(p1.name == p2.name);  //T
        System.out.println(p1.name == "hspedu");   //T

        String s1 = new String("bcde");
        String s2 = new String("bcde");
        System.out.println(s1==s2); //False

    }
}
class Person {
   
    public String name;
}

在这里插入图片描述

字符串的特性

1)String是一个final类,代表不可变的字符序列
2)字符串是不可变的。一个字符串对象一旦分配,其内容是不可变的。

  • 面试题
    1)题1
    在这里插入图片描述图解:
    在这里插入图片描述
    2)题二
    在这里插入图片描述
    3)题三
    在这里插入图片描述在这里插入图片描述
  1. 题四

在这里插入图片描述
示意图
在这里插入图片描述代码:

public class StringExercise10 {
   
}

class Test1 {
   
    String str = new String("hsp");
    final char[] ch = {
   'j', 'a', 'v', 'a'};

    public void change(String str, char ch[]) {
   
        str = "java";
        ch[0] = 'h';
    }

    public static void main(String[] args) {
   
        Test1 ex = new Test1();
        ex.change(ex.str, ex.ch);
        System.out.print(ex.str + " and ");
        System.out.println(ex.ch);
    }
}

运行结果:

在这里插入图片描述

String类的常见方法

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

  • String类的常见方法一览

  1. equals //区分大小写,判断内容是否相等
  2. equalsIgnoreCase //忽略大小写的判断内容是否相等
  3. length //获取字符的个数,字符串的长度
  4. indexOf //获取字符在字符串中第一次出现的索引,索引从0开始,如果找不到,返回-1
  5. lastIndexOf //获取字符在字符串最后1次出现的索引,索引从0开始,如找不到,返回-1
  6. substring //截取指定范围的子串
  7. trim //去前后空格
  8. charAt //获取某索引处的字符,注意不能使用Str[index]这种方式
    String str = “hello”;
    //str[0]不对
    //str.charAt(0) => h

案例演示String另一组相关的方法:

public class StringMethod02 {
   
    public static void main(String[] args) {
   
        // 1.toUpperCase转换成大写
        String s = "heLLo";
        System.out.println(s.toUpperCase());    //HELLO
        // 2.toLowerCase
        System.out.println(s.toLowerCase());    //hello
        // 3.concat拼接字符串
        String s1 = "宝玉";
        s1 = s1.concat("林黛玉").concat("薛宝钗").concat("together");
        System.out.println(s1);     //宝玉林黛玉薛宝钗together
        // 4.replace 替换字符串中的字符
        s1 = "宝玉 and 林黛玉 林黛玉 林黛玉";
        //在s1中,将所有的 林黛玉 替换成薛宝钗
        //  s1.replace()方法执行后,返回的结果才是替换过的.
        // 注意对 s1没有任何影响
        String s11 = s1.replace("林黛玉", "薛宝钗");
        System.out.println(s1);     //宝玉 and 林黛玉 林黛玉 林黛玉
        System.out.println(s11);    //宝玉 and 薛宝钗 薛宝钗 薛宝钗
        // 5.split 分割字符串,对于某些分割字符,我们需要转义比如| \\等
        String poem = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";
        //1. 以 ,为标准对poem进行分割 , 返回一个数组
        //2. 在对字符串进行分割时, 如果有特殊字符,需要加入 转义符 \
        String[] split = poem.split(",");
        poem = "E:\\aaa\\bbb";
        split = poem.split("\\\\");
        System.out.println("===分割后内容===");
        for(int i = 0; i < split.length; i++){
   
            System.out.println(split[i]);
        }
        // 6.toCharArray 转换成字符数组
        s = "happy";
        char[] chs = s.toCharArray();
        for(int i = 0; i < chs.length; i++){
   
            System.out.println(chs[i]);
        }
        // 7.compareTo 比较两个字符串的大小,如果前者大,
        // 则返回正数,后者大,则返回负数, 如果相等, 返回0
        // (1) 如果长度相同,并且每个字符也相同,就返回0
        // (2) 如果长度相同或者不相同,但是在进行比较时,可以区分大小
        //     就返回  if (c1 != c2) {
   
        //                return c1 - c2;
        //            }
        // (3) 如果前面的部分都相同,就返回 str1.len - str2.len
        String a = "jcck";
        String b = "jack";
        System.out.println(a.compareTo(b));     //返回值是 'c' - 'a' = 2的值
        //8.format格式字符串
        /* 占位符有:
         * %s字符串 %c 字符 %d 整型 %.2f 浮点型
         *
         */
        String name = "john";
        int age = 10;
        double score = 56.857;
        char gender = '男';
        //将所有的信息都拼接在一个字符串。
        String info =
                "我的姓名是" + name + "年龄是" + age + ",成绩是" + score + "性别是" + gender + ".希望大家喜欢我!";
        System.out.println(info);

        //1. %s , %d, %.2f, %c 称为占位符
        //2. 这些占位符由后面变量来替换
        //3. %s 表示后面 字符串来替换
        //4. %d 是正数来替换
        //5. %.2f 表示使用小数来替换, 替换后, 只会保留小数点两位, 并且进行四舍五入的处理
        //6. %c 使用char类型来替换
        String formatStr = "我的名字是%s年龄是%d,成绩是%.2f性别是%c.希望大家喜欢我!";

        String info2 = String.format(formatStr, name, age, score, gender);

        System.out.println("info2=" + info2);

    }
}

输出:
在这里插入图片描述

StringBuffer类

  • 基本介绍
    java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。
    很多方法与String相同,但StringBuffrt是可变长度的。
    StringBuffer是一个容器。
    在这里插入图片描述
  1. StringBuffer 的直接父类 是 AbstractStringBuilder
  2. StringBuffer 实现了 Serializable, 即StringBuffer的对象可以串行化
  3. 在父类中 AbstractStringBuilder 有属性 char[] value, 不是final
    该value 数组存放 字符串内容 , 引出存放在堆中的
  4. StringBuffer 是一个final类,不能被继承
  5. 因为StringBuffer字符内容是存放在 char[] value, 所有在变化(增加/删除)不用每次都更换地址(既不是每次创建新对象),所以效率高于String
  • String VS StringBuffer
    1)String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低(private final char value[];
    2)StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高(char[] value;//这个放在堆)

  • StringBuffer的构造器
    在这里插入图片描述√构造器的使用

public class StringBuffer02 {
   
    public static void main(String[] args) {
   

        //构造器的使用
        //1.创建一个大小为16的char[] ,用于存放字符内容
        StringBuffer stringBuffer = new StringBuffer();

        //2.通过构造器指定 char[] 大小
        StringBuffer stringBuffer1 = new StringBuffer(100);

        //3.通过给一个String创建StringBuffer, char[] 大小就是 str.length() + 16
        StringBuffer hello = new StringBuffer("hello");
    }
}

String和StringBuffer相互转换

public class StringAndStringBuffer {
   
    public static void main(String[] args) {
   

        //看 String-->StringBuffer
        String str = "hello tom";
        //方式1 使用构造器
        //注意: 返回的才是StringBuffer对象.对str本身没有影响
        StringBuffer stringBuffer = new StringBuffer(str);
        //方式2 使用的是append方法
        StringBuffer stringBuffer1 = 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值