关键字final

基本概念


 用final修饰,表示“这部分是无法修改的”。不想被修改的原因有两个:效率、设计。使用到final的有三种情况:变量(数据)、方法、类。
 

final修饰变量


final可以修饰变量,表示该变量不能被重新赋值,因为这个变量其实是"常量"。
 修饰基本类型变量:表示赋值后数值不能改变。
 修饰引用类型变量:表示赋值后引用不能改变,但对象本身的属性可以改变。
 一个既是static又是final的字段只占据一段不能改变的存储空间。

在Java中,我们无法将对象修饰为final,而只能修饰对象的引用,这意味着即使你写public final A a = new A(); 事实上a指向的对象的数据依然可以被修改,不能修改的是a本身的引用值,即你不能再对a进行重赋值。比如public final int[] a = {1, 2, 3, 4, 5},事实上a中的数值是可修改的,即可以执行a[0] = 3。

final可以修饰参数。若某个参数被final修饰了,则代表了该参数是不可改变的。
 

final修饰方法


被final定义的方法不能被重新定义(注意,这里所说的不能被重新定义,并不是指子类一定不能定义同名方法,如果父类的方法是私有类型,子类是允许定义该方法的。【此时并不代表覆盖,因为覆盖是指覆盖掉能继承过来的东西,继承不过来,就不存在覆盖说法】。这里指的不能重新定义是指不能通过改写方法来使得方法重写的多态性得以实现),但可以被重载,可以被子类继承并使用一个定义为private的方法隐式的被指定为final类型。

 如果一个父类的某个方法被private修饰,子类将无法访问该方法,自然无法覆盖该方法,所以一个定义为private的方法可以隐式地被指定为final类型。
定义为final的方法可以提高运行时的效率。当一个方法被修饰为final方法时,意味着编译器可能将该方法用内联(inline)方式载入,所谓内联方式,是指编译器不用像平常调用函数那样的方式(例如保存断点,压栈等)来调用方法,而是直接将方法内的代码通过一定的修改后copy到原代码中。这样可以让代码执行的更快(因为省略了调用函数的开销)。然而当你的final方法主体非常庞大,或是在多处调用此方法时,会导致调用主体代码迅速膨胀,可能反而会影响效率,所以要慎用final进行方法定义。

 

final修饰类


定义为final的类不能被继承,不能再派生子类。将某个类定义为final形式,类中的所有方法都被隐式地设置为final形式,但类中的成员变量可以被定义为final也可以被定义为非final形式。
final不能修饰抽象类和接口。因为抽象类可以被继承,接口可以被接口继承,而final 类不能被继承,矛盾。
 

final初始化


修饰成员属性时:
方法1:定义时直接赋值
public class K{
	private final int k = 11; //编译时常量
    public static void main(String args[]) {
        K test1 = new K();
        System.out.println(test1.k); //11
    }
}
方法2:普通代码块中赋值
public class K{
	private final int k;
	{
		k = 11; //运行时常量
	}
    public static void main(String args[]) {
        K test1 = new K();
        K test2 = new K();
        System.out.println(test1.k);  //11
        System.out.println(test2.k); //11
    }
}
方法3:构造器中赋值
public class K{
	private final int k;
	public K(){
		k = 11; //运行时常量
	}
    public static void main(String args[]) {
        K test1 = new K();
        System.out.println(test1.k);  //11
    }
}
修饰局部变量时:
方法1
public class K{
    public static void main(String args[]) {
       final int k = 11;
       System.out.println(k); //11
    }
}
方法2
public class K{
    public static void main(String args[]) {
       final int k;
       k = 11;
       System.out.println(k); //11
    }
}

static final 变量的初始化(定义在非接口中时)


方法1:直接赋值:该静态字段的值在编译期已存入类的常量池中
class Test{
	public static final String G1 = “Hello”; //编译时常量
}
方法2:static 代码块中赋值
class Test{
	public static final String G1;
	static{
		G1="Hello"; //运行时常量
	}
}
static final 变量初始化时的注意事项:The final field Test.G1 cannot be assigned
ERROR:不能在 构造方法 中初始化
class Test{
 	public static final String G1;
	public Test() {
		G1="Hello"; //运行时常量
	}
}
ERROR:不能在 任何方法(静态/非静态) 中初始化
class Test{
 	public static final String G1;
	public void T() {
		G1="Hello"; //运行时常量
	}
}
ERROR:不能在 普通代码块 中初始化  //局部,同步代码块中也不行
class Test{
 	public static final String G1;
 	{
 		G1="Hello"; //运行时常量
 	}
}
ERROR:不能利用 变量仅static修饰时的默认初始化 特性
class Test{
 	public static final String G1;
}

static final 变量的初始化(定义在接口中时)


仅一种方法:定义时直接赋值(接口中无法定义初始值设定项,即各种代码块)
interface Test{
 	public static final String G1 = "Hello";  //编译时常量
}

附仅被static修饰的变量的初始化

无初始化赋值操作时的默认值问题:

 如果没有使用任意一种正确的初始化static变量的方式初始化static变量,则static 变量会被自动设置为一些初值。(0,0.0,null,char类型变量被设置 ‘\0’,等)。


方法1:定义时直接赋值
class LL{
	public static String G1 = "hello";
}
方法2:static中赋值
class LL{
	public static String G1;
	static{
		G1 = "hello";
	}
}
方法3:构造器中赋值
class LL{
	public static String G1;
	public LL(){
		G1 = "hello";
	}
}
方法4:在对象创建过程或对象的方法要执行的语句里写入初始化语句

初始化语句被成功执行的方法:创建对象,或先创建对象再调用方法

class LL{
	public static String G1;
	{
		G1 = "hello";
	}
	public LL() {
		G1 = "world";
	}
}
public class Test {
	  public static void main(String[] args) throws Exception {
		  LL n = new LL();
		  System.out.println(LL.G1); //world
	  }
}
LL.G1先显式被赋值为"hello"再显式被赋值为"world",最后输出 world。
class LL{
	public static String G1;
	public void KK() {
		G1 = "hello";
	}
}
public class Test {
	  public static void main(String[] args) throws Exception {
		  LL n = new LL();
		  n.KK();
		  System.out.println(LL.G1); //hello
	  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值