黑马程序员技术交流社区

标题: 关于运算符重载的问题 [打印本页]

作者: 刘敏    时间: 2013-11-28 23:48
标题: 关于运算符重载的问题
本帖最后由 刘敏 于 2013-11-29 11:23 编辑

我看见Java里面直接用+,== 做一些非基本类型的操作。
比如:“asd”+ 5; if(对象==对象)
里面应该做了类似C++的操作符重载,但这些重载在哪里定义的呢? 我在Object类中也没看见呢?

作者: ″先森丶玹°    时间: 2013-11-29 00:12
equals方法是比较对象的
还有就是compareTo
你仔细找找肯定有
作者: 张天昊76    时间: 2013-11-29 00:20
对于C++我不清楚,在java中,+除了作为算术运算的加法外,还可以用来用来拼接字符串。例如:
  1. String s = "12" + 34;//  s的值不是36,而是字符串1234.
复制代码

至于你说的if(对象==对象)是判断两个对象时否想相等。

作者: 冯晓骏    时间: 2013-11-29 00:21
我不了解C++中的运算符重载怎么回事,谈谈我的理解吧,应该都是编译器的事,"asd"+5,应该是先将5自动装箱变成Integer,然后用toString方法,if(对象==对象)只是比较的地址值,这个跟重载没关系吧,任何类型的对象在堆中都有一个地址值,即使是基本数据类型,也有对应的类和对象,所以应该都是编译器编译的时候为代码进行了变形,估计读读JVM之类的书会找到
另外,网上给出的解释是,当+号两端都是字符串的时候,由于一开始设计的缺陷,导致中间会产生很多中间字符串常量,比如str = “a”+“b”+“c”,你想得到的只是"abc",但是在内存里产生了a,b,c和ab这样的中间常量,因为String是只读的,所以长度不可变嘛,这个时候开发者发现了,然后在编译器中修改成了String这种加法会自动转成StringBuffer来表示,即str = new Stringbuffer().append(a) .append(b).append(c).toString()这种形式,这样就不会产生大量的中间产物,节省了空间
希望能帮到你
作者: 刘敏    时间: 2013-11-29 00:38
冯晓骏 发表于 2013-11-29 00:21
我不了解C++中的运算符重载怎么回事,谈谈我的理解吧,应该都是编译器的事,"asd"+5,应该是先将5自动装箱 ...

非常感谢!刚逛论坛的时候看到了下面的例子多想了,其实== 没重载,只不过就是对象的地址在比较。
最后那个c==d是false只是因为 两个"aa"在内存中的地址不同罢了。
public class Demo {

public static void main(String[] args)
{
        String a="a";
        String b=a;
        String c=b+a;
        String d="a"+"a";
        String m=new String("a");
        
        System.out.println(c.hashCode()+"--"+d.hashCode()+"--"+m.hashCode());
        System.out.println(c.equals(d));
        System.out.println(c==d);
}
}

作者: HAnG    时间: 2013-11-29 00:45
我学过C++的运算符重载,但是据我了解Java是不支持运算符重载的,
而你说的那个String类的"+"应该是唯一的一个运算符重载,还是java本身定义好的。
作者: 冯晓骏    时间: 2013-11-29 00:52
刘敏 发表于 2013-11-29 00:38
非常感谢!刚逛论坛的时候看到了下面的例子多想了,其实== 没重载,只不过就是对象的地址在比较。
最后那 ...

其实没那么简单,我也在思考这个问题,现在还没有读JVM的书,所以有点人云亦云了,因为java的底层设计思想还是很发杂的,就一个String就牵扯出了很多东西,什么常量池之类的,还有什么时候new一个对象,什么时候直接返回常量池中对象的地址,这些我现在还不确定,希望以后我们有了结论可以互相交流
作者: 刘敏    时间: 2013-11-29 09:08
本帖最后由 刘敏 于 2013-11-29 09:13 编辑
冯晓骏 发表于 2013-11-29 00:52
其实没那么简单,我也在思考这个问题,现在还没有读JVM的书,所以有点人云亦云了,因为java的底层设计思 ...

做了一个实验:
String a = "test";String b = "test" +"bbb";
String c = a + "bbb";

生成b:
public static void main(java.lang.String[]);
  Code:
   0:        ldc        #2; //String test
   2:        astore_1
   3:        ldc        #3; //String testbbb
   5:        astore_2
   6:        return

生成c:
public static void main(java.lang.String[]);
  Code:
   0:        ldc        #2; //String test
   2:        astore_1
   3:        new        #3; //class java/lang/StringBuilder
   6:        dup
   7:        invokespecial        #4; //Method java/lang/StringBuilder."<init>":()V
   10:        aload_1
   11:        invokevirtual        #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   14:        ldc        #6; //String bbb
   16:        invokevirtual        #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   19:        invokevirtual        #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   22:        astore_2
   23:        return

上面是实验结果,可以看见,如果是两个字符串相加,例如b, Java在编译时就确定好了 b的理论地址,在常量区;
如果是对象加字符串,则需要在运行时new对象,c 的地址就在堆区;所以c 和b地址肯定不相同。



作者: 冯晓骏    时间: 2013-11-29 18:18
刘敏 发表于 2013-11-29 09:08
做了一个实验:
String a = "test";String b = "test" +"bbb";
String c = a + "bbb";

大牛啊,汇编我表示看不太懂。。不过你的解释很清楚,谢谢,解决了我一个疑惑




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2