Java中是否存在运算符重载?

Bha*_*esh 4 java operator-overloading

我只想知道Java中的一个简单的事情.让我们考虑Java中的以下代码段.

int x=10;
String temp="x = "+x;
System.out.println(temp);
Run Code Online (Sandbox Code Playgroud)

在Java中完全有效并产生输出,x = 10作为字符串.


虽然变量x的类型为int,但它会自动转换为String类型(包装类型).Java如何做到这一点?像C++和C#一样,运算符重载在某种程度上或某处存在于Java中,尽管它已从Java中删除.这里使用哪个特定概念将x转换为字符串.我唯一想知道的事情


还有一个问题,在Java中,布尔数据类型(不是布尔值,包装类)不能转换为任何其他类型(根据我所知).为什么会这样,在某些非常特殊的情况下,将它转换为字符串或其他类型可能会有用.

Sco*_*t A 9

编译器在内部将该短语("x ="+ x)转换为StringBuilder,并使用.append(int)将整数"添加"到字符串中.

为了超越实际的"Java如何做到这一点",我将接受斯蒂芬的建议并给出理论.从概念上讲,串联中的每个值首先转换为String,然后连接.空值连接为单词"null".

Java语言规范:

15.18.1.1字符串转换

可以通过字符串转换将任何类型转换为String类型.首先将基本类型T的值x转换为引用值,就像将其作为参数提供给适当的类实例创建表达式一样:

如果T是布尔值,则使用new Boolean(x).如果T是char,则使用new Character(x).如果T是byte,short或int,则使用new Integer(x).如果T很长,则使用新的Long(x).如果T是float,则使用new Float(x).如果T为double,则使用new Double(x).然后通过字符串转换将此引用值转换为String类型.现在只需要考虑参考值.如果引用为null,则将其转换为字符串"null"(四个ASCII字符n,u,l,l).否则,执行转换就好像通过调用没有参数的引用对象的toString方法一样; 但是如果调用toString方法的结果为null,则使用字符串"null".

toString方法由原始类Object定义; 许多类都覆盖它,特别是Boolean,Character,Integer,Long,Float,Double和String.

15.18.1.2字符串连接的优化

实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间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();
}
Run Code Online (Sandbox Code Playgroud)

生成这个 - 看看两个连接样式如何导致相同的字节码:

 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
Run Code Online (Sandbox Code Playgroud)

编译器已将"cip + ciop"转换为"new StringBuilder(cip).append(ciop).toString()".换句话说,"+"实际上是更冗长的StringBuilder习语的简写.

  • 并且它还将接受字符串上+运算符的右操作数的任何类型.对于类实例,如果没有被继承子类之一覆盖,它将使用Object.toString()方法.对于基类型,它将执行类似的操作.Object.toString(),如果没有被覆盖,并且数组实例的输出将不是非常有用.使用例如1 +""将不起作用,因为整数实例将不允许创建StringBuilder,尝试执行整数加法instea(""+ 1可以作为变通方法). (2认同)