Java无法执行运算符重载,但+
和String
以及其他一些类可以正常运行Integer
。这怎么可能?
更新
为什么这样做?
Integer i = 4;
Integer p = 5;
System.out.println(i*p); // prints 20
答案 0 :(得分:7)
+
不是运算符重载的示例。 +
作为连接运算符和算术加法运算符构建在语言中。
这意味着用Java编写程序的人不能重载操作符,但就Java语言的语法而言,+
被定义为连接和加法运算符。
修改强>
由于autoboxing,它适用于Integer
和Double
等其他类。
如果您查看执行字符串连接的Java程序的字节码,您将看到它创建StringBuilder
并使用append()
方法。 Java编译器看到+
运算符,并意识到操作数是字符串而不是基本类型(如int
)。
如果查看执行整数加法的程序的字节码,您将看到它使用iadd
指令执行整数加法。这是因为编译器意识到+
操作的操作数是整数。
就像Integer i = 4
这样的事情而言,字节码会显示你实际上在做Integer i = Integer.valueOf(4)
。这称为自动装箱。稍后,当您执行i + p
之类的内容时,i
和p
都属于Integer
类型,生成的字节码将显示您正在执行i.intValue() + p.intValue()
},其中两个方法的返回类型都是int
(实际的字节码指令再次为iadd
)。
这就是+
工作Integer
的原因,即使它们不是真正的原始类型。
答案 1 :(得分:6)
由于autoboxing,它适用于像Integer这样的原始包装器。
它适用于String,因为它是special case for concatenating strings:
Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。字符串转换是通过方法toString实现的,由Object定义并由Java中的所有类继承。有关字符串连接和转换的其他信息,请参阅Gosling,Joy和Steele,Java语言规范。
答案 2 :(得分:5)
+
是一个内置操作。这是一个例外,不是规则。
答案 3 :(得分:2)
Java不允许自定义运算符重载,但编译器开发人员仍然可以告诉编译器String1 + String2 == String1String2,并用+运算符替换正确的串联方法调用
答案 4 :(得分:2)
Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。
String s = "string 1" + "string 2";
实际执行的是
(new StringBuilder()).append("string 1").append("string 2").toString()
答案 5 :(得分:1)
正如@yan所说,这是例外,而不是规则。字符串在Java中具有特殊的地位。 Java语言规范的一小部分专门用作+
作为字符串连接运算符的角色:§15.18.1。
关于您的更新,这是另一个特例。根据具体情况,Java 有时是,足够聪明,可以在需要String
时将非String
的内容转换为String
s。其中一个特殊情况是您描述的情况,其中原语出现在需要String
的地方。基元首先转换为其引用类型 - Integer
,Double
和& c。 - 然后通过String
方法进入toString()
。
另一个特殊情况是,String
和一个非String
与字符串连接运算符+
合并,如JLS §5.4 — String Conversion中所述。
为了完整性:+
更常见的“将数字加在一起”角色在§15.18§15.18.2 — Additive Operators (+ and -) for Numeric Types的其他部分中有所描述。