Java中的代码块和继承

代码块

代码块分类:
     1.代码块:限制变量的作用域(生命周期)
       书写位置:在方法中
     2.构造代码块(在开发中 很少使用)
       书写位置: 在类中 方法
       调用时机: 如果你有构造代码块 系统会帮你调用
                 帮你在创建对象之前调用 每次创建对象 都会调用
     3.静态代码块(一定是被static修饰的)
       静态代码块 依赖类 随着类的加载而加载
       注意: 只加载一次(系统只调用一次 不管你创建了多少对象)
       应用场景: 加载驱动(数据库驱动 JDBC)
     4.同步代码块(多线程)

     例如:
     public static void main(String[] args) {
        /*
        {
            System.out.println("我是局部代码块");
        }
        */

        Person person = new Person();
        person.setName("吴彦祖");
        person.setAge(18);
        person.sayHi();

        Person person2 = new Person("吴奇隆",18);
        person2.sayHi();

    }

}
/*
 * 人名 年龄 
 * set/get 有参无参构造
 * 
 */
    class Person{
        private String name;
        private int age;    

        static {
            System.out.println("我是Person类的静态代码块");
        }

        {
            //比如 我每个对象 都会调用同一个方法 这时候可以使用
            this.sleep();
            System.out.println("我是构造代码块");
        }

        //构造
        public Person(){
            System.out.println("我是无参数的构造方法");
        }

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
            System.out.println("我是有参的构造方法");
        }

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;       
        }

        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }

        //介绍
        public void sayHi() {
            System.out.println(name + " " + age);
        }

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

继承

继承特点:
        1.减少你的代码量
        2.让类与类之间 产生关联(产生 父与子的关系)

        继承使用的关键字:extends

    继承的弊端:
        1.继承时 可以把多个类中 相同的功能或方法抽取出来
        重新构造一个类出来 把这些类 建立继承关系

        2.建立继承关系的同时 一定要符合逻辑(切记不要为了继承而继承)
        注意: 如果是继承关系 一定符合 什么是什么(项目经理 是员工 子类 是 父类)

        继承的写法:
        class 子类 extends 父类{

        }

        例如:
        public static void main(String[] args) {
        // 创建一个猫
        // 子类继承了父类 方法和属性
        Cat cat = new Cat();
        cat.name = "大咪";        
        System.out.println(cat.name);
        cat.kind = "中华田园";
        System.out.println(cat.kind);
        cat.color = "白色";
        System.out.println(cat.color);
        cat.catechMice();
        cat.sleep();
    }



    //猫类
    //姓名 颜色 种类 会睡觉 会抓老鼠
    //狗类 
    //姓名 颜色 种类 会睡觉 会啃骨头

    //抽取出 相同部分 组成 动物类

    class Animal{
        String name;
        String color;
        String kind;

        //睡觉
        public void sleep() {
            System.out.println("会睡觉");
        }
    }

    class Cat extends Animal{

        //抓老鼠
        public void catechMice() {
            System.out.println("抓老鼠");
        }

    }

    class Dog extends Animal{

        //啃骨头
        public void chewBones() {
            System.out.println("啃骨头");
        }

    }

Java中的继承

注意:
        1.Java 只允许单继承(多继承可以使用借口来间接实现)
        2.Java中 允许 多层继承(爷爷 父亲 儿子 孙子 重孙...)

        Java中 最顶层的父类(最基础的类) Object类
        如果我这个类 没有写 继承哪个父类 默认就是继承Object类


        1. 如果我要使用 这些类中 共有方法(属性)
        创建当前继承中 最顶端类 去使用

        2. 如果我要使用 这些类中 特有方法(属性)
        创建当前继承中 最末端的 类 去使用

    //A类 是 爷爷类 B类是父亲类 C类是 孙子类
    //A类中 有name  C类中 会叫爷爷


        class A{
            String name;
        }

        class B extends A{

        }

        class C extends B{
            public void call() {
                System.out.println("会叫爷爷");
            }
        }

构造方法能否被继承

构造方法能被继承么?

    答案是 构造方法不能被继承

    例如:

            public static void main(String[] args) {
                Son son = new Son();
                son.name = "儿子";
                son.sayHi();
                System.out.println("-------------");
                //有参构造创建对象
                Son son2 = new Son("小明");
                son2.sayHi();
            }
        }


        class Father{
            String name;
            //无参 有参 构造方法
            public Father(){
                System.out.println("我是爸爸类无参的构造方法");
            }
            public Father(String name) {
                this.name = name;
                System.out.println("我是爸爸有参的类构造方法");
            }

            public void sayHi() {
                System.out.println(name);
            }
        }


        class Son extends Father{
            //无参的
            public Son(){
                //如果你这里没有在子类构造方法中 调用父类的构造方法
                //系统会默认给你的子类构造方法中 添加一行代码
                super();// 调用 父类的 无参构造方法
                // super  相当于 父类的对象
                System.out.println("我是Son类无参的构造方法");
            }
            public Son(String name) {
                super();// 系统帮你默认调用父类的构造方法
                this.name = name;
                System.out.println("我是Son类有参的构造方法");
            }
        }

    为了保证继承完整性 在你创建子类对象的时候
    如果你不调用父类的构造方法 那么
    系统会默认帮你去调用 父类的无参构造方法

关键字 super 和 this

super 关键字
    super 代表的时: 父类的对象

    super调用对象  super.对象
         调用方法  super.方法

    super(); 调用的父类无参构造方法
    this();  调用的本类构造方法

    例如:

        public static void main(String[] args) {
            TestB b = new TestB();
            b.fun();
        }


    class TestA{
        int num1 = 10;
        int num2 = 20;
    }

    class TestB extends TestA{
        int num1 = 30;

        public void fun() {
            // 使用 this时 会先在本类中 寻找该属性
            // 没找到 就去父类中寻找
            System.out.println(this.num1);//30
            System.out.println(this.num2);//20
            System.out.println(super.num1);//10
        }
    }

如果父类没有无参构造方法怎么办?

如果父类没有无参构造方法怎么办?

    例如:
            class Phone{
            String name;

            //无参
        //  public Phone() {
        //      
        //  }

            //有参
            public Phone(String name) {
                this.name = name;
            }
        }

                class MI extends Phone{

            //无参
            public MI() {
                // 子类的构造方法中 如果你什么都不写 会 默认调 父类无参的构造方法
                // 如果 父类 没有无参的构造方法 
                // 就证明 父类当中 一定有 有参的构造方法
                // 无论有参 还是无参 在子类 的 构造方法中 
                // 必须 要 调用一个 必须手动指定一个有参的构造方法去调用
                super("Note2");
            }
            //有参
            public MI(String name) {
                super(name);
                this.name = name;
            }
        }

    建议: 不管是父类 还是子类 构造方法 一定要 写全 避免 出现问题

方法的重写

父类 和 子类 的方法 能不能重名?

    是可以的

    这样叫做 方法的重写

    注意:
        1.方法声明完全一致的时候 叫方法的重写
        2.方法的重写 建立在类与类之间有继承关系(子类 重写 父类 的 方法)

        例如:
        public static void main(String[] args) {
            IOS8 ios8 = new IOS8();
            ios8.siri();

            //如果直接打印对象 相当于 系统会帮你
            //在打印时 调用 toString方法
            System.out.println(ios8);
            System.out.println(ios8.toString());
        }
    }

        class IOS7{
            public void call() {
                System.out.println("打电话");
            }

            public void siri() {
                System.out.println("说英文");
            }
        }

        class IOS8 extends IOS7{

            @Override // 注解 标识这个方法是重写父类方法
            public void siri() {
                //调不调父类的方法 要根据实际情况 
                super.siri();
            }

            /*
            // 方法的重写: 对父类的方法 进行一个 功能上的 升级
            public void siri() {
                //中英文都会说
                super.siri();//调用父类的方法
                System.out.println("会说中文");

            }
            */

            // 重写 toString()方法
            // 利用tostring方法 来写 介绍自己的方法
            @Override
            public String toString() {

                return "哈哈";
            }
        }

当成员变量用 private修饰的时候 成员变量还能继承么?

当成员变量用 private修饰的时候 成员变量还能继承么?

    例如:
            public static void main(String[] args) {
                Student student = new Student("苏茜孟", 21, 17120404);
                System.out.println(student);
            }


        class People{
            //继承中 private 修饰的 变量 是不能直接访问的
            private String name;
            private int age;

            //构造方法
            public People(){

            }

            public People(String name, int age) {
                this.name = name;
                this.age = age;
            }

            //set/get方法
            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            public int getAge() {
                return age;
            }

            public void setAge(int age) {
                this.age = age;
            }

            public void eat() {
                System.out.println("吃饭");
            }

            //介绍自己
            @Override
            public String toString() {
                return "姓名: " + name + " " + "年龄: " + age + " ";
                }
        }

        class Teacher extends People{

            public Teacher() {

            }

            public Teacher(String name, int age) {
                super(name, age);
            }

            public void teach() {
                System.out.println("教书");
            }

            @Override
            public String toString() {
                return super.toString();
            }
        }

        class Student extends People{

            //学号
            private int id;

            //构造方法
            public Student() {

            }

            public Student(String name, int age, int id) {
                // 直接调用父类的 构造方法 完成初始化
                // 为了保证继承的完整性 在子类构造方法中
                // 第一行 必须 调用 父类的 构造方法(无参 有参 都行)
                super(name, age);
                // 特有属性 直接 赋值就行
                this.id = id;
            }

            public void study() {
                System.out.println("学习");
            }

            //介绍自己的方法
            @Override
            public String toString() {
                //可以在 父类的基础上 添加自己特有的属性 去打印
                return super.toString() + "学号: " + id;
            }
        }

                                                                  Day.10