多态:某一事物的多种存在形态;简单说、就是一个对象对应不同的类型
例如:对象多态性
Class 动物{}
Class 猫 extends 动物{}
猫 x= new 猫()
动物 y= new 猫()
猫这类事物即具备猫的形态,又具备动物的形态;这就是对象的多态性
多态在代码中的体现:父类或者接口的引用指向其子类的对象
多态的好处:提高代码扩展性,前期定义的代码可以使用后期的内容(被重写的父类或者接口中的抽象方法)
多态弊端:前期定义的内容不能使用(调用)后期子类特有的内容
多态的前提:必须有关系(继承 或 实现);要有覆盖(重写父类或接口中的抽象方法)
向上转型:自动类型提升,猫对象提升为动物类型,但是特有功能无法访问,作用就是限制对特有功能的访问
如果还想用具体动物猫的特有功能,可以将该对象进行进行向下转型。
Animal a = new cat()
Cat x = (cat)a
向下转型的目的就是为了使用子类中的特有方法。
注意:对于转型,自始至终都是子类对象在做着类型的变化。
ClassCastException 即为类型转换错误。
/*
姜先生和姜太公的故事
*/
class 姜太公
{
void 讲课()
{
System.out.println("管理");
}
void 钓鱼()
{
System.out.println("钓鱼");
}
}
class 姜先生 extends 姜太公
{
void 讲课()
{
System.out.println("java");
}
void 看电影()
{
System.out.println("看电影");
}
}
class BDemo
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
/*
姜先生 x = new 姜先生();
x.讲课();
x.看电影();
*/
姜太公 x = new 姜先生();
x.讲课();
x.钓鱼();
x = new 姜尚();
x.讲课();
x.钓鱼();
姜尚 y = (姜尚)x;
y.吃饭();
x.讲课();
}
}
class 姜尚 extends 姜太公
{
void 讲课()
{
System.out.println("封神榜的好与坏");
}
void 吃饭()
{
System.out.println("封神榜成就了谁?");
}
}
可以使用instanceof关键字判断对象的具体类型,只能用于引用类型的判断。通常在向下转型之前,用于健壮性的判断。
If(a instanceof Cat)
{
Cat x = (Cat)a;
x.catchMouse()
}
else if(a instanceof Dog)
{
Dog x = (Dog)a;
X.kengutou();
}
多态时、成员的特点?
成员变量:(作为了解,一般面试用)
编译时:参考引用型所属的类中是否有调用的成员变量,有、编译通过,没有、编译失败
运行时:参考引用型变量所属类中是否有调用的成员变量,并运行该所属类中的变量
简单说、就是编译和运行均参考向上转型的语句中等号左边
成员函数(非静态):(重点掌握)
编译时:参考引用变量所属的类中是否有调用的函数,有、编译通过,没有、编译失败
运行时:参考的是对象所属的类中是否有调用的函数
简单说:编译看左边,运行看右边
静态函数:
编译时:参考引用型变量所属类中是否有调用的静态方法
运行时:参考引用型变量所属的类中是否有调用的函数
简单说:编译看左边,运行看右边
内部类:将一个类定义在另一个类的内部,里面的类就称为内部类
内部类可以直接访问外部类中的成员,包括私有成员
外部类若想访问内部类中的成员,则必须创建内部类的对象
内部类一般用于类的设计。分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这时就是还有的事物定义成内部类来描述。
内部类修饰符;
在其他类中直接访问外部类中的内部类中的成员,此时需要使用下面的格式来创建:
外部类.内部类 var = new 外部类().new 内部类();//内部类权限必须不能为private
如果内部类是静态的,那就相当于一个外部类。使用下面的格式
外部类.内部类 var = new 外部类.内部类(); //内部类必须不能为private
如果内部类是静态的,成员是静态的。使用如下格式
外部类.内部类.函数名(); //如果内部类中的成员是静态的,则该内部类必须被静态修饰。
注意以下代码:
class Outer
{
int num = 3;
class Inner
{
int num = 4;
void show()
{
int num = 5;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
void method()
{
new Inner().show();
}
}
class InnerDemo
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
new Outer().method();
}
}
输出结果为 5 4 3
为什么内部类能直接访问外部类中的成员,那是因为内部类持有外部类的引用(外部类名.this)
局部内部类:内部类可以存放在局部位置上
内部类在局部位置上只能访问局部中被final修饰的局部变量
匿名内部类:就是内部类的简写格式
必须得前提:内部类必须继承或者实现一个外部类或者接口
匿名内部类:其实就是一个匿名子类对象
格式:new 父类or接口名{子类内容}
abstract class Demo
{
abstract void show();
}
class Outer
{
public void method()
{
new Demo()
{
void show()
{
System.out.println(".............");
}
}.show();
}
}
class InnerDemo1
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
new Outer().method();
}
}
匿名内部类应用:
通常的使用场景之一:
当函数参数是接口类型时,而且接口中的方法不超过三个,可以使用内部类作为实际参数进行传递。
interface Inner
{
void show1();
void show2();
}
class Outer
{
public void method()
{
Inner in = new Inner()
{
public void show1()
{System.out.println("show1");}
public void show2()
{System.out.println("show2");}
};
in.show1();
in.show2();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
new Outer().method();
}
}
与如下等同,但是实际上均使用如下方式。
interface Inner
{
void show1();
void show2();
}
class InnerClassDemo
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
show(new Inner()
{
public void show1()
{System.out.println("show1");}
public void show2()
{System.out.println("show2");}
});
}
public static void show(Inner in)
{
in.show1();
in.show2();
}
}
匿名内部类细节:
class Outer
{
void method()
{
Object obj = new Object()
{
public void show()
{
System.out.println("................show run ..........");
}
}
obj.show(); //此处会调用失败,因为匿名内部类这个子类对象被向上转型为了Object类型,这样就
//不能再使用子类特有的方法了。
}
}
本文出自 “Keyman” 博客,请务必保留此出处http://keyman.blog.51cto.com/9807984/1676887
原文:http://keyman.blog.51cto.com/9807984/1676887