public class MyTest {
public static void main(String[] args) {
String s1 = newString("abc") ;
String s2 = newString("abc") ;
}
}
我们来数,第一次是"abc"在常量堆里分配了一 个常量对象,第二次是 new String,第三次是 s1, 第四次是"abc"没分配,使用了之前的那个,所以第四次是 new String,第五次是 s2,一共进行了 5 次 内存操作。
不但"abc"是对象,而且""都 是对象,只是这样的对象和 new 的对象不太一样,这样的叫做常量对象,被放在堆里一个特定的 地方,我们管那个地方叫“常量堆”,常量对象在分配的时候有个特点,就是系统会先到常量堆里 看看有没有你想要的对象,如果有,就不建立新的常量对象,而是直接使用已经存在的那一个。
两个引用分别指向各自的对象。什么是指向?其实就是引用里存放 着对象的位置信息,如果这样看来,你觉得s1和 s2是否相等?
是我们通常要比较的是内容,那就用 s1.equals(s2), equals 用来比较两个对象的内容是否一样,==用来比较是否是一个对象。
equals方法
可惜 Java 并没有将这件事情做得足够好,按理说任何对象都可以这样比较,因为任何对象 都有 equals 这个方法。为什么任何对象都有 equals 方法?这是因为 Java 里的所有类都从一个叫 做 Object 的类继承而来,就是我们常说的 Java 语言的单根结构,所有的类都有一个共同的根类 Object。如果你写了 class MyTest { },这个类没有继承任何类,那么它就会自动继承Object,现 在你写下 Object o = new Object() ;,然后在下面用 o点点看看里面有什么?是不是有equals,这 里的 equals 就意味着它的所有子类都有 equals。 问题是 Object 里的这个 equals 方法几乎什么都没做,结果完全等同于==,设计者似乎仅仅 要给其他类的编写者一个提示,希望在写新类的时候,能够重写这个方法来定义两个对象是否相等的规则。这是因为对象如此复杂,两个对象是否相同的规则有可能不是一目了然的,比如说两 个人是否相同,你很难选择从哪个方面来比较,有性别、年龄、国籍、学历、专业等很多可能的 比较方案,现在如果写的是人类,你完全可以自己定义 equals,把你想的规则设定进去。String 就这样重写了 equals,让你能够比较内容。