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);
}
}
领取专属 10元无门槛券
私享最新 技术干货