赞
踩
基本知识:被final修饰的变量,称为常量。常量的值是不可修改的。一般和static一起使用,称为静态常量。常量命名:字母全部大写
数据在内存中的存储:java中的内存分为:栈内存和堆内存。特点:栈的存取速度比较快,栈的内存要小于堆内存。基本类型存储在栈空间中,引用类型 栈中的引用指向堆空间
基本类型存储在栈空间中的示意图
引用类型 栈中的引用指向堆空间示意图
当final修饰的是一个基本数据类型时,这个数据的值再初始化后不能被改变。当final修饰的是一个引用类型数据时,也就是修饰一个对象时,引用再初始化后将永远指向一个内存地址,不可修改,但是该内存地址中保存的对象信息,是可以进行修改的。
final修饰基本数据类型时的内存示意图
在上图中,变量a在初始化后将永远指向003这块内存,而这块内存在初始化后将永远保存数值100
final修饰引用数据类型时的内存示意图
在上图中,变量p指向了0003这块内存,0003内存中保存的是对象p的句柄(存放对象p数据的内存地址),这个句柄值是不能被修改的,也就是变量p永远指向p对象,但是p对象的数据是可以修改的。
public class Test_final { private int n1 = 2020; //普通变量 private static final int n2 = 2020; //final修饰的变量 private int age = 4; //普通变量 private static final double PI = 3.1415926; //final修饰的变量 private static final String PASSWORD = "123456";//final修饰的变量 public static void main(String[] args) { Test_final t = new Test_final(); t.test(); } public void test(){ // PI = 3; //编译错误,出现红色波浪线,不可以修改 age = 9; System.out.println(age); //9 4的值被9覆盖 System.out.println(PI); //3.1415926 final User u = new User("tom",12,1001); //final修饰的引用数据类型 u.setName("alice"); System.out.println(u.getName()); //alice User类对象u里的名字name变量值被修改 User u2 = new User("jack",13,1002); // u = u2; //编译错误,出现红色波浪线,因为u经final修饰永远指向上面定义的u对象,不能指向u2对象 System.out.println(u); //Error:(22, 9) java: 无法为最终变量u分配值 这是系统提示报错的信息 //不变性 String a = "tom"; //字符常量,放在常量池 a = "jack"; //常量池中有两个String对象 String b = "tom"; //创建流程:先判断常量池是否存在tom,如果有,就直接指向 System.out.println(a); //jack 当重新赋值,会在内存中再次分配一块新的空间 String s = "20200202"; //字符常量,放在常量池 String s1 = n1 + "0202"; String s2 = n2 + "0202"; System.out.println(s1); //20200202 System.out.println(s2); //20200202 System.out.println(s == s1);//false System.out.println(s == s2);//true //问题1 String s3 = "2020"; String s4 = s3 + "0202"; //不是字符常量 System.out.println(s == s4);//false //问题2 String s5 = "2020" + "0202";//是字符常量,在编译时已经确定值 System.out.println(s == s5);//true //问题3 String s6 = "2020"; String s7 = "0202"; String s8 = s6 + s7; //不是字符常量 s8不是通过双引号直接创建,通过运算得到的 System.out.println(s == s8);//false } } class Animal{ public final void show(){ } } final class Dog extends Animal{ //不能被重写 // @Override // public void show(){ // // } public void sum(final int a, int b){ // a = 9; //出现红色波浪线,编译错误,不能修改 b = 6; int sum = a + b; } } //Dog类不能有子类 //class YellowDog extends Dog{ // //}
// PI = 3; //编译错误,出现红色波浪线,不可以修改
age = 9;
System.out.println(age); //9 4的值被9覆盖
System.out.println(PI); //3.1415926
final User u = new User("tom",12,1001); //final修饰的引用数据类型
u.setName("alice");
System.out.println(u.getName()); //alice User类对象u里的名字name变量值被修改
User u2 = new User("jack",13,1002);
// u = u2; //编译错误,出现红色波浪线,因为u经final修饰永远指向上面定义的u对象,不能指向u2对象
System.out.println(u); //Error:(22, 9) java: 无法为最终变量u分配值 这是系统提示报错的信息
//不变性
String a = "tom"; //字符常量,放在常量池
a = "jack"; //常量池中有两个String对象
String b = "tom"; //创建流程:先判断常量池是否存在tom,如果有,就直接指向
System.out.println(a); //jack 当重新赋值,会在内存中再次分配一块新的空间
String s = "20200202"; //字符常量,放在常量池
String s1 = n1 + "0202";
String s2 = n2 + "0202";
System.out.println(s1); //20200202
System.out.println(s2); //20200202
System.out.println(s == s1);//false
System.out.println(s == s2);//true
总结:这个例子想说明的是,由于被final修饰的常量会在编译期进入常量池,如果有涉及到该常量的操作,很有可能在编译期就已经完成。
String s = "20200202"; //字符常量,放在常量池
//问题1
String s3 = "2020";
String s4 = s3 + "0202"; //不是字符常量
System.out.println(s == s4);//false
//问题2
String s5 = "2020" + "0202";//是字符常量,在编译时已经确定值
System.out.println(s == s5);//true
//问题3
String s6 = "2020";
String s7 = "0202";
String s8 = s6 + s7; //不是字符常量 s8不是通过双引号直接创建,通过运算得到的
System.out.println(s == s8);//false
class Animal{
public final void show(){
}
}
final class Dog extends Animal{
//不能被重写
// @Override
// public void show(){
//
// }
}
final class Dog extends Animal{
//不能被重写
// @Override
// public void show(){
//
// }
}
//Dog类不能有子类.不能被继承
class YellowDog extends Dog{
}
final class Dog extends Animal{
//不能被重写
// @Override
// public void show(){
//
// }
public void sum(final int a, int b){
// a = 9; //出现红色波浪线,编译错误,不能修改
b = 6;
int sum = a + b;
}
}
如果对你有帮助,点个赞吧0.0
若有不正之处,请多多谅解并欢迎批评指正,不甚感激
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。