4.1嵌套类
Java程序语言支持嵌套类,也就是说,在类内定义另外一个类
嵌套类有两种类型:静态和非静态。用static修饰符声明的嵌套类称为静态嵌套类;非静态类型称为内部类
class OuterClass{
……
static class StaticNestClass{
……
}
class InnerClass{
……
}
}
嵌套类是其所附属类或外部类的成员。内部类可以访问外部类的其他成员,即使他们被声明为private。而静态嵌套类则不能访问外部类的其他成员。作为类的成员,嵌套类可以声明为private,public,protected,包私有。
4.1.1为什么要使用嵌套
- 对单一用途的类进行逻辑分类:某个类只对其他一个类有用,就可以将前者逻辑嵌套入后者,将他们放在一起
- 提高封装度:假设两个顶层类A和B,而B要访问A的私有成员。将B嵌套入A中,A的成员可用private声明。而B可以访问这些成员,另外,B对外界是隐藏的
- 提高代码的可读性和可维护性
4.1.2 静态嵌套类
与类方法和类变量一样,静态嵌套类与外部类(指的是静态嵌套类作为某个类的成员的那个类)也相关联。与静态方法一样,静态嵌套类不能直接引用外部类定义的实例变量和方法,而只能使用对象引用间接访问
静态嵌套类访问其外部类(和其他类)的实例成员的方式,与其访问其他顶层类的实例成员一样。实际上,就行为而言,静态嵌套类仍是顶层类,它是为了打包方便才嵌套在另一个顶层类中
静态嵌套类要用外部类名访问
4.1.3内部类
(1)与实例方法和实例变量一样,内部类也与外部类的实例相关联,它可以直接访问对象的方法和字段,因为内部类与实例类相关联,所以内部类本身不能定义任何静态成员
(2)内部类的实例存在于外部类的实例里,要实例化内部类,必须首先实例化外部类,然后在外部对象中在创建内部对象,比如:
OutClass.InnerClass innerObject=
outerObject.new InnerClass();//outerObject为外部类对象,通过外部类对象来创建内部类对象
4.1.3.1局部类和匿名类
内部类还有两种类型:
- 局部类:它在方法体内声明
- 匿名内部类:它也在方法体内声明,但是不对类命名
关于局部类有几个知识点:
- 局部类可以访问所属类的成员:局部类可以访问其所属类的成员,也可以访问局部变量,但只能访问声明为final的局部变量(修饰符final表示变量或参数一旦被初始化,其值将不发生变化),因为内部类在构造的时候,会被编译器自动传入外部类对象的引用,同时也会i传入内部类访问的局部变量的引用,这也就解释内部类对象为什么可以访问外部类的成员变量和函数还有局部变量了。但是由于这些工作是在编译时进行的,Java虚拟机并没有什么所谓的内部类的概念,在Java虚拟机看来,该内部类和外部类是两个独立的class文件,假设我们不在局部变量加上final,那么意味着我们可以随时改变局部变量的值,当我们,当我们创建了一个内部类的对象后,修改了内部类所要访问的局部变量的值,那么就会造成局部变量传递给内部类对象的值和此时的值不一致
- 从JavaSE8开始,如果局部类是在方法内声明的,他就可以访问方法的参数
4.1.3.2覆盖和局部类
局部类中声明的类型会覆盖局部类所属范围内相同名称的类型声明
局部类和内部类相似(即都不是静态的,因为要访问实例成员),他们都不能定义任何的静态成员。静态方法中的局部类只能引用所属类的静态成员,但是局部类中的常量变量可以声明为静态类型,常量变量是指那些原始类型或者String类型的,声明为final的,而且被编译时常量表达式所初始化的变量
4.1.4匿名类
匿名类是表达式,而局部类是类声明,也就是说,匿名类是定义在表达式中的,使用匿名类可同时声明和实例化类,匿名类没有类名。
匿名类应该包含如下内容:
- new运算符
- 实现的接口名或继承名
- 将参数包含入构造器的括号,和通常的类实例创建表达式类似
- 类声明体(类声明体中允许方法声明,不允许语句声明)
匿名类的限制:
- 不能在匿名类中声明静态的初始化内容或者成员接口
- 匿名类可以有静态成员,但必须是常量变量
补充:
- 匿名类可以访问其所属类的成员
- 匿名类不可以访问所属范围内未声明未final的局部变量
匿名类通常用于GUI应用程序。