黑马程序员-java内部类总结

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------


内部类指在一个外部类的内部再定义一个类。

内部类可以用成员修饰符修饰,如static、public、friendly、protected和private。而外部顶级类(即类名和文件名相同的)也只能使用public和friendly。

1、成员内部类

1)成员内部类,就是作为外部类的成员,可以直接访问外部类的所有成员变量和方法,包括private的。因为内部类中持有一个外部类的引用,格式:OuterClass.this ;

2)外部类要访问内部类,必须建立内部类对象。

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

格式: OuterClass.InnerClass in=new OuterClass.new InnerClass();

3)注意,成员内部类中不能含有静态变量和方法。原因请见下面的“嵌套内部类”部分。

例1:

class  TestDemo
{
	public static void main(String[] args) 
	{
		Outer.Inner in1=new Outer().new Inner();//得到内部类的一种方式
		in1.function();
		Outer.Inner in2=new Outer().getInner();
		in2.function();
	}
}
class Outer
{
	private int x=3;
	class Inner
	{
		void function()
		{
			System.out.println("Inner:"+x);   //内部类可以访问外部类所有成员,包括私有的。
		}
	}
	/*在外部类作用范围之外得到内部类对象的另一种方式,那就是利用其外部类的方法创建并返回。
	个人推荐这种方式,尤其当内部类的构造函数无参数时*/
	public Inner getInner()   
	{
		return new Inner();
	}
}

输出结果:

Inner:3
Inner:3

2、嵌套内部类

嵌套内部类,就是用static修饰的内部类。

1)当内部类被static修饰后,就具备static的特性,只能直接访问外部类中的static成员。出现了访问局限。

2)

在外部其他类,直接访问static内部类中的非静态成员的格式:new OuterClass.InnerClass().function();

在外部其他类,直接访问static内部类中的静态成员的格式:Outer.Inner.function();

3)当内部类中定义了静态成员,则该内部类必须是嵌套类的,而嵌套类中的成员不必都是静态的;当外部类中的静态方法访问内部类时,内部类也必须是嵌套类。

例2:

class  TestDemo
{
	public static void main(String[] args) 
	{
		new Outer.Inner().function1();  //在外部其他类,直接访问static内部类中的非静态成员
		Outer.Inner.function2();        //在外部其他类,直接访问static内部类中的静态成员
	}
}
class Outer
{
	private int x=3;
	private static int y=4;
	static class Inner
	{
		void function1()
		{
			//System.out.println("Inner.x:"+x);   //出错,嵌套内部类只能访问外部类中的静态成员。
			System.out.println("Inner.y="+y);
		}
		static void function2()
		{
			System.out.println("Inner.static");
		}
	}
}

输出结果:

Inner.y=4
Inner.static


3、局部内部类

局部内部类,是指内部类定义在方法和作用域内。

1)局部内部类仍可以访问外部成员

2)内部类以及其内部成员前面不能加private、static等修饰符。因为它们是用于修饰成员的,而此时内部类已经变成了局部变量;

3)局部内部类只能访问被final修饰的局部变量。                                                                                                                                                                                                                         例3:

class  TestDemo
{
	public static void main(String[] args) 
	{
		Outer out=new Outer();
		out.method(1);
	}
}
class Outer
{
	private int x=3;
	
	void method(final int a)
	{
		int b=4;
		class Inner
		{
			void function()
			{
				//System.out.println("b="+b); //错误,局部内部类只能访问被final修饰的局部变量
				System.out.println("a="+a);   
				System.out.println("x="+x);   //局部内部类仍可以访问外部成员
			}
		}
		new Inner().function();
	}
}

输出结果:

a=1
x=3

4、匿名内部类

1)匿名内部类其实就是内部类的简写格式

2)定义匿名内部类的前提:内部类必须是继承一个类或实现一个接口。换句话说,这个类或者接口要先定义;

3)匿名内部类的格式:new 父类\接口(){定义子类的内容};

4)其实匿名内部类就是一个匿名子类对象

5)匿名内部类中定义的方法最好不超过3个

6)匿名内部类是不能加修饰符的

例4:

class  TestDemo
{
	public static void main(String[] args) 
	{
		Outer out=new Outer();
		out.method();
	}
}
class Outer
{
	private int x=3;
	
	void method()
	{
		new Abs()
		{
			public void show()
			{
				System.out.println("x="+x);
			}	
		}.show();
		//调用接口中没有的方法也是可以的
		new Abs()
		{
			public void show()
			{
				System.out.println("x="+x);
			}
			public void abs()
			{
				System.out.println("abs");
			}
		}.abs();
		//当用父类\接口型引用变量指向匿名内部类时
		Abs d=new Abs()
		{
			public void show()
			{
				System.out.println("x="+x);
			}
			public void abs()
			{
				System.out.println("abs");
			}
		};
		d.show();
		//d.abs();           //错误,根据java多态性可知
	}
}
interface Abs
{
	void show();
}

输出结果:

x=3
abs
x=3

5、内部类的作用

1)内部类可以很好的隐藏。因为内部类可以用private、protected等修饰;

2)内部类拥有外部类的所有成员的访问权限;

3)可以实现多重继承;

4)可以避免修改接口而实现同一个类中两种同名方法的调用。

下面针对各点作用举例说明,

例5:实现隐藏

class  TestDemo
{
	public static void main(String[] args) 
	{
		Outer out=new Outer();
		Abs a=out.getAbs();
		a.show();
	}
}
class Outer
{
	private class Inner implements Abs  //内部类私有化
	{
		private int i=1;
		public void show()
		{
			System.out.println(i);
		}
	}
	public Abs getAbs()               //返回值为内部类实现的接口类型
	{
		return new Inner();
	}
}
interface Abs
{
	void show();
}

输出结果:

1
此例中,内部类Inner被private修饰,它实现了接口Abs。在main中,通过getAbs()获得了内部类的对象,但是我们甚至连内部类的名字都没看到。因此内部类的第一个作用:隐藏不想让别人知道的操作,即封装性。


例6:可以访问外部类的所有成员

参见例1。


例7:可以实现多重继承

class  TestDemo
{
	public static void main(String[] args) 
	{
		Outer out=new Outer();
		System.out.println("name="+out.getName());
		System.out.println("age="+out.getAge());
	}
}
class Outer
{
	private class Inner1 extends A  
	{
		public int getAge()
		{
			return super.getAge();
		}
	}
	private class Inner2 extends B
	{
		public String getName()
		{
			return super.getName();
		}
	}
	public int getAge()               
	{
		return new Inner1().getAge();
	}
	public String getName()
	{
		return new Inner2().getName();
	}
}
class A
{
	public int getAge()
	{
		return 11;
	}
}
class B
{
	public String getName()
	{
		return "Zhangsan";
	}
}

输出结果:

name=Zhangsan
age=11
通过内部类Inner1和Inner2分别继承了类A和B,我们类Outer就拥有了类A和B的成员变量和方法,也就是间接地实现了多继承。


例8:避免修改接口而实现同一个类中两种同名方法的调用

class Outer {} extends A implements B
class A
{
	public int getAge()
	{
		return 11;
	}
}
interface B
{
	public int getAge();
}

如上所示,此时Outer类中,有两个同名的getAge()方法。既不能区别,重写时也不知道到底重写了哪一个。

而通过内部类即可解决这个问题:

class  TestDemo
{
	public static void main(String[] args) 
	{
		Outer out=new Outer();
		System.out.println("A.age="+out.getAge());
		System.out.println("B.age="+out.getInner().getAge());	
	}
}
class Outer extends A
{
	private class Inner implements B
	{
		public int getAge()
		{
			return 20;
		}
	}
	public B getInner()
	{
		return new Inner();
	}
} 
class A
{
	public int getAge()
	{
		return 11;
	}
}
interface B
{
	public int getAge();
}

延伸阅读:

1)为什么内部类可以访问外部类的所有成员,包括私有的?

2)为什么在外部类的作用范围内可以任意创建内部类对象,即使内部类是私有的?即内部类对包围它的外部类可见。

3)为什么局部内部类只能访问被final修饰的局部变量?

4)为什么嵌套内部类(静态内部类)不能访问外部类的静态成员?

要了解到这些特点背后的机制,请参阅【解惑】领略Java内部类的“内部”这篇文章。



---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com                                                                     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值