第二章开始学Java语法_第1页
第二章开始学Java语法_第2页
第二章开始学Java语法_第3页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

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

文档简介

1、第二章 开始学 Java 语法任何一种程序语言,都有一些最基础的东西,这就是这门语言要处理什么样的数据,以及如何按着 相应的规则组织和处理这些数据。千里之行,始于足下,本章将通过实例,用通俗的语言来讲述蕴涵在 Java 里的面向对象思想,通过 学习我们可以发现: 面向对象思想不是枯燥晦涩的教条, 而是可以帮助我们更有效开发代码的指导工具。音乐家可以通过驾驭复杂的和声等技巧来创作优美动听的旋律,作家也从没有把把复杂浩瀚的语法 条目当成他们创作的障碍,同样地, Java 的语法细节也仅仅是开发项目的工具,希望大家在掌握初步的 语法后,立即从面向对象思想和项目开发的需求的角度来观察语法定义的动机,学

2、以致用,而不应该过 多地“从故纸堆中找学问”,刨根问底地研究“这个类有多少方法”等类的细节性的问题。2.1 基本数据类型与操作符基本数据类型的数据是构建 Java 程序大厦的砖瓦,我们在欣赏蕴涵 Java 大型项目里优秀架构和精 密的内部实现细节时,不应该忽略 Java 语言里的基本类型数据。2.1.1 基本数据类型Java的基本数据类型分为 4 大类:整数、浮点数、字符型、布尔型。其中,整数包括 byte、int、short、long,浮点数包括 float 、 double 。由于用不同位数( bit )来存放, 它们所表示的精度和范围也有所不同,同时也有各自相应的默认值。如表 2-1 所

3、示。表 2-1 Java 的基本数据类型关键字位数范围默认值byte8-2727-10short16-215215-10int32-231231-10long64-263263-10float323.4e-0383.4e+0380.0fdouble641.7e-3081.7e+3080.0dchar8u0000uffffu0000boolean8true 或 falsefalse整数型: byte、int 、 short 、 long 。通常情况下整数型数据都是用十进制来表示,同样他们也可以表 示成十六进制或八进制。十六进制以 0x 开头,如 0x1F 的十进制数值为 31。八进制以 0 开头

4、,如 017 的 十进制数值为 15。请大家注意, 整数型变量在进行赋值时, 要注意有可能会发生因为精度不够而造成数据溢出的错误, 例如:byte b;/ byte 类型的数据最大为 127, 10000 由于数据溢出而不通过编译b = 10000;在 Java 语言里, 浮点数型有 float 、double 。浮点型数据用于表示小数。 浮点型常量有两种表示方式: 一般表示法和科学计数法。 如一般表示法 345.64 的科学计数法为 3.4564E2 。默认情况下, 浮点数常量为 double ,我们也可以在相应的数字后面添加相应的字母,f 或 F 表示 float 类型浮点数, d 或 D

5、 表示 double类型浮点数,如 123.4f 和 123.4d 前者用 32 位空间存储后者用 64 位存储。这里需要强调的一点是,在我们使用整数型数据和浮点型数据的过程中并不是用越大的数据类型存 放数据就越好,因为这样不仅有可能会造成一定的空间浪费而且还会提高相应得计算时间,因此我们应 在确保不发生数据溢出的前提下选择合适类型来存放相应的数据。在 Java 语言里,字符型用 char 表示。它用来表示单个字符,它有两种赋值方式:单引号(而不是 双引号)括起来的单个字符,用整数表示的 unicode 编码值。例如:char c1 = ' a'/ 表示 97 所对应的 uni

6、code 编码 achar c2 = 97;Java 语言里,布尔型是 boolean 。用来表示真和假,它只有两个值 true 和 false。2.1.2 基本操作符操作符就是用来计算数据的符号,我们可以把数据通过操作符组合起来得到相应的结果。按着操作 符所操作数据的个数可以分为:一元、二元、三元,这一点比较好理解。按着操作符的功能可以分为: 算术、赋值、关系、逻辑、位运算等操作符。接下来我们详细为大家介绍各种操作符的功能:算术操作符是用来描述整数和浮点数类型数据的运算规则的一组操作符。单目运算操作符包括“ -”,“+ ”,“-”,它们都只能对一个操作数进行计算。“-”为求反符号,它表示计算

7、操作数的相反数。“ + ”,“ -”分别是自增和自减符号,它们会计算操作数的加一或减一 的值,在使用这两个符号的时候需要大家注意操作符和操作数的位置对表达式结果的影响,例如:int i = 5;int j = 5;int k;/ i 的值为 6,表达式 i+ 的值为 6, k 的值为 18k=i+*3;/ i 的值为 6,但表达式 +i 的值为 5, k 的值为 15k=+j*3;注意: i+指表达式运算完后再给 i加一,而 +j 指先给 j加一然后再运算表达式的值。 双目运算操作符包括“ +”,“ -”,“ * ”,“ /”,“ %”,它们可以对两个操作符进行计算,分 别对应于加,减,乘,除

8、,求余运算。需要注意的是前四种符号可以在整数和浮点数之间进行计算,而 求余运算只能在整数之间运算。赋值操作符包括“ =”和一些扩展的赋值操作符,如:“+=”,“ -=”,“ *= ”,“ /=”,“ %=”。其中, ”=”表示把等号右边表达式的值赋给等号的左边,而一些扩展的赋值操作符是一种简写形式, 它们 表示把左操作数按着相应的运算符号的规则与右操作计算所得到的结果又符给了左操作数的那个变量, 例如:int i = 5;/ 等同于 a=a+6,故最终 a 的值为 11a += 6;关系操作符用于比较两个表达式的大小关系,计算的结果为布尔类型数据的true 和 false 。如果表达式关系成立

9、则结果为 true,否则为 false。关系操作符包括“ = =”,“ != ”,“ >”,“ <”,“ >=”, “ <=”,分别表示等于,不等于,大于,小于,大于等于,小于等于。需要注意的是:关系操作符中的 “= =”表示的比较操作符两边的操作数是否相等,而赋值操作符“=”表示把左操作数的值赋到右操作数中去。这里, 值得注意的是用来判断两个操作对象是否相等的”= ”操作符, 它主要用在 if,while 和 for 循环里的条件判断里。比如,有如下语句:int i = 10; int j = 10;if(i = j)/do action1 由于 i 和 j 相等,所

10、以在 if 语句里,会执行 do action1 部分的代码。逻辑操作符用于对布尔类型数据的计算,得到的结果也是布尔类型的数据,包括“&”,“ && ”,“|”,“ |”,“ ”,“ ! ”,分别表示逻辑与,逻辑与,逻辑或,逻辑或,逻辑异或,逻辑非。除了“!”是一元操作符以外其余的都为二元操作符。逻辑与表示只有当左右操作数都为 true 时表达式结果才为 true ,否则为 false;逻辑或表示左右操作数中只要有一个为true 时表达式结果就为 true,否则只有两个操作数都为为 false 时表达式结果才为 false;逻辑异或表示当左右操作数不同即相异时表达式结果

11、为 true , 否则如果左右操作数相同时表达式结果为false;逻辑非表示求操作数相反的值,即true 为 false, false为 true 。“&”与 “&& ”和 “|”和 “|”虽然名称相同,但是使用时却有差别,例如:int i = 1;int j = 2;boolean b1;boolean b2;/ i>5 为 false, j>5 为 false ,表达式的值为 falseb1 = ( i > 5 ) & ( j > 5);/ 只要知道 i>5 为 false 就可以确定表达式的值为 falseb2 = ( i &

12、gt; 5 ) && ( j > 5);“&”与“ |”要根据左右操作数的最终结果计算表达式的值,而“&& ”与“ |”如果可以根据左操作数的值能确定表达式结果就不会继续计算右操作数的值。位运算操作符是以二进制的方式操作数据,并且操作数和结果都是整数类型的数据,包括“”,“ & ”,“ |”,“ ”,“ >>”,“ <<”,“ >>>”,分别表示位反,位与,位或,位异或,带符号位右 移,左移,无符号位右移。位反,位与,位或,位异或表示把左右操作数按着其二进制的表达形式对每 个位的 1或 0进行相应的

13、逻辑操作, 再把新得到二进制数据转化成十进制数从而得到表达式的最终结果。 后三种操作符表示把左操作数转化成二进制数据,然后按着右操作数的大小进行相应方向的移动,再把 新得到二进制数据转化成十进制数从而得到表达式的最终结果,但需要注意的是同样是向右移动“ >> ” 表示带着符号位即最高位的 1或 0 向右移动,而“ >>>”表示无论符号位是 1 还是 0,都用 0对最高位补 位,如表 2-2 所示。表 2-2 位移运算i二进制补码i<<2i>>2i>>>27001000110000110000001000100010001-

14、1711101111101111001111101100111011其它的重要操作符有:1. 条件操作符“ (?:)”,它是唯一的一个三元操作符。使用方式如:i ? j : k ,其中 i 表达式的结果为布尔类型,如果 i 为 true 表达式结果为 j ,否则为 k。2. 括号操作符“ ( )”,用于优先表达式的计算顺序。2.1.3 操作符优先级操作符的优先级决定了处理表达式计算的先后顺序,还有一个重要的特性就是结合性,它们共同决定了表达式按着何种方式来进行各种计算最终得到相应的结果,对于初学者来说建议使用括号来明确指 定运算顺序。各种操作符的优先级和结合性如表2-3 所示。表 2-3 操作

15、符的优先级和结合性操作符优先级结合性 ,()12右,!,+ ,-3右*,/,%4左+,-5左>>,<< ,>>>6左,=,=7左= = , !=8左&9左10左|11左&&12左|13左?:14右=15右大家不必硬记这些优先级,可以通过针对容易混淆的地方加括号就可以了,比如有如下的表达式: !i=j ,首先是判断两个值是否一样,然后是个取非的操作,我们可以改写成: !(i=j) ,虽然 !的优先 级比 = 要低,加不加括号的效果是一样的,但是如果我们加了括号,看起来就更清除了。2.1.4 对象型的数据类型在 Java 语言里,以

16、类的形式,定义了一些对象类型的数据类型,并且在其中封装了针对这种类型数 据的一些操作方法,其中,我们经常会用到的有:基本数据类型的封装类和描述字符串的 String 类。下 表 2-4 描述了基本数据类型对应的封装类。表 2-4 基本数据类型对应的封装类基本数据类型对应的封装类booleanBooleancharCharacterbyteByteshortShortintIntegerlongLongdoubleDoublefloatFloat各数据类型对应的封装类里,不仅包括了基本数据类型的数据,由于它们更是类,所以会封装了一 些实用的方法,比如我们在如下的代码里,通过 Integer 类封

17、装的 doubleValue 方法,把 Integer 类型的数 据转换成 double 。Integer k = new Integer(10);k.doubleValue(); 封装类等于基本数据类型加针对基本数据类型的操作,它们是对象,这点对我们来说至关重要。 在 Java 语言里,描述字符串的 String 类有着很重要的用途,在这个类里,同样是定义了针对字符串 的一些操作,通过下面的 StringTest.java 代码,我们可以看到 String 类的一些常用方法。public class StringTestpublic static void main(String args)

18、String s1 = "Hello World"String s2 = new String("Hello World"); /输出字符串的长度 System.out.println("the length of s1 is " + s1.length(); /得到第三个字符,索引位置从 0 开始char index2 = s1.charAt(2);System.out.println(index2); /比较两个字符串 错误的做法 if(s1 = s2) System.out.println("The two Strin

19、g are equal!"); else System.out.println("The two String are not equal!"); /比较两个字符串 正确的的做法 if(s1.equals(s2) System.out.println("The two String are equal!"); else System.out.println("The two String are not equal!"); /连接字符串 s1 = s1.concat("!"); System.out.pr

20、intln("After concat the s1 is " + s1); /查找字符串的位置System.out.println(s1.indexOf("!"); System.out.println(s1.indexOf("#"); 在上述的方法里,我们针对字符串做了如下的操作:1. 首先定义了两个字符串,我们可以通过直接赋值,也可以通过以 new 的方式调用 String 的构造 函数来创建 String 类型的对象。2. 通过 length 方法可得到字符串的长度,执行到这里,会输出如下结果。the length of s1

21、 is 113. 通过 charAt 方法可得到字符串里指定索引位置的 char 类型变量,因为索引位置从 0 开始计算, 所以执行到这里,会输出 s1 对象的第三个索引位置的“ l”。4. 下面,我们将要比较 s1和 s2两个字符窜是否相等,首先用的是 =的方式,这里我们可以发现, 虽然两个字符串的内容完全相等,但是,从随后输出的内容上来看, s1=s2 的结果是 false 。这是个初学者经常会犯的错误!因为s1和 s2 都是对象,所以 =操作符是用来判断这两个对象的引用地址(即这两个对象在内存里的存储首地址)是否相等,而不是判断它们的内容是否相等。所以,我 们要用 equals 方法来判

22、断两个 String 类型的对象里的值之否相等。5. 可以通过 concat 方法,连接两个字符串,代码里我们是把! 加到了 Hello World 的后面,我们可以通过输出看到 ”Hello World! ”的效果。6. 可以通过 indexOf 方法,来查找指定字符的位置,如果找到,这个方法将返回这个字符的索引位置(索引位置同样是从 0 开始),如果没有找到,则返回 -1。2.1.5 方法(函数)的参数和返回值方法(也叫函数)是 Java 语法的重要组成部分,它的语法比较简单,但用途比较广泛,通过下面的 FunctionTest.java 代码,我们一起来学习一下方法的用途。public

23、class FuncionTest/方法定义public static int add(int i,int j)return i+j;public static void main(String args)/方法调用int result = add(2,2);System.out.println(result); 首先我们定义了一个 add 的方法,定义方法的基本语法是: 修饰符 返回类型 方法名 (参数列表 )这里的修饰符是 public 和 static 表示公有的静态方法,它的具体含义会在下文里描述,这里的返回 类型是 int ,表示 add方法将要返回一个 int 类型的结果,返回类型

24、可以是基本数据类型,也可以是类, 如果这个方法没有返回,则可以用 void 在表示。这里的方法名是 add,参数是两个 int 类型的值。而在 add 的方法主体里,是针对了两个输入参数,做了个加的操作,并且通过return 语句将结果返回。这里请大家注意,返回结果的类型必须要和方法定义时声明的返回类型相一致。而在 main 函数里调用 add 方法时,我们的做法是: int result = add(2,2); ,针对 add 方法的参数列表, 我们传入了两个 int 类型的参数,并且用了同样是 int 类型的 result 变量来接收 add 方法的返回值。如果我们在 main 函数里有多

25、个 add 操作, 那么可以把这些加法操作定义到方法体里,而不是直接在main 函数里执行操作,这样可以减少代码的冗余程度。2.2 程序流程控制 流程控制的语句起着控制代码执行顺序的作用,它由顺序、选择、循环这 3 种最基本的结构组成。 通过这种方式得到的代码,结构清楚,层次分明,易于阅读与维护。在这里需要强调的一点是,虽然 Java 是一种面向对象的语言, 我们可以把它的结构模块化, 但是模块内部最基础的结构仍是这种面向 过程的方式,只不过在整体的设计上我们运用了面向对象的理念。2.2.1 顺序与分支顺序结构是最基本最简单的结构,它按着从上到下的流程顺序的组织代码,在编程的时候我们一般 会基

26、于这种顺序结构与分支和循环进行一定的嵌套,从而使代码进行有效地运作。 分支结构由 if 和 switch 两个关键字引出。前者用于二选一后者用于多种分支情况的选择。 if else 结构: if( 条件语句 )分支语句 1;else分支语句 2;如果条件语句值为 true 时,执行分支语句 1,否则执行分支语句 2。如果需要满足条件时同时执行 多条语句,只需把这些语句用“ ”括起即可。if 结构: if( 条件语句 )语句 ;如果条件语句值为 true 时,执行语句,否则忽略该语句。同样,如果需要满足条件时同时执行多条 语句,只需把这些语句用“ ”括起即可。else if 结构:if( 条件语

27、句 1)分支语句 1;else if( 条件语句 2)分支语句 2;else if( 条件语句 n)分支语句 n;else分支语句 n+1;如果条件语句 1 为 true 时,执行分支语句 1,否则如果条件语句 2 为 true 时,执行分支语句 2, 否则如果条件语句 n 为 true 时,执行分支语句 n,否则执行分支语句 n+1。通过这种 if else 语句嵌套的 方式达到了多分支语句只执行其中一个分支语句的效果,由于if else 在本章里使用最为广泛,所以在这 里不再单独举例。switch 结构,它的语法是:switch( 条件语句 )case 值 1 : 语句 1;case 值

28、2 : 语句 2;case 值 n : 语句 n; default : 语句 default;先计算条件语句的值,该值必须为整数型或者字符型,如果值为1,执行语句 1,如果值为 2,执行语句 2 ,如果值为 n,执行语句 n,如果所有的值都不匹配就执行语句default ,default 段也可以省略掉。需要注意的是条件语句的值在与某一个值匹配执行了相应的语句之后,如果没有 break 语句打断, 则程序会继续执行下去直到遇到了一个 break 语句或者 switch 结束。例如:char flag = b'int i=1;switch(flag)case a' : i = 1

29、;case b' : i = 2;break;case c ' : i = 3;default : i = 4;上述代码的业务逻辑是,如果flag 的值为 a,'则先执行 i = 1,然后是 i = 2 ,此时遇到了 break 才会跳出 switch 语句。如果 flag 的值为 b',则执行 i = 2 ,此时遇到了 break 跳出 switch 。如果 flag 的值为 c',则执行 i = 3 , 然后执行 i = 4 ,最后跳出 switch 。如果 flag 不是其中的任何一个则执行i = 4 ,然后跳出。2.2.2 循环流程循环流程实现了

30、一种反复执行某段程序的流程结构。它是由循环语句和跳转语句共同实现的。循环 语句包括 for 、 while 、 do-while 语句,跳转语句包括 break 、 continue 语句。for 语句:for( 初始化语句 ;条件语句 ;递归语句 )循环体 ; 程序先执行初始化语句,它的作用是初始化循环变量,如果有多个语句就逗号隔开,然后判断条件 语句的值,如果为 true 执行循环体和递归语句,再判断此刻的条件语句的值,重复以上步骤,直到某次 递归之后,条件语句的值为 false ,跳出当前 for 语句。例如:while 语句:while( 条件语句 )循环体 ;判断条件语句的值如果为

31、true,执行循环体,再判断此刻的条件语句的值,重复以上步骤,直到条 件语句的值为 false,跳出当前 while 语句。do-while 语句:do循环体 ;while( 条件语句 )先执行循环体,然后判断条件语句的值如果为 true 继续执行循环体,再判断条件语句的值,重复以 上步骤,直到条件语句的值为 false ,跳出当前 do-while 语句。break 语句:可以用于 switch 语句和以上 3 种循环语句,目的是跳出整个循环语句。continue 语句:用于以上 3 种循环语句,目的是跳出当前的一次迭代,而不是跳出整个循环语句,这是它与 break 最大的区别。2.2.3

32、有争议的 goto 语句做过 BASIC 或 C 语言编程的人都知道 goto 语句是一个臭名昭著语句,它可以让代码跳转到任何的 位置,它增加了代码的复杂度,严重影响了程序的可读性,因此使用的时候应该谨慎。在 Java 里面 goto 作为一个保留字存在,但没有拿来做任何用途但是 Java 里面的 break、 continue 结合循环语句中的 label 实现了部分的 goto 跳转功能。在多层循环的嵌套中怎样从内层循环直接跳出外层循环的迭代哪,让我们看一下下面的代码Lable.java 。 public class Label public static void main(String

33、 args) int i = 0;outer: while (true)System.out.println("in while loop");while (true)i+;System.out.println("i = " + i);if (i = 2)System.out.println("continue outer"); continue outer;if (i = 4)System.out.println("break outer");break outer;在 Eclipse 中运行该程序得到如下输出:

34、in while loopi = 1i = 2continue outerin while loopi = 3i = 4break outer该程序先初始化变量 i 值为 0,然后进入了最外层循环,并且在该循环的前面加入了一个名字叫做 outer 的标签,然后打印“ in while loop ”,进入内循环, i值加一变为 1,然后内部循化迭代 i 值加一变 为 2 ,此时满足 if 条件语句打印“ continue outer ”并执行 continue outer 语句,从内层的一次迭代跳到了 外层循环的迭代,注意这种方式只有通过标签才能实现,然后继续进入内层循化,当 i 值变为 4 时

35、打印 “ break outer ”并执行 break outer 语句,曾内层的一次迭代跳出了整个外层循环,程序执行结束,这种 直接跳出的方式也只有标签可以实现。2.2.4 使用 If 语句判定是否是闰年计算机之所以如此流行,最主要的原因就是它给人们的日常生活带来的极大的方便。下面给大家展 现一个比较有趣的例子 : 如何用 if 语句判断某一年是否是闰年,请看代码 LeapYear.java 。public class LeapYearpublic static void main(String args)int year = 2008;if (year % 4 = 0 &&

36、 year % 100 != 0) | (year % 400 = 0) System.out.println(year + " is a leap year.");elseSystem.out.println(year + " is not a leap year.");在 Eclipse 中运行该程序得到如下输出:2008 is a leap year.这段代码的业务逻辑是:如果输入年份能够被 4 整除并且不被 100 整除或者能被 400 整除,该年份 就是闰年,否则不是。在 LeapYear.java 代码中我们通过 if 语句和算术运算、逻辑运

37、算结合在一起非常方便的实现了该功2.2.5 使用循环语句计算阶乘计算机语言在数学领域也发挥着举足轻重的作用,比如说如何快速的计算整数n 的阶乘,请看代码Factorial.java 。public class Factorialpublic static void main(String args)int f = 1;for (int n = 10; n > 1; n-)f = f * n;System.out.println("The result is " + f);在 Eclipse 中运行该程序得到如下输出:The result is 3628800 程序里,

38、我们可以通过 for 语句实现计算了 n 的阶乘,从 n 开始循环每次都与当前的 n 相乘把值存 放到变量 f 中,直到 n 的值减到 1 为止,这样就达到了计算整数 n 的阶乘的目的。2.2.6 使用 Switch 语句控制输出switch 语句,比如根据成绩的等级判断具体的分数段,如果我们有多分支选择的需求就可以考虑使用请看代码 GradeLevel.javapublic class GradeLevelpublic static void main(String args)char grade = 'C'switch (grade)case 'A':Sys

39、tem.out.println(grade + " is 85 100"); break; case 'B': System.out.println(grade + " is 70 84"); break; case 'C': System.out.println(grade + " is 60 69"); break; case 'D': System.out.println(grade + " is < 60"); break; default: Syste

40、m.out.println("inputerror");在 Eclipse 中运行该程序得到如下输出:C is 60 69 考试成绩一共有四个等级,根据这些等级我们能反推出所处的分数段,程序里面也作了很好的容错 机制,如果你输入了一个不正确的等级那么将得到输入错误的提示。这里需要大家注意的是每个 case语句后面都加上了一个 break 语句,大家可以把它去掉看看会有什 么样的输出。2.3 类与封装在面向对象的思想中,任何实体都可以看成对象,而我们会把这些对象分门别类抽象出它们共同的 特征,并且把这些特征归纳起来形成一个概念的定义,我们就称之为类。“封装”是面向对象思想的第

41、一大要素,如果没有能体现“封装性”的类,那么面向对象的另外大要素,“实现类的继承”以及“类的多态”将成为无源之水,无本之木。2.3.1 类的构成要素类反映了现实生活中真正存在的一些对象的特征,这些对象都有相同的属性定义和行为定义,只不 过具体的值会有所区别, 这也符合我们认知世界的规律, 因为大自然中的万物也是既有共性又有特性的。在面向对象的 Java 语言里面,我们通过关键字 class 定义一个类,在类里面存在若干个属性和方法 对应现实世界中的属性和行为。比如,汽车有位置和速度的属性,有运动和停止的行为。那我们就可以 定义 Car 类,代码请见如下的 Car.java 程序。public

42、class Car/ 位置int position;/ 速度int speed;/方法/ 运动void move() System.out.println("is moving");/停止void stop() System.out.println("is Stopped");2.3.2 类的构造函数与构造次序我们在上面只是定义了一个汽车的类,现实生活中可能有很多这样的车只不过它们的位置的速度不 同,我们可以根据这个汽车类的定义实例化出具体的正在某个位置以一定的速度运行的汽车,此时我们 就可以用 new 关键字来实例化出这个对象,并且为这个对象赋予相应的

43、属性值,这样我们才创造了一个 与现实世界中对应起来的一辆汽车。 我们在原来的 Car 类基础上加上 main 函数用以测试, 以下修改后的 的代码 Car1.java 。public class Car1/ 位置int position;/ 速度int speed;/ 运动void move() System.out.println("is moving");/停止void stop() System.out.println("is Stopped");public static void main(String args)Car1 c = new Ca

44、r1();c.position = 10;c.speed = 80;c.move();在 Eclipse 中运行该程序得到如下输出:is moving我们在 main 函数中,通过 new 语句得到了一个 Car1 的对象,该对象的引用被存放在变量 c 中,之 后我们通过变量 c 为得到的这个对象属性赋值并调用其相应的函数。注意在 Java语言里变量 c 存放的是当前对象的引用, 通过这个引用我们可以找到内存中真正存放这 个对象的那段空间,从而修改相应的属性或者调用相应的方法。这也是Java 与其他语言的区别,在 Java里面舍弃了繁琐的地址操作,简化了编程过程。在上面的例子中,我们把对象属性

45、的初始化放到了外面,其实我们完全可以在 new 语句的过程中就 执行该初始化动作,请看修改后的代码 Car2.java 。public class Car2/ 位置int position;/ 速度int speed;Car2()position = 10;speed = 80;/ 运动void move() System.out.println("is moving");/停止void stop() System.out.println("is Stopped");public static void main(String args)Car2 c =

46、 new Car2();c.move(); 在这段代码里面我们把初始化的动作放到了默认构造函数中处理。我们是否有这样的疑问那,为什么叫默认构造函数?首先 Java 里面规定这种与类的名字相同并且没有返回值得函数就叫做构造函数, 如 果构造函数又没有什么输入参数,我们就称其为默认构造函数。对于一个类来说,默认构造函数可以不 用显性定义,系统会为其指定一个只有空方法体的构造函数,就像Car1.java 中, new 语句会调用系统的默认构造函数。同样的我们也可以定义带参构造函数,请看修改后的代码Car3.java 。public class Car3/ 位置int position;/ 速度int

47、 speed;Car3(int position,int speed )this.position = position; this.speed = speed;/ 运动void move() System.out.println("is moving");/停止void stop() System.out.println("is Stopped");public static void main(String args)Car3 c = new Car3(10,80);c.move();此时我们 new 语句调用了带参的构造函数。需要强调的一点是,如果

48、指定了带参的构造函数之后就 不会再存在一个空方法体的默认构造函数, 也就是说像 Car3 这个类就不能通过 new Car3() 的方式实例化 对象。接下来我们讨论一下构造次序,其实在属性声明的位置我们可以加入赋值语句,如代码Car4.java 。public class Car4/ 位置int position = 1;/ 速度int speed = 1;/构造函数Car4(int position,int speed )this.position = position;this.speed = speed;/ 运动void move() System.out.println("i

49、s moving");/停止void stop() System.out.println("is Stopped");public static void main(String args)Car4 c = new Car4(10,80);c.move();我们在调用 new 语句时,系统先为该对象分配内存空间,此时属性 position 和 speed 取整数型的默 认值 0,接着又均被赋值为 1,然后进入构造函数的赋值语句分别被赋值为10和 80。理解对象的构造次序对我们掌握其内部实现机制起着非常重要的作用,往往我们在解决一些底层问 题的时候需要的就是这种技巧

50、。2.3.3 用 package 封装工具类和用 import 引入需要的类在大型的 Java 项目开发中我们会根据现实世界的对象并结合实际需求抽象出程序中所需的类, 这些 类的数量非常的庞大,因此如何来有效的管理好这些类就显得尤为重要了。Java 里面提供了 package 关键字帮助我们对类进行分类存放。比如我们有锤子、斧子两个工具,为了管理方便我们不妨给他们存放 在一个叫做工具的目录下面。因此在我们的 tools 的目录下面就存放了 Sinker.java 和 Axe.java 这两个类。package tools;public class Sinker 和package tools;p

51、ublic class Axe 注意,这两个类一定要存放在 tools 目录下面,并且,在类的定义里面关键字 package 一定要出现在 除了注释语句的第一行位置,否则在编译的时候系统会提示异常。并且,在使用package 里,可以用“ .”来表示目录的嵌套,即如果一个类存放在 a 目录下的 b 目录下的 c 目录那么在类的第一行一定要写成 “ package a.b.c;”。如果我们想要使用某个包中的类应该如何来操作哪?Java 里面的关键字 import 提供了这个功能。比如我们有个木匠类 Carpenter.java 想使用这两个工具类就可以这么来定义。import tools.*;p

52、ublic class Carpenterpublic static void main(String args)Axe a = new Axe();Sinker s = new Sinker();注意这里的“ * ”表示引用 tools 目录下的所有的类(因为两个类都用到了为了简单起见我们就使用 了简写形式), import 语句也可以存在多个,上面的例子中我们可以把 import 语句改写成:import tools.Axe;import tools.Sinker;表示引用了 tools 目录下的 Axe 和 Sinker 两个定义好的类。2.3.4 修饰符与类内部对象的可见性以上文的汽车

53、类为例,在使用汽车时,我们不必关心诸如汽车内部“发动机如何点火”和“冲程气 缸如何工作等细节”,同样地,汽车制造厂商也不可能将这些细节暴露给使用者。封装性是类的重要特性,在上例中,汽车类通过公有( public )的方法,向用户提供了运动( move ) 和停止( stop)的功能。另外,汽车类里的一些属性和方法,比如“发动机的状态”的属性和“发动机的点火”的方法,是 供本类使用的,不能提供给用户,这些属性和方法的类型是私有的( private ),类的外部看不到这样的 属性和方法。除了这两种类型的修饰符外,属性和对象还有第三种“受保护”(protected )类型的修饰符。凡是 被定义成“受

54、保护”的属性和方法,只能在本类和子类里使用,在类的外部是无法使用的。比如在汽车 类里可以设计一个 protected 类型的“统计保持在最大时速时间”方法,这个方法可以提供给汽车本身和 它的子类“赛车类”使用,而不必提供给汽车的使用者。类的封装性可以通过上述三种修饰符很好地体现,我们可以把实现类功能的方法及其属性定义成public ,必须把一些描述实现细节的属性和方法设置成 private ,可以把想提供给子类的方法和属性定义 成 protected 。下面的 WholeCar.java 程序详细讲述了各修饰符的用法。class Car/表示汽车内部状态的变量private int inner

55、Status;/最大时速下的行程数protected int maxspeedLength;private boolean checkStatus()/检测汽车内部状态,并设置 innerStatus 的值/.if(innerStatus>0)return true;elsereturn false;public void start()if(checkStatus() = true)System.out.println("Car Start!");elseSystem.out.println("Could not start!");/返回最大时速

56、时的行程数protected int getMaxSpeedLength()/省略一些业务细节/.return maxspeedLength;public class WholeCarpublic static void main(String args)Car car = new Car();/不正确的一些用法/1 企图访问私有的属性和放法/car.checkStatus();/System.out.println(car.innerStatus);/2 企图访问收保护的方法,建议别使用/car.getMaxSpeedLength();/只能访问 car 里的公有方法car.start() ;在这段代码里,我们首先定义了 Car 这个类,在其中,用于表示汽车内部状态的 innerStatus 变量是 private 的,表示最大时速下的行程数的 maxspeedLength 变量是 protected 的,这两个变量只在 Car 类里 被用到,在外部是不能使用的。另外, Car 里提供了一个 public 类型的 start 方法,用户可以通过这个方法开动汽车。在 s

温馨提示

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

评论

0/150

提交评论