面向对象(OOP)笔记

前言:写给自己,坚持不易,希望保持这股劲一直向前走

面向对象开发
面向对象程序设计(Object Oriented Programming,OOP)

  • 把软件系统看成各种对象的集合
  • 系统结构较稳定
  • 子系统相对独立
  • 软件可重用性、可维护性和可扩展性强

一、类与对象

1.面向对象程序设计

程序设计的过程,就是设计类的过程
万物皆对象,程序来源生活,只不过是抽象化–现实的类抽象化

人类:java程序中的类
人:Java中具体的对象
姓名,年龄等等:java中对象的属性特征,静态描述
吃饭,睡觉:Java中对象的方法,动态行为

2.类和对象的关系

类是对象的抽象,而对象是类的具体实例

类:具有相同属性和方法的一组对象的集合
实际类是不存在,只是用来分类,描述对象所具有的信息,而对象是看得见,摸得着的具体实例

属性:
描述对象的静态特征

方法:
描述对象的行为、操作(动态特征)

对象:
用来描述客观事物的一个实体,由一组属性和方法构成

3.类的定义

定义类的步骤:
(1)定义类名
(2)编写类的属性
(3)编写类的方法
注意:
类的属性和方法,一般都是同时存在的,不可分割的
类是java程序的最小组织单元。

示例:

public class  类名(首字母大写) {
        // 定义属性部分(属性不能重名,有默认值)

        属性类型(不仅仅基本数据类型)属性名称1; 
        属性类型(不仅仅基本数据类型)属性名称2; 

        

        // 定义方法部分
        public void 方法名1(){
                // 方法体
        }
        public void 方法名2(){
                // 方法体
        }
    }

4.创建对象

语法:
类名 对象名 = new 类名();

School center = new School();

每个对象的属性和方法都是相互独立的,互不干涉

引用对象成员:使用“.”进行以下操作
引用类的属性:对象名.属性
引用类的方法:对象名.方法名()

center.name = "南京xz";    //给name属性赋值
center.showCenter();	  //调用showCenter()方法
小练习:实现积分回馈功能

要求:

金卡客户积分大于1000分或普卡客户积分大于5000,获得回馈积分500分
创建客户对象,给对象的积分属性赋值,调用回馈积分方法输出卡基本信息及得到的回馈积分

在这里插入图片描述
根据题意,判断所要写的属性

//卡类
String type;
//积分
int integral;

定义输出方法

public void repay(Card card){
		System.out.println("积分:" + card.integral + ",卡类型:" + card.type);
		if ("金卡".equals(card.type)) {
			if (card.integral > 1000) {
				System.out.println("回馈积分500分!");
				card.integral += 500;
				System.out.println("回馈后积分为:" + card.integral);
			}else {
				System.out.println("积分未超过1000,无法回馈积分!");
			}
		}else if ("普卡".equals(card.type)) {
			if (card.integral > 5000) {
				System.out.println("回馈积分500分!");
				card.integral += 500;
				System.out.println("回馈后积分为:" + card.integral);
			}else {
				System.out.println("积分未超过5000,无法回馈积分!");
			}
		}else {
			System.out.println("输入卡类型无效!");
		}
	}

测试类:

public class CardTest {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		
		Card userCard = new Card();
		System.out.print("请输入您的卡类型:");
		userCard.type = input.next();
		System.out.print("请输入您的卡内积分:");
		userCard.integral = input.nextInt();
		userCard.repay(userCard);

		input.close();
	}

}

二、方法与方法重载

1.类的无参方法

方法是什么?

方法是个“黑匣子”,完成某个特定的应用程序功能,并返回结果 类的方法定义类的某种行为(或功能)

如何定义一个方法?

// 方法名:(1)驼峰命名规则(2)有意义
public   返回值类型  方法名()  {
          //这里编写方法的主体
}

方法的返回值
如果方法具有返回值,方法中必须使用关键字return返回该值,返回值类型为该值的类型
其中:返回值只能有一个
没有返回值的方法,也可以使用return,作用是结束方法调用,返回方法调用处
在这里插入图片描述

方法调用
方法之间允许相互调用,不需要知道方法的具体实现,实现重用,提高效率

在这里插入图片描述

2.类的带参方法

定义带参数的方法

<访问修饰符>  返回类型  <方法名>(<形式参数列表>) {
        //方法的主体
}

调用带参数的方法
对象名.方法名(参数1, 参数2,……,参数n)

注意:
形参需要指定参数的类型,参数类型和参数名空格分隔,形参只在方法内部可见,不需要初始化,因为其作用是接收调用方法的实际参数
带参方法传递参数时候,参数的类型和顺序要跟定义的形参列表保持一致
实参要有实际的含义,如果相同类型的参数,值顺序传递错误,那对应的方法执行的结果就是错误的

3. 方法参数传递

在这里插入图片描述

1)值传递
基本数据类型,操作传递的是变量的值,改变一个变量的值不会影响另一个变量的值
2)引用传递(地址传递)
引用数据类型(类、数组、集合等),赋值是把原对象的引用(可理解为内存地址)传递给另一个引用

4.构造方法

语法:

    访问修饰符 构造方法名(){ 
        //初始化代码
    }
    或者

    访问修饰符 构造方法名(参数类型1 参数名1, 参数类型2 参数名2 。。。。){ 
        //初始化代码
    }

特点:
无返回值类型,方法名和类名相同,可以指定参数

作用:
创建对象初始化使用,系统会自动提供默认无参构造方法

自定义构造方法

  • 方法名相同
  • 参数项不同
  • 与返回值、访问修饰符无关

此时系统不再提供默认无参构造方法

5.成员变量和局部变量

变量声明的位置决定变量的作用域,变量的作用域是变量可在程序中按照变量名访问的范围

语法:

 public class 类名{

	变量1类型  变量1;                      
	变量2类型  变量2;
	变量3类型  变量3public 返回类型 方法1(){
              变量4类型  变量4;
     }

 public 返回类型 方法2(){
           变量5类型   变量5}
}

for循环举例,循环内定义的变量,在循环外是无法直接访问的
示例:

for(int  a = 0; a < 4; a++) {
         System.out.println ("hello" );
    }
    System.out.println ( a );// 编译报错

6.两种变量的区别

作用域不同:
成员变量作用域在整个类内,而局部变量仅限于方法内
初始值不同:
成员变量有初始值,而局部变量不会赋予初始值

注意:
方法内不能有重名的局部变量,不同方法内可以定义同名的变量,同一个类中,成员和局部变量重名,那局部变量优先级高,使用this区分成员变量和局部变量,实现属性赋值操作

7.方法重载

方法重载特点:

  • 同一个类中
  • 方法名相同
  • 参数个数或类型不同
  • 与返回值、访问修饰符无关

8.this关键字的用法

  1. this关键字代表当前创建的对象
    this.属性 操作当前对象的属性
    this.方法 调用当前对象的方法。
  2. 封装对象的属性的时候,经常会使用this关键字。
  3. 构造方法中使用this必须遵守的规则:
    (1)假如在一个构造方法中使用了this语句,那么它必须作为构造方法的第一条语句(不考虑注释语句)。
    (2)只能在一个构造方法中使用this语句来调用类的其他构造方法,而不能在成员(实例)方法中用this语句来调用类的其他构造方法。
    (3)只能用this语句来调用其他构造方法,而不能通过方法名来直接调用构造方法。

三、封装与继承

1.什么是封装

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问

封装的步骤:
在这里插入图片描述

  1. 修改属性的可见性
    改为private(防止错误修改属性值)
  2. 创建公有的(public)getter和setter方法
    方便对私有的属性进行赋值和读取
  3. 在getter和setter方法内,增加属性控制逻辑语句
    对属性赋值或者读取进行合法的判断处理

封装的好处:

  • 隐藏实现细节,方便修改
  • 便于使用者正确使用系统,防止错误修改属性
  • 有助于系统之间的松耦合,提高系统独立性
  • 提高软件的可重用性
  • 降低了构建大型系统的风险

2.访问权限控制

类的访问权限控制
public修饰符:公有访问级别
默认修饰符:包级私有访问级别
不同包,使用默认修饰符修饰的类,不可以跨包使用

访问修饰符
四个关键字:

private,默认(default,friendly),protected,public

访问权限范围从小到大,即安全性从高到低
在这里插入图片描述

3.static关键字

一句话描述:

方便在没有创建任何对象的前提下,可以直接通过类进行访问(属性或者方法)

static可以用来修饰

  • 成员变量

    静态变量,可以直接通过类名访问

  • 成员方法

    静态方法,可以直接通过类名访问

  • 代码块

    静态代码块,当Java虚拟机加载类时,就会执行该代码块

注意:
static代码块,可以出现在类的任何地方,类内可以有多个static代码块
static代码块,在类加载的时候,会按照static块的先后顺序进行执行,且只会执行一次。

static变量

类的成员变量包括

  1. 类变量(静态变量)
  • 被static修饰的变量
  • 在内存中只有一个拷贝
  • 类内部,可在任何方法内直接访问静态变量
  • 其他类中,可以直接通过类名访问
  1. 实例变量
  • 没有被static修饰的变量
  • 每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响

static变量的作用
(1)能被类的所有实例共享,可作为实例之间进行交流的共享数据
(2)如果类的所有实例都包含一个相同的常量属性,可把这个属性定义为静态常量类型,从而节省内存空间

类变量(static修饰的成员变量)和实例变量的区别
1)被static修饰的变量,在内存中只有一个拷贝,类内部,可在任何方法内直接访问静态变量,其他类中,可以直接通过类名访问
2)没有被static修饰的变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响。

static方法
  1. 静态方法:可直接通过类名访问
  • 静态方法中不能使用this和super
  • 不能直接访问所属类的实例变量和实例方法
  • 可直接访问类的静态变量和静态方法
  1. 实例方法:通过实例访问
  • 可直接访问所属类的静态变量、静态方法、实例变量和实例方法
  1. 静态方法必须被实现

类方法(static修饰的成员方法)和实例方法的区别
1)静态方法中不能使用this和super,不能直接访问所属类的实例变量和实例方法,可直接访问类的静态变量和静态方法
2)可直接访问所属类的静态变量、静态方法、实例变量和实例方法

归纳:非静态方法可以访问静态属性和方法,但是反过来不成立

static代码块

JVM加载类时,加载静态代码块

  • 如果有多个静态块,按顺序加载
  • 每个静态代码块只会被执行一次

4、继承的用法

  1. 语法:
    编写父类
 [访问修饰符] class Pet { 
        //公共的属性和方法
    }

编写子类

 [访问修饰符] class Dog extends Pet { 
        //子类特有的属性和方法
    }

注意:
子类和父类要存在is-a的关系
使用的继承关键字为:extends,类和类之间只能存在单继承,即只能继承一个类,同一个类可以被多个子类继承

  1. 访问父类的成员:
    关键字:super,代表父类的对象

    子类访问父类的构造:
    super()或者super(参数)

    子类访问父类的属性:
    super.属性

    子类访问父类的方法:
    super.方法()

    注意:
    1)super关键字只能出现在存在继承关系的子类中,且只能在方法或者构造方法中
    2)在子类构造方法中,super关键字调用父类的构造,只能在第一句
    3)不可以通过super关键字访问父类的private属性或者方法

继承条件下,子类继承规则:

  • 子类构造方法没有通过super显式调用父类的有参构造方法,也没通过this显式调用自身其他构造方法,系统默认调用父类的无参构造方法

  • 子类构造方法通过super显式调用父类的有参构造方法执行父类相应构造方法,而不执行父类无参构造方法

5、子类可以继承父类的内容

1)继承public和protected修饰的属性和方法,不管子类和父类是否在同一个包里
2)继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里

父类不可以被子类继承的内容
1)父类的私有成员(属性和方法)-- private修饰的
2)子类和父类不在同包下面,父类使用默认修饰符修饰的成员
3)子类不能继承父类的构造方法(构造是跟类紧密关联的,方法名不同,有特殊用法,用户创建实例)

6、何时使用继承:

1)是否存在is-a的关系,存在就可以用
2)继承的使用条件
子类是特殊的类型,不代表是父类的角色
子类是父类的扩展,可以包含子类特有的属性和方法,且不能让父类的功能失效

四、方法重写与多态

1、方法重写

1.1、意义

当子类继承父类方法,但是父类的方法功能无法满足子类的需求,那就需要在子类重新定义父类的方法,加入子类需要的内容,这种就是方法重写

1.2、方法重写或方法的覆盖(overriding)
  1. 子类对所继承父类相同方法的一种更改,这个更改需要遵循格式按照父类的格式,访问权限,抛出异常等等,都在父类方法控制范围内,内部具体实现可以实现不同的效果。
  2. 重写时,可以用super.方法的方式来保留父类的方法
  3. 构造方法由于类名不同,所以不能被继承,也就不能被重写
  4. 方法重写的前提是:必须要存在继承的关系。
    备注:
    String字符串的equals方法就是最明显的重写,toString()也是
    使用的注解:@override,存在继承关系,可以直接写要重新方法名,自动会带出重写的方法,注意,如果加了注解,代表必须是重写方法

2、方法重写的规则

1)方法重写时,方法名与形参列表必须一致。
2)方法重写时,子类的返回值类型相同或者是其子类,即必须要小于或者等于父类的返回值类型。
3)方法重写时,子类的权限修饰符不能严于父类,即要大于或者等于父类的权限修饰符。
4)方法重写时,父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法
5)方法重写时,子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法(注:静态方法中无法使用super)
6)方法重写时,父类的私有方法不能被子类覆盖
7)方法重写时,子类抛出的异常类型要小于或者等于父类抛出的异常类型。

3、方法重载和方法重写的异同

在这里插入图片描述

4、Object类

所有类的父类,如果没有使用extends关键字指定基类,那默认是继承object类

Object类被子类经常重写的方法:

在这里插入图片描述

Object类的equals()方法

比较两个对象是否是同一个对象,是则返回true

操作符==

  • 简单数据类型,直接比较值。如1==2
  • 引用类型,比较两者是否为同一对象

(1)Object类的equals()方法与==没区别
(2)当有特殊需求,如认为属性相同即为同一对象时,需要重写equals()
(3)Java.lang.String重写了equals()方法,把equals()方法的判断变为了判断其值

5、多态

1.什么是多态

定义:

同一个行为,具有多个不同形式的表现或者能力

2.为什么使用多态

没使用多态的弊端:

频繁修改代码,代码的扩展性、可维护性差
同一个方法,可能需要针对不同的类型参数,重复定义

3.如何实现多态

使用多态实现思路

  • 编写具有继承关系的父类和子类

  • 子类重写父类方法

  • 使用父类的引用指向子类的对象
    向上转型

Pet pet = new Dog(); // 自动类型转换

向上转型
    //测试方法
    Pet pet = new Dog();
    pet.setHealth(20);
    Master master = new Master();
    master.cure(pet);

向上转型:父类的引用指向子类对象,自动进行类型转换

<父类型> <引用变量名> = new <子类型>();
  • 此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法
  • 此时通过父类引用变量无法调用子类特有的方法
向下转型

如果需要调用子类特有的方法,怎么办?

Dog dog=(Dog)pet;//将pet 转换为Dog类型
dog. catchingFlyDisc();//执行Dog特有的方法

向下转型:将一个指向子类对象的父类引用赋给一个子类的引用,即:父类类型转换为子类类型。需强制类型转换

<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;

在向下转型的过程中,如果没有转换为真实子类类型,会出现类型转换异常

如何减少在向下转型的过程中,没有转换为真实子类类型的类型转换异常?
Java中提供了 instanceof 运算符来进行类型的判断

使用instanceof时,对象的类型必须和instanceof后面的参数所指定的类在继承上有上下级关系

实现多态的两种形式:

1)父类作为方法形式参数
2)父类作为方法的返回值

父类指向子类对象时:
注意:

  1. 通过父类引用变量调用的方法是子类覆盖的方法
  2. 通过父类引用变量调用的方法是子类未覆盖的,调用的是从父类继承的旧方法
  3. 通过父类引用变量无法调用子类特有的方法(父类没有该方法,所以调用不到)
  4. 属性也类似

子类引用指向自身对象时:
注意:

  1. 子类引用变量调用的方法是子类覆盖的方法
  2. 子类引用变量调用的方法是未覆盖的,实际调用的是从父类继承的旧方法
  3. 子类引用变量可以调用子类特有的方法
  4. 属性也类似

五、抽象类与接口

1、抽象类和抽象方法

抽象类和抽象方法都使用关键字:abstract修饰

抽象类写法:

 [修饰符] abstract class 类名{
      ...
    }

抽象方法写法:

public abstract void 方法名();

注意:

方法修饰符不能为private,默认是public

使用规则:

1)抽象方法没有方法体,直接分号结尾,主要给子类进行重写

2)抽象方法必须定义在抽象类里,即:抽象方法所在的类必须是抽象类,但是抽象类可以没有抽象方法

3)子类继承抽象类,抽象方法必须在子类中被实现,除非子类是抽象类

4)没有抽象构造方法,也没有抽象静态方法(语法冲突)

5)抽象类中可以有普通构造方法,创建子类的实例时可能调用,也可以有普通方法

6)抽象类不能创建实例,因为可能包含抽象方法

7)抽象类可以作为类型使用,指向子类的实例,调用其抽象方法实际是子类重写的方法

2、什么是接口

接口(英文:Interface),在JAVA中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

接口并不是类,跟类属于不同的概念:类描述对象的属性和方法。接口则包含要实现的方法(能力)。

一个类实现接口,除非是抽象类,否则该类要实现接口中的所有方法,否则编译不通过

3、语法

使用interface关键字,代表定义的为接口

语法:

  [修饰符] interface 接口名称 [extends 父接口名,可以多个,逗号分隔] {
        [public] [static] [final] 常量;  //全局常量
		[public] [abstract] 方法;  //抽象方法
	}

4、特性

1)接口不可以被实例化,长作为类型使用

2)实现类必须实现接口的所有方法

3)实现类可以实现多个接口,implements、多个接口以逗号分隔

4)接口中的变量都是静态常量-接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误)

5)接口中的方法都是公共public,抽象的abstract,且只能是public abstract方法(用其他关键字,比如private、protected、static、final等修饰会报编译错误)所以一般都不需要再声明,写了也不会报错,但是代码检查会提示多余

6)注意:接口是java中解决多继承的有效手段

5、接口的使用

以usb接口为例:

	定义接口
        /**
         * USB接口。
         */
        public interface UsbInterface {
            /**
             * USB接口提供服务。
             */
            void service();
        }

    定义U盘实现接口
        /**
         * U盘。
         */
        public class UDisk implements UsbInterface {
            public void service() {
                System.out.println("连接USB接口,进行数据传输。");
            }
        }

    定义Usb风扇:  
        /**
         * USB风扇。
         */
        public class UShan implements UsbInterface{
            public void service() {
                System.out.println("连接usb接口,通电,风扇开始转起来。");
            }
        } 

6、接口代表一种能力

能力体现在不同的方法上,它关心的是实现类实现的接口能力,但是不关心具体的实现细节
接口体现的是一种规范和实现分离的设计哲学,充分利用接口可以极好地降低程序各模块之间的耦合,从而提高系统的可扩展性和可维护性

接口是一种能力
接口有比抽象类更好的特性:可以被多继承、设计和实现完全分离、更自然的使用多态、更容易搭建程序框架、更容易更换实现

接口是一种约定
我们知道了这个约定,直接使用就可以,而不需要关心它是如何实现的,一般我们定义接口名要根据功能来直译,然后添加详细的方法注释,这样我们看到接口就知道自己要用的方法

7、抽象类和接口的异同

相同点:
代表系统的抽象层,都不能被实例化,都能包含抽象方法-用于描述系统提供的服务,不必提供具体实现

不同点:
抽象类和接口区别-抽象方法只能存在于抽象类或者接口中,但抽象类中却能存在非抽象方法,即有方法体的方法。接口是百分之百的抽象类

语法层面上的区别:

1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。

设计层面上的区别:
抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象
设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计(只需要改模板即可)。而接口是一种行为规范,它是一种辐射式设计(接口一旦修改,所有实现类都要修改)

8、抽象类和接口的使用原则

接口做系统与外界交互的窗口-接口提供服务,接口本身一旦制定,就不允许随意修改

抽象类可完成部分功能实现,还有部分功能可作为系统的扩展点

9、面向对象设计原则

1)多用组合,少用继承
继承会继承父类的内容,有些我们不需要的内容也会继承过来,但是组合不会,使用组合就可以按照需要调用,只有真正存在is a的关系才选择使用继承,否则使用组合

2)针对扩展开放,针对改变(修改)关闭
针对扩展开发:就是需求变动,需要增加功能,少修改原有已经实现的功能模块代码,而是新建模块进行扩展,一般我们修改已经实现的代码基本会是代码有bug,
针对修改关闭:就是要把核心的,共性的,不会被修改的内容抽离,直接使用,不会动这部分的代码

3)针对接口编程-合理、高效使用接口

六、异常

1、异常定义

异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序.

异常处理:
Java编程语言使用异常处理机制为程序提供了错误处理的能力

2、异常处理关键字

try 执行代码,可能出现异常的逻辑代码块

catch 异常捕获,可以针对可能出现的异常,进行特殊处理

finally 无论是否发生异常,都会执行的代码块,除了特殊场景不执行(System.exit(1))

throw 手动抛出异常(一般是自定义异常,自己不处理,让调用该方法的代码块处理,配合throws使用)

throws 声明方法可能抛出的多个异常,多个异常用逗号分隔

在这里插入图片描述

3、try…catch…finally用法

使用try-catch块捕获异常,分为三种情况:

第一种情况 :正常
public void method(){
         try {
                  // 代码段(此处不会产生异常)
         } catch (异常类型 ex) {
                 // 对异常进行处理的代码段
         }
         // 代码段
}

在这里插入图片描述

第二种情况:出现异常
public void method(){
         try {
                // 代码段 1
                // 产生异常的代码段 2
                // 代码段 3
         } catch (异常类型 ex) {
                 // 对异常进行处理的代码段4
         }
         // 代码段5
}

在这里插入图片描述

第三种情况:异常类型不匹配
public void method(){
        try {
                 // 代码段 1
                // 产生异常的代码段 2
               // 代码段 3
        } catch (异常类型 ex) {
               // 对异常进行处理的代码段4
        }
        // 代码段5
}

在这里插入图片描述

  • 在catch块中处理异常

加入用户自定义处理信息

System.out.println("出现错误:被除数和除数必须是整数 ");
  • 调用方法输出异常信息
e.printStackTrace();
  • 异常对象常用的方法
    在这里插入图片描述
常见的异常类型

在这里插入图片描述

在try-catch块后加入finally块
  • 是否发生异常都执行
  • 不执行的唯一情况
    在这里插入图片描述

存在return的try-catch-finally块

public void method(){
         try {
               // 代码段 1
              // 产生异常的代码段 2
          } catch (异常类型 ex) {
              // 对异常进行处理的代码段3
               return;
          }finally{
                // 代码段 4
          }
}

在这里插入图片描述

当异常处理代码块中存在return,会先执行finally,然后再执行return(因为finally是不管是否发生异常,都不行运行的代码块,唯一特殊情况是:System.exit())

4、throws和throw的用法

throws场景
声明接口时,定义可能存在的异常对象,给调用接口方处理
当方法内不想处理异常的时候,可以往外层抛出该异常,留给方法调用者处理

处理方式:
调用者使用try。。catch捕获处理
调用者继续向外层抛出该异常

throw场景
一般用于自定义异常,针对特有的业务逻辑,增加异常信息,方便业务实现

二者区别:

1)throws出现在方法的声明中,在形参列表后,而throw只能出现在方法内部

2)throws代表可能抛出的异常,但是不一定会发生,但是throw是手动抛出异常,该异常是在特定业务场景下,必须存在的异常

3)throws声明的是抛出异常类型,可以是多个,但是throw是抛出一个具体的异常对象,只能是一个。

4)throws和throw一般是相互配合使用的

5、异常的分类

运行时异常
代码运行过程中,可能存在的异常,编译器编译代码是正常的,不会报错

ArrayIndexOutOfBoundsException
NullPointerException
ClassCastException
NumberFormatException
InputMismatchException
ArithmeticException

检查异常
必须要处理的异常,且不处理就不能编译通过
比如:ClassNotFoundException,FileNotFoundException,IOException,SQLException等

注意:
系统错误Error不是异常,这个不是代码可以处理的,一般是非程序异常

异常体系结构

在这里插入图片描述

6、自定义异常

  • 当JDK 中的异常类型不能满足程序的需要时,可以自定义异常类
  • 使用自定义异常的步骤

在这里插入图片描述
在这里插入图片描述

步骤:

  1. 定义异常类,继承Exception或者RuntimeException
  2. 编写构造方法,调用父类的相应构造
  3. 实例化自定义异常对象
  4. 通过throw关键字抛出异常
异常处理原则
  • 异常处理与性能

  • 异常只能用于非正常情况

  • 不要将过于庞大的代码块放在try中

  • 在catch中指定具体的异常类型

  • 需要对捕获的异常做处理

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值