2021-07-28笔记

3.枚举

3.1枚举的基本定义和使用

3.1.1枚举的定义

定义枚举类型, 需要使用到关键字 enum 。 枚举的名字是一个标识符, 遵循大驼峰命名 法。

//解释枚举原理
public class Demo1{
    public static void main(String[] args){
        Dog dog=Dog.female;
    }
}
class Dog{
    final static Dog male = new Dog();
    final static Dog female = new Dog();
}
enum Gender{
    male,femalex
}

3.1.2枚举的使用

枚举是一种自定义的数据类型,可以声明变量。在使用的时候,直接使用枚举类型.枚举值这样的形式进行枚举值的获取。

3.2枚举中的成员定义

3.2.1枚举的分析

枚举,其实可以认为是Object类的一个最终子类。 不能被其他的类、枚举继承。

3.2.2枚举中的属性定义

public enum Gender {
Male, Female;
// 1. 在枚举中定义属性、方法、构造方法... 是需要写在枚举元素的下方!
// 如果需要在枚举中定义成员,需要在最后一个枚举元素后面添加一个分号。
public String desc;
}

3.2.3枚举中的构造方法定义

public class Test2 {
// 为了防止和当前包中的Gender枚举重复,在这里写成了静态内部枚举
private static enum Gender {
// 其实,所谓枚举中的元素,其实就是一个静态的、当前类的对象。
Male("男"), Female("女");
// 添加属性
private String desc;
// 添加构造方法,为这个属性赋值
// 在枚举中定义构造方法,一般情况下,只是在当前的枚举中使用
// 所以,枚举的构造方法,一般情况下,权限都是私有的
    Gender(String desc) {
        this.desc = desc;
        }
    }
    public static void main(String[] args) {
    // 1. 枚举对象的获取
        Gender gender = Gender.Male;
    }
}

3.2.4枚举中的方法定义

public enum Gender {
Male, Female;
// 1. 在枚举中定义属性、方法、构造方法... 是需要写在枚举元素的下方!
// 如果需要在枚举中定义成员,需要在最后一个枚举元素后面添加一个分号。
public String desc;
// 2. 定义方法
    public void show() {
        System.out.println("枚举中的方法定义");
    }
    public static void display() {
        System.out.println("枚举中的静态方法的定义");
    }
}

3.2.5枚举中的方法重写

private static enum Gender {
// 其实,所谓枚举中的元素,其实就是一个静态的、当前类的对象。
Male("男"), Female("女");
// 添加属性
private String desc;
// 添加构造方法,为这个属性赋值
// 在枚举中定义构造方法,一般情况下,只是在当前的枚举中使用
// 所以,枚举的构造方法,一般情况下,权限都是私有的
    Gender(String desc) {
        this.desc = desc;
    }
    
    @Override
    public String toString() {
        return this.desc;
    }
}
​

3.2.6枚举实现接口

enum Gender implements MyInterface {
    @Override
    public void test() {
        System.out.println("接口中的方法");
    }
}
​
interface MyInterface {
    void test();
}
​

3.2.7枚举值

enum Gender implements MyInterface {
    // 其实,所谓枚举中的元素,其实就是一个静态的、当前类的对象。
    Male("男") {
        // 这里,其实就相当于是一个匿名内部类
        // 在这里,可以重写Gender中的方法
        @Override
        public void test() {
            System.out.println("Male的重写实现");
        }
    },Female("女");
    // 添加属性
    private String desc;
    // 添加构造方法,为这个属性赋值
    // 在枚举中定义构造方法,一般情况下,只是在当前的枚举中使用
    // 所以,枚举的构造方法,一般情况下,权限都是私有的
    Gender(String desc) {
        this.desc = desc;
    }
    
    @Override
    public String toString() {
        return this.desc;
    }
    @Override
    public void test() {
        System.out.println("接口中的方法");
    }
}

4.异常

4.1异常的结构和分类

4.1.1异常的结构

在Java中,用 Throwable 类来描述所有的不正常的情况。Throwable 有两个子类: ExceptionError

Error: 描述发生在JVM虚拟机级别的错误信息, 这些错误无法被处理, 不做为现在的重点。

StackOverflowError: 栈溢出错误

Exception: 描述程序遇到的异常。 异常是可以被捕获处理的, 是现在考虑的重点内容。

未经处理的异常,会导致程序无法进行编译或者运行。 因此在异常部分, 重点内容是:
异常该如何捕获处理。
Java中的异常的继承体系:
    根类: Throwable
        错误: Error
        异常: Exception
            运行时异常: RuntimeException

4.1.2异常的分类

  • 根据异常发生的位置

第一:普通的异常,会导致程序无法完成编译。 这样的异常被称为 -- 编译时异常。 (NonRuntime Exception: 非运行时异常,但是由于异常是发生在编译时期的,因此,常常称为编 译时异常。)

第二:Exception有一个子类-RuntimeException类,在这个类中,对异常进行了自动的处 理 这种异常不会影响程序的编译,但是在运行中如果遇到了这种异常 会导致程序执行的强制停止。这样的异常被称为 -- 运行时异常

  • 根据创建异常类的主体

第一:系统异常,系统提前定义好的,我们直接使用

第二:自定义异常,需要我们自己定义.

4.1.3异常的工作原理

public class Demo7 {
    public static void main(String[] args) {//4
        Math math = new Math();
        math.div(3,0);//3
    }
}
​
class Math{
    public int div(int a,int b){//2
        return a/b;//1
    }
}

原理说明

  • 1.在异常最初发生的位置创建一个异常的对象(new ArithmeticException()) 因为这里没有处理异常的能力,所以会将异常往上抛,抛给他所在的方法

  • 2.div()方法也没有处理异常的能力,所以会继续往上抛,抛给调用这个方法的位置

  • 3.调用div()方法的位置也没有处理异常的能力,所以会继续往上抛,抛给他所在的方法

  • 4.main方法也没有处理异常的能力,所以会继续往上抛,抛给JVM,JVM会调用异常对象的打印方法,将异常信息打印到控制台

4.1.4异常的特点

程序出现异常的时候,会打印异常的信息并中断程序,所以当有多个异常同时出现的时候,默认只 能执行第一个。

4.2异常的捕获处理

4.2.1try-catch

如果一个异常不去处理, 会导致程序无法编译或者运行。

try {
    // 将可能出现异常的代码写到这里
    // 如果这里的代码出现了异常,从出现异常的位置开始,到try代码段结束,所有的代码不执行。
}
catch (异常类型 标识符) {//捕获异常
    // 如果try中的代码出现了异常,并且异常的类型和catch的异常的类型是可以匹配上的,就会执行这里的逻辑
}

catch会对try里面的代码进行监听,如果try里面的代码没有发生异常,catch不会执行,会直接执 行后面的代码.如果try里面的代码发生了异常,catch会立刻捕获(效果:try里面的代码会立刻中 断,直接执行catch)。

注意:

catch中捕获的异常类型, 一定要和try中实际出现的异常类型一致。 否则将捕获不到异常, 会导致try中实际出现的异常没有被捕获处理, 依然可以终止程序的编译或运行。

4.2.2多个catch子句

  • 使用场景

    如果在try代码段中, 出现了多种类型的异常, 此时如果需要对这些异常进行不同的处理, 可以写多个catch子句。

在实际使用中:
·如果要针对不同的异常,进行不同的处理,可以用多个catch。
·如果要针对每一种异常,进行的处理方式相同,直接catch父类异常即可。
  • 语法

try{
        可能发生异常的代码
}catch(异常一 e){ //捕获异常 e就是要捕获的异常
        对当前异常的处理
}catch(异常二 e){ //捕获异常 e就是要捕获的异常
        对当前异常的处理
}catch(Exception e){ //捕获异常 e就是要捕获的异常
        对当前异常的处理
}
go on
  • 注意事项

多个catch书写的先后顺序, 对异常捕获有影响吗?
    
- 如果多个catch捕获的异常类型之间, 没有继承关系存在, 此时先后顺序无所谓。
- 如果多个catch捕获的异常类型之间, 存在继承关系, 则必须保证父类异常在后, 子类异
常在前。

4.2.3一个catch捕获多种异常

  • 使用场景

    如果try中出现了多种异常,并且某些类型的异常,处理方式相同。 并且与其他类型的处理方 式不同。 此时, 可以使用一个catch捕获处理多种异常。区分一个catch里面的多个异常时通 过instanceof.

    缺点:这种分类方式代码很混乱,所以不推荐

  • 注意事项

    在一个catch子句中捕获的多种类型的异常中,不允许出现有继承关系的异常类型.

4.2.4 final子句

  • 概念

    finally出现在try-catch子句的结尾, finally代码段中的内容, 始终会执行。

  • 语法

try{
    可能发生异常的代码
}catch(Exception e){ //捕获异常 e就是要捕获的异常
    对当前异常的处理
}finally{
    必须执行的代码:主要用于资源的释放:比如关闭数据库,关闭流,关闭锁等
}
  • 特点

    无论try代码段中有没有异常出现,无论try里面出现的异常没有被捕获处理,finally中的代码 始终会执行。基于这个特点,常常在finally中进行资源释放、流的关闭等操作

  • 作用范围

    我们发现在catch中执行return后main方法结束,finally还能正常执行

    catch中执行System.exit(0)后,程序退出,finally不能执行了

    结论:只要当前的程序在运行,finally代码就能执行.

4.2.5 try-finally语句

  • 语法

try{
    获取资源
}finally{
    释放资源
}
  • 特点

这个结构跟异常没有关系,主要用于资源的管理.

4.3两个关键字

4.3.1throw

  • 概念/使用场景

    一个异常对象,被实例化完成后,没有任何意义。不会影响到程序的编译或者运行。
    如果希望某一个异常对象生效(可以影响程序的编译、运行),需要使用关键字 throw 进行
异常的抛出。

4.3.2throws

  • 概念/使用场景

    用在方法的声明部分,写在参数列表后面,方法体前面。
    定义在方法中,表示这个方法过程结束中,可能会遇到什么异常。
    定义了throws异常抛出类型的方法,在当前的方法中,可以不处理这个异常,由调用方处理。

4.4自定义异常

4.4.1为什么要自定义异常

使用异常, 是为了处理一些重大的逻辑BUG。这些逻辑BUG可能会导致程序的崩溃。此 时,可以使用异常机制,强迫修改这个BUG。

系统中,提供很多很多的异常类型。但是, 异常类型提供的再多,也无法满足我们所有的需求。当我们需要的异常类型,系统没有提供的时候,此时我们就需要自定义异常了。

4.4.2如何自定义异常

其实,系统提供的每一种异常,都是一个类。所以,自定义异常,其实就是写一个自定义的 异常类。

  • 如果要自定义一个编译时的异常,需要继承自 Exception 类。

    特点:对异常进行处理的所有工作都要我们手动完成

  • 如果要自定义一个运行时的异常,需要继承自 RuntimeException 类。

    特点:所有的工作我们都可以不管

规范:
自定义的异常类, 理论上来讲, 类名可以任意定义。 但是出于规范, 一般都会以
Exception 作为结尾。
例如: ArrayIndexOutOfBoundsException、 NullPointerException、
ArithmeticException...
常见的异常:订单异常 用户异常 负数异常

4.4.3在重写方法中使用异常

注意点:

  • 子类的同名方法中声明的异常等级要<=父类的.

  • 如果子类同名方法声明了异常,父类必须声明异常.

  • 父类抛出了异常,子类在重写方法的时候,可以不抛出异常

如果父类方法抛出的异常是编译时异常子类重写方法的时候,可以抛出相同的异常,或子类异常

子类重写方法的时候,可以抛出运行时异常

如果父类方法抛出的异常是运行时异常子类在重写的时候,可以是任意的运行时异常,不能是编译时异常

5.字符串

5.1字符串的分类

不可变字符串:

  • 对应的类:String.

  • 特点:字符串本身不能发生改变,与指向字符串的引用无关.

  • 直接使用"",创建的是不可变字符串

可变字符串:

  • 对应的类:StringBuilder/StringBuffer.

  • 特点:字符串本身可以发生变化,与指向可变字符串的引用无关

  • 创建可变字符串 StringBuffer stringBuffer = new StringBuffer("hello world");

5.2字符串的常用方法

5.2.1字符串的构造方法

5.2.2字符串的非静态方法

因为字符串, 是常量。 任何的修改字符串的操作, 都不会对所修改的字符串造成任何的影 响。 所有的对字符串的修改操作, 其实都是实例化了新的字符串对象。 在这个新的字符串 中, 存储了修改之后的结果。 并将这个新的字符串以返回值的形式返回。 所以, 如果需要 得到对一个字符串修改之后的结果, 需要接收方法的返回值。

  • 常用的非静态方法

5.2.3字符串的静态方法

  • 常用的静态方法  

5.3 StringBuffer和StringBuilder类

5.3.1概念

都是用来操作字符串的类,我们成为可变字符串

字符串都是常量,所有的操作字符串的方法,都不能直接修改字符串本身。如果我们需要得到修改之后的结果,需要接收返回值。

StringBuffer和StringBuilder不是字符串类,是用来操作字符串的类。在类中维护了一个字 符串的属性,这些字符串操作类中的方法,可以直接修改这个属性的值。对于使用方来说,可以不去通过返回值获取操作的结果。

在StringBuffer或者StringBuilder类中,维护了一个字符数组。这些类中所有的操作方法,都是对这个字符数组进行的操作。

5.3.2常用方法 

5.3.3区别

StringBuffer和StringBuilder从功能上来讲,是一模一样的。但是他们两者还是有区别的:

  • StringBuffer是线程安全的。

  • StringBuilder是线程不安全的。

使用场景:

  • 当处于多线程的环境中, 多个线程同时操作这个对象, 此时使用StringBuffer。

  • 当没有处于多线程环境中, 只有一个线程来操作这个对象, 此时使用StringBuilder。

5.3.4备注

但凡是涉及到字符串操作的使用场景, 特别是在循环中对字符串进行的操作。 一定不要使用 字符串的方法, 用StringBuffer或者StringBuilder的方法来做。

由于字符串本身是不可变的, 所以String类所有的修改操作,其实都是在方法内实例化了一 个新的字符串对象,存储拼接之后的新的字符串的地址,返回这个新的字符串。 如果操作比 较频繁,就意味着有大量的临时字符串被实例化、被销毁, 效率极低。 StringBuffer、StringBuilder不同,在内部维护了一个字符数组,所有的操作都是围绕这个字符数组进行的 操作。当需要转成字符串的时候,才会调用 toString() 方法进行转换。当频繁用到字符串操 作的时候,没有中间的临时的字符串出现,效率较高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值