栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

阿毛的Java基础学习笔记 ---(4)面向对象(下)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

阿毛的Java基础学习笔记 ---(4)面向对象(下)

第4章 面向对象(下)

目录
      • 第4章 面向对象(下)
        • 4.1 类的继承
          • 4.1.1 继承的概念:
          • 4.1.2 方法的重写
          • 4.1.3 super关键字
        • 4.2 final关键字
        • 4.3 抽象类与接口
          • 4.3.1 抽象方法 :
          • 4.3.2 接口:
        • 4.4 多态
          • 4.4.1 多态的两种主要形式:
          • 4.4.2 对象类型的转换
          • 4.4.3 instanceof 关键字**
        • 4.5 Object类
        • 4.6 内部类
          • 4.6.1 成员内部类
          • 4.6.2 局部内部类
          • 4.6.3 静态内部类
          • 4.6.4 匿名内部类
        • 4.7 异常
          • 4.7.1 异常概述
          • 4.7.2 try...catch 和 finally
          • 4.7.3 throws关键字
          • 4.7.4 运行时异常与编译时异常:
          • 4.7.5 自定义异常

4.1 类的继承 4.1.1 继承的概念:

在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系

定义:在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类。子类继承父类的属性和方法,使得子类对象(实例)具有父类的特征和行为。

extends关键字:

class 父类{
  ……
 }
class 子类 extends 父类{
  …… 
}

继承实例:

1 // 定义Animal类
2 class Animal {
3    private String name; // 定义name属性
4    private int age;         // 定义name属性
5    public String getName() {
6        return name;
7    }
8    public void setName(String name) {
9        this.name = name;
10    }
11 public int getAge() {
12        return age;
13    }
14 public void setAge(int age) {
15        this.age = age;
16    }
17 }
18 // 定义Dog类继承Animal类
19class Dog extends Animal {
20    private String color; // 定义name属性
21    public String getColor() {
22    return color;
23 }
24 public void setColor(String color) {
25    this.color = color;
26 }
27 }
28 // 定义测试类
29 public class Example02 {
30    public static void main(String[] args) {
31       Dog dog = new Dog();    // 创建一个Dog类的实例对象
32      dog.setName("牧羊犬");   // 此时访问的方法时父类中的,子类中并没有定义
33      dog.setAge(3);           // 此时访问的方法时父类中的,子类中并没有定义
34      dog.setColor("黑色");
35      System.out.println("名称:"+dog.getName()+",年龄:"+dog.getAge()+",
36      颜色:"+dog.getColor());
37    }
38 }

继承中需要注意的要点:

(1)在Java中,类只支持单继承,不允许多重继承。也就是说一个类只能有一个直接父类,例如下面这种情况是不合法的

(2)多个类可以继承一个父类

(3)在Java中,多层继承也是可以的,即一个类的父类可以再继承另外的父类。例如,C类继承自B类,而B类又可以继承自A类,这时,C类也可称作A类的子类。例如下面这种情况是允许的

(4)在Java中,子类和父类是一种相对概念,一个类可以是某个类的父类,也可以是另一个类的子类

4.1.2 方法的重写

解释说明:在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类的方法进行重写

方法的重写实例:

1 // 定义Animal类
2 class Animal {		
3    //定义动物叫的方法		
4	void shout() {			  
5		System.out.println("动物发出叫声");
6	}
7 }
8 // 定义Dog类继承动物类
9 class Dog extends Animal {    
10	//重写父类Animal中的shout()方法
11	void shout() {			 
12		System.out.println("汪汪汪……");  
13	}
14 }
15 // 定义测试类
16 public class Example03 {	
17	public static void main(String[] args) {
18		Dog dog = new Dog(); // 创建Dog类的实例对象
19		dog.shout();           // 调用dog重写的shout()方法
20	}
21 }

注意:在子类中重写的方法需要和父类被重写的方法具有相同的方法名、参数列表以及返回值类型,且在子类重写的方法不能拥有比父类方法更加严格的访问权限

4.1.3 super关键字

解释说明:当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,Java提供了super关键字,super关键字可以在子类中调用父类的普通属性、方法以及构造方

super关键字的主要用法:

(1)使用super关键字访问父类成员变量和方法:

语法:super.成员变量
super.成员方法(参数1,参数2…)

使用实例:

1 // 定义Animal类
2 class Animal {		
3    String name = "牧羊犬";
4    //定义动物叫的方法		
5	void shout() {			  
6		System.out.println("动物发出叫声");
7	}
8 }
9 // 定义Dog类继承动物类
10 class Dog extends Animal {    
11     //重写父类Animal中的shout()方法,扩大了访问权限
12	public void shout() {			 
13         super.shout();      //调用父类中的shout()方法
14		System.out.println("汪汪汪……");  
15	}
16     public void printName(){
17         System.out.println("名字:"+super.name);      //调用父类中的name属性
18     }
19 }
20 // 定义测试类
21 public class Example05 {	
22	public static void main(String[] args) {
23		Dog dog = new Dog();  // 创建Dog类的实例对象
24		dog.shout();            // 调用dog重写的shout()方法
25         dog.printName();        // 调用Dog类中的printName()方法
26	}
27 }

注意extends的书写位置

(2)使用super关键字方法父类中指定的构造方法

语法:super(参数1,参数2…)

1 // 定义Animal类
2 class Animal {
3    private String name;
4    private int age;
5    public Animal(String name, int age) {
6        this.name = name;
7        this.age = age;
8    }
9 	 public String getName() {
10        return name;
11    }
12    public void setName(String name) {
13        this.name = name;
14    }
15    public int getAge() {
16        return age;
17    }
18    public void setAge(int age) {
19        this.age = age;
20    }
    21 public String info() {
22        return "名称:"+this.getName()+",年龄: "+this.getAge();
23   }
24 }

25 // 定义Dog类继承动物类
26 class Dog extends Animal {
27    private String color;
28    public Dog(String name, int age, String color) {
29        super(name, age);
30        this.setColor(color);
31    }
32    public String getColor() {
33        return color;
34    }
    35 public void setColor(String color) {
36        this.color = color;
37    }
38    //重写父类的info()方法
39    public String info() {
40        return super.info()+",颜色:"+this.getColor();    //扩充父类中的方法
41    }
42 }
43 // 定义测试类
44 public class Example06 {
45    public static void main(String[] args) {
46        Dog dog = new Dog("牧羊犬",3,"黑色"); // 创建Dog类的实例对象
47        System.out.println(dog.info());
48    }
49 }

使用super(name,age);

继承了父类中的 this.name=name; 和 this.age=age;

并且可以在super();语句之后添加拓展的构造语句

注意:通过super()调用父类构造方法的代码必须位于子类构造方法的第一行,并且只能出现一次

4.2 final关键字

可以使用final关键字声明类、属性、方法,在声明时需要注意以下几点:
(1)使用final修饰的类不能有子类
(2)使用final修饰的方法不能被子类重写
(3)使用final修饰的变量(成员变量和局部变量)是常量,常量不可修改

final关键字是一种限制和修饰,可以让一个类不能有子类,且如果父类的方法被final关键字修饰,那么它就不能再被子类重写该方法,被其修饰的变量称为常量,其值不能再发生改变

注意final关键字的书写位置

注意:在使用final声明变量时,要求全部的字母大写。如果一个程序中的变量使用public static final声明,则此变量将成为全局变量,如下面代码所示。

public static final String NAME = "哈士奇";
4.3 抽象类与接口

**解释说明:**当定义一个类时,常常需要定义一些成员方法描述类的行为特征,但有时这些方法的实现方式是无法确定的

4.3.1 抽象方法 :

抽象方法用abstract关键字修饰的方法,抽象方法在定义时不需要实现方法体

语法:abstract void 方法名称(参数);

注意:当一个类包含了抽象方法,该类必须是抽象类。抽象类和抽象方法一样,必须使用abstract关键字进行修饰

abstract class 抽象类名称{
    访问权限 返回值类型 方法名称(参数){
           return [返回值];
    }
    访问权限 abstract 返回值类型 抽象方法名称(参数);     //抽象方法,无方法体
}

抽象类的定义规则如下:
(1)包含一个以上抽象方法的类必须是抽象类。
(2)抽象类和抽象方法都要使用abstract关键字声明。
(3)抽象方法只需声明而不需要实现。
(4)如果一个类继承了抽象类,那么该子类必须实现抽象类中的全部抽象方法。

使用abstract关键字修饰的抽象方法不能使用private修饰,因为抽象方法必须被子类实现,如果使用了private声明,则子类无法实现该方法

4.3.2 接口:

如果一个抽象类的所有方法都是抽象的,则可以将这个类定义接口。接口是Java中最重要的概念之一,接口(并不是一个独立的东西)是一种特殊的类,由全局常量和公共的抽象方法组成,不能包含普通方法

JDK 8对接口进行了重新定义,接口中除了抽象方法外,还可以有默认方法和静态方法(也叫类方法),默认方法使用default修饰,静态方法使用static修饰,且这两种方法都允许有方法体

接口的声明:使用interface关键字声明

 public interface 接口名 extends 接口1,接口2... {
	 public static final 数据类型 常量名 = 常量值; 
     //静态方法
	 public default 返回值类型 抽象方法名(参数列表);
     //抽象方法
     public abstract 返回值类型 方法名(参数列表){
        //默认方法的方法体
     }
     public abstract 返回值类型方法名(参数列表){
        //类方法的方法体
     }
 }

注意: 接口中的变量默认使用“public static final”进行修饰,即全局常量。接口中定义的方法默认使用“public abstract”进行修饰,即抽象方法。如果接口声明为public,则接口中的变量和方法全部为public

“extends 接口1,接口2…”表示一个接口可以有多个父接口,父接口之间使用逗号分隔。Java使用接口的目的是为了克服单继承的限制,因为一个类只能有一个父类,而一个接口可以同时继承多个父接口

多学一点:经常看到编写接口中的方法时省略了public ,但是接口中的方法访问权限永远是public。与此类似,在接口中定义常量时,可以省略前面的“public static final”,此时,接口会默认为常量添加“public static final”

接口的使用: 接口的使用必须通过子类,子类通过implements关键字实现接口,并且子类必须实现接口中的所有抽象方法。需要注意的是,一个类可以同时实现多个接口,多个接口之间需要使用英文逗号(,)分隔

修饰符 class 类名 implements 接口1,接口2,...{
    ...
}

接口实例:

//定义抽象类Animal(注意这里声明时忽略了public)
interface Animal{
    int ID = 1;
    String NAME = "牧羊犬";
    void shout();
    static int getID(){
        return ID;
    }
    public void info();
    //上面有两个抽象方法不用设置函数体
}
interface Action{
    public void eat();
}
//定义Dog类实现Animal接口和Action接口
class Dog implements Animal,Action{
    //Animal接口里eat方法的重写
    public void eat(){
        System.out.println("骨头");
    }
    //Action接口里shout方法的重写
    public void shout(){
        System.out.println("汪汪汪");
    }
    //Animal接口里info方法的重写
    public void info(){
        System.out.println("名称"+NAME);
    }
}
//定义测试类
class Example11{
    public ststic void main(String args[]){
        Systrm.out.println("编号"+Animal.getID());
        //接口中的静态方法 getID(); 则可以直接使用接口名调用
        Dog dog = new Dog();
        dog.info();
        dog.shout();
        dog.eat();
    }
}

注意:接口的实现类,必须实现接口中的所有方法,否则程序编译报错!

如果在开发中一个子类既要实现接口又要继承抽象类,则可以按照以下格式定义子类:

修饰符class 类名 extends 父类名implements 接口1,接口2,... {
    ...
}

【案例4-1】打印不同的图形

【案例4-2】饲养员喂养动物

【案例4-3】多彩的声音

【案例4-4】学生和老师

【案例4-5】图形的面积与周长计算程序

【案例4-6】研究生薪资管理

4.4 多态

多态概述:多态性是面向对象思想中的一个非常重要的概念,在Java中,多态是指不同对象在调用同一个方法时表现出的多种不同行为,在同一个方法中,这种由于参数类型不同而导致执行效果不同的现象就是多态

4.4.1 多态的两种主要形式:

(1)方法的重载 (2)对象的多态性–方法重写

4.4.2 对象类型的转换

:(1)向上转型:子类对象->父类对象 (2)向下转型->子类对象

转换格式:

  • 对象向上转型: 父类类型 父类对象 = 子类实例;
  • 对象向下转型:

父类类型 父类对象 = 子类实例;

子类类型 子类对象 = (子类)父类对象;

向上转型实例:

//定义Animal类
class Animal{
    public void shout(){
    	System.out.println("喵喵...");
    }
}
//定义Dog类
class Dog extends Animal{
    //方法shout的重写
    public void shout(){
        System.out.println("汪汪...");
    }
}
//定义测试类
public class Example15{
    public static void main(String args[]){
        Dog dog = new Dog();//创建了dog对象
        Animal an = dog;//将dog向上转型为Animal类型的对象an
        an.shout();//使用父类对象an调用了shout();方法,但实际上调用的是被重写过的shout();方法
    }
}

如果对象发生了向上转型关系后,所调用的方法一定是被子类重写过的方法

父类Animal的对象an是无法调用Dog类中的eat()方法的,因为eat()方法只在子类中定义,而没有在父类中定义

向下转型实例:

//定义类Animal
class Animal{
    public void shout(){
        System.out.println("喵喵...");
    }
}
//定义Dog类
class Dog extends Animal{
    //方法shout的重写
    public void shout(){
        System.out.println("汪汪...");
    }
    public void eat(){
        System.out.println("吃骨头");
    }
}
//定义测试类
public class Example16{
    public static void main(String args[]){
        Animal an = new Dog();//此时发生了向上转型,将Dog类的实例转换成了Animal类的实例an
        //Animal an = new Dog();
        //是Dog dog = new Dog();  Animal an  = dog; 的简写形式
        Dog dog = (Dog)an;//此时发生了向下转型,将Animal类的实例an转换为Dog类的实例dog
        dog.shout();
        dog.eat();
    }
}

在向下转型时,不能直接将父类实例强制转换为子类实例,否则程序会报错

4.4.3 instanceof 关键字**

Java中可以使用instanceof关键字判断一个对象是否是某个类(或接口)的实例
语法 : 对象 instanceof类(或接口)
在上述格式中,如果对象是指定的类的实例对象,则返回true,否则返回false

【案例4-8】模拟物流快递系统

4.5 Object类

Object概述:Java提供了一个Object类,它是所有类的父类,每个类都直接或间接继承Object类,因此Object类通常被称之为超类。当定义一个类时,如果没有使用extends关键字为这个类显式地指定父类,那么该类会默认继承Object类

方法名称方法说明
boolean equals()判断两个对象是否“相等”
int hashCode()返回对象的哈希码值
String toString()返回对象的字符串表示形式

在实际开发中,通常希望对象的toString()方法返回的不仅仅是基本信息,而是对象特有的信息,这时可以重写Object类的toString()方法

toString(); 方法实例:

1 // 定义Animal类
2 class Animal {
3   //重写Object类的toString()方法
4   public String toString(){
5	return "这是一个动物。";
6   }
7 }
8 // 定义测试类
9 public class Example19 {
10	public static void main(String[] args) {
11		Animal animal = new Animal(); 			// 创建Animal类对象
12		System.out.println(animal.toString()); // 调用toString()方法并打印
13	}
14 }
4.6 内部类

内部类概述:在Java中,允许在一个类的内部定义类,这样的类称作内部类,内部类所在的类称作外部类,成员内部类可以访问外部类的所有成员

在实际开发中,根据内部类的位置、修饰符和定义方式的不同,内部类可分为4种,分别是成员内部类、局部内部类、静态内部类、匿名内部类

4.6.1 成员内部类

在一个类中除了可以定义成员变量、成员方法,还可以定义类,这样的类被称作成员内部类。成员内部类可以访问外部类的所有成员。

1 class Outer {
2    int m = 0; 		// 定义类的成员变量
3   // 下面的代码定义了一个成员方法,方法中访问内部类
4    void test1() {
5       System.out.println("外部类成员方法");
6    }
7    // 下面的代码定义了一个成员内部类
8    class Inner {
9        int n = 1;
10        void show1() {
11           // 在成员内部类的方法中访问外部类的成员变量
12           System.out.println("外部成员变量m = " + m);
13       }
14 void show2() {
15            // 在成员内部类的方法中访问外部类的成员变量
16           System.out.println("内部成员方法");
17       }
18    }
19    void test2() {
20        Inner inner = new Inner();
21        System.out.println("内部成员变量n = " + inner.n);
22        inner.show2();
23    }
24 }
25 public class Example20 {
26    public static void main(String[] args) {
27        Outer outer = new Outer();
28        Outer.Inner inner = new outer.new Inner();
29        inner.show1();
30       outer.test2();
31    }
32 }

如果想通过外部类访问内部类,则需要通过外部类创建内部类对象,创建内部类对象的具体语法格式如下:
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

(如上代码块28行代码)

4.6.2 局部内部类

局部内部类,也叫作方法内部类,是指定义在某个局部范围中的类,它和局部变量一样,都是在方法中定义的,有效范围只限于方法内部

局部内部类实例:

class Outer{
    int m = 0;
    void test1(){
        System.out.println("外部类成员方法");
    }
    void test2(){
        class Inner{
            int n = 1;
            void show(){
                //在成员内部类的方法中访问外部类的成员变量
                System.out.println("外部成员变量m="+m);
                test1();
            }
        }
        Inner inner = new Inner();
        System.out.println("局部内部成员变量n="+inner.n);
        inner.show();
    }
}
public class Examp21{
    public static void main(String args[]){
        Outer outer  = new Outer();
        outer.test2();
    }
}
4.6.3 静态内部类

所谓静态内部类,就是使用static关键字修饰的成员内部类。与成员内部类相比,在形式上,静态内部类只是在内部类前增加了static关键字

但在功能上,静态内部类只能访问外部类的静态成员,通过外部类访问静态内部类成员时,可以跳过外部类直接访问静态内部类

创建静态内部类对象的基本语法格式如下:
外部类名.静态内部类名 变量名 = new 外部类名().静态内部类名();

静态内部类实例:

class Outer{
    static int m = 0;
    static class Inner{
        int n = 1;
        void show(){
            System.out.println("外部静态变量m="+m);
            //有static关键字修饰的静态内部类只能访问有static修饰的外部类的静态变量
        }
    }
}
public class Example{
    public static void main(String args[]){
        Outer.Inner inner = new Outer.Inner();
        inner.show();
    }
}
4.6.4 匿名内部类

匿名内部类是没有名称的内部类。在Java中调用某个方法时,如果该方法的参数是接口类型,除了可以传入一个接口实现类,还可以使用实现接口的匿名内部类作为参数,在匿名内部类中直接完成方法的实现

创建匿名内部类的基本语法格式如下:
new 父接口(){
//匿名内部类实现部分
}

1 interface Animal{
2   void shout();
3 }
4 public class Example23{
5    public static void main(String[] args){
6        String name = "小花";
7        animalShout(new Animal(){
8           @Override
9            public void shout() {
10                System.out.println(name+"喵喵...");
11            }
12       });
13   }
14   public static void animalShout(Animal an){
15       an.shout();
16    }
17 }

匿名类的编写步骤:
**(1)**在调用animalShout()方法时,在方法的参数位置写上new Animal(){},这相当于创建了一个实例对象,并将对象作为参数传给animalShout()方法。在new Animal()后面有一对大括号,表示创建的对象为Animal的子类实例,该子类是匿名的。具体代码如下所示:
animalShout(new Animal(){});

**(2)**在大括号中编写匿名子类的实现代码,具体如下所示:
animalShout(new Animal() {
public void shout() {
System.out.println(“喵喵……”);
}
});

4.7 异常 4.7.1 异常概述

在程序运行的过程中,也会发生各种非正常状况,例如,程序运行时磁盘空间不足、网络连接中断、被装载的类不存在等。针对这种情况, Java语言引入了异常,以异常类的形式对这些非正常情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理

算术异常案例:

1 public class Example24 {                      
2	public static void main(String[] args) {
3		int result = divide(4, 0);    // 调用divide()方法
4		System.out.println(result);    
5	}
6    //下面的方法实现了两个整数相除
7	public static int divide(int x, int y) { 
8		int result = x / y;     	// 定义一个变量result记录两个数相除的结果
9		return result;           	// 将结果返回
10	}
11 }

程序发生了算术异常(ArithmeticException),该异常是由于文件4-24中的第3行代码调用divide()方法时传入了参数0,运算时出现了被0除的情况。异常发生后,程序会立即结束,无法继续向下执行。

上述程序产生的ArithmeticException异常只是Java异常类中的一种,Java提供了大量的异常类,这些类都继承自java.lang.Throwable类。
接下来通过一张图展示Throwable类的继承体系

Throwable有两个直接子类Error和Exception,其中,Error代表程序中产生的错误,Exception代表程序中产生的异常。
● Error类称为错误类,它表示Java程序运行时产生的系统内部错误或资源耗尽的错误,这类错误比较严重,仅靠修改程序本身是不能恢复执行的。举一个生活中的例子,在盖楼的过程中因偷工减料,导致大楼坍塌,这就相当于一个Error。例如,使用java命令去运行一个不存在的类就会出现Error错误。

● Exception类称为异常类,它表示程序本身可以处理的错误,在Java程序中进行的异常处理,都是针对Exception类及其子类的。在Exception类的众多子类中有一个特殊的子类—RuntimeException类,RuntimeException类及其子类用于表示运行时异常。 Exception类的其他子类都用于表示编译时异常。

Throwable类中的常用方法如下表

方法声明功能描述
String getMessage()返回异常的消息字符串
String toString()返回异常的简单信息描述
void printStackTrace()获取异常类名和异常信息,以及异常出现在程序中的位置,把信息输出在控制台。
4.7.2 try…catch 和 finally

为了解决异常,Java提供了对异常进行处理的方式一一异常捕获。异常捕获使用try…catch语句实现,try…catch具体语法格式如下

try{
    //程序代码块
}catch(ExceptionType(Exception类及其子类) e){
    //对ExceptionType的处理
} 

finally关键字:在程序中,有时候会希望有些语句无论程序是否发生异常都要执行,这时就可以在try…catch语句后,加一个finally代码块

1 public class Example26 {
2	public static void main(String[] args) {
3          //下面的代码定义了一个try…catch…finally语句用于捕获异常
4		try {
5			int result = divide(4, 0);       //调用divide()方法
6			System.out.println(result);
7		} catch (Exception e) {               //对捕获到的异常进行处理
8			System.out.println("捕获的异常信息为:" + e.getMessage());
9             			 return;                             //用于结束当前语句,程序第13行代码就不会执行了,而finally代码块中的代码仍会执行,不受return语句影响
10		} finally {                             
11			System.out.println("进入finally代码块");
12		}
13 System.out.println("程序继续向下执行…");
14	}
15     //下面的方法实现了两个整数相除
16	public static int divide(int x, int y) {
17		int result = x / y;           //定义一个变量result记录两个数相除的结果
18		return result;                 //将结果返回
19	}
20 }

finally中的代码块在一种情况下是不会执行的,那就是在try…catch中执行了System.exit(0)语句。System.exit(0)表示退出当前的Java虚拟机,Java虚拟机停止了,任何代码都不能再执行了

4.7.3 throws关键字

在实际开发中,大部分情况下我们会调用别人编写方法,并不知道别人编写的方法是否会发生异常。针对这种情况,Java允许在方法的后面使用throws关键字对外声明该方法有可能发生的异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过

throws关键字声明抛出异常的语法格式如下:
修饰符 返回值类型 方法名(参数1,参数2…)throws 异常类1, 异常类2…{
//方法体…
}
从上述语法格式中可以看出,throws关键字需要写在方法声明的后面,throws后面需要声明方法中发生异常的类型

throws关键字实例:

1 public class Example28 {
2	public static void main(String[] args) {
3         //下面的代码定义了一个try…catch语句用于捕获异常
4		try {
5			int result = divide(4, 2);   //调用divide()方法
7			System.out.println(result); 
8		} catch (Exception e) {           //对捕获到的异常进行处理
9			e.printStackTrace();          //打印捕获的异常信息
10		}
11	}
12 //下面的方法实现了两个整数相除,并使用throws关键字声明抛出异常
13	public static int divide(int x, int y) throws Exception {
14		int result = x / y;      //定义一个变量result记录两个数相除的结果
15		return result;            //将结果返回
16	}
17 }

(1)由于使用了try…catch对divide()方法进行了异常处理,因此程序可以编译通过

(2)如果没有使用try…catch对divide()方法进行异常处理,在main()方法继续使用throws关键字将Exception抛出,程序虽然可以通过编译,但从运行结果可以看出,在运行时期由于没有对“/by zero”的异常进行处理,最终导致程序终止运行

4.7.4 运行时异常与编译时异常:

参考图

  • 编译时异常:

在Exception类中,除了RuntimeException类及其子类,Exception的其他子类都是编译时异常。编译时异常的特点是Java编译器会对异常进行检查,如果出现异常就必须对异常进行处理,否则程序无法通过编译。
处理编译时期的异常有两种方式,具体如下:
(1)使用try…catch语句对异常进行捕获处理。
(2)使用throws关键字声明抛出异常,调用者对异常进行处理。

  • 运行时异常:

RuntimeException类及其子类都是运行时异常。运行时异常的特点是Java编译器不会对异常进行检查。也就是说,当程序中出现这类异常时,即使没有使用try…catch语句捕获或使用throws关键字声明抛出,程序也能编译通过。运行时异常一般是由程序中的逻辑错误引起的,在程序运行时无法恢复

4.7.5 自定义异常

JDK中定义了大量的异常类,虽然这些异常类可以描述编程时出现的大部分异常情况,但是在程序开发中有时可能需要描述程序中特有的异常情况

例如,前面讲解的程序中的divide()方法,不允许被除数为负数。为了解决这个问题,Java允许用户自定义异常,但自定义的异常类必须继承自Exception或其子类

自定义异常:

//自定义一个异常类,这个异常类继承于Exception
public class DivideMinusException extends Exception{
    public DivideByMinusException(){
        super();	// 调用Exception无参的构造方法
    }
    public DivideByMinusException(String message){
        super(massage);	// 调用Exception有参的构造方法
    }
}

在实际开发中,如果没有特殊的要求,自定义的异常类只需继承Exception类,在构造方法中使用super()语句调用Exception的构造方法即可。
自定义异常类中使用throw关键字在方法中声明异常的实例对象,格式如下:
throw Exception异常对象

用throw关键字抛出异常对象时,需要使用try…catch语句对抛出的异常进行处理,或者在divide()方法上使用throws关键字声明抛出异常,由该方法的调用者负责处理

自定义异常实例:

public class Example{
    public static void main(String args[]){
        //定义一个try...catch语句用于捕获异常
        try{
            int result = devide(4,-2);
            System.out.println(result);
        }
        catch(DivideNyMinusException e){	//对捕获到的异常进行处理
            System.out.println(e.getMessage);	//打印捕获的异常信息
        }
    }
    public static int divide(int x,int y) throw DivideByMinusException{	
        if(y<0){
            throw new DivideByMinusException("除非是负数");	//捕捉到异常后的行为
        }
        int result = x/y;
        return result;
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/286911.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号