版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java程序设计实用教程第1章Java概述 1.2JDK 第2章Java语言基础 2.1语言成分 22.2流程控制语句 2.3数组 2.4静态方法 2.5字符串 2.6☆☆算法分析与设计基础 第3章类的封装、继承和多态 3.1类和对象 3.2类的封装性 3.3类的继承性 203.4类的多态性 223.5类的抽象性 27 304.1接口与实现接口的类 304.3JavaAPI基础 324.4泛型 33第5章异常处理 385.1异常处理基础 385.2异常处理措施 38第6章图形用户界面设计 396.1AWT组件及其属性类 396.2事件处理 396.3Swing组件及事件 40第7章多线程设计 42 第8章流和文件操作 438.2字节流 438.3字符流 471.1了解Java习1-1Java具有哪些适合在Internet环境中运行的特点?【答】跨平台特性,完全面向对象和简单性,可靠性,安全性,多线程,支持分布式网络应用等。习1-2什么是跨平台特性?Java如何实现跨平台特性?【答】跨平台特性是指一个应用程序能够运行于不同的操作系统平台。Java采用虚拟机技术支持跨平台特性,每个操作系统运行各自版本的Java虚拟机。习1-4Java源程序文件编译后生成什么文件?程序的运行机制是什么样的?【答】Java将源程序文件(*.java)中的每个类经编译生成一个字节码文件(.class由Java虚拟机解释执行字节码文件。1.2JDK习1-6环境变量path和classpath的作用分别是什么?【答】path提供可执行文件(.exe)的路径;classpath提供类文件(.class)的路径。习1-8什么是包?为什么需要包机制?【答】包(package)是类的集合。包是Java区别类名字空间的机制。一个包中的多个类之间不能重名,不同包中的类名则可以相同。习1-9Java对源程序中的声明语句及文件命名规则有什么要求?【答】在一个Java源程序文件(*.java)中,可以使用package语句声明包,使用import语句导入包,之后使用class或interface声明多个类或接口。其中,声明为public权限的类或接口只能有一个,且文件名必须与该类名相同。习1-11程序中的错误有哪几种?分别在什么时刻被发现?【答】语法错、语义错、逻辑错。编译时能够发现语法错,运行时能够发现语义错,运行时不能发现逻辑错。2.1语言成分1.数据类型、变量及运算习2-2Java的基本数据类型有哪些?引用数据类型有哪些?【答】基本数据类型有:整数类型byte、short、int、long,浮点数类型float、double,字符类型char,布尔类型boolean;引用数据类型包括数组(array)、类(class)和接口(interface)。习2-9与C++相比,Java的变量和常量声明有什么差别?【答】Java没有全局变量成员)局部变量含义及变量声明格式与C++相同。Java没有宏替换,使用最终变量概念代替C++中的常量和宏替换。使用final关键字声明最终变量,只能赋值一次,这样既增加了常量功能,又避免全局变量和宏替换的副作用。习2-10Java的运算分为哪些类型?与C++相比,运算符及运算含义有哪些变化?【答】Java有算术运算、关系运算、位运算、逻辑运算、赋值运算、强制类型转换、条件运算、括号运算、点运算、new、+字符串连接运算和instanceof运算等,其中+字符串连接和instanceof运算符是Java新增的,此外,放弃了C++的sizeof运算符。与C++相比,Java的语法更为严谨,将C++中某些容易引起混淆的语法做了修订,编译时也将严格进行检查。在Java中,运算符及运算含义有变化的说明如下。①没有赋值功能的表达式不能作为语句。例如:②逗号是分隔符,仅用于分隔表达式,不是运算符,不能出现在表达式中。例如:System.out.println(""+(x=1,y=2));//编译错,表达式不能包含逗号x=1,y=2;//编译错,逗号仅用于分隔表达式,不是运算符③Java增加boolean类型用于逻辑运算,其值不是0或1。例如:关系运算、逻辑运算和instanceof运算的结果都是boolean类型。整数不能进行逻辑运算。Java严格区分boolean与int类型,运算类型不能混淆。boolean类型与整数类型或其他类型不能进行算术运算、关系运算、逻辑运算。例如:if、while等语句中的条件表达式不能是赋值运算,否则产生编译错。④字符串连接运算符+自动将其他类型变量值转换成字符串类型。2.整数运算的数据类型及数据溢出习2-3整数采用二进制补码表示及运算时是什么样的?如何计算byte整型的取值范围?【习题2.1】整数以二进制补码表示及运算。本题目的:理解计算机的思维。(1)整数原码整数原码(trueform)规则如图2-1所示,与数学中的整数含义相同,区分符号位和值。原码存在以下缺点:①计算时要考虑同号异号问题,且原码的符号位不能直接与数值位一起参与运算。②0有+0、-0,编码不唯一。(2)整数补码的编码规则①什么是补码?计算机中的运算器实现算术运算的基本部件是加法器。算术运算都要转换成加法才能进行运算,减正数可转换成加上值相同的负数,乘法可转换成连加,除法可转换成连减。因此,计算机需要这样一种存储整数的方式(称为补码),它能够存储并识别正负数;对于正数或负数的运算规则相同,不需要区分符号;能够将减法转换成加法进行运算。计算机采用二进制补码(complement)存储整数并进行运算。以最高位0/1作为符号位来识别正/负整数,0和正整数的补码同原码,符号位是0;负整数补码的符号位是1,其值是如何约定的?以-1为例,因为-1=0-1,运算过程如图2-2(a)所示,所以(-1)补码=(11111111)2;同理,-128=0-128,运算过程如图2-2(b)所示。上述使用减法运算得到负数的补码,是人的理解,计算机没法进行减法运算。②整数补码的编码规则。计算机对整数能够执行的运算是按位取反和加法运算。因此,获得整数补码的编码规则说明如下,如图2-3所示。0和正整数:补码=原码,符号位是0;负整数补码:符号位是1,数值位=原码数值位按位取反+1。按照补码规则求解-1、-128补码的运算过程如图2-4所示。(3)整数(补码)的位运算,见教材图2-3。(4)整数(补码)的算术运算理解:钟表盘有12格,顺时针拨进行加法运算,则逆时针拨进行减法运算。例如,计算-1,可逆时针(减法)拨1格,也可顺时针(加法)拨11格。所以,整数补码的算术运算只有加法运算,将减法转换为加法运算进行,减正数等价于加负数。例如,127-1=127+(-1)=126的运算过程如图2-5所示。Java的整数默认是int类型,byte类型只是形式上的,取相应int值的最低1个字节。所有byte和short整数运算仍然是int类型运算,运算结果是int类型,当运算结果在byte数据范围内时,也可视作byte类型。(5)整数算术运算的数据溢出问题习2-11设byteb=127,问表达式b+"+1="+(++b)的运算结果是什么?为什么?【答】"127+1=-128"。〖解释〗见教材图2-5。试题考点byte整数溢出,字符串连接运算。同理,表达式Integer.MAX_VALUE+1的运算结果也将产生int数据溢出错误。因为Integer.MAX_VALUE值为0x7fffffff,0x7fffffff+1=0x80000000,运算过程如图2-6所示。习2-11设byteb=-128;,表达式b+"-1="+(--b)的运算结果是是什么?为什么?【答】"-128-1=127"〖解释〗已知整数以二进制补码表示,设byteb=-128(10000000)2,--b执行b=(byte)(b+(-1))运算,--b运算过程如图2-7所示,先计算b+(-1),进行byte与int的加法运算,-128+(-1)=-129(1…101111111)2,再取-129的最低1字节(01111111)2看成是byte整数,符号位是0表示正数,所以b=127。表达式b+"-1="+(--b)的运算结果是"-128-1=127",这在数学意义上是错误的,因为byte整数溢出,导致表达式计算结果错误。2-2表达式(byte)127+(byte)127的运算结果是___________,其数据类型是___________。【答】254,int2-3设intmin=Integer.MIN_VALUE;,表达式min+min的运算结果是_______________。【答】0〖解释〗Integer.MIN_VALUE值为0x80000000,0x80000000+0x80000000=0,数据溢出。2-4设intmin=Integer.MIN_VALUE;,表达式(long)(min+min)的运算结果是________。【答】0〖解释〗Integer.MIN_VALUE值为0x80000000,0x80000000+0x80000000=0,数据溢出。强制类型转换,只是把0强制转换成long类型。2-5设intmin=Integer.MIN_VALUE;,表达式(long)min+(long)min的运算结果是____。【答】0xffffffff00000000,或-4294967296。〖解释〗Integer.MIN_VALUE值为0x80000000,先强制转换成long类型,值为0xffffffff80000000,再作为long类型运算,数据不溢出。2-6设intmin=Integer.MIN_VALUE;longg=min+min;,则g的值是________。【答】0〖解释〗min+min作为int类型运算,数据溢出。2-7设intmin=Integer.MIN_VALUE;longg=min;g+=min;,则g的值是________。【答】0xffffffff00000000,或-4294967296。〖解释〗longg=min;赋值将min自动扩容到long类型,再运算,long数据不溢出。3.整数位运算2-8表达式125&10的值是____________,表达式【答】8,127〖解释〗int整数二进制位运算,运算过程如图2-8所示。4.字符类型及运算习2-5Java的char字符类型与C/C++相比有什么差别?【答】两者字符常量表示形式相同,都是用单引号将字符括起来作为字符常量。不同之处如下:①C/C++的char类型表示ASCII字符,包括数字、字母、符号等,字长为1字节,取值范围为0~127;一个汉字用2字节表示。②Java的char类型表示Unicode字符,包括ASCII字符和汉字等,一个ASCII字符和汉字均占用2字节,取值范围为\u0000~\uFFFF(即0~65535)。2-9表达式'a'+1的运算结果是_____________,(char)('a'+1)的运算结果是___________。【答】98,'b'〖解释〗char也是数值类型,可将char看成是2字节无符号整数,范围是0~65535。1是int类型,4字节。'a'+1进行的是算术运算,操作数的数据类型相容,结果取较长的int数据类型,'a'+1运算含义为将'a'的ASCII码97加1。(char)('a'+1)将98强制转换成char类型,结果为'b'。2-10设charch1=108,ch2=73;,以下语句有什么错误?如何改正?【答】编译错,不能将int转换成char。改正如下:ch1=(char)(ch1+ch2);〖解释〗与byte和short类型存储和运算原理相同,char也是以int存储和运算的,在0~65535范围内的整数可看成一个Unicode字符的编码,因此能够以字符显示。两个char作为数值参加算术运算时,仍然是int类型运算,运算结果是int类型。所以,不能赋值给char变量。【思考题2-2】设charch表示16进制的一个数字字符,获得ch对应整数值的条件表达式是。【答】ch>='0'&&ch<='9'?ch-'0':ch>='a'&&ch<='f'?ch-'a'+10:ch-'A'+10〖解释〗因为16进制的数字字符范围是:['0','9']、['a','f']或['A','F'](表示值10~15)。上述表达式功能相当以下if语句嵌套:【思考题2-2】已知radix进制范围是[2,16],数字集合是['0','9']和['a','f'];设inti表示radix进制的一个数字值,将i转换成radix进制数字字符的条件表达式是________________。【答】i>=0&&i<=9?(char)(i+'0'):(char)(i-10+'a')2.2流程控制语句习2-12Java的语句与C/C++有什么差别?【答】Java语句的语法与C/C++的语法相同,Java不支持goto语句。【习题2.2】理解Java的字符类型。①以下程序段输出ASCII码可打印字符表。System.out.println("ASCII码可打印字符(\\u0021~\\u0}程序运行结果如下:ASCII码可打印字符(\u0021~\u007e)表②修改上述程序段的for语句表达式如下,输出Unicode汉字字符表。③Unicode字符的取值范围是0~65535(\u0000~\uffff),反之,并不是0~65535之中每个值都对应一个字符,标准输出语句输出没有对应字符的编码时,输出结果是问号“?”。例如,128没有对应字符,以下欲输出编码为128的字符,输出结果是问号。System.out.println((char)128);//输出“?”2.3数组习2-14与C/C++的数组相比,Java的数组做了哪些改进?具有什么样的优越性?【答】①Java数组都是动态数组,在声明数组变量之后,使用new运算符申请数组存储空②提供length属性表示数组长度。③Java的数组是引用数据类型,两个数组变量之间的赋值是引用赋值,传递地址等引用特性,没有申请新的存储空间。④Java将严格检查数组元素下标范围,程序运行时,如果a[i]的下标i取值超出0~a.length-1范围,则作为错误处理,产生“数组下标越界”异常,程序运行终止。⑤数组名不作指针使用。2-11以下数组声明错误的是___________________。(A)int[]a;(B)inta[3];(C)inta[]={1,2,3};(D)inta[]=newint[3];【答】B。〖解释〗Java数组是动态数组,声明数组变量时不需要接线指定数组长度,只有使用new运算符申请数组存储空间时才需要指定数组长度。2-12设inta[]=newint[5],b[]=a;执行语句b[0]=99;后,a中各元素值为_____________。【答】{99,0,0,0,0}〖解释〗Java的数组是引用数据类型,两个数组变量之间的赋值是引用赋值,即两个数组变量引用同一个数组,修改其中某一元素将同时改变另一数组变量相应元素,如图2-9所示。2.二维数组【实验题2-6】存储上三角矩阵的二维数组。实现以下方法,创建的存储结构如图2-10所示。图2-10存储n=5行上三角矩阵的二维数组2.4静态方法习2-16Java类中的方法与C/C++中的函数有什么差别?【答】①Java类中的方法都是类的成员方法,没有C/C++中的全局函数。②Java类的成员方法中,不能用*或&声明参数,参数没有默认值;方法体中不能用static声明局部变量。习2-17Java方法的参数能够作为输出型参数吗?【答】Java方法的参数传递原则与赋值原则相同,根据参数类型不同分二种情况:①基本数据类型参数是输入型参数,形式参数只能接收实际参数赋值,形式参数改变后值不能作用于实际参数,可以声明返回值向实际参数传递运算结果值。②引用数据类型参数是输出型参数,形式参数接收实际参数的引用赋值,即形式参数和实际参数引用同一个引用类型数据(数组或对象),任何通过形式参数对引用数据的更改都将作用于实际参数。2.5字符串习2-18Java的String字符串类有哪些特点?比C/C++的字符数组有哪些优越之处?【答】①Java的字符串常量表示形式同C/C++,是由双引号括起来的字符序列,其中可包含转义字符,如"hello!"、"汉字\n"、""(空串)等。字符串只能在同一行内,不能换行。②java.lang.String字符串是一个类,属于引用数据类型。与普通类不同的是,String类具有以下基本数据类型的特性,有赋值和连接运算,例见教材。③String类提供构造串对象、求串长length()、取字符charAt(i)、求子串substring()、比较相等equals(),比较对象大小compareTo()等操作。compareTo()方法说明详见教材4.3.1节,更多方法说明详见教材附录E。String类表示常量字符串,不提供插入、删除子串操作。④C/C++采用字符数组表示字符串,以str[i]形式对字符串str的第i个字符进行存取操作,并在库文件string.h中提供诸如strlen()、strcpy()、strcmp()、strcat()等函数实现字符串操作。这种表示方式是不健壮、不安全的,它没有对数组所使用的存储空间进行控制,也没有对数组下标进行越界检查,会产生更改字符串结束符"\0"等错误,strcpy(char*str1,char*str2)函数甚至可以将一个长字符串复制到一个短字符串的字符数组中,字符数组使用超出其预定范围的存储空间,非法占用本不属于它的存储空间,导致随意更改其他变量值等严重错误,strcat(char*str1,char*str2)函数存在同样问题。习2-19如何将数值类型的数据转换成字符串?【答】将数值与空串进行字符串连接运算,例如:习2-20设charch='a';,表达式"\"(char)"+(ch+0)+"='"+ch+"'\""的运算结果是___________。【答】"(char)97='a'"〖解释〗charch=97,即charch='a';。(ch+0),操作数类型是char、int,类型相容,+进行算术运算加法,结果取较长的数据类型。因此,当charch='a'时,ch+0的结果是int类型的97。""+97,当+运算符的两个操作数中有一个是字符串时,+进行字符串连接运算,先将其他类型变量值转换为字符串再连接。因此,""+97的结果是字符串"97"。其后表达式各项进行字符串连接运算,得到结果。习2-21能否以s[i]格式读写String字符串中的字符?为什么?如何获得字符串中的字符?【答】不能。因为String字符串不是字符数组,Java没有提供重载[]运算符功能,因此不能以s[i]格式表示指定字符。调用String类的charAt(i)方法可读取s字符串的第i个字符。习2-22如何将数值按指定格式转换成字符串?【答】调用String类的静态方法format(),返回指定格式的字符串。例如:String.format("Sum=1+...+%2$d=%1$d",55,10)//结果为“Sum=1+...+10=55”String.format("%x",0177)//八进制整数0177的十六进制形式为“7f”String.format("%o",0x80000000)//十六进制整数0x80000000的八进制形式“20000000000”String.format("%8x",127)//十进制整数127的十六进制形式为“7f”String.format("%08x",255)//十进制整数255的十六进制形式为“000000ff”String.format("%08x",-1)//十进制整数-1的十六进制形式为“ffffffff”String.format("%+08x",-1)//运行错,抛出异常,十六进制不2.6☆☆算法分析与设计基础2.6.2典型问题的算法分析与设计4.二进制运算,进制转换【实验2-12】整数类的算法设计。本例目的:①理解二进制运算和进制转换,算法设计训练。②字符串运算。技术要点:(1)将整数转换成二、十六进制原码字符串,除2取余法。2-13以下方法有什么错误?为什么?publicstaticStringto2Strin{Stringstr="";{}}【答】该算法存在问题:当value≤0时,返回"",错误,没有求解0和负数的原码。2-14正整数的十六进制原码字符串,除16取余法,递归算法。publicstaticStrin{}2-15以下方法有什么错误?为什么?publicstaticStringtoString1({Stringstr="";{}}【答】以下语句错误,将数字的ASCII码转换成字符串。例如,将15转换成"15"而非"F"。修改上述语句如下,将数字转换成字符。该算法存在问题:当value≤0时,返回"",错误,没有求解0和负数的radix进制原码。<2>实现上述功能的正确算法。(2)将整数转换成二进制补码字符串,除2取余法。为了适用于负数,将上述算法修改如下。2-16以下方法有什么错误?为什么?publicstaticStrin{Stringstr="";{}}【答】上述算法试图将除2取余法功能扩展到负数,但算法错误,因为负数补码的符号位是1。例如,当value=-1时,value%2=-1,str="-1",value/2=0,循环执行一次,返回"-1"。而"-1"的二进制字符串是"11111111111111111111111111111111"。为解决问题,修改算法如下。2-17以下方法有什么错误?为什么?publicstaticStringtoBinaryStrin{Stringstr="";{}}【答】上述算法错误,value=-1时,value%2结果为-1,(char)(value%2+'0')结果为'/'('0'的前一字符),所以不行。(3)将整数转换成二进制补码字符串,采用位运算实现除2取余法。①采用字符串连接运算//每次获得二进制的最高位,将其转换为数字字符,再顺publicstaticStringtoBinaryStri{Stringstr="";for(inti=0x80000000;i!=0;i>}【问】如果for语句如下,将会怎样?【答】错误,i>>=1,高位以1填充,i!=0条件永远成立,死循环。该算法将非0值算作1,因此算法不具有扩展性,不适合8和16进制。修改如下。//算法描述:每次获得二进制的个位,将其转换publicstaticStringtoBinaryStri{Stringstr="";{//将各位余数字符按反序连接成字符串。&}}由于String是常量字符串,字符串连接运算需要重新申请数组空间并复制原字符串,因此频繁调用字符串连接运算,效率很低。②采用字符数组代替字符串连接运算,提高效率。publicstaticStringtoBinarySt{{value>>>=1;}returnnewString(buffer}其中,value&1运算结果为0或1;(value&1)+'0'运算结果为48或49,表示'0'或'1'的编码值;(char)((value&1)+'0')运算结果为'0'或'1',即获得value的个位字符。上述算法逐个获得value的个位字符,存入buffer数组。算法描述见教材图2-26所示。<1>实现以下方法。publicstaticStringtoOpublicstaticStringtoHexSt(4)将整数转换成radix进制补码字符串,采用位运算实现除radix取余法。MyInteger类声明toString(intvalue,intradix)方法,算法实现见教材例2.17。//32个二进制位,八、十六进制增加前缀"0"、"0x"。采用位运算;采用publicstaticStringtoComplementString(intvalue,int【实验2-13】浮点数类的算法设计。本例目的:理解语法图的定义格式,根据语法图进行复杂算法设计。功能说明:将浮点数字符串转换成浮点数值,给出两种算法。技术要点:浮点数由“尾数E(或e)阶码”组成,语法图如图2-11所示。声明MyDouble类如下。publicfinalclassMyDouble//{publicstaticdoubleparseDouble(Stringstr)throws{i++;//i记住当前字符序号,跳过正负号{{}}{for(intj=0;j<exp;j++}}}3.1类和对象【实验题3-1】交换变量方法的问题讨论,理解Java对象的引用模型。本例目的:①以讨论交换两个变量值问题为例,说明基本类型和引用类型在作为方法形式参数时的参数传递原则。②与C++的指针和引用类型比较。引入问题:交换两个变量值是应用程序设计中经常遇到的一个问题,这个问题的关键是一个方法如何返回两个变量值。在C++中可将参数设计成指针(*)或引用(&)类型实现。由于Java没有指针类型,也没有&引用运算符,那么如何实现这个问题?分析解答:①在C/C++、Java中,以下swap(int,int)方法的参数类型是基本数据类型,不能交换。{}main()中调用语句如下:调用swap(i,j)方法,将实际参数i、j的值传递给形式参数x、y;在方法体中交换了x、y的值,并未改变实际参数i、j,如图3-1所示。因此,swap(int,int)方法不能交换两个实际参数变量的值。②在C/C++中,以下swap()方法的参数类型是指针或引用,能够交换。Java语法错误。{*x=*y;//对*x赋值,即对指针x所指向的实际参数变量赋值,}调用语句如下:调用swap(&i,&j)函数时,传递给指针形式参数x、y的是实际参数变量地址&i、&j,此后对*x、*y的操作就如同对i、j的操作,如图3-2所示。因此,该函数能够交换两个变量值。C++采用引用类型参数的swap()方法声明如下,功能同指针。voidswap(int&x,int{}p③在Java中,以下swa(Object,Object)方法的参数类型是引用类型,不能交换。ppublicstaticvoidswap(Objectx,Objecty){}调用语句如下:当对象作为方法参数时,参数传递的是引用,功能同两个对象引用赋值。上述swap(x,y)方法只在方法体内交换了两个形式参数x、y自己引用的对象,并没有改变实际参数str1、str2所引用的实例,执行过程如图3-3所示。因此,不能交换。swap(Objectx,Objecty)方法相当于C/C++以下函数功能,虽然指针参数x、y得到了实际参数变量i、j的地址&i、&j,但是在函数体中,它交换的是作为形式参数的两个指针变量x、y存储的地址,即交换了x、y所指向的变量,但没有交换x、y所指向变量(实际参数)的值,见图3-2(c)。voidswap(int*x,in{}④在Java中,能够交换两个数组元素值,无论数组元素类型是基本类型还是引用类型。{if(table!=null&&i>=0&&i<table.{}}{if(objs!=null&&i>=0&&{}}数组是引用类型,当方法的形式参数是数组时,实际参数向形式参数传递引用,使得形式参数与实际参数引用同一个数组,因此,在方法体中,任何对形式参数的修改都作用于实际参数,上述两个swap([],i,j)方法能够交换数组中指定的两个元素,基本类型或引用类型数据都可以,执行过程如图3-4所示。3.2类的封装习3-6下列MyDate类构造方法声明有什么错误?【答】Java不支持在方法声明时为参数指定默认值。【习题3-7】默认构造方法及重载构造方法的必要性。①如果一个类没有声明构造方法,则Java自动提供一个无参数的默认构造方法。例如:{{System.out.println(+","+p.}}程序运行结果如下:②如果一个类声明了构造方法,则Java不再提供默认构造方法。例如:{{}{}}③如果有成员变量是最终变量,由于其已经在构造方法中被赋值了,所以就不能在其他方法为最终变量name再次赋值。例如,以下Person类声明,所以set()方法体中为最终变量name再次赋值的语句编译错误。{}}}④一个类必须声明多个重载的构造方法。例如:{{}{this("",0);}{}}2.成员方法重载习3-12MyDate类中为什么set()方法可以重载,get()方法不能重载?【答】由于各set方法的参数列表不同,所以,一组set方法可以重载,共用同一个方法名;而由于get方法没有参数,一组get方法之间仅返回值的类型不同,所以,get方法不能重载,需要声明多个方法名。3.静态成员习3-14采用关键字static声明的成员有什么特性?【答】关键字static用于声明属于类而不属于实例的成员,包括成员变量和成员方法。习3-15main()方法为什么要用static声明?【答】因为main()方法是属于类的,在创建实例之前,就由Java虚拟机调用。【实验题3-2】☆☆☆MyDate类增加daysAfter(intn)方法。本例目的:①日期计算的算法研究。②演示采用3个整数表示日期,进行日期计算很麻烦。【答】MyDate类增加声明以下方法,返回当前之前/后n天的日期。publicMyDatedaysB{MyDatedate=newMyDate(this);//执行拷while(n>=((leap=date.mdate.month>=3&&MyDa{}while(n>=date.daysOfMonth{date.month=date.mon}if(date.day+n<=date.{}}3.3类的继承习3-21Java声明Object类的作用是什么?Object类中声明了哪些方法?Object类在Java类层次体系中的地位是什么样的?【答】Object类声明所有类共用的方法,方法有equals()、toString()等。根类。习3-23newPerson()instanceofObject运算结果是__________,理由是_________________。【答】true,任何类都是Object的子类,子类对象即是父类对象。【实验题3-4】类的继承性问题讨论,以Person和Student类为例。本例目的:讨论类的继承性,包括构造方法的继承性、私有成员的继承性和访问权限、最终变量的继承性。①父类声明。{{}{this(null,0);}}{return+","+this.}}②子类没有声明构造方法时,有默认构造方法。{{System.out.println(s1.toString(}}程序运行结果如下:默认构造方法Student1(),执行父类的默认构造方法Person1(),相当于声明如下:}如果父类Person1没有声明Person1()构造方法,则下列语句不能通过编译:Student1s1=newStu因此,一个类通常需要声明默认构造方法。③子类能够继承父类的私有成员(包括最终变量),但不具有访问权限。下列语句错误:System.out.println(+","+s1.age+"岁");//编译错,对父类私有成④子类不能继承父类的构造方法,子类必须声明自己的构造方法。子类不能继承父类的构造方法。因为父类构造方法创建的是父类对象,子类必须声明自己的构造方法,创建子类自己的对象。当Student1类没有声明构造方法时,下列语句错误:Student1s1=newStud子类必须声明自己的构造方法。例如:{}{System.out.println(s1.toS}}程序运行结果如下:当一个类声明了有参数的构造方法时,Java则不再提供默认构造方法。所以,当Student2类没有声明Student2()构造方法时,下列语句错误:Student2s2=newStudent2();因此,充分说明子类不能继承父类的构造方法。⑤子类的构造方法也必须重载。{}}{Student3s1=newStudent3("李System.out.println(s1.toSSystem.out.println(s2.toS}}程序运行结果如下:由此可见,两个对象的最终变量值可以是不同的。并且子类无参数的构造方法Student3()也是必需的,它实现对自己类实例的初始化。3.4类的多态习3-28以下语句有什么错误?为什么?Objectobj1=newPersoObjectobj2=newPer【答】第2句语法错,因为虽然obj1引用Person实例,但其数据类型是Object,与Person的拷贝构造方法Person(Person)的参数类型不匹配,语义上也不能由Object构造Person实例。2.子类隐藏父类实例成员变量,toString()方法的多态性研究【实验题3-5】Student1类隐藏Person2父类实例成员变量name,toString()方法覆盖。阅读程序,回答问题。{{}{}}{}}{System.out.print("s1="+s1.toStrinSystem.out.println("per="+per.toS}}【问题】①Student1类的name与Person2类的name是_____________________关系。②super(name)为_________________类的name赋值。③Student1类的toString()方法与Person2类的toString()方法是__________________关系。④main()中,per能够引用Student1类的实例,因为_________________________________。⑤main()中,编译器检查per.toString()是_______________类的_____________类的方法。⑥运行结果是__________________________________。⑦Student1类的toString()方法与Person2类的toString()方法声明和实现相同。如果Student1类省略toString()方法,则运行结果是_________________________________。⑧如果Student1类没有省略toString()方法,而希望查看Person2类的name和Student1类的name值,修改Student1类toString()方法体如下,则哪里有什么错误?为什么?如何改正?⑨如果Student1类修改构造方法如下,为自己类中声明的name进行赋值,则Person2类需要做哪些修改?}【答】每空1分。①隐藏。②Person2。③覆盖。④Student1子类对象即是父类Person2对象。⑤Person2类;Student1类。〖解释〗因为,此时方法的调用对象per引用的是Student1子类实例。⑥s1=null;per=null〖解释〗因为,Student1类声明name成员变量与父类name成员变量同名,Student1类中有两个name成员变量:和,隐藏了。Student1(name)构造方法通过super(name)语句调用父类构造方法Person2(name),其中指Person2类声明的name,相对于Student1类则是;Java默认为Student1类的赋值为null,如图3-5所示。而调用s1.toString()或per.toString(),执行Student1类的toString()方法,其中指Student1类声明的name成员变量,它的值为null。⑦s1=李小明;per=李小明〖解释〗因为,调用s1.toString()或per.toString(),执行父类的toString()方法,其中指Person2类声明的name,前述构造方法已为其赋值,如图3-5所示。实际上,此处Student1类使用的是Person2类声明的name,而非Student1类声明的name。⑧语法错。〖解释〗因为父类的name声明为private,子类没有name的访问权限。改正如下。returnsuper.toString⑨Person2类需要增加构造方法如下:}〖解释〗因为Student1类的构造方法中,默认super();,默认调用父类无参数的构造方法Person2()。{super();}3.equals(Object)方法的多态性研究习3-30Object类声明equals(Object)方法的作用是什么?【答】Object类equals(Object)方法的作用是,为子类提供比较对象相等的默认方法实现。当一个类没有声明equals(Object)方法时,能够调用父类或祖先类Object的equals(Object)方法,等价于默认equals(Object)方法。而比较对象引用,则是对各个子类均适用的规则。子类如果需要自己特定的比较对象相等规则,可声明自己的equals(Object)方法,覆盖Object类equals(Object)方法,在子类中表现出运行时多态性。习3-31Person声明equals(Person)方法如下,其中有没有错误?{returnthis==p|p!=null&name.equals(p.n}【答】没有语法错,运行结果正确。因为逻辑运算符“|”“&”没有短路计算功能,“|”优先级低于“&”,先计算“&”,再计算“|”,因此导致this==p失去作用,即当this==p时,也比较两个实例的成员变量。从算法设计角度来看,此时没必要成员变量,所以,建议使用带短路功能的逻辑运算符“||”“&&”如下,按照出现次序先计算“||”,再计算“&&”。returnthis==p||p!=null&&name.equals(p.na习3-30**Object类为什么要声明equals(Object)方法?①如果Object类没有声明equals(Object)方法,则Person类必须声明equals(Person)方法如下:那么,Student类继承该方法,但是该方法仅比较了Person声明的成员变量,没有比较Student类增加的成员变量,所以不能满足Student子类需要。因此,Student类增加方法声明如下:两者是重载关系,导致混乱,也不符合Java“简单性”原则。不能覆盖就不能实现运行时多态。再问,Student的子类将如何声明equals(?)方法?解决办法是,将两者合二为一。Student类声明覆盖父类的方法如下:推而广之,每个类应该覆盖父类的equals(父类对象)方法,参数是父类对象。②Java提出采用“简单性”原则的解决方案是:Object类声明equals(Object)方法,为子类提供默认equals(Object)方法。子类覆盖equals(Object)方法,提供符合子类需要的方法实现,由运行系统确定执行多态的方法实现。例如:习3-33设Person类覆盖equals(Object)方法,以下调用执行哪个类的方法?运行结果如何?为什么?【答】per、obj对象引用的实例如图3-6所示。//调用Object类声明的equal习3-34Student类实例与Person父类实例的可比性研究。①Student类继承父类Person的equals(Object)方法,功能不全。调用语句如下,语义是否正确?为什么?stu2.equals(stu1)//两个子类实例比较,语法正确;逻没有比较Student类增加的成员变量,功能不全。②Student类覆盖父类Person的equals(Object)方法,方法体见教材3.4.4节,算法与父类实例不可比。调用语句如下,per、stu1、stu2声明同上。per.equals(stu1)//执行Pers4.equals(Object)方法运行时多态的应用【实验题3-6】Object[]对象数组的查找与替换,理解equals(Object)方法的设计与应用。本例目的:Object[]对象数组的查找与替换算法设计,演示Object、Object[]作为方法参数或返回值;理解类型的多态,理解算法中调用的equals(Object)方法表现出运行时多态。<1>查找与替换的算法设计,调用equals(Object)方法。在例3.6的ObjectArray类中,增加查找和替换方法声明如下。publicstaticObjectsearc{}publicstaticvoidreplaceAll(Obj{if(key.equals(objs[i]))}<2>替换算法调用,替换Object实例,理解Object类的equals(Object)方法实现。替换Object实例的调用语句如下:Object[]objs={"xyz",newObjecObjectArray.printlnBracket(objs);Objectkey=newObject(),x="abc";ObjectArray.replaceAll(objs,key,x);ObjectArray.printlnBracket(objs);程序运行结果如下,填空。【答】{xyz,java.lang.Object@378bf509}【解释】①已知Object类声明toString()、equals(Object)方法如下。returnthis.getClass().getName()+"@"+Integer.toHexString(t}{}②执行上述调用语句,replaceAll(objs,key,x)方法的objs[]、key参数传递如图3-7(a)所示,此时key、objs[1]分别引用一个Object实例,两者的散列码不同,则key==objs[1]运算结果为false;调用key.equals(objs[1])执行Object类声明的equals(Object)方法,结果为false,所以,就没有替换objs[1]引用的对象;再次输出,仍然为原值。③如果key声明如下,调用replaceAll(objs,key,x)方法的参数传递如图3-7(b)所示,则将替换objs[1]引用的对象。Objectkey=objs[1],x="abc";//引用赋值,即key、objs[1]引用同一个<3>查找和替换算法调用,替换MyDate实例,理解各类的equals(Object)方法实现,理解对象引用模型。替换MyDate实例的调用语句如下:Object[]objs={newMyDate(2024,5,1),newMyDate(2024,ObjectArray.printlnBracket(objs);//输出objObjectkey=newMyDate(2024Objectfind=ObjectArrayObjectArray.replaceAll(objs,key,x);//查找成功时替换ObjectArray.printlnBracket(objs);程序运行结果如下,填空。【答】{2024年05月02日,abc}【解释】执行中的情况如图3-8所示。①查找。在objs数组中查找key引用的MyDate实例,调用key.equals(objs[0])执行MyDate类声明的equals(Object)方法,结果为true,查找成功,find引用查找到的对象。②修改查找到的对象。执行((MyDate)find).tomorrow();语句,修改find引用对象的值。③替换。调用replaceAll(objs,key,x)方法,其中key.equals(objs[1])方法结果为true,则将替换objs[1]引用的对象。3.5类的抽象习3-35什么是抽象类?在什么情况下需要设计抽象类?抽象类中是否必须有抽象方法?【答】使用关键字abstract声明的类称为抽象类,抽象类通常包含抽象方法,抽象方法是只有方法声明而没有方法体的成员方法,抽象类不能被实例化。习3-35抽象方法的意义何在?【答】抽象方法提供方法声明与方法实现相分离的机制,实现运行时多态。习3-36以下类声明有什么错误?{}【答】没有错误,抽象类也可以不包含抽象方法。习3-37如果ClosedFigure类中area()方法声明如下,会对ClosedFigure的子类有何影响?{{}}【答】此处ClosedFigure类的area()方法没有意义。因为ClosedFigure的子类不是必须覆盖area()方法,如果没有覆盖,无论是什么对象,则图形面积总为0.0。将area()方法声明为抽象方法,在编译时Java会自动检查子类是否覆盖了抽象方法。如果一个方法需要被子类覆盖,则必须声明为抽象方法。习3-37以下声明有什么错误?{protectedabstractC{}}习3-38指出以下声明中的错误。【答】MyCircle类声明编译错误,不能继承Circle最终类。习3-38指出以下声明中的错误。}}【答】Circle类中area()方法声明编译错误,不能覆盖父类的最终方法。【例3.7,实验题3-7②】图形类覆盖equals(Object)方法。例3.7的图形类覆盖equals(Object)方法如下,算法逐域比较各成员变量是否相等。{}{}{}publicclassTriangleextend{}{}publicclassRectanglee{intlength,width;}//正方形,没有增加成员变量,继承eq{}4.1接口与实现接口的类习4-1什么是接口?接口的作用是什么?【答】接口是一组抽象方法、常量和内嵌类型的集合。接口提供方法声明与方法实现相分离的机制,使得接口中声明的抽象方法能够在实现接口的类中表现出运行时多态。习4-2接口能否被实例化?为什么?接口中能否写构造方法?为什么?【答】接口不能被实例化,因为接口是声明的是抽象方法,没有方法体。接口中不能写构造方法,因为构造方法不能声明为抽象方法。习4-2接口对象引用谁的实例?【答】接口是引用类型,接口对象引用实现该接口的类的实例。习4-3接口具有怎样的继承性?【答】接口是多重继承的,一个接口可以继承多个父接口。习4-4指出以下声明中的错误。protectedinterfaceArea【答】//编译错,不能声明接口为保护的{publicstaticfinalintRIGpublicstaticabstractdoubleperimet}Areaar=newArea();习4-1说明接口与抽象类的差别。【答】相同点:①两者都包含抽象方法,为多个类约定一个功能(操作)的方法声明。②两者都不能被实例化。③两者都是引用数据类型,其对象可引用子类型(子类或实现接口的类)的实例。不同点:①抽象类为多个子类约定方法声明;接口为多个不相关的类约定方法声明。②抽象类与子类之间是单继承的;接口是多重继承的,一个接口可以继承多个父接口,一个类也可实现多个接口,则具有多个接口声明的功能。③抽象类中可以包含非抽象方法,可以声明构造方法;接口中的方法全部是抽象方法,不能声明构造方法。④抽象类中可以声明成员变量,子类可以对该成员变量赋值;接口中只能声明常量。⑤抽象类及其类中成员具有与普通类一样的访问权限;接口和接口中成员的访问权限只有public和默认两种。习4-5举例说明Java声明了哪些接口,各起什么作用。【答】①java.lang.Comparable<T>可比较接口和java.util.Comparator<T>比较器接口,提供多种对象比较大小的规则;②java.awt.LayoutManager布局管理器接口,为所有布局提供添加、删除组件的方法;③java.awt.ActionListener事件监听器接口,约定指定事件的事件处理方法;④java.lang.Runnable接口约定线程执行的操作;⑤java.io.FileFilter文件过滤器接口,约定文件过滤规则,等等。2.对象数组的算法设计,运行时多态应用【例3.6,实验题3-6~4-1】从Object[]到Area[]接口对象数组的算法设计,运行时多态应用。本题目的:Object[]根类、ClosedFigure[]抽象类、Area[]、Volume[]接口对象数组作为方法的参数,通用算法设计中方法的运行时多态应用。①【例3.6】对Object[]对象数组操作的算法设计,toString()、equals(Object)运行时多态。已知Object类声明toString()、equals(Object)方法表现运行时多态。声明Object[]objs作为方法的参数如下:publicclassObjectArra{publicstaticvoidpobjs[i].toString()//objs[i]可引用任何实例,toString()方法}publicstaticObjectseaif(key.equals(objs[i]))//equals(Object)方法比较}}各方法体中,objs[i]可引用任何实例(都是Object的子类toString()、equals(Object)方法运行时多态,因此,println(Object[]objs)、search(Object[]objs,Objectkey)方法适用于所有对象数组。②【实验题3-6】对Person[]对象数组操作的算法设计。publicclassPersonAr{publicstaticdoubleasum+=pers[i].getAge();//per}}③【实验题3-7】对图形对象数组操作的算法设计,area()方法运行时多态应用。publicclassFigureAr{publicstaticdoubleaverage(Line[]linespublicstaticdoubleaverage(Rectangle[]rects)//计算平均值,按矩形面积取值publicstaticdoubleaverage(Ellipse[]publicstaticdoubleaverage(Triangle[]publicstaticdoubleaverage(Polygon[]p}上述方法的算法相同,各计算的取值不同。其中后4个方法都是按面积计算的,如果声明ClosedFigure抽象类如下:publicabstractclass{publicabstractdoublearea()}再声明Rectangle、Ellipse、Triangle、Polygon是ClosedFigure类的子类,分别实现area()方法;则可声明以下方法://按ClosedFigure[]数组元素实际引用抽象publicstaticdoubleaverasum+=cfigs[i].area();//cfigs[}④【实验题4-1】对Area[]接口对象数组操作的算法设计,area()方法运行时多态应用。publicclassAreaArray//Area接口对象数组类,声明{publicstaticdoubleaverage(Arsum+=areas[i].area();//areas[i]引用实现Area接口的类的实}}⑤【实验题4-1】Volume[]接口对象数组的算法设计,volume()方法运行时多态应用。publicclassVolumeArray//Volume接口对象数{publicstaticdoubleaverage(Volu//volumes[i]引用实现Volume接口的类的实例,vol}}4.3JavaAPI基础1.java.lang包中的基础类库习4-9JavaAPI采用什么组织方式?默认导入的包是什么?【答】JavaAPI采用包组织类。默认导入的包是java.lang。习4-10Java为什么要将Math类声明为最终类?Math类中有哪些常用方法?【答】不能被其他类继承,使得其中方法不会被覆盖而修改。方法有abs()、max()、sin()、cos()、sqrt()等。习4-12Java为什么需要声明基本数据类型的包装类?基本数据类型的包装类有哪些?【答】Java为了实现完全面向对象。泛类T的实际参数必须是对象。8个基本数据类型对应的类为:Byte、Short、Integer、Long、Float、Double、Character、Boolean。习4-13以下表达式的执行结果是___________。newjava.util.Date().getClass().getSuperClass().getPacka【答】java.lang〖解释〗该语句输出newjava.util.Date()实例所属类的父类所在的包名。Date的父类是java.lang.Object。习4-14如何将数值字符串转换成其所表示的整数或浮点数数值?【答】调用java.lang.Integer类的以下静态方法parseInt(s)将字符串s转换成十进制整数。publicstaticintparseInt(Stri调用java.lang.Double类的以下静态方法parseDouble(s)将字符串s转换成浮点数值。publicstaticdoubleparseDouble(Strings)throws如果字符串不能转换成整数或浮点数,将抛出数值格式异常。详见教材第4~5章。习4-14如何从二、八、十六进制字符串中读取整数值?【答】调用java.lang.Integer类以下方法parseInt(s,radix)将字符串s转换成radix进制整数。publicstaticintparseInt习4-14如何将整数转换成以二进制、八进制或十六进制形式字符串?【答】①String.format(Stringformat,Object...args)方法返回format指定格式的字符串,"%o"、"%x"分别指定八进制、十六进制整数格式。②java.lang.Integer类声明以下方法,分别返回整数的二、八、十六进制形式字符串。上述方法返回的字符串不包括高位0。例如:Integer.toBinaryString(128)2.java.util包中的工具类库习4-17举例说明采用导入语句使用Java定义的类。【答】使用Java定义的、除java.lang包中的类需要导入语句,例如:importjava.util.*;习4-18获得当前日期和时间的语句是__________________________________。【答】newDate()或Calendar.getInstance()或System.currentTimeMillis()习4-18获得当前日期月份的语句是_____________________。【答】Calendar.getInstance().get(Calendar.MONTH)+14.4泛型**【实验题4-1~4-5】比较对象大小的方法及应用,泛型T的作用。本例目的:说明比较对象大小问题演变成使用Comparable<T>和Comparator<T>接口,理解接口的委托模型。技术要点:①声明min(T[])等方法对T[]泛型对象数组进行计算;②Person、ClosedFigure等类声明比较对象大小的方法,实现可比较接口,或者声明比较器接口。<1>min(对象[])计算最小值方法,调用各类声明的方法进行计算。Areamin(Area[]areas)Volumemin(Volume[]volumes)【提出问题】这些方法都是计算最小值,算法相同,能否合并功能?【答】能,声明min(T[])和min(T[]objs,comp)泛型方法,要求T类比较对象大小的方法运行时多态。<2>声明min(T[])泛型方法,<TextendsComparable<?superT>>表示T类可比较对象大小。Java约定Comparable<T>可比较接口声明compareTo(T)方法比较T对象大小。约定了方法声明,使得compareTo(T)方法在实现Comparable<T>接口的类中表现出运行时多态。声明min(T[])泛型方法如下,T必须满足<TextendsComparable<?superT>>,即T类或其祖先类?实现Comparable<T>接口,提供compareTo(T)方法比较T对象大小。publicstati
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- HSE管理体系建设工作模式
- AMI心电图诊治的进展
- LCM液晶显示模块设计培训资料
- 公务员个人思想年终工作总结
- EMBA教材营销管理
- LED显示产品培训
- 2026四上数学易错题课件
- 患者安全管理案例
- 2026年计算机硬件设计师模拟卷
- 2026年群面辩论题目分析及答案
- T-CCTAS 22-2021 城市智慧停车场系统建设与运营服务规范
- 辅警笔试题目及答案
- SF∕T 0095-2021 人身损害与疾病因果关系判定指南(司法)
- 环氧地坪施工检验批质量验收记录表
- 眼镜购销合同范例
- 太阳能直升机小学科学课件stem课程社团课课件
- 食品生产企业更衣室管理规定及更衣程序(附图片)
- T-GDASE 0042-2024 固定式液压升降装置安全技术规范
- 大棚维修协议合同范本
- 2023年陕西工业职业技术学院专任教师招聘考试真题
- (正式版)JBT 14878-2024 柔性直流换流阀子模块旁路开关
评论
0/150
提交评论