javafinal修饰的数组_Java基于final修饰数据过程解析
这篇⽂章主要介绍了Java基于final修饰数据过程解析,⽂中通过⽰例代码介绍的⾮常详细,对⼤家的学习或者⼯作具有⼀定的参考学习价值,需要的朋友可以参考下
final是Java中的⼀个重要关键字,它可以修饰数据、⽅法和类,本篇将从final修饰的数据⾓度对final做出总结。
final修饰的数据代表着:永远不变。意思是,⼀旦你⽤final修饰⼀块数据,你之后就只能看看它,你想修改它,没门。
我们不希望改变的数据有下⾯两种情况:
永不改变的编译时常量。
//编译时知道其值
private final int valueOne = 9;
在运⾏时(不是编译时)被初始化的值,且之后不希望它改变。
/
/在编译时不能知道其值
private final int i4 = Int(20);
设置成常量有啥好处呢?
很简单,让编译器觉得简单,就是最⼤的好处。⽐如把PI设置成final,且给定值为3.14,编译器⾃然会觉得这个东西不会再被修改了,是⾜够权威的。那么,编译器就会在运⾏之前(编译时)就把这3.14代⼊所有的PI中计算,这样在真正运⾏的时候,速度⽅⾯当然会快⼀点。
有初始值的final域
即声明为final且当场就给定初始值的域。
private final int valueOne = 9;
final+基本数据类型
final修饰的基本数据类型变量存储的数值永恒不变。
/*基本类型变量*/
小新记事本怎么自动换行
//带有编译时数值的final基本类型
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
public static final int VALUE_THREE = 39;
//!false:fd1.valueOne++;
//!false:fd1.VALUE_TWO++;
//!false:fd1.VALUE_THREE++;
康康上⾯醒⽬的三句false语句,很好地印证了我们之前说的:数值不让改
需要注意的是,按照惯例,下⾯是定义常量的典型⽅式:
//典型常量的定义⽅式
public static final int VALUE_THREE = 39;
public修饰符使其可被⽤于包之外。
static使数据只有⼀份。
final表⽰其⽆法被更改
名称全为⼤写英⽂字母,以下划线隔开。
final+引⽤数据类型
我们之前说过,基本类型存数值,引⽤类型存地址值。那么既然final+基本数据类型不让改数值,聪明的我们稍微⼀联想就明⽩,final+引⽤数据类型就是不让你改变量存储实际对象的地址值啦。(也就是不能再让它指向新的对象,很专⼀)
private Value v1 = new Value(1);
private final Value v2 = new Value(22);
private static final Value V_3 = new Value(333);
//引⽤变量并不是常量,存储地址可以改变
fd1.v1 = new Value(10);
//v2是引⽤变量,final修饰之后表⽰地址不能改变,但是实际对象的值是可以改变的
fd1.v2.i++;
//!false:fd1.v2 = new Value(3);
//V_3与v2类似,是静态和⾮静态的区别,下⾯会说明
fd1.V_3.i++;
//!false:fd1.V_3 = new Value(10);
}
通过例⼦,确实也证明上⾯所说,⼀个以final修饰的引⽤数据类型变量,⽆法再指向⼀个新的对象,因为它所存储的地址值已经⽆法被更改,但是并不影响它指向的实际对象。就拿⼀个⽐较典型的引⽤类型来举例,我们知道数组就是⼀种典型的引⽤类型,数组的引⽤变量存储的是数组再堆中的地址,堆中存放的就是数组每个索引的数值。
/
*引⽤变量之数组*/
private final int[] a = {1,2,3,4,5,6};
引⽤变量a被指定为final,所以它⾥⾯的地址值不能再改,也就⽆法再让它指向⼀个新的数组。
//!false:fd1.a = new int[]{2,3,4,5,6,7};
for (int i = 0; i < fd1.a.length; i++) {
fd1.a[i]++;
java下载过程但是,它指向的数组⾥的每个元素却可以改动,因为数组中的元素并没有任何的限定。
final与static final
private final int i4 = Int(20);
static final int INT_5 = Int(20);
System.out.println(fd1);//fd1: i4 = 15,INT_518
FinalData fd2 = new FinalData("fd2");
System.out.println(fd2);//fd2: i4 = 13,INT_518
FinalData fd3 = new FinalData("fd3");
System.out.println(fd3);//fd3: i4 = 1,INT_5 = 18
上⾯⽰例分别创建了三个不同的对象,对其final 和final static 进⾏测试。
需要明确的是,两者都以final修饰,都不能被改变。
三个对象的i4值,没有⽤static修饰,不相同且不能改变。
⽽INT_5的值因为被static修饰,在类加载时已经被初始化,不随对象改变⽽改变。
空⽩final域
即声明为final却没有给定初始值的域。
private final String id;//空⽩final
如果只有上⾯的这句,编译器会报错,因为它没有初始化。
Variable 'id' might not have been initialized
所以,若定义了空⽩final域,⼀定记得在构造器中给它赋值!(必须在域的定义处或者每个构造器中以表达式对final进⾏赋值,因为系统不会为final域默认初始化)
运行jar包命令//在构造器中为空⽩final域赋初值
public FinalData(){
id = "空⽩final默认id";
}
public FinalData(String id){
this.id = id;
}
不要试图在初始化之前访问域,不然会报错。
final让域可以根据对象的不同⽽不同,增加灵活性的同时,⼜保留不被改变的特性。
final修饰的参数
基本数据类型的参数
类似地,就是传⼊的参数不让改,只让读,这⼀点很好理解。
public int finalParamTest(final int i){
//!false:i++;
//不让改,只让读
return i+1;
}
但是,我⼜新增了许多测试,分别定义四种不同的参数传⼊该⽅法,发现传⼊param0和param1编译会报错。(⾮常疑惑,这部分书上没提,查了许多资料也没有理解清楚,希望⼤⽜可以评论区指点迷津)
/*检测传⼊参数*/
int param0 = 5;
final int param1 = 10;
static final int PARAM_2 = 15;
static int param3 = 20;
//!false:System.out.println(fd1.finalParamTest(param0));
//!false:System.out.println(fd1.finalParamTest(param1));
//non-static field'param1' cannot be referenced from a static context
System.out.println(fd1.finalParamTest(PARAM_2));
System.out.println(fd1.finalParamTest(param3));
/*为什么形参列表⾥的参数⽤final修饰,但是⽤final修饰的param1⽆法传进去,
⼀定要static修饰?*/
引⽤数据类型的参数
public void finalReferenceTest(final FinalData fd){
//!false:fd = new FinalData();
//不能再指向新的对象,存储地址不准变
fd.param0++;
}
还是类似,不可以让这个引⽤类型的参数再指向新的对象,但是可以改变其实际指向对象的值。
最后的最后,下⾯的代码是根据《Thinking in Java》中的⽰例,结合⾃⼰的思想,将各个板块融合⽽成的超级⽆敌测试代码,冲冲冲!pac16;
python培训班视频import java.util.Arrays;
import java.util.Random;
/**
* @auther Summerday
*/
class Value{
int i;//package access
public Value(int i){
this.i =i;vlookup为什么比对不出来
}
}
/*final域在使⽤前必须被初始化:定义时,构造器中*/
public class FinalData {
/*检测传⼊参数*/
int param0 = 5;
final int param1 = 10;
static final int PARAM_2 = 15;
static int param3 = 20;
private static Random rand = new Random(47); private final String id;//空⽩final
public FinalData(){
id = "空⽩final默认id";
}
public FinalData(String id){
this.id = id;
}
/
/带有编译时数值的final基本类型
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
//典型常量的定义⽅式
public static final int VALUE_THREE = 39;django错误日志哪里看
//在编译是不能知道其值
private final int i4 = Int(20);
static final int INT_5 = Int(20);
private Value v1 = new Value(1);
private final Value v2 = new Value(22);
private static final Value V_3 = new Value(333); private final int[] a = {1,2,3,4,5,6};
@Override
public String toString(){
return id+": "+"i4 = "+i4+",INT_5 = "+INT_5;
}
public int finalParamTest(final int i){
//!false:i++;
//不让改,只让读
return i+1;
}
public void finalReferenceTest(final FinalData fd){ //!false:fd = new FinalData();
//不能再指向新的对象,存储地址不准变
fd.param0++;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论