fianl关键词

 一、final关键字概述

 final关键字具有最终或不可改变的含义,可用于修饰类、变量、方法。因此被final修饰的类、变量、方法具有以下特征:
    --final修饰的类不能被继承;
    --final修饰的方法不能被子类重写;
    --final修饰的变量(成员变量和局部变量)是常量,只能赋予一次。

 二、使用方式
  1)修饰类,格式如下:

public final class 类名称 {
    // ...
}

  2)修饰方法,格式如下:

修饰符 final 返回值类型 方法名称(参数列表) {
    // ...
 }

  3)修饰变量

  成员变量

  final修饰的成员变量初始化(赋值)有两种方式,一种是直接赋值,另一种是通过构造方法赋值,二者选其一。
  a.直接赋值代码示例:

package cn.sjk.study.java.final;

public class Person {

    //方法1:直接赋值
    private final String name = "sjk";
    
}

  b.通过构造方法赋值代码示例:

package cn.sjk.study.java.final;

public class Person {

    //方法2:定义时没有赋值,通过构造方法来赋值
    private final String name;
    
    public Person(String name) {
        this.name = name;
    }
}

  注意:当使用构造方法对final修饰的成员变量赋值时,必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值,代码示例:

package cn.sjk.study.java.final;

    public class Person {
    
        private final String name;
        //下面的无参构造方法和带参构造方法里都必须对final的成员变量进行赋值,否则编译不通过
        public Person() {
            name = "sjk";
        }
        public Person(String name) {
            this.name = name;
        }

}

  实际开发中,初始化非final修饰的成员变量除了上面两种方式外,我们还会通过set()方法对其赋值,但是对final修饰的成员变量,只能通过上面两种方法中的任意一种,否则赋值编译会报错。如以下操作不合法:

package cn.sjk.study.java.final;

public class Person {
    
    private final String name;

    //对于final修饰的变量使用这种赋值方式不可行
    public void setName(String name) {
        this.name = name;
    }
}

  局部变量-基本类型

  基本类型的局部变量,被final修饰后,只能复制一次,不能再改变。代码示例如下

package cn.sjk.study.java.final;

public class FinalDemo {
    public static void main(String[] args) {
        //声明变量,使用final修饰
        final int age;
        //第一次赋值
        age = 18;
        //第二次赋值
        age =28; //报错,不可重复赋值
            
        //声明变量,直接赋值,使用final赋值
        final int age = 18;
        //第二次赋值
        age = 28; //报错,不可重复赋值
            
    }
}

  局部变量-引用类型
  引用类型的局部变量,被fianl修饰后,只能指向一个对象,地址不能再改变。但不影响对向内部的成员变量值的修改,代码示例如下:

public class FinalDemo2 {
    public static void main(String[] args) {
        //创建Person对象
        final Person  p = new Person();
        //创建另一个person对象
        p = new Person(); //报错,指向了新对象,地址改变
    
        //调用setName方法
        p.setName("sjk"); //可以修改
    }
}

  思考,下面两种写法,哪一种可以编译通过?
  写法1:

final int age = 0;
for (int i = 0; i < 10; i++) {
    age = i;
    System.out.println(age);
}

  写法2:

for (int i = 0; i < 10; i++) {
     final int age = i;
     System.out.println(age);
}

  根据 final 的定义,写法1报错!写法2,为什么通过编译呢?因为每次循环,都是一次新的变量age。这也是大家 需要注意的地方。

猜你喜欢

转载自www.cnblogs.com/sheng-sjk/p/10463875.html