[原创]课堂笔记学习java(初级)
[原创]课堂笔记学习java(初级)
见于此版是有关Java语言基础的版面,偶这学期专业课开始学习java,希望通过此贴把偶的课堂笔记与大家分享,与初学者共同从零学起,还请各位高手随时指点,引导大家把基础打好,谢谢
. 现在每周两节课,偶会随时更新的,因为板书很多,有些精彩的描述都是口述的,所以下面的笔记并不是很规范.
-------------------------------------------------------------------------------
1楼: 第一节课: Java 入门起步
2楼: 第二节课: 标识符 关键字及数据类型
3楼: 第三节课: 类和对象
4楼: 第四节课: static的用法和包
5楼 第五节课: 继承与访问权限
6楼 第六节课: 多态与抽象类
7楼 第七节课: 接口
8楼 第八节课: 一些重要的类(内部类, 匿名类, 异常类, Class类, 基本数据类型类等)
9楼 第九节课: 字符串
. 现在每周两节课,偶会随时更新的,因为板书很多,有些精彩的描述都是口述的,所以下面的笔记并不是很规范.
-------------------------------------------------------------------------------
1楼: 第一节课: Java 入门起步
2楼: 第二节课: 标识符 关键字及数据类型
3楼: 第三节课: 类和对象
4楼: 第四节课: static的用法和包
5楼 第五节课: 继承与访问权限
6楼 第六节课: 多态与抽象类
7楼 第七节课: 接口
8楼 第八节课: 一些重要的类(内部类, 匿名类, 异常类, Class类, 基本数据类型类等)
9楼 第九节课: 字符串
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第一节课:
1. java 语言的诞生和特点(一般的教材都会有很详细的叙述,略)
2. java 学习的起步
(1)Sun公司要实现“编写一次,到处运行”(Write once,run anywhere)的目标,必须提供相应的Java运行平台,目前Java运行平台主要分为3个版本:J2SE(标准平台),J2EE(企业平台),J2ME(移动平台)
(2)学习Java必须从J2SE开始,当然得从了解在标准平台(J2SE)上是如何开发程序开始.
a.首先从源文件(以.java结尾的文件)开始----经过java编译器(javac.exe)编译----生成字节码文件----根据内文件的本质再可以再产生两种文件:java应用 程序(application) 和 java小应用程序(applet);应用程序是由于java解释器(java.exe)执行,小应用程序是由浏览器执行(如IE)
b.提到的编译器或解释器是哪来的呢?应该知道无论哪种语言的程序执行都有自身的运行环境,java语言是由SDK(software development kit也可叫jdk)平台支持,其提供了java虚拟机JVE(java virtual environment),包含运行环境和类加载器;还提供java编译器(javac.exe)和java解释器(java.exe)
c.目前Sun公司已发布了SDK的1.5
下载地址:http://www.javaresearch.org/members/jross/jdk/jdk-1_5_0-windows-i586.exe
如果你使用的windows NT(2000,xp等)操作系统,安装完SDK后还应该正确配置系统的环境变量
如果安装路径是c:\java\里,可如下配置,右键单击我的电脑->属性->高级->环境变量,然后选择系统变量里的"新建" 设置变量名为path 变量值为
c:\java\jdk1.5\bin; 确定,再选择"新建"设置变量名为classpath 变量值为c:\java\jdk1.5\jre\lib\rt.jar; 确定则配置完毕(一个是配置JVM运行
环境,一个是配置类路径)
(3)java开发的过程和运行环境都明白了之后可以先简单的编写一个程序来运行
a.应用程序:
(a)打开记事本输入
程序代码:
public class Hello
{
public static void main (String args[ ])
{
System.out.println("你好,很高兴学习Java");
}
}
保存为Hello.java(注意保存的名字必须是和主类的名字一样(包括大小写),所谓主类就是包含main方法的类)
(b).按住"窗口+R"组合键打开运行窗口输入cmd进入dos界面转换盘符到刚刚java文件保存路径(例如保存在D盘,输入 D: 回车 )然有执行命令
javac Hello.java 回车.这时会发现在和Hello.java同一个文件夹下生成了Hello.class 字节码文件,因为上面是一个应用程序的格式所以可以通过
java解释器来生成应用程序.继续输入java Hello 回车.屏幕会显示"你好,很高兴学习Java"
b.小应用程序
(a)打开记事本输入
程序代码:
import java.applet.*;
import java.awt.*;
public class Boy extends Applet //entends代表Boy继承了小应用程序Applet类
{
public void paint(Graphics g)
{ g.setColor(Color.red);
g.drawString("我一边喝着咖啡,一边学Java呢",5,30);
g.setColor(Color.blue);
g.drawString("我学得很认真",10,50);
}
}
保存为Boy.java
(b)操作同理到生成Boy.class文件,应为程序的可是可以看出是属于小应用程序的,所以必须在浏览器中执行,众所周知浏览器只能加载网页文件(如html,xml,asp,php等 )所以要把boy.class下载网页文件中,新打开一个记事本,输入
程序代码:
保存为以.html结尾的文件(注意上述的.java或.class或.html文件都是在一个目录下),然后打开此网页文件即可预览
总结:第一节课主要简单的介绍了java的产生背景及其特点,并且从运行原理上引导大家来如何编写并运行java程序
1. java 语言的诞生和特点(一般的教材都会有很详细的叙述,略)
2. java 学习的起步
(1)Sun公司要实现“编写一次,到处运行”(Write once,run anywhere)的目标,必须提供相应的Java运行平台,目前Java运行平台主要分为3个版本:J2SE(标准平台),J2EE(企业平台),J2ME(移动平台)
(2)学习Java必须从J2SE开始,当然得从了解在标准平台(J2SE)上是如何开发程序开始.
a.首先从源文件(以.java结尾的文件)开始----经过java编译器(javac.exe)编译----生成字节码文件----根据内文件的本质再可以再产生两种文件:java应用 程序(application) 和 java小应用程序(applet);应用程序是由于java解释器(java.exe)执行,小应用程序是由浏览器执行(如IE)
b.提到的编译器或解释器是哪来的呢?应该知道无论哪种语言的程序执行都有自身的运行环境,java语言是由SDK(software development kit也可叫jdk)平台支持,其提供了java虚拟机JVE(java virtual environment),包含运行环境和类加载器;还提供java编译器(javac.exe)和java解释器(java.exe)
c.目前Sun公司已发布了SDK的1.5
下载地址:http://www.javaresearch.org/members/jross/jdk/jdk-1_5_0-windows-i586.exe
如果你使用的windows NT(2000,xp等)操作系统,安装完SDK后还应该正确配置系统的环境变量
如果安装路径是c:\java\里,可如下配置,右键单击我的电脑->属性->高级->环境变量,然后选择系统变量里的"新建" 设置变量名为path 变量值为
c:\java\jdk1.5\bin; 确定,再选择"新建"设置变量名为classpath 变量值为c:\java\jdk1.5\jre\lib\rt.jar; 确定则配置完毕(一个是配置JVM运行
环境,一个是配置类路径)
(3)java开发的过程和运行环境都明白了之后可以先简单的编写一个程序来运行
a.应用程序:
(a)打开记事本输入
程序代码:
public class Hello
{
public static void main (String args[ ])
{
System.out.println("你好,很高兴学习Java");
}
}
保存为Hello.java(注意保存的名字必须是和主类的名字一样(包括大小写),所谓主类就是包含main方法的类)
(b).按住"窗口+R"组合键打开运行窗口输入cmd进入dos界面转换盘符到刚刚java文件保存路径(例如保存在D盘,输入 D: 回车 )然有执行命令
javac Hello.java 回车.这时会发现在和Hello.java同一个文件夹下生成了Hello.class 字节码文件,因为上面是一个应用程序的格式所以可以通过
java解释器来生成应用程序.继续输入java Hello 回车.屏幕会显示"你好,很高兴学习Java"
b.小应用程序
(a)打开记事本输入
程序代码:
import java.applet.*;
import java.awt.*;
public class Boy extends Applet //entends代表Boy继承了小应用程序Applet类
{
public void paint(Graphics g)
{ g.setColor(Color.red);
g.drawString("我一边喝着咖啡,一边学Java呢",5,30);
g.setColor(Color.blue);
g.drawString("我学得很认真",10,50);
}
}
保存为Boy.java
(b)操作同理到生成Boy.class文件,应为程序的可是可以看出是属于小应用程序的,所以必须在浏览器中执行,众所周知浏览器只能加载网页文件(如html,xml,asp,php等 )所以要把boy.class下载网页文件中,新打开一个记事本,输入
程序代码:
保存为以.html结尾的文件(注意上述的.java或.class或.html文件都是在一个目录下),然后打开此网页文件即可预览
总结:第一节课主要简单的介绍了java的产生背景及其特点,并且从运行原理上引导大家来如何编写并运行java程序
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第二节课
标识符 关键字及数据类型
1.标识符: 用来表示类名,变量名,方法名,类型名,数组名,文件名的有效字符序列.
特点:java语言规定标识符由字母,下划线,美元符号和数字组成,并且第一个字符不能是数字字符.
java语言使用unicode标准字符集其包含65536个字符,比C和C++所使用的ASCII码多很多.
2.关键字:编程语言中已经被赋予特定意义的一些单词,不能把这类词作为名字来用,具体的关键字书上列举的很全,略.
3.数据类型
逻辑类型: boolean 用ture(真)和false(假)来赋值,没有赋值默认情况时表示false
整数类型:
(1) int型变量,内存分配4个字节的空间,即32位的空间,所以可以表示-2^31到2^31-1的整数,例如int x=10;
(2) byte型变量,内存分配1个字节的空间,范围从-2^7到2^7-1,例如byte x=127
(3) short型变量,内存分配2个字节的空间,范围从-2^15到2^15-1,例如short x=1000
(4) long型变量,内存分配8个字节的空间,范围从-2^63到2^63-1,例如long x=700000;
字符类型:
(1)常量:java使用unicode字符集,所以字符表中的每个字符都是一个字符常量,用单引号括上,例如'A','你','あ'
注意有些字符不能通过键盘直接输入到字符串中或程序中,这时就需要转意字符常量,例如:'\n'(换行),'\b'(退格),'\''(单引号)等等.
(2)变量:通过关键字char来定义字符变量
char型变量,内存分配2个字节的空间,因为是字符不存在负数的概念,所以范围从0到2^16-1(即65535),例如char name='刘',grade='A'
如果要查一个字符在unicode字符集里的顺序位置,必须使用int类型转换,如(int)'A',但不可以用short型转换(范围只有一半);同样道理如果想得到一个在0到65535之间的数字在unicode字符集中所对应的字符必须使用char型转换,如(char)30000.具体含义理解如下面代码
程序代码:
public class Sign_Num
{ public static void main (String args[ ])
{ char chinaWord='你',japanWord='ぁ';
int p1=36328,p2=38358;
System.out.println("汉字\'你\'在unicode表中的顺序位置:"+(int)chinaWord);
System.out.println("日语\'ぁ\'在unicode表中的顺序位置:"+(int)japanWord);
System.out.println("unicode表中第20328位置上的字符是:"+(char)p1);
System.out.println("unicode表中第12358位置上的字符是:"+(char)p2);
}
}
除了char以外还要稍微介绍一下String,在C或C++中,String是一个以空为终结的字符数组,而在java中它是java.lang包中的String类来创建一个字符串变量,因此字符串变量是一个对象.String的具体介绍在后面会学习到.
浮点类型:
(1)float型 内存分配4个字节,占32位,范围从10^-38到10^38 和 -10^38到-10^-38
例float x=123.456f,y=2e20f; 注意float型定义的数据末尾必须有"f",为了和double区别
(2)double型 内存分配8个字节,范围从10^-308到10^308 和 -10^-308到-10^-308
例double x=1234567.98,y=8980.09d; 末尾可以有"d"也可以不写
基本数据类型转换:
类型按精度从低到高:byte short int long float double
(1)当把级别低的变量赋值给级别高的变量时,系统自动完成数据类型的转换,例
int x=100;
float y;
y=x;
结果y的值应该是100.0
(2)当把级别高的变量赋值给级别低的变量时,必须使用显示类型转换运算,格式为类型名)要转换的值;例
int x=(int)23.89f;
结果x的值为23
所以强制转换运算可能导致精度的损失
(3)当把一个整数赋值给一个byte,short,int或long型变量时,不可以超出这些变量的取值范围,否则必须进行类型转换运算,例
byte a=(byte)128;
byte b=(byte)-129;//超出范围
结果a值为128,b值为127
用下面的代码来复习下:
程序代码:
public class Example2_2
{ public static void main (String args[ ])
{ int c=2200;
long d=8000;
float f;
double g=123456789.123456789;
c=(int)d;
f=(float)g; //导致精度的损失
System.out.print("c= "+c);
System.out.println(" d= "+d);
System.out.println("f= "+f);
System.out.println("g= "+g);
}
}
java中的数组
格式: 数组元素类型 数组名字[ ] 或
数组元素类型 [ ]数组名字 例
float boy[];
创建数组: 数组名字=new 数组元素的类型[数组元素的个数]; 例
boy=new float[2]; //意思是boy获得了两个用来存放float型数据的空间
注意:和C和C++不同的是java允许使用int型变量来指定数组大小,例
int size=30;
double number=new double[size];
程序代码复习数组:
程序代码:
public class Example2_3
{ public static void main(String args[])
{ int a[]={100,200,300};
int b[]={10,11,12,13,14,15,16};
b=a;
b[0]=123456;
System.out.println("数组a:"+a[0]+","+a[1]+","+a[2]);
System.out.println("数组b:"+b[0]+","+b[1]+","+b[2]);
System.out.println("数组b的长度:"+b.length);
}
}
总结:本节课把编程语言中的基础-关键字,数据类型等概念复习一遍,尤其是在java中的用法,为以后在使用变量的学习中做基础.
标识符 关键字及数据类型
1.标识符: 用来表示类名,变量名,方法名,类型名,数组名,文件名的有效字符序列.
特点:java语言规定标识符由字母,下划线,美元符号和数字组成,并且第一个字符不能是数字字符.
java语言使用unicode标准字符集其包含65536个字符,比C和C++所使用的ASCII码多很多.
2.关键字:编程语言中已经被赋予特定意义的一些单词,不能把这类词作为名字来用,具体的关键字书上列举的很全,略.
3.数据类型
逻辑类型: boolean 用ture(真)和false(假)来赋值,没有赋值默认情况时表示false
整数类型:
(1) int型变量,内存分配4个字节的空间,即32位的空间,所以可以表示-2^31到2^31-1的整数,例如int x=10;
(2) byte型变量,内存分配1个字节的空间,范围从-2^7到2^7-1,例如byte x=127
(3) short型变量,内存分配2个字节的空间,范围从-2^15到2^15-1,例如short x=1000
(4) long型变量,内存分配8个字节的空间,范围从-2^63到2^63-1,例如long x=700000;
字符类型:
(1)常量:java使用unicode字符集,所以字符表中的每个字符都是一个字符常量,用单引号括上,例如'A','你','あ'
注意有些字符不能通过键盘直接输入到字符串中或程序中,这时就需要转意字符常量,例如:'\n'(换行),'\b'(退格),'\''(单引号)等等.
(2)变量:通过关键字char来定义字符变量
char型变量,内存分配2个字节的空间,因为是字符不存在负数的概念,所以范围从0到2^16-1(即65535),例如char name='刘',grade='A'
如果要查一个字符在unicode字符集里的顺序位置,必须使用int类型转换,如(int)'A',但不可以用short型转换(范围只有一半);同样道理如果想得到一个在0到65535之间的数字在unicode字符集中所对应的字符必须使用char型转换,如(char)30000.具体含义理解如下面代码
程序代码:
public class Sign_Num
{ public static void main (String args[ ])
{ char chinaWord='你',japanWord='ぁ';
int p1=36328,p2=38358;
System.out.println("汉字\'你\'在unicode表中的顺序位置:"+(int)chinaWord);
System.out.println("日语\'ぁ\'在unicode表中的顺序位置:"+(int)japanWord);
System.out.println("unicode表中第20328位置上的字符是:"+(char)p1);
System.out.println("unicode表中第12358位置上的字符是:"+(char)p2);
}
}
除了char以外还要稍微介绍一下String,在C或C++中,String是一个以空为终结的字符数组,而在java中它是java.lang包中的String类来创建一个字符串变量,因此字符串变量是一个对象.String的具体介绍在后面会学习到.
浮点类型:
(1)float型 内存分配4个字节,占32位,范围从10^-38到10^38 和 -10^38到-10^-38
例float x=123.456f,y=2e20f; 注意float型定义的数据末尾必须有"f",为了和double区别
(2)double型 内存分配8个字节,范围从10^-308到10^308 和 -10^-308到-10^-308
例double x=1234567.98,y=8980.09d; 末尾可以有"d"也可以不写
基本数据类型转换:
类型按精度从低到高:byte short int long float double
(1)当把级别低的变量赋值给级别高的变量时,系统自动完成数据类型的转换,例
int x=100;
float y;
y=x;
结果y的值应该是100.0
(2)当把级别高的变量赋值给级别低的变量时,必须使用显示类型转换运算,格式为类型名)要转换的值;例
int x=(int)23.89f;
结果x的值为23
所以强制转换运算可能导致精度的损失
(3)当把一个整数赋值给一个byte,short,int或long型变量时,不可以超出这些变量的取值范围,否则必须进行类型转换运算,例
byte a=(byte)128;
byte b=(byte)-129;//超出范围
结果a值为128,b值为127
用下面的代码来复习下:
程序代码:
public class Example2_2
{ public static void main (String args[ ])
{ int c=2200;
long d=8000;
float f;
double g=123456789.123456789;
c=(int)d;
f=(float)g; //导致精度的损失
System.out.print("c= "+c);
System.out.println(" d= "+d);
System.out.println("f= "+f);
System.out.println("g= "+g);
}
}
java中的数组
格式: 数组元素类型 数组名字[ ] 或
数组元素类型 [ ]数组名字 例
float boy[];
创建数组: 数组名字=new 数组元素的类型[数组元素的个数]; 例
boy=new float[2]; //意思是boy获得了两个用来存放float型数据的空间
注意:和C和C++不同的是java允许使用int型变量来指定数组大小,例
int size=30;
double number=new double[size];
程序代码复习数组:
程序代码:
public class Example2_3
{ public static void main(String args[])
{ int a[]={100,200,300};
int b[]={10,11,12,13,14,15,16};
b=a;
b[0]=123456;
System.out.println("数组a:"+a[0]+","+a[1]+","+a[2]);
System.out.println("数组b:"+b[0]+","+b[1]+","+b[2]);
System.out.println("数组b的长度:"+b.length);
}
}
总结:本节课把编程语言中的基础-关键字,数据类型等概念复习一遍,尤其是在java中的用法,为以后在使用变量的学习中做基础.
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第三节课
运算符 表达式和语句
因为大家肯定都学过C或C++的,所以这部分的内容自己可以回忆,都是一样的,略.
类和对象
1.类:类是组成java程序的基本要素.类封装了一类对象的状态和方法.类是用来定义对象的模板.
类的实现包括两个部分:类声明和类体.基本格式为:
程序代码:
class 类名
{
类体的内容
}
其中class是关键字,用来类定义."class 类名"是类的声明部分,类名必须是合法的java标识符,{}之间的内容是类
体,由变量的定义和方法(函数)的定义组成.
所谓变量定义,如int x或 intx=10;
但不能出现除声明以外的变量操作语句,如 int x; x=10;//是错误的
(1)变量:成员变量和局部变量
a.成员变量在整个类内都有效,局部变量只在定义它的方体体内有效.例:
程序代码:
class Sun
{ int distance;
int find()
{int a=12;
distance=a;//合法,distance是成员变量在整个类内有效
return distance;
}
void g()
{inty;
y=a; //非法,a是局部变量,不在find()中就会失效
}
}
注意:成员变量在它在类中书写的先后位置无关.但不提倡把成员变量的定义分散的写在方法之间或类体的后面.
b.成员变量又分为实例成员变量(实例变量)和类成员变量(类变量)
类变量是指变量类型前加关键字 static 的成员变量,也称为静态变量.例:
程序代码:
class Sun
{float x; //实例变量
static int y; //类变量
}
c.当局部变量与成员变量名字相同时,则成员变量被隐藏,即这个成员变量在这个方法内暂时失效,例:
程序代码:
class Tom
{int x=90,y;
void f()
{int x=3;
y=x; //y得到的值应是3,因为成员变量x=90与y在此方法体里失效
}
}
但如果想在方法体内使用成员变量则通过关键字 this 来实现,例:
程序代码:
class 三角形
{float sideA,sideB,sideC,lengthSum;
void setside(float sideA,float sideB,float sideC)
{this.sideA=sideA; http://this.sideA表示成员变量sideA
this.sideB=sideB;
this.sideC=sideC;
}
}
(2)方法
方法即是函数,包括声明和定义,在类体中是函数的定义,与C或C++中函数的声明或定义格式是一样的.
a.类方法和实例方法
实例方法即在方法返回值类型前加上关键字static,例:
程序代码:
class A
{int a;
float max(float a,float b)//实例方法
{//...}
static float min()//类方法
{//...}
}
[code]
b.方法的重载
方法的重载定义为多个函数定义时函数名必须相同,参数的类型和个数必须不同.例:
[code]
class Area
{float getArea(float r)
{return 3.14*r*r;}
double getArea(float x,int y)
{return x*y;}
float getArea(float x,float y)
{return x+y;}
double getArea(float x,float y,float z)
{return x*y*z*0.2;}
}
注意:在函数的重载中方法的返回值类型和参数的名字不参加比较.
c.构造方法
构在方法是一种特殊方法,它的名字必须与类名完全相同,而且没有类型,构造方法也可以重载的.
用法:一般用类创建对象时,使用构在方法,后面会有详细说明.
程序代码:
class 梯形
{float 上底,下底,高;
梯形()
{上底=60;
下底=100;
高=20}
梯形(float x,float y,float z)
{上底=x;
下底=y;
高=z;
}
}
2.对象
类是创建对象的模板.当使用一个类创建了一个对象时,也就是说给出了这个类的一个实例.
(1)对象的创建:包括对象的声明和为对象分配内存空间
声明格式: 类的名字 对象的名字;
分配内存空间格式; 类的名字 对象的名字=new 类的名字(); 例:
程序代码:
class XiyoujiRenwu
{ float height,weight;
String head, ear,hand,foot, mouth;
void speak(String s)
{ System.out.println(s);
}
}
class A
{ public static void main(String args[])
{ XiyoujiRenwu zhubajie; //声明对象
zhubajie=new XiyoujiRenwu(); //为对象分配内存,使用new 运算符和默认的构造方法
}
}
程序代码:
class Point
{ int x,y;
Point(int a,int b)
{ x=a;
y=b;
}
}
public class A
{ public static void main(String args[])
{ Point p1,p2,p3; //声明对象p1和p2
p1=new Point(10,10); //为对象分配内存,使用 new 和类中的构造方法
p2=new Point(23,35); //为对象分配内存,使用 new 和类中的构造方法
// p3=new Point(); 错误语句!当类中定义了一个或多个构造方法,那么java不提供默认的构造方法
}
}
(2)对象的内存模型
声明对象时,内存不分配空间,只存在一个空对象;当用new 分配内存空间时,类中的成员变量就会被分配到相应的空
间中,并通过构造方法(如果有)初始化,函数的入口地址也会被载入内存.但此时局部变量不会被分配内存空间,只有
当对象调用类中的函数时,函数中的局部变量才被分配空间,但函数执行完后,局部变量释放内存,所以如果在函数中
没有对局部变量进行初始化,就没有默认值,因此在使用局部变量之前,要事先为其赋值.
创建多个对象之间没有相互状态影响,个用个自的内存空间.
(3)对象的使用
对象不仅可以改变自己变量的状态,而且还拥有了使用创建它的那个类中的方法的能力,对象通过使用这些方法可以产生一定的行为.通过使用运算符" . "对象可以实现对自己的变量的访问和方法的调用.具体使用如程序例子:
程序代码:
class XiyoujiRenwu
{ float height,weight;
String head, ear,hand,foot,mouth;
void speak(String s)
{ head="歪着头";
System.out.println(s);
}
}
class Example4_3
{ public static void main(String args[])
{ XiyoujiRenwu zhubajie,sunwukong;//声明对象
zhubajie=new XiyoujiRenwu(); //为对象分配内存
sunwukong=new XiyoujiRenwu();
zhubajie.height=1.80f; //对象给自己的变量赋值
zhubajie.head="大头";
zhubajie.ear="一双大耳朵";
sunwukong.height=1.62f; //对象给自己的变量赋值
sunwukong.weight=1000f;
sunwukong.head="绣发飘飘";
System.out.println("zhubajie的身高:"+zhubajie.height);
System.out.println("zhubajie的头:"+zhubajie.head);
System.out.println("sunwukong的重量:"+sunwukong.weight);
System.out.println("sunwukong的头:"+sunwukong.head);
zhubajie.speak("俺老猪我想娶媳妇"); //对象调用方法
System.out.println("zhubajie现在的头:"+zhubajie.head);
sunwukong.speak("老孙我重1000斤,我想骗八戒背我"); //对象调用方法
System.out.println("sunwukong现在的头:"+sunwukong.head);
}
}
程序代码:
class 梯形
{ float 上底,下底,高,面积;
梯形(float x,float y,float h)
{ 上底=x;
下底=y;
高=h;
}
float 计算面积()
{ 面积=(上底+下底)*高/2.0f;
return 面积;
}
void 修改高(float height)
{ 高=height;
}
float 获取高()
{ return 高;
}
}
public class Example4_4
{ public static void main(String args[])
{ 梯形 laderOne=new 梯形(12.0f,3.5f,50),laderTwo=new 梯形(2.67f,3.0f,10);
System.out.println("laderOne的高是:"+laderOne.获取高());
System.out.println("laderTwo的高是:"+laderTwo.获取高());
System.out.println("laderOne的面积是:"+laderOne.计算面积());
System.out.println("laderTwo的面积是:"+laderTwo.计算面积());
laderOne.修改高(10);
float h=laderOne.获取高();
laderTwo.修改高(h*2);
System.out.println("laderOne现在的高是:"+laderOne.获取高());
System.out.println("laderTwo现在的高是:"+laderTwo.获取高());
System.out.println("laderOne现在的面积是:"+laderOne.计算面积());
System.out.println("laderTwo现在的面积是:"+laderTwo.计算面积());
}
}
总结:介绍了类和对象及通过类体中的变量和方法来实现对对象的应用
运算符 表达式和语句
因为大家肯定都学过C或C++的,所以这部分的内容自己可以回忆,都是一样的,略.
类和对象
1.类:类是组成java程序的基本要素.类封装了一类对象的状态和方法.类是用来定义对象的模板.
类的实现包括两个部分:类声明和类体.基本格式为:
程序代码:
class 类名
{
类体的内容
}
其中class是关键字,用来类定义."class 类名"是类的声明部分,类名必须是合法的java标识符,{}之间的内容是类
体,由变量的定义和方法(函数)的定义组成.
所谓变量定义,如int x或 intx=10;
但不能出现除声明以外的变量操作语句,如 int x; x=10;//是错误的
(1)变量:成员变量和局部变量
a.成员变量在整个类内都有效,局部变量只在定义它的方体体内有效.例:
程序代码:
class Sun
{ int distance;
int find()
{int a=12;
distance=a;//合法,distance是成员变量在整个类内有效
return distance;
}
void g()
{inty;
y=a; //非法,a是局部变量,不在find()中就会失效
}
}
注意:成员变量在它在类中书写的先后位置无关.但不提倡把成员变量的定义分散的写在方法之间或类体的后面.
b.成员变量又分为实例成员变量(实例变量)和类成员变量(类变量)
类变量是指变量类型前加关键字 static 的成员变量,也称为静态变量.例:
程序代码:
class Sun
{float x; //实例变量
static int y; //类变量
}
c.当局部变量与成员变量名字相同时,则成员变量被隐藏,即这个成员变量在这个方法内暂时失效,例:
程序代码:
class Tom
{int x=90,y;
void f()
{int x=3;
y=x; //y得到的值应是3,因为成员变量x=90与y在此方法体里失效
}
}
但如果想在方法体内使用成员变量则通过关键字 this 来实现,例:
程序代码:
class 三角形
{float sideA,sideB,sideC,lengthSum;
void setside(float sideA,float sideB,float sideC)
{this.sideA=sideA; http://this.sideA表示成员变量sideA
this.sideB=sideB;
this.sideC=sideC;
}
}
(2)方法
方法即是函数,包括声明和定义,在类体中是函数的定义,与C或C++中函数的声明或定义格式是一样的.
a.类方法和实例方法
实例方法即在方法返回值类型前加上关键字static,例:
程序代码:
class A
{int a;
float max(float a,float b)//实例方法
{//...}
static float min()//类方法
{//...}
}
[code]
b.方法的重载
方法的重载定义为多个函数定义时函数名必须相同,参数的类型和个数必须不同.例:
[code]
class Area
{float getArea(float r)
{return 3.14*r*r;}
double getArea(float x,int y)
{return x*y;}
float getArea(float x,float y)
{return x+y;}
double getArea(float x,float y,float z)
{return x*y*z*0.2;}
}
注意:在函数的重载中方法的返回值类型和参数的名字不参加比较.
c.构造方法
构在方法是一种特殊方法,它的名字必须与类名完全相同,而且没有类型,构造方法也可以重载的.
用法:一般用类创建对象时,使用构在方法,后面会有详细说明.
程序代码:
class 梯形
{float 上底,下底,高;
梯形()
{上底=60;
下底=100;
高=20}
梯形(float x,float y,float z)
{上底=x;
下底=y;
高=z;
}
}
2.对象
类是创建对象的模板.当使用一个类创建了一个对象时,也就是说给出了这个类的一个实例.
(1)对象的创建:包括对象的声明和为对象分配内存空间
声明格式: 类的名字 对象的名字;
分配内存空间格式; 类的名字 对象的名字=new 类的名字(); 例:
程序代码:
class XiyoujiRenwu
{ float height,weight;
String head, ear,hand,foot, mouth;
void speak(String s)
{ System.out.println(s);
}
}
class A
{ public static void main(String args[])
{ XiyoujiRenwu zhubajie; //声明对象
zhubajie=new XiyoujiRenwu(); //为对象分配内存,使用new 运算符和默认的构造方法
}
}
程序代码:
class Point
{ int x,y;
Point(int a,int b)
{ x=a;
y=b;
}
}
public class A
{ public static void main(String args[])
{ Point p1,p2,p3; //声明对象p1和p2
p1=new Point(10,10); //为对象分配内存,使用 new 和类中的构造方法
p2=new Point(23,35); //为对象分配内存,使用 new 和类中的构造方法
// p3=new Point(); 错误语句!当类中定义了一个或多个构造方法,那么java不提供默认的构造方法
}
}
(2)对象的内存模型
声明对象时,内存不分配空间,只存在一个空对象;当用new 分配内存空间时,类中的成员变量就会被分配到相应的空
间中,并通过构造方法(如果有)初始化,函数的入口地址也会被载入内存.但此时局部变量不会被分配内存空间,只有
当对象调用类中的函数时,函数中的局部变量才被分配空间,但函数执行完后,局部变量释放内存,所以如果在函数中
没有对局部变量进行初始化,就没有默认值,因此在使用局部变量之前,要事先为其赋值.
创建多个对象之间没有相互状态影响,个用个自的内存空间.
(3)对象的使用
对象不仅可以改变自己变量的状态,而且还拥有了使用创建它的那个类中的方法的能力,对象通过使用这些方法可以产生一定的行为.通过使用运算符" . "对象可以实现对自己的变量的访问和方法的调用.具体使用如程序例子:
程序代码:
class XiyoujiRenwu
{ float height,weight;
String head, ear,hand,foot,mouth;
void speak(String s)
{ head="歪着头";
System.out.println(s);
}
}
class Example4_3
{ public static void main(String args[])
{ XiyoujiRenwu zhubajie,sunwukong;//声明对象
zhubajie=new XiyoujiRenwu(); //为对象分配内存
sunwukong=new XiyoujiRenwu();
zhubajie.height=1.80f; //对象给自己的变量赋值
zhubajie.head="大头";
zhubajie.ear="一双大耳朵";
sunwukong.height=1.62f; //对象给自己的变量赋值
sunwukong.weight=1000f;
sunwukong.head="绣发飘飘";
System.out.println("zhubajie的身高:"+zhubajie.height);
System.out.println("zhubajie的头:"+zhubajie.head);
System.out.println("sunwukong的重量:"+sunwukong.weight);
System.out.println("sunwukong的头:"+sunwukong.head);
zhubajie.speak("俺老猪我想娶媳妇"); //对象调用方法
System.out.println("zhubajie现在的头:"+zhubajie.head);
sunwukong.speak("老孙我重1000斤,我想骗八戒背我"); //对象调用方法
System.out.println("sunwukong现在的头:"+sunwukong.head);
}
}
程序代码:
class 梯形
{ float 上底,下底,高,面积;
梯形(float x,float y,float h)
{ 上底=x;
下底=y;
高=h;
}
float 计算面积()
{ 面积=(上底+下底)*高/2.0f;
return 面积;
}
void 修改高(float height)
{ 高=height;
}
float 获取高()
{ return 高;
}
}
public class Example4_4
{ public static void main(String args[])
{ 梯形 laderOne=new 梯形(12.0f,3.5f,50),laderTwo=new 梯形(2.67f,3.0f,10);
System.out.println("laderOne的高是:"+laderOne.获取高());
System.out.println("laderTwo的高是:"+laderTwo.获取高());
System.out.println("laderOne的面积是:"+laderOne.计算面积());
System.out.println("laderTwo的面积是:"+laderTwo.计算面积());
laderOne.修改高(10);
float h=laderOne.获取高();
laderTwo.修改高(h*2);
System.out.println("laderOne现在的高是:"+laderOne.获取高());
System.out.println("laderTwo现在的高是:"+laderTwo.获取高());
System.out.println("laderOne现在的面积是:"+laderOne.计算面积());
System.out.println("laderTwo现在的面积是:"+laderTwo.计算面积());
}
}
总结:介绍了类和对象及通过类体中的变量和方法来实现对对象的应用
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第四节课
static的用法和包
上次课提到了static关键字,下面介绍一下具体的用法
1.实例变量和类变量
我们已经知道一个类可以使用new关键字可以创建多个不同的对象,这些对象被分配不同的内存空间.具体说的话,不同的对象的实例变量将被分配不同的内存空间,如果类中的成员变量有类变量,那么所有对象的这个类变量都分配分配给相同的一处内存,改变其中一个对象的这个类变量会影响其他对象的这个类变量,也就是说对象共享类变量.如
程序代码:
class Takecare
{
static int x;
int y;
}
class A
{
Takecare A1=now Takecare();
Takecare A2=now Takecare();
//在此代码中如果给x赋值那么,A1.x 和A2.x指的是同一个内存空间,无论那个对象修改都是对一个x进行操作
}
当java程序执行时,类的字节码文件被加载到内存,如果该类没有创建对象,类的实例成员变量不会被分配内存.但是类中的类变量被加载到内存时,会被分配相应的内存空间.简单的说就是,没创建对象当类加载到内存时候,只有类变量(static)会被分配内存空间,只有创建对象时候实例变量才会被分配空间的.
像上面的例子里,在没有创建Takecare的对象时候,Takecare:是有空间的即此时可以访问的,当且仅当Takecare A1=now Takecare()时A1.y才会有内存空间.
通过下面的例子体会一下,不同的对象会共享一个底
程序代码:
class 梯形
{ float 上底,高;
static float 下底;
梯形(float x,float y,float h)
{ 上底=x; 下底=y; 高=h;
}
float 获取下底()
{ return 下底;
}
void 修改下底(float b)
{ 下底=b;
}
}
class Example4_7
{ public static void main(String args[])
{ 梯形 laderOne=new 梯形(3.0f,10.0f,20),laderTwo=new 梯形(2.0f,3.0f,10);
梯形.下底=200; //通过类名操作类变量
System.out.println("laderOne的下底:"+laderOne.获取下底());
System.out.println("laderTwo的下底:"+laderTwo.获取下底());
laderTwo.修改下底(60); //通过对象操作类变量
System.out.println("laderOne的下底:"+laderOne.获取下底());
System.out.println("laderTwo的下底:"+laderTwo.获取下底());
}
}
2.实例方法和类方法
和实例变量和类变量的描述时是一样,当类的字节码加载到内存是类方法的入口地址就会被加载到相应的内存空间,即此时可以访问;而当且只有创建对象之后,实例方法的入口地址才会被加载到内存中,这是才可以调用.
既然知道了实例方法和类方法开始生效的时间,可以知道他们可以调用何种类的成员变量:
1)类方法因为是在创建对象之前就已经生效了,这时候实例变量还没有被分配内存空间,只有类变量被分配了内存空间,所以类方法只能调用被分配内存空间的变量即类变量;
2)实例方法是在创建对象之后才开始生效的,这是无论是类变量还是实例变量都已经被分配了内存空间,所以实例方法生效后可以调用类变量和实例变量.
程序代码:
class Fibi
{ public static long fibinacii(int n)
{ long c=0;
if(n==1||n==2)
c=1;
else
c=fibinacii(n-1)+fibinacii(n-2);
return c;
}
}
public class Example4_8
{ public static void main(String args[])
{ System.out.println(Fibi.fibinacii(7));// 可见还没哟创建Fibi的对象时就可以调用fibinacii()方法,因为属于static修饰的类变量
}
}
包
包是java中有效的管理类的一个机制,包有类似于目录结构的层次结构.通过import关键字可以在程序中使用包
语法格式:
import<包名>.*; //包含包中的所有类
import<包名><类名>//包含包中的指定类
例如:
import java.awt.*; //包含java.awt包中的所有类
import java.awt.JButton;//包含java.awt包中的JButton类
既然知道了怎么使用,那如何制作包呢,可以通过关键字package声明包语句.package语句作为java源文件的一个条语句,指明该源文件定义的类的所在包.
语法格式:
package 包名;
如果源文件中省略了package语句,那么源文件中定义命名的类将被隐含的认为是无名包的一部分,即源文件中定义命名的类在同一个包中,但该报没有名字而已.
包还可以是一个合法的表示符,也可以是若干个标识符加"."分割而成,如
package sunrise;
package sunrise.com.cn
程序如果使用了包的语句,如
package desney.tom;
那么目录必须包含有如下结构,如
C:\cartoon\desney\tom
并且要将源文件保存在目录C:\cartoon\desney\tom中,才能使用这个包,然后编译源文件:
C:\cartoon\desney\tom\javac 源文件.java
或
jacac C:\cartoon\desney\tom\源文件.java
从一个例子体会此过程:
程序代码:
package desney.tom;
public class PrimNumber
{ public void getPrimnumber(int n)
{ int sum=0,i,j;
for(i=1;i<=n;i++)
{ for(j=2;j<=i/2;j++)
{ if(i%j==0)
break;
}
if(j>i/2)
System.out.print(" "+i);
}
}
public static void main(String args[])
{ PrimNumber p=new PrimNumber();
p.getPrimnumber(20);
}
}
保存上述源文件到C:\cartoon\desney\tom下,然后编译
C:\cartoon\desney\tom\javac PrimNumber.java
运行程序时必须到desney\tom的上一层目录cartoon中来运行,如
C:\cartoon\java desney.tom.PrimNumber
因为起了报名,类PrimNumber的全名应该为desney.tom.PrimNumber
导入这个包时也要注意名称
程序代码:
import desney.tom.PrimNumber;
所以用package可以把认可类都打包然后在其他程序中使用,于c或c++中的头文件有着相似的效果,差别就是java中的包里只能是类
注意:使用import可以导入包中的类.在编写源文件时,除了自己编写的类外,经常需要使用java提供的去多类,这些类可能不在一个包中.在学习java时,使用已经存在的类,避免一切从头做起,这是面向对象编程的一个重要方面.
总结:具体的把static修饰的变量和方法的使用方法做了介绍;对java中包有了初步认识
static的用法和包
上次课提到了static关键字,下面介绍一下具体的用法
1.实例变量和类变量
我们已经知道一个类可以使用new关键字可以创建多个不同的对象,这些对象被分配不同的内存空间.具体说的话,不同的对象的实例变量将被分配不同的内存空间,如果类中的成员变量有类变量,那么所有对象的这个类变量都分配分配给相同的一处内存,改变其中一个对象的这个类变量会影响其他对象的这个类变量,也就是说对象共享类变量.如
程序代码:
class Takecare
{
static int x;
int y;
}
class A
{
Takecare A1=now Takecare();
Takecare A2=now Takecare();
//在此代码中如果给x赋值那么,A1.x 和A2.x指的是同一个内存空间,无论那个对象修改都是对一个x进行操作
}
当java程序执行时,类的字节码文件被加载到内存,如果该类没有创建对象,类的实例成员变量不会被分配内存.但是类中的类变量被加载到内存时,会被分配相应的内存空间.简单的说就是,没创建对象当类加载到内存时候,只有类变量(static)会被分配内存空间,只有创建对象时候实例变量才会被分配空间的.
像上面的例子里,在没有创建Takecare的对象时候,Takecare:是有空间的即此时可以访问的,当且仅当Takecare A1=now Takecare()时A1.y才会有内存空间.
通过下面的例子体会一下,不同的对象会共享一个底
程序代码:
class 梯形
{ float 上底,高;
static float 下底;
梯形(float x,float y,float h)
{ 上底=x; 下底=y; 高=h;
}
float 获取下底()
{ return 下底;
}
void 修改下底(float b)
{ 下底=b;
}
}
class Example4_7
{ public static void main(String args[])
{ 梯形 laderOne=new 梯形(3.0f,10.0f,20),laderTwo=new 梯形(2.0f,3.0f,10);
梯形.下底=200; //通过类名操作类变量
System.out.println("laderOne的下底:"+laderOne.获取下底());
System.out.println("laderTwo的下底:"+laderTwo.获取下底());
laderTwo.修改下底(60); //通过对象操作类变量
System.out.println("laderOne的下底:"+laderOne.获取下底());
System.out.println("laderTwo的下底:"+laderTwo.获取下底());
}
}
2.实例方法和类方法
和实例变量和类变量的描述时是一样,当类的字节码加载到内存是类方法的入口地址就会被加载到相应的内存空间,即此时可以访问;而当且只有创建对象之后,实例方法的入口地址才会被加载到内存中,这是才可以调用.
既然知道了实例方法和类方法开始生效的时间,可以知道他们可以调用何种类的成员变量:
1)类方法因为是在创建对象之前就已经生效了,这时候实例变量还没有被分配内存空间,只有类变量被分配了内存空间,所以类方法只能调用被分配内存空间的变量即类变量;
2)实例方法是在创建对象之后才开始生效的,这是无论是类变量还是实例变量都已经被分配了内存空间,所以实例方法生效后可以调用类变量和实例变量.
程序代码:
class Fibi
{ public static long fibinacii(int n)
{ long c=0;
if(n==1||n==2)
c=1;
else
c=fibinacii(n-1)+fibinacii(n-2);
return c;
}
}
public class Example4_8
{ public static void main(String args[])
{ System.out.println(Fibi.fibinacii(7));// 可见还没哟创建Fibi的对象时就可以调用fibinacii()方法,因为属于static修饰的类变量
}
}
包
包是java中有效的管理类的一个机制,包有类似于目录结构的层次结构.通过import关键字可以在程序中使用包
语法格式:
import<包名>.*; //包含包中的所有类
import<包名><类名>//包含包中的指定类
例如:
import java.awt.*; //包含java.awt包中的所有类
import java.awt.JButton;//包含java.awt包中的JButton类
既然知道了怎么使用,那如何制作包呢,可以通过关键字package声明包语句.package语句作为java源文件的一个条语句,指明该源文件定义的类的所在包.
语法格式:
package 包名;
如果源文件中省略了package语句,那么源文件中定义命名的类将被隐含的认为是无名包的一部分,即源文件中定义命名的类在同一个包中,但该报没有名字而已.
包还可以是一个合法的表示符,也可以是若干个标识符加"."分割而成,如
package sunrise;
package sunrise.com.cn
程序如果使用了包的语句,如
package desney.tom;
那么目录必须包含有如下结构,如
C:\cartoon\desney\tom
并且要将源文件保存在目录C:\cartoon\desney\tom中,才能使用这个包,然后编译源文件:
C:\cartoon\desney\tom\javac 源文件.java
或
jacac C:\cartoon\desney\tom\源文件.java
从一个例子体会此过程:
程序代码:
package desney.tom;
public class PrimNumber
{ public void getPrimnumber(int n)
{ int sum=0,i,j;
for(i=1;i<=n;i++)
{ for(j=2;j<=i/2;j++)
{ if(i%j==0)
break;
}
if(j>i/2)
System.out.print(" "+i);
}
}
public static void main(String args[])
{ PrimNumber p=new PrimNumber();
p.getPrimnumber(20);
}
}
保存上述源文件到C:\cartoon\desney\tom下,然后编译
C:\cartoon\desney\tom\javac PrimNumber.java
运行程序时必须到desney\tom的上一层目录cartoon中来运行,如
C:\cartoon\java desney.tom.PrimNumber
因为起了报名,类PrimNumber的全名应该为desney.tom.PrimNumber
导入这个包时也要注意名称
程序代码:
import desney.tom.PrimNumber;
所以用package可以把认可类都打包然后在其他程序中使用,于c或c++中的头文件有着相似的效果,差别就是java中的包里只能是类
注意:使用import可以导入包中的类.在编写源文件时,除了自己编写的类外,经常需要使用java提供的去多类,这些类可能不在一个包中.在学习java时,使用已经存在的类,避免一切从头做起,这是面向对象编程的一个重要方面.
总结:具体的把static修饰的变量和方法的使用方法做了介绍;对java中包有了初步认识
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第五节课
继承与访问权限
继承的概念:
继承是一种由己有的类创建新类的机制.利用继承,可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加它自己的新的状态和行为.由继承而得到的类称为子类,被继承的类称为父亲.java不支持多重继承,即子类只能有一个父亲(有别于C++的语法).
子类:
在类的声明中,通过使用关键字extends来声明一个类的子类,格式为:
class 子类名 extends 父类名
{
//...
}
注:如果一个类声明中没有使用extends关键字,这个类被系统默认为是Object的直接子类,Object是java.lang包中的类
子类的继承性
所谓子类的继承父类的成员变量作为自己的一个成员变量,就好像它们是在子类中直接声明一样,可以被子类中自己声明的任何实例方法操作,也就是说,一个子类继承的成员应当是这个类的完全意义的成员,如果子类中声明的实例方法不能操作父类的某个成员变量,该成员变量就没有被子类继承;所谓子类继承父类的方法作为子类中的一个方法,就象它们在子类中直接声明一样,可以被子类中自己声明的任何实例方法调用.
1) 子类和父类在同一包中的继承性
如果子类和父类在同一包中,那么子类自然地继承了其父类中不是private的成员变量作为自己的成员变量,并自然地继承了其父类中不是private的成员方法作为自己的成员方法,继承的成员的访问权限保持不变. 例如:
程序代码:
class Father
{ private int money;
float weight,height;
String head;
void speak(String s)
{ System.out.println(s);
}
}
class Son extends Father
{ String hand,foot;
}
public class Example4_15
{ public static void main(String args[])
{ Son boy;
boy=new Son();
boy.weight=1.80f;
boy.height=120f;
boy.head="一个头";
boy.hand="两只手 ";
boy.foot="两只脚";
boy.speak("我是儿子");
System.out.println(boy.hand+boy.foot+boy.head+boy.weight+boy.height);
}
}
2)子类和父类不在同一个包中的继承性
如果子类和父类不在同一个包中,那么,子类继承了父亲的protected,public成员变量和成员方法作为子类的成员变量和方法,继承的成员或方法的访问权限保持不变.如果子类和父类和父类不在同一包中,子类不能继承父类的友好变量和友好方法.
上面提到的private,protected,public以及友好(friendly)等字眼就是访问权限,下面来讲解一下他们具体的意义
当一个类创建了一个对象之后,该对象可以通过"."运算符操作自己的变量,使用类中的方法,但对象操作自己变量和使用类中的方法是有一定限制的.所谓访问权限是指对象是否可以通过"."运算符作自己的变量或使用类中的方法.访问权限的修饰符有private,protected和public,都些都是java中的关键字,还有就是友好(friendly)但它不是关键字只是种默认时的权限.访问权限由高到低:public->protected->friendly->private
具体分析如下:
用关键字private修饰的成员变量和方法称为私有变量和方法.如
class room
{private float weight;
private float f(float a,float b){//....}
}
当在另外一个类中用类Tom创建一个对象后,该对象不能访问自己的私有变量和私有方法.如
class jerry
{void g()
{Tom cat=new Tom;
cat.weight=23f;//错误,因为weight被私有修饰,不可一被对象访问
cat.f(3f,4f);//错误,f()被private修饰,不能被使用
}
}
对于私有成员变量或方法,只有在本类中创建该类的对象时,这个对象才能访问自己的私有成员变量和类中的私有方法.如
程序代码:
class Example4_14//所有代码都包含在一个类中
{ private int money;
Example4_14()
{ money=2000;
}
private int getMoney()
{ return money;
}
public static void main(String args[])
{ Example4_14 exa=new Example4_14();
exa.money=3000;
int m=exa.getMoney();
System.out.println("money="+m);
}
}
当然如果类中只有变量是私有的,而能操作此变量的函数是共有的,就可以间接对此私有变量进行操作,如
程序代码:
class room
{private float weight;
float f(float weight){this.weight=weight;}//都在一个类中方法可以访问变量
}
class jerry
{void g()
{Tom cat=new Tom;
cat.f(23f);//正确,f()没有被private修饰可以访问,这样就间接的操作了weight,相当于cat.weight=23f;
}
}
公有关键字public顾名思义,是访问权限最大的了,只要被它修饰无论在哪里都可以访问到
class room
{public float weight;
public float f(float a,float b){//....}
}
class jerry
{void g()
{Tom cat=new Tom;
cat.weight=23f;//正确
cat.f(3f,4f);//正确
}
}
友好(friendly)的概念,即不被private,protected,public修饰的成员变量和方法被称为友好变量和友好方法,如.
class room
{float weight;//友好变量
float f(float a,float b){//....}//友好方法
}
当在另一个类中用类Tom创建了一个对象后,如果这个类与Tom类在同一个包中,那么该对象能访问自己的友好变量和友好方法.在任何一个与Tom同一个包中的类,也可以通过Tom类的类名访问Tom类的类友好成员变量和类友好方法.
假如jerry和Tom是同一个包中的类,那么下述jerry类中的cat.weight.cat.f(3,4)都是合法的
class jerry
{void g()
{Tom cat=new Tom;
cat.weight=23f;//正确
cat.f(3f,4f);//正确
}
}
受保护关键字protected的用法只有在继承中才能体现出来,就是为什么先把继承引出来的原因,可以看看上面继承时说的子类和父类不在同一包中时,只有public和protected修饰的变量和方法才可以被继承使用.除了在继承这点的区别,在同一包中时,用法和作用和友好是一摸一样的,注意体会一下.
来全面总结一下protected的用法:
一个类A中的protected成员变量和方法可以被它的直接子类和间接子类继承,比如B是A的子类,C是B的子类,D又是C的子类,那么B,C,D类都继承了A的protected的成员变量和方法.如果用D类在D本身创建了一个对象,那么该对象总是可以通过"."运算符访问继承的或者自己定义的protected变量和方法,但是,如果在另一个类中,比如Other类,用D类创建了一个对象object,该对象通过"."运算符访问protected变量和方法的权限如下所述:
1)子类D中亲自声明的protected成员变量和方法,不可能是从别的类继承来的,object访问这些非继承的protected成员变量和方法时,只要other类和D类在同一包中就可以了.
2)如果子类D的对象的protected成员变量或方法是从父类继承来的,那么就要一直追追述到该protected成员变量或方法的"祖先"类,即最先头的父类A,如果Other类和A类在同一包中,object对象能访问继承的protected变量或protected方法.
访问权限不只能修饰变量和成员还是可以修饰类的,但protected和private不可以
类声明时,如果关键字class前面加上public关键字,就称这样的类是一个public类,如
public class A
{//...}
可以在任何另外一个类中,使用public类创建对象.如果一个类不加public修饰,如
class A
{//...}
这样的类称为友好类,那么另外一个类中使用友好类创建对象时,要保证它们是在同一个包中
特别注意:不能用protected和private修饰类
总结:简单的引入了继承和访问权限的概念,重在体会,为下次课学习多态,抽象类以及接口打下基础.
继承与访问权限
继承的概念:
继承是一种由己有的类创建新类的机制.利用继承,可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加它自己的新的状态和行为.由继承而得到的类称为子类,被继承的类称为父亲.java不支持多重继承,即子类只能有一个父亲(有别于C++的语法).
子类:
在类的声明中,通过使用关键字extends来声明一个类的子类,格式为:
class 子类名 extends 父类名
{
//...
}
注:如果一个类声明中没有使用extends关键字,这个类被系统默认为是Object的直接子类,Object是java.lang包中的类
子类的继承性
所谓子类的继承父类的成员变量作为自己的一个成员变量,就好像它们是在子类中直接声明一样,可以被子类中自己声明的任何实例方法操作,也就是说,一个子类继承的成员应当是这个类的完全意义的成员,如果子类中声明的实例方法不能操作父类的某个成员变量,该成员变量就没有被子类继承;所谓子类继承父类的方法作为子类中的一个方法,就象它们在子类中直接声明一样,可以被子类中自己声明的任何实例方法调用.
1) 子类和父类在同一包中的继承性
如果子类和父类在同一包中,那么子类自然地继承了其父类中不是private的成员变量作为自己的成员变量,并自然地继承了其父类中不是private的成员方法作为自己的成员方法,继承的成员的访问权限保持不变. 例如:
程序代码:
class Father
{ private int money;
float weight,height;
String head;
void speak(String s)
{ System.out.println(s);
}
}
class Son extends Father
{ String hand,foot;
}
public class Example4_15
{ public static void main(String args[])
{ Son boy;
boy=new Son();
boy.weight=1.80f;
boy.height=120f;
boy.head="一个头";
boy.hand="两只手 ";
boy.foot="两只脚";
boy.speak("我是儿子");
System.out.println(boy.hand+boy.foot+boy.head+boy.weight+boy.height);
}
}
2)子类和父类不在同一个包中的继承性
如果子类和父类不在同一个包中,那么,子类继承了父亲的protected,public成员变量和成员方法作为子类的成员变量和方法,继承的成员或方法的访问权限保持不变.如果子类和父类和父类不在同一包中,子类不能继承父类的友好变量和友好方法.
上面提到的private,protected,public以及友好(friendly)等字眼就是访问权限,下面来讲解一下他们具体的意义
当一个类创建了一个对象之后,该对象可以通过"."运算符操作自己的变量,使用类中的方法,但对象操作自己变量和使用类中的方法是有一定限制的.所谓访问权限是指对象是否可以通过"."运算符作自己的变量或使用类中的方法.访问权限的修饰符有private,protected和public,都些都是java中的关键字,还有就是友好(friendly)但它不是关键字只是种默认时的权限.访问权限由高到低:public->protected->friendly->private
具体分析如下:
用关键字private修饰的成员变量和方法称为私有变量和方法.如
class room
{private float weight;
private float f(float a,float b){//....}
}
当在另外一个类中用类Tom创建一个对象后,该对象不能访问自己的私有变量和私有方法.如
class jerry
{void g()
{Tom cat=new Tom;
cat.weight=23f;//错误,因为weight被私有修饰,不可一被对象访问
cat.f(3f,4f);//错误,f()被private修饰,不能被使用
}
}
对于私有成员变量或方法,只有在本类中创建该类的对象时,这个对象才能访问自己的私有成员变量和类中的私有方法.如
程序代码:
class Example4_14//所有代码都包含在一个类中
{ private int money;
Example4_14()
{ money=2000;
}
private int getMoney()
{ return money;
}
public static void main(String args[])
{ Example4_14 exa=new Example4_14();
exa.money=3000;
int m=exa.getMoney();
System.out.println("money="+m);
}
}
当然如果类中只有变量是私有的,而能操作此变量的函数是共有的,就可以间接对此私有变量进行操作,如
程序代码:
class room
{private float weight;
float f(float weight){this.weight=weight;}//都在一个类中方法可以访问变量
}
class jerry
{void g()
{Tom cat=new Tom;
cat.f(23f);//正确,f()没有被private修饰可以访问,这样就间接的操作了weight,相当于cat.weight=23f;
}
}
公有关键字public顾名思义,是访问权限最大的了,只要被它修饰无论在哪里都可以访问到
class room
{public float weight;
public float f(float a,float b){//....}
}
class jerry
{void g()
{Tom cat=new Tom;
cat.weight=23f;//正确
cat.f(3f,4f);//正确
}
}
友好(friendly)的概念,即不被private,protected,public修饰的成员变量和方法被称为友好变量和友好方法,如.
class room
{float weight;//友好变量
float f(float a,float b){//....}//友好方法
}
当在另一个类中用类Tom创建了一个对象后,如果这个类与Tom类在同一个包中,那么该对象能访问自己的友好变量和友好方法.在任何一个与Tom同一个包中的类,也可以通过Tom类的类名访问Tom类的类友好成员变量和类友好方法.
假如jerry和Tom是同一个包中的类,那么下述jerry类中的cat.weight.cat.f(3,4)都是合法的
class jerry
{void g()
{Tom cat=new Tom;
cat.weight=23f;//正确
cat.f(3f,4f);//正确
}
}
受保护关键字protected的用法只有在继承中才能体现出来,就是为什么先把继承引出来的原因,可以看看上面继承时说的子类和父类不在同一包中时,只有public和protected修饰的变量和方法才可以被继承使用.除了在继承这点的区别,在同一包中时,用法和作用和友好是一摸一样的,注意体会一下.
来全面总结一下protected的用法:
一个类A中的protected成员变量和方法可以被它的直接子类和间接子类继承,比如B是A的子类,C是B的子类,D又是C的子类,那么B,C,D类都继承了A的protected的成员变量和方法.如果用D类在D本身创建了一个对象,那么该对象总是可以通过"."运算符访问继承的或者自己定义的protected变量和方法,但是,如果在另一个类中,比如Other类,用D类创建了一个对象object,该对象通过"."运算符访问protected变量和方法的权限如下所述:
1)子类D中亲自声明的protected成员变量和方法,不可能是从别的类继承来的,object访问这些非继承的protected成员变量和方法时,只要other类和D类在同一包中就可以了.
2)如果子类D的对象的protected成员变量或方法是从父类继承来的,那么就要一直追追述到该protected成员变量或方法的"祖先"类,即最先头的父类A,如果Other类和A类在同一包中,object对象能访问继承的protected变量或protected方法.
访问权限不只能修饰变量和成员还是可以修饰类的,但protected和private不可以
类声明时,如果关键字class前面加上public关键字,就称这样的类是一个public类,如
public class A
{//...}
可以在任何另外一个类中,使用public类创建对象.如果一个类不加public修饰,如
class A
{//...}
这样的类称为友好类,那么另外一个类中使用友好类创建对象时,要保证它们是在同一个包中
特别注意:不能用protected和private修饰类
总结:简单的引入了继承和访问权限的概念,重在体会,为下次课学习多态,抽象类以及接口打下基础.
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第六节课
多态与抽象类
多态是java中一个比较重要的概念,在认识和理解它之前先熟悉一下下面的几个概念.
1.成员变量的隐藏和方法的重写
成员变量的隐藏:子类可以隐藏继承的成员变量,对于子类可以从父类继承成员变量,只要子类中定义的成员变量和父类中的成员变量
同名时,子类就隐藏了继承的成员变量.但不提倡这种做法,子类总是自己定义变量而隐藏父类的变量,这样会浪费很多空间.
方法的重写:子类可以隐藏已继承的方法,子类通过方法重写来隐藏继承的方法.具体是指,子类中定义一个方法,并且这个方法的名字
,返回值类型,参数个数和类型与父类继承的方法完全相同.
注意:方法的重写与方法的重载要分清楚,回顾一下方法的重载的定义为方法名必须相同,参数的类型和个数必须不同.
用下面的程序好好体会一下方法的重写(还有重载)
程序代码:
class Chengji
{ float f(float x,float y)
{ return x*y;
}
}
class Xiangjia extends Chengji
{
float f(float x,float y) //方法的重写,方法的名字,返回值类型,参数个数和类型与父类完全相同
{ return x+y ;
}
//float f(float,x,int y) {return x-y;}错误的语句,在方法名相同的情况下既不属于"重写"也不属于"重载"
//float f(int x,int y,int z){z=x-y; return z;}方法的重写,琢磨一下定义就知道了
}
public class Example
{ public static void main(String args[])
{ Xiangjia sum;
sum=new Xiangjia();
float c=sum.f(4,6);//调用的是子类里的f(),因为子类重写了父类的f()
//c=sum.f(1,2,3); 这个则是调用了重载的函数;当然具体调用那个要根据实参的个数和类型来判断喽
System.out.println(c);
}
}
如果没有重写父类的方法,那使用父类中的方法时就正常使用,看看下面这个混合使用的例子
程序代码:
class Area
{ float f(float r )
{ return 3.14159f*r*r;
}
float g(float x,float y)
{ return x+y;
}
}
class Circle extends Area
{ float f(float r)
{ return 3.14159f*2.0f*r;//重写
}
}
public class Example4_17
{ public static void main(String args[])
{ Circle yuan;
yuan=new Circle();
float length=yuan.f(5.0f);
float sum=yuan.g(232.645f,418.567f); //父类中的方法正常使用
System.out.println(length);
System.out.println(sum);
}
}
注意:重写父类的方法时,不可以降低方法的访问权限.下面的例子中,子类重写父类的方法f,该方法在父类中的访问权限实protected
级别,子类重写时不允许级别低于protected级别.
程序代码:
class Chengji
{
protected float f(float x,float y)
{return x*y;}
}
class Xiangjia extends Chengji
{
float f(float x,float y)//错误,friendly的权限低于protected
{return x+y;}
}
class Xiangjian extends Chengji
{
public float f(float x,float y)//正确,public的权限高于protected
{return x-y;}
}
子类重写了父类中的方法后也有办法访问被隐藏的父类的方法的,这就要引入super关键字了
1).使用关键字super调用父类的构造方法
子类不继承父类的构造方法,因此,子类如果想使用父类的构造方法,必须在子类的构造方法中使用,并且必须使用关键字super来表示
,而且super必须是子类构造方法中的头一条语句.例如:
程序代码:
class Student
{ int number;String name;
Student()
{
}
Student(int number,String name)//父类的构造方法
{ this.number=number;
this.name=name;
System.out.println("I am "+name+ "my number is "+number);
}
}
class Univer_Student extends Student
{ boolean 婚否;
Univer_Student(int number,String name,boolean b) //子类的构造方法
{ super(number,name);//子类构造方法中的第一条语句
婚否=b;
System.out.println("婚否="+婚否);
}
}
public class Example4_23
{ public static void main(String args[])
{ Univer_Student zhang=new Univer_Student(9901,"和晓林",false);
}
}
注意:如果在子类的构造方法中,没有使用关键字super调用父类的某个构造方法,那么默认有super();语句,即调用父类不带参数的构
造方法.
如果类里定义一个或多个构造方法,那么java不提供默认的构造方法(不带参数的构造方法),因此,当在父类中定义多个构造方法时,
应当包括一个不带参数的构造方法,以防子类省略super时出现错误.
2).使用关键字super操作被隐藏的成员变量和方法
如果在子类中想使用被子类隐藏了的父类的成员变量或方法就可以使用关键字super.比如super.x,super.play(),就是被子类隐藏的
父类的成员变量x和方法play().例如
程序代码:
class Sum
{ int n;
float f()
{ float sum=0;
for(int i=1;i<=n;i++)
sum=sum+i;
return sum;
}
}
class Average extends Sum
{ int n;
float f()
{ float c;
super.n=n;//调用被隐藏的父类中的变量n
c=super.f();//调用父类中被隐藏的方法f()
return c/n;
}
float g()
{ float c;
c=super.f();//调用父类中被隐藏的方法f()
return c/2;
}
}
public class Example
{ public static void main(String args[])
{ Average aver=new Average();
aver.n=100;
float result_1=aver.f();
float result_2=aver.g();
System.out.println("result_1="+result_1);
System.out.println("result_2="+result_2);
}
}
2.对象的上转型对象(具体用途在抽象类中体现出来)
我们经常说"老虎是哺乳动物","狗是哺乳动物"等.若哺乳类是老虎类的父类,这样说当然正确,但当说老虎是哺乳动物时,老虎讲失掉老虎独有的属性和功能.下面就介绍对象的上转型对象.
假设B类是A类的子类或间接子类,当用子类B创建一个对象,并把这个对象的引用放到A类的对象中时,如
A a;
a=new B();
或
A a;
B b=new B();
a=b;
那么,称这个A类对象a是子类对象b的上转型对象(好比说:"老虎是哺乳动物").对象的上转型型对象的实体是子类负责创建的,但上转型对象会失去原来的一些功能.
上转型对象具有如下特点:
1)上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能使用子类新增的方法(失掉了一些功能).
2)上转型对象可以操作子类继承或隐藏的成员变量,也可以使用子类继承的或重写的方法.
3)上转型对象操作子类继承或重写的方法时,就时通知对应的子类对象去调用这些方法.因此,如果子类重写了父类的某个方法后,对象的上转型对象调用这个方法时,一定是调用了这个重写的方法.
4)可以讲对象的上转型对象再强制转换到一个子类的对象,这时,该子类对象又具备了子类的所有属性和功能.
注意:a.不要将父类创建的对象和子类对象的上转型对象混淆;b.不可以将父类创建的对象的引用赋值给子类声明的对象(不能说:"哺乳动物是老虎")
体会下面的例子来掌握上转型对象的概念
程序代码:
class 类人猿
{ private int n=100;
void crySpeak(String s)
{ System.out.println(s);
}
}
class People extends 类人猿
{ void computer(int a,int b)
{ int c=a*b;
System.out.println(c);
}
void crySpeak(String s)
{ System.out.println("**"+s+"**");
}
}
class Example
{ public static void main(String args[])
{ 类人猿 monkey=new People(); //把子类创建的对象赋给父类创建的对象monkey,则monkey现在就是一个上转型对象
monkey.crySpeak("I love this game");//monkey可以调用子类中继承或重写的方法
People people=(People)monkey; //把上转型对象强制转换为子类的对象,赋值子类创建的对象
people.computer(10,10);
}
}
3.final 关键字
final可以修饰类,成员变量,方法中的参数.如变量被其修饰后就相当于C++中常量的概念,不可以再对其更改
final类不可以被继承,即不能有子类,如
A就是一个final类.有时候出于安全性的考虑,将一些类修饰为final类.例如:java提供的String类,它对于编辑器和解释器的正常运行有很重要的作用,对它不能轻易改变.因此它被修饰为final类.
如果一个方法被修饰为final方法,则这个方法不可以被重写;
如果一个成员变量被修饰为final的,就是常量,常量必须赋初始值,而且不能再发生变化;
如果方法的参数被修饰为final的,该参数的值不能被改变.
体会下面的例子:
程序代码:
class A
{
final double PI=3.1415926;//变量PI为常量不可再被更改
public double getArea(final double r)//参数r被初始化后不可以被更改
{ //r=20;错误,r不可以被修改
return PI*r*r;
}
}
public class
{ public static void main(String args[])
{ A a=new A();
System.out.println("面积:"+a.getArea(100));
}
}
4.准备工作都做完了,下面让我们开始正式学习多态性
我们经常说:"哺乳动物有很多叫声",比如,"汪汪","喵喵","嚎","吼"等,这就是叫声的多态.
当一个类有很多子类时,并且这些子类都重写了父类中的某个方法.那么当把子类创建的对象的引用放到一个父类的对象中时,就得到
了该对象的一个上转型对象,那么这个上转的对象在调用这个方法时就可能具有多种形态,因为不同的子类在重写父类的方法时可能
产生不同的行为,比如,狗类的上转型对象调用"叫声"方法时产生的行为是"汪汪",而猫类的上转型对象调用"叫声"的方法时,产生的行为是"喵喵",等等.
多态性就是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为,下面的例子展示了多态性.
程序代码:
class 动物
{ void cry()
{
}
}
class 狗 extends 动物
{ void cry()//方法的重写
{ System.out.println("汪汪.....");
}
}
class 猫 extends 动物
{ void cry()//方法的重写
{ System.out.println("喵喵.....");
}
}
class Example4_20
{ public static void main(String args[])
{ 动物 dongwu;
dongwu=new 狗();
dongwu.cry();
dongwu=new 猫();
dongwu.cry();
}
}
5.抽象(abstract)类
用关键字abstract修饰的类称为抽象(abstract)类.如
abstract class A
{//...}
abstract类的几个特点:
1)abstract类中可以有abstract方法
与普通的类相比,abstract类可以有abstract方法.对于abstract方法,只允许声明,不允许实现,而且不允许使用final修饰abstract方法.下面的A类中的min()方法就是abstract方法
abstract class A
{ abstract int min(int x,int y);
int max(int x,int y)
{ return x>y?x:y;
}
}
注意:abstract类中也可以没有abstract方法
2)对于abstract类,不能使用new运算符创建该类的对象,需产生其子类,由子类创建对象,如果一个类是abstract类的子类,它必须具体实现abstract方法,这就是为什么不允许使用final修饰abstract方法的原因.体会一下下面的例子:
程序代码:
abstract class A
{ abstract int min(int x,int y);
int max(int x,int y)
{ return x>y?x:y;
}
}
class B extends A
{ int min(int x,int y) //子类中具体实现了min()的功能
{ return x }
}
public class Example
{ public static void main(String args[])
{ A a;
B b=new B();
int max=b.max(12,34);
int min=b.min(12,34);
System.out.println("max="+max+" min="+min);
a=b;
max=a.max(12,34);
System.out.println("max="+max);
}
}
一个abstract类只关心它的子类是否具有某种功能,并不关心功能的具体行为,功能的具体行为由子类负责实现,抽象类中的抽象方法可以强制子类必须给出这些方法的具体实现.理解下面的例子来充分学习抽象类.
程序代码:
abstract class 图形
{ public abstract double 求面积();//相当于给子类们发出了求面积的具体表现命令
}
class 梯形 extends 图形
{ double a,b,h;
梯形(double a,double b,double h)
{ this.a=a;
this.b=b;
this.h=h;
}
public double 求面积()//子类梯形类实现了求面积功能
{ return((1/2.0)*(a+b)*h);
}
}
class 圆形 extends 图形
{ double r;
圆形(double r)
{ this.r=r;
}
public double 求面积()//子类圆形类实现了求面积功能
{ return(3.14*r*r);
}
}
class 堆
{ 图形 底;//只是声明
double 高;
堆(图形 底,double 高)//调用时候就可以用上转型对象来解释为什么了
{ this.底=底;
this.高=高;
}
void 换底(图形 底)
{ this.底=底;
}
public double 求体积()
{ return (底.求面积()*高)/3.0;
}
}
public class Example
{ public static void main(String args[])
{ 堆 zui;
图形 tuxing;
tuxing=new 梯形(2.0,7.0,10.7);
System.out.println("梯形的面积"+tuxing.求面积());
zui=new 堆(tuxing,30);
System.out.println("梯形底的堆的体积"+zui.求体积());
tuxing=new 圆形(10);
System.out.println("半径是10的圆的面积"+tuxing.求面积());
zui.换底(tuxing);
System.out.println("圆形底的堆的体积"+zui.求体积());
}
}
总结:初步了解了多态性和抽象类及与其相关的概念.
多态与抽象类
多态是java中一个比较重要的概念,在认识和理解它之前先熟悉一下下面的几个概念.
1.成员变量的隐藏和方法的重写
成员变量的隐藏:子类可以隐藏继承的成员变量,对于子类可以从父类继承成员变量,只要子类中定义的成员变量和父类中的成员变量
同名时,子类就隐藏了继承的成员变量.但不提倡这种做法,子类总是自己定义变量而隐藏父类的变量,这样会浪费很多空间.
方法的重写:子类可以隐藏已继承的方法,子类通过方法重写来隐藏继承的方法.具体是指,子类中定义一个方法,并且这个方法的名字
,返回值类型,参数个数和类型与父类继承的方法完全相同.
注意:方法的重写与方法的重载要分清楚,回顾一下方法的重载的定义为方法名必须相同,参数的类型和个数必须不同.
用下面的程序好好体会一下方法的重写(还有重载)
程序代码:
class Chengji
{ float f(float x,float y)
{ return x*y;
}
}
class Xiangjia extends Chengji
{
float f(float x,float y) //方法的重写,方法的名字,返回值类型,参数个数和类型与父类完全相同
{ return x+y ;
}
//float f(float,x,int y) {return x-y;}错误的语句,在方法名相同的情况下既不属于"重写"也不属于"重载"
//float f(int x,int y,int z){z=x-y; return z;}方法的重写,琢磨一下定义就知道了
}
public class Example
{ public static void main(String args[])
{ Xiangjia sum;
sum=new Xiangjia();
float c=sum.f(4,6);//调用的是子类里的f(),因为子类重写了父类的f()
//c=sum.f(1,2,3); 这个则是调用了重载的函数;当然具体调用那个要根据实参的个数和类型来判断喽
System.out.println(c);
}
}
如果没有重写父类的方法,那使用父类中的方法时就正常使用,看看下面这个混合使用的例子
程序代码:
class Area
{ float f(float r )
{ return 3.14159f*r*r;
}
float g(float x,float y)
{ return x+y;
}
}
class Circle extends Area
{ float f(float r)
{ return 3.14159f*2.0f*r;//重写
}
}
public class Example4_17
{ public static void main(String args[])
{ Circle yuan;
yuan=new Circle();
float length=yuan.f(5.0f);
float sum=yuan.g(232.645f,418.567f); //父类中的方法正常使用
System.out.println(length);
System.out.println(sum);
}
}
注意:重写父类的方法时,不可以降低方法的访问权限.下面的例子中,子类重写父类的方法f,该方法在父类中的访问权限实protected
级别,子类重写时不允许级别低于protected级别.
程序代码:
class Chengji
{
protected float f(float x,float y)
{return x*y;}
}
class Xiangjia extends Chengji
{
float f(float x,float y)//错误,friendly的权限低于protected
{return x+y;}
}
class Xiangjian extends Chengji
{
public float f(float x,float y)//正确,public的权限高于protected
{return x-y;}
}
子类重写了父类中的方法后也有办法访问被隐藏的父类的方法的,这就要引入super关键字了
1).使用关键字super调用父类的构造方法
子类不继承父类的构造方法,因此,子类如果想使用父类的构造方法,必须在子类的构造方法中使用,并且必须使用关键字super来表示
,而且super必须是子类构造方法中的头一条语句.例如:
程序代码:
class Student
{ int number;String name;
Student()
{
}
Student(int number,String name)//父类的构造方法
{ this.number=number;
this.name=name;
System.out.println("I am "+name+ "my number is "+number);
}
}
class Univer_Student extends Student
{ boolean 婚否;
Univer_Student(int number,String name,boolean b) //子类的构造方法
{ super(number,name);//子类构造方法中的第一条语句
婚否=b;
System.out.println("婚否="+婚否);
}
}
public class Example4_23
{ public static void main(String args[])
{ Univer_Student zhang=new Univer_Student(9901,"和晓林",false);
}
}
注意:如果在子类的构造方法中,没有使用关键字super调用父类的某个构造方法,那么默认有super();语句,即调用父类不带参数的构
造方法.
如果类里定义一个或多个构造方法,那么java不提供默认的构造方法(不带参数的构造方法),因此,当在父类中定义多个构造方法时,
应当包括一个不带参数的构造方法,以防子类省略super时出现错误.
2).使用关键字super操作被隐藏的成员变量和方法
如果在子类中想使用被子类隐藏了的父类的成员变量或方法就可以使用关键字super.比如super.x,super.play(),就是被子类隐藏的
父类的成员变量x和方法play().例如
程序代码:
class Sum
{ int n;
float f()
{ float sum=0;
for(int i=1;i<=n;i++)
sum=sum+i;
return sum;
}
}
class Average extends Sum
{ int n;
float f()
{ float c;
super.n=n;//调用被隐藏的父类中的变量n
c=super.f();//调用父类中被隐藏的方法f()
return c/n;
}
float g()
{ float c;
c=super.f();//调用父类中被隐藏的方法f()
return c/2;
}
}
public class Example
{ public static void main(String args[])
{ Average aver=new Average();
aver.n=100;
float result_1=aver.f();
float result_2=aver.g();
System.out.println("result_1="+result_1);
System.out.println("result_2="+result_2);
}
}
2.对象的上转型对象(具体用途在抽象类中体现出来)
我们经常说"老虎是哺乳动物","狗是哺乳动物"等.若哺乳类是老虎类的父类,这样说当然正确,但当说老虎是哺乳动物时,老虎讲失掉老虎独有的属性和功能.下面就介绍对象的上转型对象.
假设B类是A类的子类或间接子类,当用子类B创建一个对象,并把这个对象的引用放到A类的对象中时,如
A a;
a=new B();
或
A a;
B b=new B();
a=b;
那么,称这个A类对象a是子类对象b的上转型对象(好比说:"老虎是哺乳动物").对象的上转型型对象的实体是子类负责创建的,但上转型对象会失去原来的一些功能.
上转型对象具有如下特点:
1)上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能使用子类新增的方法(失掉了一些功能).
2)上转型对象可以操作子类继承或隐藏的成员变量,也可以使用子类继承的或重写的方法.
3)上转型对象操作子类继承或重写的方法时,就时通知对应的子类对象去调用这些方法.因此,如果子类重写了父类的某个方法后,对象的上转型对象调用这个方法时,一定是调用了这个重写的方法.
4)可以讲对象的上转型对象再强制转换到一个子类的对象,这时,该子类对象又具备了子类的所有属性和功能.
注意:a.不要将父类创建的对象和子类对象的上转型对象混淆;b.不可以将父类创建的对象的引用赋值给子类声明的对象(不能说:"哺乳动物是老虎")
体会下面的例子来掌握上转型对象的概念
程序代码:
class 类人猿
{ private int n=100;
void crySpeak(String s)
{ System.out.println(s);
}
}
class People extends 类人猿
{ void computer(int a,int b)
{ int c=a*b;
System.out.println(c);
}
void crySpeak(String s)
{ System.out.println("**"+s+"**");
}
}
class Example
{ public static void main(String args[])
{ 类人猿 monkey=new People(); //把子类创建的对象赋给父类创建的对象monkey,则monkey现在就是一个上转型对象
monkey.crySpeak("I love this game");//monkey可以调用子类中继承或重写的方法
People people=(People)monkey; //把上转型对象强制转换为子类的对象,赋值子类创建的对象
people.computer(10,10);
}
}
3.final 关键字
final可以修饰类,成员变量,方法中的参数.如变量被其修饰后就相当于C++中常量的概念,不可以再对其更改
final类不可以被继承,即不能有子类,如
A就是一个final类.有时候出于安全性的考虑,将一些类修饰为final类.例如:java提供的String类,它对于编辑器和解释器的正常运行有很重要的作用,对它不能轻易改变.因此它被修饰为final类.
如果一个方法被修饰为final方法,则这个方法不可以被重写;
如果一个成员变量被修饰为final的,就是常量,常量必须赋初始值,而且不能再发生变化;
如果方法的参数被修饰为final的,该参数的值不能被改变.
体会下面的例子:
程序代码:
class A
{
final double PI=3.1415926;//变量PI为常量不可再被更改
public double getArea(final double r)//参数r被初始化后不可以被更改
{ //r=20;错误,r不可以被修改
return PI*r*r;
}
}
public class
{ public static void main(String args[])
{ A a=new A();
System.out.println("面积:"+a.getArea(100));
}
}
4.准备工作都做完了,下面让我们开始正式学习多态性
我们经常说:"哺乳动物有很多叫声",比如,"汪汪","喵喵","嚎","吼"等,这就是叫声的多态.
当一个类有很多子类时,并且这些子类都重写了父类中的某个方法.那么当把子类创建的对象的引用放到一个父类的对象中时,就得到
了该对象的一个上转型对象,那么这个上转的对象在调用这个方法时就可能具有多种形态,因为不同的子类在重写父类的方法时可能
产生不同的行为,比如,狗类的上转型对象调用"叫声"方法时产生的行为是"汪汪",而猫类的上转型对象调用"叫声"的方法时,产生的行为是"喵喵",等等.
多态性就是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为,下面的例子展示了多态性.
程序代码:
class 动物
{ void cry()
{
}
}
class 狗 extends 动物
{ void cry()//方法的重写
{ System.out.println("汪汪.....");
}
}
class 猫 extends 动物
{ void cry()//方法的重写
{ System.out.println("喵喵.....");
}
}
class Example4_20
{ public static void main(String args[])
{ 动物 dongwu;
dongwu=new 狗();
dongwu.cry();
dongwu=new 猫();
dongwu.cry();
}
}
5.抽象(abstract)类
用关键字abstract修饰的类称为抽象(abstract)类.如
abstract class A
{//...}
abstract类的几个特点:
1)abstract类中可以有abstract方法
与普通的类相比,abstract类可以有abstract方法.对于abstract方法,只允许声明,不允许实现,而且不允许使用final修饰abstract方法.下面的A类中的min()方法就是abstract方法
abstract class A
{ abstract int min(int x,int y);
int max(int x,int y)
{ return x>y?x:y;
}
}
注意:abstract类中也可以没有abstract方法
2)对于abstract类,不能使用new运算符创建该类的对象,需产生其子类,由子类创建对象,如果一个类是abstract类的子类,它必须具体实现abstract方法,这就是为什么不允许使用final修饰abstract方法的原因.体会一下下面的例子:
程序代码:
abstract class A
{ abstract int min(int x,int y);
int max(int x,int y)
{ return x>y?x:y;
}
}
class B extends A
{ int min(int x,int y) //子类中具体实现了min()的功能
{ return x
}
public class Example
{ public static void main(String args[])
{ A a;
B b=new B();
int max=b.max(12,34);
int min=b.min(12,34);
System.out.println("max="+max+" min="+min);
a=b;
max=a.max(12,34);
System.out.println("max="+max);
}
}
一个abstract类只关心它的子类是否具有某种功能,并不关心功能的具体行为,功能的具体行为由子类负责实现,抽象类中的抽象方法可以强制子类必须给出这些方法的具体实现.理解下面的例子来充分学习抽象类.
程序代码:
abstract class 图形
{ public abstract double 求面积();//相当于给子类们发出了求面积的具体表现命令
}
class 梯形 extends 图形
{ double a,b,h;
梯形(double a,double b,double h)
{ this.a=a;
this.b=b;
this.h=h;
}
public double 求面积()//子类梯形类实现了求面积功能
{ return((1/2.0)*(a+b)*h);
}
}
class 圆形 extends 图形
{ double r;
圆形(double r)
{ this.r=r;
}
public double 求面积()//子类圆形类实现了求面积功能
{ return(3.14*r*r);
}
}
class 堆
{ 图形 底;//只是声明
double 高;
堆(图形 底,double 高)//调用时候就可以用上转型对象来解释为什么了
{ this.底=底;
this.高=高;
}
void 换底(图形 底)
{ this.底=底;
}
public double 求体积()
{ return (底.求面积()*高)/3.0;
}
}
public class Example
{ public static void main(String args[])
{ 堆 zui;
图形 tuxing;
tuxing=new 梯形(2.0,7.0,10.7);
System.out.println("梯形的面积"+tuxing.求面积());
zui=new 堆(tuxing,30);
System.out.println("梯形底的堆的体积"+zui.求体积());
tuxing=new 圆形(10);
System.out.println("半径是10的圆的面积"+tuxing.求面积());
zui.换底(tuxing);
System.out.println("圆形底的堆的体积"+zui.求体积());
}
}
总结:初步了解了多态性和抽象类及与其相关的概念.
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第七节课
接 口
接口在java中尤其是面向对象语言中是一个很重要的概念.
java中使用接口概念的原因:java不支持多继承性,即一个类只能有一个父类.单继承性使得java简单,易于管理程序.为了克服单继
承的缺点,java使用了接口.
一个类可以实现多个接口.使用关键字inte***ce来定义一个接口.接口的定义和类的定义很相似,分为接口的声明和接口体.
1.接口声明及接口体
前面曾使用class关键字来声明类,接口通过使用关键字inte***ce来声明.格式
inte***ce 接口的名字
接口体中包含常量的定义和方法定义两部分.接口体中只进行方法的声明,不允许提供方法的实现,所以,方法的定义没有方法体,且
用";"结尾.如
程序代码:
inte***ce Printable
{
final int max=100;
void add();
float sum(float x,float y);
}
2.接口的使用
一个类通过使用关键字implements声明自己使用一个或多个接口.如果使用多个接口,用逗号隔开接口名.如:
class A implements Printable,Addable
类A使用接口Printable 和接口Addable
子类使用接口格式也一样,如:
class B extends A implements Printable,Addable
子类B使用接口Printable 和接口Addable
如果一个类使用了某个接口,那么这个类必须实现该接口的所有方法,即为这些方法提供方法体.需要注意的是:在类中实现接口的
方法时,方法的名字,返回值类型,参数个数及类型,必须与接口中的完全一致.特别要注意的是:接口中的方法默认是public
abstract方法,所以类在实现接口方法时必须给出方法体,并且一定要用public来修饰,而且接口中的常量默认是public static常
量.
由于接口体中只有常量定义和public的abstract方法定义,程序在编写接口时,允许省略常量前面的public,final和static修饰,也
允许省略方法前的public和abstract修饰.另外,如果接口方法的返回类型不是void型,那么在类中实现接口方法时,方法体至少要
有一个return语句;如果是void型,类体除了两个大括号外,也可以没有任何语句.
java提供的接口都在相应的包中,通过引入包可以使用java提供的接口.也可以自己定义接口,一个java源文件就是由类和接口组成的.
虽然"使用接口"的描述的很罗嗦,看看下面的例子就容易掌握了
程序代码:
inte***ce Computable//定义接口
{ int MAX=100;
int f(int x);//声明方法(是public abstrac型的,只是省略了关键字)
}
class China implements Computable
{ int number;
public int f(int x) //不要忘记public关键字
{ int sum=0;
for(int i=1;i<=x;i++)
{ sum=sum+i;
}
return sum;
}
}
class Japan implements Computable
{ int number;
public int f(int x)//不要忘记public关键字
{ return 44+x;
}
}
public class E
{ public static void main(String args[])
{ China zhang;
Japan henlu;
zhang=new China();
henlu=new Japan();
zhang.number=991898+Computable.MAX;
henlu.number=941448+Computable.MAX;
System.out.println("number:"+zhang.number+"求和"+zhang.f(100));
System.out.println("number:"+henlu.number+"求和"+henlu.f(100));
}
}
还要注意的就是如果一个类声明实现一个接口,但没有实现接口中的所有方法,那么这个类必须是abstract类,如
程序代码:
inte***ce Computable
{final int max=100;
void speak(String s);
int f(int x);
abstract class A implements Computable//类A使用的接口但类体中并没有实现接口中speak()的方法,所以此类必须是抽象类
{public int f(int x)//只是实现了接口中的一个方法
{int sum=0;
for(int i=1;i<=x;i++)
sum+=i;
return
}
}
类实现的接口方法以及接口中的常量可以被类的对象调用,而且常量也可以用类名或接口名直接调用.这理解不难,因为前面讲过
final修饰的常量,在内存程序加载字节码时,内存就给常量分配了一个固定空间,不可以改变(直到程序结束),所以这个地址是固定
了,并且这个常量是来自一个接口,所以此接口名或者使用这个接口的类的对象可以直接调用这个常量喽.方法也是一样的.
接口声明时,如果关键字inte***ce前面加public关键字,就称这样的接口是一个public接口.public接口可以被任何一个类使用.如
果一个接口不加public修饰,就称为友好接口类,友好接口可以被同一包中的类使用.
如果父类使用了某个接口,那么子类也就自然使用了该接口,子类不必再使用关键字implements声明自己使用这个接口了.
接口也可以被继承,即可以通过关键字extends声明一个接口是另一个接口的子接口.由于接口中的方法和常量都是public的,子接
口将继承父接口中的全部方法和常量.
3.理解接口
讲了半天,你已经知道如何定义和使用接口了,但你会疑问,使用接口的好处在哪里?其实接口的思想就在于它可以增加很多类都需
要实现的功能,使用相同的接口类不一定由继承的关系,就是象各种各样的商品,他们可能隶属不同的公司,工商部门要求不管哪里
的商品必须具有显示商标的功能(即实现同一接口),但商标的具体制作由各个公司自己去实现,这就是接口的灵活所在.再比如,你
是一个项目的主管,你需要管理许多部门,这些部门要开发一些软件所需要的类,你可能要求某个类实现一个接口,也就是说你对一
些类是否具有这个功能非常关心,但不关心功能的具体实现.比如,这个功能是speaklove,但你不关心是用汉语实现功能还是用英语
实现speaklove.还是用个例子来理解一下接口,如:
程序代码:
inte***ce 收费 //定义接口收费功能
{ public void 收取费用();
}
inte***ce 调节温度 //定义接口调节温度功能
{ public void controlTemperature();
}
class 公共汽车 implements 收费 //一般的公共汽车只具有收费功能,空调车少
{ public void 收取费用()
{ System.out.println("公共汽车:一元/张,不计算公里数");
}
}
class 出租车 implements 收费, 调节温度//出租车比较高级当然除了收费功能还有空调喽
{ public void 收取费用()
{ System.out.println("出租车:1.60元/公里,起价3公里");
}
public void controlTemperature()
{ System.out.println("安装了Hair空调");
}
}
class 电影院 implements 收费,调节温度//电影院有收费和调节温度功能
{ public void 收取费用()
{ System.out.println("电影院:门票,十元/张");
}
public void controlTemperature()
{ System.out.println("安装了中央空调");
}
}
class E
{ public static void main(String args[])
{ 公共汽车 七路=new 公共汽车();
出租车 天宇=new 出租车();
电影院 红星=new 电影院();
七路.收取费用();
天宇.收取费用();
红星.收取费用();
天宇.controlTemperature();
红星.controlTemperature();
}
}
从这个例子可以看出来定义了多个接口,不同类根据自己的需要可以灵活使用想要的接口.建议接口里实现的方法越少越好,可以定
义多个接口来实现多种功能.
4.接口回调
接口回调是指:可以把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量中.那么该接口变量就可以调用被类实现的
接口中的方法.实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法.通过例子掌握接口回调
的意义,如
程序代码:
inte***ce ShowMessage//接口
{ void 显示商标(String s);
}
class TV implements ShowMessage//使用接口
{ public void 显示商标(String s)
{ System.out.println(s);
}
}
class PC implements ShowMessage//使用接口
{ public void 显示商标(String s)
{ System.out.println(s);
}
}
public class E
{ public static void main(String args[])
{ ShowMessage sm;//声明了一个接口变量
sm=new TV();//把使用该接口的类的对象赋给接口变量
sm.显示商标("长城牌电视机");//此时接口变量就可以使用被该类实现的接口中的方法了
sm=new PC(); //另一个对象赋给接口变量
sm.显示商标("联想奔月5008PC机");
}
}
体会一下,如果你理解上节课讲的上转型对象,就可以很轻松理解接口回调的过程
回顾下上节课中将抽象类时给的例子,计算面积的那个,下面用接口l来实现,比较不同点
程序代码:
inte***ce Computerable
{ public double 求面积();
}
class 梯形 implements Computerable
{ double a,b,h;
梯形(double a,double b,double h)
{ this.a=a;
this.b=b;
this.h=h;
}
public double 求面积()
{ return((1/2.0)*(a+b)*h);
}
}
class 圆形 implements Computerable
{ double r;
圆形(double r)
{ this.r=r;
}
public double 求面积()
{ return(3.14*r*r);
}
}
class 堆
{ Computerable 底;
double 高;
堆(Computerable 底,double 高)
{ this.底=底;
this.高=高;
}
void 换底(Computerable 底)
{ this.底=底;
}
public double 求体积()
{ return (底.求面积()*高)/3.0;
}
}
public class E
{ public static void main(String args[])
{ 堆 zui;
Computerable bottom;//声明接口变量
bottom=new 梯形(2.0,7.0,10.7); //回调
System.out.println("梯形的面积"+bottom.求面积());
zui=new 堆(bottom,30);
System.out.println("梯形底的堆的体积"+zui.求体积());
bottom=new 圆形(10);
System.out.println("半径是10的圆的面积"+bottom.求面积());
zui.换底(bottom);
System.out.println("圆形底的堆的体积"+zui.求体积());
}
}
上面的例子明白后或者理解了什么时接口回调,再讨论下"接口做参数"的概念
如果准备给一个方法的参数传递一个值,可能希望该方法的参数的类型时都不了类型,这样就可以想该参数传递byte int long float double类型的数据.
如果一个方法的参数时接口类型,就可以将任何实现改接口类的实例传递给该接口参数,那么接口参数就可以回调类实现的接口方法.
比如上面的例子中堆那个类,
程序代码:
class 堆
{ Computerable 底;//声明接口类型变量
double 高;
堆(Computerable 底,double 高) //方法的参数类型是接口
{ this.底=底;
this.高=高;
}
void 换底(Computerable 底)
{ this.底=底;
}
public double 求体积()
{ return (底.求面积()*高)/3.0;//"底"是接口类型的变量怎么能使用求面积的方法呢,说明了肯定是接口回调,即传进来的参数是一个被对象赋过值的接口变量,才使得此接口变量可以使用被类实现的方法
}
}
如果还是不太明白过程,把下面的程序理解就行了
程序代码:
inte***ce SpeakHello //接口
{ void speakHello();
}
class Chinese implements SpeakHello//使用接口
{ public void speakHello()
{ System.out.println("中国人习惯问候语:你好,吃饭了吗? ");
}
}
class English implements SpeakHello//使用接口
{ public void speakHello()
{ System.out.println("英国人习惯问候语:你好,天气不错 ");
}
}
class KindHello
{ public void lookHello(SpeakHello hello)//接口做参数
{ hello.speakHello();//被赋值了的接口(回调后的接口)就可以使用被类实现了的方法speakHello();
}
}
public class E
{ public static void main(String args[])
{ KindHello kindHello=new KindHello();
kindHello.lookHello(new Chinese());//可以把它分解为SpeakHello hello; 和hello=new Chinese();
kindHello.lookHello(new English());
}
}
总结:花了一个篇幅讲接口,就证明它的重要性,灵活使用接口对以后编写java程序再性能上会有质的提高的
接 口
接口在java中尤其是面向对象语言中是一个很重要的概念.
java中使用接口概念的原因:java不支持多继承性,即一个类只能有一个父类.单继承性使得java简单,易于管理程序.为了克服单继
承的缺点,java使用了接口.
一个类可以实现多个接口.使用关键字inte***ce来定义一个接口.接口的定义和类的定义很相似,分为接口的声明和接口体.
1.接口声明及接口体
前面曾使用class关键字来声明类,接口通过使用关键字inte***ce来声明.格式
inte***ce 接口的名字
接口体中包含常量的定义和方法定义两部分.接口体中只进行方法的声明,不允许提供方法的实现,所以,方法的定义没有方法体,且
用";"结尾.如
程序代码:
inte***ce Printable
{
final int max=100;
void add();
float sum(float x,float y);
}
2.接口的使用
一个类通过使用关键字implements声明自己使用一个或多个接口.如果使用多个接口,用逗号隔开接口名.如:
class A implements Printable,Addable
类A使用接口Printable 和接口Addable
子类使用接口格式也一样,如:
class B extends A implements Printable,Addable
子类B使用接口Printable 和接口Addable
如果一个类使用了某个接口,那么这个类必须实现该接口的所有方法,即为这些方法提供方法体.需要注意的是:在类中实现接口的
方法时,方法的名字,返回值类型,参数个数及类型,必须与接口中的完全一致.特别要注意的是:接口中的方法默认是public
abstract方法,所以类在实现接口方法时必须给出方法体,并且一定要用public来修饰,而且接口中的常量默认是public static常
量.
由于接口体中只有常量定义和public的abstract方法定义,程序在编写接口时,允许省略常量前面的public,final和static修饰,也
允许省略方法前的public和abstract修饰.另外,如果接口方法的返回类型不是void型,那么在类中实现接口方法时,方法体至少要
有一个return语句;如果是void型,类体除了两个大括号外,也可以没有任何语句.
java提供的接口都在相应的包中,通过引入包可以使用java提供的接口.也可以自己定义接口,一个java源文件就是由类和接口组成的.
虽然"使用接口"的描述的很罗嗦,看看下面的例子就容易掌握了
程序代码:
inte***ce Computable//定义接口
{ int MAX=100;
int f(int x);//声明方法(是public abstrac型的,只是省略了关键字)
}
class China implements Computable
{ int number;
public int f(int x) //不要忘记public关键字
{ int sum=0;
for(int i=1;i<=x;i++)
{ sum=sum+i;
}
return sum;
}
}
class Japan implements Computable
{ int number;
public int f(int x)//不要忘记public关键字
{ return 44+x;
}
}
public class E
{ public static void main(String args[])
{ China zhang;
Japan henlu;
zhang=new China();
henlu=new Japan();
zhang.number=991898+Computable.MAX;
henlu.number=941448+Computable.MAX;
System.out.println("number:"+zhang.number+"求和"+zhang.f(100));
System.out.println("number:"+henlu.number+"求和"+henlu.f(100));
}
}
还要注意的就是如果一个类声明实现一个接口,但没有实现接口中的所有方法,那么这个类必须是abstract类,如
程序代码:
inte***ce Computable
{final int max=100;
void speak(String s);
int f(int x);
abstract class A implements Computable//类A使用的接口但类体中并没有实现接口中speak()的方法,所以此类必须是抽象类
{public int f(int x)//只是实现了接口中的一个方法
{int sum=0;
for(int i=1;i<=x;i++)
sum+=i;
return
}
}
类实现的接口方法以及接口中的常量可以被类的对象调用,而且常量也可以用类名或接口名直接调用.这理解不难,因为前面讲过
final修饰的常量,在内存程序加载字节码时,内存就给常量分配了一个固定空间,不可以改变(直到程序结束),所以这个地址是固定
了,并且这个常量是来自一个接口,所以此接口名或者使用这个接口的类的对象可以直接调用这个常量喽.方法也是一样的.
接口声明时,如果关键字inte***ce前面加public关键字,就称这样的接口是一个public接口.public接口可以被任何一个类使用.如
果一个接口不加public修饰,就称为友好接口类,友好接口可以被同一包中的类使用.
如果父类使用了某个接口,那么子类也就自然使用了该接口,子类不必再使用关键字implements声明自己使用这个接口了.
接口也可以被继承,即可以通过关键字extends声明一个接口是另一个接口的子接口.由于接口中的方法和常量都是public的,子接
口将继承父接口中的全部方法和常量.
3.理解接口
讲了半天,你已经知道如何定义和使用接口了,但你会疑问,使用接口的好处在哪里?其实接口的思想就在于它可以增加很多类都需
要实现的功能,使用相同的接口类不一定由继承的关系,就是象各种各样的商品,他们可能隶属不同的公司,工商部门要求不管哪里
的商品必须具有显示商标的功能(即实现同一接口),但商标的具体制作由各个公司自己去实现,这就是接口的灵活所在.再比如,你
是一个项目的主管,你需要管理许多部门,这些部门要开发一些软件所需要的类,你可能要求某个类实现一个接口,也就是说你对一
些类是否具有这个功能非常关心,但不关心功能的具体实现.比如,这个功能是speaklove,但你不关心是用汉语实现功能还是用英语
实现speaklove.还是用个例子来理解一下接口,如:
程序代码:
inte***ce 收费 //定义接口收费功能
{ public void 收取费用();
}
inte***ce 调节温度 //定义接口调节温度功能
{ public void controlTemperature();
}
class 公共汽车 implements 收费 //一般的公共汽车只具有收费功能,空调车少
{ public void 收取费用()
{ System.out.println("公共汽车:一元/张,不计算公里数");
}
}
class 出租车 implements 收费, 调节温度//出租车比较高级当然除了收费功能还有空调喽
{ public void 收取费用()
{ System.out.println("出租车:1.60元/公里,起价3公里");
}
public void controlTemperature()
{ System.out.println("安装了Hair空调");
}
}
class 电影院 implements 收费,调节温度//电影院有收费和调节温度功能
{ public void 收取费用()
{ System.out.println("电影院:门票,十元/张");
}
public void controlTemperature()
{ System.out.println("安装了中央空调");
}
}
class E
{ public static void main(String args[])
{ 公共汽车 七路=new 公共汽车();
出租车 天宇=new 出租车();
电影院 红星=new 电影院();
七路.收取费用();
天宇.收取费用();
红星.收取费用();
天宇.controlTemperature();
红星.controlTemperature();
}
}
从这个例子可以看出来定义了多个接口,不同类根据自己的需要可以灵活使用想要的接口.建议接口里实现的方法越少越好,可以定
义多个接口来实现多种功能.
4.接口回调
接口回调是指:可以把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量中.那么该接口变量就可以调用被类实现的
接口中的方法.实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法.通过例子掌握接口回调
的意义,如
程序代码:
inte***ce ShowMessage//接口
{ void 显示商标(String s);
}
class TV implements ShowMessage//使用接口
{ public void 显示商标(String s)
{ System.out.println(s);
}
}
class PC implements ShowMessage//使用接口
{ public void 显示商标(String s)
{ System.out.println(s);
}
}
public class E
{ public static void main(String args[])
{ ShowMessage sm;//声明了一个接口变量
sm=new TV();//把使用该接口的类的对象赋给接口变量
sm.显示商标("长城牌电视机");//此时接口变量就可以使用被该类实现的接口中的方法了
sm=new PC(); //另一个对象赋给接口变量
sm.显示商标("联想奔月5008PC机");
}
}
体会一下,如果你理解上节课讲的上转型对象,就可以很轻松理解接口回调的过程
回顾下上节课中将抽象类时给的例子,计算面积的那个,下面用接口l来实现,比较不同点
程序代码:
inte***ce Computerable
{ public double 求面积();
}
class 梯形 implements Computerable
{ double a,b,h;
梯形(double a,double b,double h)
{ this.a=a;
this.b=b;
this.h=h;
}
public double 求面积()
{ return((1/2.0)*(a+b)*h);
}
}
class 圆形 implements Computerable
{ double r;
圆形(double r)
{ this.r=r;
}
public double 求面积()
{ return(3.14*r*r);
}
}
class 堆
{ Computerable 底;
double 高;
堆(Computerable 底,double 高)
{ this.底=底;
this.高=高;
}
void 换底(Computerable 底)
{ this.底=底;
}
public double 求体积()
{ return (底.求面积()*高)/3.0;
}
}
public class E
{ public static void main(String args[])
{ 堆 zui;
Computerable bottom;//声明接口变量
bottom=new 梯形(2.0,7.0,10.7); //回调
System.out.println("梯形的面积"+bottom.求面积());
zui=new 堆(bottom,30);
System.out.println("梯形底的堆的体积"+zui.求体积());
bottom=new 圆形(10);
System.out.println("半径是10的圆的面积"+bottom.求面积());
zui.换底(bottom);
System.out.println("圆形底的堆的体积"+zui.求体积());
}
}
上面的例子明白后或者理解了什么时接口回调,再讨论下"接口做参数"的概念
如果准备给一个方法的参数传递一个值,可能希望该方法的参数的类型时都不了类型,这样就可以想该参数传递byte int long float double类型的数据.
如果一个方法的参数时接口类型,就可以将任何实现改接口类的实例传递给该接口参数,那么接口参数就可以回调类实现的接口方法.
比如上面的例子中堆那个类,
程序代码:
class 堆
{ Computerable 底;//声明接口类型变量
double 高;
堆(Computerable 底,double 高) //方法的参数类型是接口
{ this.底=底;
this.高=高;
}
void 换底(Computerable 底)
{ this.底=底;
}
public double 求体积()
{ return (底.求面积()*高)/3.0;//"底"是接口类型的变量怎么能使用求面积的方法呢,说明了肯定是接口回调,即传进来的参数是一个被对象赋过值的接口变量,才使得此接口变量可以使用被类实现的方法
}
}
如果还是不太明白过程,把下面的程序理解就行了
程序代码:
inte***ce SpeakHello //接口
{ void speakHello();
}
class Chinese implements SpeakHello//使用接口
{ public void speakHello()
{ System.out.println("中国人习惯问候语:你好,吃饭了吗? ");
}
}
class English implements SpeakHello//使用接口
{ public void speakHello()
{ System.out.println("英国人习惯问候语:你好,天气不错 ");
}
}
class KindHello
{ public void lookHello(SpeakHello hello)//接口做参数
{ hello.speakHello();//被赋值了的接口(回调后的接口)就可以使用被类实现了的方法speakHello();
}
}
public class E
{ public static void main(String args[])
{ KindHello kindHello=new KindHello();
kindHello.lookHello(new Chinese());//可以把它分解为SpeakHello hello; 和hello=new Chinese();
kindHello.lookHello(new English());
}
}
总结:花了一个篇幅讲接口,就证明它的重要性,灵活使用接口对以后编写java程序再性能上会有质的提高的
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第八节课
一些比较重要的类
1.内部类
类可以有两种重要的成员:成员变量和方法,类还可以有一种成员:内部类.
java支持在一个类中声明另一个类,这样的类称为内部类,而包含内部类的类称为内部类的外部类.声明内部类如同在类中声明方法
和成员变量一样,一个类把内部类看作是自己的成员.内部类的外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用
外嵌类中的方法.内部类的类体中不可以声明类变量和方法.外嵌类的类体中可以用内部类声明对象,作为外嵌类的成员.举例体会:
程序代码:
class China
{ final String nationalAnthem="义勇军进行曲";
Beijing beijing; //Beijing 是个内部类,其声明了一个对象作为外嵌类的成员
China()
{ beijing=new Beijing();
}
String getSong()
{ return nationalAnthem;
}
class Beijing //内部类的声明
{ String name="北京";
void speak()
{ System.out.println("我们是"+name+" 我们的国歌是:"+getSong());
}
}
}
public class E
{ public static void main(String args[])
{ China china=new China();
china.beijing.speak();
}
}
2.匿名类
a) 和类有关的匿名类
当使用类创建对象时,程序允许把类体与对象的创建组合在一起,也就是说,类创建对象时,除了构造方法还有类体,此类体被认为是
该类的一个子类去掉类声明后的类体,称作匿名类.匿名类就是一个子类,由于无名可用,所以不可能用匿名类声明对象,但却可以直
接用匿名类创建对象.假设People是类,那么下列代码就是用People的一个子类(匿名类)创建对象:
new People()
{
匿名类的类体
}
因此,匿名类可以继承父类的方法也可以重写父类的方法.使用匿名类时,必然是在某个类中直接用匿名类创建对象,因此匿名类一定
是内部类,匿名类可以访问外嵌类中的成员变量和方法,匿名类的类体中不可以声明static成员变量和static方法.
尽管匿名类创建的对象没有经历类声明的步骤,但匿名对象的引用必须传递一个匹配的参数,匿名类的主要途径就是向方法的参数传
值.
假设f(B x)是一个方法
void f(B x){
x调用B类中的方法
}
其中参数是B类的对象,那么在调用方法f时可以向其参数x传递一个匿名对象,例如:
f(new B()
{匿名类的类体}
)
如果匿名类继承了类的方法,x就调用继承的方法,如果匿名类重写了父类的方法,x就调用重写的方法.
看看下面的例子,用匿名类创建一个对象,并向一个方法的参数传递一个匿名类的对象.
程序代码:
class Cubic
{ double getCubic(int n)
{ return 0;
}
}
abstract class Sqrt
{ public abstract double getSqrt(int x);
}
class A
{ void f(Cubic cubic)
{ double result=cubic.getCubic(3);//执行匿名类体中重写的getCubic()
System.out.println(result);
}
}
public class E
{ public static void main(String args[])
{ A a=new A();
a.f(new Cubic() //使用匿名类创建对象,将该对象传递给方法f的参数cubic
{ double getCubic(int n)//类体
{ return n*n*n;
}
}
);
Sqrt ss=new Sqrt() //使用匿名类创建对象,ss是该对象的上转型对象
{ public double getSqrt(int x) //匿名类是abstract类Sqrt的一个子类,所以必须实现getSqrt()方法
{ return Math.sqrt(x);
}
};
double m=ss.getSqrt(5); //上转型对象调用子类重写的方法
System.out.println(m);
}
}
b) 和接口相关的匿名类
假设Computable是一个接口,那么,java允许直接调用接口名和一个类体创建一个匿名对象,此类体被认为是实现Computable接口的
类去掉类声明后的类体,称为匿名类.下面这个例子就是用实现了Computable接口的类(匿名类)创建对象:
程序代码:
inte***ce Cubic
{ double getCubic(int n);
}
inte***ce Sqrt
{ public double getSqrt(int x);
}
class A
{ void f(Cubic cubic)
{ double result=cubic.getCubic(3); //执行匿名类体中实现getCubic()方法
System.out.println(result);
}
}
public class E
{ public static void main(String args[])
{ A a=new A();
a.f(new Cubic() //使用匿名类创建对象,将该对象传递给方法f的参数cubic
{ public double getCubic(int n)
{ return n*n*n;
}
}
);
Sqrt ss=new Sqrt() //使用匿名类创建对象,接口ss存放该对象的引用
{ public double getSqrt(int x)//匿名类是实现Sqrt接口的方法,所以必须要实现getSqrt方法
{ return Math.sqrt(x);
}
};
double m=ss.getSqrt(5); //接口回调类实现的方法
System.out.println(m);
}
}
3.异常类
所谓异常就是程序运行时可能出现的一些错误,如试图打开一个根本不存在的文件等,异常处理将会改变程序的控制流程,让程序有机会对错误作出处理.
当程序运行出现异常时,java运行环境就用异常类Exception的相应子类创建一个异常对象,并等待处理,例如读取下一个不存在的文
件时,运行环境就用异常类IOException创建一个对象.异常对象可以调用如下方法得到或输出有关异常的信息:
public String getMessage() , public void printStackTrace() , public String toString()
java使用try-catch语句来处理异常,将可能出现的异常操作放在try-catch语句的try的部分.当try部分中的某个语句发生异常
后,try部分将立刻结束执行,而转向执行相应的catch部分,所以程序可以将发生异常后的处理放在catch部分.try-catch语句可以由
几个catch组成,分别处理发生的相应异常.
try-catch语句格式如下:
try
{
包含可能发生异常的语句
}
catch(ExceptionSubClass1 e)
{
}
catch(ExceptionSubClass2 e)
{
}
...
各个catch参数中的异常类都是Exception的某个子类,标明try部分可能发生的异常,这些子类之间不能由父子关系,否则保留一个含
有父类参数的catch即可.
通过例子掌握try-catch语句的用法,如:
程序代码:
public class E
{ public static void main(String args[ ])
{ int n=0,m=0,t=555;
try{ m=Integer.parseInt("8888");//Integer.parseInt是可以将数字格式的字符串转换成int型数据
n=Integer.parseInt("abc789");//"abc"不是属于数字格式的字符串,所以通过Integer.parseInt转换时会出现异常
t=9999; //发生异常后就立刻进入catch部分,所以t=9999没有被执行
}
catch(NumberFormatException e)
{ System.out.println("发生异常:"+e.getMessage());//得到发生异常的部分
e.printStackTrace();
n=123;
}
System.out.println("n="+n+",m="+m+",t="+t);
}
}//结果应该是n=123,m=8888,t=555
在
程序中也可以扩展Exception类定义自己的异常类,然后规定哪些方法产生这样的异常.一个方法在声明时可以使用throws关键字声明要产生的若干
异常,并在该方法的方法体中具体给出产生异常类的操作,即用相应的异常类创建对象,并使用throw关键字抛出该异常类,导致该方法结束执行.程序必须在
try-catch语句中调用能发生异常的方法,其中catch的作用就是捕获throw方法抛出的异常现象.
注意:throw时java的关键字,该关键字的作用就是抛出异常.throw和throws是两个不同的关键字.
下面的例子中,Computer类中有一个计算最大公约数的方法,如果向该方法传递负整数,方法就抛出定义的异常.
程序代码:
class NopositiveException extends Exception//子定义的异常类
{ String message;
NopositiveException(int m,int n)
{ message="数字"+m+"或"+n+"不是正整数";
}
public String toString()
{ return message;
}
}
class Computer
{ public int getMaxCommonDivisor(int m,int n) throws NopositiveException//声明NopositiveException自定义的异常类
{ if(n<=0||m<=0)//不满足条件时候
{ NopositiveException exception=new NopositiveException(m,n);//创建自定义异常类的对象,用来抛出异常
throw exception; //抛出异常,结束方法的执行
}
if(m<n)
{ int temp=0;
temp=m;
m=n;
n=temp;
}
int r=m%n;
while(r!=0)
{ m=n;
n=r;
r=m%n;
}
return n;
}
}
public class E
{ public static void main(String args[])
{ int m=24,n=36,result=0;
Computer a=new Computer();
try { result=a.getMaxCommonDivisor(m,n);
System.out.println(m+"和"+n+"的最大公约数 "+result);
m=-12;
n=22;
result=a.getMaxCommonDivisor(m,n);
System.out.println(m+"和"+n+"的最大公约数 "+result);
}
catch(NopositiveException e)
{ System.out.println(e.toString());
}
}
}
4. Class 类
Class
是java.lang包中的类,该类的实例用来封装对象运行时的状态.当一个类被加载且创建对象时,和改类相关的一个类型为Class的对象就会自动创
建.Class类本身不提供构造方法,因此,不能用new运算符和构造方法创建一个Class对象.任何对象调用getClass()方法都可以获取和该
对象相关的一个Class对象,这个Class对象调用如下的方法可以获取创建对象的类的有关信息,比如类的名字,类中的方法名称,成员变量的名称等.
String getName() //返回类的名字
Constructor[] getDeclaredConstructors() //返回类的全部构造方法
Field[] getDeclaredFields() //返回类的全部成员变量
Method[] getDeclaredMethods() //返回类的全部方法
执行下面的例子来演示这几个函数的作用,如
程序代码:
import java.lang.reflect.*;
class Rect
{ double width,height,area;
public double getArea()
{ area=height*width;
return area;
}
}
public class E
{ public static void main(String args[])
{ Rect rect=new Rect();
Class cs=rect.getClass();//通过getClass来获取rect这个对象
String className=cs.getName();
Constructor[] con=cs.getDeclaredConstructors();
Field[] field=cs.getDeclaredFields() ;
Method[] method=cs.getDeclaredMethods();
System.out.println("类的名字:"+className);
System.out.println("类中有如下的成员变量:");
for(int i=0;i<field.length;i++)
{ System.out.println(field.toString());
}
System.out.println("类中有如下的方法:");
for(int i=0;i<method.length;i++)
{ System.out.println(method.toString());
}
System.out.println("类中有如下的构造方法:");
for(int i=0;i<con.length;i++)
{ System.out.println(con[i].toString());
}
}
}
创建对象最常用的方式就是使用new运算符和类的构造方法,实际上也可以使用Class对象得到一个类的实例.为了得到一个类的对象,可以先得到一个和该类相关的Class对象,做到这点并不是难,只要使用Class的类方法:
public static Class forname(String className) throws ClassNotFoundException
就可以返回一个和参数calssName指定的类相关的Class对象.再让这个Class对象调用
public Object newInstance () throws InstantiationException,IllegalAccessException
方法就可以得到一个className类的对象.
要特别注意的是,使用Class对象调用newInstance()实例化一个className类的对象时,className类必须有无参数的构造方法.
看看下面的例子,如
程序代码:
class Rect
{ double width,height,area;
public double getArea()
{ area=height*width;
return area;
}
}
public class
{ public static void main(String args[])
{ try{ Class cs=Class.forName("Rect");//没有通过new来创建对象,用forname()制定类的实例
Rect rect=(Rect)cs.newInstance();//得到此实例即创建对象
rect.width=100;
rect.height=200;
System.out.println("rect的面积"+rect.getArea());
}
catch(Exception e){}
}
}
5.基本类型的类
java
的基本数据类型包括byte,int,short,long,float,double,char.java同时也提供了基本类型相关的类,实现了对基本
类型的封装.这些类在java.lang包中,分别是Byte,Integer,Short,Long,Float,Double,Character
这些基本类型都有自己的构造方法,如
Double(double num) //创建了一个Double类型的对象 并调用doubleValue()方法可以返回该对象含有double型数据
Float(float num) //创建了一个Float类型的对象 并调用floatValue()方法可以返回该对象含有float型数据
Byte(byte num) //创建了一个Byte类型的对象 并调用byteValue()方法可以返回该对象含有byte型数据
Integer(int num) //创建了一个Integer类型的对象 并调用intValue()方法可以返回该对象含有int型数据
Short(short num) //创建了一个Short类型的对象 并调用shortValue()方法可以返回该对象含有short型数据
Long(long num) //创建了一个Long类型的对象 并调用longValue()方法可以返回该对象含有long型数据
Character类实现了对char基本型数据的类包装.
可以使用Character的构造方法:
Character (char c)
创建一个Character类型的对象.Character对象调用charValue()方法可以返回该对象含有的char类型数据.
Character类还包括了一些类方法,这些方法可以直接通过类名调用,用来进行字符分类,比如判断一个字符是否是数字字符或改变一个字符的大小写等.
public static boolean isDigit(char ch) //如果ch是数字字符,方法返回true,否则返回false
public static boolean isLetter(char ch) //如果ch是字母,方法返回true
public static boolean isLetterOrDigit(char ch) //如果ch是数字字符或者字母,方法返回true
public static boolean isLowerCase(char ch) //如果ch是小写字母
public static boolean isUpperCase(char ch) //如果ch是大写字母
public static char toLowerCase(char ch) //返回ch的小写形式
public static char toUpperCase(char ch) //返回ch的大写形式
public static boolean isSpaceChar(char ch) //如果是空格,返回true
通过下面的例子掌握Character类的这些成员方法的使用,如
程序代码:
public class E
{ public static void main(String args[ ])
{ char a[]={'a','b','c','D','E','F'};
for(int i=0;i<a.length;i++)
{ if(Character.isLowerCase(a[i]))
{ a[i]=Character.toUpperCase(a[i]);
}
else if(Character.isUpperCase(a[i]))
{ a[i]=Character.toLowerCase(a[i]);
}
}
for(int i=0;i<a.length;i++)
{ System.out.print(" "+a[i]);
}
}
}
总结:此小节主要将了一些特殊的类的用法[/i][/i][/i][/i][/i][/i][/i][/i]
一些比较重要的类
1.内部类
类可以有两种重要的成员:成员变量和方法,类还可以有一种成员:内部类.
java支持在一个类中声明另一个类,这样的类称为内部类,而包含内部类的类称为内部类的外部类.声明内部类如同在类中声明方法
和成员变量一样,一个类把内部类看作是自己的成员.内部类的外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用
外嵌类中的方法.内部类的类体中不可以声明类变量和方法.外嵌类的类体中可以用内部类声明对象,作为外嵌类的成员.举例体会:
程序代码:
class China
{ final String nationalAnthem="义勇军进行曲";
Beijing beijing; //Beijing 是个内部类,其声明了一个对象作为外嵌类的成员
China()
{ beijing=new Beijing();
}
String getSong()
{ return nationalAnthem;
}
class Beijing //内部类的声明
{ String name="北京";
void speak()
{ System.out.println("我们是"+name+" 我们的国歌是:"+getSong());
}
}
}
public class E
{ public static void main(String args[])
{ China china=new China();
china.beijing.speak();
}
}
2.匿名类
a) 和类有关的匿名类
当使用类创建对象时,程序允许把类体与对象的创建组合在一起,也就是说,类创建对象时,除了构造方法还有类体,此类体被认为是
该类的一个子类去掉类声明后的类体,称作匿名类.匿名类就是一个子类,由于无名可用,所以不可能用匿名类声明对象,但却可以直
接用匿名类创建对象.假设People是类,那么下列代码就是用People的一个子类(匿名类)创建对象:
new People()
{
匿名类的类体
}
因此,匿名类可以继承父类的方法也可以重写父类的方法.使用匿名类时,必然是在某个类中直接用匿名类创建对象,因此匿名类一定
是内部类,匿名类可以访问外嵌类中的成员变量和方法,匿名类的类体中不可以声明static成员变量和static方法.
尽管匿名类创建的对象没有经历类声明的步骤,但匿名对象的引用必须传递一个匹配的参数,匿名类的主要途径就是向方法的参数传
值.
假设f(B x)是一个方法
void f(B x){
x调用B类中的方法
}
其中参数是B类的对象,那么在调用方法f时可以向其参数x传递一个匿名对象,例如:
f(new B()
{匿名类的类体}
)
如果匿名类继承了类的方法,x就调用继承的方法,如果匿名类重写了父类的方法,x就调用重写的方法.
看看下面的例子,用匿名类创建一个对象,并向一个方法的参数传递一个匿名类的对象.
程序代码:
class Cubic
{ double getCubic(int n)
{ return 0;
}
}
abstract class Sqrt
{ public abstract double getSqrt(int x);
}
class A
{ void f(Cubic cubic)
{ double result=cubic.getCubic(3);//执行匿名类体中重写的getCubic()
System.out.println(result);
}
}
public class E
{ public static void main(String args[])
{ A a=new A();
a.f(new Cubic() //使用匿名类创建对象,将该对象传递给方法f的参数cubic
{ double getCubic(int n)//类体
{ return n*n*n;
}
}
);
Sqrt ss=new Sqrt() //使用匿名类创建对象,ss是该对象的上转型对象
{ public double getSqrt(int x) //匿名类是abstract类Sqrt的一个子类,所以必须实现getSqrt()方法
{ return Math.sqrt(x);
}
};
double m=ss.getSqrt(5); //上转型对象调用子类重写的方法
System.out.println(m);
}
}
b) 和接口相关的匿名类
假设Computable是一个接口,那么,java允许直接调用接口名和一个类体创建一个匿名对象,此类体被认为是实现Computable接口的
类去掉类声明后的类体,称为匿名类.下面这个例子就是用实现了Computable接口的类(匿名类)创建对象:
程序代码:
inte***ce Cubic
{ double getCubic(int n);
}
inte***ce Sqrt
{ public double getSqrt(int x);
}
class A
{ void f(Cubic cubic)
{ double result=cubic.getCubic(3); //执行匿名类体中实现getCubic()方法
System.out.println(result);
}
}
public class E
{ public static void main(String args[])
{ A a=new A();
a.f(new Cubic() //使用匿名类创建对象,将该对象传递给方法f的参数cubic
{ public double getCubic(int n)
{ return n*n*n;
}
}
);
Sqrt ss=new Sqrt() //使用匿名类创建对象,接口ss存放该对象的引用
{ public double getSqrt(int x)//匿名类是实现Sqrt接口的方法,所以必须要实现getSqrt方法
{ return Math.sqrt(x);
}
};
double m=ss.getSqrt(5); //接口回调类实现的方法
System.out.println(m);
}
}
3.异常类
所谓异常就是程序运行时可能出现的一些错误,如试图打开一个根本不存在的文件等,异常处理将会改变程序的控制流程,让程序有机会对错误作出处理.
当程序运行出现异常时,java运行环境就用异常类Exception的相应子类创建一个异常对象,并等待处理,例如读取下一个不存在的文
件时,运行环境就用异常类IOException创建一个对象.异常对象可以调用如下方法得到或输出有关异常的信息:
public String getMessage() , public void printStackTrace() , public String toString()
java使用try-catch语句来处理异常,将可能出现的异常操作放在try-catch语句的try的部分.当try部分中的某个语句发生异常
后,try部分将立刻结束执行,而转向执行相应的catch部分,所以程序可以将发生异常后的处理放在catch部分.try-catch语句可以由
几个catch组成,分别处理发生的相应异常.
try-catch语句格式如下:
try
{
包含可能发生异常的语句
}
catch(ExceptionSubClass1 e)
{
}
catch(ExceptionSubClass2 e)
{
}
...
各个catch参数中的异常类都是Exception的某个子类,标明try部分可能发生的异常,这些子类之间不能由父子关系,否则保留一个含
有父类参数的catch即可.
通过例子掌握try-catch语句的用法,如:
程序代码:
public class E
{ public static void main(String args[ ])
{ int n=0,m=0,t=555;
try{ m=Integer.parseInt("8888");//Integer.parseInt是可以将数字格式的字符串转换成int型数据
n=Integer.parseInt("abc789");//"abc"不是属于数字格式的字符串,所以通过Integer.parseInt转换时会出现异常
t=9999; //发生异常后就立刻进入catch部分,所以t=9999没有被执行
}
catch(NumberFormatException e)
{ System.out.println("发生异常:"+e.getMessage());//得到发生异常的部分
e.printStackTrace();
n=123;
}
System.out.println("n="+n+",m="+m+",t="+t);
}
}//结果应该是n=123,m=8888,t=555
在
程序中也可以扩展Exception类定义自己的异常类,然后规定哪些方法产生这样的异常.一个方法在声明时可以使用throws关键字声明要产生的若干
异常,并在该方法的方法体中具体给出产生异常类的操作,即用相应的异常类创建对象,并使用throw关键字抛出该异常类,导致该方法结束执行.程序必须在
try-catch语句中调用能发生异常的方法,其中catch的作用就是捕获throw方法抛出的异常现象.
注意:throw时java的关键字,该关键字的作用就是抛出异常.throw和throws是两个不同的关键字.
下面的例子中,Computer类中有一个计算最大公约数的方法,如果向该方法传递负整数,方法就抛出定义的异常.
程序代码:
class NopositiveException extends Exception//子定义的异常类
{ String message;
NopositiveException(int m,int n)
{ message="数字"+m+"或"+n+"不是正整数";
}
public String toString()
{ return message;
}
}
class Computer
{ public int getMaxCommonDivisor(int m,int n) throws NopositiveException//声明NopositiveException自定义的异常类
{ if(n<=0||m<=0)//不满足条件时候
{ NopositiveException exception=new NopositiveException(m,n);//创建自定义异常类的对象,用来抛出异常
throw exception; //抛出异常,结束方法的执行
}
if(m<n)
{ int temp=0;
temp=m;
m=n;
n=temp;
}
int r=m%n;
while(r!=0)
{ m=n;
n=r;
r=m%n;
}
return n;
}
}
public class E
{ public static void main(String args[])
{ int m=24,n=36,result=0;
Computer a=new Computer();
try { result=a.getMaxCommonDivisor(m,n);
System.out.println(m+"和"+n+"的最大公约数 "+result);
m=-12;
n=22;
result=a.getMaxCommonDivisor(m,n);
System.out.println(m+"和"+n+"的最大公约数 "+result);
}
catch(NopositiveException e)
{ System.out.println(e.toString());
}
}
}
4. Class 类
Class
是java.lang包中的类,该类的实例用来封装对象运行时的状态.当一个类被加载且创建对象时,和改类相关的一个类型为Class的对象就会自动创
建.Class类本身不提供构造方法,因此,不能用new运算符和构造方法创建一个Class对象.任何对象调用getClass()方法都可以获取和该
对象相关的一个Class对象,这个Class对象调用如下的方法可以获取创建对象的类的有关信息,比如类的名字,类中的方法名称,成员变量的名称等.
String getName() //返回类的名字
Constructor[] getDeclaredConstructors() //返回类的全部构造方法
Field[] getDeclaredFields() //返回类的全部成员变量
Method[] getDeclaredMethods() //返回类的全部方法
执行下面的例子来演示这几个函数的作用,如
程序代码:
import java.lang.reflect.*;
class Rect
{ double width,height,area;
public double getArea()
{ area=height*width;
return area;
}
}
public class E
{ public static void main(String args[])
{ Rect rect=new Rect();
Class cs=rect.getClass();//通过getClass来获取rect这个对象
String className=cs.getName();
Constructor[] con=cs.getDeclaredConstructors();
Field[] field=cs.getDeclaredFields() ;
Method[] method=cs.getDeclaredMethods();
System.out.println("类的名字:"+className);
System.out.println("类中有如下的成员变量:");
for(int i=0;i<field.length;i++)
{ System.out.println(field.toString());
}
System.out.println("类中有如下的方法:");
for(int i=0;i<method.length;i++)
{ System.out.println(method.toString());
}
System.out.println("类中有如下的构造方法:");
for(int i=0;i<con.length;i++)
{ System.out.println(con[i].toString());
}
}
}
创建对象最常用的方式就是使用new运算符和类的构造方法,实际上也可以使用Class对象得到一个类的实例.为了得到一个类的对象,可以先得到一个和该类相关的Class对象,做到这点并不是难,只要使用Class的类方法:
public static Class forname(String className) throws ClassNotFoundException
就可以返回一个和参数calssName指定的类相关的Class对象.再让这个Class对象调用
public Object newInstance () throws InstantiationException,IllegalAccessException
方法就可以得到一个className类的对象.
要特别注意的是,使用Class对象调用newInstance()实例化一个className类的对象时,className类必须有无参数的构造方法.
看看下面的例子,如
程序代码:
class Rect
{ double width,height,area;
public double getArea()
{ area=height*width;
return area;
}
}
public class
{ public static void main(String args[])
{ try{ Class cs=Class.forName("Rect");//没有通过new来创建对象,用forname()制定类的实例
Rect rect=(Rect)cs.newInstance();//得到此实例即创建对象
rect.width=100;
rect.height=200;
System.out.println("rect的面积"+rect.getArea());
}
catch(Exception e){}
}
}
5.基本类型的类
java
的基本数据类型包括byte,int,short,long,float,double,char.java同时也提供了基本类型相关的类,实现了对基本
类型的封装.这些类在java.lang包中,分别是Byte,Integer,Short,Long,Float,Double,Character
这些基本类型都有自己的构造方法,如
Double(double num) //创建了一个Double类型的对象 并调用doubleValue()方法可以返回该对象含有double型数据
Float(float num) //创建了一个Float类型的对象 并调用floatValue()方法可以返回该对象含有float型数据
Byte(byte num) //创建了一个Byte类型的对象 并调用byteValue()方法可以返回该对象含有byte型数据
Integer(int num) //创建了一个Integer类型的对象 并调用intValue()方法可以返回该对象含有int型数据
Short(short num) //创建了一个Short类型的对象 并调用shortValue()方法可以返回该对象含有short型数据
Long(long num) //创建了一个Long类型的对象 并调用longValue()方法可以返回该对象含有long型数据
Character类实现了对char基本型数据的类包装.
可以使用Character的构造方法:
Character (char c)
创建一个Character类型的对象.Character对象调用charValue()方法可以返回该对象含有的char类型数据.
Character类还包括了一些类方法,这些方法可以直接通过类名调用,用来进行字符分类,比如判断一个字符是否是数字字符或改变一个字符的大小写等.
public static boolean isDigit(char ch) //如果ch是数字字符,方法返回true,否则返回false
public static boolean isLetter(char ch) //如果ch是字母,方法返回true
public static boolean isLetterOrDigit(char ch) //如果ch是数字字符或者字母,方法返回true
public static boolean isLowerCase(char ch) //如果ch是小写字母
public static boolean isUpperCase(char ch) //如果ch是大写字母
public static char toLowerCase(char ch) //返回ch的小写形式
public static char toUpperCase(char ch) //返回ch的大写形式
public static boolean isSpaceChar(char ch) //如果是空格,返回true
通过下面的例子掌握Character类的这些成员方法的使用,如
程序代码:
public class E
{ public static void main(String args[ ])
{ char a[]={'a','b','c','D','E','F'};
for(int i=0;i<a.length;i++)
{ if(Character.isLowerCase(a[i]))
{ a[i]=Character.toUpperCase(a[i]);
}
else if(Character.isUpperCase(a[i]))
{ a[i]=Character.toLowerCase(a[i]);
}
}
for(int i=0;i<a.length;i++)
{ System.out.print(" "+a[i]);
}
}
}
总结:此小节主要将了一些特殊的类的用法[/i][/i][/i][/i][/i][/i][/i][/i]
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
第九节课
字符串
1.什么是字符串
java使用java.lang包中的String类来创建一个字符串变量,因此字符串变量是一个对象.
a) 字符串常量
如, "你好","bc-cn","12345789"
字符串常量在内存中一但定义,地址空间是不可改变的,直到程序结束.就是说字符串常量在内存中有固定的地址.
b) 声明字符串
String str;
c) 创建字符串
使用String类的构造方法,例如:
str=new String("I like bc-cn.net"); //当然如果没有声明直接创建也是可以的,回忆一下匿名类的概念
声明和创建可以一步完成:
String str=new String("I like bc-cn.net");
也可以用一个已创建的字符串创建另一个字符串,如
String s=String(str);
String类还有两个比较常用的构造方法.
(1)String (char a[]) //用一个字符数组a创建一个字符串对象,如
char a[]={'b','o','y'};
String s=new=new String(a);
上述过程相当于:
String s=new String("boy");
(2)String(char a[],int startIndex,int count)
提取字符数组a中的一部分字符创建一个字符串对象,参数startIndex和count分别指定在a中提取字符的起始位置(例如第一位置从0开始依次类推)和从该位置开始截取的字符个数,例如
char a[]={'s','t','b','u','s','n'};
String s=new String(a,2,3); //从2开始,即第三个位置(b),截取3个字符
上述过程相当于:
String s=new String("bus");
d)引用字符串常量对象
字符串常量是对象,因此可以把字符串常量的引用赋值给一个字符串变量,例如:
String s1,s2;
s1="how are you";
s2="how are you";
分析:"how are you"是个字符串常量,所以在内存中的地址是固定的,赋值给了s1和s2,就说明s1和s2用的是同一个空间
2.字符串的常用方法
1)public int length()
使用String类中的length()方法可以获取一个字符串的长度,如
String s="we are student",tom="我们是学生";
int n1,n2,n3;
n1=s.length(); //n1的值是15
n2=tom.length(); //n2的值是5.
n3="we are student=我们是学生".length();// n3的值是21
2)public boolean equals(String s)
字符串对象调用String类中的equals方法,比较当前字符串对象的实体是否与参数指定的字符串s的实体相同,如:
String tom=new String("we are student");
String boy=new String("We are students");
String jerry=new String(tom);
则:tom.equals(boy)或tom.equals(jerry) 的值都是true 因为比较是是实体,即字符串本身(各个位置的字符与长度是否相同)
注意:如果是tom==jerry或tome==boy 的值就是false,因为new了之后,字符串就是对象,tom,boy,jerry是引用值(地址),因为每个对象在创建后都有自己的内存空间,所以用"=="比较当然会不同喽
字符串对象调用public boolean equalsIgnoreCase(String s) 比较当前字符串对象与参数指定的字符串s是否相同,比较时候忽略大小写.
仔细体会下面的例子:
程序代码:
class E
{ public static void main(String args[])
{ String s1,s2;
s1=new String("we are students");
s2=new String("we are students");
System.out.println(s1.equals(s2));//字符串实体相同,输出结果是true
System.out.println(s1==s2); //对象各自分配的空间不同,输出结果为false
String s3,s4;
s3="how are you";
s4="how are you";
System.out.println(s3.equals(s4)); //同一个空间,结果为true
System.out.println(s3==s4); //同一个空间,结果为true
}
}
3)public boolean startsWith(String s) 和public boolean endWith(String s)
字符串对象调用startsWith(String s)方法,判断当前字符串对象的 前缀 是否是参数指定的字符串s,如
String tom="bbs.bc-cn.net",jerry="www.bc-cn.net";
tom.startsWith("bbs")的值是true
jerry.startsWith("bbs")的值是false
同样,endWith(String s)判断的就是后缀
字符串对象调用public boolean startsWith(String prefix,int toffset)方法,判断当前字符串从toffset索引处开始的前缀是否是参数指定的字符串prefix,如:
String str="123456";
boolean boo=str.startsWith("456",3)// 很容易看出来,boo的值应该是true
4)public boolean regionMatches(int firstStart,String other,int otherStart,int length)
字
符串调用此方法,从当前字符串参数firstStart指定的位置开始处,取长度为length的一个子串,并将这个子串和参数other指定的一个子串
进行比较.其中,other指定的字符串是从参数otherStart指定的位置开始,从other中取长度为length的一个子串.如果两个子串相同
则该方法返回true
使用该方法的重载方法:
public boolean regionMatches(boolean b,int firstStart,String other,int otherStart,int length)
可以通过参数b决定是否忽略大小写,当b为ture时,忽略大小写
这个方法描述起来虽然罗嗦,但看完下面的例子就很容易掌握了,如
程序代码:
class E
{ public static void main(String args[])
{ int number=0;
String s="student;entropy;engage,english,client";
for(int k=0;k { if(s.regionMatches(k,"en",0,2))//k是第一个串的其实位置,0是"en"的其实位置,2是每次取的子串的长度
{ number++;
}
}
System.out.println("number="+number);
}//这个例子很容易看出是在统计s中出现en的次数
}
5)public int compareTo(String s)
字符串对象可以使用String类中的compareTo(String s)的方法,按字典序与参数s指定的字符串比较大小.如果当前字符串与s相同,该方法返回值0;如果当前字符串对象大于s,该方法返回正值;如果小于s,该方法返回负值.例如:
String str="abcde";
str.compareTo("boy")小于0
str.compareTo("aba")大于0
str.compareTo("abcde")等于0
按字典序比较两个字符串还可以使用public int compareToIgnoreCase(String s) 该方法忽略大小写
看看下面的例子是将一个字符串数组按字典序重新排序
程序代码:
class E
{ public static void main(String args[])
{ String a[]={"door","apple","Applet","girl","boy"};
for(int i=0;i { for(int j=i+1;j { if(a[j].compareTo(a)<0)//如果当前字符串比下一个字符串字典序号大,交换
{ String temp=a;
a[i]=a[j];
a[j]=temp;
}
}
}
for(int i=0;i { System.out.print(" "+a[i]);
}
}
}
6)public int indexOf(String s)
字符串对象调用indexOf(String s)方法从当前字符串的头开始检索字符串s,并返回首次出现s的位置.如果没有检索到字符串s,该方法返回-1.
字符串调用public int indexOf(String s,int startpoint)方法从当前字符串的startpoint位置处开始检索字符串s,并返回首次出现s的位置.如果没有检索到返回-1.
字符串调用public int lastIndexOf(String s)方法从当前字符串的头开始检索字符串s,并返回最后出现s的位置.如果没有检索到返回-1.
如:
String s="bbs.bc-cn.net";
s.indexOf("b"); //值为0
s.indexOf("b",3); //值为4
s.lastIndexOf(".");//值为9 即net前面那个"."
7)public String substring(int startpoint)
字符串对象调用该方法获得一个当前的字符串的子串,该子串是从当前字符串的startpoint处截取到字符串的末尾处所得到的字符串.
字符串对象调用substring(int start,int end)方法获得一个当前字符串的子串,该子串是从当前串的start处截取到end处所得到的字符串,但不包括end处所对应的字符.
例如:
String tom="I love tom";
string s=tom.substring(2,5);// 得到的s应是"lov"
8)public String replaceAll(String oldString,String newString)
字符串对象调用该方法可以获得一个串对象,这个串对象是通过参数newString指定的字符串替换s中由oldString指定的所有字符串而得到的字符串.
字
符串对象调用public String replaceFirst(String oldString,String
newString)方法可以获得一个串对象,这个串对象是通过用参数newString指定的字符串替换s中出现的第一个oldString指定字符串
而得到得字符串.
例如:
String tom="hello,tom";
String jerry=new String(tom.replaceAll("tom","jerry")); //jerry的应该是"hello,jerry"
9)public String trim()
字符串常量调用此方法得到一个字符串对象,该字符对象是s去掉前后空格后的字符串.
如:
程序代码:
class E
{ public static void main(String args[])
{ String path="c:\\myfile\\2000\\result.txt";
int index=path.lastIndexOf("\\"); //得到最后出现'\'的位置,注意'\'是转移字符,要想单独表示'\'时应该写成"\\"
String fileName=path.substring(index+1);//得到'\'后面的子串即result.txt
String newName=fileName.replaceAll(".txt",".java"); //把result.txt中的txt替换成java
System.out.println(path);
System.out.println(fileName); //输出应为result.txt
System.out.println(newName); //输出应为result.java
}
}
3.字符串与基本数据的相互转换
a)
java.lang包中的Integer类调用其类方法:
public static int parseInt(String s)
其可以将"数字"格式的字符串,如"123456",转化为int型数据,例如
int x;
String s="123456";
x=Integer.parseInt(s);//整形x值为123456
类似的还有Byte,Short,Long,Float,Double类调相应的类方法:
byte Byte.parseByte(String s); //将字符串转换为byte格式
short Short.parseShort(String s);
long Long.parseLong(String s);
float Float.parseFloat(String s);
double Double.parseDouble(String s);
注意使用这些时候要放在try-catch中捕获异常 NumberFormatException ,后面会有例子格式说明
b)可以用下列的方法把数字型变量转换为字符串:
public static String valueOf(byte n)
public static String valueOf(int n)
public static String valueOf(long n)
public static String valueOf(float n)
public static String valueOf(double n)
如: String str=String.valueOf(12345678.9);
c)可以用下列方法(Long 类)得到整数的各种进制的字符串:
public static String toBinaryString(long i)
public static String toOctalString(long i)
public static String toHexString(long i)
public static String toString(long i,int p)
其中的toString(long i,int p)返回整数i的p进制表示
下面一个转换的综合例子,仔细体会一下:
程序代码:
public class E
{ public static void main(String args[])
{ double n,sum=0,item=0;
boolean computable=true;
for(int i=0;i { try{ item=Double.parseDouble(args[i]);
sum=sum+item;
}
catch(NumberFormatException e)
{ System.out.println("您键入了非数字字符:"+e);
computable=false;
}
}
if(computable)
{ n=sum/args.length;
System.out.println("平均数:"+n);
}
int number=123456;
String binaryString=Long.toBinaryString(number);
System.out.println(number+"的二进制表示:"+binaryString);
System.out.println(number+"的十六进制表示:"+Long.toString(number,16));
String str="1110110";
int p=0,m=0;
for(int i=str.length()-1;i>=0;i--)
{ char c=str.charAt(i);
int a=Integer.parseInt(""+c);
p=p+(int)(a*Math.pow(2,m));
m++;
}
System.out.println(str+"的十进制表示:"+p);
}
}
分析:应用程序中的main方法中的参数args能接受从键盘输入的字符串.首先编译源文件:
编译通过后,输入java E 12 15 16 36 回车
这时,程序中的args[0],args[1],args[2],args[3]分别得到字符串12,15,16和36.在程序中再将这些字符串转换为数值进行计算,得到所需的结果.
上述例子输出结果为:
平均数:19.75
123456的二进制表示:11110001001000000
123456的十六进制表示:1e240
1110110的十进制表示:118
4.对象的字符串表示
所有的类都默认时java.lang包中Object类的子类或者间接子类.Object类有一个public方法toString,一个对象通过调用该方法可以获得该对象的字符串表示.如:
程序代码:
import java.util.Date;
import java.awt.*;
public class E
{ public static void main(String args[])
{ Date date=new Date();//Date包中的类 获取系统当前时间
Button button=new Button("确定");//awt包中的类
System.out.println(date.toString());//date的属性用字符串表示,即当前系统时间
System.out.println(button.toString());//把button的属性用字符串表示出来,(即位置,大小,可用,名称等等)
}
}
显示结果为:
Sun Nov 26 20:38:30 CST 2006
java.awt.Button[button0,0,0,0x0,invalid,lable=确定]
5.StringTokenizer类
StringTokenizer(String s) 为字符串s构造一个分析器.使用默认的分隔符集合,即空格符(若干个空格被看成一个空格),换行符,回车符,Tab符,进纸符.
StringTokenizer(String s,String dilim) 为字符串s构造一个分析器,参数dilim中的字符被作为分隔符.
如:StringTokenizer fenxi=new StringTokenizer("we are student");//用空格区分单词
StringTokenizer fenxi=new StringTokenizer("we,are ;student",", ; ");//用"," 和";"还有空格来区分单词
StringTokenizer
可以用nextToken()方法逐个获取字符串中的语言符号(单词),每当调用nextToken()时,都将在字符串中获得下一语言符号,每当获取到
下一个语言符号,字符串分析器中负责计数的变量的值就自动减一,该计数变量的初始值等于字符串中单词的个数.通常用while循环来逐个获取语言符号,为
了控制循环,可以使用StringTokenizer类中的hasMoreTokens()方法,只有字符串中还有语言符号,即计数变量的值大于0,该方
法就返回true,否则返回false.另外还可以随时让分析器调用countTokens()方法得到分析器中计数变量的值.
通过下面的例子理解StringTokenizer类的使用,如
程序代码:
import java.util.*;
public class E
{ public static void main(String args[])
{ String s="I am Geng.X.y and she is my girlfriend";
StringTokenizer fenxi=new StringTokenizer(s," ,");
int number=fenxi.countTokens();
while(fenxi.hasMoreTokens())
{ String str=fenxi.nextToken();
System.out.println(str);
System.out.println("还剩"+fenxi.countTokens()+"个单词");
}
System.out.println("s共有单词:"+number+"个");
}
}[/i][/i][/i]
字符串
1.什么是字符串
java使用java.lang包中的String类来创建一个字符串变量,因此字符串变量是一个对象.
a) 字符串常量
如, "你好","bc-cn","12345789"
字符串常量在内存中一但定义,地址空间是不可改变的,直到程序结束.就是说字符串常量在内存中有固定的地址.
b) 声明字符串
String str;
c) 创建字符串
使用String类的构造方法,例如:
str=new String("I like bc-cn.net"); //当然如果没有声明直接创建也是可以的,回忆一下匿名类的概念
声明和创建可以一步完成:
String str=new String("I like bc-cn.net");
也可以用一个已创建的字符串创建另一个字符串,如
String s=String(str);
String类还有两个比较常用的构造方法.
(1)String (char a[]) //用一个字符数组a创建一个字符串对象,如
char a[]={'b','o','y'};
String s=new=new String(a);
上述过程相当于:
String s=new String("boy");
(2)String(char a[],int startIndex,int count)
提取字符数组a中的一部分字符创建一个字符串对象,参数startIndex和count分别指定在a中提取字符的起始位置(例如第一位置从0开始依次类推)和从该位置开始截取的字符个数,例如
char a[]={'s','t','b','u','s','n'};
String s=new String(a,2,3); //从2开始,即第三个位置(b),截取3个字符
上述过程相当于:
String s=new String("bus");
d)引用字符串常量对象
字符串常量是对象,因此可以把字符串常量的引用赋值给一个字符串变量,例如:
String s1,s2;
s1="how are you";
s2="how are you";
分析:"how are you"是个字符串常量,所以在内存中的地址是固定的,赋值给了s1和s2,就说明s1和s2用的是同一个空间
2.字符串的常用方法
1)public int length()
使用String类中的length()方法可以获取一个字符串的长度,如
String s="we are student",tom="我们是学生";
int n1,n2,n3;
n1=s.length(); //n1的值是15
n2=tom.length(); //n2的值是5.
n3="we are student=我们是学生".length();// n3的值是21
2)public boolean equals(String s)
字符串对象调用String类中的equals方法,比较当前字符串对象的实体是否与参数指定的字符串s的实体相同,如:
String tom=new String("we are student");
String boy=new String("We are students");
String jerry=new String(tom);
则:tom.equals(boy)或tom.equals(jerry) 的值都是true 因为比较是是实体,即字符串本身(各个位置的字符与长度是否相同)
注意:如果是tom==jerry或tome==boy 的值就是false,因为new了之后,字符串就是对象,tom,boy,jerry是引用值(地址),因为每个对象在创建后都有自己的内存空间,所以用"=="比较当然会不同喽
字符串对象调用public boolean equalsIgnoreCase(String s) 比较当前字符串对象与参数指定的字符串s是否相同,比较时候忽略大小写.
仔细体会下面的例子:
程序代码:
class E
{ public static void main(String args[])
{ String s1,s2;
s1=new String("we are students");
s2=new String("we are students");
System.out.println(s1.equals(s2));//字符串实体相同,输出结果是true
System.out.println(s1==s2); //对象各自分配的空间不同,输出结果为false
String s3,s4;
s3="how are you";
s4="how are you";
System.out.println(s3.equals(s4)); //同一个空间,结果为true
System.out.println(s3==s4); //同一个空间,结果为true
}
}
3)public boolean startsWith(String s) 和public boolean endWith(String s)
字符串对象调用startsWith(String s)方法,判断当前字符串对象的 前缀 是否是参数指定的字符串s,如
String tom="bbs.bc-cn.net",jerry="www.bc-cn.net";
tom.startsWith("bbs")的值是true
jerry.startsWith("bbs")的值是false
同样,endWith(String s)判断的就是后缀
字符串对象调用public boolean startsWith(String prefix,int toffset)方法,判断当前字符串从toffset索引处开始的前缀是否是参数指定的字符串prefix,如:
String str="123456";
boolean boo=str.startsWith("456",3)// 很容易看出来,boo的值应该是true
4)public boolean regionMatches(int firstStart,String other,int otherStart,int length)
字
符串调用此方法,从当前字符串参数firstStart指定的位置开始处,取长度为length的一个子串,并将这个子串和参数other指定的一个子串
进行比较.其中,other指定的字符串是从参数otherStart指定的位置开始,从other中取长度为length的一个子串.如果两个子串相同
则该方法返回true
使用该方法的重载方法:
public boolean regionMatches(boolean b,int firstStart,String other,int otherStart,int length)
可以通过参数b决定是否忽略大小写,当b为ture时,忽略大小写
这个方法描述起来虽然罗嗦,但看完下面的例子就很容易掌握了,如
程序代码:
class E
{ public static void main(String args[])
{ int number=0;
String s="student;entropy;engage,english,client";
for(int k=0;k
{ number++;
}
}
System.out.println("number="+number);
}//这个例子很容易看出是在统计s中出现en的次数
}
5)public int compareTo(String s)
字符串对象可以使用String类中的compareTo(String s)的方法,按字典序与参数s指定的字符串比较大小.如果当前字符串与s相同,该方法返回值0;如果当前字符串对象大于s,该方法返回正值;如果小于s,该方法返回负值.例如:
String str="abcde";
str.compareTo("boy")小于0
str.compareTo("aba")大于0
str.compareTo("abcde")等于0
按字典序比较两个字符串还可以使用public int compareToIgnoreCase(String s) 该方法忽略大小写
看看下面的例子是将一个字符串数组按字典序重新排序
程序代码:
class E
{ public static void main(String args[])
{ String a[]={"door","apple","Applet","girl","boy"};
for(int i=0;i
{ String temp=a;
a[i]=a[j];
a[j]=temp;
}
}
}
for(int i=0;i
}
}
}
6)public int indexOf(String s)
字符串对象调用indexOf(String s)方法从当前字符串的头开始检索字符串s,并返回首次出现s的位置.如果没有检索到字符串s,该方法返回-1.
字符串调用public int indexOf(String s,int startpoint)方法从当前字符串的startpoint位置处开始检索字符串s,并返回首次出现s的位置.如果没有检索到返回-1.
字符串调用public int lastIndexOf(String s)方法从当前字符串的头开始检索字符串s,并返回最后出现s的位置.如果没有检索到返回-1.
如:
String s="bbs.bc-cn.net";
s.indexOf("b"); //值为0
s.indexOf("b",3); //值为4
s.lastIndexOf(".");//值为9 即net前面那个"."
7)public String substring(int startpoint)
字符串对象调用该方法获得一个当前的字符串的子串,该子串是从当前字符串的startpoint处截取到字符串的末尾处所得到的字符串.
字符串对象调用substring(int start,int end)方法获得一个当前字符串的子串,该子串是从当前串的start处截取到end处所得到的字符串,但不包括end处所对应的字符.
例如:
String tom="I love tom";
string s=tom.substring(2,5);// 得到的s应是"lov"
8)public String replaceAll(String oldString,String newString)
字符串对象调用该方法可以获得一个串对象,这个串对象是通过参数newString指定的字符串替换s中由oldString指定的所有字符串而得到的字符串.
字
符串对象调用public String replaceFirst(String oldString,String
newString)方法可以获得一个串对象,这个串对象是通过用参数newString指定的字符串替换s中出现的第一个oldString指定字符串
而得到得字符串.
例如:
String tom="hello,tom";
String jerry=new String(tom.replaceAll("tom","jerry")); //jerry的应该是"hello,jerry"
9)public String trim()
字符串常量调用此方法得到一个字符串对象,该字符对象是s去掉前后空格后的字符串.
如:
程序代码:
class E
{ public static void main(String args[])
{ String path="c:\\myfile\\2000\\result.txt";
int index=path.lastIndexOf("\\"); //得到最后出现'\'的位置,注意'\'是转移字符,要想单独表示'\'时应该写成"\\"
String fileName=path.substring(index+1);//得到'\'后面的子串即result.txt
String newName=fileName.replaceAll(".txt",".java"); //把result.txt中的txt替换成java
System.out.println(path);
System.out.println(fileName); //输出应为result.txt
System.out.println(newName); //输出应为result.java
}
}
3.字符串与基本数据的相互转换
a)
java.lang包中的Integer类调用其类方法:
public static int parseInt(String s)
其可以将"数字"格式的字符串,如"123456",转化为int型数据,例如
int x;
String s="123456";
x=Integer.parseInt(s);//整形x值为123456
类似的还有Byte,Short,Long,Float,Double类调相应的类方法:
byte Byte.parseByte(String s); //将字符串转换为byte格式
short Short.parseShort(String s);
long Long.parseLong(String s);
float Float.parseFloat(String s);
double Double.parseDouble(String s);
注意使用这些时候要放在try-catch中捕获异常 NumberFormatException ,后面会有例子格式说明
b)可以用下列的方法把数字型变量转换为字符串:
public static String valueOf(byte n)
public static String valueOf(int n)
public static String valueOf(long n)
public static String valueOf(float n)
public static String valueOf(double n)
如: String str=String.valueOf(12345678.9);
c)可以用下列方法(Long 类)得到整数的各种进制的字符串:
public static String toBinaryString(long i)
public static String toOctalString(long i)
public static String toHexString(long i)
public static String toString(long i,int p)
其中的toString(long i,int p)返回整数i的p进制表示
下面一个转换的综合例子,仔细体会一下:
程序代码:
public class E
{ public static void main(String args[])
{ double n,sum=0,item=0;
boolean computable=true;
for(int i=0;i
sum=sum+item;
}
catch(NumberFormatException e)
{ System.out.println("您键入了非数字字符:"+e);
computable=false;
}
}
if(computable)
{ n=sum/args.length;
System.out.println("平均数:"+n);
}
int number=123456;
String binaryString=Long.toBinaryString(number);
System.out.println(number+"的二进制表示:"+binaryString);
System.out.println(number+"的十六进制表示:"+Long.toString(number,16));
String str="1110110";
int p=0,m=0;
for(int i=str.length()-1;i>=0;i--)
{ char c=str.charAt(i);
int a=Integer.parseInt(""+c);
p=p+(int)(a*Math.pow(2,m));
m++;
}
System.out.println(str+"的十进制表示:"+p);
}
}
分析:应用程序中的main方法中的参数args能接受从键盘输入的字符串.首先编译源文件:
编译通过后,输入java E 12 15 16 36 回车
这时,程序中的args[0],args[1],args[2],args[3]分别得到字符串12,15,16和36.在程序中再将这些字符串转换为数值进行计算,得到所需的结果.
上述例子输出结果为:
平均数:19.75
123456的二进制表示:11110001001000000
123456的十六进制表示:1e240
1110110的十进制表示:118
4.对象的字符串表示
所有的类都默认时java.lang包中Object类的子类或者间接子类.Object类有一个public方法toString,一个对象通过调用该方法可以获得该对象的字符串表示.如:
程序代码:
import java.util.Date;
import java.awt.*;
public class E
{ public static void main(String args[])
{ Date date=new Date();//Date包中的类 获取系统当前时间
Button button=new Button("确定");//awt包中的类
System.out.println(date.toString());//date的属性用字符串表示,即当前系统时间
System.out.println(button.toString());//把button的属性用字符串表示出来,(即位置,大小,可用,名称等等)
}
}
显示结果为:
Sun Nov 26 20:38:30 CST 2006
java.awt.Button[button0,0,0,0x0,invalid,lable=确定]
5.StringTokenizer类
StringTokenizer(String s) 为字符串s构造一个分析器.使用默认的分隔符集合,即空格符(若干个空格被看成一个空格),换行符,回车符,Tab符,进纸符.
StringTokenizer(String s,String dilim) 为字符串s构造一个分析器,参数dilim中的字符被作为分隔符.
如:StringTokenizer fenxi=new StringTokenizer("we are student");//用空格区分单词
StringTokenizer fenxi=new StringTokenizer("we,are ;student",", ; ");//用"," 和";"还有空格来区分单词
StringTokenizer
可以用nextToken()方法逐个获取字符串中的语言符号(单词),每当调用nextToken()时,都将在字符串中获得下一语言符号,每当获取到
下一个语言符号,字符串分析器中负责计数的变量的值就自动减一,该计数变量的初始值等于字符串中单词的个数.通常用while循环来逐个获取语言符号,为
了控制循环,可以使用StringTokenizer类中的hasMoreTokens()方法,只有字符串中还有语言符号,即计数变量的值大于0,该方
法就返回true,否则返回false.另外还可以随时让分析器调用countTokens()方法得到分析器中计数变量的值.
通过下面的例子理解StringTokenizer类的使用,如
程序代码:
import java.util.*;
public class E
{ public static void main(String args[])
{ String s="I am Geng.X.y and she is my girlfriend";
StringTokenizer fenxi=new StringTokenizer(s," ,");
int number=fenxi.countTokens();
while(fenxi.hasMoreTokens())
{ String str=fenxi.nextToken();
System.out.println(str);
System.out.println("还剩"+fenxi.countTokens()+"个单词");
}
System.out.println("s共有单词:"+number+"个");
}
}[/i][/i][/i]
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
回复: [原创]课堂笔记学习java(初级)
6.字符串与字符,字节数组
1)字符串和字符数组
a)用字符数组创建字符串对象
String (char[]) //该构造方法用指定的字符数组构造一个字符串对象
String (char[],int offset,int length) //用指定的字符数组的一部分,即从起始位置offset开始取length个字符构造字符串对象
如前面的例子:
char a[]={'b','o','y'};
String s=new=new String(a);
b)将字符串中的字符复制到字符数组
public
void getChars(int start,int end,char c[],int offset)
//字符串调用此方法将当前的字符串中的一部分字符复制到数组c中,将字符串中从start到end-1位置上的字符复制到数组c中,并从数组c中的
offset处开始存放这些字符,需要注意的是,必须保证数促c能容纳下要复制的字符.
public char[] toCharArray() 字符串对象调用该方法可以初始化一个字符数组,该数组的长度与字符串的长度相等,并将字符串对象的全部字符复制到该数组中.
体会下面俩个例子:
程序代码:
class E
{ public static void main(String args[])
{ char c[],d[],e[];
String s="巴西足球队击败德国足球队";
c=new char[2];
s.getChars(5,7,c,0);
System.out.println(c); //输出击败
d=new char[s.length()];
s.getChars(7,12,d,0);
s.getChars(5,7,d,5);
s.getChars(0,5,d,7);
System.out.println(d);//d[]中保存的是德国足球队击败巴西足球队
e=new char[s.length()];
e=s.toCharArray()
System.out.println(e);//e[]中保存的s的内容即"巴西足球队击败德国足球队"
}
}
程序代码:
class E
{ public static void main(String args[])
{ String s="编程论坛";
char a[]=s.toCharArray();//把字符串转成字符数组
for(int i=0;i { a=(char)(a^'t');//把每个字符都处理下
}
String secret=new String(a);
System.out.println("密文:"+secret);
for(int i=0;i { a[i]=(char)(a[i]^'t');
}
String code=new String(a);
System.out.println("原文:"+code);
}
}
2)字符串和字节数组
和字符数组的形容类似
a)用字节创建字符串对象
String (byte [])
String (byte[],int offset,int length)
b)将字符串转换为字节数组
public byte[] getBytes()
例如:
程序代码:
public class E
{ public static void main(String args[])
{ byte d[]="你我他".getBytes();
System.out.println("数组d的长度是(一个汉字占两个字节):"+d.length);//输出"数组d的长度是(一个汉字占两个字节):6"
String s=new String(d,0,2);
System.out.println(s);//输出"你"
}
}
7.StringBuffer类
前面学习了String字符串对象,String类创建的字符串对象是不可修改的,也就是说String字符串不能修改,删除,替换字符串中的某个字符,即String对象一但创建,那么实体是不可以再发生变化的.
下面介绍StringBuffer类,该类能创建可修改的字符串序列,也就是说,该类对象的实体的内存空间可以自动改变大小,便于存放一个可变的字符序列.比如,一个StringBuffer对象调用用append()方法可以追加字符序列,例如:
StringBuffer s=new StringBuffer("I love this game");
s.append(" !!");
//s的值就变为I love this game !!
1)StringBuffer的构造方法
a)StringBuffer()//无参数,可容纳16个字符,可以通过调用capacity()方法获取当前实体的实际容量
b)StringBuffer(int size)//指定size大小的容量,当存放大于size时,实体容量自动增加,以便存放所增加的字符
c)StringBuffer(String s)//指定实体的初始容量为参数s的长度额外再加16个字符,当超过size大小时,实体容量自动增加,以便存放所增加的字符
注意:可以用String(StringBuffer bufferstring)创建一个字符串的对象
2)StringBuffer类常用的方法
a)append方法//追加字符串,刚刚讲过
b)char charAt(int n)//得到第n(n>=0&&n<=s.capacity())个位置的字符
c)void setCharAt(int n,char ch)//替换第n个位置的字符
d)StringBuffer insert(int index,String str)//再第index的位置插入字符串str,并返回当前对象的引用
e)StringBuffer reverse()//逆置当前对象的实体,并返回当前对象的引用
f)StringBuffer delete(int startIndex,int endIndex)//删除从startIndex~endIndex-1之间的字符串,并返回当前对象的引用
g)StringBuffer replace(int startIndex,int endIndex,String str)//用字符串str替换startIndex~endIndex-1之间的字符串,并返回当前对象的引用
例如:
程序代码:
class E
{ public static void main(String args[ ])
{ StringBuffer str=new StringBuffer("62791720");
str.insert(0,"010-");//在第0个位置插入010-,当前实体变为"010-62791720"
str.setCharAt(7 ,'8'); //把第8个位置的字符设置为8,当前实体变为"010-62781720"
str.setCharAt(str.length()-1,'7');//把最后一个位置的字符设置为7,当前实体变为"010-62781727"
System.out.println(str); //输出当前实体"010-62781727"
str.append("-446");//追加字符串-446,当前实体变为"010-62781727-446"
System.out.println(str);
str.reverse();//逆置当前实体,实体变为644-72718726-010
System.out.println(str);
}
}
总结:字符串是很重要的概念,此节深入理解字符串及其相关方法的应用[/i][/i]
1)字符串和字符数组
a)用字符数组创建字符串对象
String (char[]) //该构造方法用指定的字符数组构造一个字符串对象
String (char[],int offset,int length) //用指定的字符数组的一部分,即从起始位置offset开始取length个字符构造字符串对象
如前面的例子:
char a[]={'b','o','y'};
String s=new=new String(a);
b)将字符串中的字符复制到字符数组
public
void getChars(int start,int end,char c[],int offset)
//字符串调用此方法将当前的字符串中的一部分字符复制到数组c中,将字符串中从start到end-1位置上的字符复制到数组c中,并从数组c中的
offset处开始存放这些字符,需要注意的是,必须保证数促c能容纳下要复制的字符.
public char[] toCharArray() 字符串对象调用该方法可以初始化一个字符数组,该数组的长度与字符串的长度相等,并将字符串对象的全部字符复制到该数组中.
体会下面俩个例子:
程序代码:
class E
{ public static void main(String args[])
{ char c[],d[],e[];
String s="巴西足球队击败德国足球队";
c=new char[2];
s.getChars(5,7,c,0);
System.out.println(c); //输出击败
d=new char[s.length()];
s.getChars(7,12,d,0);
s.getChars(5,7,d,5);
s.getChars(0,5,d,7);
System.out.println(d);//d[]中保存的是德国足球队击败巴西足球队
e=new char[s.length()];
e=s.toCharArray()
System.out.println(e);//e[]中保存的s的内容即"巴西足球队击败德国足球队"
}
}
程序代码:
class E
{ public static void main(String args[])
{ String s="编程论坛";
char a[]=s.toCharArray();//把字符串转成字符数组
for(int i=0;i
}
String secret=new String(a);
System.out.println("密文:"+secret);
for(int i=0;i
}
String code=new String(a);
System.out.println("原文:"+code);
}
}
2)字符串和字节数组
和字符数组的形容类似
a)用字节创建字符串对象
String (byte [])
String (byte[],int offset,int length)
b)将字符串转换为字节数组
public byte[] getBytes()
例如:
程序代码:
public class E
{ public static void main(String args[])
{ byte d[]="你我他".getBytes();
System.out.println("数组d的长度是(一个汉字占两个字节):"+d.length);//输出"数组d的长度是(一个汉字占两个字节):6"
String s=new String(d,0,2);
System.out.println(s);//输出"你"
}
}
7.StringBuffer类
前面学习了String字符串对象,String类创建的字符串对象是不可修改的,也就是说String字符串不能修改,删除,替换字符串中的某个字符,即String对象一但创建,那么实体是不可以再发生变化的.
下面介绍StringBuffer类,该类能创建可修改的字符串序列,也就是说,该类对象的实体的内存空间可以自动改变大小,便于存放一个可变的字符序列.比如,一个StringBuffer对象调用用append()方法可以追加字符序列,例如:
StringBuffer s=new StringBuffer("I love this game");
s.append(" !!");
//s的值就变为I love this game !!
1)StringBuffer的构造方法
a)StringBuffer()//无参数,可容纳16个字符,可以通过调用capacity()方法获取当前实体的实际容量
b)StringBuffer(int size)//指定size大小的容量,当存放大于size时,实体容量自动增加,以便存放所增加的字符
c)StringBuffer(String s)//指定实体的初始容量为参数s的长度额外再加16个字符,当超过size大小时,实体容量自动增加,以便存放所增加的字符
注意:可以用String(StringBuffer bufferstring)创建一个字符串的对象
2)StringBuffer类常用的方法
a)append方法//追加字符串,刚刚讲过
b)char charAt(int n)//得到第n(n>=0&&n<=s.capacity())个位置的字符
c)void setCharAt(int n,char ch)//替换第n个位置的字符
d)StringBuffer insert(int index,String str)//再第index的位置插入字符串str,并返回当前对象的引用
e)StringBuffer reverse()//逆置当前对象的实体,并返回当前对象的引用
f)StringBuffer delete(int startIndex,int endIndex)//删除从startIndex~endIndex-1之间的字符串,并返回当前对象的引用
g)StringBuffer replace(int startIndex,int endIndex,String str)//用字符串str替换startIndex~endIndex-1之间的字符串,并返回当前对象的引用
例如:
程序代码:
class E
{ public static void main(String args[ ])
{ StringBuffer str=new StringBuffer("62791720");
str.insert(0,"010-");//在第0个位置插入010-,当前实体变为"010-62791720"
str.setCharAt(7 ,'8'); //把第8个位置的字符设置为8,当前实体变为"010-62781720"
str.setCharAt(str.length()-1,'7');//把最后一个位置的字符设置为7,当前实体变为"010-62781727"
System.out.println(str); //输出当前实体"010-62781727"
str.append("-446");//追加字符串-446,当前实体变为"010-62781727-446"
System.out.println(str);
str.reverse();//逆置当前实体,实体变为644-72718726-010
System.out.println(str);
}
}
总结:字符串是很重要的概念,此节深入理解字符串及其相关方法的应用[/i][/i]
Admin- Admin
- 帖子数 : 195
总管理员 :
GG鼓励奖 :
魅力王子 :
注册日期 : 08-03-01
人物特征表
幸运者: vip
您在这个论坛的权限:
您不能在这个论坛回复主题