JAVA学习笔记04——继承与多态

继承与多态

1.继承
基本语法:
public class 子类名称 extends 父类名称{…}

成员变量访问特点:
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找
间接通过成员方法访问成员变量:
方法属于谁,就优先用谁,没有则向上找

成员方法访问特点:
创建的对象是谁,就优先用谁,如果没有则向上找

构造方法访问特点:
1.子类构造方法当中有一个默认隐含的super()调用,所以一定先调用父类构造,再执行子类构造
2.子类构造可以通过super关键字来调用父类构造。
3.super的父类构造调用,必须是子类构造的第一条语句。

super关键字用法:
1.在子类的成员方法中,访问父类的成员变量
2.在子类的成员方法中,访问父类的成员方法
3.在子类的构造方法中,访问父类的构造方法

public class son extends father{
    
    
    public son(){
    
    
        super();
        System.out.println("子类构造方法");
    }

    public void method(){
    
    
        System.out.println(super.num);
        super.method();
    }
}

this关键字用法:
1.在本类的成员方法中,访问本类的成员变量
2.在本类的成员方法中访问另一个成员方法
3.在本类的构造方法中访问另一个构造方法

JAVA继承特征:
1.JAVA是单继承
2.JAVA可以多级继承

2.抽象
抽象方法语法:
public abstract void 方法名();
抽象方法所在的类必须是抽象类
语法:
public abstract class 类名{}

public abstract class Person {
    
    
    public abstract void method();
}

抽象类与抽象方法:
1.不能直接创建抽象类对象
2.必须用一个子类继承抽象父类
3.子类必须覆盖重写父类所有抽象方法
4.抽象类中可以有构造方法,是供子类创建对象时,初始化父类成员使用的
5.抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类

public abstract class father {
    
    
    public abstract void method();
}
public class son extends father{
    
    
    @Override
    public void method() {
    
    
        System.out.println("这是一个子类方法");
    }
}

3.接口
一种公共规范的标准,多个类的公共规范。
接口是一种引用数据类型,最重要的是抽象方法
语法:
public interface 接口名称{}

抽象方法:
public abstract 返回值类型 方法名称(参数列表);
注意:
1.接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
2.这两个关键字可以省略

使用:
1.接口不能直接使用,必须有一个实现类来实现该接口
public class 实现类名称 implements 接口名称{}
2.接口的实现类必须覆盖重写接口中所有的抽象方法
实现:去掉abstract关键字,加上方法体大括号
3.创建实现类的对象进行使用

public interface MyInterfaceAbstract {
    
    
    public abstract void methodAbs();   //接口抽象方法的定义
}

public class MyInterfaceAbstractImpl implements MyInterfaceAbstract{
    
    
    @Override
    public void methodAbs() {
    
    
        System.out.println("这是一个方法");   //重写接口的抽象方法
    }
}
public class demo01Interface {
    
    
    public static void main(String[] args) {
    
    
        MyInterfaceAbstractImpl impl=new MyInterfaceAbstractImpl();
        impl.methodAbs();   //创建对象实现抽象方法
    }
}

默认方法
语法:
public default 返回值类型 方法名称(参数列表){}
1.接口的默认方法可以通过接口实现类对象直接调用
2.接口的默认方法可以被接口实现类进行覆盖重写

public interface MyInterfaceDefault {
    
    
    public abstract void methodAbs();
//    public abstract void methodAbs2();  //新增抽象方法
    public default void methodDefault(){
    
    
        System.out.println("这是新添加的默认方法");
    }
}
public class MyInterfaceDefaultA implements MyInterfaceDefault{
    
    
    @Override
    public void methodAbs() {
    
    
        System.out.println("实现抽象方法A");
    }
}
public class MyInterfaceDefaultB implements MyInterfaceDefault{
    
    
    @Override
    public void methodAbs() {
    
    
        System.out.println("实现抽象方法B");
    }

    @Override
    public void methodDefault() {
    
    
        System.out.println("这是B重写默认方法");    //覆盖重写
    }
}

public class demo02Interface {
    
    
    public static void main(String[] args) {
    
    
        MyInterfaceDefaultA a=new MyInterfaceDefaultA();
        a.methodAbs();
        a.methodDefault();  //调用默认方法
        MyInterfaceDefaultB b=new MyInterfaceDefaultB();
        b.methodDefault();  //调用重写默认方法
    }
}

静态方法
语法:
public static 返回值类型 方法名称(参数列表){}
注意事项:
1.不能通过接口实现类的对象来调用接口当中的静态方法
2.通过接口名称直接调用静态方法

public interface MyInterfaceStatic {
    
    
    public static void methodStatic(){
    
    
        System.out.println("这是一个静态方法");
    }
}
public class demo03Interface {
    
    
    public static void main(String[] args) {
    
    
        MyInterfaceStatic.methodStatic();
    }
}

私有方法
解决多个静态方法之间重复代码
普通私有方法:
private 返回值类型 方法名称(参数列表){}
静态私有方法:
private static 返回值类型 方法名称(参数列表){}

public interface MyInterfacePrivateA {
    
    
    public default void MethodDefault1(){
    
    
        System.out.println("这是默认方法1");
        methodCommon();
    }
    public default void MethodDefault2(){
    
    
        System.out.println("这是默认方法2");
        methodCommon();
    }
    private void methodCommon(){
    
    
        System.out.println("默认方法");
    }
}

接口的常量
接口当中也可以定义成员变量,但是必须使用public static final三个关键字进行修饰
从效果上看,这其实就是接口的常量
语法:
public static final 数据类型 常量名称=数据值;
注意:
1.接口当中的常量可以省略public static final关键字
2.接口当中的常量必须赋值
3.接口中常量名称使用完全大写,用下划线分隔

使用:
接口名称.常量名称

public interface MyInterfaceConst {
    
    
    public static final int NUM_My_Class=10;
}

多个接口
语法:
public class 类名称 implements 接口1,接口2{}
如果多个接口中存在重名的抽象方法,重写一次即可
如果实现类没有重写所有抽象方法,则实现类是一个抽象类
如果多个接口中存在重复的默认方法,那么实现类一定要对冲突的默认方法进行重写
一个类如果父类与接口当中的方法重名冲突,那么优先父类的方法

接口多继承
1.类与类之间单继承,直接父类只有一个
2.类与接口之间是多实现的,一个雷可以实现多个接口
3.接口与接口之间多继承
注意:
1.多个父接口当中的抽象方法如果重复,并无问题
2.多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,并且必须带default关键字

4.多态
语法:
父类名称 对象名=new 子类名称();
接口名称 对象名=new 实现类名称();

public class Father {
    
    
    public void method(){
    
    
        System.out.println("父类方法");
    }
}
public class Son extends Father{
    
    
    public void method(){
    
    
        System.out.println("子类方法");
    }
}
public class Demo01Multi {
    
    
    public static void main(String[] args) {
    
    
        Father obj=new Son();
        obj.method();   //子类方法
    }
}

访问成员变量的两种方式:
1.直接通过对象名访问成员变量:等号左边是谁优先用谁,没有则向上查找
2.间接通过成员方法访问成员变量:该方法属于谁优先用谁,没有则向上查找

成员方法访问的方式:
new的哪个类名,就有限用谁,没有则向上查找
成员变量:编译看左,运行看左
成员方法:编译看左,运行看右

如何才能知道一个父类的引用对象本来是什么子类?
语法:
对象 instanceof 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例

5.final关键字
1.修饰类
当前这个类不能有任何子类
public final class 类名称(参数列表){}
2.修饰方法
当前这个方法不能被覆盖重写
public final 返回值 方法名称(参数列表){}
3.修饰局部变量
变量不可改变
final 变量类型 变量名称=值;
对于基本类型来说,不可变说的是变量当中的数据不可改变
对于引用类型来说,不可变说的是变量当中的地址值不可改变
4.修饰成员变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量不可变
注意:
1.由于成员变量有默认值,所以用了final之后必须手动赋值
2.对于final的成员变量,要么直接赋值,要么通过构造方法赋值

6.权限修饰符

public protected default private
同一个类 yes yes yes yes
同一个包 yes yes yes no
不同包子类 yes yes no no
不同包非子类 yes no no no

7.内部类
1.成员内部类
修饰符 class 类名称{
修饰符 class 内部类名称{}
}
注意:
内部类使用外部类随意访问;外用内一定要有内部类对象

public class Body {
    
    
    public class Heart{
    
    
        public void beat(){
    
    
            System.out.println("内部类方法");
            method();   //调用外部类方法
        }
    }
    public void method(){
    
    
        Heart heart=new Heart();    //调用内部类方法
        System.out.println("外部类方法");
    }
}

使用:
1.间接方式:在外部类的方法当中使用内部类,main只调用外部类方法
2.直接方式:
类名称 对象名=new 类名称();
外部类名称.内部类名称 对象名=new 外部类型名称

public class Body {
    
    
    public class Heart{
    
    
        public void beat(){
    
    
            System.out.println("内部类方法");
            method();   //调用外部类方法
        }
    }
    public void method(){
    
    
        Heart heart=new Heart();    //调用内部类方法
        System.out.println("外部类方法");
    }
}
public class demo01 {
    
    
    public static void main(String[] args) {
    
    
        Body body=new Body();
        body.method();
        Body.Heart heart=new Body().new Heart();
        heart.beat();
    }
}

同名变量访问:
外部类名称.this.成员变量

public class Outer {
    
    
    int num=10;
    public class Inner{
    
    
        int num=20;
        public void method(){
    
    
            int num=30;
            System.out.println(num);    //30
            System.out.println(this.num);   //20
            System.out.println(Outer.this.num); //10
        }
    }
}

2.局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类
只有当前所属的方法才能使用它,出了这个方法外面就不能用了
语法:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
}
}
}

public class Outer {
    
    
    public void methodOuter(){
    
    
        class Inner{
    
        //局部内部类
            int num=10;
            public void methodInner(){
    
    
                System.out.println(num);
            }
        }
        Inner inner=new Inner();
        inner.methodInner();
    }
}

定义一个类的时候,权限修饰符规则:
1.外部类:public/default
2.成员内部类:public/protected/default/private
3.局部内部类:什么都不能写

匿名内部类:
接口名称 对象名=new 接口名称{
//覆盖重写所有抽象方法
}

public class DemoMain {
    
    
    public static void main(String[] args) {
    
    
        MyInterface obj=new MyInterface() {
    
    
            @Override
            public void method() {
    
    
                System.out.println("匿名内部类实现方法");
            }
        };
        obj.method();
        new MyInterface(){
    
    
            public void method(){
    
    
                System.out.println("匿名内部类实现方法2");
            }
        }.method();
    }
}

注意事项:
1.匿名内部类在创建对象的时候只能使用唯一一次,如果希望多次创建对象,而且类的内容一样的话,就必须使用单独定义的实现类了。
2.匿名对象,在调用方法的时候只能调用唯一一次,如果希望同一个对象调用多次方法,就必须给对象起个名字。
3.匿名内部类省略了实现类/子类名称,但是匿名对象是省略了对象名称

猜你喜欢

转载自blog.csdn.net/qq_44708714/article/details/106791223
今日推荐