Java内部类

所谓的内部类,就是将一个类定义到另一个类的定义内部。这里引入一个词——嵌套类,嵌套类包括静态嵌套类和非静态嵌套类(内部类),这里的非静态嵌套类就是内部类,而嵌套类呢在接下来的介绍中会讲到。

对于内部类(非静态嵌套类),可以分为三种:

(1) 局部内部类

(2) 匿名内部类

(3) 成员内部类

接下来看看内部类的创建方式:

一、创建局部内部类。

public class LocalInnerClass {
	private static final String LABEL = "LocalInnerClass";
	class LocalClass{
		public LocalClass(){
			System.out.println("LocalClass()");
		}
		public String getLabel(){
			return LABEL;
		}
	}
	public LocalClass getLocalClass(){
		return new LocalClass();
	}
	public static void main(String[] args){
		LocalInnerClass lic = new LocalInnerClass();
		/*
		 * 创建内部类对象的格式为:外部类.内部类  内部类的引用 = 外部类实例化对象的引用.返回内部类引用的方发(或者).new 内部类;
		 * */
		LocalInnerClass.LocalClass localclass = lic.getLocalClass();
//		LocalInnerClass.LocalClass localclass2 = lic.new LocalClass();
		System.out.println(localclass.getLabel());
	}
}
运行结果:LocalClass() LocalInnerClass


局部内部类的特点:局部内部类不能有访问说明符,如public、protected、private等,这是因为局部内部类不是外围类的一部分;但是它可以访问当前代码块内的常亮以及此外围类的所有成员。


二、创建匿名内部类。

package Inner;
/*
 * 定义的一个接口
 * */
public interface Ainterface {
	String readString();
	int value();
}
package Inner;
public class Anonymousinnerclass {
	public Ainterface getAinterface(){
		/*
		 * 匿名内部类的定义
		 * */
		return new Ainterface(){
			private int i = 100;
			private String string = "Anonymousinnerclass";
			public String readString(){
				return string;
			}
			public int value(){
				return i;
			}
		};
	}
	public static void main(String[] args){
		Anonymousinnerclass aic = new Anonymousinnerclass();
		Ainterface ai = aic.getAinterface();
		System.out.println(ai.readString()+","+ai.value());
	}
}
运行结果:Anonymousinnerclass,100

对于上面的例子,很多刚学Java的人都会奇怪,getAinterface()方法将返回值的生成与表示这个返回值的类的定义结合了在一起!而这就是匿名内部类。下面我们就简化一下上面的匿名内部类,通过语法的简化形式,相信大家能更理解。

上面例子的简化形式:


public class TestAnonymous {
	class MyAnonymous implements Ainterface{
		private int i = 100;
		private String string = "Anonymousinnerclass";
		public String readString(){
			return string;
		}
		public int value(){
			return i;
		}
	}
	/*
	 * 向上转型为Ainterface
	 * */
	public Ainterface getAinterface(){
		return new MyAnonymous();
	}
	public static void main(String[] args){
		TestAnonymous ta = new TestAnonymous();
		Ainterface atf = ta.getAinterface();
		System.out.println(atf.readString()+","+atf.value());
	}
}
运行结果:Anonymousinnerclass,100

三、创建成员内部类。

/*
 * 成员内部类都有访问说明符,如public、private、protected等修饰
 * 成员内部类是可以访问外部类的静态与非静态的方法和成员变量的。
 * */
public class MemberInnerClass {
	private int x = 10;
	public void value(){
	}
	/*
	 * 成员内部类的创建
	 * */
	public class MemberClass{
		/*
		 * 可以在内部类中定义于外部类同名的成员变量于方法
		 * */
		private int x = 100;
		public void value(){
			System.out.println("内部类_x:"+this.x);
			System.out.println("外部类_x:"+MemberInnerClass.this.x);
		}
	}
	public static void main(String[] args){
		MemberInnerClass mic = new MemberInnerClass();
		MemberInnerClass.MemberClass mc = mic.new MemberClass();
		mc.value();
	}
}
运行结果:
内部类_x:100
外部类_x:10

四、创建嵌套类

将内部类声明为static,从而不需要内部类对象与外围类对象之间存在联系,就称之为嵌套类。嵌套类的static有何含义?对于普通内部类,其对象隐式地保存了一个引用,并指向了创建他的外围类的对象,而嵌套类则不是这样。
对嵌套类:
1.要创建嵌套类的对象,并不需要其外围类的对象。
2.不能从嵌套类的对象中访问非静态类的外围类对象。
嵌套类和普通内部类还有一个区别。普通内部类的字段和方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和字段,也不能包含嵌套类。而嵌套类则可以包含所有这些东西。内部类会通过一个特殊的this引用可以链接到其外围类的对象,嵌套类就没有这个特殊的this引用,这就使得它类似于一个static方法。

示例:

public interface Destination {
	String readLabel();
}
public class Parcel11 {
	/*
	 * 嵌套类不同于内部类,嵌套类可以包含static,但内部类则不能
	 * */
	private static class ParcelDestination implements Destination{
		private String label;
		private ParcelDestination(String whereTo){
			label = whereTo;
		}
		public String readLabel(){
			return label;
		}
		public static void f(){}
		static int x = 10;
		/*
		 * 嵌套类内部再定义一个嵌套类
		 * */
		static class AnotherLevel{
			public static void f(){}
			static int x = 10;
		}
	}
	public static Destination destination(String s){
		return new ParcelDestination(s);
	}
	public static void main(String[] args){
		Destination d = destination("This insertinnerclass ");
		System.out.print(d.readLabel());
	}
}	
运行结果:This insertinnerclass 


接下来,深入总结一下内部类的一些重要知识点:
(1)使用.this与.new
如果要在内部类中生成对外部类对象的引用,可以使用外部类的名字后面紧跟着圆点和this。这样产生的引用自动地具有正确的类型,这一点在编译期就被知晓并受到检查,因此没有任何运行时的开销。
下面示例展示了如何使用.this:

/*
 * 使用内部类的.this
 * */
public class DoThis {
	void fun(){
		System.out.print("DoThis.fun()");
	}
	class Inner{
		public DoThis outer(){
			return DoThis.this;
		}
	}
	public Inner inner(){
		return new Inner();
	}
	public static void main(String[] args){
		DoThis dothis = new DoThis();
		DoThis.Inner inner = dothis.inner();
		inner.outer().fun();
	}
}
结果:DoThis.fun() 
而.new,之前已经介绍过了,是用于创建内部类对象的方法之一,也就是外部类引用.new 内部类()。

2)定义匿名内部类的条件
内部类必须继承一个父类或者实现一个接口,其中父类又包括普通类与抽象类。
下面就来展示这三种情况:


继承普通类

public class Wrapping {		//定义的普通类
	private int i;
	public Wrapping(int x){
		i = x;
	}
	public int value(){
		return i;
	}
}

public class SympleClass {
	public Wrapping wrapping(int x){
		return new Wrapping(x){
			public int value(){
				return x;
			}
		};
	}
	public static void main(String[] args){
		SympleClass sc = new SympleClass();
		Wrapping w = sc.wrapping(100);
		System.out.println(w.value());
	}
}
结果:100


继承抽象类

public abstract class Wrapping2 {
	public abstract int value();
}
public class SympleClass {
	private int x = 100;
	public Wrapping2 wrapping2(){
		return new Wrapping2(){
			public int value(){
				return x;
			}
		};
	}
	public static void main(String[] args){
		SympleClass sc = new SympleClass();
		Wrapping2 w = sc.wrapping2();
		System.out.println(w.value());
	}
}
结果:100


实现接口

package Inner;
/*
 * 定义的一个接口
 * */
public interface Ainterface {
	String readString();
	int value();
}
package Inner;
public class Anonymousinnerclass {
	public Ainterface getAinterface(){
		/*
		 * 匿名内部类的定义
		 * */
		return new Ainterface(){
			private int i = 100;
			private String string = "Anonymousinnerclass";
			public String readString(){
				return string;
			}
			public int value(){
				return i;
			}
		};
	}
	public static void main(String[] args){
		Anonymousinnerclass aic = new Anonymousinnerclass();
		Ainterface ai = aic.getAinterface();
		System.out.println(ai.readString()+","+ai.value());
	}
}
运行结果:Anonymousinnerclass,100

(3)那为什么需要内部类呢?

在《Think in Java》中,每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的、可继承多个具体的或抽象的类的能力,一些设计与编程问题就难以解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效的实现了“多重继承”。也就是说,内部类允许继承多个非接口类型(类与抽象类)。

总结一下节点:

(1)解决了多继承的问题

(2)多个内部类可以以不同的方式实现同一接口,继承同一个类。

(3)创建内部类对象的时刻并不依赖于对外围类对象的创建。

(4)内部类并没有“is-a”关系,它就是一个独立的实体。

(5)内部类提供了更好的封装,除了外围类,其他类都不能访问。

但对于内部类的使用,我们必须要清楚什么时候能用,什么时候不能用。相信随着对Java的深入学习,我们能够更好的识别什么情况下应该使用接口,什么情况下使用内部类,或者同时使用二者。












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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值