java-final修饰符问题

final实例变量和类变量初始化如下:

public class FinalInstanceVaribaleTest {

/*

* 对于final类变量而言,必须显示指定初始值

* 1.定义final类变量时指定初始值

* 2.在静态初始化块中为final类变量指定初始值

* 最终都会被抽取到构造器中赋初始值

*/

///定义final类变量时赋初始值

final static int svar1="Java讲义".length();;

final static int svar2;

/*

* 对于final实例变量在下列三个位置指定初始值

* 1.定义final实例变量时指定初始值

* 2.在非静态初始化块为final实例变量指定初始值

* 3.在构造器中为final实例变量指定初始值

* 最终都会被抽取到静态初始块中赋初始值,除些外不能被赋值

*/

///在静态初始化块中时赋值

static{

svar2="XML讲义".length();

}

//定义Java实例变量时赋初始值

final int var1="Java讲义".length();

final int var2;

final int var3;

//在初始化块中为var2赋初始值

{

var2="轻量级JavaEE企业应用实战".length();

}

//在构造器为var3赋初始值

public FinalInstanceVaribaleTest(){

this.var3="XML讲义".length();

}

public static void main(String[] args) {

FinalInstanceVaribaleTest fiv=new FinalInstanceVaribaleTest();

}

}

final作用:当initPrice不使用final修饰时currentPrice为-2.8,因为INSTANCE对象初始化时initPrice还未初始化成20,所以currentPrice为负。

class Price{

final static Price INSTANCE=new Price(2.8);//首先执行,initPrice=0

static double initPrice=20;

double currentPrice;

public Price(double discount){

currentPrice=initPrice-discount;

}

}

public class PriceTest {

public static void main(String[] args) {

Price p=new Price(2.8);

}

}

Result:

-2.8

17.2

当initPrice使用final修饰时currentPrice为17.2,因为对于一个使用final修饰的变量而言,如果定义该final指定初始值,并且这个初始值(形如2,2.3,“java”这样的直接量)可以在编译时就确定下来,那么它将成为一个宏变量,直接进行替换成对应值。对于上面的currentPrice=initPrice-discount;效果相当于:currentPrice=20-discount;PS:对于类变量、实例变量而言,只有在定义时赋初始值才可以起到宏替换的作用.

class Price{

final static Price INSTANCE=new Price(2.8);

final static double initPrice=20;

double currentPrice;

public Price(double discount){

currentPrice=initPrice-discount;

}

}

public class PriceTest {

public static void main(String[] args) {

Price p=new Price(2.8);

}

}

Result:

17.2

17.2

小结:对于一个final变量,不管它是类变量还是实例变量,只要定义该变量使用了final修饰符,在定义时指定了初始值,并且这个值(字面量、直接量)可以在编译时定下来,那么这个final变量本年上已经不再是变量了,而是相当于一个直接量。如下普通变量宏替换

public class FinalTest {

public static void main(String[] args) {

///下面定义了四个宏变量

final int a=5+2;

final double b=1.2/3;

final String str="Java";

final String book1="Java:"+99.0;

///book2无法在编译时确定下来

final String book2="Java:"+String.valueOf(99.0);

System.out.println(book1=="Java:99.0");///true

System.out.println(book2=="Java:99.0");///false

/*

* Java会缓存曾经用过的字符串直接量。如String a="java",字符串

* 池中就会缓存了一个字符串"java",如果程序再次执行String b="java"

* 会让b直接指向字符串池中"java"字符串,因此a==b将会返回true

*/

final String str1="Java讲义";

final String str2="Java"+"讲义";

System.out.println(str1==str2);///true

///定义普通直接量

String fs1="Java";

String fs2="讲义";

String fs3=fs1+fs2;///两个普通量不会执行宏替换

System.out.println(str1==fs3);//false

///定义字符串直接量

final String s1="Java";

final String s2="讲义";

String s3=s1+s2;////执行宏替换

System.out.println(str1==s3);///true

}

}

final修饰方法时,不可以被子类重写,可以使用@Override注解强制重写测试。final还用于内部类中的局部变量,如果程序需要在匿名内部类(局部内部类)中使用局部变量,这个局部变量需要使用final修饰符修饰。PS:由于内部类可能扩大局部变量的作用域,并且不加final修饰符修饰可能导致该变量值可以随意改变,会引起极大混乱。

interface IntArrayProductor{

int product();

}

public class CommandTest {

public int[] process(IntArrayProductor cmd,int length){

int[] result=new int[length];

for (int i = 0; i

result[i]=cmd.product();

}

return result;

}

public static void main(String[] args) {

CommandTest ct=new CommandTest();

final int seed=5;

int[] result=ct.process(new IntArrayProductor() {

@Override

public int product() {

// TODO Auto-generated method stub

return (int)Math.round(Math.random()*seed);

}

}, 6);

}

}

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180507G1F0H700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券