欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java学习系列(二十三)Java面向对象之内部类详解

程序员文章站 2022-05-01 11:28:50
...

 

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45372395

 

一、前言

 

内部类也称寄生类,就是把一个类放在类里面(即内部类的上一级程序单元是类)定义,将其作为外部类的成员。内部类主要用几种定义形式:静态(static)内部类,非静态内部类,匿名内部类(也就是没有名字的寄生类)。内部类的好处就是内部类可以直接外部类的(包括私有)成员,反之不能。下面我们通过一些实例来详细讲解一下Java中内部类的使用及几种定义形式的相互调用。

 

二、实例说明

 

(1)匿名内部类:当程序创建匿名内部类时,会立即创建匿名内部类(实现类)的实例。

 

interface IBreathe {
	void breathe();
}

/**
 * 匿名内部类的使用,定义形式如下:
 * 
 * new 接口() | 父类构造器<参数>){ 
 * 		// 类体部分... 
 * };
 * 
 * @author [*昨日重现*] lhy_ycu@163.com
 * @since version 1.0
 * @datetime 2015年4月29日 下午10:17:40
 */

public class Anonymous {

	// 这里相当于创建了接口IBreathe的匿名实现类,并创建了匿名内部类的实例
	// 将实现类的实例赋值给接口变量 ,属于向上转型
	IBreathe breathe = new IBreathe() {
		// 必须实现接口里的所有抽象方法
		@Override
		public void breathe() {
			System.out.println("呼吸新鲜空气...");
		}
	};

	public static void main(String[] args) {
		Anonymous anonymous = new Anonymous();
		anonymous.breathe.breathe();
	}
}

 

注意以下几点:
1)只要父类是抽象类或者是一个接口,那么其子类中的方法都可以使用匿名内部类来实现;反过来也就是说使用匿名内部类有个前提:它必须显示地继承一个父类或实现一个接口。
2)匿名内部类必须实现接口或抽象类中所有的抽象方法。
3)匿名内部类适合创建只需一次使用的类。
4)匿名内部类不能有构造器而且程序以后无法再访问它,因为它没有类名。

 

(2)静态内部类:它属于外部类(宿主类)的静态成员,所以它不能访问外部类的非静态成员(属性、方法)。

 

/**
 * 外部类(宿主类)中包含静态内部类作为外部类的一个静态成员
 * 
 * @author [*昨日重现*] lhy_ycu@163.com
 * @since version 1.0
 * @datetime 2015年4月29日 下午11:00:51
 */

public class Out {
	private static String name = "张三";
	private String sex = "男";

	static class In {
		private static String name = "李四";

		public void info() {
			// 静态内部类不能访问外部类的非静态成员,所以下面这句会编译不通过
			// System.out.println("外部类的sex = " + sex);
			System.out.println("in的info方法被调用,name:" + name);
		}
	}

	public static void main(String[] args) {
		// 打印结果(编译器遵循就近原则):in的info方法被调用,name:李四
		// 这里只需要把外部类当成静态内部类的包就行了
		// 所以In前加不加Out.都是一样的
		new In().info();
		new Out.In().info();
	}
}

 

如果要在外部类的外面访问静态内部类的成员:Out.In in = new Out.In();in.info();当然,静态内部类也可以派生子类:class InSub extends Out.In {},编写和调用方式与普通类一样,这里不再赘述。下面看看重点来看看非静态内部类定义和使用。

 

(3)非静态内部类:在创建非静态内部类的实例前,必须先创建外部类实例,也就是说非静态内部类必须寄生在外部类的实例(Outer.this)里面。所以在创建非静态内部类的实例前,必须先创建外部类实例。

 

/**
 * 非静态内部类的使用
 * 
 * @author [*昨日重现*] lhy_ycu@163.com
 * @since version 1.0
 * @datetime 2015年4月29日 下午11:26:06
 */

public class Outer {
	int number = 10;

	// 定义非静态内部类
	class Inner {
		int number = 100;

		public void info() {
			int number = 1000;
			System.out.println("Inner内部类的info()方法被调用~");
			System.out.println("number变量的值为:" + number);// 方法的局部变量,所以为1000
			System.out.println("number变量的值为:" + this.number);// 指向寄生类成员,所以为100
			System.out.println("number变量的值为:" + Outer.this.number);// 指向宿主类成员,所以为10
		}
	}

	/**
	 * 通过外部类的方法来访问寄生类的成员(属性、方法)
	 */
	public void info() {
		System.out.println("Outer外部类的info()方法被调用~");
		Inner inner = new Inner();
		inner.info();
		System.out.println(inner.number);
	}

	public static void main(String[] args) {
		new Outer().info();
	}
}

如果在外部类的外面使用内部类,那么在创建非静态内部类的实例前,必须先创建外部类实例。
Outer outer = new Outer();
Outer.Inner in = outer.new Inner();
等价于==》Outer.Inner in2 = new Outer().new Inner();

 

当然非静态内部类也可以派生子类,如下:

 

//非静态内部类派生子类
class InnerSub extends Outer.Inner {
	public InnerSub() {
		// 由于Outer.Inner是非静态内部类,因此必须使用"宿主对象"来调用它的构造器
		new Outer().super();
	}}

 

 

 

三、总结

 

1)有static修饰的内部类属于外部类本身,没有static修饰的内部类属于类实例 。

2)记住方法是谁的,就用谁来调用。

3)没有static修饰的内部类,【必须寄生在“外部类”的实例里】;反之则寄生在外部类本身里。

4)静态内部类是寄生在类本身里面的,所以就不需要程序员理会宿主。-把外部类当成静态内部类的包就行了。

5)非静态内部类派生子类:由于子类的构造器必须调用父类构造器一次,因此必须在子类构造器中使用宿主对象来调用它的构造器。

 

四、结束语

 

关于Java中的内部类的定义和使用基本内容就这些,后面会陆续更新包括:正则表达式、Java性能优化、学习JVM等等,敬请关注。