Java第七课 继承、权限修饰符、static、this和super、重载和重写、抽象类、接口

一、继承 extends

  1. 子类继承父类:在每一个子类对象中都有独有的父类对象
  2. 继承是一种高级封装
  3. 父类哪些东西不能继承
    • 私有的 private
    • 构造方法
    • 非同包父类受保护类型 protected
  4. 通过访问修饰符和包进行访问权限控制
    好处
    提高代码的复用性。
    类与类之间产生了关系,是多态的前提。
class 父类 { ...     
 }   
class 子类 extends 父类 { ...      
}
/*
 * 定义员工类Employee,做为父类
 * */
class Employee {
    String name; // 定义name属性      
    // 定义员工的工作方法      
    public void work() {      
       System.out.println("尽心尽力地工作");          
     }     
}  
 /*  * 
 * 定义讲师类Teacher 继承 员工类Employee 
 *  */
class Teacher extends Employee{ 
    // 定义一个打印name的方法      
    public void printName() {      
       System.out.println("name=" + name);         
    }      
}  
/*  * 
定义测试类 
*/ 
   public class ExtendDemo01 {
      public static void main(String[] args) {              
            // 创建一个讲师类对象 
           Teacher t = new Teacher();                         
           // 为该员工类的name属性进行赋值 
           t.name = "小明";                         
           // 调用该员工的printName()方法   
           t.printName();// name = 小明                          
           // 调用Teacher类继承来的work()方法           
           t.work();  // 尽心尽力地工作    
      }      
}

二、权限修饰符

项目类内同包不同包子类其他
private
(default)
protected
public

三、static

  • 构造方法<普通代码块<静态代码块
  1. 被static修饰的属性和方法称之为类属性和类方法、无需对象,通过类名就可以调用,所以static违背了面向对象的原则,还会占用大量内存。
  2. 原因:因为JVM在启动时static就会创建,所以不用创建对象,他的存活周期和JVM一样长
  3. 当一个属性或方法使用频次高且当前工程中许多类需要时要用static,否则少用。
  4. 静态方法只能访问静态属性和静态方法

类方法的执行流程

public class Father {
    public int a = 1;
    public static int b = 2;

    static {
        System.out.println("静态代码块");
    }

    public Father() {
        System.out.println("构造代码块");
    }

    {
        System.out.println("普通代码块");
    }
}

public class Test {
    public static void main(String[] args) {
        Father father;
        System.out.println(Father.b);
    }
}

结果

静态代码块
2

public class Test {
    public static void main(String[] args) {
        Father father=new Father();
        System.out.println(father.a);
        System.out.println(Father.b);
        
    }
}

结果

静态代码块
普通代码块
构造代码块
1
2

子类与父类的方法执行流程

public class Father {
    static {
        System.out.println("父类静态代码块");
    }

    public Father() {
        System.out.println("父类构造代码块");
    }

    {
        System.out.println("父类普通代码块");
    }
}
public class Son extends Father {
    static {
        System.out.println("子类静态代码块");
    }

    public Son() {
        System.out.println("子类构造代码块");
    }

    {
        System.out.println("子类普通代码块");
    }
}
public class Test {
    public static void main(String[] args) {
        new Son();
    }
}

结果

父类静态代码块
子类静态代码块
父类普通代码块
父类构造代码块
子类普通代码块
子类构造代码块

四、this和super

  1. super :代表父类的存储空间标识(可以理解为父亲的引用)。
  2. this :代表当前对象的引用(谁调用就代表谁)。
this.成员变量     ‐‐    本类的    
super.成员变量     ‐‐    父类的     
this.成员方法名()   ‐‐    本类的       
super.成员方法名()   ‐‐    父类的

五、重载(overload)和重写(override)

  1. 方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返 回值类型无关。 参数列表:个数不同,数据类型不同,顺序不同。 重载方法调用:JVM通过方法的参数列表,调用不同的方法。
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
  1. 如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。
    方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效 果,也称为重写或者复写。声明不变,重新实现。
public class Person {
    public void show(){
        System.out.println("Person的show方法");
    }
}
public class Teacher extends Person {
    @Override
    public void show(){
        System.out.println("重写Person父类的show方法");
    }
}

测试类

public class Test7 {
    public static void main(String[] args) {
        Teacher teacher=new Teacher();
        teacher.show();
    }
}

结果

重写Person父类的show方法

六、抽象类 abstract

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

子类重写父类的抽象方法,除非子类也是抽象方法。

public class Teacher extends Person {
    @Override
    public void show(){
        System.out.println("重写Person父类的show方法");
    }
}

七、接口 interface

  1. 方法默认为公共的抽象方法(public abstract)
  2. 属性默认为公共的静态的常量(public static
  3. 子类必须实现父接口中所有的抽象方法,除非其子类或接口也是抽象类
    接口和接口之间的继承用extends
  4. 接口不能直接实化
    作用:
    * 同步开发
    * 隐藏实现
    父接口
public interface LiveAble {
    //定义抽象方法
    public abstract void eat();
    public abstract void sleep();
}

实现父接口

public class Animal implements LiveAble {
    @Override
    public void eat() {
        System.out.println("吃东西");
    }

    @Override
    public void sleep() {
        System.out.println("睡觉");
    }
}

测试类

public class InterfaceDemo {
    public static void main(String[] args) {
        //创建子类对象
        Animal animal=new Animal();
        //调用实现后的方法
        animal.eat();
        animal.sleep();
    }
}

结果

吃东西
睡觉

八、多态

  1. 自动类型转换
  • 父类引用指向子类对象
    多态体现的格式:
  1. 强制类型转换
  • 子类类型 变量名 = (子类类型) 父类变量名
  1. . 继承或者实现【二选一】
  2. 方法的重写【意义体现:不重写,无意义】
  3. 父类引用指向子类对象【格式体现】 一个父类有多个子类,在构建方法时以父类的引用作为参数,在调用方法时,传入不同子类对象实现

定义父类:

public abstract class Animal {    
   public abstract void eat();  
} 

定义子类:

class Cat extends Animal {       
      public void eat() {  
          System.out.println("吃鱼");     
      }   
}    
class Dog extends Animal {       
      public void eat() {  
           System.out.println("吃骨头");      
      }
}

定义测试类:

public class Test {    
    public static void main(String[] args) {             
     // 多态形式,创建对象        
     Animal a1 = new Cat();          
     // 调用的是 Cat 的 eat         
     a1.eat();                     
     // 多态形式,创建对象         
     Animal a2 = new Dog();          
     // 调用的是 Dog 的 eat         
     a2.eat();                   
     }
}

多态的好处

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展 性与便利。代码如下:

定义父类

public abstract class Animal {       
      public abstract void eat();   
} 

定义子类:

class Cat extends Animal {      
      public void eat() {              
      System.out.println("吃鱼");       
     }  
}       
class Dog extends Animal {     
      public void eat() {           
         System.out.println("吃骨头");      
      }   
}

定义测试类:

在这里插入代码片
public class Test {     
      public static void main(String[] args) {         
             // 多态形式,创建对象         
             Cat c = new Cat();           
             Dog d = new Dog();            
             // 调用showCatEat          
             showCatEat(c);       
             // 调用showDogEat 
             showDogEat(d);            
             /*        
             以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代        
             而执行效果一致         
             */         
             showAnimalEat(c);         
             showAnimalEat(d);
            }       
      public static void showCatEat (Cat c){         
              c.eat();     
        }       
      public static void showDogEat (Dog d){        
             d.eat();     
       }       
      public static void showAnimalEat (Animal a){        
             a.eat();     
       } 
}

由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当 然可以把Cat对象和Dog对象,传递给方法。
当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致, 所以showAnimalEat完全可以替代以上两方法。 不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用 showAnimalEat都可以完成。
所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。

转型的异常

public class Test {     
       public static void main(String[] args) {         
              // 向上转型           
              Animal a = new Cat();           
              a.eat(); // 调用的是 Cat 的 eat          
              // 向下转型           
              Dog d = (Dog)a;                
              d.watchHouse();// 调用的是 Dog 的 watchHouse 【运行报错】     
             }   
 }

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了 Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。 为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

//如果变量属于该数据类型,返回true。 如果变量不属于该数据类型,返回false
变量名 instanceof 数据类型  

所以,转换前,我们好先做一个判断,代码如下:

public class Test {     
     public static void main(String[] args) {         
          // 向上转型           
          Animal a = new Cat();           
          a.eat();  // 调用的是 Cat 的 eat           
         // 向下转型           
          if (a instanceof Cat){             
          Cat c = (Cat)a;                    
          c.catchMouse(); // 调用的是 Cat 的 catchMouse         
          } else if (a instanceof Dog){            
          Dog d = (Dog)a;                    
           d.watchHouse(); // 调用的是 Dog 的 watchHouse         
          }     
}   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值