----------------------Android培训、Java培训、期待与您交流! ----------------------
1 何为面向对象
面向对象(Object-Oriented,简称OO)就是一种常见的程序结构设计方法。
面向对象思想的基础是将相关的数据和方法放在一起,组合成一种新的复合数据类型,然后使用新创建的复合数据类型作为项目的基础。
面向对象是一个很抽象的概念,它相对面向过程而言。过程与对象都是一种解决问题的思想。
面向过程:强调的是功能行为,一种过程,先干啥,再干啥;
面向对象:将功能封装到对象里,强调的是具备某功能的对象;
按照面向对象的思想,可以把任何的东西看做对象。
-----------------------------分割线-----------------------------
封装是干嘛的?
把对象的状态和行为看成一个统一的整体,将二者存放在一个独立的模块中(类);
"信息隐藏", 把不需要让外界知道的信息隐藏起来,尽可能隐藏对象功能实现细节,字段。
封装机制在程序中的体现是:把描述对象的状态用字段表示,描述对象的行为用方法表示,把字段和方法定义在一个类中,并保证外界不能任意更改其内部的字段值,也不许任意调动其内部的功能方法。
-----------------------------分割线-----------------------------
3 面向对象的三大特征之一:继承
继承: 提高代码的复用性;让类与类之间产生了关系,有了这关系,才有了多态的特性。
只有类与类之间有所属关系才可以继承。两者之间都应有同意方法或同一属性时可以继承。
当子类继承父类,沿袭了父类的功能到子类中。但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖函数,保留父类的功能定义,并重写功能内容。
-----------------------------分割线-----------------------------
4 函数的一个特性:覆盖
子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败
静态只能覆盖静态
重载与重写的区别:
重载(Overload):只看同名函数的参数列表
覆盖(Override):子父类方法要一模一样
this:相当于是本类中对象
super:相当于是本类的父类对象
子父类中的构造函数
子类的实例化过程如下:
在对子类对象进行初始化时,父类的构造函数也会执行。那是因为子类的构造函数默认第一行有一条隐式的语句super();
super():会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super()
当父类中没有空参数的构造函数时,子类必须手动通过super或者this方法形式来指定要访问的构造函数。
也就是说,如果需要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。
PS:super()语句只能定义在子类构造函数第一行,this()方法和super()只能择其一。
注意:java中只支持单继承,不支持多继承,只能继承一个类。
java中支持多层继承。如父类的子类可以再被继承。
具体调用时,一般是创建子类的对象。为什么?
原因一:父类可能不可以创建对象;原因二:子类能具有更多的功能。
简单来说:查阅父类的功能,创建子类对象使用功能。
注意:java继承中,访问权限:父类中被private修饰的不能被子类继承,子类在继承时访问权限不能低于父类,比如说父类中是protect修饰的话,子类应当用protect、public
-----------------------------分割线-----------------------------
5 final关键字
final:最终。作为一个修饰符,
①可以修饰类,函数,变量
②被final修饰的类不可以被继承,为了避免被继承,被子类复写功能
③被final修饰的方法不可以被复写
④被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值七个名字,方便于阅读。(PS:常量的书写规范:所有字母都大写,如果由多个单词组成,单词间通过下划线_连接)
⑤ 内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
第5点的 原因:
编译程序实现上有困难,因为内部类对象的生命周期会超过局部变量的生命期。
局部变量的生命期:当该方法被调用时,该方法中的局部变量在栈中被创建,当方法调用结束时,退栈,这些局部变量全部死亡。
内部类对象生命期,与其它类一样,当创建一个局部内部类对象后,只有当没有其它人再引用它时,它才能死亡。所以完全可能一个方法已调用结束(局部变量已死亡),但该局部类的对象仍然活着。即:局部类的对象生命期会超过局部变量。
定义为final后,编译程序的实现方法:将所有的局部内部类对象要访问的final型局部变量,都拷贝成为该内部类对象中的一个数据成员。这样,即使栈中局部变量(含final)已死亡,但由于它是final,其值永不变,因而局部内部类对象在变量死亡后,照样可以访问final型局部变量。
PS:能够修饰class的修饰符只有public、final。
-----------------------------分割线-----------------------------
6 抽象类
抽象类的适用:当多个类中出现了相同的功能,但是功能的主体不一样,这时可以进行向上抽取,此时只抽取功能定义,而不抽取功能主体。
抽象类特点:
①.抽象方法一定在抽象类中
② 抽象类中可以拥有非抽象方法
③ 抽象方法和抽象类都要被关键字abstract修饰
④ 抽象类不可以用new对象创建,因为调用抽象类是没有意义的 (PS:匿名内部类的特例)
⑤ 抽象类中的抽象方法若要被使用,必须由子类复写完所有的抽象方法后,建立子类对象调用;若子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
抽象类与一般类的区别:
没有太大的不同,抽象类主要是在事物的描述时,该事物出现了一些看不懂的东西,这些不能确定的部分(功能),需要明确出现,但是无法定义主体。通过抽象方法来表示。
抽象类比一般类多了个抽象方法,在类中可以定义抽象方法;抽象类不能实例化
-----------------------------分割线-----------------------------
7 接口
接口:一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类就可以用接口来表示
接口中成员都是public的。
接口的格式:
常量:public static final
方法:public abstract
interface Inter
{
public static final int NUM=3;
public abstract void show();
}
格式中public、abstract、final、static修饰符没写,它也会自动补上,但是为了阅读性,建议写全。
接口是不可以创建对象的,因为有抽象方法,需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化,否则子类是一个抽象类。
接口可以被类多实现。只有在接口与接口之间存在多继承。
抽象类和接口异同:相同:
① 都可以在内部定义抽象方法。
② 通常都在顶层。
③ 都不可以实例化,都需要子类来实现。
不同点:
① 抽象类中可以定义抽象方法和非抽象方法,而接口中只能定义抽象方法。(在Java8中接口也可以定义非抽象方法了)
② 接口的出现可以多实现。抽象类只能单继承。也就是说:接口的出现避免了单继承的局限性。
③ 继承和实现的关系不一致。继承:is a,实现:like a 。
-----------------------------分割线-----------------------------
8 面向对象之多态
多态指同一个实体同时具有多种形式。比如说:养个动物,可以养一只狗,也可以养只猫,养条鱼也行,它们都是动物的表示形态。
实现多态的机制:
父类的引用变量可以指向子类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的真正实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。
多态的作用:
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
多态的前提:
必须是类与类之间有关系。要么继承,要么实现;通常还有一个前提:存在覆盖。
多态的好处:
多态的出现大大的提高程序的扩展性。
多态的弊端:
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
-----------------------------分割线-----------------------------
9 多态中引用变量类型转换
向上转型(子类→父类):(自动完成)
父类名称 父类对象 = 子类实例 ;
向下转型(父类→子类):(强制完成)
子类名称 子类对象 = (子类名称)父类实例 ;
切记:多态自始至终都是子类对象在做着变化。
论坛上有个很有意思的比喻,形象的以武侠来形容了多态和继承。特摘到日记历来:继承:你有一个武林高手师父,人称“玉罗刹”,然后你从你师傅那里学到了他的全部武功。
扩展:后来你又自创了你自己的武功。
多态:你现在可以用你师傅的名号“玉罗刹”去行侠仗义,你师父会的你都会。别人可以认为你就是你师父。但是,你不能使用你自己的武功,因为你还带着“玉罗刹”的面具。如果你想要使用自己的武功,就必须先拿下面具(使用强制转换,将父类对象引用转换成子类对象类型)。
java不允许的:你师父不会使用你的武功,所以你师父不能伪装成你(父类对象不能强转成子类对象类型)
然而,你的师傅可以收很多的徒弟,每个徒弟都可以修炼自己的武功,所以到最后,你师父能干的事,他的徒弟们都可以取代他的位置
下面是代码演示:
class A//玉罗刹
{
public void Jiuyinzhenjing()//九阴真经
{
System.out.println("this is A Say");
}
}
class B extends A//你继承了你师父的全部武学
{
public void Rulaishenzhang()//如来神掌
{
System.out.println("this is B Sing");
}
}
public class Duotai
{
public static void main(String[] args)
{
A shifu = new B();
shifu.Jiuyinzhenjing();//使用“玉罗刹”的名号使用九阴真经
B tudi= new B();
tudi.Jiuyinzhenjing();//使用师父的九阴真经
tudi.Rulaishenzhang();//自己使用如来神掌
//a.Rulaishenzhang();//不可以,你师父不会如来神掌
B you;
you = (B)shifu;//你拿下面具,露出真面目,可以使用如来神掌了
you.Rulaishenzhang();
Sharen(shifu);//师父用九阴真经去杀了10000人
Sharen(tudi);//徒弟也可以用九阴真经去杀10000人
}
public static void Sharen(A a)//师父的绝学九阴真经杀人
{
a.Jiuyinzhenjing();
System.out.println("使用九阴真经杀了10000人!");
}
}
-----------------------------分割线-----------------------------
10 多态中引用变量类型转换
在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考做左边。
代码举例:
class Fu
{
static int num = 5;
void method1()
{
System.out.println("fu method_1");
}
void method2()
{
System.out.println("fu method_2");
}
static void method4()
{
System.out.println("fu method_4");
}
}
class Zi extends Fu
{
static int num = 8;
void method1()
{
System.out.println("zi method_1");
}
void method3()
{
System.out.println("zi method_3");
}
static void method4()
{
System.out.println("zi method_4");
}
}
public class DuoTaiDemo
{
public static void main(String[] args)
{
Fu f = new Zi();
System.out.println(f.num);
f.method4();
Zi z = new Zi();
z.method4();
//输出为5、fu method_4、zi method_4
}
}
----------------------Android培训、Java培训、期待与您交流! ----------------------