Java面向对象核心技术

抽象类

由来

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有 意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为 抽象方法 Java 语法规定,包含抽象方法的类就是 抽象类
注意:

抽象类可以没有抽象方法,但是如果一个类已经声明成了抽象类,即使这个类中没有抽象方法,它也不能再实例化,即不能直接构造一个该类的对象。如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译通不过。java中的抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型、方法名称和所需的参数,没有方法体,也就是说抽象方法只需要声明而不需要实现。

定义

抽象方法 : 没有方法体的方法。
抽象类 :包含抽象方法的类

抽象方法

使用 abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。

修饰符 abstract   返回值类型  方法名  ( 参数列表 )
public abstract void go();

抽象类

如果一个类包含抽象方法,那么该类必须是抽象类。
abstract class 类名字 {
}
public abstract class Animal { 
    public abstract void go(); 
}

 抽象的实现与使用

/*
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。

如何使用抽象类和抽象方法:
1. 不能直接创建new抽象类对象。
2. 必须用一个子类来继承抽象父类。
3. 子类必须覆盖重写抽象父类当中所有的抽象方法。
覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
4. 创建子类对象进行使用。
 */
public abstract class Animal {

    // 这是一个抽象方法,代表吃东西,但是具体吃什么(大括号的内容)不确定。
    public abstract void eat();

    // 这是普通的成员方法
//    public void normalMethod() {
//
//    }

}
继承抽象类的子类 必须重写父类所有的抽象方法 。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。
public class Cat extends Animal {
    public void run() {
        System.out.println( "小猫咪在墙头跑" );
    }
}

public class CatTest {
    public static void main(String[] args) { 
        // 创建子类对象 
        Cat c = new Cat();
        // 调用run方法 
        c.run();
    }
}
我们将上面这种方法重写的操作,也叫做 实现方法

注意事项

1. 抽象类 不能创建对象 ,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
子类的构造方法中,有默认的 super() ,需要访问父类构造方法。
3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
4. 抽象类的子类,必须重写抽象父类中 所有的 抽象方法,否则,编译无法通过而报错。除非该子类也是抽象
类。
假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义

接口

定义

接口,是 Java 语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是 封装了方法 ,包含抽象方法( JDK 7 及以前),默认方法和静态方法( JDK 8 ),私有方法 JDK 9 )。
接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成 .class 文件,但一定要明确它并不是类,而是另外一种引用数据类型

定义格式

public interface 接口名称 {
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
}

异常

概念

异常是指程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java理异常的方式是中断处理。

异常分类

我们平常说的异常就是指 Exception ,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。
异常 (Exception) 的分类 : 根据在编译时期还是运行时期去检查异常
编译时期异常 :checked 异常。在编译时期 , 就会检查 , 如果没有处理异常 , 则编译失败。 ( 如日期格式化异常 )
运行时期异常 :runtime 异常。在运行时期 , 检查异常 . 在编译时期 , 运行异常不会编译器检测 ( 不报错 ) ( 如数学异 )

异常的处理

Java 异常处理的五个关键字: try catch fifinally throw throws

1.抛出异常throw

throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

使用格式
throw new 异常类名 ( 参数 );

 

public class ThrowDemo {
    public static void main(String[] args) {
        //创建一个数组 
        int[] arr = {2, 4, 52, 2};
        //根据索引找对应的元素 
        int index = 4;
        int element = getElement( arr, index );
        System.out.println( element );
        System.out.println( "over" );
    }

    /**
     * 根据 索引找到数组中对应的元素
     */
    public static int getElement(int[] arr, int index) {
        //判断 索引是否越界 
        if ( index < 0 || index > arr.length‐1)
        { 
            /*判断条件如果满足,当执行完throw抛出异常对象后,
            方法已经无法继续运算。 这时就会结束当前方法的执行,并将异常告知给调用者。
            这时就需要通过异常来解决。 */
            throw new ArrayIndexOutOfBoundsException( "角标越界了。" );
        }
        int element = arr[index];
        return element;
    }
}

2.声明异常throws

声明异常 :将问题标识出来,报告给调用者。如果方法内通过 throw 抛出了编译时异常,而没有捕获处理,那么必须通过 throws 进行声明,让调用者去处理。
关键字 throws 运用于 方法声明之上 , 用于表示当前方法不处理异常 , 而是提醒该方法的调用者来处理异常 ( 抛出异常 )
声明异常格式:
修饰符 返回值类型 方法名 ( 参数 ) throws 异常类名 1, 异常类名 2…{ }

 

public class ThrowsDemo {
    public static void main(String[] args) throws FileNotFoundException {
        read( "a.txt" );
    }
    // 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明

    public static void read(String path) throws FileNotFoundException {
        if ( !path.equals( "a.txt" ) ) {
            //如果不是 a.txt这个文件
            //如果不是 a.txt 则认为该文件不存在,是一个错误,也就是异常 throw
            throw new FileNotFoundException( "文件不存在" );
        }
    }
}

注意:throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗号隔开。

3.捕获异常try   catch 语句

使用格式:

try {
编写可能会出现异常的代码
} catch ( 异常类型 e ){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常  
}
try 该代码块中编写可能产生异常的代码。
catch 用来进行某种异常的捕获,实现对捕获到的异常进行处理。
注意:try和catch都不能单独使用,必须连用!!!!
import java.io.IOException;

/*
    try...catch:异常处理的第二种方式,自己处理异常
    格式:
        try{
            可能产生异常的代码
        }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
            异常的处理逻辑,异常异常对象之后,怎么处理异常对象
            一般在工作中,会把异常的信息记录到一个日志中
        }
        ...
        catch(异常类名 变量名){

        }
    注意:
        1.try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
        2.如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch之后的代码
          如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try...catch之后的代码
 */
public class TryCatchdemo {
    public static void main(String[] args) {
        try{
            //可能产生异常的代码
            readFile("d:\\a.tx");
            System.out.println("资源释放");
        }catch (IOException e){
            //try中抛出什么异常对象,catch就定义什么异常变量,用来接收这个异常对象
            //异常的处理逻辑,异常异常对象之后,怎么处理异常对象
            //System.out.println("catch - 传递的文件后缀不是.txt");

            /*
                Throwable类中定义了3个异常处理的方法
                 String getMessage() 返回此 throwable 的简短描述。
                 String toString() 返回此 throwable 的详细消息字符串。
                 void printStackTrace()  JVM打印异常对象,默认此方法,打印的异常信息是最全面的
             */
            //System.out.println(e.getMessage());//文件的后缀名不对
            //System.out.println(e.toString());
            //重写Object类的toString java.io.IOException: 文件的后缀名不对
            //System.out.println(e);//java.io.IOException: 文件的后缀名不对

            /*
                java.io.IOException: 文件的后缀名不对
                    at com.itheima.demo02.Exception.Demo01TryCatch.readFile(Demo01TryCatch.java:55)
                    at com.itheima.demo02.Exception.Demo01TryCatch.main(Demo01TryCatch.java:27)
             */
            e.printStackTrace();
        }
        System.out.println("后续代码");
    }

    /*
       如果传递的路径,不是.txt结尾
       那么我们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对

    */
    public static void readFile(String fileName) throws IOException {

        if(!fileName.endsWith(".txt")){
            throw new IOException("后缀名不对");
        }

        System.out.println("路径没问题,读取文件");
    }
}

4.finally

定义:Finally 关键一般与try一起使用,在程序进入try块之后,无论程序是因为异常而中止或其它方式返回终止的,finally块的内容一定会被执行 。finally不能单独使用。

格式:
try{
        可能产生异常的代码
    }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
        异常的处理逻辑,异常异常对象之后,怎么处理异常对象
        一般在工作中,会把异常的信息记录到一个日志中
    }
    ...
    catch(异常类名 变量名){

    }finally{
        无论是否出现异常都会执行
    }
注意: 
1.finally不能单独使用,必须和try一起使用 
2.finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要资源释放(IO)
public class Demo02TryCatchFinally {
    public static void main(String[] args) {
        try {
            //可能会产生异常的代码
            readFile("c:\\a.tx");
        } catch (IOException e) {
            //异常的处理逻辑
            e.printStackTrace();
        } finally {
            //无论是否出现异常,都会执行
            System.out.println("资源释放");
        }
    }
    public static void readFile(String fileName) throws IOException {

        if(!fileName.endsWith(".txt")){
            throw new IOException("文件的后缀名不对");
        }

        System.out.println("路径没有问题,读取文件");
    }
}

注意:
1. 当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。
2. 运行时异常被抛出可以不处理。即不捕获也不声明抛出。
3. 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出。
4. 如果父类抛出了多个异常 , 子类重写父类方法时 , 抛出和父类相同的异常或者是父类异常的子类或者不抛出异 常。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值