当前位置: 首页 > 面试题库 >

Java String类如何覆盖+运算符?

何向荣
2023-03-14
问题内容

当String是类时,为什么在Java中可以使用+运算符添加String?在String.java代码中,我没有找到该操作符的任何实现。这个概念是否违反了面向对象?


问题答案:

让我们看一下下面的Java简单表达式

int x=15;
String temp="x = "+x;

编译器"x = "+x;StringBuilder内部进行转换,并用于.append(int)将整数“添加”到字符串中。

5.1.11。字符串转换

可以通过字符串转换将任何类型转换为String类型。

首先将原始类型T的值x转换为参考值,就像通过将其作为适当的类实例创建表达式的参数(第15.9节):

  • 如果T为布尔值,则使用新的Boolean(x)。
  • 如果T为char,则使用新的Character(x)。
  • 如果T为byte,short或int,则使用新的Integer(x)。
  • 如果T长,则使用新的Long(x)。
  • 如果T为float,则使用新的Float(x)。
  • 如果T为double,则使用新的Double(x)。
  • 然后,通过字符串转换将该参考值转换为String类型。

现在只需要考虑参考值:

  • 如果引用为null,则将其转换为字符串“ null”(四个ASCII字符n,u,l,l)。
  • 否则,转换的执行就好像是通过调用不带参数的引用对象的toString方法进行的;但是,如果调用toString方法的结果为null,则使用字符串“ null”。
    toString方法由原始类Object(第4.3.2节)定义。许多类都覆盖它,特别是布尔,字符,整数,长整型,浮点型,双精度和字符串。

有关字符串转换上下文的详细信息,请参见§5.4。

15.18.1。

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

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

优化版本实际上不会首先进行完全包装的String转换。

这是编译器使用的优化版本的一个很好的例子,尽管无需转换原语,你可以在其中看到编译器在后台将事物更改为StringBuilder:

http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/

这个java代码:

public static void main(String[] args) {
    String cip = "cip";
    String ciop = "ciop";
    String plus = cip + ciop;
    String build = new StringBuilder(cip).append(ciop).toString();
}

生成此代码-查看两种串联样式如何导致相同的字节码:

 L0
    LINENUMBER 23 L0
    LDC "cip"
    ASTORE 1
   L1
    LINENUMBER 24 L1
    LDC "ciop"
    ASTORE 2

   // cip + ciop

   L2
    LINENUMBER 25 L2

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 3

    // new StringBuilder(cip).append(ciop).toString()

   L3
    LINENUMBER 26 L3

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 4
   L4
    LINENUMBER 27 L4
    RETURN

查看上面的示例以及如何基于给定示例中的源代码生成字节代码,你将能够注意到编译器已在内部转换了以下语句

cip+ciop; 

进入

new StringBuilder(cip).append(ciop).toString();

换句话说,+字符串连接中的运算符实际上是更冗长的StringBuilder习惯用法的简写形式。



 类似资料:
  • 问题内容: 我正在尝试从open jdk更改某些类,所以我正在创建与open jdk类相同的包结构,并且正在使用netbeans更改类。当我在构建项目时,如果覆盖类中出现问题,我会收到错误消息。如果成功构建了我的项目,则应用程序似乎不考虑我对类的更改,而是使用打开的jdk类。知道我该如何使用我的类而不是openjdk的类? 例: 如果我在项目中创建类 _sun.net.www.protocol.h

  • 问题内容: 我正在尝试Backbone.js,而我正在尝试的事情之一就是调用远程API,因此,据我了解的文档资料,我需要能够覆盖Backbone.sync 。 在文档本身中没有如何执行此操作的示例,并且似乎没有用于Backbone的google组…有人可以指出执行此操作的示例吗? 问题答案: 看看这个带注释的源示例,在该示例中,它们被本地存储替代项覆盖 基本上,Backbone.sync应该是一个

  • 使用Powershell 5,您现在可以实现自定义类。最终,您需要开始重载运算符以执行以下操作 但这似乎没有很好的记录,在Stack Overflow上搜索后,我找不到如何做到这一点。

  • 问题内容: 我创建了一个自定义样式表,该样式表将覆盖Wordpress模板的原始CSS。但是,在我的日历页面上,原始CSS具有声明的每个表格单元格的高度: 有什么办法可以覆盖这个吗? 问题答案: 覆盖!important修饰符 只需使用添加另一个CSS规则,并赋予选择器更高的特异性(向选择器添加其他标签,id或类) 在比现有选择器晚的位置添加具有相同选择器的CSS规则(平局中,最后一个定义的获胜者

  • 问题内容: 我的模型有很多布尔字段。我将它们分为3组,将其渲染为。 现在,我需要将此数据保存回数据库。即,我需要将单个小部件返回的数据拆分为多个布尔列。我认为这适合该方法,不是吗? 问题是,我该怎么做?像这样吗 如果是这样,如何设置值? 或者其他的东西?所有数据都存储在哪里? 问题答案: 你要存储数据的位置是新模型实例:

  • Net:“junitreport”似乎没有提供一种方法来设置它在执行转换时使用的临时文件夹,而且似乎也没有提供更新“java”的方法。io。报告任务的tmpdir。在这种情况下,请设置“user”。主页或java。io。调用ant时从命令行调用tmpdir不是一个可以使用的解决方案。 详细介绍:我在ant/mantis中使用junit任务,语法如下: 这似乎是一种非常标准的用法,添加了“echo”