`

Java final关键字

    博客分类:
  • Java
阅读更多

final 主要应用于两个方面:编译器常量,运行期常量(运行期初始化后不再改变).

主要应用场景:

1.final 基本数据:编译器常量

2.final对象引用:仅保持引用不变,引用的对象的具体属性等可以改变[对arr与string适用]

3.空白final:定义的时候未赋值,则使用前必须赋值,且必须在构造方法中赋值.

4.final参数:如果参数基本类型,则值不能改变,如果参数为引用,则引用不能改变

5.final方法:不能被子类重写(非重载),一定情况下,内嵌函数,提升性能

6.final类:不能为继承,不可变设计模式

7.特殊情况: 反射方法可以更改final,但是仅限于空白final的情况,具体测试如下:。

当final定义时,未赋值的时候,可以改变值。

 

public class Tests{
	 final int x;
	 public Tests(){
		 x=2;
	 }
	 	
	public static  void changeFieldByReflect(Tests t) throws Exception {
		Class clazz = t.getClass();
		Field fieldX = clazz.getDeclaredField("x");
		fieldX.setAccessible(true);
		fieldX.setInt(t, 500);
		System.out.println("chage x vlaue by reflect is " + fieldX.getInt(t));
	}
	
	public static void getFieldByReflect(Tests t) throws Exception{
		Class clazz = t.getClass();
		Field fieldX = clazz.getDeclaredField("x");
		fieldX.setAccessible(true);
		System.out.println("get x vlaue by reflect is " + fieldX.getInt(t));
	}
	
	public static void main(String[] args) throws Exception {
		System.out.println("////////////---对象 t");
		Tests t = new Tests();
		System.out.println("x filed is "+t.x);
		Tests.changeFieldByReflect(t);
		System.out.println("get x value by normal is "+t.x);
		Tests.getFieldByReflect(t);
		System.out.println("////////////---对象 tt");
		Tests tt = new Tests();
		Tests.getFieldByReflect(tt);

	}
}

 结果为:

////////////---对象 t

x filed is 2

chage x vlaue by reflect is 500

get x value by normal is 500

get x vlaue by reflect is 500

////////////---对象 tt

get x vlaue by reflect is 2


当final x定义的时候赋值了,则反射方法无法改变其值

 

 

public class Tests{
	 final int x=100;
	 public Tests(){
	 }
}
 

   result is:

////////////---对象 t

x filed is 100

chage x vlaue by reflect is 500

get x value by normal is 100

get x vlaue by reflect is 500

////////////---对象 tt

get x vlaue by reflect is 100

 

比较关键的一个API:

AccessibleObject.setAccessible(boolean flag)

将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查.

如果底层字段为 final 字段,则该方法将抛出一 个 IllegalAccessException,除非 setAccessible(true) 已经继承该字段并且该字段是一个非静态字段。在通过 程序的其他部分可以访问类的实例之前,只有使用空白 final 字段反序列化或重构类的实例期间,以这种方式设置 final 字段才有意义。在其他任 何上下文中使用该方法都可能会有不可预知的结果,包括程序的其他部分继续使用该字段的原始值的情况。

设置为true,取消访问检查,提升反射效率。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics