java的4种内部类

原文链接:https://blog.csdn.net/ll530304349/article/details/52926848

一直对内部类、静态内部类这些名词的认识不太清晰,做一些小小的总结。 
一、什么是嵌套类(nested class)? 
首先Java中的嵌套类(nested class)是指定义在另一个类的内部的类,所以叫嵌套类。它有很多种分类的方式,从类型上分,有成员类(member class)、匿名类(anonymous class)和局部类(local class);从属性上来说,有静态类(static class)和内部类(inner class)之分,除了静态成员类之外,其他的非静态成员类、匿名类和局部类都可以说是内部类。下面我们来了解每种类型的特点和作用。

二、成员类(member class) 
成员类是我们用的比较常见的一种类型,就是在一个类的内部(类的结构体内)定义的类,而成员类又分为静态成员类(static member class)和内部成员类(inner member class)、也就是非静态成员类。 
1、静态成员类(static member class) 
静态成员类就是定义在类的内部的,用static修饰符修饰的类,是最简单的嵌套类。可以这么来理解,它就是一个普通的类,只不过恰巧被声明在另一个类的内部用作辅助而已,而你将它声明在类的外部不是不可以,只是声明在内部更能看出它“辅助”外部类的作用罢了。由于是static修饰的,它不能访问外部类的非static属性和方法,但它可以单独创建,就是在不需要外部类的实例的情况下可以创建,比如Builder模式中的内部类Builder类就必须是static的,为什么呢?因为Builder是要创建外部类实例的辅助类,是独立存在的,它的职责是创建外部类的实例,所以它必须是static的。至于为什么这么说,在区别里我会说明的。 
2、内部成员类(inner member class) 
内部成员类也叫非静态成员类,就是没有static修饰的写在外部类结构体内的类。内部成员类最关键的一个特点就是它具有一个隐含的外部类的实例,所以说内部成员类和它的外部类至少是一对一的关系,一个外部类实例对应着至少一个内部类实例,没有外部类实例是创建不了内部类实例的!内部成员类可以访问外部类的所有方法和属性,这是与静态成员类行为上的区别。它的常见用法就是表示外围类所代表的对象的一个组件,比如Set的组件之一迭代器Iterator。 
3、区别 
静态成员类和非静态成员类有什么至关重要的区别呢?我们为什么要分静态和非静态呢?其实最重要的原因就是外围实例(enclosing instance)的区别,非静态成员类的实例中隐含着一个外部类的实例,也就是说,非静态成员类是“依附”于外部类的,需要外部类的实例才能有自己的实例,而静态成员类的static就表示了它的独立性,它只是与外部类相关,而不与它的某个实例相关。比如一个策略Host发布自己的静态比较器实例,如果比较器是内部实现的,那它必然是一个静态内部类,因为它与你的Host实例没有关系,是与Host类相关的。而且编辑器也告诉了我么你这一点,类的静态属性的类型不能是内部成员类,必须是静态成员类!(仔细思考一下,原因就是static属性不能提供一个隐含的外部类实例)

三、匿名类(anonymous class) 
匿名类也是内部类之一哦,我们应该时刻清楚内部类与静态类的区别。匿名类是Java的特性之一,在声明新的对象的同时声明类,即同时声明和实例化,并且不能再次使用,所以才“匿名”。同样,作为内部类,匿名类也会具有外部类的具体实例,这个是很需要注意的问题(内存泄漏方面,如果你保存了一个长期存在的内部类实例,它具有你外部类实例的隐含实例,那么即使你的外部类已经应该抛弃了,但由于它的引用仍然存在,它就不能被回收)。另外我们要注意,匿名类是可以存在在静态环境中,它不会拥有外部实例,但也不能拥有任何静态成员。 
匿名类就是一个简洁的“一次性”类的实现方式,但要尽量保持简洁,比如android中的button点击监听经常遇到的代码:

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //具体实现
            }
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这是一种简洁的方式,但一旦内部实现变多,就会增大代码的阅读难度,就应该采取别的实现方式了。 
《Effective Java》中总结的匿名类的作用有主要三种:1、动态常见函数对象(function object);2、主要是用于创建过程对象,比如Runnable、Thread实例等;3、用于静态工厂方法的内部。在我看来其实可以用更抽象的方式来表达: 
1、当内部类只在一个函数中作为参数使用一次(函数对象就是典型); 
2、当内部类作为过程对象使用(Runnable就是过程对象); 
3、当内部类只当做实例在函数中直接返回(静态工厂返回实例)

四、局部类(local class) 
局部类是用的非常少的类,它也是内部类之一,一般出现在函数体的内部,其实只要是“可以声明局部变量”的地方,都可以声明局部类,并且作用域规则和局部变量一样,除了可以重复使用,其他特点和匿名类一样。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值