---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
一、多态
1、多态性的概念
多态是指事物存在的多种形态,当一个类有很多子类时,并且这些子类重写了父类中的某个方法。那么当把子类创建的对象引用放到一个父类的对象中时,就得到了该对象的一个上转型对象,那么这个上转型对象在调用这个方法时就可能具有多种形态,因为不同的子类在重写父类的方法时可能产生不同的行为,比如,狗类的上转型对象调用“叫声”方法时产生的行为是“汪汪”,而猫的上转型对象调用“叫声”方法时,产生的行为是“喵喵”,等等。多态性就是指父类的某个方法在被其子类重写时,可以各自产生自己的功能行为。下面来看一个简单的多态的例子:
<span style="font-size:14px;"><span style="font-size:14px;"><pre class="java" name="code">abstract class Animal {
abstract void eat();
}
class Cat extends Animal{
void eat() {
System.out.println("吃鱼");
}
void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
void eat() {
System.out.println("啃骨头");
}
void kanJia() {
System.out.println("看家");
}
}
class Pig extends Ainmal {
void eat() {
System.out.println("吃食料");
}
void gongDi() {
System.out.println("拱地");
}
}
class
{
public static void main(String[] args)
{
Animal c = new Cat();//类型提升,向上转型
c.eat();
Animal d = new Dog();
d.eat();
Animal p = new pig();
p.eat();
}
</span></span>
2、多态的前提
A:类与类(或接口)要有继承(或实现)关系。 B:一定要有方法的重写。 C:一定要有父类或者接口的引用指向子类的对象。
<span style="font-size:14px;"><span style="font-size:14px;">class Demo2 {
public static void main(String[] args) {
林平之 小林子 = new 林平之();
小林子.自宫();
}
}
abstract class 葵花宝典 {
public abstract void 自宫();
}
class 林平之 extends 葵花宝典 {
public void 自宫() {
System.out.println("用指甲刀");
}
}
class 岳不群 extends 葵花宝典 {
public void 自宫() {
System.out.println("用钳子");
}
}
class 刘瑾 extends 葵花宝典 {
public void 自宫() {
System.out.println("用锤子,不忍直视!!!");
}
}</span></span>
3、多态的好处与弊端
多态的好处:多态的出现大大提高了代码的扩展性;
多态的弊端:只能使用父类的引用访问父类中的成员;
例:
<span style="font-size:14px;"><span style="font-size:14px;">class Fu {
void method_1() {
System.out.println("fu_method_1");
}
void method_2() {
System.out.println("fu_method_2");
}
}
class Zi extends Fu {
void method_1() {
System.out.println("zi_method_1");
}
void method_3() {
System.out.println("zi_method_2");
}
}
class Demo {
public static void main() {
Fu f=new Zi();
f.method_1();//合法,输出:zi_method_1,因为父类中的method_1方法被子类复写了
f.method_2();//合法,输出:fu_method_2,子类没有复写父类中的method_2方法,所以输出父类中的内容
f.method_3();//非法,因为父类中没有method_3这个方法
}
}</span></span>
4、多态中成员的特点
A:成员变量:编译和运行都看左边。
例:
<span style="font-size:14px;"><span style="font-size:14px;">class Fu {
int x=2;
}
class Zi extends Fu {
int x=3;
}
class Demo {
public static void main() {
Fu f=new Zi();
System.out.println("x="+f.x);
}</span></span>
输出结果是:2,不是3,因为在多态中对于成员变量无论编译还是运行都看父类。
B:非静态方法:编译看父类,运行看子类。
<span style="font-size:14px;"><span style="font-size:14px;">class Fu {
void method_1() {
System.out.println("fu_method_1");
}
void method_2() {
System.out.println("fu_method_2");
}
}
class Zi extends Fu {
void method_1() {
System.out.println("zi_method_1");
}
void method_3() {
System.out.println("zi_method_2");
}
}
class Demo {
public static void main() {
Fu f=new Zi();
f.method_1();//合法,输出:zi_method_1,因为父类中的method_1方法被子类复写了
f.method_2();//合法,输出:fu_method_2,子类没有复写父类中的method_2方法,所以输出父类中的内容
f.method_3();//非法,因为父类中没有method_3这个方法
}
}</span></span>
C:静态方法:编译和运行都看左边。
<span style="font-size:14px;"><span style="font-size:14px;">class Fu {
static void method_1() {
System.out.println("fu_method_1");
}
}
class Zi extends Fu {
static void method_1() {
System.out.println("zi_method_1");
}
}
class Demo {
public static void main() {
Fu f=new Zi();
f.method_1();//合法,输出:fu_method_1
Zi z=new Zi();
z.method();//输出:zi_method_1
}
}</span></span>
二、内部类
1、内部类的定义
类可以有两种重要的的成员:成员变量和方法,类还可以有一种成员:内部类。
Java支持在一个类中声明另一个类,这样的类称为内部类,而包含了内部类的类称为内部类的外嵌类。声明内部类如同在类中声明方法或成员变量一样,一个类把内部类看作是自己的成员。内部类的外嵌类的成员变量在内部类中仍然有效。内部类中的方法也可以调用 外嵌类中的方法。
2、内部类的种类
内部类分为:非静态内部类,静态内部类,局部内部类,匿名内部类。
(1)非静态内部类
定义:在一个外部类中有成员变量和成员方法,那么成员内部类就是把整个一个类当成了外部类的成员对待了
访问方式:内部类访问外部类,内部类可以直接访问外部类,包括私有成员,因为内部类拥有外部类的引用是:类名.this
外部类访问内部类,外部类访问内部类的成员,必须要建立内部类的对象:
格式: 外部类名.内部类名 = 外部类对象.内部类对象
例:
<span style="font-size:14px;">class Outer {
int x=1;
class Inner {
int x=2;
void method() {
int x=3;
System.out.println("外部类中的x=:"+Outer.this.x);
System.out.println("内部类中的x=:"+this.x);
System.out.println("内部类方法中的x=:"+x);
}
}
}
class Test {
public static void main(String[] args) {
Outer.Inner d = new Outer().new Inner();
d.method();
}
}</span>
输出结果是:外部类中的x=1
内部类中的x=2
内部类方法中的x=3
(2)静态内部类
定义:就是在成员内部类的基础上加上static
格式:外部类名.内部类名 = 外部类名.内部类对象
例:
<span style="font-size:14px;">class Outer {
static class Inner {
static void method_1() {
System.out.println("method_1");
}
void method_2() {
System.out.println("method_2")
}
}
void function() {
new Outer.Inner.method_1();//访问静态方法方式
new Outer.Inner().method_2();//访问非静态方法方式
}
}
class Test {
public static void main(String[] args) {
Outer d = new Outer();
d.function();
}
}
</span>
(3)局部内部类
定义:在外部类成员方法中定义的内部类,他更像局部变量
注意:
第一:方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
第二:方法内部类对象不能使用该内部类所在方法的非final局部变量。因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。 但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!
例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。
第三:方法内部类的修饰符。与成员内部类不同,方法内部类更像一个局部变量。可以用于修饰方法内部类的只有final和abstract。
第四:静态方法内的方法内部类。静态方法是没有this引用的,因此在静态方法内的内部类遭受同样的待遇,即:只能访问外部类的 静态成员。
例:
class Outer {
int x=3;
void method() {
int y1=1;
final int y2=2;
class Inner {
void function() {
System.out.println("x="+Out.this.x);
System.out.println("y1="+y1);//非法
System.out.println("y2="+y2);//合法
}
new Inner().function();
}
}
}
class Demo {
public static void main() {
new Outer().method();
}
}
(4)匿名内部类
匿名内部类:没有名字的内部类。其实就是内部类的简化写法。
匿名内部类实现前提:内部类可以继承或实现一个外部类或者接口。
格式为:new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
我们来看个非静态内部类 继承外部类的例子:
abstract class Test {
abstract void show();
}
class Outer {
int x=3;
class Inner extends Test {
void show() {
System.out.println("show"+x);
}
}
public void method() {
new Inner().show();
}
}
class InnerDemo {
public static void main(String[]) {
new Outer().method();
}
}
但是当我们换成匿名内部类的形式时:
abstract class Test {
abstract void show();
}
class Outer {
int x=3;
/*
class Inner extends Test {
void show() {
System.out.println("show"+x);
}
}*/
public void method() {
//new Inner().show();
new Test(){
void show() {
System.out.println("show:"+x);
}
void haha() {
System.out.println("haha");
}
}.show();//这是Test的一个子类对象,加上子类调用
new Test(){
void show() {
System.ou7t.println("show:"+x);
}
void haha() {
System.out.println("haha");
}
}.haha();//合法,子类新增的功能
}
}
class InnerDemo {
public static void main(String[]) {
new Outer().method();
}
}
显然换成匿名内部类是代码简化许多,但是对于调用其中的方法时,就显得麻烦了,所以对代码做进一步的修改:
abstract class Test {
abstract void show();
}
class Outer {
int x=3;
public void method() {
Test t=new Test(){
void show() {
System.out.println("show:"+x);
}
void haha() {
System.out.println("haha");
}
};
t.show();//合法
t.haha();//非法,多态
}
}
class InnerDemo {
public static void main(String[]) {
new Outer().function();
}
}
为什么上面代码中t.haha();//非法呢,可以参见上面讲到的多态中对象对于成员方法的编译和调用规则。
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------