黑马程序员—面向对象3

----------------------   JavaEE+Android、Java培训、期待与您交流! ----------------------


多态

java引用变量有两种类型:编译时的类型和运行时的类型,编译时的类型由声明该变量时使用的类型决定,运行时的类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就会出现所谓的多态。其实多态就是父类的对象指向子类的对象,就是多态。也可以理解为事物存在的多种体现形态。

1.多态的基本体现:

父类的引用指向了自己的子类对象,即父类的引用可以接收自己的子类对象。

2.多态的前提:

必须是类与类之间有关系,要么继承,要么实现。通常还有一个前提:存在覆盖。

3.多态的好处:

多态的出现大大的提高了程序的扩展性。

4.多态的弊端:

虽然提高了扩展性,但只能使用父类的引用访问父类中的成员。

5.多态的应用:

如Fruit a=new Apple();

6.多态的出现代码中的特点(多态使用的注意事项)

Animal a=new Cat();       //类型提升,向上转型

Cat c=(Cat)a;          //向下转型,强制将父类的引用转成子类类型。

千万不要出现这样的操作,就是将父类对象转成子类类型(Animal a=new Animal(); Cat c=(Cat)a)。我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。多态自始至终都是子类对象在做着变化。

判断所属类型关键字:instanceof:if(a instanceof Cat)类型有限。

Fu f=new zi(); f.method_3(子类特有方法)编译失败。

在多态中成员函数的特点 :

在编译时期:参阅引用型变量多数的类中是否有调用的方法,如果有,编译通过,如果没有便以失败。

在运行时期:参阅的是对象所属的类中是否有调用的方法。

简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。(动态绑定)

在多态中成员变量的特点:无论编译和运行都参考左边(引用型变量所属的类)。

在多态中静态函数的特点:无论编译和运行,都参考左边。只要引用在,就找引用型变量所属类中的内容。静态方法一进内存就已经绑定在该方法所属的类上了。(静态绑定)

内部类

先看下面代码:

<span style="font-size: 14px; ">//情况一:创建两个常规类A和B
class A{
	int a = 5;
	void  fun(){
		C c = new C();
		c.method();
		System.out.println("A:" + a);
	}

	//情况二:将C类放入A类中
class C{
		void method(){
			System.out.println("C访问A:" + a);//可直接访问
		}
	}
}
class B{
	void fu(){
		int a = 6;
		A me = new A();
		System.out.println("访问A中a:" + me.a);//必须建立对象后才能访问
	}
}

class  Demo
{
	public static void main(String[] args) 
	{
		A x = new A();
		B y = new B();
		x.fun();
		y.fu();
	}
}</span>

内部类:将一个类定义在另一个类之中,里面那个类就称为内部类(内置类,嵌套类)

一、访问规则(即使用内部类的好处):

1、内部类方法可以访问该类所在的类中作用域的成员,包括私有成员变量。

2、内部类可以对同一个包中的其他类隐藏起来,从而不被访问

3、使用匿名内部类是比较便捷简单的,这种情况较多的用于AWT设计中。

注:为何内部类可直接访问外部类:

由于成员可被对象访问,内部类中持有了一个外部类的引用,因此就可以直接用:外部类名.this.成员

二、访问格式:

1、当内部类定义在外部类的成员位置上,而且非私有,可在外部其他类中直接建立内部类对象

格式:外部类名.内部类名  变量名 = 外部类对象.内部类对象

2、当内部类在成员变量的位置上,可被成员修饰符修饰

·private:将内部类在外部类中进行封装

·static:内部类具备了static的特性,当内部类被static修饰(下面说到的静态内部类),只可访问外部类中的static的成员,访问则受限。

注:(Outer为外部类名,Inner为内部类名,function为非静态成员)

在其他类中,如何访问静态内部类中非静态成员:new Outer.Inner.function();(建立对象访问)

在其他类中,如何访问静态内部类中的静态成员:Outer.Inner.function();(可直接访问)

注意:

1、当内部类中定义了静态成员,该内部类必须为静态的

2、当外部类中静态方法访问内部类时,内部类必须为静态

3、内部类一般定义为private的,而很少定义为public的

三、内部类定义原则:------->多在程序设计中使用

1、当描述事物时,事物的内部还有事物,则该事物使用内部类来描述,因为内部事物要使用外部事物内容

举例:楼房内部还有家庭住户,家庭住户中还有房间,这就可以用内部类描述。(总不能访问一个住户,就建立一个楼房对象吧)

2、何时定义内部类:

当一个类需要直接访问另一个类中的成员时,则可以将这个类放入另一个类中,并将内部类封装。

3、内部类生成文件:

我们在编译一个源文件是,如果代码中有内部类,你会发现,生成的class文件中含有例如这样的文件:A$C.class。这是为什么呢?因为内部类是一种编译现象,与虚拟机无关。编译器将会把内部类翻译成用$(美元符号)分隔外部类名和内部类名的常规类文件,而虚拟机对此却一无所知。 

局部内部类(也称局部类)
看下面一段代码:
<span style="font-size: 14px; ">class A{
	private int a = 5;
	void  fun(){
		class B{//在方法中创建一个内部类
			void method(){
				System.out.println("C访问A:" + a);//可直接访问
			}
		}
		B c = new B();//建立一个对象
		c.method();
	}
}
class  Demo
{
	public static void main(String[] args) 
	{
		A x = new A();
		x.fun();
	}
}</span>

局部内部类:当内部类只在外部类中的某个方法中,创建了这个类型的对象时,且仅使用了一次,那么可在这个方法中定义局部类。

注意:

1、局部内部类不可用public或者private访问修饰符声明,它的作用域被限定在了声明这个局部类的代码块中

2、局部类的优势:a.对外界完全隐藏,即使此方法所在的类也不可访问,也就是说,除此方法外,无任何方法知道它的存在。b.可访问包含他们的外部类,因还持有外部类的引用;还可访问局部变量,但是局部变量必须被声明为final。

记住:局部内部类不可悲成员修饰符修饰,如static

代码如下:

<span style="font-size: 14px; ">/*
局部内部类测试:
*/

class Outer//类不能用private,但是内部类是可以的
{
	int x = 3;
	private static class InnerOuter//可在外部类的任意有效的地方,可以用private和static
	{		//......
	}
	//含局部变量时
	void method(final int a)//需访问加final
	{
		final int y = 4;//y需要被声明为最终类型,即final才可被局部内部类中的成员访问
		class Inner//在方法中,相当于局部成员,不能为static或private
		{
			void fun()//不能定义静态成员(变量和方法)
			{
				System.out.println("访问外部类成员变量:+ Outer.this :" + Outer.this.x);
				System.out.println("局部内部类访问本地变量定义为final:" + y);
				System.out.println("方法中的参数需定义为final:" + a);
			}
		}
		new Inner().fun();
	}
}

class InnerClassDemo0
{
	public static void main(String[] args) 
	{
		Outer ou = new Outer();
		ou.method(7);//打印3、4、7
		ou.method(5);//打印3、4、8
	}
}</span>

说明:为什么定义为final了,还可以改变值7和8;这是因为在传入7后,运行method方法结束后,在栈内存中就会随即消亡,然后就可以再传入8,运行下一个method方法。

五、匿名内部类:

1、匿名内部类:就是内部类的一种简写格式。

当只创建该类的一个对象,可不用再为其命名。所以称之为匿名内部类。代码示例:

<span style="font-size: 14px; ">class Outer2
{
	int x = 3;
	public  void fun()
	{
		/*
		其中Inner()被改写为AbsDemo(){}  (其实就是对父类的复写)
		*/
		new AbsDemo()//看这里
		{
			void show()
			{
				System.out.println("匿名show:" + x);
			}
		}.show();//</span><span style="font-size: 14px; ">new Inner().show();的简写</span><span style="font-size: 14px; ">
	}
}</span>

2、定义前提:

内部类必须继承一个类或实现接口。

但是有一种很特殊,可以不直接继承一个父类,仍可定义一个匿名内部类。因为任何类都是Object的子类。

3、格式:

new    父类或接口(参数){定义子类的内容};

4、要点说明:

      A.其实匿名内部类就是一个匿名子类对象,可以理解为带有内容的对象。

      B.匿名内部类中的方法最好少于3个,方法少,比较方便简单,匿名内部类一定要简化,否则就违背了初衷。

六、静态内部类

1、概述:

上面提到当内部类在成员变量的位置上,可被成员修饰符static修饰,这就是静态内部类

2、使用前提:

某些情况下,会把内部类作为一个隐藏的类,不需要使用内部类引用外部类的对象。因此,可以将外部类声明为static,就可以消除产生的引用。在内部类不需要访问外部类对象的时候,应该使用静态内部类。

<span style="font-size: 14px; ">/*
静态内部类测试:最大值最小值
*/

class ArrayAlg
{
	public static class Pair
	{
		private double first;
		private double second;
		//构造函数获得两个值
		public Pair(double first,double second)
		{
			this.first = first;
			this.second = second;
		}
		
		//访问器:访问私有变量first和second
		public double getFirst()
		{
			return first;
		}
		public double getSecond()
		{
			return second;
		}
	}
	//定义一个获得最大值和最小值的功能
	public static Pair minmax(double[] arr)
	{
		//min和max要分别设置最大和最小,然后才能和数组中的数比较
		double min = Double.MAX_VALUE;
		double max = Double.MIN_VALUE;

		for (int i=0;i<arr.length;i++)
		{
			if (min > arr[i])
				min = arr[i];
			if (max < arr[i])
				max = arr[i];
		}
		return new Pair(min,max);
	}
}

class ArrayZDemo
{
	public static void main(String[] args) 
	{
		double[] d = new double[20];
		for (int i=0;i<d.length;i++)
			d[i] = 100*Math.random();
		ArrayAlg.Pair p = ArrayAlg.minmax(d);
		System.out.println("min = " + p.getFirst());
		System.out.println("max = " + p.getSecond());
	}
}
</span>


----------------------   JavaEE+Android、Java培训、期待与您交流! ----------------------

详细请查看: http://edu.csdn.net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值