在常量的处理上,String和基本类型的处理有些类似的地方,那就是Constant Folding(暂且翻译成常量折叠)和常量传播。
废话不说,直接看代码:
public class Test {
public static void main(String[] args) {
System.out.println(TestFinal.str);
System.out.println(TestFinal.i);
}
}
使用的TestFinal类的代码:
public class TestFinal {
public static final int i=5;
public static final String str="Hello world";
}
直接反汇编Test.class文件:
javap -verbose Test >test.txt
结果:
Compiled from "Test.java"
public class Test extends java.lang.Object
SourceFile: "Test.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #7.#16; // java/lang/Object."<init>":()V <br>const #2 = Field #17.#18; // java/lang/System.out:Ljava/io/PrintStream; <br>const #3 = String #19; // Hello world <br>const #4 = Method #20.#21; // java/io/PrintStream.println:(Ljava/lang/String;)V <br>const #5 = Method #20.#22; // java/io/PrintStream.println:(I)V <br>const #6 = class #23; // Test <br>const #7 = class #24; // java/lang/Object <br>const #8 = Asciz <init>; <br>const #9 = Asciz ()V; <br>const #10 = Asciz Code; <br>const #11 = Asciz LineNumberTable; <br>const #12 = Asciz main; <br>const #13 = Asciz ([Ljava/lang/String;)V; <br>const #14 = Asciz SourceFile; <br>const #15 = Asciz Test.java; <br>const #16 = NameAndType #8:#9;// "<init>":()V <br>const #17 = class #25; // java/lang/System <br>const #18 = NameAndType #26:#27;// out:Ljava/io/PrintStream; <br>const #19 = Asciz Hello world; <br>const #20 = class #28; // java/io/PrintStream <br>const #21 = NameAndType #29:#30;// println:(Ljava/lang/String;)V <br>const #22 = NameAndType #29:#31;// println:(I)V <br>const #23 = Asciz Test; <br>const #24 = Asciz java/lang/Object; <br>const #25 = Asciz java/lang/System; <br>const #26 = Asciz out; <br>const #27 = Asciz Ljava/io/PrintStream;; <br>const #28 = Asciz java/io/PrintStream; <br>const #29 = Asciz println; <br>const #30 = Asciz (Ljava/lang/String;)V; <br>const #31 = Asciz (I)V; </init></init></init>
{
public Test();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V <br> 4: return <br> LineNumberTable: <br> line 1: 0 </init>
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String Hello world
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: iconst_5
12: invokevirtual #5; //Method java/io/PrintStream.println:(I)V
15: return
LineNumberTable:
line 3: 0
line 4: 8
line 5: 15
}
从里面可以看到,这个类根本没有TestFinal类的信息,使用的常量都直接替换为对应的值了。
所以,如果修改了TestFinal中的String常量和基本类型常量的值的话,一定要记得把相关的使用到该类中的变量的java文件(这里是Test.java)重新编译。
另外,众所周知,String是Immutable类,平时常见的Immutable类有很多,比如基本类型的wrapper类,Integer,Float等。但是分析问题的时候一定要注意场景,不要什么都和Immutable联系起来,比如这个例子:
public class Test {
public static void main(String[] args) {
String str="ImmutableString";
StringBuilder builder=new StringBuilder("可变的StringBuilder");
System.out.println(str);
System.out.println(builder);
change(str);
change(builder);
System.out.println(str);
System.out.println(builder);
}
public static void change(String str){
str="新的String";//
}
public static void change(StringBuilder builder){
builder=new StringBuilder("新的StringBuilder!");
}
}
只要对参数变量使用了赋值“=”处理,一切改变对外都是没有作用的,因此这个例子跟String的不变性没有任何关系。根本原因还是java的“pass by value”问题。关于这一点不想多说了,使用The Java Programming Language中的说法。
分享到:
相关推荐
答:不会发生死锁,(但有一点int是按值传递的,所以每次改变的都只是一个副本,因此不会出现死锁。但如果把int换做一个object,那么死锁会发生) 30.简要谈一下您对微软.NET 构架下remoting和webservice两项技术的...
- **接口定义**:接口是一种特殊的抽象类,它只包含抽象方法和常量(默认为`public static final`)。因此,选项A描述正确,即接口是抽象方法和常量值定义的集合。 - **接口实现**:多个不相关的类可以实现同一个...
`NaN`的一个奇特性质是它与任何值比较(包括自身)都返回`false`,这意味着`Double.NaN != Double.NaN`也成立。这是因为根据IEEE 754标准,`NaN`不等于任何值,包括自身,这使得在程序中处理`NaN`时需格外小心。 ##...
1. **串(String)**:串是一种特殊类型的线性表,由一个或多个字符组成。选项A正确表明了这一点。串的长度可以为零,即空串,但并不意味着空串就是空白串,空串仅仅是没有字符的串,选项D是错误的。串中元素可以是...
3. **处理特殊情况:** 如果最终`dp[M]`仍然为初始的最大值,则说明无法凑成该金额,输出"Impossible"。 **示例代码框架:** ```cpp #include #include using namespace std; int main() { int M, K; while ...
- **设计考虑**:由于数组的特殊性质(不能直接复制),没有提供自动管理数组的智能指针。 ##### 20. **可以混合使用 C 风格与 C++ 风格的内存分派与重新分配吗?** - **兼容性问题**:虽然理论上可行,但在实践...
- **知识点拓展**:通过实现`Runnable`接口的方式更灵活,因为它允许线程共享相同的代码,而继承`Thread`类则不能实现这一点。 #### 菜单使用 - **知识点11:快捷键使用** - 在软件中,许多菜单命令都提供了...
- 对于一般应用,`int`通常足够使用,但在处理特殊需求时(如大范围数字),`long`或`long long`更为合适。 **1.2 64位机上的64位类型是什么样的?** - 在64位系统上,`long long`类型通常是64位的,能表示的范围极...
)可以被用来分割某些特殊字符。举例如下: $first = 'Hello'; $second = "World"; $full1 = "$first $second"; # 产生 Hello World $full2 = '$first $second';# 产生 $first $second 可以将字符和数字利用运算...