【java】内部类

一、内部类

  • 什么是内部类

        内部类:把一个类定义在另一个类的内部,这个类就叫做内部类,而包含这个类的类就叫外部类。按照范围,内部类可以简单分为三种:静态内部类,成员内部类和局部内部类。这三种内部类的角色简单的对应了类变量、成员变量和局部变量。

package oop;

/*
 * OuterClass是外部类,他包含了内部类InnerClass
 */
public class OuterClass {
	/*
	 * InnerClass是内部类,因为他定义在类OuterClass中
	 */
	class InnerClass{
		
	}
}
  • 为什么需要内部类

        想象这样一个场景,人和心脏的关系,人包含了心脏,这样的关系可以利用组合来实现也可以利用内部类来实现。利用组合来实现,也就是定义一个心脏类,在人类中引用;利用内部类来实现,即在人类中定义一个心脏类。但是利用哪一种方式来实现会更好呢?在人的内部会有很多私有属性是不让其他人直接访问的,和心脏密切相关的例如血管动脉等,这些属性不必让外部访问,也没必要对外提供接口,如果用组合关系来实现,那么心脏所涉及的属性将要全部对外提供访问的接口,并且在定义心脏的时候需要传入这些接口,这将会增加了编码的复杂性。除此之外,心脏作为人类的内部属性之一,也不希望能被其他类访问,如果心脏类在人类外部定义,那么除了人类之外的其他类也可以访问。简单总结,内部类具有以下特点:

        1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之中,不允许同一个包中的其他类访问,也就是内部类可以用private修饰;

        2. 内部类成员可以直接访问外部类中私有数据;

        3. 对于创建那些只需要使用一次的类,匿名内部类更适合;

二、内部类详细

  • 非静态内部类

        非静态内部类即是成员内部类,可以简单这样理解,成员内部类的角色和成员变量、方法等扮演的角色相同,例如成员内部类可以用成员变量的修饰符修饰。

        1. 成员内部类的定义可以使用例如private、final、static(即静态内部类)等修饰符,也可以使用default、protected、public等修饰符,即成员变量可以使用的修饰符,成员内部类都可以使用;

        2. 成员内部类内部不能定义static修饰的成员,当然属性的宏替换例外,即static final修饰的属性除外,因为在类加载阶段就已经替换成常量,除此之外,根据静态不能方为非静态的原则,外部类的static修饰成员也不能引用成员内部类;

        3. 成员内部类可以直接访问外部类的所有属性和方法,包括private、static修饰符修饰的属性和方法,其中,如果成员内部类中定义和外部类同名的属性和方法,则不能直接使用,需要通过OuterClass.this.filedName和OuterClass.this.functionName来调用外部类包含的属性和方法;

        4. 想要在外部类之外使用成员内部类(权限和访问修饰符保持一致,例如private修饰的内部类不能在外部类以外访问,default不能在包以外访问),则需要先有外部类对象才能实例化内部类对象:OuterClass.InnerClass oi = new OuterClass().new InnerClass();或者OuterClass oc = new OuterClass;OuterClass.InnerClass oi = oc.new InnerClass();

        根据内部类实例化的方式可以知道,内部类想要实例化必须要先有外部类的实例存在,因此非静态内部类内部不能用static修饰,除了宏替换. 在类加载阶段可以替换成常量。

package oop;

/*
 * OuterClass是外部类,他包含了内部类InnerClass
 */
public class OuterClass {
	/*
	 * InnerClass是内部类,因为他定义在类OuterClass中
	 */
	class InnerClass {
		
	}
	
	public static void main(String[] args) {
		/*
		 * 在外部类以外引用内部类
		 */
		OuterClass.InnerClass oi = new OuterClass().new InnerClass();
	}
}

  • 静态内部类

        用static修饰成员内部类,则该内部类是静态内部类。静态内部类的角色就相当于外部类中的静态成员(静态属性和静态方法),他直接属于外部类本身,而不是外部类的实例对象。

        1. 静态内部类的修饰符和成员内部类一致;

        2. 根据静态不能访问非静态的原则,静态内部类只能访问外部类中的静态成员;

        3. 和成员内部类区别的是,静态内部类内部可以定义static和非static修饰的成员,而成员内部类内部不能用static修饰;

        4. 要想在外部类以外访问静态内部类,不需要先有外部类的实例对象,直接使用外部类类名即可:OuterClass.InnerClass oi = new OuerClass.InnerClass();

package oop;

/*
 * OuterClass是外部类,他包含了内部类InnerClass
 */
public class OuterClass {
	/*
	 * InnerClass是内部类,因为他定义在类OuterClass中
	 */
	static class InnerClass {
		
	}
	
	public static void main(String[] args) {
		/*
		 * 在外部类以外引用内部类
		 */
		OuterClass.InnerClass oi = new OuterClass.InnerClass();
	}
}

  • 局部内部类

        局部内部类定义在方法或者代码块中,局部内部类的角色相当于局部变量,局部变量不能使用修饰符,因此局部内部类也不能使用任何修饰符,所以局部内部类内部不能定义static修饰的成员,而且java规定,局部内部类访问外部类的局部变量,则该局部变量必须用final修饰。

package oop;

/*
 * OuterClass是外部类,他包含了内部类InnerClass
 */
public class OuterClass {
	public void show(){
		/*
		 * 方法中定义局部内部类
		 */
		class LocalClass {
			
		}
	}
}

        但是在JDK 1.8当中,局部内部类访问外部类的局部变量,已经不需要再定义成final类型,如以下例子。

package oop;

/*
 * OuterClass是外部类,他包含了内部类InnerClass
 */
public class OuterClass {
	public void show(){
		/*
		 * 方法中定义局部内部类
		 */
		int y = 4;
		class LocalClass {
			void function(){
				System.out.println(y);
			}
		}
		new LocalClass().function();
	}
}
package oop;

public class Main {
	public static void main(String[] args) {
		/*
		 * 程序无报错,输出4
		 */
		new OuterClass().show();
	}
}

  • 匿名内部类

        匿名内部类是局部内部类的特殊形式。

        1. 匿名内部类适合只需要创建一次的类;

        2. 使用匿名内部类的前提是该类必须继承一个类或者实现又给接口;

        3. 如果匿名内部类要访问外部类的局部变量,则该局部变量必须用final修饰;

package oop;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class FrameDemo {
	private Frame frame;
	
	private void init(){
		frame = new Frame("frame");
		/*
		 * 方法中添加了WindowAdapter的匿名内部类,在匿名内部类中重写了windowClosing方法
		 * WindowAdapter实现了WindowListener接口
		 */
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				frame.dispose();
			}
		});
		frame.setVisible(true);
	}
}

附注:

        本文如有错漏之处,烦请不吝指正,谢谢!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值