String str和final String str有什么区别

hongweibing1 2015-07-11 05:03:09

String本来就是final
那String str和final String str有什么区别?


String a = "hello2";
final String b = "hello";
String c = "hello";

System.out.println(a==(b+2));
System.out.println(a==(c+2));


为什么第一个为true,第二个为false
...全文
3839 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
周英俊520 2019-08-01
  • 打赏
  • 举报
回复
为什么2楼答非所问还有人点赞 搞不懂
zjk_1991 2016-04-08
  • 打赏
  • 举报
回复
字符串对象可以存放在两个地方,字符串池(pool)和堆
编译期确定如何给一个引用变量赋值
1)String s="abc";这种形式决定将从pool中寻找内容相同的字符串并返回地址给s,pool中没有就会在pool中新建并返回地址给s
2)String s = new String("abc");这种形式决定运行期将在堆上新建字符串对象并返回给s,但这个对象不会加入到pool中
3)String s=s1+s2;s1和s2都是变量,这种形式决定将在堆上创建s1和s2(即便s1和s2指向的对象在池中已经存在,也会将值拷贝到对象创建新对象),然后创建s1+s2并赋给s
4)String s = "ab"+"cd";同1),都是来自于池
5)String s = "ab"+s1;类似3)
6)String s = S1+S2;S1和S2是常量,常量只能赋值一次,S1,S2如果在声明的地方就赋值,那么这个值在编译期就是确定的,后面无法更改,S1+S2在执行前可确定S1/S2已经在池中存在,当然在池中进行,所以s指向pool;但是若S1,S2如果是实例常量在构造器中赋值,或是类常量在静态块中赋值,S1+S2无法确定二者皆来自于池,于是在堆上进行
所以会有以下的结果
public class Test

{

public static final String A="ab";

public static final String B="cd";



public static final String C;

public static final String D;

static{

C = "ab";

D = "cd";

}

public static void main(String[] args) {

String t = "abcd";//指向池



String s1 = "ab";//指向池

String s2 = "cd";//指向池



String s = s1+s2;//指向堆

System.out.println(s==t);//false



String ss = "ab"+s2;//指向堆

System.out.println(ss==t);//false



String sss = "ab"+"cd";//指向池

System.out.println(sss==t);//true



String ssss = A+B;//指向池

System.out.println(ssss==t);//true



System.out.println((C+D)==t);//false

}
Crawl.W 2016-01-15
  • 打赏
  • 举报
回复
我理解是不是java优化内容是常量的变量定义直接是bound to的形式,==比较的是地址和里面的内容,我也是新手。非常量则是point to
多木多多木 2015-07-31
  • 打赏
  • 举报
回复 1
final关键字修饰的类不能被继承,修饰的方法不能被覆写,修饰的变量值不能修改。
cricel 2015-07-30
  • 打赏
  • 举报
回复
final String str 和 String str的区别就在于被final修饰的不能再改变,而没有被final修饰的String可以在后续继续改变值,final可以简单理解为最终变量,无法变化的量
小哥该吃药了 2015-07-14
  • 打赏
  • 举报
回复
楼上的说那么多,一句没看懂。。。。。
比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==
  • 打赏
  • 举报
回复
引用 8 楼 reliveIT 的回复:
[quote=引用 2 楼 qq118194716 的回复:] final的三种修饰,别搞混淆了 修饰类,表示该类不能被继承,就是你不能再去写它的子类了,意思是string没有子类了 修饰变量,修饰常量时,表示常量值固定不可更改,修饰类时表示指向的对象是固定的,不可以再指向其他对象了,但是如果对象是可变的你依然可以改变对象的内容 修饰方法,和修饰类有点像,表示该方法不能被子类复写 查string的源码 ,存数据的方式:

private final char value[];
表明String不仅不能被复写,连它里面存数组的域都是final的,意思你一旦初始化它你就没法改它了 a==(b+2) 的理解同楼上 a==(c+2) ,c+2 会返回 new String("hello2")而不是在常量池里寻找出来的
楼主还是很牛逼的。不过在JDK 8上不是new String,而是new StringBuilder。其他楼讲那么多,然而并没有什么卵用。 字节码常量池、方法区运行时常量池和堆内存,JVM什么时候用哪里区别清楚就可以了,和String类被final修饰没什么关系,和String中final修饰的value[]也没什么关系。
public cn.wxy.enumm.Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
  stack=1, locals=1, args_size=1
	 0: aload_0
	 1: invokespecial #8                  // Method java/lang/Object."<init>":()V
	 4: return
  LineNumberTable:
	line 3: 0
  LocalVariableTable:
	Start  Length  Slot  Name   Signature
		0       5     0  this   Lcn/wxy/enumm/Main;

public static void main(java.lang.String[])
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=5, locals=4, args_size=1
	 0: ldc           #16                 // String hello2
	 2: astore_1
	 3: ldc           #18                 // String hello
	 5: astore_2
	 6: ldc           #18                 // String hello
	 8: astore_3
	 9: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
	12: aload_1
	13: ldc           #16                 // String hello2
	15: if_acmpne     22
	18: iconst_1
	19: goto          23
	22: iconst_0
	23: invokevirtual #26                 // Method java/io/PrintStream.println:(Z)V
	26: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
	29: aload_1
	30: new           #32                 // class java/lang/StringBuilder
	33: dup
	34: aload_3
	35: invokestatic  #34                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
	38: invokespecial #40                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
	41: iconst_2
	42: invokevirtual #43                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
	45: invokevirtual #47                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
	48: if_acmpne     55
	51: iconst_1
	52: goto          56
	55: iconst_0
	56: invokevirtual #26                 // Method java/io/PrintStream.println:(Z)V
	59: return
  LineNumberTable:
	line 13: 0
	line 14: 3
	line 15: 6
	line 17: 9
	line 18: 26
	line 20: 59
  LocalVariableTable:
	Start  Length  Slot  Name   Signature
		0      60     0  args   [Ljava/lang/String;
		3      57     1     a   Ljava/lang/String;
		6      54     2     b   Ljava/lang/String;
		9      51     3     c   Ljava/lang/String;
[/quote] 忘了讲了,上面这个是楼主代码的编译后字节码,其实也就是虚拟机的执行步骤。 倒着讲: 1. 48、51、52、55的语义:a==(c+2),如果相等,则返回ture,否则返回false; 2. 从26到45都是为1的比较做准备,从局部变量表获取final b,iconst_2把2压运行时栈,然后new StringBuilder包起来; 3. 最后,a是直接从方法区常量池获取,而(c+2)则是等到运行时才能确定,直接从方法区中SB对象的toString方法获取,然后你比较地址,显然不相等。
  • 打赏
  • 举报
回复
引用 2 楼 qq118194716 的回复:
final的三种修饰,别搞混淆了 修饰类,表示该类不能被继承,就是你不能再去写它的子类了,意思是string没有子类了 修饰变量,修饰常量时,表示常量值固定不可更改,修饰类时表示指向的对象是固定的,不可以再指向其他对象了,但是如果对象是可变的你依然可以改变对象的内容 修饰方法,和修饰类有点像,表示该方法不能被子类复写 查string的源码 ,存数据的方式:

private final char value[];
表明String不仅不能被复写,连它里面存数组的域都是final的,意思你一旦初始化它你就没法改它了 a==(b+2) 的理解同楼上 a==(c+2) ,c+2 会返回 new String("hello2")而不是在常量池里寻找出来的
楼主还是很牛逼的。不过在JDK 8上不是new String,而是new StringBuilder。其他楼讲那么多,然而并没有什么卵用。 字节码常量池、方法区运行时常量池和堆内存,JVM什么时候用哪里区别清楚就可以了,和String类被final修饰没什么关系,和String中final修饰的value[]也没什么关系。
public cn.wxy.enumm.Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
  stack=1, locals=1, args_size=1
	 0: aload_0
	 1: invokespecial #8                  // Method java/lang/Object."<init>":()V
	 4: return
  LineNumberTable:
	line 3: 0
  LocalVariableTable:
	Start  Length  Slot  Name   Signature
		0       5     0  this   Lcn/wxy/enumm/Main;

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=5, locals=4, args_size=1
	 0: ldc           #16                 // String hello2
	 2: astore_1
	 3: ldc           #18                 // String hello
	 5: astore_2
	 6: ldc           #18                 // String hello
	 8: astore_3
	 9: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
	12: aload_1
	13: ldc           #16                 // String hello2
	15: if_acmpne     22
	18: iconst_1
	19: goto          23
	22: iconst_0
	23: invokevirtual #26                 // Method java/io/PrintStream.println:(Z)V
	26: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
	29: aload_1
	30: new           #32                 // class java/lang/StringBuilder
	33: dup
	34: aload_3
	35: invokestatic  #34                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
	38: invokespecial #40                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
	41: iconst_2
	42: invokevirtual #43                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
	45: invokevirtual #47                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
	48: if_acmpne     55
	51: iconst_1
	52: goto          56
	55: iconst_0
	56: invokevirtual #26                 // Method java/io/PrintStream.println:(Z)V
	59: return
  LineNumberTable:
	line 13: 0
	line 14: 3
	line 15: 6
	line 17: 9
	line 18: 26
	line 20: 59
  LocalVariableTable:
	Start  Length  Slot  Name   Signature
		0      60     0  args   [Ljava/lang/String;
		3      57     1     a   Ljava/lang/String;
		6      54     2     b   Ljava/lang/String;
		9      51     3     c   Ljava/lang/String;
hongweibing1 2015-07-12
  • 打赏
  • 举报
回复
多谢各位的关注
hongweibing1 2015-07-12
  • 打赏
  • 举报
回复
引用 2 楼 qq118194716 的回复:
final的三种修饰,别搞混淆了 修饰类,表示该类不能被继承,就是你不能再去写它的子类了,意思是string没有子类了 修饰变量,修饰常量时,表示常量值固定不可更改,修饰类时表示指向的对象是固定的,不可以再指向其他对象了,但是如果对象是可变的你依然可以改变对象的内容 修饰方法,和修饰类有点像,表示该方法不能被子类复写 查string的源码 ,存数据的方式:

private final char value[];
表明String不仅不能被复写,连它里面存数组的域都是final的,意思你一旦初始化它你就没法改它了 a==(b+2) 的理解同楼上 a==(c+2) ,c+2 会返回 new String("hello2")而不是在常量池里寻找出来的
非常感谢
hongweibing1 2015-07-12
  • 打赏
  • 举报
回复
引用 1 楼 Java_Web_Android 的回复:
楼主是final关键字没有掌握好。 用final声明的变量为常量,也就是说System.out.println(a==(b+2));和System.out.println(a==("hello"+2));效果是一样的。 符号+是连接字符串用的。
我好像明白点什么了,String本身是final修饰的是这个类,而final String str此时修饰的是变量str,谢谢呀
finemi 2015-07-11
  • 打赏
  • 举报
回复
又是一个final和String之间搞错的,,,所以我上次的String误解普及很有必要呀。。
alan19931103 2015-07-11
  • 打赏
  • 举报
回复
字符串内容没有区别。 但是引用有,final的引用不能再改变。
飏飏一蝶 2015-07-11
  • 打赏
  • 举报
回复
final的三种修饰,别搞混淆了 修饰类,表示该类不能被继承,就是你不能再去写它的子类了,意思是string没有子类了 修饰变量,修饰常量时,表示常量值固定不可更改,修饰类时表示指向的对象是固定的,不可以再指向其他对象了,但是如果对象是可变的你依然可以改变对象的内容 修饰方法,和修饰类有点像,表示该方法不能被子类复写 查string的源码 ,存数据的方式:

private final char value[];
表明String不仅不能被复写,连它里面存数组的域都是final的,意思你一旦初始化它你就没法改它了 a==(b+2) 的理解同楼上 a==(c+2) ,c+2 会返回 new String("hello2")而不是在常量池里寻找出来的
雨杉 2015-07-11
  • 打赏
  • 举报
回复
楼主是final关键字没有掌握好。 用final声明的变量为常量,也就是说System.out.println(a==(b+2));和System.out.println(a==("hello"+2));效果是一样的。 符号+是连接字符串用的。

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧