• Java入门——(3)面对对象(下)


    关键词:  类的继承、final关键字、多态、接口、异常、包、访问控制
    一、类的继承
          1、类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法,使用extends关键字。
     
    class A{}
    class B extends A{}
           在Java中继承的体现:
           ①Java允许单继承。不直接支持多继承,将多继承进行其他方式的体现。
           ②单继承:一个子类只能有一个父类。
    class A{}
    class B{}
    class C extends A,B{}  //C类不可以同时继承A类和B类
           ③多继承:一个子类可以有多个父类,用多实现体现。
           ④多重继承,继承体系。
           学习继承体系时,应该参阅顶层的类中的内容,了解这个体系的基本功能。使用这个体系功能,需要创建最子类的对象。(看顶层,建底层。)
     
          2、override:子父类中的定义了一模一样的函数。运行的结果:子类的函数在运行。这种情况在子父类中,是函数的另一个特性:override(重写、覆盖、复写)。
          重写的注意事项:

          ①子类覆盖父类,必须保证权限要大于或等于父类的权限。

          ②静态覆盖静态。

          ③写法上必须一模一样,函数的返回值类型 函数名 参数列表都要一样。

           3、super关键字

           ①子父类中构造函数的特点:
           当子父类都有构造函数时,先执行父类的构造函数,再执行子类的构造函数,因为子类的所有的构造函数中的第一行都有一句隐式语句
           super();//默认调用的是父类中的空参数的构造函数。
     
           为什么子类中的构造函数有一句隐式的super()?
           原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。才可以更方便使用父类中的内容。
           当父类中没有空参数构造函数时,子类的构造函数必须同构显式的super语句指定要访问父类中的构造函数。
           细节:

    ①如果子类的构造函数第一行写了this调用了背离其他构造函数,那么super调用父类的语句是没有的,因为this()或者super(),只能在构造函数的第一行,因为初始化动作要先执行。

    ②父类构造函数中是否有隐式的super呢?也是有的,只要是构造函数默认第一行都是super();

    父类的父类是谁?super调用的到底是谁的构造函数,在Java体系在设计,定义了一个所有对象的父类object。
    总结:类中的构造函数默认第一行都有隐式的super()语句,在访问父类中的构造函数。
    所以父类的构造函数既可以给自己对象初始化,也可以给自己的子类对象初始化。
    如果默认的隐式super的语句没有对应的构造函数,必须在构造函数中通过this后者super的形式明确调用的构造函数。
     
    super应用:
    ①子类的实例化过程的应用,也是super调用的应用。

    ②只要使用父类的指定初始化动作,就在子类中通过super(参数列表)格式进行调用。

    super关键字的用法:

    ①使用super关键字调用父类的成员变量和成员方法。具体格式:

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

    ②使用super关键字调用父类的构造方法,具体格式:

    super([参数1,参数2……….])
    通过super调用父类构造方法的代码必须位于子类构造方法的第一行,且只能出现一次。
          在定义一个类时,如果没有特殊需求,尽量在类中定义一个无参的构造方法,避免继承时出现错误。
     
          继承的弊端:打破封装性。
     
    二、final关键字
     
          1、final(最终化)修饰符,可以修饰类、方法、变量(成员变量、局部变量、静态变量)。

          ①final修饰的类是一个最终类,该类将不能被继承,不能派生子类。

          ②final 修饰的方法是最终方法,不可以重写。
          当父类中定义某个方法时,如果不希望被子类重写,就可以使用final关键字修饰该方法。
          如:public final void shout(){}

    ③final修饰的变量是一个常量,只能被赋值一个。

     如:final int num = 2;

    2、【什么时候会在程序中定义final常量呢?】
    当程序中一个数据使用时是固定不变的,这时为了增加阅读性,可以给该数据起个名字。
    这是变量,为了保证这个变量的值不被修改,加上final修饰,这是一个阅读性很强的常量。
    书写规范,被final修饰的常量名所有字母都是大写的。如果由多个单词间通过 _ 连接。
     
    三、抽象类和接口
    1、abstract(抽象)
    抽象类:在描述事物时,没有足够的信息描述一个事物,这时该事物就是抽象事物。
    定义了抽象函数的类,也必须被abstract关键字修饰,被abstract关键字修饰的类是抽象类。
    抽象方法的类必须声明为抽象类,但抽象类可以不包含任何抽象方法,只要abstract关键字修饰即可。
     
    【抽象类的特点】

            ①抽象类和抽象方法都需要被abstract修饰。(抽象方法一定要定义在抽象类中)。

    //定义抽象类Animal
    abstract class Animal{
    //定义抽象方法shuot()
    abstract int shout ();
    }

           ②抽象类不可以创建实例,原因:调用抽象方法没有方法体。

           ③只要覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。否则该子类还是一个抽象类。

           之所以继承,更多的是在思想,是面对共性类型操作会更简单。
     
        2、接口(interface)
        接口:如果一个类中的所有抽象方法都是抽象的,则可以将这个类用另外一种方式来定义,即接口。在定义接口时,需要使用interface关键字来声明,如:
    1 interface Animal{
    2     int ID = 1; //定义全局变量
    3     void breathe(); //定义抽象方法
    4     void run ();
    5 } // Animal 即为一个接口,接口中定义的的方法和变量都包含一些默认修饰符“public abstract”(抽象方法)“public static final”(全局变量)。
     
          接口的特点:

    ①接口可以创建对象;

    ②子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。

    ③实现多接口示例:

    复制代码
    interface Run{
    程序代码…..
    }
    interface Fly{
    程序代码…..
    }
    class Bird implements Run,Fly{
    程序代码…….
    }
    复制代码
           定义子类去覆盖接口的方法:子类必须和接口产生关系,类与类的关系是继承,类与接口之间的关系是实现,通过关键字implements 。
     
    接口最重要的体现:解决多继承的弊端。将多继承这种机制在Java中通过多实现完成。
    多继承的弊端:当多个父类中有相同功能时,子类调用会产生不确定性。
    其核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。
    接口中的功能都没有方法体,由子类来明确。
     
           如果子类想要继承扩展其他类中的功能,可通过接口实现:
    class Dog extends Canidae implements Animal{ //先继承,再实现
    程序代码……
    }
           父类定义事物的基本功能,接口定义事物的扩展功能。
     
           接口出现后的一些细节:类与类之间是继承关系,类与接口是实现关系;接口与接口之间是继承关系,而且可以多继承。
     
    四、多态
    1、多态的概述
    【体现】
    父类的引用或者接口的引用指向了自己的子类对象。
    Dog d = new Dog(); // Dog对象的类型是Dog类型
    Animal a = new Dog(); // Dog对象的类型右边是Dog类型,左边Animal 类型。
    【好处】
    提高了程序的扩展性。
    【弊端】
    通过父类引用操作子类对象时,只能使用父类中已有的方法,不能操作子类特有的方法。
    【前提】
    ①必须有关系,继承、实现。
    ②通常都有重写操作。
    复制代码
     1 //定义接口Animal
     2 interface Animal{
     3     void shout();
     4 }
     5 //定义Cat类实现Animal接口
     6 class Cat implements Animal{
     7        //实现shout()方法
     8     public void shout(){
     9         System.out.println("喵喵...");
    10     }
    11 }
    12 //定义Dog类型实现Animal接口
    13 class Dog implements Animal{
    14     public void shout(){
    15         System.out.println("汪汪");
    16     }
    17 }
    18 //定义测试类
    19 public class Example13 {
    20     public static void main(String[] args) {
    21         Animal an1 =new Cat();//创建Cat对象,使用Animal类型的变量an1引用
    22         Animal an2 =new Dog();//创建Dog对象,使用Animal类型的变量an2引用
    23         animalShout(an1);     //调用animalShout()方法,将an1作为参数传入
    24         animalShout(an2);     //调用animalShout()方法,将an2作为参数传入
    25     }
    26     public static void animalShout(Animal an) {
    27         an.shout();
    28     }
    29 }
    复制代码

    运行结果

    喵喵…
    汪汪
    【子类的特有方法如何调用?】
    Animal a = new Dog();//Animal是父类型,new Dog()子对象。
    但是父类型引用指向子类对象时,这就是让子类对象进行了类型的提升(向上转型)。
    向上转型好处:提高了扩展性,隐藏了子类型。
    弊端:不能使用子类型的特有方法。
    如果想使用子类的特有方法,只有子类型可以用。
    可以向下转型,强制转换。
    Animal a = new Dog();
    a.eat();
    Dog d = (Dog)a; //将a转型为Dog 类型。向下转型。
    d.lookHome();
    向下转型什么时候用?当需要使用子类型的特有内容时。
    注意:无论向上还是向下转型,最终都是子类对象做着类型的变化。
    【向下转型的注意事项】
    Animal a = new Dog();
    Cat c = (Cat)a;//向下转型因为不明确具体子类对象类型,所以容易引发classCastException(转型异常)异常。
    所以为了避免这个问题,需要在向下转型前,做类型的判断。
    判断类型用的是关键字 instanceof
    复制代码
    if(a instanceof Cat){   //a指向的对象的类型是Cat类型。
        //将a转型Cat 类型。
        Cat c = (Cat)a;
        c.catchMouse();
    }else if(a instanceof Dog){
        Dog d = (Dog) a;
        d.lookHome();
    }
    复制代码
    示例:
    复制代码
     1 interface Animal{
     2     void shout();//定义抽象方法shout()
     3 }
     4 //定义Cat类实现Animal接口
     5 class Cat implements Animal{
     6     //实现抽象方法shout()
     7     public void shout(){
     8         System.out.println("喵喵...");
     9     }
    10     //定义sleep()方法
    11     public void sleep(){
    12         System.out.println("猫在睡觉.....");
    13     }
    14 }
    15 //定义Dog类实现Animal接口
    16 class Dog implements Animal{
    17     //实现抽象方法shout()
    18     public void shout(){
    19         System.out.println("汪汪...");
    20     }
    21 }
    22 //定义测试类
    23 public class Example14 {
    24     public static void main(String[] args) {
    25         Animal dog = new Dog();    //创建Dog类的实例对象
    26         animalShout(dog);    //调用animalShout()方法,将dog作为参数传入
    27     }
    28     public static void animalShout(Animal animal) {
    29         if (animal instanceof Cat) {
    30             Cat cat = (Cat) animal;//将animal对象强制装换为Cat类型
    31             cat.shout();           //调用cat的shout()方法
    32             cat.sleep();           //调用cat的sleep()方法
    33         }else{
    34             System.out.println("this animal is not a cat!");
    35         }
    36     }
    37 }
    复制代码

     运行结果:

    this animal is not a cat!
    【转型总结】

    ①什么时候向上转型?

    提高程序的扩展性,不关系子类类型(子类型被隐藏)。
    需要用子类的特有方法吗?不需要,向上转型。

    ②什么时候向下转型?

    需要使用子类型的特有方法时。
    但是一定要使用instanceof 进行类型的判断。避免发生classCastException。
     
    2、匿名内部类格式:
    new 父类(参数列表)或父接口(){
    // 匿名内部类实现部分
    }

    示例

    复制代码
     1 interface Animal{
     2     void shout();
     3 }
     4 public class Example18 {
     5     public static void main(String[] args) {
     6         animalShout(new Animal(){
     7             public void shout() {
     8                 System.out.println("喵喵...");
     9             }
    10         });
    11     }
    12     public static void animalShout(Animal an) {
    13         an.shout();
    14     }
    15 }
    复制代码

    运行结果

    喵喵... 
         
         3、Object类是所有类的根类,定义了所有对象都具备的功能,一般情况下均会重写Object的toString()方法,来返回指定的信息。
         示例:
    复制代码
     1 class Animal{
     2     /*//定义动物叫的方法
     3     void shout(){
     4         System.out.println("动物叫");
     5     }*/
     6     //重写Object类中的toString()方法
     7 
     8     @Override
     9     public String toString() {
    10         return "I am an animal!";
    11     }
    12 }
    13 //定义测试类
    14 public class Example16 {
    15     public static void main(String[] args) {
    16         Animal animal = new Animal();       //创建Animal类对象
    17         System.out.println(animal.toString()); //调用toString()方法并打印
    18     }
    19 }
    复制代码

    五、异常

           1、Throwable类的继承体系

          

           
     
    ①错误类(Error类):表示Java运行时产生的系统内部错误或资源耗尽的错误,是比较严重的,仅靠修改程序本身是不能恢复执行的。
    ②运行时异常与编译时异常:
         编译时异常:在Java中Exception类中除了RuntimeException类即其子类都是编译时异常。特点是编译器会检测的异常,如果出现异常就必须对异常进行处理,否则程序无法通过编译。

         运行时异常:RuntimeException类即其子类都是运行时异常,编译器不会检测的异常,不需要声明。

            ③Throwable常用方法
    Throwable常用方法
    方法声明 功能描述
    String getMessage() 返回此throwable的详细消息字符串
    void printStackTrace() 将此throwable及其追踪输出至标准错误流
    void printStackTrace(PrintStream s) 将此throwable及其追踪输出至指定的输出流
    2、try...catch和finally
    异常捕获:Java中对异常有针对性的语句进行捕获。
    语句:
    try{
          //需要被检测的语句
    }catch(ExceptionType(Exception类及其子类) e) {
          //ExceptionType的处理
    }
    发生异常后继续执行一段程序
    finally{
        //一定会被执行的语句
    }

    示例

    复制代码
     1 public class Example20 {
     2     public static void main(String[] args) {
     3        // 下面的代码定义了一个try...catch语句用于捕捉异常
     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;    //用于结束当前语句
    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 }
    复制代码

    运行结果

    捕获的异常信息是:/by zero
    进入代码块

    在程序设计时,经常会在try...catch后使用finally代码块来完成必须做的事情,例如释放系统资源。需注意,当try...catch中执行了System.exit(0)语句,则退出Java虚拟机,任何代码都不能继续执行。

    try catch finally 组合方式:

    ①try catch :对代码进行异常检测,并对检测的异常传递给catch处理。

           异常捕获处理。
    Void show ()throws {//不需要throws
        try{
             throw new Exception();
        }finally{
        }
    }

    ②try finally:对代码进行异常检测,检测到异常后因为没有catch,所以一样会被默认jvm抛出。

          异常是没有捕获处理的,但是功能所开启资源需要进行关闭,所有finally只为关闭资源。
    Void show () {//需要throws
        try{
             throw new Exception();
        }finally{
        }
    }

    ③try catch finally

           检测异常,并传递给catch 处理,并定义资源释放。

    ④try catch1 catch2 catch3………

    3、throws关键字
    ①throws关键字声明抛出异常的语法格式如下:
       修饰符 返回值类型 方法名([参数1,参数2…])throws ExceptionType1[,ExceptionType2….]{
        }
    ② 声明:将问题标识出来,报告给调用者。
       格式:
    void show ()throws Exception{
         throw new Exception();
    }
            如果函数内通过throw抛出了编译时异常,捕获,那么必须通过throws进行声明,让调用者去处理。
     
    4、自定义异常格式:
    throw Exception 异常对象
           示例
    复制代码
     1 class DivideByMinusException extends Exception{
     2         public DivideByMinusException(){
     3             super();//调用Exception无参的构造方法
     4         }
     5         public DivideByMinusException(String message){
     6             super(message);//调用Exception无参的构造方法
     7         }
     8 }
     9 public class Example26 {
    10     public static void main(String[] args) {
    11         try{
    12             int result = divide(4,-2);
    13             System.out.println(result);
    14         }catch (DivideByMinusException e){
    15             System.out.println(e.getMessage());
    16         }
    17     }
    18     public static int divide(int x,int y)throws DivideByMinusException{
    19         if(y<0){
    20             throw new DivideByMinusException("被除数是负数");
    21         }
    22         int result = x/y ;
    23         return result;
    24     }
    25 } 
    复制代码
     
    六、包的定义与使用
    1、Java 中的包是专门用来存放类的,通常功能相同的类存放在相同的包中。
    如: 
    1 package cn.itcast.chapter04; 
    2 public class Example01 {….} 
    包的声明只能位于Java源文件的第一行
    2、包的导入
    import 包名.类名;
          3、常用的包
           ①java.lang:包含Java语言的核心类,如String、Math、System和Thread类等,使用这个包中的类无需使用import语句导入,系统会自动导入这个包下的所有类。
           ②java.util: 包含Java中大量工具类、集合类等,例如Arrays、List、Set等。
           ③java.net:包含Java网络编程相关的类和接口。
           ④java.io:包含了Java输入、输出有关的类和接口。
     
    七、访问权限修饰符权限:

    访问控制级别

     

    同一类中

    同一包下

    (有无关系均可)

    不同包下(子类)

    不同包下

    (没有关系)

    private

    Y

         

    default(默认)

    Y

    Y

       

    protected

    Y

    Y

    Y

     

    public

    Y

    Y

    Y

    Y

     
  • 相关阅读:
    elinput校验利率输入框
    Schema 和 Universal Link
    Oracle数据库恢复删除数据的方法
    element ui 获取table行索引
    愿有人陪你颠沛流离
    古诗词中爱情的模样
    在细雨中呐喊
    麦田里的守望者
    我打碎了夕阳
    工作笔记
  • 原文地址:https://www.cnblogs.com/lijing5921/p/7112446.html
Copyright © 2020-2023  润新知