JAVA基础知识2.ppt_第1页
JAVA基础知识2.ppt_第2页
JAVA基础知识2.ppt_第3页
JAVA基础知识2.ppt_第4页
JAVA基础知识2.ppt_第5页
已阅读5页,还剩57页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第2章 Java语言基础,本章将介绍Java语言的基础知识,包括基本语言要素、基本数据类型、变量、数组、运算符等。扎实地掌握这些内容对后续学习是很有必要的。,2.1 预备知识 2.2 基本语言要素 2.3 基本数据类型 2.4 变量 2.5 数组 2.6 运算符,Return,2.1 预备知识,2.1.1 一个简单的Java程序 2.1.2 两种控制语句2.1.3 关于程序块,Return,在第1章中,我们已经学会了编写“Hello World”这种极为简单的Java程序。为了便于本章后面内容的叙述,本节将再介绍一个稍复杂的Java程序,使读者在学习Java语言的基础知识前也能够编写简单的Ja

2、va程序。,2.1.1 一个简单的Java程序,class MyExample public static void main(String args) int num; num = 200; System.out.println(This is num: + num); num = num * 2; System.out.print(The value of num * 2 is:); System.out.println(num); ,下面是一个简单的Java程序。读者将会看到,这个程序虽然不是很复杂,但其中所包含的内容和功能却很丰富。,运行结果: This is num: 200 The

3、 value of num * 2 is: 400,对大多数的编程语言来说,程序源代码文件的命名是任意的,只要符合所运行的操作系统平台的要求即可。但这对于Java来说就行不通。在开始进行Java编程前,读者需要知道的第一件事情就是:源文件的名称必须与主类名一致。这一点非常重要。对于上面的例子,源程序文件名就应该是MyExample.java。下面我们将解释其中的原因。 在Java中,一个源程序文件被称为一个编译单元(Compilation Unit),它是包含一个或多个类定义的文本文件。Java编译器要求源程序文件使用.java作为扩展名。请注意,文件扩展名的长度是4个字符,因此所用操作系统一

4、定要有支持长文件名的能力。这就意味着DOS和Windows 3.x是不支持Java文件命名规则的。 从上述示例程序中可以看出,程序中定义的类名也是MyExample,这不是巧合。在Java中,所有的代码都必须驻留在类中。按照约定,类名必须与源程序的文件名相同,同时还要确保文件名的大小写字母与类名一样,因为Java是区分大小写的。虽然文件名与类名必须一致的约定显得似乎有些死板,但是这个约定有助于编程人员轻松地维护和组织程序。,1关于该程序的命名,在第1章中曾经涉及到这方面的内容。要编译并运行示例程序MyExample,首先要运行编译器程序javac,并在命令行上指定源程序文件名,具体格式如下。

5、C:javac MyExample.java 这样,编译器javac产生一个名为MyExample.class的文件,该文件包含程序的字节码。前面已讨论过,Java字节码中包含的是Java解释程序将要执行的指令码,因此javac的输出结果并不是可以直接运行的代码。 要真正运行该程序,必须使用名为java的Java解释器。具体方法是将类名MyExample作为一个命令行参数输入,格式如下: C:java MyExample 如果程序运行正常,将输出如下内容: This is num: 200 The value of num * 2 is: 400,2编译和运行程序,提示:当Java源代码被编译

6、后,每个单独的类都被放入自己的输出文件中,并以类的名字加.class扩展名为其文件名。这就是为什么Java源程序文件必须与其中包含的类同名的原因源程序文件将与.class文件同名。运行Java解释器,实际上是指定想要解释器运行的类的名字,它会自动搜索包含该名字且带有.class扩展名的文件。如果找到,它将运行包含在该指定类中的代码。,Return,2.1.2 两种控制语句,1.if控制语句 Java中的if控制语句与其他编程语言中的IF语句非常相似,并且与C/C+语言中的if语句的语法完全相同。它最简单的形式如下: if(condition) statement; 其中:condition是一

7、个布尔表达式。如果其值为真,那么执行语句statement;如果其值为假,则语句statement将被绕过而不被执行。 例如下列语句: if (num 2008) println(You are welcome!); 该语句的功能是:如果变量num的值小于2008,那么条件表达式的值为真,方法println()将被调用执行,否则方法println()被绕过而不被执行。,尽管在后面的第3章中将详细讨论Java控制语句,这里我们还是先简要介绍两种控制语句,以便能在本章后面的例程中使用它们。,class IfSample public static void main(String args) in

8、t a,b; a = 100; b = 200; if(a b) System.out.println(a now greater than b); ,下面的程序说明了if控制语句的用法。,运行结果: a is less than b a now equal to b a now greater than b,在几乎所有的编程语言中,循环语句都是很重要的组成部分,这对于Java也不例外。事实上,在后面的有关章节中读者将会看到,Java提供了一套功能强大的循环结构,而for循环也许是最通用的。如果读者对C/C+熟悉,会发现Java的for循环和C/C+语言中的for循环操作完全一样。 最简单的f

9、or循环结构的形式如下: for(initialization; condition; iteration) statement; 其中,循环体的初始化部分(initialization)设置循环变量并为变量赋初始值。条件判断部分(condition)是测试循环控制变量的布尔表达式。若测试结果为真,循环体(statement)继续反复执行;若测试结果为假,循环结束。迭代部分(iteration)的表达式决定循环控制变量在每次循环后是如何改变的。,2.for循环语句,class ForTest public static void main(String args) int a; for(a =

10、 0; a10; a = a+1) System.out.println(This is a: + a); ,下面的这个短程序说明了for循环的使用方法。,运行结果如下: This is a: 0 This is a: 1 This is a: 2 This is a: 3 This is a: 4 This is a: 5 This is a: 6 This is a: 7 This is a: 8 This is a: 9,在该例子中,a是循环控制变量,它在for的初始化部分被初始化为零。在每次重复迭代(包括第一次)的开始,执行条件测试a 10。如果测试的结果为真,则println()语句

11、被执行,然后执行循环体的迭代部分。此过程将持续进行下去,直到条件测试的结果为假。,注意:通常在Java专业程序员编写的程序中,循环体的迭代部分很少会看到象“a = a + 1;”的语句。原因是:Java语言中有一个特殊的增量运算符,即“+”和“-”,它们的作用分别是为对象加1和为对象减1 。 这样,前述的for循环语句通常写成下列这样: for(a = 0; a10; a+),Return,2.1.3 关于程序块,在Java语言中,可以将2个或2个以上的语句组成一个语句组,这样的一组语句被称为程序块(Codeblocks)。程序块通过将所属语句放在大括号中来实现。一旦创建了程序块,它就成为一个

12、逻辑单元,可以作为一个单独的语句来使用。例如,程序块可以作为Java中if控制语句和for控制语句的目标。下面我们来看一下如下的if控制语句: if (a b) / begin a block a = b; b = 0; / end of block 本例中,如果a小于b,那么在程序块内的两条语句都将被执行。因此,程序块中的这2条语句组成一个逻辑单元,不能出现一条语句运行,而另一条语句不运行的情况。其中的关键点是如果你需要将两个或多个语句在逻辑上连接起来,就可以将其放入一个程序块中。,2.1.3 关于程序块,又例如,下面的程序将for循环作为一个程序块使用: class BlockTest p

13、ublic static void main(String args) int a,b; b = 20; / the target of this loop is a block for (a = 0; a10; a+) System.out.println(This is a: + a); System.out.println(This is b: + b); b = b - 2; 在本例中,for循环作为一个程序块使用,而不是一个单独的语句。这样每循环一次,块内的3条语句都要运行一次,此事实当然为程序的执行结果所证实。在本书的后面,读者将会看到程序块的其他性质和用法。勿庸置疑,程序块存在的

14、主要原因是为了创建逻辑上独立的代码单元。,Return,2.2 基本语言要素,2.2.1 标识符2.2.2 Java关键字2.2.3 字面量2.2.4 分隔符2.2.5 注释,Return,前面我们通过几个短的程序使读者对Java编程有一个初步的轮廓。在本节里,我们将开始对Java语言元素进行介绍,Java的基本语言要素包括标识符、关键字、字面量、分隔符、注释、数据类型、变量以及运算符等。,2.2.1 标识符,标识符(Identifier)是赋给类、方法或者变量的名称。一个Java标识符可以由大写/小写字母、数字、下划线(_)、美元符号($)按照一定的顺序组合而成,但不能以数字开头,因为这样容

15、易与数字、常量相混淆。 下面是一些合法的标识符: TotalTmp Count x4$myvar this_is_var 以下是一些非法的标识符: 2thupku high-digNot/okjava b = true; System.out.println(b is: + b); b = false; System.out.println(b is: + b); if (b) System.out.println(This is executed.); b = false; if(b) System.out.println(This is not executed.); System.out

16、.println(11 1 is + (11 1); ,运行结果如下: b is: true b is: false This is executed. 11 1 is true,Return,下面对以上程序代码作几点说明。首先,读者已经看到了,当用方法println()输出布尔类型的值时,显示的是“true”或“false”;其次,布尔变量的值本身就足以用来对if语句进行控制,没有必要将if语句写成如下的形式。 if (b = true) . 另外,关系运算符(例如1的值就是“true”。在表达式111的两边额外地加上括号,是由于加号“+”运算符的优先级比运算符“”的优先级要高。,2.3.6

17、 对字面量的进一步讨论,在本章2.2.3小节中我们曾简要介绍过字面量(或常量)。现已介绍完基本数据类型,让我们对字面量作进一步讨论。,1整数型字面,整数可能是程序中最常用的类型。任何一个数字的值就是一个整数字面量。例如1、2、3、42等。这些都是十进制的值,这意味着对它们的描述基于数字10。在Java中,还有另外两种进制被整数字面量使用:八进制(Octal,基数是8)和十六进制(Hexadecimal,基数是16)。八进制的值通过在它的前面加一个前导0来表示,而正常的十进制数字则不用前导零。这样看起来有效的值09对八进制来说将产生一个编译错误,因为9超出了八进制的范围07。对编程人员来说,十六

18、进制更常用,它清楚地与8的大小相匹配,如8、16、32、64等。通过前导的0 x或0X表示一个十六进制的字面量。十六进制数的范围是015,用AF(或af)来替代1015。 整数字面量产生int值,在Java中它是32位的整数值。既然Java对类型要求严格,你可能会纳闷,为什么将一个整数字面量赋给Java的其他整数类型如byte或long而没有产生类型不匹配的错误呢。庆幸的是,这个问题已很好解决。当一个字面量的值被赋给一个byte或 short型的变量时,如果字面量的值没有超过对应类型的范围则不会产生错误。所以,一个字面量总是可以被赋给一个long变量。但是,指定一个long字面量,你需要清楚地

19、告诉编译器字面量的值是long型,这可以通过在字面量的后面加一个大写或小写的L来做到这一点。例如0 x7ffffffffffffffL(或9223372036854775807L)就是long型中最大的。,2浮点型字面量,浮点数是指具有小数部分的十进制数值,它们可以通过标准记数法或者科学记数法来表示。 标准记数法(Standard notation)由整数部分加小数点加小数部分组成。例如2.0、3.14159、0.6667等都是有效的标准记数法的浮点数值。科学记数法(Scientific notation)是浮点数加一表明乘以10的指定幂次的后缀,指数是紧跟E或e的一个十进制的数字,它可以是正

20、值、零或者负值。例如6.022E23、314159E-05、2e+100等。 Java中的浮点字面量默认是双精度。为了指明一个浮点字面量,编程人员必须在字面量后面加F或f。当然,你也可以通过在字面量后面加D或d来指明一个双精度浮点字面量,但这样做当然是多余的。默认的双精度类型要占用64位存储空间,而精确度低些的浮点类型仅仅需要32位。,3布尔型字面量,布尔型字面量很简单,因为布尔型字面量只有两个逻辑值:treu(真)或false(假)。真值或假值不会改变任何数字的表示。在Java中,真字面量的值不等于1,假字面量的值也不等于0,它们仅仅能被赋给已定义的布尔变量,或在布尔的运算符表达式中使用。这

21、一点与C/C+中是不同的。,4字符型字面量,我们已经知道,Java采用Unicode字符集来表示字符。Java的字符是16位值,可以被转换为整数并可进行像加或减这样的整数运算。通过将字符包括在单引号之内来表示字符字面量。所有可见的ASCII字符都能直接被包括在单引号之内,例如a,z,and 。对于那些不能直接被包括的字符,有若干转义序列,这样允许你输入所需要的字符。例如,代表单个引号字符本身,n代表换行符字符。 为直接得到八进制或十六进制字符的值也有一个机制。对八进制来说,使用反斜线加3个阿拉伯数字。例如,141是字母a。对十六进制来说,使用反斜线和u加上4个十六进制阿拉伯数字。例如,u006

22、1因为高位字节是零,代表ISO-Latin-1字符集中的a。ua432是一个日文片假名字符。教材P41页表2-5列出了Java中的字符转义序列。,5字符串字面量,同其他大多数编程语言一样,Java中的字符串字面量使用双引号括起来。字符串字面量的例子如下。 Hello World! threenlines This is in quotes 为字符型字面量所规定的字符转义序列和八进制/十六进制记法,在字符串内同样是适用的。对于Java字符串,应特别注意的是它们必须在代码的同一行开始、同一行结束,而不像某些语言有换行连接转义序列。 注意:读者可能知道,在其他大多数语言(包括C/C+)中,字符串作为

23、字符的数组被实现,然而在Java中却并非如此。在Java中,字符串实际上是对象类型,Java是将字符串作为对象实现的。因此,它有广泛的字符串处理能力,而且功能既强又好用。 在Java中,如果要声明真正意义上的常量(即使用标识符代表某个常值),可使用关键字final(类似于C/C+中的const)。例如,在下面的例子中就声明了一个int类型常量: final int ARRAY_SIZE = 5;,Return,2.4 变量,2.4.1 Java变量的声明2.4.2 变量的作用域和生存期2.4.3 类型转换,Return,变量是Java程序中的一个基本存储单元。变量由一个数据类型、标识符以及一个

24、可选初始值的组合来进行定义。此外,所有的变量都有一个作用域,指定变量的可见性和生存期。本节将对Java变量及其相关问题作详细说明。,2.4.1 Java变量的声明,在Java中,所有的变量必须先声明再使用。基本的变量声明方法如下。 type identifier = value,identifier = value . ; 其中,type应是Java的基本类型之一,或者类及接口类型的名字(关于类和接口将在本书后面有关章节中讨论)。identifier(标识符)是变量的名字,其后用一个等号和一个值来初始化变量。需要注意的是,初始化表达式的取值必须与指定变量类型一样或兼容。在声明指定类型的多个变量

25、时,使用逗号将各变量分开。 以下是变量声明的几个例子,其中有一些已经进行了初始化: int a, b, c; / declares three ints, a, b, and c. int d = 3, e, f = 5; / declares three more ints, initializing d and f. byte g = 123;/ initializes g. double pi = 3.1416;/ declares an approximation of pi. char x = x;/ the variable x has the value x. 不难知道,你所选择

26、的标识符名称没有任何表明它们相应类型的成分。许多读者可能还记得FORTRAN语言中预先规定从I到N的所有标识符都为整型变量,而其他标识符为实型变量。Java则允许任何合法的标识符具有任何它所声明的数据类型。,1声明一个变量,Return,尽管前面的例子中仅将字面量作为其初始值,Java语言也允许在变量声明时使用任何有效的表达式来动态地初始化变量。例如,下面的程序代码用于在给定直角三角形两个直角边长度的情况下,求其斜边长度。 / Demonstrate dynamic initialization. class DynInit public static void main(String arg

27、s) double a = 3.0, b = 4.0; / c is dynamically initialized: double c = Math.sqrt(a * a + b * b); System.out.println(Hypotenuse is: + c); 在这里,我们定义了3个局部变量a、b、c。前两个变量a和b被初始化为常量,而直角三角形的斜边c则被动态地初始化(使用勾股定理)。该程序用了Java中另外一个内置的方法sqrt(),它是Math类的一个成员,计算它的参数的平方根。这里关键的一点是初始化表达式可以使用任何有效的元素,包括方法调用、其他变量或字面量。,2动态初始化

28、,2.4.2 变量的作用域和生存期,大多数计算机编程语言定义了两大类作用域:全局和局部。然而,这些传统型的作用域并不适合Java的严格的面向对象编程模型。将一个变量定义为全局变量当然是可行的,但这是例外而不是规则。在Java中,两个主要的作用域是通过类和方法定义的。尽管类的作用域和方法的作用域的区别有点人为规定,因为类的作用域有若干独特的特点和属性,而且这些特点和属性不能应用到方法定义的作用域,但这些差别还是很有意义的。类(以及在其内定义的变量)的作用域问题我们将在本书后面的章节中介绍。到现在为止,我们将仅仅考虑由方法或在一个方法内定义的作用域。,到目前为止,我们所使用的所有变量都是在方法ma

29、in()后面被声明。事实上,Java允许变量在任何程序块内被声明。前面已经说明过了,程序块被包括在一对大括号中。一个程序块定义了一个作用域。这样,每当开始一个新块,你就创建了一个新的作用域。不难发现,一个作用域决定了哪些对象对程序的其他部分是可见的,也决定了这些对象的生存期。,下面对作用域问题作几点说明: (1)方法定义的作用域以它的左大括号开始。但是,如果该方法有参数,那么它们也被包括在该方法的作用域中。参数问题在后面章节中将作进一步的讨论,因此现在可认为它们与方法中其他变量的作用域是一样的。 (2)作为一个通用规则,在一个作用域中定义的变量对于该作用域外的程序是不可见(即访问)的。因此,当

30、你在一个作用域中定义一个变量时,你就将该变量局部化并且保护它不被非授权访问和/或修改。实际上,作用域规则为封装提供了基础。 (3)作用域可以进行嵌套。例如,每当你创建一个程序块,就创建了一个新的嵌套的作用域。这样,外面的作用域包含内部的作用域。这意味着外部作用域定义的对象对于内部作用域中的程序是可见的。但反过来就不是,内部作用域定义的对象对于外部是不可见的。,考察下面的程序。 / Demonstrate block scope. class ScopeExample public static void main(String args) int x; / known to all code

31、within main x = 10; if (x = 10) / start new scope int y = 20; / known only to this block / x and y both known here. System.out.println(x and y: + x + + y); x = y * 2; / y = 100; / Error! y is not known here. / x is still known here. System.out.println(x is + x); ,正如注释中说明的,在方法main()的开始定义了变量x,因此它对于mai

32、n()中的所有的随后代码都是可见的。在if程序块中定义了变量y,因为一个块定义一个作用域,y仅仅对在它的块以内的其他代码可见。这就是在它的块之外的程序行y=100;被注释掉的原因。如果你将该行前面的注释符号去掉,编译程序时就会出现错误,因为变量y在它的程序块之外是不可见的。在if程序块中可以使用变量x,因为块(即一个嵌套作用域)中的程序代码可以访问被其包围作用域中所定义的任意变量。显然,变量可以在程序块内的任何地方被声明,但是只有在他们被声明以后才是合法有效的。因此,如果你在一个方法的开始定义了一个变量,那么它对于在该方法以内的所有程序都是可用的。反之,如果你在一个程序块的末尾声明了一个变量,

33、它就没有任何用处,因为没有程序会访问它。,另一个需要注意的地方是:变量在其作用域内被创建,离开其作用域时被撤消。这意味着一个变量一旦离开它的作用域,将不再保存它的值了。因此,在一个方法内定义的变量在几次调用该方法之间将不再保存它们的值。同样,在块内定义的变量在该块被舍弃时,也将丢掉它的值。因此,一个变量的生存期就被限定在它的作用域之内。 如果一个声明定义包括了动态初始化,那么每次进入声明它的程序块时,该变量都要被重新初始化。例如,考虑如下的程序。,/ Demonstrate lifetime of a variable. class LifeTime public static void ma

34、in(String args) int x; for(x = 0; x 3; x+) int y = -1; / y is initialized each time block is entered System.out.println(y is: + y); / this always prints -1 y = 100; System.out.println(y is now: + y); ,可以看到,每次进入内部的for循环,y都要被重新初始化为-1。这样,即使它随后被赋值为100,该值还是被丢弃了。,运行结果如下: y is: -1 y is now: 100 y is: -1 y

35、is now: 100 y is: -1 y is now: 100,Return,另外还有一点,尽管程序块能被嵌套,但不能将内部作用域声明的变量与其外部作用域声明的变量重名。在这一点上,Java不同于C和C+。下面的例子企图为两个独立的变量起同样的名字。在Java中,这是不合法的。但在C/C+中,它将是合法的,而且两个变量bar将是独立的。 / This program will not compile class ScopeErr public static void main(String args) int bar = 100; / creates a new scope here.

36、int bar = 200; / Compile-time error bar already defined! ,2.4.3 类型转换,如果读者以前有一定的编程经验,那么就应该知道将一种类型的值赋给另外类型的一个变量是相当常见的。如果这两种类型是兼容的,那么Java将自动地进行转换。例如,将int类型的值赋给long类型的变量,总是可行的。然而,不是所有的类型都是兼容的,因此,不是所有的类型转换都是可以隐式实现的。例如,没有将double型转换为byte型的定义。幸好,获得不兼容的类型之间的转换仍然是可能的。要达到这个目的,必须使用一个强制类型转换,它能完成两个不兼容的类型之间的显式变换。让

37、我们看看自动类型转换和强制类型转换。,1Java的自动类型转换,如果下列两个条件都能满足,那么将一种类型的数据赋给另外一种类型变量时,将执行自动类型转换。这两个条件分别是:这两种类型是兼容的;目的数据类型的取值范围比来源数据类型的取值范围要大。 当满足以上两个条件时,自动的“加宽转换”就可以进行。例如,int型的取值范围比所有byte型的合法取值范围要大,因此不需要随后将介绍的显式强制类型转换语句。 对于加宽转换,数字类型,包括整数(integer)和浮点(floating-point)类型都是彼此兼容的,但是,数字类型和字符类型(char)或布尔类型(boolean)是不兼容的。字符类型(c

38、har)和布尔类型(boolean)也是互相不兼容的。,2不兼容类型的强制类型转换,尽管自动类型转换是很有帮助的,但并不能满足所有的编程需要。例如,当需要将int型的值赋给一个byte型的变量时该怎么办?这种转换不会自动进行,因为byte型的有效取值范围比int型的要小。此时,只有采取被称为“变窄转换”的转换方式。因为你肯定要将源数据类型的值变小才能适合目标数据类型。 在这种情况下,为了完成两种不兼容类型之间的转换,就必须进行强制类型转换。所谓的强制类型转换是一种显式的类型变换方式,其通用格式如下。 (target-type) value 其中,目标类型(target-type)指定了要将指定

39、值所转换成的类型。例如,下面的程序段将int型强制转换成byte型。如果整型变量的取值超出了byte型的取值范围,它的值将会因为对byte型的值域取模(整数除以byte得到的余数)而减少。 int a; byte b; / . b = (byte) a; 当把一个浮点值赋给整数类型时,将发生一种不同的类型转换:截断。大家都知道整数没有小数部分。这样,当把浮点值赋给整数类型时,它的小数部分将会被舍去。例如,如果将值1.23赋给一个整数,其结果只是1,0.23被舍弃。当然,如果浮点值太大而不能适合目标整数类型,那么它的值将会因为对目标类型值域取模而减少。,/ Demonstrate casts.

40、class Conversion public static void main(String args) byte b; int i = 258; double d = 338.136; System.out.println(nConversion of int to byte.); b = (byte) i; System.out.println(i and b + i + + b); System.out.println(nConversion of double to int.); i = (int) d; System.out.println(d and i + d + + i);

41、System.out.println(nConversion of double to byte.); b = (byte) d; System.out.println(d and b + d + + b); ,下面让我们分析一下每个类型转换。当值258被强制转换为byte变量时,其结果是258除以256(256是byte类型的变化范围)的余数2;当把变量d转换为int型,它的小数部分被舍弃了;当把变量d转换为byte型,它的小数部分被舍弃了,而且它的值减少为256的模,即82。,运行结果如下: Conversion of int to byte. i and b 258 2 Conversi

42、on of double to int. d and i 338.136 338 Conversion of double to byte. d and b 338.136 82,下面的这个程序说明了强制类型转换过程。,以下是不会丢失信息的类型转换方式,原始类型 目标类型 byte short, char, int, long, float, double short int, long, float, double char int, long, float, double int long, float, double long float, double float double,3表达

43、式中类型的自动提升,除了赋值方式,类型变换还可以在表达式中进行。在表达式中,对中间值的精确要求有时超过任何一个操作数的范围。例如,考察下面的表达式。 byte a = 40; byte b = 50; byte c = 100; int d = a * b / c; 中间项结果a*b很容易超过它的任何一个byte型操作数的范围。为处理这种问题,当分析表达式时,Java自动提升各个byte型或short型的操作数到int型。这意味着子表达式a*b使用整数而不是字节型来执行。这样,尽管变量a和b都被指定为byte型,50*40中间表达式的结果2000是合法的。 自动类型提升有好处,但它也会引起令人

44、疑惑的编译错误。例如,下面这个看起来正确的程序却会引起一些问题。 byte b = 50; b = b * 2; / Error! Cannot assign an int to a byte! 该程序试图将一个完全合法的byte型的值50*2再存储给一个byte型的变量。但是,当表达式求值的时候,操作数被自动地提升为int型,计算结果也被提升为int型。这样,表达式的结果现在是int型,不强制转换它就不能被赋为byte型。 在理解了上述溢出后果的情况下,就知道应该使用一个显式的强制类型转换。 byte b = 50; b = (byte)(b * 2); 这样将产生正确的结果100。,4关于

45、类型提升的若干约定,Return,除了将byte型和shorts型提升到int型以外,Java语言还规定了若干适用于表达式的类型提升规则。首先,如前面所描述的,所有的byte型和short型的值被提升到 int型。其次,如果一个操作数是long型,整个表达式将被提升到long型;如果一个操作数是float型,整个表达式将被提升到float型;如果有一个操作数是double型,计算结果就是double型。 例如,下面的程序显示了在表达式中的每个值是如何被提升的,以匹配各自双目运算符的第二个参数。 class Promote public static void main(String args)

46、 byte b = 42; char c = a; short s = 1024; int i = 50000; float f = 5.67f; double d = .1234; double result = (f * b) + (i / c) - (d * s); System.out.println(f * b) + + + (i / c) + - + (d * s); System.out.println(result = + result); 让我们进一步考察一下发生在下列程序行的类型提升。 double result = (f * b) + (i / c) - (d * s);

47、 在第一个子表达式f*b中,变量b被提升为float类型,该子表达式的结果当然是float类型。接下来,在子表达式i/c,中,变量c被提升为int类型,该子表达式的结果当然是int类型。然后,子表达式d*s中的变量s被提升为double类型,该子表达式的结果当然也是double类型。最后,考虑三个中间值,float类型,int类型,和double类型。float类型加int类型的结果是float类型。然后float类型减去提升为double类型的d*s变量,该表达式的最后结果是double类型。,2.5 数组,2.5.1 一维数组2.5.2 多维数组2.5.3 声明数组的另一种格式2.5.4

48、关于Java中的字符串,Return,数组(Array)是在基本数据类型的基础上发展而来的一种较高级的数据结构类型,它是相同类型变量的集合,可以使用共同的名字对它进行引用。本节将具体对Java中的数组问题进行介绍。,2.5.1 一维数组,尽管该例子定义了month_days是一个数组变量的事实,但实际上没有数组变量存在。事实上,month_days的值被设置为空,它代表一个数组没有值。为了使数组month_days成为实际的、物理上存在的整型数组,必须用运算符new来为其分配地址,并将它赋给month_days。运算符new是专门用来分配内存的运算符。 尽管该例子定义了month_days是一

49、个数组变量的事实,但实际上没有数组变量存在。事实上,month_days的值被设置为空,它代表一个数组没有值。为了使数组month_days成为实际的、物理上存在的整型数组,必须用运算符new来为其分配地址,并将它赋给month_days。运算符new是专门用来分配内存的运算符。,Return,数组可被定义为任何有效数据类型,可以是一维的,也可以是多维的。对数组元素的访问通过其下标进行。数组提供了一种将有联系的信息进行分组的有效方法。 一维数组实质上是相同类型的变量列表。要创建一个数组,首先必须指定数组变量所需的类型。一维数组的通用声明格式如下。 type var-name; 其中,type指

50、定了数组的基本类型。基本类型决定了组成数组的每一个基本元素的数据类型。这样,数组的基本类型决定了数组存储的数据类型。 例如,下面的例子定义了数据类型为int,名为month_days的数组。 int month_days;,显然,获得一个数组需要两步:第一步,首先必须定义变量所需的类型;第二步,必须使用运算符new来为数组所要存储的数据分配内存,并将它们分配给数组变量。 注意:所有的数组下标从零开始。,2.5.2 多维数组,在Java中,多维数组实际上就是“数组的数组”。在定义多维数组变量时,要将每个维数放在它们各自的方括号中。 例如,下面的语句声明了一个名为twoD的二维数组变量。 int

51、twoD = new int45; 该语句分配了一个4行5列的数组并把它分配给数组twoD。实际上这个矩阵表示了int类型数组的实现过程。,下列程序从左到右,从上到下为数组的每个元素赋值,然后显示数组的值。,/ Demonstrate a two-dimensional array. class TwoDArray public static void main(String args) int twoD= new int45; int i, j, k = 0; for(i=0; i4; i+) for(j=0; j5; j+) twoDij = k; k+; for(i=0; i4; i+)

52、 for(j=0; j5; j+) System.out.print(twoDij + ); System.out.println(); ,程序运行的结果如下: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19,当给多维数组分配内存时,只需指定第一个(即最左边)维数的内存即可。你可以单独地对余下的维数进行内存分配。例如,下面的程序在数组twoD被定义时给它的第一个维数分配内存,对第二维则是手工分配内存。int twoD = new int4;twoD0 = new int5;twoD1 = new int5;twoD2 = new int5;t

53、woD3 = new int5;,对于大多数应用程序来说,我们不推荐使用不规则的多维数组,因为如果把握不好运行过程中可能出错。但是,不规则多维数组在某些情况下的使用效率较高。例如,如果你需要一个很大的二维数组,而其元素仅仅被稀疏地占用(即其中一维的元素不是全被使用),这时使用不规则数组可能是较好的解决方案。 对多维数组进行初始化也是可能的。初始化多维数组只不过是把每一维的初始化列表用它自己的大括号括起来即可。,下面的程序可产生一个矩阵,该矩阵的每个元素取值为数组下标行和列之积。,/ Initialize a two-dimensional array. class Matrix public

54、static void main(String args) double m = 0*0, 1*0, 2*0, 3*0 , 0*1, 1*1, 2*1, 3*1 , 0*2, 1*2, 2*2, 3*2 , 0*3, 1*3, 2*3, 3*3 ; int i, j; for(i=0; i4; i+) for(j=0; j4; j+) System.out.print(mij + ); System.out.println(); ,Return,程序运行的结果如下: 0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 0.0 2.0 4.0 6.0 0.0 3.0 6.0 9.0,

55、2.5.3 声明数组的另一种格式,Return,在Java中,声明数组还有如下的第二种格式。 type var-name; 这里,方括号紧跟在类型标识符type的后面,而不是跟在数组变量名的后面。例如,下面的两条声明语句是等价的: int al = new int3; int a2 = new int3; 以下的两个定义也是等价的。 char twod1 = new char34; char twod2 = new char34; 在Java中同时保留这两种数组声明格式主要是为了增强灵活性。,2.5.4 关于Java中的字符串,在前面关于基本数据类型以及数组的讨论中,并没有提到字符串或字符串数

56、据类型。这不是因为Java不支持这种类型,而是因为在Java中,字符串类型应该叫做字符串对象(String),从其首字母的大小写即可看出。它不是一种简单的类型,也不是简单的字符数组(在C/C+中是)。字符串(String)在Java中被定义为一种内置对象。要完全了解它需要理解几个与对象相关的特征,因此有关字符串(String)的详细讨论放到后面的内容中进行讲解。 这里,我们只简单地介绍一下字符串的使用。字符串(String)类型通常被用来声明字符串变量。当然,你也可以定义字符串数组。一个被引号引起来的字符串字面量可以被分配给字符串变量。一个字符串类型的变量可被分配给另一个字符串类型的变量。在进

57、行输出时,也可以使用方法println()进行,就像输出其他类型变量的值一样。 String str = This is a test; System.out.println(str); 这里,str是字符串(String)类型的一个对象,它被分配给字符串“This is a test”,该字符串通过println()语句输出。 另外说明一下指针问题。如果读者是经验丰富的C/C+程序员,那么对这些语言中提供的指针肯定比较熟悉。然而,Java语言不支持(或者说不允许指针)使用指针。之所以不允许指针存在,主要是因为这样做将可能使Java Applet(小应用程序)突破Java运行环境和主机之间的防火墙限制,带来一系列的安全问题。虽然使用指针有很多好处,但只要在Java的执行环境范围内,就不需要也不可能使用指针进行程序处理。,Return,2.6 运算符,2.6.1 算术运算符2.6.2 关系运算符2.6.3 位运算符2.6.4 逻辑运算符2.6.5 其他运算符2.6.6 运算符的优先级,Return,在Java语言中,运算符可以划分为四大类:算术运算

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论