第3章 面向对象.docx
《第3章 面向对象.docx》由会员分享,可在线阅读,更多相关《第3章 面向对象.docx(34页珍藏版)》请在冰豆网上搜索。
第3章面向对象
第3章面向对象
1.首先为什么选择面向对象语言开发程序。
面向对象编程可以现实生活中真实存在的事物直接映射到程序中。
2.面向过程的缺点:
现实生活中业务需求抽象成算法,直接映射成函数,一旦算法改变,函数便需要重新写,对系统的其他模块影响很多。
当系统模块逐渐复杂,算法与算法之间复杂性大大增强,函数复杂性较高,不适大型项目的开发。
3.程序=算法+数据结构;
面向过程主要研究算法;而面向对象主要研究数据结构。
4.类和对象
类:
简单的说,类就是类型。
一组具有相同特征和功能的事物,我们说,他们是一类的。
普遍的抽象的事物。
对象:
利用一抽象好的类型,创造一个符合这个类型的事物。
怎么区分类和对象:
哲学上讲,人们认识事物的过程可以:
从特殊一般特殊。
比如:
想创建一个显示器的类,可以先找一个具体的现实,研究他有什么特征和功能。
然后抽出一个具有这些特征和功能的模型,这就是一个显示器的类。
利用个类抽象好的类,创造一个具有这个类的特称和功能的事物,这个事物就是对象。
5.现实世界与计算机世界
引申同一个事物,在不同环境下,不同人对其有不同的理解。
在程序中,由于研究领域的不同,需求不同,对同一事物,可能有不同的理解和映射。
在自己的项目中,我们只关心与我们项目有关的事物的特征与功能。
例:
在学生管理系统中,创建学生类没必要设置血型的属性。
6.创建对象的语法:
利用new关键字
数据类型对象=new数据类型();
例:
Stringstr=newString(“ssss”);
new关键字就是调用构造器用的。
利用构造器创建对象并初始化,如果一个变量没有创建对象并初始化,那么这个变量不能使用。
Studentstr=newStudent();
Studentstr为声明一个Student的变量,在内存中的栈空间分配资源。
newStudent()为调用构造方法,创建一个对象,在堆中分配资源;
str=newStudent();利用“=”,把栈中的变量连接到堆中的对象上。
Java中的对象是在堆中创建。
怎么判断是否创建对象,一般看有几个new构造器,一个new构造器,就在堆中开辟一个对象。
用类创建对象也叫对象的实例化。
声明变量是在栈中定义的。
所有基本数据类型全部在栈中定义。
题:
ClassDemoobjectName=newClassDemo();
ClassDemoobjectName2=newClassDemo();
创建了两个对象,因为两个new调用了两次构造方法。
7.类中都能写什么(不包括内部类的情况)
属性:
对应显示生活中事物的特征。
方法:
对应显示生活中事物的功能。
构造器(构造方法,构造函数)
块(静态块,动态块)
8.属性:
对应显示生活中事物的特征。
只能在类中定义(也可以是接口之类)
语法:
修饰符数据类型属性名;
例:
privateStringname;
JVM默认给他们初始化。
所有属性都有默认值:
int为0,复合数据类型默认为null
9.方法:
对应显示生活中事物的功能。
只能在类中定义(也可以是接口之类)
语法:
修饰符方法的返回值类型方法名(参数列表){}
例:
publicvoidsetName(Stringname){}
publicvoidmethod(参数类型1变量1,参数类型2变量2…){}
10.构造器的作用与特点
作用:
就是创建对象并初始化。
特点:
与类名相同,无任何返回类型,这里无返回类型,并不是返回空类型,即void。
如果没有为类定义一个显示的构造方法,那么,系统会为程序提供一个“共有的,无参的构造函数”,如果用户自定义了构造器,那么体统不会为用户再创建一个无参共有的构造器。
用户创建对象时,利用new关键字调用构造函数,如果这个类都没有这个构造函数,那么就不能调用了。
例:
类Student的构造方法:
为publicStudent(参数列表){}
11.块
块分:
静态块:
只在第一次类加载时,执行一次。
动态块:
每创建一个对象,即每调用一次构造,均执行一次。
类中各个部分的执行顺序:
静态块静态方法块构造方法实例方法
publicclassDemo4{
static{
System.out.println("静态块");
}
{
System.out.println("动态块");
}
publicstaticvoidstaticShow(){
System.out.println("静态方法");
}
publicvoidshow(){
System.out.println("普通方法");
}
publicDemo4(){
System.out.println("构造方法");
}
publicstaticvoidmain(String[]args){
Demo4.staticShow();
newDemo4().show();
}
}
打印:
静态块
静态方法
动态块
构造方法
普通方法
12.null为空对象,表示没有创建对象
例:
Stringstr1=“”;创建对象了,可以使用str1
Stringstr2=null;没有创建对象,不可以使用str2
null与“”的区别:
null没有开辟内存空间,“”开辟内存空间,但是,没有存储东西。
因为,只有开辟空间的才能使用,所以,“”可以使用,null不可以。
13.Java源文件中都能写什么
注释除外,Java源文件中不同内容存在顺序之分
packagemypage;//包语句
import包;//倒包语句
class或interface等的定义。
一个Java源文件可以写多个类,但不推荐使用。
14.包:
package关键字
包的作用:
管理并组织代码。
由于不同开发的程序有可能有相同的类或接口,为了使他们同时存在,这时要使用包。
由于一个工程,不同代码完成不同的功能,因此,可以利用包,来区分不同的代码模块,例:
dao包中放操作数据库的类,service包放工程的业务逻辑类等等。
注意:
包名的定义采取小写字母,不要用中文。
包名也不能重复,为了避免包名的重复,企业中采取域名倒转的形式定义包
语法:
package域名.公司名.项目名.模块名…..;
例:
packagecom.px1987.studentsystem.dao;
packagecom.lfy.shoppingsystem.service;
15.面向对象的特点
抽象,封装,继承,多态
抽象:
我们从现实世界,从事物中提取对我们项目有用的东西,提取成概念。
封装:
把抽象成的概念在计算机中写成类,接口等。
例如:
类封装了这个事物的特称和功能。
封装的作用,用于创建类和隐藏类中的信息。
组合:
就在来类中使用了另一个类或接口,也可扩展其他类的。
publicclassDemo5{
privateStringstr;
privateAppleapple;
publicvoidshow(Appleapple){
this.apple=apple;
}
}
16.访问控制权限:
用于封装和隐藏信息的,除内部类外,访问控制权限只能修饰属性,方法,构造器,不能修饰方法内的变量。
分为4中:
public,protected,默认,private
public:
访问权限最高,在此工程下均可以访问。
protected:
只能在本包中的类,或其他包中的子类可以访问。
默认(也就是什么也不写):
在本包中使用。
private:
访问权限最低,只能在本类中使用。
注意:
以后除非程序特殊设计,否则,属性全部私有(private),并为这些属性设置setter和getter方法,由于访问和修改这些属性。
17.继承:
现实生活中,存在着一种继承的关系,继承者会得到被继承的一些特称和功能。
Java中继承利用extends关键字
继承的好处就是:
可以获得父类的某些属性和方法。
继承的坏处就是:
破坏类的封装性。
注意:
Java中只支持单继承,继承的类只能继承父类的共有方法和protected方法。
包括共有属性和protected属性。
例:
publicclassFather{}
publicclassSonextendsFather{}
18.多态(在现实生活同一种事物,在不同的条件,呈现出不同的状态)。
例:
同样是洗的功能,洗衣服与洗车是不一样。
多态在代码中体现2种形式:
重写,重载
重写:
在有继承关系的两个类中,父类具有一个方法A();子类继承方法A(),但是,之类不想拥有和父类一致的方法A(),这样在子类中可以重新定义A()。
publicclassGraph{
publicvoiddrawMe()throwsNullPointerException{
System.out.println("画一个图形");
}
}
publicclassTriangleextendsGraph{
publicvoiddrawMe(){
System.out.println("画一个三角形!
");
}
}
重写特点:
1.必须与父类要重写方法的名字一致。
2.子类重写父类的方法,这个方法的访问权限不能小于父类方法。
3.子类重写父类的方法,抛出的异常不能大于父类抛出的异常。
重载:
在同一个类中,方法名相同,参数列表不同(包括类型不同,数量不同,顺序不同)。
例:
publicclassWasher{
publicvoidwash(){
System.out.println("默认洗15分钟");
}
publicvoidwash(inttime){
System.out.println("洗"+time+"分钟");
}
}
实参与形参:
形参:
当你定义一个方法时,这里方法参数类表,均为形参。
实参:
当你调用这个方法时,为这些方法传入参数时,这些参数叫实参。
例:
publicvoidshow(intnum){}//这里的intnum为形参
show(100);//这里的100为实参
隐式重载:
publicclassFather{
publicvoiddriver(){
System.out.println("开车");
}
}
publicclassSonextendsFather{
publicvoiddriver(Stringticket){
System.out.println("开得是"+ticket+"票的车!
");
}
}
多态也叫做“动态绑定”。
绑定:
绑定是指确定属性和方式归哪个类所有,类型是什么。
例如:
在Test类中有属性name,有方法getName(),那么当你创建一个Test的对像testObject,那么当调用相应的name属性或getName()方法,这个过程就是一个绑定过程,他把Test中的相互属性和方法绑到了你创建的这个对象上。
绑定分为:
前期绑定(编译时绑定)和后期绑定(运行时绑定或动态绑定)。
判断父类声明子类实例化的秘籍:
Java中所有的属性,静态方法全部为前期绑定。
你声明什么类型的对象,那么你调用的属性,就是你声明的类所属的属性。
调用静态方法,也看是谁声明的,就是谁的静态方法。
Java中所有的实例方法(非静态方法)为后期绑定,即动态绑定。
调用方法时,真正调用的是new类型()的方法,真正实例化的对象的方法。
软件工程中推荐使用的一种创建对象的形式:
父类声明子类实例化。
语法:
父类对象=new子类();
例:
Fatherobj=newSon();
一定要看以下程序。
publicclassFather{
publicintage=30;
publicvoidshowMe(){
System.out.println("我是爸爸!
");
}
publicstaticvoidshowSex(){
System.out.println("爸爸是男人");
}
}
publicclassSonextendsFather{
publicintage=5;
publicvoidshowMe(){
System.out.println("我是儿子!
");
}
publicstaticvoidshowSex(){
System.out.println("儿子是男人");
}
}
publicclassTestSon{
publicstaticvoidmain(String[]args){
//当你在eclipse保存时,也就是编译时,第一行,第三行,就已经绑定了,换句话说,这些值,这些类型就已经确定,这就是为什么叫前期绑定。
//由于Java中的实例方法为后期绑定,因此,只有在这个程序运行时,第二行才知道,自己到底调用的是谁的方法。
Fatherobj=newSon();
intage=obj.age;//第一行
System.out.println(age);
obj.showMe();//第二行
obj.showSex();//第三行
}
}
父类声明子类实例化的好处:
当调用这个父类声明子类实例化的对象,可以默认向上转型。
publicclassFruit{
publicvoideat(){
System.out.println("吃水果了~~~");
}
}
publicclassAppleextendsFruit{
@Override
publicvoideat(){
System.out.println("吃苹果");
}
}
publicclassOrangeextendsFruit{
@Override
publicvoideat(){
System.out.println("吃橘子");
}
}
publicclassBananaextendsFruit{
@Override
publicvoideat(){
System.out.println("吃香蕉");
}
}
publicclassPerson{
publicvoideatFruit(Fruitf){
f.eat();
}
}
publicclassTestPerson{
publicstaticvoidmain(String[]args){
Personp=newPerson();
System.out.println("请输入你最爱吃的水果:
");
Scannerscanner=newScanner(System.in);
StringfruitString=scanner.next();
Fruitf=null;
if(fruitString.equals("apple")){
f=newApple();
}elseif(fruitString.equals("orange")){
f=newOrange();
}elseif(fruitString.equals("banana")){
f=newBanana();
}
p.eatFruit(f);
}
}
19.引包语句:
如果你要用到了其他包中的类或接口等。
你需要利用import语句引包。
import包名.*;引入该包中所有的类或接口等。
但是不会引入其中子包中的类。
import包名.类名;引入该包中的这个类
如果使用了多个包中相同的类,不能利用import语句引包。
必须在创建对象时,写出完整的包路径类信息。
例:
a包中有个类Test,b包中也有个类也叫Test,在我的程序中同时要使用两个包中的Test,必须这么写
a.Testtest=newa.Test();
b.Testtest2=newb.Test();
Stringstr=newString();
java.lang.Stringstr=newjava.lang.String();
注意:
所有的类,必须引包才能使用,本包中的类除外。
java.lang.*除外;
20.技术展望:
String的比较。
(1).对字符串类型的比较,要先判断此字符串是否为null,然后在进行比较,防止字符串为空,调用equals方式是,发生空指针异常现象。
例:
比较String变量str,是否等于tom,应该如下比较
if(str!
=null&&str.equals(“tom”)){
语句;
}
(2).利用字符串的反写比较方式,被比较的字符串常量,放到前边,利用字符串常量的equals方法反过来比较str变量,这样不会出现空指针异常问题。
例:
if(“tom”.equals(str)){
语句;
}
21.this与supper关键字
this代表当前类的对象,也就是,this所在的这个类的对象,有系统创建,属于隐式对象。
例:
publicclassThisDemo{
privateStringname;
privateintage;
privateStringsex;
publicvoidsetName(Stringname){
this.name=name;//此处如不写this,阅读不便。
}
publicvoidinit(){
this.show();//代表ThisDemo的对象
this.age=10;
}
}
方法之间的调用过程,内部实现是利用堆栈实现的(后进先出)。
注意:
this关键字不能与static连用。
this的作用:
1.利用this可以直接调用this所在的这个类的属性和方法。
2.利用this还可以在本类的构造方法中调用其他的构造方法。
调用方式为this(参数),且此语句只能在构造器的第一句出现。
不能出现在非构造器中。
publicclassThisDemo{
publicThisDemo(){
this
(1);
System.out.println("无参构造器");
}
publicThisDemo(intnum){
this("22");
System.out.println("int参数的构造器");
}
publicThisDemo(Stringnum){
System.out.println("String参数的构造器");
}
}
super关键字:
super关键字只能出现在由于继承关系的类中。
Java中所有的类均有父类。
如果我们写一个类,并没有显示的extends继承一个父类。
那么他默认继承Object类。
如果一个类Son,继承至父类Father,那么,当你调用子类的构造函数时,默认都会先调用父类的构造,然后在调用子类的构造。
例:
publicclassSuperDemo{
publicSuperDemo(){
System.out.println("父类的构造");
}
}
publicclassSonDemoextendsSuperDemo{
publicSonDemo(){
System.out.println("子类的构造");
}
}
publicclassTestSuperDemo{
publicstaticvoidmain(String[]args){
newSonDemo();
}
}
打印:
父类的构造
子类的构造
注意:
子类的构造必须和父类构造一致,否则,必须利用super关键字显示的调用父类构造。
例:
publicclassSuperDemo{
publicSuperDemo(intnum){
System.out.println("父类的构造");
}
}
publicclassSonDemoextendsSuperDemo{
publicSonDemo(){
super(10);
System.out.println("子类的构造");
}
}
由于父类的构造SuperDemo(intnum),而子类的构造为,SonDemo(),与父类的构造参数不同,因此必须利用super(整形参数),显示调用父类带整数参数的构造。
如果父类与子类均有一个无参的构造,那么子类会隐式调用super()方法。
例:
publicclassSuperDemo{
publicSuperDemo(){
System.out.println("父类的构造");
}
}
publicclassSonDemoextendsSuperDemo{
publicSonDemo(){
super();//此处可有可无,因为即使不写,也会隐式调用super();
System.out.println("子类的构造");
}
}
注意:
super关键字在构造器中使用,只能写在第一行。
在构造其中super关键字不能和this关键字一起使用。
因为不能同时在第一行。
super的作用:
1.显示的调用父类构造,必须写在之类构造器的第一行,如果不写默认调用super();因此如果父类没有无参的构造就会出现编译错误。
2.在子类中,可以调用父类的某些方法(public,protected)。
例:
如果父类有一共有或保护型的方法show(),子类重写了这个方法show(),正常我们调用子类的show方法,但是如果程序需要调用父类的show方法,
super.show();其调用的就是父类的方法。
例:
publicclassSuperDemo{
publicvoidshow(){
System.out.println("父类的show方法");
}
}
public