Java final修饰符

**final修饰符,可以修饰变量、方法、类,
final关键字表示修饰的变量、方法、类,不可再被改变。**

一、final变量

1、final修饰成员变量

 成员变量是随着类的初始化和对象的初始化而初始化的。
 当类初始化的时候,系统会为类变量(static)分配内存,并分配默认值;
 当创建对象的时候,系统会为对象的实例变量分配内存,并分配默认值。
 也就是说,静态初始化块可对类变量赋值
  普通初始化块、构造器,可以对实例变量赋值‘’

JAVA语法规定:final修饰的成员变量必须有程序显式的赋值 color=#00ffff
==>>类变量:必须在声明该类变量时或者在静态代码块,其中两者之一
指定
==>>实例变量:必须在声明时、构造器、非静态初始化块,三者之一指定

package codes.AutoBoxing_UnBoxing;

public class finalVeriable {
    //①类变量,声明时初始化
    final static int a=123;
    final static int b;
    //②类变量,静态初始化块初始化
    static {
        b=1234;
    }
    //①成员变量,声明时初始化
    final  int  c=100;
    final  int  d;
    final  int   e;
    //②成员变量,构造器初始化
    finalVeriable(){
        d=200;
    }
    //③成员变量非静态代码块
    {
        e=300;
    }
    public  static  void main(String args[]){

        System.out.println(a);
        System.out.println(b);
        finalVeriable fv=new finalVeriable();
        System.out.println(fv.c);
        System.out.println(fv.d);
        System.out.println(fv.e);
    }
}

3、final修饰基本变量和引用类型变量的区别

 基本类型变量:基本变量的值不能被改变
引用变量:它保存的仅仅是一个引用,final只保证引用类型变量所引用的地址不会变,即一直引用同一个对象,但这个对象完全可以发生改变。

4、可执行“宏替换”的final变量

无论是类变量、成员变量,还是局部变量,只要
①final修饰
②声明时就赋值
③值在编译时就能确定;
那么,它就是不再是一个变量,而是一个直接量。


public class FinalLocalTest {

    //s1为普通的字符串直接量,放在字符串池中
    String s1="HelloWorld";
    String s2="Hello";
    String s3="World";

    final String s4="Hello";
    final String s5="World";

    String s6="Hello"+"World";
    //s2和s3都是普通变量,编译器不会提供"宏替换",因此编译器无法在编译时确定s7的值
    //s7无法指向字符串池中缓存的"HelloWorld"
    String s7=s2+s3;
    //编译器可以对s4和s5执行“宏替换”,在编译阶段就可确定s8
    String s8=s4+s5;

    public static void main(String args[]){
        FinalLocalTest ft=new FinalLocalTest();
        //输出true
        System.out.println(ft.s1==ft.s6);
        //输出false
        System.out.println(ft.s1==ft.s7);
        //输出true
        System.out.println(ft.s1==ft.s8);
    }
}

二、final方法

final修饰的方法不可被重写。
被private final修饰的方法,仅仅是不能被重写,是可以被重载的。

三、final类

final修饰的类不可以有子类。例如Java.lang.Math就是一个final类,它不可以有子类。

四、不可变类(immutable)

   不可变类指的是,创建该类的对象后,该对象的实例变量是不可变的;
JAVA提供的8个包装类和java.lang.String类都是不可变类,当创建其实例后,其实例的实例变量都是不可改变的。

   code1如下,试图定义一个名为Person的不可变类,但因为Person类包含了一个引用类型的成员变量(Name),且这个引用类是可变类,所以导致Person01这个类也变成了可变类。
   由于Person类在初始化的时候,Person类的实例变量name,引用了该Name的一个对象,所以当这个可变对象的变化的时候,Person类的实例变量name也随之改变了。

//修改前  达不到实现不可变类的目的
class  Name{
    private  String  firstName;
    private  String  lastName;
    Name(String firstName,String lastName){
        this.firstName=firstName;
        this.lastName=lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
public class Person {
    private  final Name  name;
    Person01(Name name){
        this.name=name;
    }
    public Name getName() {
        return name;
    }

    public  static  void main(String args[]){
        Name  name01=new Name("孙","悟空");
        Person p1=new Person(name01);
        //输出  悟空
        System.out.println(p1.getName().getLastName());
        /*********************************************/
        p1.getName().setLastName("八戒");
        //输出   八戒
        System.out.println(p1.getName().getLastName());


    }
}

   为了保持Person对象的不可变性,必须保持好Person对象引用类型的成员变量name ,让程序无法访问到name成员变量,也就无法利用name成员变量的可变性来改变Person对象了。
   Person类改写了设置name实例变量的方法,也改写了name的getter方法。
直接利用已有的可变对象,是有风险的


//修改后达到,实现不可变类的目的
class  Name{
    private  String  firstName;
    private  String  lastName;
    Name(String firstName,String lastName){
        this.firstName=firstName;
        this.lastName=lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
public class Person01 {
    private  final Name  name;
    public Person01(Name name){
        this.name=new Name(name.getFirstName(),name.getLastName());
    }
    public Name getName() {
        return new Name(name.getFirstName(),name.getLastName());
    }

    public  static  void main(String args[]){
        Name  name01=new Name("孙","悟空");
        Person01 p1=new Person01(name01);
        //输出 悟空
        System.out.println(p1.getName().getLastName());
        /*********************************************/
        p1.getName().setLastName("八戒");
        //输出  悟空
        System.out.println(p1.getName().getLastName());


    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值