------- android培训、java培训、期待与您交流! ----------
一.多态
定义:某一类事物的多种存在形态
简单说:就是一个对象对应着不同类型
多态在代码中的体现:
父类或者接口的引用指向其子类的对象
多态的好处:
提高了代码的扩展性,前期定义的代码可以使用后期的内容
多态的弊端:
前期定义的内容不能使用调用后期子类的特有内容
多态的前提:
1、必须由关系,继承,实现
2、要有覆盖
例如
猫这个对象对应的类型是猫类型
猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫成为动物
动物 y = new 猫();
动物是猫和狗具体事物中抽取出来的父类型
父类型引用指向了子类对象
例子
abstract class Animal //抽象类
{
abstractvoid eat();
}
class Cat extends Animal
{
publicvoid eat()
{
System.out.println("吃鱼");
}
publicvoid catchMouse()
{
System.out.println("抓老鼠");
}
}
class Dog extends Animal
{
publicvoid eat()
{
System.out.println("吃骨头");
}
publicvoid kanJia()
{
System.out.println("看家");
}
}
class duotai
{
publicstatic void main(String[] args)
{
//Catc = new Cat();
//c.eat();
//Dogd = new Dog();
//d.eat(); 以前的写法
}
}
多态的写法
Animal a = new Cat();
a.eat();
自动类型提升,猫对象提升成了动物类型,但是无法访问(猫的)特有功能
提升扩展性,作用就是限制对特有功能的访问
专业讲:向上转型
如果还想用具体动物猫的特有功能
可以将该对象进行向下转型
Cat c = (Cat)a; //强制将父类的引用,转成子类类型
c.catchMouse();
可以写成这样
毕姥爷 x = new 毕老师();
x.讲课();
毕老师 y = (毕老师)x;
y.看电影();
这件事自始至终都是子类对象(毕老师)在进行变化
注意:千万不要出现这样的操作,就是将父类对象转成子类类型
我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换
多态自始至终都是子类对象在做着变化
if(a instanceof Cat)
instanceof用于判断对象的具体类型,只能用于引用数据类型判断
Cat处可以写类,也可以写接口
通常在向下转型前,用于健壮性的判断
多态时,成员的特点:
1,成员变量。
编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边。(引用性变量所属的类)
2,成员函数(非静态)。
编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。(运行就是看子类自己的方法)//函数(方法)覆盖
因为成员函数存在覆盖特性。
3,静态函数。
编译时:参考引用型变量所属的类中的是否有调用的静态方法。
运行时:参考引用型变量所属的类中的是否有调用的静态方法。
简单说,编译和运行都看左边。
其实对于静态方法,是不需要对象的。直接用类名调用即可。
例:
class Fu
{
intnum =3; // voidshow(){sop("fu");
}
class Zi extends Fu
{
intnum =4; // void show(){sop("zi");
}
class DuoTaiDemo
{
publicstatic void main(String args[])
{
Fuf = new Zi();
System.out.println(f.num);//f.show();
}
}
此时打印出的为3,因为此时已转型为父类,覆盖只发在在方法(函数)上,如果执行f.show();,则由于覆盖显示zi
Object:是所有对象的直接后者间接父类,上帝
该类中定义的肯定是所有对象都具备的功能
二.内部类
内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类
如同一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液、跳动)
显然,此处不能单方面用属性或者方法表示一个心脏,而需要一个类
而心脏又在人体当中,正如同是内部类在外部内当中
实例1:内部类的基本结构
//外部类
class Out {
privateint age = 12;
//内部类
classIn {
publicvoid print() {
System.out.println(age);
}
}
}
public class Demo {
publicstatic void main(String[] args) {
Out.Inin = new Out().new In();
in.print();
//或者采用下种方式访问
/*
Outout = new Out();
Out.Inin = out.new In();
in.print();
*/
}
}
运行结果:12
从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?
因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点
如同心脏可以直接访问身体的血液,而不是通过医生来抽血
程序编译过后会产生两个.class文件,分别是Out.class和Out$In.class
其中$代表了上面程序中Out.In中的那个 .
Out.In in = new Out().new In()可以用来生成内部类的对象,这种方法存在两个小知识点需要注意
1.开头的Out是为了标明需要生成的内部类对象在哪个外部类当中
2.必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量
内部类访问特点:
1,内部类可以直接访问外部类中的成员,包括私有。
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用
格式: 外部类名.this
2,外部类要访问内部类,必须建立内部类的对象。
一般类不可以私有,但内部类可以私有,因为此时内部类是外部类的一个成员
访问格式:
1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中
可以直接建立内部类对象
格式: 外部类名.内部类名 变量名= 外部类对象.内部类对象;
如
Outer.Inter bb = new Outer().newInter();
内部类能直接访问外部类中成员,因为内部类持有了外部类的引用
外部类名.this
2、当内部类在成员位置上,就可以被成员修饰符所修饰
比如, private:将内部类在外部类中进行封装
static:内部类就具备了static的特性
当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限
在外部其他类中,如何直接访问static内部类的非静态成员呢?
Outer.Inter bb = new Outer().newInter();
在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function();
注意:当内部类中定义了静态成员,该内部类必须是static的
当外部类中的静态方法访问内部类时,内部类也必须是static的
当描述事物时,事物的内部还有事物,该事物用内部类来描述
因为内部事物在使用外部事物的内容
内部类定义在局部时
如
class Outer
{
voidmethod(final int a) //成员
{
classInter //局部
{
}
}
}
1、不可以被成员修饰符修饰
2、可以直接访问外部类中的成员,因为还持有外部类中的引用
但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量
匿名内部类:
1、匿名内部类其实就是内部类的简写格式
2、定义匿名内部类的前提:
内部类必须继承一个类或者实现接口
3、匿名内部类的格式:
new 父类或者接口(){定义子类的内容}
4、其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象
匿名内部类作用:简化书写,覆盖方法