黑马程序员技术交流社区
标题: java总结之面向对象,快来补充和完善吧! [打印本页]
作者: 歌癫 时间: 2014-5-5 12:48
标题: java总结之面向对象,快来补充和完善吧!
Java 面向对象
一、面向对象概念
1、什么是面向对象?
① 面向对象是一种思想,是基于面向过程的;
② 面向过程强调的是功能行为;面向对象强调的是具有功能行为的对象。
③ 对象是指具备某些功能的一个整体;任何事物都可以看作为一个对象,面向对象就是我们熟知某些对象的功能,拿来为我所用,是一种思想。举例:餐厅服务员、发廊师傅、人体的免疫系统等等。
2、面向对象的特点:
a) 封装
b) 继承
c) 多态
3、类与对象的关系:
a) 类:就是对现实生活中的事物的描述;
b) 对象:就是这类事物实实在在存在的个体;
c) 映射到java中,类就是关键字class定义的类;对象就是java在堆内存中用new关键字建立的实体。
4、匿名对象的两种使用情况:(匿名对象是对象的简化形式)
a) 当对一个对象的方法(功能)仅调用一次时;
b) 当把一个对象作为实际参数进行传递时;
作者: 歌癫 时间: 2014-5-5 12:49
二、面向对象三特征———封装
1、封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式;
2、好处:
a) 将变化隔离;
b) 方便使用;
c) 提供复用性;
d) 提高安全性;
3、封装原则:
a) 把不需要对外提供的内容都隐藏起来,通过private 声明。
b) 把属性都隐藏,提供公共方法对其访问,通过public 声明;
4、封装内容:(封装也即定义类)
a) 成员变量,对应事物的属性;
b) 成员函数,对应事物的功能行为;
c) 在定义类之前,应该充分对事物的属性和功能行为的分析,再用代码来体现;
5、注意事项:
a) 通常情况下,成员变量一般定义为私有,不对外提供访问,以保证数据的安全性;但可以对外提供公共的访问方法,规范写法:对应属性xxx,提供setXxx()和getXxx()两个方法。
b) 类中不一定有main主函数,主函数只是程序的入口,保证程序能够独立运行,被java虚拟机识别。如果这个类不需要独立运行,则不需要主函数。
6、构造函数:(给对象进行初始化,是函数的一种。任何对象的建立都要初始化)
a) 函数名和类名相同;
b) 不用定义返回值类型;
c) 不可以写return 语句;
d) 如果类中没有定义构造函数,则系统会默认一个空参数的构造函数;例:Person(){}
e) 多个构造函数以重载的形式存在;
f) 构造函数和一般函数的区别:
i. 两种函数的定义的格式不同;
ii. 构造函数是在对象一创建时,就被调用执行,用于初始化,而且初始化动作只执行一次。一般函数,是对象创建后,需要调用才执行,可以被调用多次。
g) 构造函数和构造代码块的区别:
① 构造函数是给与之对应的对象进行初始化,有针对性;
② 构造代码块,是给所有对象进行初始化,只有对象一建立就会调用这个代码块;
7、static 关键字 和 this 关键字
a) Static 关键字:是一个修饰符,用于修饰成员(成员变量和成员方法)
i. 特点:随着类的加载而加载;优先于对象存在;被所有对象共享;可以直接被类名调用;
ii. 注意事项:
①静态方法只能访问静态成员;
②静态方法中不可以写this、super关键字;因为this、super等关键字代表对象,而静态方法的存在,对象可能还不存在;
③主函数是静态的;
b) this关键字:代表本类类型对象的引用;
① 哪个对象在调用this所在的函数,this就代表哪个对象;类中的成员调用,都是由对象来完成的,本类用this来表示。
② 当定义类中功能(方法)时,该方法内部要用到调用该函数的对象时,这时用this 来表示这个对象;但凡本类功能内部使用到了本类对象,都用this表示。
③ this 在构造函数之间调用时,只能放在第一行,因为初始化动作要先执行,且只有一次。
8、对象的初始化过程:
a) 例:Person p = new Person(“zhangsan”,25 );————这句话都做了什么?
i. 因为new用到Person.class,所以 会先找到Person.class文件,并加载到内存中;
ii. 执行该类中的static 代码块,如果存在的话,给Person.class 进行初始化;
iii. 在堆内存中开辟空间,分配内存地址;
iv. 在堆内存中建立对象的特有属性,并进行默认初始化;
v. 对属性进行显式初始化;
vi. 给对象进行构造代码块初始化;
vii. 给对象进行对应的构造函数初始化;
viii. 把内存地址赋给栈内存中的p 变量
9、单例设计模式:
a) 设计模式:解决某一类问题最行之有效的方法。
b) 单例设计模式:解决一个类在内存中只存在一个对象。
举例:多个程序读取一个配置文件时,建议配置文件封装成对象。会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,就需要该配置文件对象在内存中是唯一的。
c) 如何保证对象的唯一性?
① 不让其他程序创建该类对象;通过私有化构造函数来完成;
② 让其他程序可以访问该类对象;通过在类中创建一个私有且静态的本类对象来完成;
③ 为了让其他程序可以访问这个本来对象,对外提供一个公共方法;通过定义一个共有且静态的方法来完成,返回该类对象;
d)实现方式:
① 饿汉式:开发中一般用这种方式,安全,简单;
class Single
{
private Single(){}
private static Single s = new Single();
public static Single getInstance()
{
return s;
}
}
② 懒汉式:对象是方法被调用时,才初始化,也叫做对象的延时加载。存在安全性;解决方式:用到线程锁和双重判断。
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class){
s = new Single();
}
}
return s;
}
}
作者: 歌癫 时间: 2014-5-5 12:52
三、面向对象三特征————继承
1、继承的特点:
a) 提高了代码的复用性;
b) 让类与类之间产生了关系,有了这个关系,才有了多态的特性。
2、注意事项:
a) 千万不要为了获取其他类的功能,简化代码而继承。
b) 必须是类与类之间有所属关系才可以继承。所属关系 is a
c) 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造函数中第一行都有默认的语句super(); 如果父类中没有空参数的构造函数,那么子类的构造函数中,必须通过super语句指定要访问的父类中的构造函数。 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。
3、java中的继承方式:
a) 只支持单继承,不支持多继承;因为多继承容易带来安全隐患。当多个父类中定义了相同功能,而功能的内容不同时,子类对象不确定要运行哪一个。
b) java保留了这种多继承机制,并用另一种体现形式来表示,叫多实现。
c) java支持多层继承。C继承B,B继承A;这就形成了一个继承体系;
4、如何使用继承体系中的功能?
a) 先查阅体系中父类的描述,因为父类是该体系中最共性的功能;
b) 在具体调用时,最好创建最子类对象;因为父类可能不能创建对象(抽象类或接口),创建子类对象可以使用更多的功能,包括基本共性功能,也包括特有功能;
总之就是:查阅父类功能,创建子类对象使用功能。
5、子父类的出现后,成员的变化:
a) 成员变量:
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量用this关键字调用;子类要访问类中的同名成员变量用super关键字调用。Super和this一样,this代表本类对象的引用,super代表父类对象的引用。
b) 成员函数:
如果子类中出现和父类完全相同的函数时,当子类对象调用这个函数,会运行子类函数的内容;如同父类的函数被覆盖一样。这是函数的另一个特性——函数的覆盖;
C)函数的覆盖:
① 必须保证子类函数权限大于等于父类函数的权限,才可以覆盖,否则编译失败;
② 静态只能覆盖静态;
③ 函数的覆盖(重写),子父类方法要一模一样;函数的重载,只看同名函数的参数列表;
6、子类实例化过程:
a) 在对子类对象进行初始化时,父类的构造函数也会运行,因为在子类构造函数的第一行默认有一个隐式的super()语句,super()会默认访问父类中的空参数构造函数;
b) 为什么会有隐式的super()语句呢?因为父类的中的数据子类可以直接获取,所以在子类初始化时,要看父类是如何对这些数据进行初始化的。
c) 子类所有的构造函数都会默认访问父类的空参数构造函数,如果父类中没有空参数构造函数,则要通过super关键字手动指定访问父类非空参数的构造函数。
7、Final关键字
a) 继承的弊端:打破了封装性,对于一些类或者类中的一些功能,是需要被继承或重写的,这就出现final关键字;它可以解决这个问题。
b) Final关键字的特点:
i. 是一个修饰符,可以修饰类、方法、变量;
ii. 被final修饰的类,是一个最终类,不可以被继承;
iii. 被final修饰的方法,是一个最终方法,不可以被重写;
iv. 被final修饰的变量,是一个常量,只能赋值一次;
v. 内部类只能访问被final修饰的局部常量;
8、抽象类:(看不懂的,不明确的)
a) 特点:
i. 抽象方法一定定义在抽象类中;
ii. 抽象方法和抽象类都要被abstract关键字修饰;
iii. 抽象类不可以被new关键字创建对象,调用抽象方法没有意义;
iv. 抽象类中的方法要被使用,必须有子类覆盖其所有抽象方法后,建立子类对象调用;如果子类只覆盖了部分方法,那么这个子类还是抽象类;
b) 抽象类的注意点:
① 抽象类中有构造函数,用于给子类对象进行初始化;
② 抽象类中可以定义非抽象方法;抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。
③ 抽象关键字abstract不能和final、private、static共存;
④ 抽象类中也可以不定义抽象方法;定义抽象方法的目的只是不让该类创建对象;
9、模版方法设计模式:
a) 什么是模版方法设计模式:在定义功能时,功能的一部分是确定的,有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去。由该类的子类去完成;
b) 举例:获取一段程序运行的时间;
abstract class GetTime
{
public final void getTime(){//唯一,防止复写
long star = System.currentTimeMillis();
runCode();
long end = System.currentTimeMillis();
System.out.println("毫秒:"+(end-star));
}
public abstract void runCode();//这部分功能不明确,只声明而不实现
}
class SubTime extends GetTime //继承获取程序运行时间的类
{
//实现父类runCode方法
public void runCode(){
for(int x=0;x<3000;x++){
System.out.println(x);
}
}
}
10、接口:用interface来定义,是一个特殊的抽象类
a) 特点:
i. 接口是对外暴露的规则;
ii. 接口是程序的功能扩展,降低了耦合性;
iii. 接口可以用于多实现;
iv. 类与接口直接是实现关系,而且类可以继承一个类的同时实现多个接口;
v. 接口和接口之间可以有继承关系;
b) 接口和抽象类的区别:
① 抽象类只能被继承,而且只能单继承。 接口需要被实现,而且可以多实现。
② 抽象类中可以定义非抽象方法,子类可以直接继承使用。 接口中都有抽象方法,需要子类去实现。
③ 抽象类使用的是 is a 关系。接口使用的 like a 关系。
④ 抽象类的成员修饰符可以自定义。 接口中的成员修饰符是固定的。全都是public的。
作者: 歌癫 时间: 2014-5-5 12:57
四、面向对象三特征————多态
1、多态:可以理解为事物存在的多种体现形态;举例:人,男人和女人;动物,猫和狗等
2、多态的体现;
a) 父类的引用指向了自己的子类对象;
b) 父类的引用也可以接收自己的子类对象;
3、多态的前提;
a) 必须是类与类之间有关系,要么继承,要么实现;
b) 通常,还有一个前提,存在覆盖;
4、多态的好处;多态的出现,大大的提高了程序的扩展性
5、多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员;不可以访问子类中特有的方法。(前期不能使用后期产生的功能,即访问的局限性)
6、多态中的成员变量和成员函数:
a) 在多态中,成员函数的特点:
i. 在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,没有则编译失败;
ii. 在运行时期:参阅对象所属的类中是否有调用的方法。
iii. 简单总结就是:成员函数带多态调用时,编译看左边---运行看右边;
b) 在多态中,成员变量的特点;
i. 无论编译和运行,都参考左边(引用型变量所属的类)。
c) 在多态中,静态成员函数的特点;
i. 无论编译和运行,都参考左边;
7、多态的应用:
a) 举例:
class 毕姥爷{
void 讲课(){
System.out.println("企业管理");
}
void 钓鱼(){
System.out.println("钓鱼");
}
}
class 毕老师 extends 毕姥爷{
void 讲课(){
System.out.println("JAVA");
}
void 看电影(){
System.out.println("看电影");
}
}
class {
public static void main(String[] args) {
毕姥爷 x = new 毕老师(); //毕老师对象被提升为了毕姥爷类型。
// x.讲课();
// x.看电影(); //错误.
毕老师 y = (毕老师)x; //将毕姥爷类型强制转换成毕老师类型。
y.看电影();//在多态中,自始自终都是子类对象在做着类型的变化。
}
}
B) 如果想用子类对象的特有方法,如何判断对象是哪个具体的子类类型呢?
可以通过一个关键字 instanceof ;//判断对象是否实现了指定的接口或继承了指定的类
格式:<对象 instanceof 类型> ,判断一个对象是否所属于指定的类型。
Student instanceof Person = true;//student继承了person类
8、内部类:
a) 内部类访问规则:
i. 内部类可以直接访问外部类中的成员,包括私有;之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
ii. 外部类要访问内部类,必须建立内部类的对象;
b) 内部类访问格式:
① 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象:
格式————外部类名.内部类名 变量名 = 外部类对象.内部类对象;
Outer.Inner in = new Outer().new Inner();
② 当内部类在成员位置上,就可以被成员修饰符所修饰;
比如:private,将内部类在外部类中进行封装。
static,内部类就具备了静态的特性;
当内部类被static修饰后,只能直接访问外部类的静态成员,出现访问局限。
③ 在外部其他类中,如何直接访问static内部类的非静态成员呢?
new Outer.Inner().function();
④ 在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function();
c) 注意:当内部类定义了静态成员,该内部类必须是静态的;
当外部类中的静态方法,访问内部类时,内部类也必须是静态的;
d) 内部类定义在局部时,
① 不可以被成员修饰符修饰;
② 可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
e) 什么时候定义内部类?
当描述事物时,事物的内部还有事物,该事物用内部类来描述。
因为内部事务在使用外部事物的内容;举例:
class Body
{
private class Xinzang
{
}
public void show()
{
new Xinzang();
}
}
9、匿名内部类:
a) 匿名内部类:没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。
b) 匿名内部类格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。
c) 什么时候使用呢?
i. 当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。 其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。
d) 举例:
//1
new Object(){
void show(){
System.out.println("show run");
}
}.show();
//2
Object obj = new Object(){
void show(){
System.out.println("show run");
}
};
obj.show();
1和2的写法正确吗?有区别吗?说出原因。
写法是正确,1和2都是在通过匿名内部类建立一个Object类的子类对象。
区别:
第一个可是编译通过,并运行。
第二个编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了Object类型,而编译时检查Object类中是否有show方法,所以编译失败。
作者: 刘晶 时间: 2014-5-5 13:06
这不是下载的笔记上的东西吗:L:L
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |