final关键字的字面意思是最终的, 不可修改的. 这似乎是一个看见名字就大概能知道怎么用的语法, 但你是否有深究过final在各个场景中的具体使用方法, 注意事项, 以及背后涉及的Java设计思想呢?
// 代码示例
public static void main(String[] args) {final Person p = new Person(20, "炭烧生蚝");p.setAge(18); //可以修改p对象的数据System.out.Age()); //输出18Person pp = new Person(30, "蚝生烧炭");p = pp; //这行代码会报错, 不能通过编译, 因为p经final修饰永远指向上面定义的p对象, 不能指向pp对象.
}
public static void main(String[] args) {int n1 = 2019; //普通变量final int n2 = 2019; //final修饰的变量String s = "20190522"; String s1 = n1 + "0522"; //拼接字符串"20190512"String s2 = n2 + "0522"; System.out.println(s == s1); //falseSystem.out.println(s == s2); //true
}
首先要介绍一点: 整数-127-128是默认加载到常量池里的, 也就是说如果涉及到-127-128的整数操作, 默认在编译期就能确定整数的值. 所以这里我故意选用数字2019(大于128), 避免数字默认就存在常量池中.
总结: 这个例子想说明的是: 由于被final修饰的常量会在编译期进入常量池, 如果有涉及到该常量的操作, 很有可能在编译期就已经完成.
提示: 在JDK1.8以后, 通过内部类访问外部局部变量时, 无需显式把外部局部变量声明为final. 不是说不需要声明为final了, 而是这件事情在编译期间系统帮我们做了. 但是我们还是有必要了解为什么要用final修饰外部局部变量.
public class Outter {public static void main(String[] args) {final int a = 10;new Thread(){@Overridepublic void run() {System.out.println(a);}}.start();}
}
javap -c .class文件的绝对路径
, 就能查看.class文件的反编译代码. 以上的Outter类经过编译产生两个.class文件, 分别是Outter.class和Outter$1.class
, 也就是说内部类会单独编译成一个.class文件. 下面给出Outter$1.class
的反编译代码.Compiled from "Outter.java"
final class forTest.Outter$1 extends java.lang.Thread {forTest.Outter$1();Code:0: aload_01: invokespecial #1 // Method java/lang/Thread."<init>":()V4: returnpublic void run();Code:0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;3: bipush 105: invokevirtual #3 // Method java/io/PrintStream.println:(I)V8: return
}
run()
方法反编译代码中的第3行:3: bipush 10
run()
方法执行过程中是以压栈的形式存储到本地变量表中的, 也就是说在内部类打印变量a的值时, 这个变量a不是外部的局部变量a, 因为如果是外部局部变量的话, 应该会使用load
指令加载变量的值. 也就是说系统以拷贝的形式把外部局部变量a复制了一个副本到内部类中, 内部类有一个变量指向外部变量a所指向的值.
//原代码
public static void test(){String s1 = "包夹方法a";a();String s2 = "包夹方法a";
}public static final void a(){System.out.println("我是方法a中的代码");System.out.println("我是方法a中的代码");
}//经过编译后
public static void test(){String s1 = "包夹方法a";System.out.println("我是方法a中的代码");System.out.println("我是方法a中的代码");String s2 = "包夹方法a";
}
本文发布于:2024-01-27 19:14:57,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063540972106.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |