黑马程序员----内部类

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
1.内部类
1.1内部类的细节

1.1 内部类的由来:因为访问的特点。一个类如果直接访问另一个类中的成员,建议写内部类。
1.2 内部类出现后访问特点:
内部类可以直接访问外部类的成员,包括私有的。
外部类要访问内部类需要创建内部类的对象。
1.3 内部类在成员位置可以给成员修饰符所修饰。★★★
public : 格式 外部类名.内部类名 变量名 = new 外部类().new 内部类();
static :
情况一:访问静态内部类中的非静态成员。
外部类名.内部类名 变量名 = new 外部类名.内部类名();
情况二:访问静态内部类中的静态成员。
外部类名.内部类名.静态成员;
注意事项:
1,非静态内部类中,不允许定义静态成员,只可以定被final修饰的static常量。
2,外部类的静态方法要访问内部类,需要创建内部类的对象,一定要注意,该内部类必须被静态修饰。
否则,只能通过外部类对象.内部类对象的方式访问。看以下代码演示。
class Outer
		{
			static class Inner1
			{
			}

			class Inner2
			{
			}

			public static void method()
			{
				//访问Inner1.
				new Inner1();

				//访问Inner2非静态。
				new Outer().new Inner2();

			}

		}

1.4 非静态内部类之所以可以直接访问外部类中的成员:原因是内部类持有了 外部类名.this
1.5 局部内部类。
局部内部类一样可以直接访问我外部类中的成员。
注意:局部内部类不能直接访问局部中的变量:局部变量生命周期太短,很有可能局部变量已消失,而内部类对象还在。
局部内部类只能访问被final修饰的局部变量,因为是一个常量,值不变。
1.6 内部类是可以继承其他类和实现接口的。★★★★
如果内部类不需要对外提供,可以通过其继承的父类或者实现的接口,这种公共的类型对外提供。
1.2内部类的访问方式


当A类中的内容要被B类直接访问,而A类还需要创建B的对象,访问B的内容时,
这时,可以将B类定义到A类的内部。这样访问更为便捷。

将B称之为内部类(内置类,嵌套类)。


访问方式:
内部类可以直接访问外部类中的所有成员,包含私有的。
而外部类要想访问内部类中的成员,必须创建内部类的对象。

当描述事物时,事物的内部还有事物,这个内部的事物还在访问外部事物中的内容。
这时就将这个事物通过内部类来描述。


【内部类被访问的方式】
情况一:内部类在成员位置上的被访问方式。
成员是可以被指定的修饰符所修饰的。

public:不多见:因为更多的时候,内部类已经被封装到了外部类中,不直接对外提供。

class Outer//外部类。
{
	private static int num = 4;
	public class Inner//内部类。
	{
		void show()
		{
			System.out.println("num="+num);
		}
//		static void show1(){}//非静态内部类中不允许定义静态成员。仅允许在非静态内部类中定义 静态常量 static final。
//		如果想要在内部类中定义静态成员,必须内部类也要被静态修饰。
	}

	/*
	内部类被静态修饰后,随着Outer的加载而加载。可以把一个静态内部类理解为就是一个外部类。

	*/
	static class Inner2
	{
		void show2()
		{
			System.out.println("Inner2 show2 run..."+num);
		}
		static void staticShow()
		{
			System.out.println("Inner2 staticShow run");
		}
	}
	void method()
	{
		/*Outer.*/Inner in = new /*Outer.*/Inner();
		in.show();
	}
}




class InnerClassDemo
{
	public static void main(String[] args)
	{
//		Outer out = new Outer();
//		out.method();

		//测试情况一:直接访问Outer中的Inner内部类的非静态成员。
		//创建内部类的对象就哦了。内部类作为成员,应该先有外部类对象,再有内部类对象。
//		Outer.Inner in = new Outer().new Inner();
//		in.show();

		//测试情况二:对静态内部类中的非静态成员进行调用。
		//因为内部类是静态,所以不需要创建Outer的对象。直接创建内部类对象就哦了。
//		Outer.Inner2 in = new Outer.Inner2();
//		in.show2();
//		如果静态内部类有静态成员,该如何访问呢?既然静态内部类已随外部类加载,而且静态成员随着类的加载而加载,
//		就不需要对象,直接用类名调用即可。
//		Outer.Inner2.staticShow();
		

	}
}

1.3内部类中this


/*
为什么内部类就能直接访问外部类中的成员呢?
那是因为内部类其实持有了外部类的引用  外部类.this 
对于静态内部类不持有 外部类.this  而是直接使用 外部类名。
*/
class Outer
{
	int num = 3;
	class Inner
	{
		int num = 4;

		void show()
		{
			int num = 5;
			System.out.println("num="+num);
			System.out.println("num="+this.num);
			System.out.println("num="+Outer.this.num);
		}
	}
	
	void method()
	{
//		System.out.println(num);
		new Inner().show();
	}
}


class InnerClassDemo2 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
		out.method();
	}
}
1.4局部内部类


内部类其实也可以定义在外部类的局部位置上。

内部类定义在局部时,只能访问被final修饰的局部变量。
为啥呢?因为编译生产的class中直接操作那个最终数值了。

class Outer
{
	int  num = 3;
	void method()
	{
		final int  x = 10;
//		final int x = 5;//局部变量。
		int y = 2;
		class Inner//局部内部类。不能被成员修饰符修饰。
		{
			void show()
			{
//				System.out.println("y="+y);//访问失败。y的生命周期太短了。
				System.out.println("x="+x);
				System.out.println("inner show run........"+num);
			}
		}
		new Inner().show();
	}
}
class InnerClassDemo3 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
		out.method();
	}
}
1.5内部类继承或者实现接口

看API,发现类名或者接口名称中有 . 说明是内部类,或者内部接口。

内部类的延伸。
内部类是可以继承或者实现外部其他的类或者接口的。

好处:通过内部类的方式对类进行继承重写,或者接口进行实现。
通过公共的方式对其内部类对象进行访问。因为通常内部类很有可能被外部类封装其中。
我们就可以通过父类或者接口的方式访问到内部类对象。


abstract class AbsDemo
{
	abstract void show();
}

class Outer
{
	int num = 3;
	private class Inner extends AbsDemo
	{
		//重写抽象方法show。
		void show()
		{
			System.out.println("num="+num);
		}
	}
	//获取内部类的对象。 
	public AbsDemo getObject()
	{
		return new Inner();
	}

	public void method()
	{
		new Inner().show();
	}
}

class InnerClassDemo4 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
//		out.method();
		//如果Inner对外提供,可以如此获取。
//		Outer.Inner in = out.getObject();
//		in.show();
		//如果Inner被private 。可以通过父类型获取。
		AbsDemo a = out.getObject();//多态。
		a.show();
	}
}

1.6匿名内部类

其实就是对1.6的简化书写。
原理:匿名内部列其实就是一个子类对象。
格式:new 父类or接口(){子类内容}

如果实在接收不了匿名内部类的格式,可以还原成内部类。

其实InnerClassDemo7.java涉及的练习以及面试题要动手做?并写出原因。

通常匿名内部类中的方式不要过多(少于两个),以免降低阅读性。

/*
对以下代码进行简化。
匿名内部类:其实就是一个带有内容的子类对象。
格式:new 父类or接口(){子类的内容}
匿名内部类就是内部类的简化形式。
别忘了:匿名内部类有前提,内部类必须要继承父类或者实现接口。

*/

abstract class AbsDemo
{
	abstract void show();
}


class Outer
{
	int num = 3;
	/*
	class Inner extends AbsDemo
	{
		void show()
		{
			System.out.println("num="+num);
		}
	}
	*/
	public void method()
	{
		
//		new Inner().show();
		/*
		不想创建具体的子类型。还想创建AbsDemo的子类对象。
		怎么实现呢?没有子类型干脆,直接使用父类型就哦了。
		可是在该例子中是抽象类,怎么可以new对象呢?
		抽象类之所以不能new对象是因为抽象方法没重写。直接重写不就哦了吗?
		*/
		new AbsDemo()//这就是传说中的一个AbsDemo的子类对象。只不过这个对象有点胖!这是一个带着内容的子类对象。
					//这种写法一个称呼:匿名内部类。
		{
			//重写抽象的show方法。
			void show()
			{
				System.out.println("num===="+num);
			}
		}.show();

	}
}


class InnerClassDemo5 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
		out.method();
	}
}

1.7匿名内部类练习


//匿名内部类练习。
interface Inter
{
	public void show();
}
class Outer
{
	//代码补足。要求使用匿名内部类。
	public static Inter method()
	{
		//既然在Oute类中使用到了Inter的对象。可以使用内部类来完成。
		//需要子类型,只要简化格式即可,因为接口中就只有一个方法。
		return new Inter()
		{
			public void show()
			{
				//code..;
			}
		};
//		return new Inner();
	} 
	
	/*
//	还原成内部类。  当静态方法访问内部类时,内部类必须是静态的。
	static class Inner implements Inter
	{
		public void show(){}
	}
	*/
}
//Outer$Inner.class 成员内部类Inner
//Outer$1Inner.class 局部内部类名称为Inner
//Outer$2.class//匿名内部类。



//面试题。
class Outer2
{
	public void method()
	{
		//以下两个对象有区别吗?
		new Object()
		{
			public void show(){}
		}.show();//这个可以编译通过。

		Object obj = new Object()
		{
			public void show(){}
		};
//		obj.show();//编译失败。为啥呢?因为匿名内部类是子类对象,当Object obj指向时,就被提升了Object。而Object类中没有定义show方法,编译失败。

	}

//	class Inner extends Object
//	{
//		public void show(){}
//	}
}


class InnerClassDemo7 
{
	public static void main(String[] args) 
	{
		Outer.method().show();
		/*
		Outer.method():Outer类中有一个method的方法。这个方式静态的。
		Outer.method.show():能调用show()的必然是对象,说明method方法运算完应该返回一个对象。而且能调用Inter中的show方法,说明这个对象的类型是Inter。
		
		*/

		Inter in = Outer.method();new InterImpl();
		in.show();
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值