绍兴在线制作网站,WordPress积分打赏插件制作,经典网站设计欣赏,需要做网站的企业电话Java把内存划分成两种#xff1a;一种是栈内存#xff0c;一种是堆内存。 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时#xff0c;Java就在栈中为这个变量分配内存空间#xff0c;当超过变量的作用域后#…Java把内存划分成两种一种是栈内存一种是堆内存。 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时Java就在栈中为这个变量分配内存空间当超过变量的作用域后Java会自动释放掉为该变量所分配的内存空间该内存空间可以立即被另作他用。 堆内存用来存放由new创建的对象和数组。 在堆中分配的内存由Java虚拟机的自动垃圾回收器来管理。 在堆中产生了一个数组或对象后还可以在栈中定义一个特殊的变量让栈中这个变量的取值等于数组或对象在堆内存中的首地址栈中的这个变量就成了数组或对象的引用变量这是java中引用的定义。 引用变量就相当于是为数组或对象起的一个名称以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。 插述java和c引用是不一样的 java去除指针概念就用引用罗... 你看 java: A a new A(1); A b new A(2); b a; 没有问题a 和 b引用同一个对象A(1)原来的A(2)成为没有被引用的对象。 垃圾回收机制会在之后的某个时刻把A(2)干掉。 而C则不然。C的引用就语义上说是“别名”而并不是指针的另一种用法 A a A(1); A b A(2); A c b; //c 是 b的别名 c a; //虽然不合法但如果合法的话也并不是 c 引用 a而是拷贝操作 c.operator ( a ) C的“引用”是从一而终的而Java的“引用”可以改变被引用的对象 如果非要对比着看那么Java中的“引用”倒是和C/C的指针更像一些和C的“引用”很不一样。 具体的说 栈与堆都是Java用来在Ram中存放数据的地方。与C不同Java自动管理栈和堆程序员不能直接地设置栈或堆而c仅自动管理栈堆由程序员管理。 Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等 指令建立它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的堆的优势是可以动态地分配内存大小生存期也不必事先告诉编译器因为它是在运行时 动态分配内存的Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是由于要在运行时动态分配内存存取速度较慢。 栈的优势是存取速度比堆要快仅次于寄存器栈数据可以共享。但缺点是存在栈中的数据大小与生存期必须是确定的缺乏灵活性。栈中主要存放一些基本 类型的变量,int, short, long, byte, float, double, boolean, char和对象句柄。 栈有一个很重要的特殊性就是存在栈中的数据可以共享。假设我们同时定义 int a 3; int b 3 编译器先处理int a 3首先它会在栈中创建一个变量为a的引用然后查找栈中是否有3这个值如果没找到就将3存放进来然后将a指向3。接着处理int b 3在创建完b的引用变量后因为在栈中已经有3这个值便将b直接指向3。这样就出现了a与b同时均指向3的情况。这时如果再令a4那么编译器 会重新搜索栈中是否有4值如果没有则将4存放进来并令a指向4如果已经有了则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这 种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的因为这种情况a的修改并不会影响到b, 它是由编译器完成的它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态会影响到另一个对象引用变量。 String是一个特殊的包装类数据。可以用 String str new String(abc); String str abc; 两种的形式来创建第一种是用new()来新建对象的它会在存放于堆中。每调用一次就会创建一个新的对象。 而第二种是先在栈中创建一个对String类的对象引用变量str然后查找栈中有没有存放abc如果没有则将abc存放进栈并令str指向”abc”如果已经有”abc” 则直接令str指向“abc”。 比较类里面的数值是否相等时用equals()方法当测试两个包装类的引用是否指向同一个对象时用下面用例子说明上面的理论。 String str1 abc; String str2 abc; System.out.println(str1str2); //true 可以看出str1和str2是指向同一个对象的。 String str1 new String (abc); String str2 new String (abc); System.out.println(str1str2); // false 用new的方式是生成不同的对象。每一次生成一个。 因此用第二种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str new String(abc)的代码则一概在堆中创建新对象而不管其字符串值是否相等是否有必要创建新对象从而加重了程序的负担。 另一方面, 要注意: 我们在使用诸如String str abc的格式定义类时总是想当然地认为创建了String类的对象str。担心陷阱对象可能并没有被创建而可能只是指向一个先前已经创建的 对象。只有通过new()方法才能保证每次都创建一个新的对象。 由于String类的immutable性质当String变量需要经常变换其值时应该考虑使用StringBuffer类以提高程序效率。 附现在正式大家忙着找工作的时候往往参加完各公司的笔试后大家会讨论这些笔试题目。昨天在年级的就业信息群里大家讨论了这样一个问题String a”blog””java”;这个语句会产生几个java对象有的人说三个有的人说四个。究竟是几个呢java中字符串类型是个非常特殊的类型也是最常用的类型正因为它的特殊性和常用性很多公司笔试题都有它的身影。我在网上看了些资料现总结出来以供大家参考。1 首先String不属于8种基本数据类型String是一个对象。因为对象的默认值是null所以String的默认值也是null。2 New String()和new String(“”)都是声明一个新的空字符串是空串不是null。3 String str”kvill”; String strnew String(“kvill”);的区别在这里我们不谈堆也不谈栈只先简单引入常量池这个简单的概念。常量池指的是在编译期间被确定并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量也包括字符串常量。例1String s0”kvill”;String s1”kvill”;String s2”kv””ill”;System.out.println(s0s1);System.out.println(s0s2);结果为TrueTrue首先我们要知道java会确保一个字符串只有一个拷贝。因为例子中s0和s1中的”kvill”都是字符串常量他们在编译期就被确定了所以s0s1为true而”kv”和”ill”也都是字符串常量当一个字符串由多个字符串常量连接而成时它自己肯定也是字符串常量所以s2也同样在编译期间就被解析为一个字符串常量所以s2也是常量池中”kvill”的一个引用。用new String()创建的字符串不是常量不能在编译期间就确定所以new String()创建的字符串不放入常量池它们有自己的地址空间。例2String s0”kvill”;String s1new String(“kvill”);String s2”kv”new String(“ill”);System.out.println(s0s1);System.out.println(s0s2);System.out.println(s1s2);结果为FalseFalseFalse例2中s0还是常量池中”kvill”的引用s1因为无法在编译期间确定所以是运行时创建的新对象”kvill”的引用s2因为有后半部分new String(“ill”)所以也无法在编译期间确定所以也是一个新创建对象”kvill”的应用。4 String.intern();再补充介绍一点存在于.class文件中的常量池在运行期间被jvm装载并且可以扩充。String的intern()方法就是扩充常量池的一个方法当一个String实例str调用intern()方法时java查找常量池中是否有相同unicode的字符串常量如果有则返回其引用如果没有则在常量池中增加一个unicode等于str的字符串并返回它的引用。例3String s0”kvill”;String s1new String(“kvill”);String s2new String(“kvill”);System.out.println(s0s1);S1.intern();S2s2.intern();System.out.println(s0s1);System.out.prntln(s0s1.intern());System.out.println(s0s2);结果为FalseFalse //虽然执行了s1.intern()但它的返回值没有赋给s1TrueTrue最后再破除一个错误的理解有人说“使用String.intern()方法可以将一个String类保存到一个全局的String表中如果具有相同值的unicode字符串已经在这个表中那么该方法返回表中已有字符串的地址如果在表中没有相同值的字符串则将自己的地址注册到表中”如果把这个全局的String表理解为常量吃的话最后一句话“如果在表中没有相同值的字符串则将自己的地址注册到表中”是错的。例4String s1new String(“kvill”);String s2s1.intern();System.out.println(s1s1.intern());System.out.println(s1” ”s2);System.out.println(s2s1.intern());结果是FalseKvill kvillTrue我们没有声明一个”kvill”常量所以常量池中一开始没有”kvill”的当我们调用s1.intern()后就在常量池中新添加了一个”kvill”常量原来的不在常量池中的”kvill”仍然存在也就不是“把自己的地址注册到常量池中”了。例5String str1”java”;String str2”blog”;String sstr1str2;System.out.println(s”javablog”);结果是false。Jvm确实对型如String str1”java”;的String对象放在常量池里但是它是在编译时那么做的而String sstr1str2;是在运行时刻才能知道也就是说str1str2是在堆里创建的所以结果为false了。5 关于equals()和Equals()就是比较两字符串的内容是否相等而是比较两字符串的地址是否相同也就是是否是同一个字符串的引用。6 关于String是不可变的String的实例一旦生成就不会再改变了比如说String str”kv””ill””ans”;首先”kv”和”ill”生成了”kvill”存在内存中然后”kvill”和”ans”生成了”kvillans”并把这个字符串的地址赋给了str就是String的不可变产生了很多临时变量这就是为什么建议用StringBuffer的原因了。7 StringBuffer类StringBuffer类是可变的不会在字符串常量池中而是在堆中不会留下一大堆无用的对象。而且它可将字符串缓冲区安全地用于多个线程。每个StringBuffer对象都有一定的容量。只要StringBuffer对象所包含的字符序列的长度没有超出此容量就无需分配新的内部缓冲区数组。如果内部缓冲区溢出则此容量自动增大。这个初始容量是16个字符。StringBuffer sbnew StringBuffer(); //初始容量为16个字符Sb.append(“1234”); //这是4和字符没有溢出System.out.println(sb.length()); //输出字符串长度4System.out.println(sb.capacity()); //输出该字符串缓冲区的容量是16Sb.append(“12345678901234567”); //这是17个字符扩容为1716个字符的容量System.out.println(sb.length()); //输出字符串长度是17System.out.println(sb.capacity()); //输出该字符串缓冲区的容量是34字符串的长度和字符缓冲区的容量是两个概念注意区别。8 StringBuilder类j2se5.0提供了StringBuilder类它和StringBuffer类是孪生兄弟。它存在的价值在于对字符串操作的效率更高。不足的是线程安全无法保证不保证同步。那么两者性能到底差多少呢很多请参阅http://book.csdn.net/bookfiles/135/1001354628.shtml单个线程的时候使用StringBuilder类以提高效率。多线程时使用StringBuffer以保证安全。转载于:https://www.cnblogs.com/weiqubo/archive/2009/10/22/1930058.html