`
java_mzd
  • 浏览: 580204 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

Java内存分配、管理小结

阅读更多

P.S.

想写这篇总结酝酿了有个来月了,却始终感觉还差点什么东西,一直未敢动笔。

       最近两天连夜奋战,重新整理下前面查阅的资料、笔记,还是决定将它写出来。

       现在提出几个问题,如果都能熟练回答的大虾,请您飘过.如以往一样,我是小菜,本文自然也是针对小菜阶层的总结。

 

首先是概念层面的几个问题:

 

  • Java中运行时内存结构有哪几种?
  • Java中为什么要设计堆栈分离?
  • Java多线程中是如何实现数据共享的?
  • Java反射的基础是什么?

然后是运用层面:

  • 引用类型变量和对象的区别?
  • 什么情况下用局部变量,什么情况下用成员变量?
  • 数组如何初始化?声明一个数组的过程中,如何分配内存?
  • 声明基本类型数组和声明引用类型的数组,初始化时,内存分配机制有什么区?
  • 在什么情况下,我们的方法设计为静态化,为什么?(上次胡老师问文奇,问的哑口无言,当时想回答,却老感觉表述不清楚,这里也简单说明一下)

好了,问题提完了,如果您都能一眼看出答案,那么,没有必要再浪费您宝贵的时间看下去了

如果您还不太明白,请跟随我一路走下去。

 

Java中运行时内存结构

   1.1 方法区: 

方法区是系统分配的一个内存逻辑区域,是JVM在装载类文件时,用于存储类型信息的(类的描述信息)。

    

方法区存放的信息包括:

            1.1.1类的基本信息:

  1. 每个类的全限定名
  2. 每个类的直接超类的全限定名(可约束类型转换)
  3. 该类是类还是接口
  4. 该类型的访问修饰符
  5. 直接超接口的全限定名的有序列表

             1.1.2已装载类的详细信息

  1.  运行时常量池

    在方法区中,每个类型都对应一个常量池,存放该类型所用到的所有常量,常量池中存储了诸如文字字符串、final变量值、类名和方法名常量。它们以数组形式通过索引被访问,是外部调用与类联系及类型对象化的桥梁。(存的可能是个普通的字符串,然后经过常量池解析,则变成指向某个类的引用)

  2.  字段信息

    字段信息存放类中声明的每一个字段的信息,包括字段的名、类型、修饰符。

    字段名称指的是类或接口的实例变量或类变量,字段的描述符是一个指示字段的类型的字符串,如private A a=null;a为字段名,A为描述符,private为修饰符

  3.  方法信息

    类中声明的每一个方法的信息,包括方法名、返回值类型、参数类型、修饰符、异常、方法的字节码。

    (在编译的时候,就已经将方法的局部变量、操作数栈大小等确定并存放在字节码中,在装载的时候,随着类一起装入方法区。)

    在运行时,JVM从常量池中获得符号引用,然后在运行时解析成引用项的实际地址,最后通过常量池中的全限定名、方法和字段描述符,把当前类或接口中的代码与其它类或接口中的代码联系起来。
  4.  静态变量

    这个没什么好说的,就是类变量,类的所有实例都共享,我们只需知道,在方法区有个静态区,静态区专门存放静态变量和静态块。

  5.  到类classloader的引用到该类的类装载器的引用。
  6.  到类class 的引用虚拟机为每一个被装载的类型创建一个class 实例,用来代表这个被装载的类。 

    由此我们可以知道反射的基础

在装载类的时候,加入方法区中的所有信息,最后都会形成Class类的实例,代表这个被装载的类。方法区中的所有的信息,都是可以通过这个Class类对象反射得到。我们知道对象是类的实例,类是相同结构的对象的一种抽象。同类的各个对象之间,其实是拥有相同的结构(属性),拥有相同的功能(方法),各个对象的区别只在于属性值的不同
    同样的,我们所有的类,其实都是Class类的实例,他们都拥有相同的结构-----Field数组、Method数组。而各个类中的属性都是Field属性的一个具体属性值,方法都是Method属性的一个具体属性值。


 

 在运行时,JVM从常量池中获得符号引用,然后在运行时解析成引用项的实际地址,最后通过常量池中的全限定名、方法和字段描述符,把当前类或接口中的代码与其它类或接口中的代码联系起来。

 

1.2 Java栈

JVM栈是程序运行时单位,决定了程序如何执行,或者说数据如何处理。

Java中,一个线程就会有一个线程的JVM栈与之对应,因为不过的线程执行逻辑显然不同,因此都需要一个独立的JVM栈来存放该线程的执行逻辑。

对方法的调用:

Java栈内存,以的形式存放本地方法调用状态,包括方法调用的参数局部变量、中间结果等(方法都是以方法帧的形式存放在方法区的),每调用一个方法就将对应该方法的方法帧压入Java 栈,成为当前方法帧。当调用结束(返回)时,就弹出该帧。

 

这意味着:

在方法中定义的一些基本类型的变量和引用变量都在方法的栈内存中分配。当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后(方法执行完成后),Java 会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作它用--------同时,因为变量被释放,该变量对应的对象,也就失去了引用,也就变成了可以被gc对象回收的垃圾。


因此我们可以知道成员变量与局部变量的区别:

局部变量,在方法内部声明,当该方法运行完时,内存即被释放。
成员变量,只要该对象还在,哪怕某一个方法运行完了,还是存在。
从系统的角度来说,声明局部变量有利于内存空间的更高效利用(方法运行完即回收)。
成员变量可用于各个方法间进行数据共享。

 

 

Java 栈内存的组成:
局部变量区、操作数栈、帧数据区组成。
(1):局部变量区为一个以字为单位的数组,每个数组元素对应一个局部变量的值。调用方法时,将方法的局部变量组成一个数组,通过索引来访问。若为非静态方法,则加入一个隐含的引用参数this,该参数指向调用这个方法的对象。而静态方法则没有this参数。因此,对象无法调用静态方法。

 

由此,我们可以知道,方法什么时候设计为静态,什么时候为非静态?

前面已经说过,对象是类的一个实例,各个对象结构相同,只是属性不同。
而静态方法是对象无法调用的。
所以,静态方法适合那些工具类中的工具方法,这些类只是用来实现一些功能,也不需要产生对象,通过设置对象的属性来得到各个不同的个体。


(2):操作数栈也是一个数组,但是通过栈操作来访问。所谓操作数是那些被指令操作的数据。当需要对参数操作时如a=b+c,就将即将被操作的参数压栈,如将b 和c 压栈,然后由操作指令将它们弹出,并执行操作。虚拟机将操作数栈作为工作区。
(3):帧数据区处理常量池解析,异常处理等

 

1.3 java堆 

      java的堆是一个运行时的数据区,用来存储数据的单元,存放通过new关键字新建的对象数组,对象从中分配内存。
      在堆中声明的对象,是不能直接访问的,必须通过在栈中声明的指向该引用的变量来调用。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。
   

     由此我们可以知道,引用类型变量和对象的区别: 

声明的对象是在堆内存中初始化的, 真正用来存储数据的。不能直接访问。

引用类型变量是保存在栈当中的,一个用来引用堆中对象的符号而已(指针)。


堆与栈的比较
JAVA堆与栈都是用来存放数据的,那么他们之间到底有什么差异呢?既然栈也能存放数据,为什么还要设计堆呢?


1.从存放数据的角度:

      前面我们已经说明:

      栈中存放的是基本类型的变量or引用类型的变量

       堆中存放的是对象or数组对象.

       在栈中,引用变量的大小为32位,基本类型为1-8个字节。
       但是对象的大小和数组的大小是动态的,这也决定了堆中数据的动态性,因为它是在运行时动态分配内存的,生存期也不必在编译时确定,Java 的垃圾收集器会自动收走这些不再使用的数据。

 

2.从数据共享的角度:

    1).在单个线程类,栈中的数据可共享

    例如我们定义:

 int a=3;
 int b=3;

    编译器先处理int a = 3;首先它会在栈中创建一个变量为a 的引用,然后查找栈中是否有3 这个值,如果没找到,就将3 存放进来,然后将a 指向3。接着处理int b = 3;在创建完b 的引用变量后,因为在栈中已经有3这个值,便将b 直接指向3。这样,就出现了a 与b 同时均指向3的情况。

    而如果我们定义: 

Integer a=new Integer(3);//(1)
Integer b=new Integer(3);//(2)

   这个时候执行过程为:在执行(1)时,首先在栈中创建一个变量a,然后在堆内存中实例化一个对象,并且将变量a指向这个实例化的对象。在执行(2)时,过程类似,此时,在堆内存中,会有两个Integer类型的对象。 

 

    2).在进程的各个线程之间,数据的共享通过堆来实现

        例:那么,在多线程开发中,我们的数据共享又是怎么实现的呢?

 

  如图所示,堆中的数据是所有线程栈所共享的,我们可以通过参数传递,将一个堆中的数据传入各个栈的工作内存中,从而实现多个线程间的数据共享

(多个进程间的数据共享则需要通过网络传输了。) 

 

3.从程序设计的的角度:

从软件设计的角度看,JVM栈代表了处理逻辑,而JVM堆代表了数据。这样分开,使得处理逻辑更为清晰。分而治之的思想。这种隔离、模块化的思想在软件设计的方方面面都有体现。


4.值传递和引用传递的真相

有了以上关于栈和堆的种种了解后,我们很容易就可以知道值传递和引用传递的真相:

1.程序运行永远都是在JVM栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传对象本身。

但是传引用的错觉是如何造成的呢?

在运行JVM栈中,基本类型和引用的处理是一样的,都是传值,所以,如果是传引用的方法调用,也同时可以理解为“传引用值”的传值调用,即引用的处理跟基本类型是完全一样的。

但是当进入被调用方法时,被传递的这个引用的值,被程序解释(或者查找)到JVM堆中的对象,这个时候才对应到真正的对象。

如果此时进行修改,修改的是引用对应的对象,而不是引用本身,即:修改的是JVM堆中的数据。所以这个修改是可以保持的了。

 

 

最后:

从某种意义上来说对象都是由基本类型组成的。 

可以把一个对象看作为一棵树,对象的属性如果还是对象,则还是一颗树(即非叶子节点),基本类型则为树的叶子节点。程序参数传递时,被传递的值本身都是不能进行修改的,但是,如果这个值是一个非叶子节点(即一个对象引用),则可以修改这个节点下面的所有内容。 


其实,面向对象方式的程序与以前结构化的程序在执行上没有任何区别

面向对象的引入,只是改变了我们对待问题的思考方式,而更接近于自然方式的思考。

当我们把对象拆开,其实对象的属性就是数据,存放在JVM堆中;而对象的行为(方法),就是运行逻辑,放在JVM栈中。我们在编写对象的时候,其实即编写了数据结构,也编写的处理数据的逻辑。 

 

 

P.S

关于数组的内存分配,对象初始化的内存分配等问题,由于篇幅问题,下次再搞个专题写吧。

 连续几天几夜对着此文了。想吐的很,先到这里吧。

  • 大小: 13.2 KB
65
8
分享到:
评论
23 楼 a455642158 2012-07-05  
关于静态变量,楼主说这个没什么好说的,就是类变量,类的所有实例都共享,我们只需知道,在方法区有个静态区,静态区专门存放静态变量和静态块。
好好说一下嘛……俺不清楚咧。
谢谢……
22 楼 爱老虎哟 2011-08-18  
运行时常量是属于方法区??
我从JVMS-JavaSE7中得知Runtime Constant Pool(运行时常量池)与Method Area(方法区)是并列的两个逻辑内存区。
21 楼 491823151 2011-05-20  
补充点:栈中也可分配对象。只有当编译器检查到该对象不存在逃逸时。栈上分配,有效利用堆
20 楼 zkgale 2011-01-14  
满好的,谢谢你

不过,可能还是象前面几位说的那样吧,在分配的细节上写得还不是很深入,
不管怎么说,让我在引用关系方面的理解更深入了一些.
继续加油,很给力
19 楼 z_jiankun 2011-01-06  
zzc_zj 写道
分析得很细致,一遍没完全看明白,收藏下来,继续看


同感
18 楼 anmo 2011-01-05  
总结的有深度,学习一下!
17 楼 wanglong1615 2011-01-04  
JAVA堆与栈都是用来存放数据的,那么他们之间到底有什么差异呢?既然栈也能存放数据,为什么还要设计堆呢?
我觉得还有一个原因,也就是为什么有基本类型和基本类型的包装类一样。
在JAVA中,基本类型是经常被使用和运算的,设计基本类型,最主要是节约性能的考虑。
16 楼 javahero1984 2011-01-03  
不错,至少楼主是用心总结了,值得学习和讨论。
15 楼 culbertzp 2010-12-30  
bu_choreography 写道
2.从数据共享的角度:.
这块对整型的引用讲的很好。
补充一点:整型在常量池里只能表示-128到127.超过这个范围的就不归常量池管了
例如
Integer a = 128;
Integer b = 128;
a==b  返回的是false.


如果:

Integer a = 128;
int b = 128;
a == b 返回的是true

int a = 128;
int b = 128;
a == b 返回的也是true
14 楼 Irving_wei 2010-12-28  
  挺不错
13 楼 CosmosWon 2010-12-27  
明白了,但是我觉得楼主在这段上还有待斟酌:
(当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后(方法执行完成后),Java 会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作它用。--------同时,因为变量被释放,该变量对应的对象,也就失去了引用,也就变成了可以被gc对象回收的垃圾。)
当然了,本文也不是在讨论垃圾回收的,呵呵,不过既然说了,应该在说的精确点。
12 楼 hjk685 2010-12-24  
很有条理
11 楼 java_mzd 2010-12-23  
eXeSP 写道
查了下以前的帖子:
引用
java虚拟机规范中说:Primitive values do not share state with other primitive values. A variable whose type is a primitive type always holds a primitive value of that type.
看一下实际的处理情况:
  int a=3;
  int b=3;
打开class文件,这2句就4个字节,内容是“06 3B 06 3C”
看对应的虚拟机指令,可以知道变量里实际存储的是什么:
Code:
  0: iconst_3 //3
  1: istore_1
  2: iconst_3 //3
  3: istore_2
第1个字节06 iconst_3是一个指令,让CPU把寄存器放上3的值
第2个字节3B istore_0也是一个指令,就是让CPU把寄存器的值放到第1个变量的内存中
第3个字节06 iconst_3是一个指令,让CPU把寄存器放上3的值
第4个字节3C istore_1也是一个指令,就是让CPU把寄存器的值放到第2个变量的内存中
(jvm没有“寄存器”的概念,用“Operand Stack 操作数栈”。)


int a = 3,int b =3是直接从指令获取数值,而没有进行栈中交换或进入常量池。

引用
这里可以看到JAVA虚拟机的一个小技巧,它把一些对常用常量(比如0,1,2,3,4,5)的操作直接定义成了指令,而不是传统的操作指令后带操作数。
目的是减少指令长度。有心的人再用 int a = 6...试,根本就没有iconst_6的指令!
而是bipush 6,机器码10 06, 2个字节,10就是bipush, 06就是操作数6,就是传统的指令+操作数。


那么大于6的数呢


引用

int e=32330;
对应指令:
11: sipush 32330
14: istore 5
这句,11-13,正好是3个字节的指令大小,一个字节是sipush指令,2个字节用来存储32330这个数.两次使用到这个数,都是把它直接存给变量的。


那么如果大于2个字节的数又如何?

引用

int f = 65535;
对应指令:
4: ldc #2; //int 65535
6: istore_3


对于65535,它是大于两个字节的,编译的时候把它放入常量池部分,而把取这个数的指令写为ldc#2,我感觉这样一个直观的好处是减少了指令代码的长度.尤其是多次使用到一个相同的数时
.

大于2个字节的int数值,开始进入常量池。

那么int和Integer一样吗?

引用

Integer i = 3;
sun的编译器是这样处理的:
Integer i=Integer.valueOf(3);
而不是通过new来创建了,因为Integer类中静态的创建了-128~+127之间的对象,需要的数在这个范围之内时,直接返回,此范围之外的数才通过new来创建.






多谢多谢。  我还真没注意在cpu中到底怎么处理这部分。
受教了。
10 楼 生活小丑 2010-12-22  
java内存分配方面的知识一直都是朦朦胧胧的,说知道说不清楚,说不知道,还有点知道,网上搜了好多文章,楼主的文章算是比较详细的了.
9 楼 eXeSP 2010-12-22  
查了下以前的帖子:
引用
java虚拟机规范中说:Primitive values do not share state with other primitive values. A variable whose type is a primitive type always holds a primitive value of that type.
看一下实际的处理情况:
  int a=3;
  int b=3;
打开class文件,这2句就4个字节,内容是“06 3B 06 3C”
看对应的虚拟机指令,可以知道变量里实际存储的是什么:
Code:
  0: iconst_3 //3
  1: istore_1
  2: iconst_3 //3
  3: istore_2
第1个字节06 iconst_3是一个指令,让CPU把寄存器放上3的值
第2个字节3B istore_0也是一个指令,就是让CPU把寄存器的值放到第1个变量的内存中
第3个字节06 iconst_3是一个指令,让CPU把寄存器放上3的值
第4个字节3C istore_1也是一个指令,就是让CPU把寄存器的值放到第2个变量的内存中
(jvm没有“寄存器”的概念,用“Operand Stack 操作数栈”。)


int a = 3,int b =3是直接从指令获取数值,而没有进行栈中交换或进入常量池。

引用
这里可以看到JAVA虚拟机的一个小技巧,它把一些对常用常量(比如0,1,2,3,4,5)的操作直接定义成了指令,而不是传统的操作指令后带操作数。
目的是减少指令长度。有心的人再用 int a = 6...试,根本就没有iconst_6的指令!
而是bipush 6,机器码10 06, 2个字节,10就是bipush, 06就是操作数6,就是传统的指令+操作数。


那么大于6的数呢


引用

int e=32330;
对应指令:
11: sipush 32330
14: istore 5
这句,11-13,正好是3个字节的指令大小,一个字节是sipush指令,2个字节用来存储32330这个数.两次使用到这个数,都是把它直接存给变量的。


那么如果大于2个字节的数又如何?

引用

int f = 65535;
对应指令:
4: ldc #2; //int 65535
6: istore_3


对于65535,它是大于两个字节的,编译的时候把它放入常量池部分,而把取这个数的指令写为ldc#2,我感觉这样一个直观的好处是减少了指令代码的长度.尤其是多次使用到一个相同的数时
.

大于2个字节的int数值,开始进入常量池。

那么int和Integer一样吗?

引用

Integer i = 3;
sun的编译器是这样处理的:
Integer i=Integer.valueOf(3);
而不是通过new来创建了,因为Integer类中静态的创建了-128~+127之间的对象,需要的数在这个范围之内时,直接返回,此范围之外的数才通过new来创建.




8 楼 eXeSP 2010-12-22  


在方法区,Integer类中静态的创建了-128~+127之间的对象。int a = 3的数值是从常量池返回到栈当中的吧,想问问int b = 3,b是先从栈还是先从常量池查找数值,印象中String的话是从常量池查找的。
7 楼 iuf6853 2010-12-22  
辛苦了,让出入java圣殿的门外汉们受益匪浅。
6 楼 zzc_zj 2010-12-22  
分析得很细致,一遍没完全看明白,收藏下来,继续看
5 楼 java_mzd 2010-12-22  
juda 写道
写的不错,鼓励一下

多谢鼓励。
继续加油。
4 楼 java_mzd 2010-12-22  
bu_choreography 写道
2.从数据共享的角度:.
这块对整型的引用讲的很好。
补充一点:整型在常量池里只能表示-128到127.超过这个范围的就不归常量池管了
例如
Integer a = 128;
Integer b = 128;
a==b  返回的是false.


多谢指导,意思就是现在常量池整形只能存一个字节?
  那么关于double等类型的是不是也有相应变化呢?
最近借不到《深入JVM》
还是再查查资料吧。
多些指导

相关推荐

    Java内存分配、管理小结.doc

    Java内存分配、管理小结

    java中jvm内存分配相关资料总结整理

    关于java的内存分配问题,jvm的运行原理相关资料总结

    JAVA 内存管理总结

     Java的内存管理是对象的分配和释放问题。(两部分)  分配 :内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。  释放 :...

    JAVA内存逃逸分析.pptx

    这个文档是在学习了Java内存过程中总结出来的,描述了Java内存分配的过程,jdk基本初始化参数,内存逃逸级别等

    深入java虚拟机

    1. JVM调优 1.1 JVM调优总结(一)-一些概念 1.2 JVM调优总结(二)-一些概念 1.3 JVM调优总结(三)-基本垃圾回收算法 1.4 JVM调优总结(四)-垃圾...4.2 JVM内存管理:深入垃圾收集器与内存分配策略 4.3 深入理解JVM

    java垃圾回收以及jvm参数调优概述

    而且这两个问题针对的内存区域就是Java内存模型中的堆。垃圾回收机制的引入可以有效的防止内存泄露、保证内存的有效使用,也大大解放了Java程序员的双手,使得他们在编写程序的时候不再需要考虑内存管理。本文主要对...

    java基础知识总结.docx

    对java一些常用基础的总结,java基本知识,数组,java内存分配,方法总结,面向对象,常用API,常用集合

    java 字符串内存分配的分析与总结(推荐)

    下面小编就为大家带来一篇java 字符串内存分配的分析与总结(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Java内存以及GC

    Java内存区域与内存溢出  Java虚拟机中的内存分配图:  各个区域的特性总结如下表:  补充说明:  当多线程情形下,可能多个线程要在堆上分配内存,那么可能出现内存分配的同步问题,解决方案有两个...

    Java JVM 面试题总结

    JVM 面试题总结 JVM 的主要作用是什么? 请你描述一下 Java 的内存区域?...内存分配方式有哪些呢? 请你说一下对象的内存布局? 对象访问定位的方式有哪些? 如何判断对象已经死亡? 如何判断一个不再使用的类?

    java 面试题 总结

    内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    / 41 2.5 本章小结 / 42 第3章 垃圾收集器与内存分配策略 / 43 3.1 概述 / 43 3.2 对象已死? / 44 3.2.1 引用计数算法 / 44 3.2.2 根搜索算法 / 46 3.2.3 再谈引用 / 47 3.2.4 生存还是死亡? / 48 3.2.5 ...

    深入理解Java虚拟机视频教程(jvm性能调优+内存模型+虚拟机原理)视频教程

    视频目录 第1节说在前面的话 [免费观看] 00:05:07分钟 | 第2节整个部分要讲的内容说明 [免费观看] 00:06:58分钟 | 第3节环境搭建以及jdk,...第104节字节码执行引擎小结00:03:38分钟 | 第105节总结与回顾00:10:55分钟

    Java虚拟机

    原子性、可见性和有序性在Java内存模型中的体现;先行发生原则的规则和使用;线程在Java语言中的实现原理;虚拟机实现高效并发所做的一系列锁优化措施。 前言 第一部分 走近Java 第1章 走近Java 1.1 概述 1.2 ...

    Java语言的科学与艺术 斯坦福大学经典教材

    6.8 复习题 6.9 编程练习 第7章 对象和内存 7.1 内存结构 7.2 将内存分配给变量 7.3 原始类型与对象 7.4 链接对象 7.5 小结 7.6 复习题 7.7 编程练习 第8章 字符串和字符 8.1 枚举的原则 8.2 字符 8.3 作为抽象概念...

    jvm内存管理和垃圾回收

    很久之前就一直在学习JVM,但是一直也没有好好的总结,最近终于有了空闲,将之前学习的内容整理成了一个PPT。 也希望大神们可以批评指正。... Java内存模型 内存分配策略 分代垃圾收集 虚拟机工具 垃圾收集器

    Java语言的科学与艺术(国外计算机科学经典教材)

     7.2 将内存分配给变量  7.3 原始类型与对象  7.4 链接对象  7.5 小结  7.6 复习题  7.7 编程练习 第8章 字符串和字符  8.1 枚举的原则  8.2 字符  8.3 作为抽象概念的字符串  8.4 使用String类中的方法 ...

    疯狂JAVA讲义

    学生提问:能不能只分配内存空间,不赋初始值呢?89 4.5.4 使用数组 90 学生提问:为什么要我记住这些异常信息? 91 4.5.5 JDK1.5提供了foreach循环 91 4.6 深入数组 93 4.6.1 内存中的数组 93 学生提问:为...

    java基础心得总结.rar

    描述java基础容易忽略的问题,如下面几个知识点: int a = 1;1会存放在栈里 String s1 = "thanks";thanks会存放在data segment里 String s2 = new String("thanks");thanks会存放在data segment里 String a ="th...

    java基础入门教程

    所 以 有 人 说 :"现 在 第 三 方 的 开 发 商 都 团 结 在 Java大旗 周 围了 !",纷 纷 推 出 用Java 开 发 的 各 种 软 件 产 品 ,以 期尽 快 地 占 领 市 场 。 四 、 Java 语 言 的 应 用 前 景 Java 语 言 ...

Global site tag (gtag.js) - Google Analytics