字符串文字和字符串对象的添加之间的区别

如何解决字符串文字和字符串对象的添加之间的区别

|| 字符串文字和字符串对象的添加有什么区别? 例如
    String s1 =\"hello\";
    String s2 =\"hello1\";
    String s3 =\"hello\" + \"hello1\";
    String s4 =\"hellohello1\";
    String s5 = s1 + s2;

    System.out.println(s3 == s4); // returns true
    System.out.println(s3 == s5); // return false
    System.out.println(s4 == s5); // return false
为什么
s3
/
s4
s5
不在同一位置?     

解决方法

由于
s1 + s2
不是常数表达式,由于
s1
s2
不是
final
,因此其结果不会被求和,即创建另一个对象来表示它,因此引用比较将生成
false
。 JLS 3.10.5字符串文字:   字符串文字(或更一般而言,为常量表达式的值(第15.28节)的字符串)为“ interned \”,以便使用String.intern方法共享唯一的实例。 JLS 15.28常数表达式:   编译时常量表达式是表示原始类型或String的值的表达式,该值不会突然完成,并且仅使用以下内容组成:         ...   引用常量变量的简单名称(第4.12.4节)。    JLS 4.12.4定义了“ 7”个变量。 如果将
s1
s2
声明为
final
,则
s3 == s5
将是
true
。     ,因为您正在比较参考。要比较内容,请使用
s1.equals(s2)
。 如果您对引用的比较是有意的,则不清楚为什么您期望编译器/ JVM内收或不内收以不同方式产生的相同字符串。     ,编辑:我假设您知道您正在比较引用,而不是字符串的内容。如果否,那么您正在寻找ѭ16((如上所述)。 编译器将
s3
优化为
\"hellohello1\"
,ѭ2也重用了
s3
。我很惊讶该编译器不够聪明,无法对ѭ3进行相同的处理。您正在使用哪个JDK版本?仅对常量表达式允许这种优化(请参阅Java语言规范的15.28)。换句话说,对非最终变量的任何赋值都拒绝了后续优化的可能性。 这是一个简单类的ѭ21的输出,该类将您的代码包装到一个主要方法中(不是有人要它,但我很好奇我自己)。因此,让我们看看发生了什么:
public static void main(java.lang.String[]);
  Code:
    0:  ldc #16; //String hello
    2:  astore_1
    3:  ldc #18; //String hello1
    5:  astore_2
    6:  ldc #20; //String hellohello1
    8:  astore_3
    9:  ldc #20; //String hellohello1
    11: astore  4
    13: new #22; //class java/lang/StringBuilder
    16: dup
    17: aload_1
    18: invokestatic    #24; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
    21: invokespecial   #30; //Method java/lang/StringBuilder.\"<init>\":(Ljava/lang/String;)V
    24: aload_2
    25: invokevirtual   #33; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    28: invokevirtual   #37; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    31: astore  5
    33: getstatic   #41; //Field java/lang/System.out:Ljava/io/PrintStream;
    36: aload_3
    37: aload   4
    39: if_acmpne   46
    42: iconst_1
    43: goto    47
    46: iconst_0
    47: invokevirtual   #47; //Method java/io/PrintStream.println:(Z)V
    50: getstatic   #41; //Field java/lang/System.out:Ljava/io/PrintStream;
    53: aload_3
    54: aload   5
    56: if_acmpne   63
    59: iconst_1
    60: goto    64
    63: iconst_0
    64: invokevirtual   #47; //Method java/io/PrintStream.println:(Z)V
    67: getstatic   #41; //Field java/lang/System.out:Ljava/io/PrintStream;
    70: aload   4
    72: aload   5
    74: if_acmpne   81
    77: iconst_1
    78: goto    82
    81: iconst_0
    82: invokevirtual   #47; //Method java/io/PrintStream.println:(Z)V
    85: return

LocalVariableTable: 
  Start  Length  Slot  Name   Signature
   0     86      0     args   [Ljava/lang/String;
   3     83      1     s1     Ljava/lang/String;
   6     80      2     s2     Ljava/lang/String;
   9     77      3     s3     Ljava/lang/String;
  13     73      4     s4     Ljava/lang/String;
  33     53      5     s5     Ljava/lang/String;


}
我不是有经验的阅读字节码,但我会努力的:) 以#开头的数字(例如#16)是对常量池的引用。内容总是作为注释添加到此行
ldc #16
后跟
astore_1
表示“装入常数#16并将其存储在插槽1中”。如您所见,这在插槽1-4的开头执行了4次,转换为s1,s2,s3和s4(请参阅LocalVariableTable)。 对于s5,无需过多说明,显然有一个StringBuilder并加载了插槽1(in25ѭ)和插槽2(
aload_2
),然后将结果存储在插槽5(
astore 5
)中。     ,因为编译器优化了字符串文字的串联。 实际上,这并不重要(大部分时间),因为您通常希望使用equals方法比较Strings是否相等,而不要检查对象引用是否相同。 另请注意,您可以使用以下内容来实习s5:
s5 = s5.intern();
但是,这很少需要。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-