繁体   English   中英

Java:字符串文字和+运算符

[英]Java: String literal and + operator

import java.util.*;
import java.lang.*;
import java.io.*;    

class Test {
   public static void main (String[] args)  {

      String a="hello"+"world";  //line 1
      String b="hello";
      String c="world";
      String d=b+c;
      String e="helloworld";
      System.out.println(e==a);
      System.out.println(a==d);
     }
}

输出:

true

false

通过这次讨论,String类如何覆盖+运算符? 我知道'a'和'e'将引用相同的String文字对象。

有人能告诉我吗

  1. 为什么ad没有引用相同的字符串文字对象?

  2. 第1行中创建了多少个对象

JLS 4.3.3起。 类字符串

当结果不是编译时常量表达式(第15.28节)时,字符串串联运算符+ (第15.18.1节)隐式创建一个新的String对象。

因为a的字面值是"helloworld" ,而d的字面值是b + c的引用对象,所以它不是JLS 4.3.3以上的字面值。

JLS 3.10.5字符串文字开始

字符串文字包含零个或多个用双引号引起来的字符。

15.28开始。 常数表达式

编译时常量表达式是表示原始类型或String的值的表达式,该值不会突然完成,并且仅使用以下内容组成:

  • 基本类型的文字和字符串类型的文字(§3.10.1,§3.10.2,§3.10.3,§3.10.4,§3.10.5)

如果要制作System.out.println(a==d); 真正使用final关键字,请参见以下代码:

  String a="hello"+"world";  //line 1
  final String b="hello"; // now b is a literal
  final String c="world";// now c is a literal
  String d=b+c;
  String e="helloworld";
  System.out.println(e==a);
  System.out.println(a==d);// now it will be true because both are literals.

回答评论:
在第1行中创建了多少个对象:答案是3
字符串a =“ hello” +“ world”;

第一个文字对象hello
第二文字对象world
第三文字对象"hello"+"world" == "helloworld"

==符号检查对变量的引用是否相同。 要检查是否有任何对象与其他对象相等,请使用Object.equals(Object o)方法,如下所示:

e.equals(a);

==运算符检查引用相等性,而不检查对象相等性。 在您的示例中,创建了两个内容为"helloworld" String实例。 变量ae指向同一个实例(见下文),而ad没有。 可以使用equals()方法检查字符串是否相等,即a.equals(d)为true。

ae引用同一实例的原因是String常量是内在的。 每次遇到一个字符串常量(例如"helloworld" )时,都会检查是否已遇到这样的常量,如果已经遇到,则将返回旧的String实例,而不是创建一个新的实例。 尽管"hello" + "world"看起来不像String常量,但是Java编译器已将其优化为String常量,因此它像e一样被内插,这就是a == e为true的原因。 相反, b + c没有优化为常数,这就是为什么a == d为假(但是a.equals(d)为真)的原因。

1)这是因为String对象是不可变的。 一旦创建了String对象并为其分配了一个值,它就永远具有无法更改的相同值。 因此,当您对它进行任何操作(例如,联接)时,总会创建一个新的String对象。

在堆中,有一个特殊的部分用作String常量的池。 如果编译器遇到String文字,则它首先检查内存的这一部分是否已经存在相同的对象( String )。 如果是这样,它将为这个已经存在的对象( String )分配一个引用,而不是创建一个新的引用。 (这就是String不可变的原因,因此没有人可以更改它。因为如果多个引用指向此String,而其中一个引用将更改其值,则会造成混乱。)

现在,让我们看一下此代码段中的情况,并尝试一次找到两个问题的答案。

(1) String a="hello"+"world";  //line 1
(2) String b="hello"; // now b is a literal
(3) String c="world";
(4) String d=b+c;
(5) String e="helloworld";
(6) System.out.println(e==a);
(7) System.out.println(a==d);

(1)首先,创建一个指向String类型的参考值a 然后,在前面提到的堆中的这个特殊池中创建了文字“ hello”(第一个String对象)。 然后在池中创建文字“世界”(第二个String对象)。 然后,由于字符串是不可变的,因此在该池中创建了另一个文字-“ helloworld”,并将其分配给此引用变量a (第三个字符串对象-这是对问题2的回答)。

(2)在(1)中创建的文字“ hello”和“ world”是在池中创建的,没有分配任何参考值,但它们仍然存在于该池中。 在此行中,创建了类型为String b的引用变量,并将其分配给池中存在的此文字“ hello”。

(3)与(2)相同

(4)创建类型为String d的参考值。 尽管在这个特殊的堆部分(池)中已经有一个字符串文字,其值为“ helloworld”,但是在堆中创建了一个值为“ helloworld”的新String对象 -这意味着在堆的非池部分。 因此,您有两个不同的String类型的对象,其值均为“ helloworld”(一个在池中,另一个在堆的非池部分中)。 如果现在与==运算符参考值ad进行比较,它们都指向不同的对象(尽管具有相同的值,所以方法equals将返回true)。

(5)创建字符串类型的参考值e 在堆的池部分中,已经有一个字符串“ helloworld”(我们在(1)中创建了它,并将其指向引用变量a ),因此将引用变量e分配给了此对象。 并指向同一个地方 因此,如果您比较引用a == e,则为true。 方法等于

(6)和(7)在前面的几点中进行了解释

TLDR:

1)因为它不是同一对象

2)3

==运算符检查两个对象是否引用内存中的相同位置。

a = "hello" + "world;" 计算为文字"helloworld"并给出e="helloworld" 它们引用相同的存储位置。 因此,表达式e==a计算为true。

表达式d=b+c计算结果也为"helloworld"但此结果存储在其他位置。 它没有引用相同的对象。 因此,表达式a==d计算结果为false。

使用a.equals(d)将输出true,因为equals()检查2个对象的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM