面向对象总结.docx
- 文档编号:6862604
- 上传时间:2023-01-11
- 格式:DOCX
- 页数:15
- 大小:24.60KB
面向对象总结.docx
《面向对象总结.docx》由会员分享,可在线阅读,更多相关《面向对象总结.docx(15页珍藏版)》请在冰豆网上搜索。
面向对象总结
总结
面向对象
面向对象是相对于面向过程而言的
面向过程:
注重的是执行的过程,强调的是执行的动作。
面向对象:
注重的是具体的事物,将具体的功能定义到该事物当中。
以后不用再定义具体功能,只有找到该事物,就已具备了这些功能。
这个事物就称之为对象。
面向对象是复杂的事情简单化
总结面向对象:
1,面向对象是一种符合现在人们思考习惯的一种思想
2,面向对象出现让角色做着转变,从执行者变成了指挥者
3,面向对象将复杂的事情简单化,不再强调过程,而强调对象,找了对象,其实就是找到了方法。
面向对象的开始:
不断地创造对象,使用对象,并维护对象直接的关系,日后开发,先要确定问题领域。
从问题领域中将对象抽取。
功能该定义到那个对象中
原则:
哪个对象对该功能最熟悉,就定义哪个对象。
日后学习和开发,在实现需要时,不用先定义要想有没有具备实现功能的对象,如果有找个对象并指挥这个对象的功能来完成需求即可。
如果没有应用的对象,自己造个对象,将所需功能定义到该对象中,该对象就可以进行复用。
以后使用时,只要找到这个对象,也就找到了这一列功能。
开发变得简单化。
面向对象语言:
有三个特征
封装、继承、多态
类与对象的关系?
计算机语言开发,其实就是不到的使用计算机语言描述现实生活中的事物。
对于java语言,它描述事物时通过类体系的。
类:
就是对现实对象的描述,类其实就是一组对象的共性的属性和行为的一个抽象
对象:
就是该类事物具体实实在在存在的个体。
描述任意一类事物,其实就是在描述该类事物的属性和行为,所有定义类就是在定义属性和行为。
属性对应的就是一个值。
而值不确定。
所有属性对应一个变量。
行为就是一个功能,对应的是类中的函数
定义类其实就是在定义成员,成员包括成员变量和成员函数。
成员变量和局部变量:
类中的属性称为成员变量
定义在函数中的变量称为局部变量
成员变量和局部变量的区别
1.作用范围:
成员变量:
定义在类中,作用于整个类
局部变量:
只在它所属的局部大括号中有效。
必然函数上的参数
2.存储情况
成员变量:
存储在堆内存中,随着对象的存在而存在,当对象变成垃圾被回收时,成员变量会被删除。
局部变量:
存储在栈内存中,当方法被调用时,会被语句执行的时候,才存在。
但方法运行完毕,或者语句被运行完毕时,局部会被自动释放。
3.初始化情况
成员变量:
在堆内存中有默认初始化值。
局部变量:
必须手动初始化后,才可以被自动释放。
匿名对象:
没有名字的对象
是定义对象的一种简化形式。
newCar().run();
使用注意:
1.当对象队方法进行一次调用的时候,可以使用匿名对象对代码进行简化。
如果对象要对成员进行多次调用,必须给对象起个名字,不能在使用匿名对象。
2.匿名对象可以作为参数进行传递。
封装:
是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
将变化隔离
便于使用
提高安全性
提高重用性
封装的原则:
将不需要对外提供的内容都隐藏起来,提供公共方法对其访问。
通常将成员变量私有化,并通过对外提供set和get方法对其进行设置和获取。
私有是封装的一种体现形式。
构造函数
构造函数在对象建立时被直接调用
作用:
用于给对象初始化。
构造函数和一般函数区别:
一般函数时用于定义对象应该具备的功能
而构造函数定义的是,对象在调用功能之前,在建立时,应具备的一些内容。
构造函数是在对象建立时被调用,给对象初始化
一般函数是对象建立后,当对象调用该功能是才会被执行。
this:
就代表所在函数所属对象的引用。
简单说:
那个对象调用this所在的函数,this就代表哪个对象。
this语句只能定义在构造函数的第一行
因为构造函数时初始化动作,初始化动作必须放在第一行。
对象的建立以及初始化过程:
Perosnp=newPerson();
1.将Person.class文件加载进内存。
2.如果p定义函数中,那么在栈内存中开辟一个变量空间p。
3.在堆内存中给对象分配空间
4.给对象中的属性进行默认初始化
5.给对象中的属性进行显示初始化
6.调用构造代码块对对象进行初始化。
7.调用对应的构造函数进行对象初始化。
对象初始化化完毕。
8.将对象内存地址赋值给p变量,让p变量指向该对象。
静态
static是一个修饰符,用于修饰成员
1.静态成员随着类的加载而加载
2.静态成员优先于对象存在
3.静态成员被所有对象所共享
4.静态成员可以被类名直接调用
注意事项:
1.静态方法只能访问静态成员,非静态方法既可以访问静态又可以访问非静态
2.静态方法中不可以使用this,super关键字
简单说:
先进内存的数据不能访问后进内存的数据
3.主函数是静态的
好处:
静态成员多了一种调用方式,可以直接被类名调用,格式:
类名.静态成员
也可一被对象调用
弊端:
静态方法只能访问静态成员,出现了访问局限性。
静态修饰的是对象共享的数据,存放在方法区的静态区中。
非静态是每一个对象的特有数据,存放在对象所在的堆内存中。
1.静态变量也称为类变量,既可以直接被类名调用的变量。
非静态变量成为成员变量,或实例变量,是被对象调用的,是所属具体对象的。
2.静态变量随着类的加载而加载,生命周期最长。
实例变量,随着对象的创建而加载,随着对象消失。
3.静态变量存储在方法区的静态区中。
实例变量存在于对象所属的堆内存中。
4.静态变量数据,被所有对象所共享。
实例变量是对象中的特有数据。
静态变量在静态区中也会进行默认初始化
什么时候使用静态?
成员变量:
当该成员变量所存储的数据,每一个对象都是一样的,这时没有必要把该数据存储到每一个对象中。
只要让所有对象共享该数据即可,就要被static修饰。
成员函数;
当成员函数内并没有访问对象中的特有数据是,就将该方法定义成静态的。
Main主函数
publicstaticvoidmain(String[]args)
public:
jvm调用的函数必须权限足够大。
所有被public修饰。
static:
主函数随着类的加载而加载,jvm不需要创建该类的对象即可以完成对该函数的调用,所有是静态的。
void:
主函数没有返回值。
main:
函数名,之固定的。
(String[]args):
主函数的参数列表,参数类型是:
一个字符串数组类型的参数
args:
参数名
静态代码块static{}
作用:
当类在加载进内存是,如果需要进行一些内容的执行,完成一个类的初始化。
就需要使用静态代码块。
静态代码块在类被加载是被调用。
静态代码块只被掉一次,如果建立多个对象,只有第一个会调用静态代码块。
单例设计模式:
解决的问题:
保证一个类在内存中只存在一个对象。
简单说,保证一个类在内存中的对象唯一性。
如何保证一个类在内存中的对象唯一性呢?
1.为了控制该类的对象建立,不让其他程序建立该类的对象。
2.在本类中自定义一个本类对象
3.对外提供获取该对象的方式。
代码具体体现:
1.私有化构造函数
2.创建一个私有并静态的本类的对象
3.创建一个公共的static方法返回该对象。
帮助文档的建立:
javadoc-d存放地址-author-version文件名.java
继承:
好处:
1.继承的出现,提高了代码的复用性。
2.继承的出现,让类于类产生了关系,导致了面向对象的第三个特征——多态,即继承是多态的前提。
java中只支持单继承,不支持多继承。
(java将多继承进行了改良,避免了安全隐患的产生)。
继承体系:
classA(){}
classB()extendsA{}
classC()extendsB{}
这就是继承体系。
原则:
1.A类中定义的是这个体系中的最共性的功能。
2.要使用这个体系的功能,建议建立最子类的对象来完成调用。
父类是由子类不断向上抽取而来的
A中定义的功能是该体系中最共性的功能
所以要了解这个体系的功能,只要参考A类中的功能即可。
了解后,需要建立对象来调用这些功能,建立C类对象,因为C中可以使用A类中的共性功能,也可以使用C类中的特有功能。
使用一个体系:
1.参照父类功能
2,建立最子类对象。
什么时候定义继承?
只要一个事物是另一个事物的一种。
就可以用继承体现。
如何判断是否应该继承?
可以先设为可以继承,用更简单的方法判断,一个类如果继承了另一个类,那么这个类是否应该具备另一个类的所有的成员。
如果可以,继承有效,如果
不可以,继承无效。
注意:
不应该为了获取另一个类的部分功能就去继承。
这样仅仅是为了提高代码复用性而继承,并没有判断事物之间的关系。
继承中的成员变量:
当子父类中出现同名的成员变量时,这时为了区分两个变量在子类中,用this调用子类的变量。
用super调用父类的变量。
this表示对象的引用
super代表的是父类的存储空间
继承中的成员函数:
当子父类中出现一摸一样的函数时,子类对象在调用该函数时运行的是子类中的函数。
这就是函数的另一个特性:
覆盖(复习,重写)override。
如果要调用父类的方法:
super.方法名()
继承中构造函数:
子类的构造函数运行前,父类的构造函数先运行。
因为子类的构造函数的第一行,有一句默认隐式语句:
super();
子类在实例化的时候,因为子类继承了父类的成员数据,所有必须先看父类是如何对自己的成员变量初始化的。
不让其他类继承:
需要关键字:
final
1.可以修饰类,可以修饰方法,可以修饰变量
2.final修饰的类不能被继承
3.final修饰的方法不能被覆盖
4.final修饰的常量不能被修改
通常程序中会使用一些不会变化的数据。
也就是常见的一些常量值。
比如3.14,那么这个数据直接使用就可以了,但是不利于阅读,所有一般情况下,都会被
被该数据起一个易读的名称。
用final修饰常量,常量名必须都为大写,如果有多个单词构成变量名,就要在单词间加下划线。
抽象类
抽象类就是子类不断抽取而来的,只抽取了子类的功能声明,而没有具体的功能。
抽象类的特点:
1.抽象类和抽象方法必须用abstract关键在修饰。
2.抽象方法一定存放在抽象类中
3,抽象类不可以被实例化。
也就是不可以通过该类建立对象。
因为抽象类建立对象后,调用抽象方法没意义。
4,只有抽象类的子类将抽象类中的抽象方法全都覆盖掉,该子类就可以了建立对象了。
如果只是部分覆盖,那么该子类还是一个抽象类。
抽象的关键字:
abstract
当类中出现了抽象方法后,该类也必须标识成抽象的。
抽象类什么时候定义。
当我们分析事物时,对对象进行描述时,其实就不断把对象中的共性内容向上抽取。
在抽取过程中,发现对象具备相同的功能,但是功能的细节不同。
这时在定义类时,该功能是没有具体的实现的,是由具体的对象来完成的。
那么该功能就是抽象的。
1,抽象类中是否有构造函数。
有。
只要是class定义的类,里面肯定有构造函数。
抽象类中的构造函数,用于给子类提供实例化。
其实抽象类和一般类没什么区别。
该怎么描述事物,就怎么描述。
只不过,有些功能,该是类中无法确定内容个,所以比普通类多了抽象方法。
2,抽象类中是否可以不定义抽象方法。
可以的,没有抽象方法的抽象类存在意义仅仅是不让该类创建对象。
因为创建的没意义。
这种情况在javaawt中有具体体现。
这种情况不多见。
3,抽象关键字和哪些关键字不可以共存。
final:
如果方法被抽象,就需要被覆盖,而final是不可以被覆盖,所以冲突。
编译提示:
非法的修饰符组合:
abstract和final
private:
如果函数被私有了,子类无法直接访问,怎么覆盖呢?
编译提示:
非法的修饰符组合:
abstract和private
static:
不需要对象,类名既可以调用抽象方法。
而调用抽象方法没有意义。
编译提示:
非法的修饰符组合:
abstract和static
接口:
当抽象类中的方法都是抽象的时候,这时可以把该类定义成接口的形式。
1.接口中的方法都是抽象的。
2.接口不可以被实例化
3.只有子类实现了接口中的所有抽象方法后,该子类才可以实例化,否则该子类还是一个抽象类
格式特点
当定义接口时,接口中的常见的成员有两种:
1,全局常量。
2,抽象方法。
而且接口中的成员都有固定的修饰符:
全局常量:
publicstaticfinal
成员方法:
publicabstract
如果要使用接口中的方法,必须定义一个类实现接口中的所有的抽象方法后,该子类才可以建立对象并调用这些方法。
继承和实现的一点小区别:
类与类之间称为继承:
因为该类无论是抽象的还是非抽象的,它内部可以定义非抽象方法,这个方法可以直接被子类使用,所以子类继承就可以应用了。
类与接口是实现关系:
因为接口中的方法全都是抽象的,必须由子类实现完才可以实例化。
所以就用了更确切的关键字来表示。
implements.
类只能单继承,而接口可以被多实现。
因为接口中的方法都没有主体。
接口的出现就避免了单继承的局限性。
父类中定义的该对象的基本功能,而接口中定义的是该对象的扩展功能。
抽象类和接口的区别:
1,
抽象类只能被单继承。
接口可以被多实现。
2,
抽象类中可以定义非抽象方法,直接被子类使用。
接口中只有抽象方法,必须被子类实现后才可以被使用。
3,
抽象类中定义体系中的基本共性功能。
接口中通常定义体系中对象的扩展功能。
4,
接口的出现避免了单继承的局限性。
5,
抽象类被继承,是isa关系。
xx1是xx2中的一种。
接口可以被实现,是likea关系xx1象xx2中的一种。
接口的基本思想:
1,接口就是对外暴露的规则。
2,接口是功能的扩展。
3,接口的出现降低了耦合性(紧密联系程度)。
耦合性的降低就是实现了模块化的开发。
多态:
1,在程序中的体现:
父类引用或者接口引用指向了自己的子类对象。
2,好处:
提高了代码的扩展性,后期的可维护性
3,前提:
(1),类与类之间必须有继承关系或者实现关系。
(2),通常都需要进行覆盖。
4,弊端:
前期调用的时候,只能调用父类中的方法,而不能调用具体子类的特有方法。
因为前期还不知道具体的子类是谁。
多态的思想:
以前:
定义对象,并指挥对象做事情(调用对象方法),当对象多了以后,指挥动作就会很麻烦,这时重新思考这个问题,找到这些对象的共性类型,直接指挥这个共性类型做事情即可。
这样凡是属于这个类型的个体都会执行。
当你想使用子类的特有功能时,需要将父类型转成子类型才可以使用。
注意:
必须保证,这个父类型指向的是该子类型的对象.
可以对传入的对象进行类型的判断。
通过一个关键字来完成:
instanceof:
对象instanceof类型用于判断该对象是否所属于该类型
多态中的细节
在多态中:
成员变量:
编译时期:
看的引用型变量所属的类中是否有所调用的变量.
运行时期:
也是看引用型变量所属的类是否有调用的变量。
简单的话:
成员变量,编译和运行都看等号的左边。
成员函数:
编译时期:
看的引用型变量所属的类中是否有调用的方法。
运行时期:
看的对象所属的类中是否有调用的方法,如果父子出现同名方法,会运行子类中的方法。
因为方法有覆盖特性。
简单说:
对于成员函数,编译看左边,运行看右边。
其实非静态函数,在内存有一个动态绑定机制。
其实就是f指向了具体的子类对象。
编译看到的f所属的Fu类中是否有这个方法。
运行的时候f就绑定到了一个具体的子类对象上,子类对象运行时会覆盖父类中的相同想法,而运行子类的内容。
静态函数:
编译时期:
看的是引用型变量所属的类中是否有调用的方法。
运行时期:
也是看的是引用型变量所属的类中是否有调用的方法。
简单说:
对于静态函数,编译看左边,运行也看左边.
静态函数存放于每一个所属类的静态区中,它是被静态绑定,就是类一加载,就已经有固定所以的调用就是哪个类名。
整体总结:
成员变量和静态成员:
编译和运行都看左边。
只有非静态的成员函数:
编译看左边,运行看右边。
当定义功能时,该功能中有一部分功能是确定,一部分功能是不确定的。
这时将不确定的部分通过一个函数暴露出去,延迟到子类去完成。
这时我们发现解决这类功能部分明确部分不明确需求,用这个思想就可以很高效。
这个思想就成了一个解决该类问题就有效的方案。
起个名字就叫做:
模版方法设计模式。
Object:
java中已有的一个所有类的父类。
也称为根类,你可以把它理解为java中的上帝。
java中的类都是直接或者间接继承自object类。
所有对象都具备方法有哪些呢?
booleanequals(Objectobj):
对对象进行比较。
该方法的默认是比较内存地址,所以很多对象都对该方法进行覆盖。
StringtoString():
将对象变成字符串:
格式:
对象类型@对象哈希值,但是这个结果没什么意义,所以,该方法一般也会被覆盖,建立该对象的自己特有的对应字符串的表现形式。
inthashCode():
获取每一个对象的哈希值,可以理解为是地址值,是通过哈希算法完成的。
ClassgetClass():
获取一个对象的所属字节码文件对象。
voidfinalize():
垃圾回收器调用的垃圾回收方法。
内部类:
访问方式:
内部类可以直接访问外部类中的成员。
外部类想要访问内部类,需要建立内部类对象。
有A类和B类,当A类想要直接访问B类中的成员,而B类又需要建立A类的对象来A类中的成员。
这时,就将A类定义成B类的内部类。
什么时候定义内部类呢?
当分析一个事物时,该事物的内部还有具体的事物,这个具体的事物在使用该事物中的其他成员。
这时就将这个具体的事物用内部类来描述。
比如人体是一个类,人体有心脏,心脏的功能在直接访问人体的其他内容。
这时就将心脏定义在人体类中,作为内部类存在。
而且内部类通常都不会直接对外提供,都会封装到外部类中,外部了一般会通过对外提供方法的形式对其进行访问
内部类只有默认权限修饰符,或者public修饰符时,可以被外部类直接访问到。
注意要保证的是该内部类必须定义在外部类的成员位置上。
格式:
外部类名.内部类名变量=外部类对象.内部类对象;
Outer.Innerin=newOuter().newInner();
in.show();
但是一般不会这么用,因为内部类都会被外部类隐藏,通常都是外部类提供方法获取内部类的对象。
这样可以对获取对象可控。
通常内部类都会被private私有化。
当内部类中如果有静态成员时,该内部类也必须是静态的。
而静态内部类只能访问外部类中的静态成员。
在执行static内部类方法时,两种情况。
1,内部类静态,但是方法没静态。
该方法需要被对象调用执行。
Outer.Innerin=newOuter.Inner();//产生了一个静态内部类对象。
in.show();
2,内部类静态,而且方法也是静态的。
静态内部列随着对象的加载就已经存在了,静态方法随着内部类的加载也存在了。
这时是不需要对象的。
Outer.Inner.show();
非静态的内部类之所以可以直接访问外部类中的成员,那是因为内部类中都持有一个外部类对象引用:
外部类名.this如Outer.this.num
静态的内部类之所以可以直接访问外部类中的静态成员,其实持有的是外部类名。
内部类定义局部位置上,只能访问该局部中的被final修饰的常量
异常:
就是程序运行时出现的不正常情况。
发现当调用者往里传入了除数0,就发生编译通过(语法没错误),而运行失败的情况。
出现一个ArithmeticException:
/byzero一个异常。
运行提前终止,后续的代码就不会在执行了。
其实异常就是程序中出现的问题:
这个问题包括问题的名称,问题的信息,以及问题出现的位置。
这个问题中内部中的有很多,按照面向对象将这个问题封装成了对象。
通过if判断形式,也可以对问题进行处理。
但是这样会导致,问题处理代码和正常的业务流程代码都定义在了一起,不便于阅读,当把问题封装成对象后,当该问题产生后,可以让程序进行跳转有一个特定的区域对问题进行处理。
这样,异常的出现可以使问题处理代码和业务逻辑代码相分离,提高了程序的阅读性。
问题分为两大类:
1,可以处理的问题。
一般用Exception(异常)来进行描述。
这个问题可以有针对性的代码进行处理。
2,重大错误问题,
用Error进行描述。
这个问题发生后,一般不编写针对的代码进行处理,而是要对程序进行修正。
通常都有JVM抛出的问题。
这两个派系,他们的子类都有一个共同特征:
所有子类名成结尾都是以父类名作为后缀。
无论错误,异常,他们都有,名称标识,同时也有问题的信息。
问题出现的位置。
既然有这样的共性可以向上继续抽取。
他们就有了一个共同的父类Throwable,该父类中就定义了该体系中最共性的方法.
StringgetMessage():
获取异常的信息。
StringtoString():
将异常对象变成字符串。
其实该类是覆盖Object类中的toString();
voidprintStackTrace():
打印异常在内存中的详细信息。
直接打印到控制台。
异常的处理:
有两种:
1,抛出。
2,使用java中指定的代码块进行自定义处理。
try
{
需要检测异常的代码;
}
catch(异常类变量)
{
异常处理代码;
}
finally
{
一定会被执行的代码;
}
如果使用到了一个声明了异常的功能时,必须要对应的throws或者try的处理方式。
否则编译失败。
但是有一种特殊情况。
当功能上声明的异常是一个特殊的异常子类时,这时该功能被调用,可以不用任何处理方式,一样可以编译通过。
这个特殊异常就是Exception中的一个子类RuntimeException。
(运行时异常)
异常分两种:
1,编译时被检测的异常.包括除了Exception子类RuntimeException以外的所有异常。
如果在函数上声明,如果调用时,没有处理方式,编译会编译失败。
而且这种异常需要有针对性的处理方式。
是可被处理的。
2,编译时不被检测的异常:
包括RuntimeException以及子类。
该异常也称为运行时异常,如果功能声明了此异常,调用者可以不用任何处理方式。
通过该异常不需声明。
如果发生,就是需要程序停止,对代码进行修正。
自定义异常的步骤:
定义一个类对问题描述。
要想成为异常,必须继承异常类才可以。
这样才可以成为异常体系中的一员。
其实最根本原因:
异常体系和其他对象的不同之处在于异常体系都具备可抛性。
异常的类和对象都可以被两个关键字所操作,而且只有异常体系具备这个特点
哪两个关键字呢?
throwsthrow
自定义异常可以继承Exception
也可以继承RuntimeException。
如果该问题发生,不需要声明需要是调用修正代码,那么就需要继承RuntimeException。
当函数内容通过throw抛出了一个编译时检测的异
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 面向 对象 总结