阶段一/ Java单例模式与多态/关于多态的总结1

 

目录

一、前言:不存在继承接口时的static、final修饰的变量

二、get方法

三、方法继承

三、变量


⚠️:重写的概念感觉是和多态绑定的,例如static关键字的不能重写,但是也是可以重新定义的,不过就没有多态现象了

一、前言:不存在继承接口时的static、final修饰的变量

1、单一类的对象实例化的顺序,假设类也是第一次加载

  1. 加载所有的静态属性
  2. 执行静态代码块,若有多个静态代码块顺序执行
  3. 类的加载完成,开始实例化对象,加载该对象的所有的属性
  4. 执行构造代码块,若有多个构造代码块顺序执行
  5. 依据传递的参数选择执行哪个构造函数

2、关于赋值的地方

  • 普通成员变量
    • 无所谓在哪,但是要记住别在static修饰的地方(static修饰的方法只能访问静态属性,毕竟只要类加载完毕就可以调用static修饰的方法,此时有可能还没创建对象),后续还可以修改
  • static
    • 只要在static修饰的地方就可以,后续可修改
  • final
    • 声明的时候初始化
    • 构造代码块
    • 构造方法,这边要注意在构造方法中赋值必须默认构造方法及其重载的构造方法都要赋值
    • 以上,只能且必须选一种,因为常量,一旦给值了就不能变
  • static + final
    • 此处取static、 final可赋值的交集,final最迟要在构造方法赋值,static只能在有static修饰的地方,且static不能修饰构造方法,故只能在声明的时候初始化或者静态代码块中赋值。

1、单一类的对象实例化的顺序,假设类也是第一次加载

(1)加载所有的静态变量,这里边加载desc,STATICFINAL,同时初始化STATICFINAL

(2)执行静态代码块,若有多个静态代码块顺序执行

(3)类的加载完成,开始实例化对象,加载所有的属性,这边加载species,SEX,同时初始化SEX

(4)执行构造代码块,若有多个构造代码块顺序执行

(5)依据传递的参数选择执行哪个构造函数

public class Animal {
    public String species;
    public final String SEX = "female";
    public static String desc;
    public static final int STATICFINAL = 900;
    {
        System.out.println("对象的常量SEX " + SEX);
        System.out.println("对象构造代码块");
    }
    public Animal(){
        System.out.println("对象构造方法");
    }
    static {
        System.out.println("静态常量STATICFINAL " + STATICFINAL);
        System.out.println("静态代码块");
    }
}
public class Test {
    public static void main(String[] args){
        Animal animal = new Animal();
    }
}

输出: 

静态常量STATICFINAL 900
静态代码块
对象的常量SEX female
对象构造代码块
对象构造方法

二、get方法

通过普通的get(继承)/ default(接口)方法调用

  • 父类引用指向子类对象(接口指向实现类对象),调用的是子类重写的方法,返回的也是子类的属性值,不是父类或接口中的同名属性值
  • 若父类和接口有重名的属性及get方法但是子类(实现类)没有定义,此时只要子类(实现类)没有用到该属性就不会有问题,此时父类引用指向子类对象或者接口指向实现类对象,调用的是父类中的get方法返回的是父类中的属性值。

get(继承)方法有final修饰/ default(接口,接口中不能带final,final与接口不兼容)

  • 子类不能重写该方法,但是咱不反对重载哈。若父类有public final void getNAME()方法声明,则子类中不可以再重写,此时若接口中有void getAge();也不会出错(尽管实现类要实现接口中所有的抽象方法,子类也不允许重写,不过没事哈,咱从父类继承了哈),此时接口指向实现类对象,接口.getNAME()调用的是实现类继承自父类的方法,若接口中是default void getNAME()有实现体,此时接口指向实现类对象,接口.getNAME()调用的依旧是实现类继承自父类的方法。

get(继承)方法有static修饰/static(接口)

  • 接口的静态方法只能通过接口名.静态方法调用,即使接口指向实现类对象,也只能通过接口调用,例如IBehavior iBehavior = new Bird();,只能通过IBehavior调用,而不能通过iBehavior调用。
  • 若父类子类接口都有重名的static方法,例如都有public static void getSpecies(),则父类引用指向子类对象,调用的是父类自己的static方法,而不是子类的,参见二,接口.静态方法,调用的是接口自己的。
  • 实现类不能重写,但同继承,依旧可以定义自己的,若接口有public static void getSpecies()方法,实现类也可以定义自己的public [static] void getSpecies()方法,加不加static都可,访问修饰符的访问权限也要大于等于接口中的访问权限,就算接口指向实现类但是这边大概由于静态方法得通过接口调用,故只能调到接口自己的。
  • static void getSpecies(),在实现类的外部,无法通过实现类对象调用接口中static修饰的方法,只能通过接口.静态方法调用,但是若子类从父类继承了public [static] void getSpecies()则用子类(实现类)对象调用getSpecies()是可以的,不过调用的是父类的方法。

三、方法继承

  • 普通方法,子类可随意重写,此时父类引用指向子类对象调用的是子类重写的方法
  • final修饰的方法,子类不可以重写,例如父类已经有了public final void sleep(),则子类不能再定义public [final] void sleep();但是子类可以重载该方法
  • static修饰的方法,子类不可以重写,但是子类可以定义自己的(注意不能丢掉static哈),例如父类有static void sayHello(),则子类不可以有void sayHello(),提示子类中的sayHello()不可以覆盖父类中的sayHello(),被覆盖的方法为static,但是这不妨害我们自己定义,不过得带上static还有记住访问修饰符的访问权限必须大于等于父类哈,例如public static void sayHello()。此时父类引用指向子类对象调用的是父类自己定的sayHello,因为子类定义的sayHello算子类独有的方法。

三、变量

直接调用成员属性

  • 接口和其父类若有重名变量,若子类没有同名的变量则会报错,因为父类和接口均能匹配到该变量,这一点和方法也不一样,不过若一定要这么做也不是没办法,我们可以在子类(实现类)通过super.属性调用自父类继承的属性;通过接口名.属性调用接口的。
  • 关于继承,父类引用指向子类对象,则父类引用.成员属性(其中包括子类和父类成员变量声明完全一样的),调用的均是父类的成员属性而不是子类同名的成员属性,这点和方法不同。
  • 同理关于接口,接口引用指向实现类的对象,则接口引用.变量(其中包括实现类与接口同名的变量),调用的均是接口自己的变量,而不是实现类中同名的变量。接口中的属性默认是public static final 。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值