【疯狂Java讲义】Java学习记录(内部类)

 内部类

内部类(寄生类)

外部类(宿主类)

内部类就是把一个类放在类里面定义

- 由于它的上一级程序单元是类,

  因此它完全可以使用private | 默认 | public这4个访问控制符。

- 由于它的上一级程序单元是类,

  因此有static修饰的内部类,属于外部类本身;

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

内部类生成的class文件名为:外部类$内部类.class

内部类的一个好处:它可以直接访问外部类的privat成员(成员变量/方法/构造器)

内部类可以直接访问外部类的成员,包括private成员

反过来,外部类不可以访问内部类的成员。

内部类,还有个名称叫做“寄生类”。

- 如果是没有static修饰的内部类的实例,必须寄生在“外部类”的对象里。

- 如果是有static修饰的内部类的实例,寄生在“外部类”的类本身里。

1、非静态内部类

- 没有static修饰的内部类,因为它的实例只要寄生外部类的实例中。

- 无论是创建非静态内部类的实例,还是派生子类,都要保证先有宿主对象。

- 也属于非静态成员——因为不能被外部类的静态成员所访问。

2、静态内部类

- 静态内部类要用static修饰。因为它的实例只要寄生外部类的类本身即可。

   使用时,无需程序员关心“宿主”。基本上,你可以把外部类当成静态内部类的“包”来使用。

- 静态内部类也是属于静态成员,因此它不能访问外部类的非静态成员(成员变量、方法)

使用内部类

1、定义变量

2、创建实例

3、访问它的类Field / 类方法

(1)如果在外部类的里面使用内部类,并没有太多需要注意的地方。

(2)在外部类的外面使用内部类,

①非静态内部类

- 声明变量:外部类.内部类 变量名

- 创建非静态内部类的实例。

   在此之前,必须先创建外部类的实例 —— 必须先创建宿主

   接下来,用 宿主.new 外部类构造器();

Outer.Inner in;
		
Outer outer = new Outer();
		
//从下面代码可以看出outer是宿主对象,in寄生在outer里面
in = outer.new Inner();
		
// 上面3行代码,与下面一行代码是相同的
Outer.Inner in2 = new Outer().new Inner();

- 非静态内部类派生子类

  由于子类的构造器,必须调用父类构造器一次。

  因此必须在子类构造器中使用宿主对象去调用非静态内部类的构造器。

②静态内部类

- 静态内部类它是寄生外部类的类本身里的,所以一般不需要程序员去理会宿主。

   你可以把外部类当成静态内部类的包就行了。

3、局部内部类(了解一下)

- 用的不是很多!

- 局部内部类,是一个局部成员,和局部变量相似,因此不能用static修饰。

- 局部内部类可以用final修饰,表明这个局部内部类不能被继承。

- 局部内部类的作用域实在太有限了,只能在方法内使用——出了方法就不能使用了。

- 由于局部内部类只能在当前方法中使用,因此使用起来比较简单。

- 局部内部类的class文件名为 外部类$N内部类.class

   ——为什么要有N?因为一个外部类,不同方法中可以定义多个同名的局部内部类。

4、匿名内部类

- 它是一个“没有名字”的内部类,所以程序以后无法再访问这个“匿名内部类”。

   当程序创建匿名内部类时,会立即创建匿名内部类的实例

匿名内部类的语法

new 接口() | 父类构造器(参数) {

        //类体部分

}

——上面语法格式实际上返回匿名内部类的实例。

匿名内部类的规则

①匿名内部类必须显式继承一个父类,或实现【一个】接口

②匿名内部类必须实现接口或抽象类中所有的抽象方法。

    ——因为匿名内部类需要立即创建实例,因此它不能是抽象的。

③匿名内部类不能有构造器。

    ——因为匿名内部类没有类名,构造器名无法确定。

interface Workable {
	void work();
}

public class 匿名内部类 {

	public static void main(String[] args) {
		// 此处相当于 
		// ①创建Workable的匿名的实现类
		// ②并创建匿名的实现类的实例
		// 将实现类的实例赋给接口变量,典型的向上转型
		Workable w = new Workable() {
			
			private int age = 20;
			{
				System.out.println("初始化。。。");
			}
			
			//实现接口中的抽象方法是必须的
			@Override
			public void work() {
				// TODO Auto-generated method stub
				System.out.println("我正在工作。。。");
			}
			
			private void test() {
				System.out.println("普通的方法。。。");
			}
		};
		/*
		  上面的代码相当于
		    class MyWorker implements Workable {
			    private int age = 20;
				{
					System.out.println("初始化。。。");
				}
				@Override
				public void work() {
					// TODO Auto-generated method stub
					System.out.println("我正在工作。。。");
				}
				
				private void test() {
					System.out.println("普通的方法。。。");
				}
			}
		 * 
		 */
		
		w.work();
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值