1.
首先补充一个地方:
class前面如果不加任何修饰符,则默认为default
显示这段代码输出结果:
分析这段代码:
输出结果如下:
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd2:i4=13 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd2:i4=1 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd2:i4=1 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd2:i4=9 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd2:i4=8 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd2:i4=0 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd1:i4=15 ,INT_5 = 18
fd2:i4=2 ,INT_5 = 18
可以得知INT_5=18是一直不会去发生改变的,来看下是如何定义的:
再来看一下i4是如何定义的:
但是为什么fd2的i4是一直变化的,但是fd1是一直不变的
永不改变的编译常量:编译期常量定义,根据惯例,即是static又是final域的也就是编译期常量。
不能因为数据是final的就认为在编译时可以知道他的值,运行时使用rand函数进行随机生成数值进行初始化i4和INT_5就说明了这点;
在数值部分,也定义了静态和非静态的区别:
次区别只有在数值运行时被初始化后才会被显现,static是静态的,因此因此INT_5的值是唯一的,是不可以通过创建第二个finaldata对象而加以改变的,因为他是static的,在装载时已经被初始化的了,但是不是每次创建对象时都会进行初始化操作。
v1到vAL_3说明了final的引用意义,
不能因为v2是final的,就认为他是无法改变他的值,他是一个引用,final意味着无法将v2再次指向一个新的对象:
数组定义如下:
其中a是数组对象:
由此可以得知final是可以改变的但是不可以指向新的对象,佐证如下:
final定义的变量可以在同一个对象的情况下被改变,但是如果换了一个对象,那么就是不能再赋予新的值的,作用域是一个对象内部,
但是作用域即是static又是final的则是编译产量,因此是存在于整个生命周期的,不可以轻易被改变的。
完整验证代码如下,可以复制拿去验证:
import java.util.Random;
public class finalData {
private static Random rand=new Random(47);
private String id;
public finalData(String id){ // 定义一个构造方法
this.id=id;
}
private final int Valueone=9;
private static final int VALUE_TWO=99;
//以上两个都带有final,因此可以用作编译期常量,区别并不是很大
private static final int VALUE_THREE=39;
/**上面一行是常用的用于定义编译期常量的写法,定义为public表示可以为包之外所用,
* 定义为static,则强调只有一份
* 定义为final,则说明他是一个常量
* 带有恒定初始值也就是编译常量:
* 根据惯例,编译常量也就是即是final域又是static域的。
*/
private final int i4=rand.nextInt(20);
static final int INT_5=rand.nextInt(20);
private Value v1=new Value(11);
private final Value v2=new Value(22);
private static final Value v3=new Value(33);
private final int[] a={1,2,3,4,5,6,7};
public String toString(){
return id+":"+"i4="+i4+" ,INT_5 = "+INT_5;
}
public static void main(String[] args){
finalData fd1=new finalData("fd1");
//fd1.Valueone++;//调用的时候发现会有错误, private final int Valueone=9;
fd1.v2.i++;//将i中值自增1,看看是否会变成23
fd1.v1=new Value(9);//看下将v1的参数从11改成9会不会成功 private Value v1=new Value(11);//这个可以的运行无错误
for(int i=0;i<fd1.a.length;i++){//取fd1类中数组的长度作为循环的次数
fd1.a[i]++; //对象的持续性变化
System.out.println("验证fd1.a[i]++等于 =="+fd1.a[i]++);
// fd1.v2=new Value(0); //Error:(28, 16) java: 无法为最终变量v2分配值
// fd1.v3=new Value(1); //Error:(29, 16) java: 无法为最终变量v3分配值
// fd1.a=new int[3]; //Error:(30, 16) java: 无法为最终变量a分配值
System.out.println(fd1);
System.out.println(fd1);
finalData fd2=new finalData("fd2");
System.out.println(fd1);
System.out.println(fd2);
}
}
}