1.首先理解java中的内存地址是什么?
Java把内存划分成两种:一种是栈内存,一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
堆内存用来存放由new创建的对象和数组。
在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。
![](https://i-blog.csdnimg.cn/blog_migrate/4cdb6123514a1eee46fc8f7ca287f1b5.jpeg)
2.“==”用于比较对象比较的是什么?
对比对象实例的内存地址,又可以说是判断对象实例是否物理相等。若用"=="比较两对象是否相等,即比较上图所指向的堆内存空间的地址是否是同一个地址。
3.没有重写根类的“equals”比较的是什么?
当对象所属的类没有重写根类Object的equals()方法时,equals()判断的是对象实例的ID(内存地址),是否是同一对象实例;该方法就是使用的等号(==)的判断结果。即比较所指向上图堆内存空间的地址是否是同一个地址。
4.String类直接量和new String的区别及==和equals比较字符串时比较的是什么?
![](https://i-blog.csdnimg.cn/blog_migrate/c0550b747c71cc065a2be36c81e7489a.jpeg)
例:
/*
下方代码,jvm将会使用常量池来管理这些字符串
/*
String s1="china";
String s2="china";
String s3="china";
/*
下方代码,jvm将会使用常量池来管理这些字符串,然后调用String类的构造器来创建一个新的String对象,新创建的对象保存在堆内存中,栈内存中存放的是其引用,指堆内存中的首地址。
/*
String ss1=new String("china");
String ss2=new String("china");
String ss3=new String("china");
/*
下方代码出现此结果原因是:==号比较的是指向常量池中“china”字符串的地址是否相等,图示很显然他们都指向同一个,其地址相等,返回true。
*/
System.out.println(s1==s2);//true
System.out.println(s1==s3);//true
System.out.println(s2==s3);//true
/*
下方代码出现此结果原因是:==号比较的是指向堆中“china”字符串的地址是否相等,但使用new时,每次调用都会使构造器创建一个新的String对象,图示创建了3个,他们的地址是不同的,因此返回false。
*/
System.out.println(ss1==ss2);//false
System.out.println(ss1==ss3);//false
System.out.println(ss2==ss3);//false
/*
下方代码出现此结果原因是:未重写的equals比较的是分别指向常量池与堆内存中“china”字符串的地址中的内容是否相等,图示很显然他们的内容都是"china",相等,返回true。
*/
System.out.println(s1.equals(s2));//true
System.out.println(s1.equals(s3));//true
System.out.println(s3.equals(s2));//true
System.out.println(ss1.equals(ss2));//true
System.out.println(ss1.equals(ss3));//true
System.out.println(ss3.equals(ss2));//true