三个修饰符

Java中三个非常重要、的修饰符:static、final 和 abstract


1 static

static:静态修饰符
能够修饰属性、方法、初始化代码快、内部类,不能修饰局部变量和类

1.1 static 修饰属性—静态属性

1)本类所有对象共享

2)可以直接通过 类名.静态属性 访问

三个修饰符_第1张图片

三个修饰符_第2张图片

实际编程中应尽量用类名直接调用静态属性,这样能把静态变量和实例变量加以区分,从而提高代码的可读性。

三个修饰符_第3张图片

1.2 static 修饰方法—静态方法

1)全类公有的方法
2) 可以使用类名.方法名直接调用

三个修饰符_第4张图片

3)静态方法与对象无关,不依赖对象所以无法使用this或super关键字

三个修饰符_第5张图片

4)静态方法只能访问静态成员(非静态方法中,无论方法和属性是否是静态的都能够访问)

三个修饰符_第6张图片

5)静态方法/属性可以被继承

三个修饰符_第7张图片

6)静态方法只能被静态方法覆盖且没有多态

使用多态时:子类对象给父类引用赋值 ,运行时会调用子类覆盖的方法,但是当对一个引用调用静态方法时,等同于对这个引用类型调用静态方法。
例:

Super sub = new Sub();
sub.m1();
//由于m1()方法为静态方法,所以当使用 引用.方法名调用时 sub.m1() 会自动被替换为 引用类型.方法名 Super.m1();

1.3 类加载

类加载的时机与过程:

1)当JVM第一次使用某个类时(new 对象、调用静态成员、使用子类)需要通过ClassPath查找该类的.class文件

2)将.class文件中保存的该类信息(属性、方法….)加载到内存中(内存中的模板)

3)加载时会初始化该类的必要信息,初始化静态属性、静态方法、执行该类静态初始化代码块等。
加载时机1:访问静态成员

三个修饰符_第8张图片

加载时机2:创建对像

三个修饰符_第9张图片

加载时机3:创建子类对象或加载子类时

三个修饰符_第10张图片

注意:
1)一次运行中类加载只会执行一次
2)只声明引用,不会进行类加载

1.4 静态初始化代码块

作用:在类加载时对静态属性进行初始化的工作

1.5 类加载的过程:

1)如果有需要先加载父类(初始化父类静态属性、执行父类静态初始化代码块)
2)初始化本类静态属性,执行本类静态初始化代码块


2 final

final属性能够修饰变量、方法 和类。变量 包括属性、局部变量

2.1 常量

用final修饰的变量和属性一般称之为常量。

定义:一旦赋值,其值不能改变的变量

对于基本类型的常量而言,所谓的不改变妹纸的是不能改变变量的值。

对于对象类型的常量而言,保存的是对象的地址,一旦指向某个对象以后,不能指向其他对像,但是完全可以改变这个对象的属性。

对于final属性而言,虚拟机在分配完空间以后,将不会为其赋予默认值,,从而把为final属性赋值的机会留给程序员。

但Java语言规定,一旦对象创建完成,则对像的final类型的属性就不能赋值了,故,对于 final 类型的实例变量,能够赋值的时机,就是在分配空间之后,对象创建完成之前。

赋值机会:
1)声明同时赋值(如果该属性不是static修饰的则除了浪费空间外无任何意义)

2)构造方法赋值(如果有多个构造方法,则多个构造方法都得对final属性赋值,这样就保证了当一个对象被创建的时候,无论调用的是哪一个构造方法,final属性都被正确地赋值了。)

3)初始化代码块,静态初始化代码块。

2.2 final方法

final修饰的方法不允许被覆盖。

final修饰方法意义在于:防止子类在定义新方法时,造成不经意的重写。
Eg:

class Super{
    public void m1();
    public final void m2(){}
}

class Sub extends Super{
    public void m1(){} //能够覆盖父类方法
    public void m2(){} //编译出错!无法覆盖父类方法
}

上面的代码中,Super类中有两个方法,m1是普通方法,能被子类覆盖,m2方法被final修饰,故子类方法不能够覆盖父类方法。

2.3 final类

用final修饰类表示这个类不能被继承。

Eg:

final class MyClass{}
class Sub extends MyClass{}
//编译出错,无法继承一个final类

final修饰方法和final修饰类的区别:

1)一个类有final方法,这个类能够被继承,但是无法覆盖final方法

2)一个类如果本身就是final的,则这个类无法被继承,且它所有的方法都无法被覆盖。

注意:
1)常用 public static final (公开静态常量) 用于保存一些常用且不可变的值。

2)final 修饰基本类型变量- -值不可变

3)final 修饰对象引用- - 地址不可变

4)final static 可以连用,private、static、final 均不能与abstract连用。、

5)JDK中一些基础类库被定义为final,例如:String、Math、Integer、Double等

6)static final修饰的成员变量称为常量,必须声明同时初始化,不可被改变。

static final 常量会在编译期被替换。
Eg:

class Foo{
    public static final int NUM = 100;
}

class Goo{
    public static void main(String[] args){
        System.out.println(Foo.NUM);
        //编译代码时,JVM会自动替换为:System.out.println(Foo.NUM);
    }
}

// static final 常量Foo.NUM在编译时会被常量100替换,在运行Goo类时,Foo类不需要被载入

3 abstract

修饰 类 、方法

3.1 抽象类

abstract修饰类,则这个类就成为了一个抽象类,抽象类的特点是:

抽象类只能用来声明引用,不能用来创建对象。

三个修饰符_第11张图片

虽然抽象类不能创建对象,但是抽象类可以被继承,才从而创建子类对象。

abstract class MyAbstract{
    public void m(){ }
}

class MySubClass extends MyAbstract{  }

public class TestAbtract1{
    public static void main(String[] args){
        MyAbstract ma; //可以声明抽象类的引用类型
        // ma = new MyAbtract(); 错误的代码
        ma = new MySubClass(); //但是可以创建子类对象
    }
}

//写抽象类的目的就是:为了能够让子类继承

3.2 抽象方法

用 abstract 修饰的方法称为抽象方法。

定义一个方法分两个部分:方法的声明,方法的实现。

抽象方法指的是:一个只有声明,没有实现的方法。对于抽象方法来说,方法的实现部分用一个分号来代替。
Eg:

class MyAbstract{
    public abstract void m1(); // 抽象方法
    public void m2(){} //普通方法

//抽象方法的实现留给子类来完成

三个修饰符_第12张图片

注意
1)抽象类可以没有抽象方法,有抽象方法的类一定是抽象类

2)子类覆盖父类的抽象方法时,并不是用一个特殊的实现替换一个一般的实现,而是在父类没有方法实现的情况下,子类给出一个方法的实现。

3)子类继承抽象类,要么也成为抽象类,要么就必须实现抽象类中所有的抽象方法。

3.3 不影响多态的使用

1)使用子类实现父类中所有的抽象方法

三个修饰符_第13张图片

2)使用多态创建对象

三个修饰符_第14张图片

3.4 抽象的作用

方法的声明是共性,方法的实现是特性。

使用抽象方法,就可以让我们把方法的声明放在父类中,把方法的实现留在子类中。这样一方面,能够很好的体现出“共性放在父类”这个基本的原则,另一方面,用父类类型的引用又可以调用这些方法,并不影响多态语法的正常使用。

你可能感兴趣的:(Java面向对象—学习笔记)