java — 关于final的总结

关于java中final关键字的总结

文章目录

    • 一. 引言
    • 二. final修饰变量:相当于常量
    • 三. final修饰方法
    • 四. final修饰类
    • 五. 简单说说final和其他关键字的使用

一. 引言

final是java中一个非常重要的关键字,final关键字在java中可以用于类、方法、变量,java中的String类、System类、StringBuffer类都不可被继承,是final的典型例子。下面就来总结我所学过的final的用法。


二. final修饰变量:相当于常量

1. 成员变量:
简述: 就是在类里面定义的变量,成员变量随着类的初始化而初始话或者对象的初始化而初始化。成员变量中包含类变量和实例变量。对于类变量,按我个人理解,就是可以通过类直接调用的变量,随着类的加载而加载,因此是静态static的。而实例变量,就是在类中定义的非静态变量。执行普通初始化块、构造器时候可以对实例变量进行赋初值。还有一点值得注意的是:final修饰的成员变量要程序员显示赋初值。


①. final对类变量的初始化:两种方法:显式初始化,代码块初始化。

class Student{
     
    //实例变量
    String name;
    int age;

    //类变量:显式初始化
    final static int id = 10;
    //类变量:代码块初始化
    final static int level;

    static{
     
        //代码块初始化,注意:代码块也要是静态的
        //static修饰的变量随着类的加载而加载,早于方法,对象
        level = 4;
    }
}

②. final对实例变量的初始化:代码块赋值,构造器赋值,和非静态代码块赋值。
其实很好理解为什么是非静态代码块,因为如果是静态代码块,在类加载的时候就已经赋值,但是此时的实例变量需要创建对象才开始出现,所以相当于静态代码块在对一个不存在的变量赋值。

class Student{
     
    //显式初始化
   final int age = 10;
   
   //构造器初始化:
   final int level;
   final String name;

    public Student(int level, String name) {
     
        this.level = level;
        this.name = name;
    }
    
    //非静态代码块初始化
    final int score;
    {
     
        score = 100;
    }
}

③. final对变量赋值的一些注意点
        2.1:如果在定义final变量的时候已经赋初值,那么就不可以重新在代码块中和在构造器中重新赋值了。相当于对一个常量赋值,是不可以的。

        2.2:如果一开始就打算在代码块中或者构造器中对实例变量赋值,那么就不要显式初始化。对于类变量也一样。

        2.3:不能在方法中对final变量进行赋值。我的理解就是final的变量无论是类变量还是实例变量,都要在属性形成后才赋值。而方法需要被调用生效开始赋值,考虑到方法不一定会被调用,也有可能导致final的变量得不到初值。当然这是个人理解了。
java — 关于final的总结_第1张图片


2. 局部变量:
简述:局部变量就是方法中定义的变量,包括形参以及代码块中定义的变量

public class finalTest {
     
    public static void main(String[] args) {
     
        {
     
            //对代码块中的变量赋值
            final int b = 10;
        }
    }
}

class Student {
     
    int age;
    public void test(final int a){
     
        //java不能对形参赋值,因为传进参数那一刻就已经赋值了,这样做是修改了。
        //a = 10; 报错
        final String name = "Mike";
        //已经赋值了的不能再改变
        //name = "john";
    }
}


3. final修饰基本数据类型和引用数据类型的不同:
说明:对于基本数据类型,final修饰变量之后,就变成了一个常量,值是不可改变的。而对于引用数据类型,用final修饰过后,只能保证该引用数据类型所引用的地址不会变,就是说,执行的地址不会改变,但是属性还是可以变的。类似于数组、对象。而对于String本身就是final的,字符串也是存放在常量池中,本身就是不可变。
下面就来演示对引用数据类型的修改

public class finalTest {
     
    public static void main(String[] args) {
     
        //1. 对数组
        final int[] arr = new int[]{
     1,2,3,7,8,9,4,2,7};
        System.out.println(Arrays.toString(arr));//[1, 2, 3, 7, 8, 9, 4, 2, 7]
        arr[0] = 10;
        arr[1] = 9;
        arr[2] = 8;
        arr[3] = 7;
        System.out.println(Arrays.toString(arr));//[10, 9, 8, 7, 8, 9, 4, 2, 7]
        //可以看到就是说,final过后还可以进行修改。

        //2. 对对象
        //①
        final Student s = new Student(18, 101, "John");
        System.out.println(s);//Student{age=18, number=101, name='John'}
        s.age = 10;
        s.number = 102;
        s.name = "Mary";
        System.out.println(s);//Student{age=10, number=102, name='Mary'}

        //②.
        Student s1 = new Student(22, 103, "Mike");
        s1 = null;
        System.out.println(s1);//null,可以修改为null

        final Student s2 = new Student(22, 103, "Mike");
        s2 = null;//加入final之后再修改会报错,因为地址是不可以改的
    }
}

class Student {
     
    int age;
    int number;
    String name;

    public Student(int age, int number, String name) {
     
        this.age = age;
        this.number = number;
        this.name = name;
    }

    @Override
    public String toString() {
     
        return "Student{" +
                "age=" + age +
                ", number=" + number +
                ", name='" + name + '\'' +
                '}';
    }
}




三. final修饰方法

final用来修饰一个方法,表明此方法不可以被重写,比如Object中的getClass()方法。如果在一个程序中有些方法不想要被重写,就可以使用final。
java — 关于final的总结_第2张图片
但是值得注意的是,对于final修饰的方法,如果是私有的方法,对于java而言,子类本身就是不可以重写的,如此一来,即使是父类中用private修饰的方法,子类也会因为访问权限不够而无法实现重写。所以这时候子类可以定义和父类同名同参的方法,因为这里不是重写的关系,二者没有关联。

class People{
     
    private final void eat(){
     
        System.out.println("吃饭");
    }
}

class Student extends People{
     
    public  void eat(){
     //这里的eat和上面的eat是没有关系的
        System.out.println("学生应该好好吃饭");
    }
}


当然,对于java而言,重载也是没有问题的

class People{
     
    public final void eat(){
     
        System.out.println("吃饭");
    }
    public void eat(String food){
     
        System.out.println("吃饭" + food);
    }
    public void eat(String food, String food2){
     
        System.out.println("吃饭" + food + food2);
    }
}


四. final修饰类

对于用final修饰的类,意思就是不可继承了,所以这也就是为什么不把final和abstract放在一起了。


五. 简单说说final和其他关键字的使用

①. final + static : static final
修饰变量:即是静态的又是final的,表明该属性是全局常量
修饰方法:表明该方法是静态的,而且在整个程序中只有一个.

②. final 和 abstract不能出现在一个方法中,abstract的方法本身就是抽象的,要被子类继承重写,而final方法是不可被继承的,二者本身就矛盾了。


你可能感兴趣的:(笔记,java)