1、JAVA语言基础 第2章 Java语言基础 JAVA一种编程语言,主要运行在J2ME/SE/EE三个平台上。目前JVAV在安卓手机平台上也很流行。 对于有C/c++语言基础的同学,JAVA语言可以分为两部分学习: (1)基本部分(这一部分与C/c++语言相似) (2)面向对象部分 本章讨论JAVA语言基本部分 1 形式语言概念 JAVA是一种高级的、形式化的编程语言。 在世界上曾出现过上千种计算机语言中,很多是高级语言,它们无一例外的都是形式化的语言,JAVA是其中最流行的之一。 早期:二进制语言,程序与CPU指令一一对应,程序员要适应机器的思维方式。 稍后,出
2、现了(宏)汇编语言。用助记符代表二进制的CPU指令,减轻记忆负担,程序员仍要适应机器的思维方式。汇编语言要通过一个翻译程序(汇编程序)将助记符转换为二进制的CPU指令,现在仍有少量从事控制方面或计算机底层编程的人使用汇编语言 再后,出现了高级语言,这是一个飞越,程序员可以用接近人的思维方式而不是机器的思维方式编程。高级语言程序要通过一个翻译程序(叫编译程序或解释程序)转换成二进制的CPU指令方能运行。 与大多数高级语言不同的是,JAVA为了实现垮平台,将程序的翻译变为两步: (1)将源程序转换为JAVA字节码(.class), JAVA字节码是一种与平台无关的中级语言。 (2)JVM将
3、JAVA字节码解释或JIT(just in time)编译成与CPU有关的二进制指令,并运行。 目前还有一些超级语言。它们比高级语言更接进人的自然思维,功能更强大,如VFP、SQL、FLASH AS、MATLAB等编程语言。超级语言往往有很强的专门性,缺乏通用性。 未来,可能出现完全用自然语言编程的技术。 现有的高级语言都是形式化的,什么叫形式语言? 不严格的说,与自然语言相比,形式语言也是符号的集合,但形式语言符号的语义是严格定义的、没有二义性的,当用形式语言符号解题时,结果也没有自然语言的模糊性。举例:数学语言即为形式语言。 对形式语言的研究始于古希腊的逻辑学和形而上学,而近
4、代采用的主要研究思想和方法来源于数理逻辑和代数。在计算机软件出现以前,对形式语言的研究就达到很高水平了。 为什么现有的计算机语言都是形式化的? 因为计算机还没高级到能很好的理解自然语言,形式化的高级语言是计算机编程目前所能达到的最高程度。 形式语言的语法有哪些成分? 与自然语言类似,有词法和句法。 以C语言为例,其语法包括: 词法: (1)关键字:预设的、有唯一语义的“单词”,C语言大约有几十个关键字。 (2)操作符:预设的、有唯一语义的运算符号。 (3)数据类型:预设的、有唯一语义的数据类型,比如整数、浮点数、字符、数组、结构体等等 (4)标识符:程序员可自定义
5、的“单词”,用来标识常量或变量。标识符也有唯一语义。 句法: (1)表达式和顺序语句 (2)选择语句:表示“如果怎样,那么怎样” (3)循环语句:表示“这件事做多少遍” (4)转移语句:表示“从现在位置转移到另外一个位置” 计算机语言解题的特点: 并不善于推理和归纳,它最擅长做的是两件事: (1)判断:如果这样,那就这样。 (2)循环:像一个机器人一样,重复的、以惊人的速度做同一件事。 初学者一定要了解计算机解题的上述特点,才能写出程序,主要是掌握循环的使用。 2 JAVA语言的关键字 JAVA语言有40多个关键字,其中一部分与C/C++相同,其含义及用法也
6、基本相同,如下表所示。 boolean float void abstract instanceof break for volatile assert interface byte if while catch native case int class new char long default package const null this extends private continue return throw final protected do short throws finally pub
7、lic double static transient implements super else switch try import synchronized 3 JAVA语言标识符 标识符是程序员自定义的符号,主要用于给变量、常量、函数等命名,命名规则与c/c++基本相同。 Java标识符由数字,字母和下划线“ _”,美元符号“$”组成。Java标识符是区分大小写的,而且还要求首位不能是数字。最重要的是,Java关键字不能当作Java标识符。 下面的标识符是合法的: myName,My_name,Points,$points,_sys_ta
8、 下面的标识符是非法的: #name,25name,class,&time,if 在实际工作中,标识符的命名是很重要的事,不仅要合乎上述语法要求,而且要合理,要满足“见名知意、作用域尽可能小”等原则,要满足企业(或项目组)的规定。正规的软件企业将标识符的命名规则作为严格的项目纪律,不允许程序员自行其是。 java语言常见的标识符命名约定有: (0)见名知意。见到标识符的名字,就能大致猜到其含义。 (1)类和接口名。每个字的首字母大写,含有大小写。例如,MyClass,HelloWorld,Time等。 (2)方法名。首字的首字母小写,其余的首字母大写,含大小写。尽量
9、少用下划线。例如,myName,setTime等。 (3)常量名。基本数据类型的常量名使用全部大写字母,字与字之间用下划线分隔。对象常量客大小混些。例如,SIZE_NAME。 (4)变量名。可大小写混写,首字符小写,字间分隔符用字的首字母大写。不用下划线,少用美元符号。 (5)不要使用中文,因为有些系统对中文支持不好。 4 JAVA代码注释 与C/c++基本相同。 比如://单行注释 /* 多行注释。。。 */ 在实际工作中,写好程序的注释也是极为重要的,程序注释是关键性的技术文档,对程序的后续维护升级有重要的价值,一套程序注释的行数多于或接近于代码的行数
10、是很常见的。 程序的注释的好坏往往体现了程序员的职业素养的高低,切勿忽视。 注释应该怎样写呢?最重要的是,注释要说明的是被注释的代码是做什么的,而不是怎么做。做什么由注释说明,怎么做由代码说明。比如你写了一个对数组排序的函数,只需在注释中说明该函数是做数组排序的,而具体的排序算法不必在注释中说明。 5 基本数据类型 JAVA语言支持多种数据类型,分为基本类型和引用类型,下面分别介绍: 简单数据类型(基本数据类型) (八进制数以0前缀,十六进制数以0x或0X为前缀) 类型 关键字 占用字节数 整型 int byte short long 4
11、 1 2 8 浮点型 float double 4(后缀f/F) 8 布尔型 boolean 字符型 char 浮点型数据采用科学计数法形式。如:123e3或123E3,其中e或E之前必须有数,且e或E后面的指数必须为整数。浮点数在机器中默认为double,占8字节。对于float型的值,要在数字后加f或F特别说明,如12.3F,它在机器中占4字节,表示精度较低。 浮点型数据之所以采用科学计数法,是因为在表示大数据时,占用的字节少,但其精度不够,比如: double x=123456.789, y=123456.789; x==y; //不一定返回tr
12、ue,因为精度问题,x,y不一定相等。 如何解决上述问题?同学们可以上网搜索“浮点数 判等”。 小知识:JAVA是纯面向对象的语言,与C/C++不同的是,JAVA的简单数据类型也可以是面向对象的,对应一些包装类,有属性和操作,这一点以后讲解JAVA API时再介绍。 引用数据类型: 数组、类、接口,以后陆续介绍。 【提示:Java不支持C/C++中的指针、结构体和共用体】 重要知识:JAVA引用数据类型和简单数据类型有什么区别? 引用类型变量的名字代表其引用(首地址),而简单类型变量的名字代表其值。引用类型本质上是指针,但JAVA取消了指针的概念和语法,代之与
13、引用”。 重要知识:强类型语言和弱类型语言 很多同学在学习编程语言时,对繁杂的数据类型及类型转换规则感觉很头痛。为什么编程语言要做如此繁琐的规定? 与C/C++一样,JAVA是一种强类型语言。 按类型划分,高级编程语言可分为强类型的(如C/C++/JAVA/C#/VB.NET、弱类型的(如VB)和无类型的(如VbSrcript)。 为什么大多数主流语言都是强类型的?从编译器的设计上看,编译时所有对象类型(除多态对象外)均确定,因此在内存的位置也确定,这可以简化编译器的设计、提高效率、节约资源;其次它可以帮助程序员检查一些类型的不匹配引起的错误,比如将一个整数和一个字符串
14、相加,这可能有违程序员的本意,也可能会给程序带来潜在的危险,这时编译器会给你报错。 强类型语言有利于提高程序的健壮性,但也给程序员带来一些麻烦,你必需时时留意类型转换问题,否则编译器要么报错,要么留下潜在的危险。但从长远来说它将帮助你减少程序出错的可能性。 对于强类型的编程语言,数据类型转换是程序员常用又极容易犯大错误的地方,一定要特别小心,反复验证。在一些专业的JAVA编程书里,对数据类型转换都加以较详尽的说明。我们要知道:不正确的数据类型转换是编程重大隐患所在,有时编译器不能识别这种错误。 强类型的编程语言对数据类型检查较完善,适合可靠性要求高的应用。而弱类型(如VB)和无类型
15、的(如Vbsrcript)编程语言,数据类型检查很松散,程序员也不需做细致的类型检查,适合可靠性要求低的应用。 要学好JAVA语言(或其他强类型语言),特别要注意类型问题。实际上,无论从理论上和实践上,无论使用何种强类型高级语言,类型问题永远是重要问题,专业程序员对此绝不会掉以轻心。 6 常量与变量 变量和常量的区别在于:变量一经定义和赋值,还可以重新赋值,而常量一经定义和赋值,不能重新赋值。 JAVA语言变量和常量的概念与C/C++相同,定义常量的语法上略有不同。 (1) 变量的声明格式为: type identifier[=value][,ident
16、ifier[=value]...]; 例如:int a=10,b,c; double d1,d2=0.0; 其中,多个变量间用逗号隔开,变量可以在定义时赋初值,也可以在以后赋值。 (2)使用final关键字来定义一个常量,比如: int final PI=3.17; 习惯上将常量的名字统统大写。 在计算机语言中,常量可以表示“数学常数”, 但常量的真正含义不是“数学常数”,而是“只读”,它可以保护常量所在的内存单元不被意外修改----在编程务实中,如果一些量不允许被修改,可以将其声明为常量。 7 运算符 JAVA主要有4
17、类运算符: u 算术运算符;+,-,*,/,++,--,%等 u 位运算符: &, | , !,<<, >>等 u 关系运算符;>,<, >=, == u 布尔运算符。&, | , !,&&(条件与), ||(条件或)等 此外还有: 赋值运算符:= 强制类型转换符()。比如:(int)x 条件运算符: 表达式1? 表达式2: 表达式3 括号运算符() 字符串连接运算符:+ 点运算符 “.” ,用于分割包/子包/类/类成员 JAVA运算符的优先级结合性(左结合,右结合)与c/c++相同。 【提示:对于繁多的运算
18、符,同学们无需一次性掌握,本课件也没有列出JAVA的全部运算符】 8 JAVA“简单数据类型”的转换 JAVA作为强类型语言,数据类型转换规则相当烦杂枯燥,本章不做全面介绍,只介绍初学者编程常见的“简单数据类型”转换方式。 前面第5小节介绍的Java整型、浮点型、字符型被视为简单数据类型,这些类型由低级到高级分别为: (byte,short,char)--int--long--float--double 当从低级到高级转换时,我们叫“赋值相容”,这种转换是隐式的(或叫自动的),不需要特别处理,比如以下转换是合法的: --------------------------
19、 short x=100; int i=x; long l=i; float f=l; double d=f; ----------------------------------- 下面的例子,字符型转为整型也是合法的,自符型会转换为对应ASCII码值,例如: ------------------------------------ char a='c'; int i=a; System.out.println(i); ------------------------------------- 输出: 99; (99是c的ASCII码值)
20、 对于平级 (byte,short,char是平级的)和高级到低级的转换,是“赋值不相容”,这种转换是显式的(或叫非自动的、强制的类型转换),被转换的数据前面必需加一个 “(类型)”运算符。 例如:对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换,应使用下述的强制类型转换。 -------------------------------------------------------------------------------- short i=99; char a=(char)i; //()为强制类型转换符 System.out.prin
21、tln(c); -------------------------------------------------------------------------------- 输出:c; (99是c的ASCII码值) 下面是一个从高级到低级,必需使用强制类型转换的例子: -------------------------------------------------------------------------------- double x=99; int i=(int)x; byte b=(byte)i; char c=(char)i; -----------
22、 可以想象,这种转换可能会导致数据溢出,要特别小心。 看这个程序: public class Convert { public static void main(String args[]) { double x=99; int i=(int)x; byte b=(byte)i; System.out.println(b); } } 运行结果
23、是:99 如果把x改为99999呢?运行结果是: -97 b为什么变成-97呢?因为b的类型是byte,只占1字节,数据表示范围是-127—128,当遇到99999时,b溢出了,变成一个莫名其妙的-97。 从这个例子我们看出数据类型转换的危险性,本例这种情况编译器不给你报错,因为代码完全符合语法要求。这需要程序员认真测试:将x的值从最小到最大都测一遍。再看这个例子: public class Convert { public static void main(String args[]) { double x=127; by
24、te b=(byte)x; b++; System.out.println(b); } } 我们希望b为128,但程序的输出却是-128。这种情况编译器不给你报错,因为代码完全符合语法要求。 从上面两个例子看出:数据类型转换多么容易出错,即便强类型的语言也不能避免。在实际工作中,如果出现这种错误,可能会造成严重问题, 应该对数据的上下边界进行测试以避免错误。 9 Java语句 大多数高级语言的语句由3种基本结构组成: 顺序结构、分支结构、循环结构(均为单入口,单出口)
25、 有人从理论上证明过,这三种结构组成的算法可解任何计算机可计算的问题。 这三种结构必需有入口和出口,结构内的每一个语句都应该有机会被执行(但并不是每次运行时每个语句都应被执行最少一次。) Java语句分类: 上述语句在C/C++已详尽介绍过,本章不做详述。需要注意的是,3种循环语句是等效的。 关注循环语句 循环语句体现了计算机解题和数学解题的最大不同,数学解题往往要寻求一个“式子”,使用巧办法,而计算机解题可以使用笨办法,一遍遍的去重
26、复。初学编程者一定要注意这个特点。 比如: 求1-100的和,计算机程序可以怎么做?用数学方法怎么做? 比如: 求100个数组元素的和,数组元素的排列没有规律,计算机程序可以怎么做?用数学方法怎么做? 计算机解题的方法叫算法,算法有些与我们习惯的数学方法相同,有些则不同。 程序的效率分为两种:时间复杂度(执行速度快慢)和空间复杂度(占用资源多少)。循环语句与程序的时间复杂度有莫大关系。优化程序时间复杂度最关键的是减少循环次数。比如把3重循环改为2重循环等等。程序的时间复杂度与代码量的多少关系不大,与循环次数的关系很大。 10 函数 与C/C++一样,函数是JAVA可重复使
27、用的最小程序模块,一个函数实现一个“功能”,该功能可以是一个算法或一个算法的一部分,也可以是一个输入输出模块,也可以是一个初始化模块。无论如何,一个函数应该只实现一个单一的功能,而不宜实现多个功能。 对初学编程者,最重要的技能是:学会使用循环解题,学会写函数。 在JAVA语言中,函数被改称为“方法,method”,实际上,“方法”的写作与函数的写作没有太大区别,方法就是函数,其基本语法为: 返回类型 函数名(形参,形参,….) //方法原型声明 { //方法体代码 return 返回类型 } JAVA的方法原型声明还有一些扩展性或修饰性的
28、变化,以后课程将陆续介绍。JAVA的方法除了普通方法,还有静态方法、构造方法、析构方法、重载方法、重写(覆盖)方法、this方法、super方法等多种,以后课程将陆续介绍。 11 数组 JAVA数组的概念,与C/c++相同,但语法有所不同. • 一维数组(向量) • 二维数组(矩阵) • 多维数组(不常用) 与int,float……一样, 数组是一种数据类型,但数组类型是引用类型的(而不是简单类型的)。 声明和使用数组的顺序是: (1)先声明数组变量; (2)用new操作符给数组分配内存空间; (3)用下标访问数组元素. 11.1 一维数组 一维数组又叫向
29、量。声明一维数组有两种等效的方法: (1) 数据类型名[] 数组名 例: int[] a;//声明数组a,数组元素为int 型 (2) 数据类型名 数组名[] 例: int a[];//声明数组a,数组元素为int 型 上面两种写法是等效的. 声明数组后还不能直接使用数组,接下来要指定数组大小(数组元素有多少),并用new操作符并为数组分配内存。语法是: 数组名= new 数据类型[长度] 例: int[] a;//声明数组a,数组元素为int 型 a=new int[5]; //a有5个元素,每个元素默认初值为0,
30、 例: int a[]; //声明数组a,数组元素为int 型 a = new int[5];//与例1一样 例:上两例的两句均可合并为一句: int a[] = new int[5]; 数组变量一经new,数组元素就都有了默认值. 比如 int a = new int[5]; 数组元素默认值均为0 为了照顾C语言程序员的习惯,也可以省略new操作符,直接声明并初始化数组: int a[]={1,2,3,4,5} 这种写法与C语言一样,但数组存放在内存的位置与C不同,C语言局部数组(在函数内声明的数组)存放在内存的栈中,全局数组存放在
31、堆中。而JAVA的局部数组存放在内存的堆中,JAVA只有局部数组,没有全局数组。 栈是系统掌管的内存区,系统为每个程序建立一个栈,栈很小(一般不超过4M内存),栈的效率好但程序员无法干预栈。堆是系统为程序员创建的自由内存区,系统为每个程序建立一个堆,堆可以很大,堆的效率较差,好处是程序员可以干预堆的内存分配和释放。 数组元素及下标 数组元素是数组的一个成员,用下标表示,下标取值范为从0到数组长度减1。 例: int[] a;//声明数组a,数组元素为int 型 a=new int[5]; //a有5个元素,每个元素默认初值为0, 此时,数组a有5个元素,数组元素名及
32、值分别为: a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0 上例中下标范围从0—(5-1) 【注意:JAVA语言数组下标不能越界!上例中, a[-1], a[5]的写法是不可以的,编译器会报错.这一点与C/C++不同。】 测量数组长度: 可以使用 数组名.length 测量数组长度,即数组有多少个元素。length返回整数。 例:int i; int[] a; a=new int[5]; i=a.length; //此时i=5, length实际上是JAVA内置的数组类的一个属性。 初始化数组用new或不用new
33、 数组声明时赋初值:这是C语言程序员习惯的写法,可以不用new操作符 例:int a[]={1,2,2,1,5}; 上面的一句等效于下面若干句: int[] a; a=new int[5]; a[0]=1;a[1]=2;a[2]=2;a[3]=1;a[4]=5; JAVA初始化数组用new或不用new,数组都分配在堆里,这一点与C++不一样,C++初始化数组用new则数组在堆里(堆对象),否则数组在栈里(栈对象)。 在C++和JAVA语言里,new操作符的含义均为:为对象在堆中分配内存。 11.2 二维数组(矩阵) 声明二维
34、数组的语法,与一维数组相似,只是多了个[] (1)int mat[][]; mat=new int[3][4]; (2)int mat[][] = new int [3][4]; 上面两种写法是等效的,声明了一个有3*4个元素的二维数组,可以把它想像成3行4列的矩阵.所有元素的初值都为0. 二维数组元素表示格式如下: 二维数组名[下标1][下标2], 下标1,2的值从0开始. 比如:mat[1][2]=10;//表示第2行第3列的数组元素值为10 11.3 理解数组的引用特性 我们知道,C/c++的数组本质上是指针,下面的C语言代码: i
35、nt a[]={1,2,3,4,5}; int *b; b=a; b[0]=100; 此时a[0]为多少?为什么? JAVA语言没有指针的概念,也没有“*,&,->”等关于指针的语法,却有“引用”的概念,可以把引用理解为指针的改头换面: 下面的伪代码: void fun(int [] a) {int[] b=a; b[0]=100;} int a[]={1,2,3,4,5}; fun (a); 假如是C/c++语言,我们知道实参a[0]也被改为100. 假如是JAVA语言,是否也有同样效果?是 结论:JAVA的数组是引用类型, 数组名代表数组在内存中的
36、首地址。这个特性与C/c++相同。 而JAVA基本类型(int,folat,char..等)不是引用类型,其名字代表其值而不是首地址,这个特性与C/c++相同。 JAVA的类和接口是引用类型,类和接口的名字也代表他们在内存中的首地址。实际上,JAVA的数组本质上是一个类。 问题1: int a=10, b=10; b==a; // 应为true还是false ? 问题2: int a[]={1,2,3,4,5}; int b[]={1,2,3,4,5}; b==a; //应为true还是false ? a[0]==b[0]; //应为tru
37、e还是false ? 答案1: int a=10, b=10; b==a; // 应为true,基本类型比较的是值 答案2: int a[]={1,2,3,4,5}; int b[]={1,2,3,4,5}; b==a; //应为false。引用类型比较的是其引用(地址),b和在不同的内存空间中,其引用不同。 a[0]==b[0]; //应为true,因为这两个数组的元素是基本类型 12 字符串 与C/C++相同,JAVA语言本身不支持字符串,但可以通过JAVA API一个叫String的类方便的使用字符串(类似的,C语言可以通过一
38、些标准函数使用字符串) 声明字符串变量 (1)String str = "abc"; String实际上是JAVA API中的一个类,但也可以当做一个数据类型使用,因为JAVA的类是引用类型的,所以String也是引用类型。 创建字符串还有另一种更规范的写法: (2)String str=new String("abc") 上述2种写法,效果是有差别的,在后续课程介绍JAVA API时再讲解。 JAVA字符串可以进行一些运算: 赋值运算:String str1 = "abc"; String str2 = str1; 连接运算: str1= "abc" +
39、"xyz"; //str的值为"abcxyz" 关系运算:"ABX" < "AXB" //结果是true,由第2个字符得出比较结果 “ABC” > “AB” //结果是true,较长字符串比较结果“较大” JAVA的String是字符串类型,而不是字符数组类型,不能用下标方式访问:比如str[1]是错的. String的其它特性在以后课程介绍JAVA API时继续讨论。 13 样例程序演示 至此,完成了JAVA语言基本部分的讲解,下面演示几个样例程序。由于篇幅原因,本课件不给出源代码,同学们直接打开配套的课件附件学习即可。 这些样例程序都不长,算法
40、也很简单,同学们最需关注是其编程风格:main()方法只包含启动程序的代码,而算法及输入输出都写在其它方法中,对于小程序来说,这种风格需要多写几行代码、多几个方法调用,似乎画蛇添足。但这种风格是值得模仿的,可以从中学到如何写方法(一个方法只实现一个功能),以及方法之间如何相互调用,这对以后写大型程序很有用。要知道,有些几万行代码的程序,其main()方法只有寥寥几行代码而已,main()方法的任务就是启动程序,不应该负责算法或输入输出的执行。 14 堆、栈、JAVA的内存自动管理机制 JAVA语言最重要的特点是跨平台,在第1章中已做过讲解。JAVA语言另一个重要的特点是内存自动管
41、理(也叫垃圾自动回收),这种技术应用于90年代,是java或其它新型编程语言的重要特性, 它是怎么实现的?又有什么好处? 要从操作系统对内存的管理谈起。 在计算机系统中,内存是由操作系统管理的,当一个程序被创建时,操作系统将为该程序分配内存,一个程序占有的内存大致上分为栈和堆2部分,我们在使用电脑时,有时会遇到“栈溢出”或“内存溢出”的问题,此时程序崩溃,原因一般是程序员在栈中创建了大对象使栈“爆仓”,或者在堆中创建对象后忘记释放内存使堆“爆仓”。 栈是较小的内存区,一般不超过4M,这块内存的使用完全由操作系统控制,程序员不能干预。堆要比栈大得多,而且程序员可以控制堆的使用,在
42、堆中分配/释放内存。 C语言:使用malloc()/free()函数分配/释放堆内存,学习C语言版的“数据结构”课程时,常常要使用这2个函数,这是因为程序员必须在堆中创建数据结构,然后才能对其自由操作。C语言的另一个特点是, 默认情况下,全局量存在堆中,局部量存在栈中。 C++语言:new操作符创建的对象在堆中(堆对象),否则在栈中(栈对象)。 C和C++都没有自动内存管理功能,当堆中的对象不再使用时,程序员必需亲自写代码释放堆内存。C语言可调用free()函数释放堆内存,C++可调用析构方法或free释放堆内存,当程序员忘记这样做,时间长了就可能造成堆溢出。 而JA
43、VA语言具有自动内存管理功能,只要是引用类型的数据(类、接口、数组、字符串等等),无论是否用new创建,都放在堆中,当某对象长时间不使用,JAVA会按某种算法自动回收该对象占有的堆内存,这样不容易造成堆溢出。 下面谈一下栈。栈是较小的内存区,一般不超过4M,这块内存的使用完全由操作系统控制,程序员不能干预。栈空间使用不当,是很容易溢出的。 下面的C/C++代码: main() { int a[1000000]; } 会发生什么? 局部数组a[1000000]过大,编译时正常,运行时使栈溢出。 如何解决这个问题? C语言有2种办法,这2种办法都可以把大数组分配
44、在堆中: (1)把数组声明为全局的,比如: int a[1000000]; main() { } (2)使用C标准函数库中的内存分配函数malloc(),要注意的是,当数组不再有用时,使用标准函数库中的内存去配函数free()释放内存,否则容易造成堆溢出。 C++只要用new创建数组,即可使数组创建在堆中,要注意的是,当数组不再有用时,要调用析构函数或free释放内存,否则容易造成堆溢出。 JAVA语言呢?JAVA语言的数组,无论是否使用new,都创建在堆中,所以不会因数组过大造成栈溢出。而且,JAVA语言具有内存自动管理功能,只要是引用类型的数据(数
45、组、字符串、类等)全部放在堆中,由JAVA的“垃圾自动回收”机制管理,堆中不用的数据所占内存由“垃圾自动回收机制”按某种算法自动回收。程序员无需为堆内存的分配、释放操心。 【注意:JAVA内存自动管理,只对堆内存有效,对栈内存无效,栈内存是操作系统完全控制的】 根据上面的讲解,应该知道,C++和JAVA语言的new操作符,其确切的语义是:为对象在堆中分配内存。 课后习题 一、简答题 1 程序的注释应该写什么内容? 2 强类型编程语言有什么优点? 3 理解数组的引用特性 4 理解JAVA“简单数据类型”的转换规则 5 通过示例代码理解JAVA
46、简单数据类型”强制转换时潜在的危险。 6 JAVA语言自动内存管理的原理和优点是什么? 7 new操作符的确切含义是什么? 二、编程题 1 写一个“JAVA运算符大全”程序,为用户演示各种运算符的使用。 2 对于一个可以用循环方式求解的编程问题,试用while,do-while,for三种循环分别求解,验证三种循环的等效性。 3 写一个程序,判断一个字符串是否为JAVA语言的关键字,如果是关键字,则输出一行文字,解释该关键字的含义. 三、网络调研题 1 JAVA语言没有指针的语法,原因何在? 2 上网搜索“浮点数 比较”或“浮点数 判等”,了解浮点数的相关特点。 22 / 22






