聊聊java中final那点事

1.final是什么

final是一个java关键字,一个修饰符,可用于修饰变量,方法,修饰类.java

2.final有什么用

  • final能够修饰变量时,能够使其值不能改变
  • final修饰方法时使其不能被重写
  • final修饰类时,使其不能被继承.

3.final修饰成员变量

fianl最多见的用法时用来修饰成员变量,成员变量分为静态变量与普通变量. 对于final修饰的变量,不是不能被赋值,是其值不能被改变,能够理解成只能赋一次值.能够在定义时赋值,也能够在定义后在另外赋值,但不管何种方式只能被赋值一次.数组

(1)修饰静态变量

修饰静态变量时,能够选择如下两种方式赋值:函数

  • 在定义时赋值
  • 静态初始化块内赋值
final static int a = 6;
final static int b;
static 
{
	b = 6;
}

(2)修饰普通成员变量

修饰普通成员变量时,能够选择如下三种方式赋值:this

  • 定义时赋值
  • 初始化块内赋值
  • 构造方法赋值
public class test
{
	int c = 1;
	int d;
	int e;
	{
		d = 2;
	}
	public test()
	{
		e = 3;
	}
}

根据"静态"不能访问"非静态"规则,就是说静态的方法不能访问非静态成员,static初始化块不能初始化非静态成员,普通初始化块也不能初始化静态变量. 可是,有一个"bug"就是java容许经过方法访问final成员,所以...有趣的事情发生了.code

public class test
{
    final int a;
    {
        System.out.println(a);//这里会报错
        printA();
        a = 3;
        printA();
    }
    void printA()
    {
        System.out.println(a);
    }
    public static void main(String[] args) {
        new test();
    }
}

以上这段代码会报错,由于java不容许final成员未初始化前访问.对象

在这里插入图片描述

把上面那一行出错的代码注释后...竟然经过了编译?!blog

public class test
{
    final int a;
    {
        //System.out.println(a);//这里会报错
        printA();
        a = 3;
        printA();
    }
    void printA()
    {
        System.out.println(a);
    }
    public static void main(String[] args) {
        new test();
    }
}

printA()中只是用方法包装了一下输出函数,竟然就经过了编译...有没有兴趣看一下结果?继承

在这里插入图片描述

emmmmmm....final"默认值"为0.....总之就不要想这些歪门邪道去在final初始化以前访问final变量了 ,在使用final变量前初始化,初始化,初始化,重要的事情说三遍.图片

4.final修饰局部变量

final修饰局部变量其实也分两种,一种是修饰形参,一种是修饰方法内部的局部变量内存

(1)修饰形参

没什么好说的...就是形参的值不能改变.

public void f(final int a)
{
	a = 3;//报错.
}

(2)修饰局部变量

修饰局部变量时能够定义时赋值,也能够在定义后在赋值(仅一次).

public void f()
{
	final int  a = 3;
	final int b;
	b = 2;
}

(3)final修饰引用变量

嗯.....这个是一个特别一点的例子,Talk is cheap.上代码.

import java.util.Arrays;

public class test
{
    public static void main(String[] args) {
        final int[] arr = {1,2,3};
        arr[1] = 5;
        Arrays.stream(arr).forEach(System.out::print);
        System.out.println();
        final A a = new A();
        a.setA(9);
        System.out.println(a.getA());
    }
}

class A
{
    private int a = 3;
    public void setA(int a)
    {
        this.a = a;
    }
    public int getA()
    {
        return a;
    }
}

为何final数组能够赋值???fianl对象的值被改变了???看看结果:

在这里插入图片描述

final数组竟然被改变了??final对象的值也被改变了?? 其实呢,由于数组是引用类型,final修饰引用类型时,只能保证这个变量永远"指向"那一段内存空间,保存的仅仅是一个引用,可是那段内存空间的值是能够改变的.修饰对象时也是同样的道理.

5.final修饰方法

final修饰的方法不能被重写,固然,不能"配合"private"使用",由于private把方法变成了私有,至关于对子类不可见,子类都不知道父类"还有这玩意",就能够进行所谓的"重写"了.

class A
{
	private final void f(){}
}
class B extends A
{
	public final void f(){}//没毛病
}

由于B类的f()是属于B类的,不是从A类继承过来的.

6.final修饰类

final修饰类时表示该类不能被继承.

final class A{}
class B extends A{}//出错

这是做者的公众号,欢迎关注.

在这里插入图片描述

相关文章
相关标签/搜索