黑马程序员--Java学习14--多态和内部类

---------------------- 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培训、期待与您交流! ----------------------









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值