Java 基本布尔值到字符串的连接/转换

Java 基本布尔值到字符串的连接/转换,java,string,casting,boolean,string-concatenation,Java,String,Casting,Boolean,String Concatenation,这是怎么回事?我似乎找不到答案 boolean bool=true; System.out.println("the value of bool is : " + true); //or System.out.println("the value of bool is : " + bool); 幕后发生的事情是什么 布尔值如何转换为字符串,因为布尔值不能隐式转换 类型铸造 是否涉及自动装箱/拆箱 像toString()或String.valueOf()这样的方法是以某种方式涉及的吗 这是一个

这是怎么回事?我似乎找不到答案

boolean bool=true;
System.out.println("the value of bool is : " + true);
//or
System.out.println("the value of bool is : " + bool);
  • 幕后发生的事情是什么
  • 布尔值如何转换为字符串,因为布尔值不能隐式转换 类型铸造
  • 是否涉及自动装箱/拆箱
  • toString()
    String.valueOf()
    这样的方法是以某种方式涉及的吗

    • 这是一个编译器的东西。如果用于连接的正确操作数是对象,则对象将通过
      toString()
      方法发送,而如果操作数是基元,则编译器知道使用哪种类型特定的行为将基元转换为字符串。

      Java语言规范中详细说明了确切的规则

      根据这些规则,
      “str”+bool
      相当于:

      "str" + new Boolean(bool).toString()
      
      boolean bool = true;
      System.out.println(new StringBuilder("the value of bool is : ").append(bool).toString());
      
      也就是说,编译器在如何准确计算整个表达式方面有很大的回旋余地。来自JLS:

      实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间字符串对象。为了提高重复字符串连接的性能,Java编译器可以使用
      StringBuffer
      类或类似技术来减少通过计算表达式创建的中间
      string
      对象的数量

      对于基本类型,实现还可以通过直接从基本类型转换为字符串来优化包装器对象的创建

      例如,使用我的编译器可以执行以下操作:

      boolean bool = true;
      System.out.println("the value of bool is : " + bool);
      
      完全等同于:

      "str" + new Boolean(bool).toString()
      
      boolean bool = true;
      System.out.println(new StringBuilder("the value of bool is : ").append(bool).toString());
      
      它们产生相同的字节码:

      Code:
         0: iconst_1      
         1: istore_1      
         2: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
         5: new           #166                // class java/lang/StringBuilder
         8: dup           
         9: ldc           #168                // String the value of bool is : 
        11: invokespecial #170                // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
        14: iload_1       
        15: invokevirtual #172                // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
        18: invokevirtual #176                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        21: invokevirtual #69                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        24: return        
      
      代码:
      0:iconst_1
      1:istore_1
      2:getstatic#59//Field java/lang/System.out:Ljava/io/PrintStream;
      5:new#166//class java/lang/StringBuilder
      8:dup
      9:ldc#168//String bool的值为:
      11:invokespecial#170//方法java/lang/StringBuilder。”“:(Ljava/lang/String;)V
      14:iload_1
      15:invokevirtual#172//方法java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      18:invokevirtual#176//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
      21:invokevirtual#69//方法java/io/PrintStream.println:(Ljava/lang/String;)V
      24:返回
      
      编译器将其翻译为

      StringBuilder sb = new StringBuilder("the value of bool is : ");
      sb.append(true);
      System.out.println(sb.toString());
      

      连接和转换的规则在中进行了解释。

      阅读本文:我明白了。。你能给我指一份文件吗?@VinayWadhwa:参考我的答案。两个代码段创建相同的字节码这一事实是否意味着前者必须转换为后者?(在转换成字节码之前,也就是说)@VinayWadhwa我不认为JLS指定了应该如何实现字符串连接——仅仅是结果应该是什么。然而,据我所知,SnorcleJava编译器使用
      StringBuffer
      ,然后是
      StringBuilder
      实现了它。让字符串连接成为JVM中的内在操作可能是完全允许的。@VinayWadhwa这似乎是这样暗示的:“为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer类或类似的技术…”和“对于基本类型,实现还可以优化包装器对象的创建…“哪个编译器?每个编译器?如果你能告诉我这些信息的来源,我将不胜感激。我认为,您提供的参考与您的答案无关。它说:实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间字符串对象。为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer类或类似技术来减少通过表达式求值创建的中间字符串对象的数量。要了解规则,请阅读JLS。要了解它的实际工作原理,请阅读编译器生成的字节码。