第八讲

Java语言基础第八讲

一.代码块的概述和分类

  • 概述
    • 在Java中使用{}括起来的代码被称为代码块.
  • 代码块分类 :
    • 根据位置和声明不同,分为局部代码块,构造代码块,静态代码块,同步代码块(多线程学).
  • 常见代码块的应用

    • 局部代码块—在方法中出现,限定生命周期,及早释放,提高内存利用率.
    • 构造代码块—在类中方法外出现,多个构造方法中相同的代码存放在一起,每次调用构造都执行,并且优先于构造方法执行.
    • 静态代码块—在类中方法外出现,并用static 修饰,用于给类进行初始化,在加载的时候就执行(即在加载主类的时候调用一次),并且优先于构造方法执行,一般用于加载驱动.

      class Demo_Code {
          public static void main(String[] args) {
              {
                  int x = 10;             //局部代码块,定义在一对{}之内,用来限定代码生命周期
                  System.out.println(x);
              }
      
              Student s = new Student();
              System.out.println("-----------------");
              Student s1 = new Student("张撒",23);
          }
          static {                        //主方法的静态代码块优先于主方法执行
              System.out.println("主方法的静态代码块");
          }
      }
      
      class Student {
      
          private String name;
          private int age;
      
          public Student() {
              study();
              System.out.println("空参构造");
          }
      
          public Student(String name,int age) {
              this.name = name;
              this.age = age;
              study();
              System.out.println("有参构造");
          } 
      
          public void setName(String name) {
              this.name = name;
          }
          public String getName() {
              return name;
          }
              public void setAge(int age) {
              this.age = age;
          }
          public int getAge() {
              return age;
          }
      
          public void study() {
              System.out.println("学生学习");
          }
          {                       //构造代码块,类中方法外
                                  //每创建一次对象,就执行一次,优先于构造方法执行
              System.out.println("构造代码块");
          }
          static {                //静态代码块,类中方法外,随着类的加载而加载,只执行一次
                                  //用来给类初始化
              System.out.println("主方法的静态代码块");
          }
      }
      
  • 面试题:看程序,写结果

    class Test2_Student {
        public static void main(String[] args) {
            System.out.println("我是main方法");     
    
            Student s1 = new Student();
            Student s2 = new Student();
        }
        static {            
            System.out.println("Demo2_Student静态代码块");   
        }
    }
    
    class Student {
        static {            
            System.out.println("Student 静态代码块");
        }
    
        {       
            System.out.println("Student 构造代码块");
        }
    
        public Student() {      
            System.out.println("Student 构造方法");
        }
    }
    
    
    /*执行结果:
    Demo2_Student静态代码块          //优先于主方法执行
    我是main方法
    Student 静态代码块
    Student 构造代码块
    Student 构造方法
    Student 构造代码块
    Student 构造方法
    */
    

二.继承的概述

  • 继承(extends)概念 :
    • 让类与类之间产生关系,子父类关系
  • 继承的好处和弊端:
    • 好处—-
      • 1.提高了代码的复用性.
      • 2.提高了代码的可维护性.
      • 3.让类与类之间产生关系,是多态的前提;
    • 弊端—- 类的耦合性增强了
  • 开发的原则:
    • 高内聚(内聚指的是自己完成一件事的能力);
    • 低耦合(耦合指的是类与类的关系).
  • 继承案例演示:

    • 动物类,猫类,狗类
    • 定义两个属性(颜色,腿的个数)两个功能(吃饭,睡觉)

      class Demo1_Extends {
          public static void main(String[] args) {
              Cat c = new Cat();
              c.color = "花";
              c.leg = 4;
              c.eat();
              c.sleep();
       
              System.out.println(c.leg  + "..." + c.color);
          }
      }
      class Animal {
          String color;                   //动物的颜色
          int leg;                        //动物腿的个数
       
          public void eat() {             //吃饭的功能
              System.out.println("吃饭");
          }
       
          public void sleep() {           //睡觉的功能
              System.out.println("睡觉");
          }
      }
       
      class Cat extends Animal {
      
      }
       
      class Dog extends Animal {
      
      }
       
      /*
      extends是继承的意思
      Animal是父类
      Cat和Dog都是子类
      */
      
  • Java中类的继承特点

    • java中只支持单继承,不支持多继承;(一个儿子只能有一个人亲爹).
    • java中支持多层继承(继承体系);

      • 如果想用这个体系的所有功能,用底层的类创建对象;
      • 如果想用这个体系的共性功能,看最顶层的类.

        //多层继承,B继承A,C继承B.
        class Demo2_Extends {
            public static void main(String[] args) {
                DemoC d = new DemoC();
                d.show();
            }
        }
        class DemoA {
            public void show() {
                System.out.println("DemoA");
            }
        }
         
        class DemoB extends DemoA {
            public void method() {
                System.out.println("DemoB");
            }
        }
         
        class DemoC extends DemoB {
            public void print() {
                System.out.println("DemoC");
            }
        }
        
  • 继承的注意事项:
    • 子类只能继承父类所有非私有的成员(成员变量和成员方法);
    • 子类不能继承父类的构造方法,但是可以通过 super 关键字来访问父类构造方法;
    • 不能为了部分功能去继承.
  • 什么时候使用继承?
    • 继承其实体现的是一种关系” is a “.
  • 继承中成员变量的关系

    • 同名变量
    • 不同名变量

      //同名和不同名变量
      class Demo4_Extends {
          public static void main(String[] args) {
              Son s =  new Son();
              s.print();
          }
      }
      class Father {
          int num1 = 10;
          int num2 = 30;          //先演示的时候,不加此处的num2
      }
      class Son extends Father {
          int num2 = 20;
          public void print(){
              System.out.println(num1);
              System.out.println(num2);       //num = 20,就近原则
          }
      }
      

三.this 和 super 的区别以及应用场景

  • this 和 super 分别代表什么.
    • this 代表的是当前对象的引用,谁来调用我,我就代表谁;
    • super 代表当前对象父类的引用.
  • this和super的区别:

    • 调用成员变量.
      • this.成员变量,调用本类中成员变量,也可以调用父类的成员变量
      • super.成员变量,调用父类的成员变量.
    • 调用成员方法
      • this.成员方法,调用本类的成员方法,也可以调用父类的成员方法.
      • super.成员方法,调用父类的成员方法.
    • 调用构造方法

      • this(…) 调用本类的构造方法;
      • super(…) 调用父类的构造方法.

        class Demo4_Extends {
            public static void main(String[] args) {
                Son s = new Son();
                s.print();
            }
        }
        
        class Father {
            int num1 = 10;
            int num2 = 30;
        }
         
        class Son extends Father {
            int num2 = 20;
         
            public void print() {
                System.out.println(this.num1);              //this既可以调用本类的,也可以调用父类的(本类没有的情况下)
                System.out.println(this.num2);              //就近原则,子类有就不用父类的了
                System.out.println(super.num2);
            }
        }
        
  • 继承中构造方法的关系

    • 子类中所有构造方法默认都会访问父类中的空参构造方法.
      • 原因—-因为子类会继承父类的数据,可能还会使用父类的数据,所以子类在初始化之前,一定要先完成父类数据的初始化.
    • 其实,每一个构造方法的第一条语句默认都是super() object 类最顶层的父类.

      class Demo5_Extends {
          public static void main(String[] args) {
              Son s = new Son();
          }
      }
      class Father extends Object {
          public Father() {
              //super();
              System.out.println("Father 的构造方法");
          }
      }
       
      class Son extends Father {
          public Son() {
              //super();                          //这是一条语句,如果不写,系统会默认加上,用来访问父类中的空参构造
              System.out.println("Son 的构造方法");
          }
      }
      

四.继承中构造方法的注意事项

  • 父类没有无参构造方法,子类怎么办?
    • super解决:用super(….)显式调用父类的有参构造,如:super(name,age);
    • this解决:通过this调用本类的有参构造,然后在本类的有参构造里,又调用了父类的有参构造,相当于间接调用父类的有参构造.
  • 注意事项

    • super(…)或者this(….)必须出现在构造方法的第一条语句上,只能出现其一
    • super和this两个关键字可以共存,但this和super语句不能共存.

      class Demo6_Extends {
          public static void main(String[] args) {
              Son s1 = new Son();
              System.out.println(s1.getName() + "..." + s1.getAge());
              System.out.println("--------------------");
              Son s2 = new Son("张三",23);
              System.out.println(s2.getName() + "..." + s2.getAge());
          }
      }
      class Father {
          private String name;            //姓名
          private int age;                //年龄
       
          public Father() {               //空参构造
              System.out.println("Father 空参构造");
          }
       
          public Father(String name,int age) {    //有参构造
              this.name = name;
              this.age = age;
              System.out.println("Father 有参构造");
          }
       
          public void setName(String name) {  //设置姓名
              this.name = name;
          }
       
          public String getName() {           //获取姓名
              return name;
          }
       
          public void setAge(int age) {       //设置年龄
              this.age = age;
          }
       
          public int getAge() {               //获取年龄
              return age;
          }
      }
       
      class Son extends Father {
          public Son() {                      //空参构造
              this("王五",25);              //本类中的构造方法
              //super("李四",24);               //调用父类中的构造方法
      
              System.out.println("Son 空参构造");
          }
       
          public Son(String name,int age) {   //有参构造
              super(name,age);
              System.out.println("Son 有参构造");
          }
      }
      
  • 继承中的面试题

    //案例一
    class Fu{
        public int num = 10;
        public Fu(){
            System.out.println("fu");
        }
    }
    class Zi extends Fu{
        public int num = 20;
        public Zi(){
            //super();
            System.out.println("zi");
        }
        public void show(){
            int num = 30;
            System.out.println(num);
            System.out.println(this.num);
            System.out.println(super.num);
        }
    }
    class Test1_Extends {
        public static void main(String[] args) {
            Zi z = new Zi();
            z.show();
        }
    }
    
    
    //案例二:
    
        1,jvm调用了main方法,main进栈,因为子要使用父类的东西,所以父类要先加载
        2,遇到Zi z = new Zi();会先将Fu.class和Zi.class分别加载进内存,再创建对象,当Fu.class加载进内存
        父类的静态代码块会随着Fu.class一起加载,当Zi.class加载进内存,子类的静态代码块会随着Zi.class一起加载
        第一个输出,静态代码块Fu,第二个输出静态代码块Zi
        3,走Zi类的构造方法,因为java中是分层初始化的,先初始化父类,再初始化子类,所以先走的父类构造,但是在执行
        父类构造时,发现父类有构造代码块,构造代码块是优先于构造方法执行的所以
        第三个输出构造代码块Fu,第四个输出构造方法Fu
        4,Fu类初始化结束,子类初始化,第五个输出的是构造代码块Zi,构造方法Zi
        */
    
    class Test2_Extends {
        public static void main(String[] args) {
            Zi z = new Zi();
        }
        /*
    
    }
    class Fu {
        static {
            System.out.println("静态代码块Fu");
        }
     
        {
            System.out.println("构造代码块Fu");
        }
     
        public Fu() {
            System.out.println("构造方法Fu");
        }
    }
     
    class Zi extends Fu {
        static {
            System.out.println("静态代码块Zi");
        }
     
        {
            System.out.println("构造代码块Zi");
        }
     
        public Zi() {
            System.out.println("构造方法Zi");
        }
    }
    

五.继承中成员方法的关系

  • 不同名的方法:直接调用就可以
  • 同名的方法:称为方法的重写,用子类对象直接调用的是子类已经重写的方法    

    • 要想调用父类的方法,可以在子类重写的方法中添加super();

      class Demo7_Extends {
          public static void main(String[] args) {
              Son s = new Son();
              s.print();
              s.method();
          }
      }
      class Father {
          public void print() {
              System.out.println("Fu print");
          }
      }
       
      class Son extends Father {
          public void method() {
              System.out.println("Zi Method");
          }
       
          public void print() {
              super.print();                          //super可以调用父类的成员方法
              System.out.println("Zi print");
          }
      }
      

六.方法重写(override)的概述与应用

  • 什么是方法重写
    • 重写指的是子父类出现了一模一样的方法.(返回值类型可以子父类,这个得要学完面向对象中讲)
  • 方法重写的应用
    • 当子类需要父类的功能,而功能主体子类有自己特有的内容时,可以重写父类中的方法,这样既延续了父类的功能,有定义了子类特有的内容.
  • 方法重写的注意事项:
    • 父类中私有方法不能被重写(因为父类私有方法子类根本就无法继承)
    • 子类重写父类方法时,子类方法的访问权限不能小于父类的访问权限;
    • 静态只能覆盖静态,不能覆盖非静态,非静态也不能覆盖静态.
  • 重写与重载的区别:
    • 重写(override)指的是子父类出现了一么一样的方法,与返回值类型有关,自子父类返回值类型是一致的.
    • 重载(overland)指的是在同一个类中,方法名相同,参数列表不同,与返回值类型无关.
    • 子类对父类调用方法的时候:
    • 先找子类本身,再找父类.
  • 使用继承后的学生和老师的案例

    • 属性:姓名,年龄;
    • 行为:吃饭.
    • 老师特有的方法:讲课
    • 学生特有的方法:学习

      class Demo_Person {
          public static void main(String[] args) {
          Student s = new Student("小明",12);
          System.out.println("姓名是:" + s.getName() + ",年龄是:" + s.getAge());
          s.study();
          }
      }
      
      class Person {
          private String name;
          private int age;
      
          public Person() {}
      
          public Person(String name,int age) {
              this.name = name;
              this.age = age;
          }
          public void setName(String name) {
              this.name = name;   
          }
          public String getName() {
              return name;
          }
          public void setAge(int age) {
              this.age = age;
          }
          public int getAge() {
              return age;
          }
      
          public void eat() {
              System.out.println("吃饭");
          }
      }
      
      class Teacher extends Person {
      
          public Teacher() {}
          public Teacher(String name,int age) {
              super(name,age);
          }
          public void teach() {
              System.out.println("老师讲课");
          }
      }
      class Student extends Person {
      
          public Student() {}
          public Student(String name,int age) {
              super(name,age);
          }
          public void study() {
              System.out.println("学生学习");
          }
      }
      
  • 猫狗类型案例.

    • 猫狗案例继承版
    • 属性:毛的颜色,腿的个数
    • 行为:吃饭
    • 猫特有行为:抓老鼠catchMouse
    • 狗特有行为:看家lookHome

      class Demo_Animal {
          public static void main(String[] args) {
              Cat c = new Cat("黄",4);
              System.out.println(c.getColor() + "---" + c.getLeg());
              c.eat();
              c.catchMouse();
              System.out.println("-----------");
      
              Dog d = new Dog("黑",4);
              System.out.println(d.getColor() + "---" + d.getLeg());
              d.eat();
              d.lookHome();
          }
      }
      class Animal {
          private String color;
          private int leg;
      
          public Animal() {}
      
          public Animal(String color,int leg) {
              this.color = color;
              this.leg = leg;
          }
          public void setColor(String color) {
              this.color = color; 
          }
          public String getColor() {
              return color;
          }
          public void setLeg(int leg) {
              this.leg = leg;
          }
          public int getLeg() {
              return leg;
          }
          public void eat() {
              System.out.println("吃饭");
          }
      }
      
      class Dog extends Animal {
      
          public Dog() {}
          public Dog(String color,int leg) {
              super(color,leg);
          }
          public void eat() {
              System.out.println("狗吃肉");
          }
          public void lookHome() {
              System.out.println("看家");
          }
      }
      
      class Cat extends Animal {
      
          public Cat() {}
          public Cat(String color,int leg) {
              super(color,leg);
          }
              public void eat() {
              System.out.println("猫吃鱼");
          }
          public void catchMouse() {
              System.out.println("抓老鼠");
          }
      }
      

七.final关键字概述及其特点.

  • final 概述: 用于修饰类变量,变量,方法,是”最终”的意思.
  • final的特点
    • final修饰的类不能被继承
    • final修饰的方法不能被子类重写
    • final修饰的变量都是常量,只能赋值一次.
  • 常量命名规范:如果是一个单词,所有字母大写,如果是多个单词,每个单词都大写,中间用下划线隔开

        class Demo1_Final {
            public static void main(String[] args) {
                Son s = new Son();
                s.print();
            }
        }
        final class Father {        //final修饰的类不能被继承
            public void print() {
                System.out.println("访问底层数据资源");
            }
        }
         
        class Son extends Father {
            final int NUM = 10; 
            public static final double P1 = 3.14;   //final修饰变量叫做常量,一般会与public static共用
            public void print() {
                NUM = 20;
                System.out.println(NUM);
            }
        }
    
  • final修饰局部变量:

    • 基本数据类型,值不能改变
    • 引用数据类型,地址不能改变,但是地址所指向的对象的属性可以改变

      class Demo2_Final {
          public static void main(String[] args) {
              final int num = 10;         //基本数据类型,值不能改变
              num = 20;
              System.out.println(num);
       
              final Person p = new Person("张三",23);
              p = new Person("李四",24);        //引用数据类型,地址不能改变,但是地址所指向的对象的属性可以改变 
              p.setName("李四");
              p.setAge(24);
       
              System.out.println(p.getName() + "..." + p.getAge());
       
              method(10);
              method(20);
          }
       
          public static void method(final int x) {
              System.out.println(x);
          }
      }
      
  • final修饰变量的初始化时机

    • 显示初始化 
    • 在对象构造完毕前即可

      class Demo3_Final {
          public static void main(String[] args) {
              Demo d = new Demo();
              d.print();
          }
      }
      class Demo {
              //final int num = 10;           //表示显式初始化
          final int num;                      //成员变量的默认初始化值是无效值,因为final修饰的变量只能被赋值一次,
                                              //所以会特别珍惜这次赋值,所以系统的默认初始化值是无效的
      
          public Demo() {
              num = 10;
          }
          public void print() {
              System.out.println(num);
          }
      }   
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值