java经典讲稿14.docx
《java经典讲稿14.docx》由会员分享,可在线阅读,更多相关《java经典讲稿14.docx(24页珍藏版)》请在冰豆网上搜索。
![java经典讲稿14.docx](https://file1.bdocx.com/fileroot1/2022-11/24/32254e89-9610-4d40-a492-2122958099ec/32254e89-9610-4d40-a492-2122958099ec1.gif)
java经典讲稿14
9面向对象
在这部分内容中,介绍了java的核心内容,掌握以下内容:
了解面向对象的基本概念
了解面向对象的三个主要特征
掌握类与对象的关系
掌握类的定义
掌握对象的声明与使用
9.1什么是面向对象
程序经历了两个方式:
面向过程、面向对象。
面向过程是看重程序的过程,遇到什么问题解决什么问题;
面向对象是看重程序的分析,先把成型之后的程序设计好,再把问题分解开,一个部分一个部分的解决。
面向对象的三个特征:
封装、继承、多态
封装性:
将对象的属性和方法都隐藏起来,对外不可见,起到对程序的保护作用。
继承性:
扩展类的功能,并省去了很多重复性的劳动。
多态性:
方法的重载、对象的多态。
类与对象的关系是java中最重要的部分,想学习java就必须把类与对象的关系弄清楚。
类:
是一个抽象的描述,是概念性的,对一些具有相同属性和行为的事物的综合描述。
比如说人类。
是人类,就有姓名、性别、年龄、身高、体重、国籍等等共同的属性,也有吃喝拉撒睡共同的行为。
对象:
是一个类中的具体的一个个体。
比如张三是一个学生,李四是一个职员,王五是一个士兵。
类是不能直接使用的,必须实例化一个实体,也就是对象,才能使用。
我可以让张三站起来,但是不能让人类站起来。
概况一点,就是说类是相同属性对象的集合,对象是类的具体实例,类是一个标准,设计的对象都符合这个标准。
类和对象都有其固定的格式,比如说定义一个人类,用class关键字一修饰就行:
classPerson{}
然后是属性,比如姓名和年龄,定义两个变量就行了:
Stringname;//表示姓名
intage;//表示年龄
还有方法,比如吃喝,定义这两个方法:
publicvoideat(){}
publicvoiddrink(){}
这样就完成了一个类的定义。
要使用这个类,必须有一个实例化的对象,格式为:
类名对象名=null;//声明对象
对象名=new类名();//实例化对象
类名对象名=new类名();//这是写到一起的格式
与上面类对应起来,可以这样实例化一个对象:
Personper=newPerson();
这样一来,per作为一个具体的人,就可以使用了。
在程序开发中,一个类用类图来标识这些属性和方法:
Person
name:
String
age:
int
+eat():
void
+drink():
void
第一层写类名,第二层写属性,第三层写方法,有个+标识访问权限。
Personper=newPerson();
在开发中最好还是分着写,不容易报错。
实例化之后就可以对对象属性进行赋值了,也可以使用对象调用方法,比如:
per.name=”张三”;
per.age=30;
per.eat();
per.drink();
我们来把这个程序写全,看看效果如何:
实例25:
Classdemo.java
目标:
使用对象。
文件名:
Classdemo.java
文件路径:
E:
\java\7
学习内容:
定义对象属性和方法
代码内容:
classPerson{
Stringname;//声明姓名属性
intage;//声明年龄属性
publicvoideat(){//定义吃方法
System.out.println("姓名:
"+name+",年龄:
"+age+",调用了吃方法。
");
}
publicvoiddrink(){//定义喝方法
System.out.println("姓名:
"+name+",年龄:
"+age+",调用了喝方法。
");
}
}
publicclassClassdemo{
publicstaticvoidmain(Stringargs[]){
//Personper=newPerson();//创建并实例化对象,开发中最好分着写,如下:
Personper=null;//声明对象
per=newPerson();//实例化对象
per.name="张三";//为per的name属性赋值
per.age=30;//为per的age属性赋值
per.eat();//为per调用吃方法
per.drink();//为per调用喝方法
}
}
运行结果如下:
E:
\java\7>javaClassdemo
姓名:
张三,年龄:
30,调用了吃方法。
姓名:
张三,年龄:
30,调用了喝方法。
如果在代码中没有去实例化per对象,试一下出现了什么,是一个空指向异常,记住这个异常,因为它会经常与我们约会的。
根据对象的格式,我们为person类多实例化几个对象,然后再去调用属性和方法,寻找个汉子或妹子,把宿舍人员全部输出出来。
考虑一个问题,就是两个对象指向一个空间地址的情况,如:
per2=per1;分析一下栈内存和堆内存的指向情况。
再考虑一个问题,就是两个对象分别实例化之后,再出现per2=per1,分析一下情况。
在这里出现了name=李四,age=40的这段空间没有对象引用了,既然占着地方不干活,这就变成了一个垃圾空间,等待java的垃圾回收机制进行回收,数据就丢失了。
9.2java三大特性之封装性
为什么要进行封装呢?
封装就如同我们的皮肤和肌肉,保护着内脏一个道理,如果没有皮肤和肌肉,别人想拿走你的肾脏,只需要拿手一拽就行了。
Java也是一样,对象的属性方法如果不保护起来,别人岂不是想调用什么就能调用什么,还有什么安全可言呢。
封装之后,对象的属性和方法是对外不可见的。
怎么实现封装?
可以使用下面的方式对对象的属性和方法进行封装:
Private属性类型属性名称
Private方法返回值方法名称(参数。
。
。
){}
我们把实例25修改一下,将person类的属性改成:
PrivateStringname;//声明姓名属性
Privateintage;//声明年龄属性
然后再运行一次,这次看到了什么呢,在per对象对属性赋值的时候,无法对封装的属性进行访问了。
怎么访问封装的内容呢?
这些属性我们是要拿来用的,不能访问是肯定不行的,要访问封装之后的属性,就要使用seter()和geter()方法来完成。
Seter()方法是设置属性;geter()方法是访问属性。
比如上面的name属性,就应该写成:
PublicstaticvoidsetName(Stringn){}
PublicStringgetName(){}
注意name中的n是要大写的,因为方法的命名规则,首字母小写,后面每个单词首字母大写。
我们来把实例25都改写完,就变成了下面的实例26:
实例26:
Packagedemo.java
目标:
对象的封装性。
文件名:
Packagedemo.java
文件路径:
E:
\java\7
学习内容:
使用封装方式定义对象属性和方法
代码内容:
classPerson{
privateStringname;//声明姓名属性
privateintage;//声明年龄属性
publicvoidsetName(Stringn){//设置姓名
name=n;
}
publicvoidsetAge(inta){//设置年龄
age=a;
}
publicStringgetName(){//取得姓名
returnname;
}
publicintgetAge(){//取得年龄
returnage;
}
publicvoideat(){//定义吃方法
System.out.println("姓名:
"+name+",年龄:
"+age+",调用了吃方法。
");
}
publicvoiddrink(){//定义喝方法
System.out.println("姓名:
"+name+",年龄:
"+age+",调用了喝方法。
");
}
}
publicclassPackagedemo{
publicstaticvoidmain(Stringargs[]){
Personper=newPerson();//声明并实例化对象
per.setName("张三");//调用setter设置姓名
per.setAge(30);//调用setter设置年龄
per.eat();//为per调用吃方法
per.drink();//为per调用喝方法
}
}
运行一下,看到输出跟前面实例25一样的。
如果要对属性的范围进行限制的话,直接加到seter()方法中即可,假如我们将年龄的范围设置在0-150之间,那么把下面这个条件加进去就完成了验证操作。
if(a>=0&&a<=150){//加入验证
age=a;
}
上面说的是对属性的封装,接下来看方法,也就是构造方法。
构造方法:
只有对一个对象实例化,就是说出了new,就会调用构造方法,Personper=newPerson();中new后面的person()方法就是一个构造方法。
构造方法是干什么用的哪?
构造方法的主要目的就是为类中的属性进行初始化。
构造方法是怎么定义的哪?
Class类名称{
访问权限类名称(参数类型1参数1,参数类型2参数2,。
。
。
){
程序语句(注意构造方法没有返回值)
}
}
注意,构造方法名称必须与类名称保持一致;声明构造方法不能加返回值类型;构造方法不能使用return返回值。
例如:
classPerson{
publicPerson(){//声明构造方法
System.out.println("看到这句话,说明一个新的Person对象诞生了!
!
!
");
}
}
这就是一个构造方法。
在声明对象的时候,是不会调用它的,只是在实例化对象的时候,才会启用构造方法。
例如:
实例27:
Constructdemo.java
目标:
构造方法。
文件名:
Constructdemo.java
文件路径:
E:
\java\7
学习内容:
构造方法在实例化对象时才启用
代码内容:
classPerson{
publicPerson(){//声明构造方法
System.out.println("看到这句话,说明一个新的Person对象诞生了!
!
!
");
}
}
publicclassConstructdemo{
publicstaticvoidmain(Stringargs[]){
System.out.println("这里只声明对象:
Personper=null;");
Personper=null;//声明对象时不会去调用构造方法
System.out.println("这里实例化对象:
per=newPerson();");
per=newPerson();//实例化对象,这时就启用了构造方法
}
}
运行时,先注解实例化对象,输出结果为:
E:
\java\7>javaConstructdemo
这里只声明对象:
Personper=null;
然后取消注解,重新编译运行,输出结果为:
E:
\java\7>javaConstructdemo
这里只声明对象:
Personper=null;
这里实例化对象:
per=newPerson();
看到这句话,说明一个新的Person对象诞生了!
!
!
那么,我们在之前的例子中并没有去写构造方法,为什么还能正常执行呢,其实,这就是java的机制,如果我们没有编写构造方法,java会自行加载一个什么都不做的无参的构造方法:
classPerson{
publicPerson(){//如果什么都不写,自动生成这个无参的什么都不做的构造方法
}
}
构造方法也是方法,那就可以往里面传递参数,比如我们把这个类的封装写全:
classPerson{//定义一个类
privateStringname;//定义类中的name属性,并封装
privateintage;//定义类中的age属性,并封装
publicPerson(Stringn,inta){//声明构造方法,为类中的属性初始化
this.setName(n);//把值赋给name
this.setAge(a);//把值赋给age
}
publicvoidsetName(Stringn){//用seter方法设置name
name=n;
}
publicvoidsetAge(inta){//用seter方法设置age
if(a>0&&a<150){//加上一个范围,看起来像个真事
age=a;
}
}
publicStringgetName(){//用geter方法获得name
returnname;
}
publicintgetAge(){//用geter方法获得age
returnage;
}
publicvoideat(){//定义吃方法
System.out.println("姓名:
"+this.getName()+",年龄:
"+this.getAge()+",调用了吃方法。
");
}
publicvoiddrink(){//定义喝方法
System.out.println("姓名:
"+this.getName()+",年龄:
"+this.getAge()+",调用了喝方法。
");
}
}
这段代码就完完整整的表达了一个类。
代码中的this关键字表示对象本身,this.setName(n)的作用就是name=n。
用this就是把name值传过来的时候也经过检验。
直接等就是裸奔着过来,虽然可行,但是不好。
代码中已经明确的使用了一个构造方法,这时候就不会自动生成无参的啥也不干的构造方法了,所以这个时候再去运行,就会提示一个错误:
E:
\java\7>javacConstructdemo2.java
Constructdemo2.java:
35:
找不到符号
符号:
构造函数Person()
位置:
类Person
per=newPerson();//实例化对象,这时就启用了构造方法
^
1错误
这个错误就是说没有可以调用的构造方法,因为new后面是person(),是个无参的方法,而类中的构造方法是publicPerson(Stringn,inta),带着两个参数过来的,所以实例化per时,应该写成:
per=newPerson("淘淘",8);
找个汉子或妹子,把程序补齐。
构造方法作为方法,也可以使用重载的。
比如把参数的个数改变一下。
找人试一下,奖励自告奋勇的,惩处畏缩不前的。
如果一个对象只用到一次,那可以采用匿名对象的方式,匿名,就是没有名字,上面定义了一个per对象,per就是对象名,只用一次的话,可以直接写成这样的方式:
newPerson("淘淘",8).eat();
这就是匿名对象,没有名字,记住,只用一次的情况才能这样写,否则,会找不到对象的。
9.3分析实例
学习到现在,可以对实际问题进行简单的分析了,在拿到一个具体问题的时候,按照以下的思路走,把问题分析清楚,再着手进行代码的编写,清晰明了。
1,根据问题列出所需要的类;
2,写出类中所有的属性;
3,对列出的属性依次封装;(private)
4,对封装的属性使用seter和geter方法存读;
5,根据需要添加若干构造方法;
6,为主方法添加相应的方法;
7,类中的方法都不要输出,而是交给被调用处进行输出。
现在分析一个问题,比如我们面前的教材,把我们的教材名称和价格还有出版社等信息输出。
在这个问题中,第一步明显有一个类,就是教材,那定义个书类。
classBook{}
第二步,分析属性,有书名,有价格,有出版社,有作者,有isbn号,有了这几个属性,就基本确定了这本教材。
列出来就是:
书名
String
Name
备注
价格
Float
Price
备注
出版社
String
Press
备注
作者
String
Author
备注
Isbn
String
Isbn
备注
第三步,根据这5个属性分别封装,
PrivateStringname;
Privatefloatprice;
PrivateStringpress;
PrivateStringauthor;
PrivateStringisbn;
第四步,为这5个属性分别列出存取的seter和geter方法,共10个:
PublicvoidsetName(Stringn){
Name=n;
}
PublicStringgetName(){
Returnname;
}
PublicvoidsetPrice(floatpe){
price=pe;
}
PublicfloatgetPrice(){
Returnprice;
}
PublicvoidsetPress(Stringps){
press=ps;
}
PublicStringgetPress(){
Returnpress;
}
PublicvoidsetAuthor(Stringa){
author=a;
}
PublicStringgetAuthor(){
Returnauthor;
}
PublicvoidsetIsbn(Stringi){
Isbn=i;
}
PublicStringgetIsbn(){
Returnisbn;
}
第五步,添加构造方法,这里有5个属性,就传5个参数好了:
PublicBook(Stringn,floatpe,Stringps,Stringa,Stringi){
This.setName(n);
This.setPrice(pe);
This.setPress(ps);
This.setAuthor(a);
This.setIsbn(i);
}
第六步,添加方法,比如说打印出这个教材:
Publicvoidprint(){
System.out.println(“教材名称:
”+this.getName()+”教材价格:
”+this.getPrice()+教材出版社:
”+this.getPress()+”教材作者:
”+this.getAuthor()+”教材isbn号码:
”+this.getIsbn());
}
现在完成这个实例:
实例28:
Bookdemo.java
目标:
类的分析。
文件名:
Bookdemo.java
文件路径:
E:
\java\7
学习内容:
分析问题的思路
代码内容:
classBook{
privateStringname;
privatefloatprice;
privateStringpress;
privateStringauthor;
privateStringisbn;
publicvoidsetName(Stringn){
name=n;
}
publicStringgetName(){
returnname;
}
publicvoidsetPrice(floatpe){
price=pe;
}
publicfloatgetPrice(){
returnprice;
}
publicvoidsetPress(Stringps){
press=ps;
}
publicStringgetPress(){
returnpress;
}
publicvoidsetAuthor(Stringa){
author=a;
}
publicStringgetAuthor(){
returnauthor;
}
publicvoidsetIsbn(Stringi){
isbn=i;
}
publicStringgetIsbn(){
returnisbn;
}
publicBook(){}
publicBook(Stringn,floatpe,Stringps,Stringa,Stringi){
this.setName(n);
this.setPrice(pe);
this.setPress(ps);
this.setAuthor(a);
this.setIsbn(i);
}
publicvoidprint(){
System.out.println("教材名称:
"+this.getName()+",教材价格:
"+this.getPrice()+"出版社:
"+this.getPress()+",作者:
"+this.getAuthor()+",isbn:
"+this.getIsbn());
}
}
publicclassBookdemo{
publicstaticvoidmain(Stringargs[]){
Bookbook=null;
book=newBook("java面向对象程序设计",34.00f,"清华大学出版社","耿详义、张跃平","9787-302-21352-9");
book.print();
}
}
运行结果为:
E:
\java\7>javaBookdemo
教材名称:
java面向对象程序设计,教材价格:
34.0出版社:
清华大学出版社,作者:
耿详义、张跃平,isbn:
9787-302-21352-9
这就是类的分析过程。
其中有个句子Bookbook=null,这样的句子初学时很容易犯迷糊,尤其是声明与赋值写在一起,三个单词一样的,只是首字母大小写的问题。
心里一定要清楚的知道,大写的是类,小写的是对象。
回想一下,写别的数据类型都是小写,如int,float等,但是写String的时候,S总是要大写,啥原因,String就是一个类。
在进行一些操作的时候,需要注意一下。
比如赋值:
inti=1,;就是把1赋值给i,在栈内存就搞定了,但是Stringi=”1