static关键字和继承、多态
文章目录
static关键字
概念:成员变量/属性,使用static修饰后,该属性由对象层级提升为类层级。且随着类的加载而初始化,和是否创建对象无关。也就是说,这个属性是被类拥有,该类的所有对象都是可以实现共享
-
被static修饰的,成员变量,不在堆内存,也不再栈内存。而是在方法区,被多个对象共享
-
被static修饰的成员变量,用 “类名.” 方式访问
使用方式:
-
普通方法:能够调用 普通方法和属性,也能调用 被static修饰的方法和属性
-
被static修饰的方法:只能访问,被static修饰的方法和属性。因为,被static修饰,会随着类的加载而加载,类加载的时候,是没有创建对象的。所以不能使用普通的成员方法
-
static修饰代码块:
-
普通代码块,随着构造方法的执行而执行,但是要优先构造方法加载执行 (就是说每次创建对象,都为执普通代码块行代码块)
-
普通代码块的使用场景:
- 可以吧一些需要执行构造方法之前的一些准备性工作,放在代码块中
- 可以对成员变量,做统一初始化
-
static修饰的代码块:
static{ ... }
和普通代码块不同的是,static修饰的代码块:
- 随着类的加载,而加载 (意味着,static修饰的代码块在类加载的时候就要执行)
- 只执行一次,随着类的释放而释放 (普通代码块,会随着对象的创建而执行)
-
总结:
-
static定义的属性,保存在方法区,被所有堆内存中的对象共享 (仅限于该类的对象)
-
static修饰的成员,随着类加载而加载到方法区,直到类销毁时才销毁。生命周期很长。
-
main方法,是类加载后,才被执行。所以,static修饰的成员要优先于main方法和构造方法的执行
-
在开发中,只有被共享的才加 static,不要乱用
-
(重点)为什么被static修饰的方法中,不能使用this?
this,本质上是当前类对象的引用。在构造函数执行之后,才能存在。而static修饰的方法在类加载时就已经加载进内存。所以,不能使用this
继承
-
关键字:extends
-
本质:从已有类得到继承信息创建新类的过程
1. 特点:
- 提高了代码的复用性,可维护性和扩展性
- 是多态的前提条件
- 子类不能继承 父类的构造方法和私有方法,但是私有属性可以继承,但不能直接访问
- 类对象实例化之前,会调用父类的无参构造(要初始化你继承的成员变量)。相当于在子类构造方法的第一行加了 super()。如果想要调用父类有参构造,那么直接在 super(parm1, parm2) 传入参数即可
- Java语言中只支持单继承不支持多继承,也就是说一个子类只能有一个父
类,但一个父类可以有多个子类。
2. 继承中的代码块 ( 考点):
-
先执行父类的静态代码块,再执行子类的静态代码块。
-
执行父类的构造块,执行父类的构造方法体。
-
执行子类的构造块,执行子类的构造方法体。
方法重写
从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写
一个和父类一样的方法来覆盖从父类中继承下来的版本,该方式就叫做
方法的重写(Override)
- 方法名相同、参数列表相同以及返回值类型相同
final关键字
- 本质: 修饰不可改变内容
- 通常使用 public static final共同修饰成员变量来表示常量
- 当用final修饰引用时,该引用就不能指向其他对象。但是不影响该对象内部的修改
- 被final 修饰的类,是不能被继承
- 被final 修饰的方法,不可被重写,但可以继承
- 被final 修饰的属性,必须初始化,且不可变
多态
1. 基本概念
前提:继承
本质:父类引用指向子类的对象,所以你用父类引用去调用方法或属性,其实访问的是子类对象的内存空间。
使用多态时:
- 在编译阶段,调用的是父类中的方法
- 在执行阶段,调用的子类中的方法
2. 注意:
- 多态的前提是继承,在访问子类对象时,若找不到的就直接去父类找。
- 若是父类和子类,都有重名的静态(static) 方法,那么这两个方法不构成重写。
3. 强制类型转换
当父类,想要调用子类独有的方法时,就需要将子父类的引用转化为子类的的引用。
分类:
-
自动类型转换
子类转化为父类,例如: 狗是动物
-
强制类型装换
父类转化为子类,例如:动物是狗 (不一定啊,所以有些时候强制转换会出问题)
注意事项:
-
引用类型之间的转换,必须发生在父子类之间 (前提:继承)
-
强制转换,可能会产生异常 : ClassCastException,解决办法:instanceof方法。语法格式
引用名.instanceof (数据类型 )
在强制类型转换之前,需要判断:
Animal animal = new Cat(); if(animal.instanceof(Dog)){ // 如果类型对应才能强转 Dog dog = (Dog)animal; }
用instanceof方法判断后,就会避免 ClassCastException 的风险
其实,这也是多态的缺点:父类想要调用子类独有的方法,要进行强制类型转换
abstract关键字
表示抽象,abstract的作用,和字面意思相同,表示抽象,就是说不能实现的事物。用法:
-
抽象方法:
不能具体实现的方法,所以没有方法体,以分号 " ; " 结尾
-
抽象类:
不能具体实例化的类 (不能创建具体的对象)
注意事项:
- 抽象类中,可以有抽象方法、也可以没有
- 抽象类和普通的Javabean 基本上一样,属性、getter、setter、构造方法、普通方法等等
- 在开发中,常常会遇到:抽象类引用指向子类的对象。其实就是多态的实现
- private 和 abstract 不能一起修饰同一个方法 ( 因为abstract的前提是要继承,private的类是私有的不能实现继承)
- final 和 abstract 不能一起修饰同一个方法,因为 final修饰的方法不能重写
之所以 有抽象类,是为了避免我们调用抽象方法,所以才有了抽象类。那么,抽象类中如果没有抽象方法,确实可以,但这样是没有什么意义
Interface,接口
1. 基本概念:
-
接口是一种比抽象类还要抽象的类,体现在接口中的方法全部是抽象方法
-
但是从,JDK 1.9开始,接口中允许出现私有方法 (Java9的新特性)
-
在接口中定义一个默认方法,子类可以不重写(Java8的新特性)
如果给一个接口新添加一个方法,那么所有实现类都要重写,所谓牵一发而动全身,有些实现类压根儿就不需要新增接口中的方法。所以才有了这一新特性
// 格式(public 可以省略): public default void show{ ...; }
而且,默认的方法实现类也可以重写。
-
因为,接口不能创建对象。所以,在接口中定义一个 static静态方法,可以通过 接口名**.**方法名的形式调用(Java8的新特性)
// 通过 接口名 直接调用 public static void test{ ... }
-
使用 Interface 关键字定义
// 定义一个 InterfaceTest 接口
public interface InterfaceTest{
// 接口中的属性,一定是常量
// public static final可以省略
public static final int NUM = 1;
// 接口中定义的方法一定是抽象方法
// public abstract 可以省略
public abstract void show();
// 但是从 Java9的新特性,允许出现私有方法
private void privateShow(){
// 方法体
...
}
}
接口主要是对类的行为的一种约束
2. 接口的作用
- Java中,一个类只能继承一个父类,可以有多个子类。但是,接口完美的解决这个问题,一个类可以实现多个接口
- 类和接口之间的关系:
3. 接口和抽象类的主要区别
-
关键字不同,接口 - Interface,抽象类 - abstract
-
抽象类是继承 - extends,接口是 实现 - implements
-
继承抽象类,只能是单继承; 而,实现接口,可以做到多个接口同时实现
-
抽象类中,可以有构造方法;接口中,不能有构造方法