在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。
引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
1、== 和 equals的区别:
原因是基本类型的变量存在栈中,系统先创建一个变量为a的引用,然后查找栈中是否有10这个值,如果没找到,就将10存放进来然,并且a指向10,同理b也是一样,创建一个变量为b的引用,这里,栈中有是10,把b指向10,所以在比较的过程中,a和b在内存中指向的位置是相同的。
而对于下面情况:
String a=new String("abc");
String b=new String("abc");
a==b; 返回的则是一个false。这是因为,对于对象的比较是对对象引用的比较,对于a和b ,他们在内存中对应的地址是不一样的,重新开辟内存空间,把“abc”存到里面。所以 a==b 返回的值是一个false.
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //truestr1和str2指向同一个地址。创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度
==操作符并不涉及对象内容的比较。若要对对象内容进行比较,则用equals. 如果 在本例中,a.equals(b)则返回是一个true值。在使用“==”的时候千万要注意常量;
再看一个例子:
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b + 2;
String e = d + 2;
System.out.println((a == c));
System.out.println((a == e));这里接结果是,第一是true,第二个是false;执行过程:
创建一个变量a,然后查找,是否有 “hello2”这个值,显然,这里是没有找到的。那么给他开辟一个空间存放 hello2,同理创建b,;当运行到第三行的时候,b和d 的内存地址是一样的,即 b==d 是true; 这里注意第四行代码, 在执行过程中相当于 String c = "hello"+2;但是e 就不是这样了,new StringBuilder(d),再append 2,,new 一个对象出来了,内存地址自然是不通的。所以 a==e 的结果自然是不一样的。
equals:不能比较基本数据类型,基本数据类型不是类类型;比如:
int x = 1;
System.out.println(a.equals(1));结果是false;
equals 本身依赖于 “==”,但是比如字符串的比较,为什么是内容的比较呢?因为String 已经对equals进行了重写,保证了他是对 字符串长度和内容的比较。所以,一般情况下,就算你是重新new出来的字符串对象,只要保证他的字符串长度和内容一样,那么他就是返回true;
总而言之,==是对对象地址的比较,而equals是对对象内容的比较,只要字符串内容,长度一样即可(若方法没有对equals重写,那么他的效果和“==”是一样的)。对于基本数据类型,一般用==,而对于字符串的比较,一般用equals
2、对于compareTo(), 在API中,java.lang包下面的基本数据类型的封装类都提供了该方法,如 Integer,Float,Byte,Short,Character 等在基本数据中,compareTo()是比较两个Character 对象;
在 Boolean中,是用boolean的实例于其它实例进行比较;
在String 中,则是按照字典顺序进行比较,返回的值是一个int 型。
贴一段代码
public class Test{
public static void main(String args[]){String s1=new String("abc");
String s2=new String("abc");
System.out.println((s1==s2)? "true":"false");
System.out.println((s1.equals(s2))? "true":"false");
if(s1.compareTo(s2)==0){
System.out.println("s1 is equal s2");}
s1=s2;
System.out.println((s1==s2)? "true":"false");
}
}程序的运行结果为:
false
true
s1 is equals s2
true
这里需要说明的一点,s2对象赋值给s1之后,s2和s1的引用其实是指向了内存中的同一个位置。所以,再进行比较时,就是true.
这里附上引用变量的内存解析图解:(这里 ox12ab等就是地址值)
我从来不相信什么懒洋洋的自由。我向往的自由是通过勤奋和努力实现的更广阔的人生。 我要做一个自由又自律的人,靠势必实现的决心认真地活着。