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

标签 java operator-overloading

我只想了解 Java 中的一件简单的事情。让我们考虑以下 Java 代码段。

int x=10;
String temp="x = "+x;
System.out.println(temp);

在 Java 中完全有效并生成输出 x = 10 作为字符串。


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


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

最佳答案

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

为了超越实际的“Java 如何做到这一点”,我将采纳 Stephen 的建议并提供理论知识。从概念上讲,连接中的每个值首先转换为 String,然后连接。空值被连接为单词“null”。

来自Java Language Specification :

15.18.1.1 String Conversion

Any type may be converted to type String by string conversion. A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression:

If T is boolean, then use new Boolean(x). If T is char, then use new Character(x). If T is byte, short, or int, then use new Integer(x). If T is long, then use new Long(x). If T is float, then use new Float(x). If T is double, then use new Double(x). This reference value is then converted to type String by string conversion. Now only reference values need to be considered. If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.

The toString method is defined by the primordial class Object; many classes override it, notably Boolean, Character, Integer, Long, Float, Double, and String.

15.18.1.2 Optimization of String Concatenation

An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression. For primitive types, an implementation may also optimize away the creation of a wrapper object by converting directly from a primitive type to a 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 习语的简写。

关于java - Java 中是否存在运算符重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8003206/

相关文章:

java - 如何使用 ExecutorService 等待所有线程完成?

带 1 个参数的 C++ 2D 数组索引(为什么这行得通?)

C++:在多态单例类上重载删除

C++ 运算符== 重载

Ruby:仅在某些情况下重载运算符行为

Java 简单的网络浏览器奇怪的输出

java - 为什么每次执行以下代码时 main 是第一个执行的线程

java - 在此实例中正确使用 "for"

java - 处理:复数库?

c++ - C++ 中的运算符重载