JAVA Nested Class -- Java 嵌套类

1.Nested Class 嵌套类

JAVA语言允许你在一个类里面定义另外一个类,这样的类被称为嵌套类。举例如下:

class OuterClass {
		...
	class NestedClass {
		...
	}
}

术语:嵌套类分为2大类:静态和非静态。被声明为static的嵌套类称为静态嵌套类;非静态嵌套类则被称为内部类。

class OuterClass {
	...
 	static class StaticNestedClass {
		...
	}
	class InnerClass
}

一个嵌套类是它的包围类的成员。非静态嵌套类(inner classes)可以访问包围类的其他成员,即使成员被声明为private。静态嵌套类不能访问包围类的其他成员。作为OuterClass的成员,嵌套类可以被声明为private,public, protected, 或者 package private。(记得outerclass只能被声明为public或者package private)

为什么要使用嵌套类?

以下是一些吸引人的理由:

  1. 是一个逻辑上分组那些只在一个地方使用的方法:如果一个类只对某个类有用,那么逻辑上他就应该嵌入那个类,让他们合二为一。
  2. 提高封装性:考虑2个top-level的类,A和B, B需要访问A的成员,除此之外,A的成员还将被声明为private。通过在A中隐藏B,A的成员就能被声明为private,B也能访问他们。此外,B本身也可以在外面的世界隐藏掉。
  3. 可以提高可读性和维护性:在顶层类中嵌套小型类使得代码更接近于被使用的地方

静态嵌套类

作为类方法和变量,嵌套类关联与他的包围类。就像静态类方法,嵌套类不能直接引用他的包围类实例的变量或者方法: 可以通过对象引用来达成目的
请使用包围类的名字来访问静态嵌套类:

OuterClass.StaticNestedClass

举例,要创建一个静态类对象,使用以下语法:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

内部类

作为实例方法和变量,内部类关联于它的包围类的一个实例,并能直接访问对象的方法和成员。同时,因为内部类关联于一个实例,它就不能定义它自己的静态成员
内部类的实例存在于一个外部类的实例中,考虑以下classes:

class OuterClass {
	...
	class InnerClass {
		...
	}
}

InnerClass的实例只能存在OuterClass的实例内部,能直接访问包围类的方法和域。
要实例化一个内部类,你首先要实例化OuterClass。然后,使用语法在包围类里面创建内部类对象:

OuterClass.InnerClass innerClass = outerObjct.new InnerClass

遮蔽效应

在特定范围(比如内部类或者方法定义)的类型声明(比如成员变量或者参数名字)和 在包围类的声明同名,那么该声明就会遮蔽包围类的声明。你不能只通过它的名字来引用。下面就是一个例子:

public class ShadowTest {
	public int x= 0;
	class FirstLevel {
		public int x = 1;
		void methodInFirstLevel(int x) {
			System.out.println("x = " + x);
			System.out.println("this.x = " + this.x);
			System.out.println("ShadowTest.this.x = " + ShadowTest..this.x);
		}
	}
	public static void main(String... args) {
		ShadowTest st = new ShadowTest();
		ShadowTest.FirstLevel f1 = st,new FirstLevel;
		f1.methodInFirstLevel(23);
	}
}

以下是例子的输出:

x = 23
this.x = 1
ShadowTest.this.x = 0

这个例子定义了三个变量都名为x:类ShadowTest的成员变量,内部类FirstLevel的成员变量,还有方法methodFirstLevel的参数。定义为方法methodFirstLevel的变量x遮蔽了内部类FirstLevel的变量。结果就是,当你在方法methodLevel里使用变量x的时候,它指向的方法参数。要指向内部类FirstLevel的成员变量,使用关键字this来代表包围类:

System.out.println("this.x = " + this.x);

可以通过所属的类名来指向更大包围范围的变量。举个例子,以下表达式就从方法methodFirstLevel里访问了类ShadowTest的成员变量:

System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);

序列化

不赞同去序列化内部类,包括local 和 anonymous类。当java编译器去编译某些结构,比如内部类,它会创建复合结构;有类,方法,域和其他的在源代码中没有对应的结构的结构。复合结构让java编译器在不改变JVM的前提下实现了新的java功能。然而,复合结构在不同的java编译器版本中会有不同的变化,也就是说,.class文件会有不同的实现。结果就是你会遇到兼容性问题,假如你在不同版本的JRE里进行序列化。参考章节Implicit and Synthetic Parameters in the section Obtaining Names of Method Parameters for more information about the synthetic constructs generated when an inner class is compiled.

本地类和无名类

此外还有2种类型的内部类。你可以在一个方法的内部声明一个嵌套类。我们称之为本地类。你也可以在方法里声明一个没有名字的嵌套类,我们称之为匿名类。

修饰符

对于嵌套类,你可以使用同样对于外部类成员能使用的修饰符, 来限制其他类的成员访问它的权限

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值