</p> 斗劲类琅缦沔的数值是否相等时,用equals()体例;当测试两个包装类的引用是否指向统一个对象时,用==,下面用例子声名膳缦沔的理论。
( {* J3 i2 [, G+ m String str1 = "abc";
0 e! H# h! `; H8 T5 j. Z String str2 = "abc";& ^; m8 t& y" a0 V f5 d4 G
System.out.println(str1==str2); //true可以看出str1和str2是指向统一个对象的。
/ b* c! T( \* o# b. [# X String str1 =new String ("abc");2 ?/ g: I& U% V
String str2 =new String ("abc");
7 ?0 C2 C. q$ o C8 W; W6 Q! r System.out.println(str1==str2); // false用new的体例是生成分歧的对象。每一次生成一个。( |$ d: }" F, w, i2 B; Q6 Q
是以用第二种体例建树多个“abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节约内存空间. 同时它可以在必然水平上提高轨范的运行速度,因为JVM会自动按照栈中数据的现实情形来抉择是否有需要建树新对象。而对于String str = new String("abc");的代码,则一概在堆中建树新对象,而不管其字符串值是否相等,是否有需要建树新对象,从而加重了轨范的承担。" |! s! Y7 ]8 v: b0 k
另一方面, 要注重: 我们在使用诸如String str = "abc";的名目界说类时,老是想当然地认为,建树了String类的对象str。担忧陷阱!对象可能并没有被建树!而可能只是指向一个先前已经建树的 对象。只有经由过程new()体例才能保证每次都建树一个新的对象。 因为String类的immutable性质,当String变量需要经常变换其制瘫,应该考虑使用StringBuffer类,以提高轨范效率。
) e9 s+ w4 T/ G java中内存分配策略及堆和栈的斗劲
( l9 ]; K$ X- f& X4 V 2.1 内存分配策略按照编译事理的不雅概念,轨范运行时的内存分配有三种策略,分袂是静态的,栈式的,和堆式的.静态存储分配是指在编译时就能确定每个数据方针在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求轨范代码中不允 许有可变数据结构(好比可变数组)的存在,也不许可有嵌套或者递归的结构呈现,因为它们城市导致编译轨范无法计较切确的存储空间需求.栈式存储分配也可称为动态存储分配,是由一个近似于仓库的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,轨范对数据区的需求在编译时是完全未知 的,只有到运行的时辰才能够知道,可是划定在运行中进入一个轨范模块时,必需知道该轨范模块所需的数据区巨细才能够为其分配内存.和我们在数据结构所熟知 的栈一样,栈式存储分配按照前进前辈后出的原则进行分配。+ b5 T5 r* ^$ P4 A& o0 H7 D& x
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的进口处必需知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时 模块进口处都无法确定存储要求的数据结构的内存分配,好比可变长度串和对象实例.堆由大片的可操作块或余暇块组成,堆中的内存可以按照肆意挨次分配和释 放.
* `! N5 v5 q( z1 g6 N, g j 2.2 堆和栈的斗劲9 S; o [1 l0 T7 w. z# G
膳缦沔的界说从编译事理的教材中总结而来,除静态存储分配之外,都显得很机械和难以理解,下面撇开静态存储分配,集中斗劲堆和栈:从堆和栈的功能和浸染来通俗的斗劲,堆首要用来存放对象的,栈主若是用来执行轨范的.而这种分歧又主若是因为堆和栈的特点抉择的:在编程中,例如C/C++中,所有的体例挪用都是经由过程栈来进行的,所有的局部变量,形式参数都是从栈平分配内存空间的。现实上也不是什么分配,只是从栈顶 向上用就行,就仿佛工场中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到下班具的位置,你所要做的只是把工具放下来就行.退出函数的时辰,改削栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行轨范了.需要注重的是,在分配的时辰,好比为一个即将要挪用的轨范模块分配数据区时,应事先知道这个数据区的巨细,也就说是虽然分配是在程 序运行时进行的,可是分配的巨细若干好多是确定的,不变的,而这个"巨细若干好多"是在编译时确定的,不是在运行时.堆是应用轨范在运行的时辰请求操作系统分配给自己内存,因为从操作系统打点的内存分配,所以在分配和销毁时都要占用时刻,是以用堆的效率很是低.可是堆的 利益在于,编译器不必知道要从堆里分配若干好多存储空间,也不必知道存储的数据要在堆里勾留多长的时刻,是以,用堆保留数据时会获得更大的矫捷性。事实上,面 向对象的多态性,堆内存分配是必不成少的,因为多态变量所需的存储空间只有在运行时建树了对象之后才能确定.在C++中,要求建树一个对象时,只需用 new呼吁编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保留.当然,为达到这种矫捷性,必然会支出必然的价钱:在堆里分配存储空间时会花 失踪更长的时刻!这也恰是导致我们适才所说的效率低的原因,看来列宁同志说的好,人的利益往往也是人的错误谬误,人的错误谬误往往也是人的利益.' j& }) g c3 c7 C$ F+ q4 K- Q
2.3 JVM中的堆和栈JVM是基于仓库的虚拟机.JVM为每个新建树的线程都分配一个仓库.也就是说,对于一个Java轨范来说,它的运行就是经由过程对仓库的操作来完成的。仓库以帧为单元保留线程的状况。JVM对仓库只进行两种操作:以帧为单元的压栈和出栈操作。6 _7 x" j g; L& S0 G
我们知道,某个线程正在执行的体例称为此线程的当前体例.我们可能不知道,当前体例使用的帧称为当前帧。当线程激活一个Java体例,JVM就会在线程的 Java仓库里新压入一个帧。这个帧自然成为了当前帧.在此体例执行时代,这个帧将用来保留参数,局部变量,中心计较过程和其他数据.这个帧在这里和编译 事理中的勾当记载的概念是差不多的.从Java的这种分配机制来看,仓库又可以这样理解:仓库(Stack)是操作系统在成立某个历程时或者线程(在撑持多线程的操作系统中是线程)为这个线程成立的存储区域,该区域具有前进前辈后出的特征。- b( t0 ]5 K! Z& g+ j+ B! m& O
每一个Java应用都独一对应一个JVM实例,每一个实例独一对应一个堆。应用轨范在运行中所建树的所有类实例或数组都放在这个堆中,并由应用所有的线程 共享.跟C/C++分歧,Java平分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆平分配的,可是这个对象的引用却是在仓库平分配,也 就是耸ё仝成立一个对象时从两个处所都分配内存,在堆平分配的内存现实成立这个对象,而在仓库平分配的内存只是一个指向这个堆对象的指针(引用)而已。 |