1. 关于final
- final修饰的类不能被继承
- final修饰的方法不能被重载(可以重写)
- final修饰的变量不能被改变(修饰引用变量时不能改变引用所指向的对象,但是可以修改引用指向对象的内容)
2. 关于abstract
- abstract用来修饰类、接口和方法,接口即使没有用abstract修饰也会隐式的指明为abstract
- abstract修饰的类为抽象类,不能被实例化,因此只能通过实例化其子类来使用该抽象类
3. 总结
- 由于final修饰的类不能别继承
- 但是abstract修饰的类必须被继承后才能使用,否则没有意义
- 所有final和abstract不能同时修饰一个类
2. final修饰的变量如何初始化
1. 只有final修饰的变量
- 在定义处直接通过”=”进行赋值
- 通过类的构造方法进行赋值,但是要注意类中所有的构造方法都必须对final修饰的变量进行赋值
- 在非静态块中初始化```java
public class Demo02 {
private final int a;
{
} } ```a = 10;
2. 同时有static和final修饰的变量
- 只能在定义处通过”=”赋值(不准确,下面有补充)
- 原因:
- static修饰的变量可以不赋初值,是在构造器之前完成初始化,其执行时机是在类加载时执行,并且会被初始化为0/null,后续过程中如果发现用户给变量赋了初值,则会改为用户赋的值
- final修饰的变量可以不赋初值,但必须初始化,在运行时被初始化,可以直接通过”=”初始化,也可以通过构造方法初始化
- static final修饰的变量在javac(编译)时生成ConstantValue属性,在类加载过程中通过ConstantValue属性值给该字段赋值ConstantValue属性没有默认值,只能通过”=”显式的赋值
- 理解:
- static修饰的变量可以不赋初值,但是会被初始化为0/null,并且在构造器之前完成初始化
- final修饰的变量如果不赋初值则必须在所有的构造器中为其初始化
- 所以static final修饰的变量必须通过”=”赋值,否则将无法初始化,而final修饰的变量必须初始化,所以只能在定义处通过”=”赋值
- 补充:static final修饰的变量可以在静态块中初始化```java
public class Demo02 {
private static final int b;
static {
} } ```b = 20;
Java程序的初始化规则
1. 变量的初始化规则,一下规则优先级依次递减
- 静态对象(变量)优先于非静态对象(变量),其中静态对象(变量)只初始化一次,而非静态对象(变量)可能会初始化多次
- 父类优先于子类进行初始化
- 按照成员变量的定义顺序进行初始化。即使变量定义散布于方法定义,它们依然在任何方法(包括构造方法)被调用之前初始化
2. Java程序初始化不同模块的执行顺序
- 父类的静态常量
- 父类静态代码块
- 子类静态常量
- 子类静态代码块
- 父类非静态变量
- 父类非静态代码块
- 父类构造函数
- 子类非静态变量
- 子类非静态代码块
- 子类构造函数
public final 修饰的变量建议加上static
public class A{
public static final int num = 10;
// ...
}
- 如果不加static,则在其他类中要使用num值就必须先new对象再通过对象来拿属性值,而new对象会浪费内存
- 加上static可以节省内存:
- 不需要new对象直接通过
A.num
拿值 - static是共享变量,在内存中只会存在该变量的一份存储
- 不需要new对象直接通过
- final修饰的变量不可变,因此不存在并发冲突问题
**在对象数组中 实际存放的不是对象本身,而放的是对象引用的地址。 **