Java内部类(Inner Class)

简单的说,内部(inner)类指那些类定义代码被置于其它类定义中的类;而对于一般的、类定义代码不嵌套在其它类定义中的类,称为顶层(top-level)类。对于一个内部类,包含其定义代码的类称为它的外部(outer)类。

<!--[if !supportLists]-->1 <!--[endif]-->Static member class(静态成员类)

类声明中包含“static”关键字的内部类。如以下示例代码,

Inner1/Inner2/Inner3/Inner4就是Outer的四个静态成员类。静态成员类的使用方式与一般顶层类的使用方式基本相同。


<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> public class Outer{
// justlikestaticmethod,staticmemberclasshaspublic/private/defaultaccessprivilegelevels

// accessprivilegelevel:public
public static class Inner1{
public Inner1(){
// Staticmemberinnerclasscanaccessstaticmethodofouterclass
staticMethod();
// Compileerror:staticmemberinnerclasscannotaccessinstancemethodofouterclass
// instanceMethod();
}
}

// accessprivilegelevel:default
static class Inner2{

}

// accessprivilegelevel:private
private static class Inner3{
// defineanestedinnerclassinanotherinnerclass
public static class Inner4{
}
}

private static void staticMethod(){
// cannotdefineaninnerclassinamethod
/* publicstaticclassInner4(){
}
*/
}

private void instanceMethod(){
// privatestaticmemberclasscanbeaccessedonlyinitsouterclassdefinitionscope
Inner3inner3 = new Inner3();
// howtousenestedinnerclass
Inner3.Inner4inner4 = new Inner3.Inner4();
}
}

class Test{
Outer.Inner1inner1
= new Outer.Inner1();
// TestandOuterareinthesamepackage,soInner2canbeaccessedhere
Outer.Inner2inner2 = new Outer.Inner2();
// Compileerror:Inner3cannotbeaccessedhere
// Outer.Inner3inner3=newOuter.Inner3();
}


<!--[if !supportLists]-->1.1 <!--[endif]-->静态成员类特性

  • 静态成员类可访问外部类的任一静态字段或静态方法
  • 像静态方法或静态字段一样,静态成员类有public/private/default权限修饰符

<!--[if !supportLists]-->1.2 <!--[endif]-->静态成员类约束

  • 静态成员类不能与外部类重名

  • 像外部类的静态方法一样,不能直接访问外部类的实例字段和实例方法
  • 静态成员类只能定义于外部类的顶层代码或外部类其它静态成员类的顶层代码中(嵌套定义);不能定义于外部类的某个函数中。

<!--[if !supportLists]-->1.3 <!--[endif]-->新增语法

如示例代码所示,可以以“OuterClass.InnerClass”的方式来引用某个内部类。

<!--[if !supportLists]-->1.4 <!--[endif]-->什么时候使用静态成员类

BA的辅助类,且只为A所用时,可将B定义为A的静态成员类。例如JDK中的LinkedList类就有Entry静态成员类:

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> public class LinkedList < E > extends AbstractSequentialList < E >
…;
private static class Entry < E > {
Eelement;
Entry
< E > next;
Entry
< E > previous;

Entry(Eelement,Entry
< E > next,Entry < E > previous){
this .element = element;
this .next = next;
this .previous = previous;
}
}
…;
}

显然,Entry用来表示LinkedList中的一个结点,只被LinkedList自身使用。

<!--[if !supportLists]-->2 <!--[endif]-->Member class(成员类)

一个静态成员类,若去掉“static”关键字,就成为成员类。如下示例代码,Inner1/Inner2/Inner3/Inner4就是Outer的四个成员类

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> public class Outer{
// justlikeinstancemethod,memberclasshaspublic/private/defaultaccessprivilegelevels
private int data;

// accessprivilegelevel:public
public class Inner1{
private int data;
private int data1;
public Inner1(){
// memberclasscanaccessitsouterclass'instancefielddirectly
data1 = 1 ;
// itselfdatafield
data = 1 ;
// itsouterclassinstancefield
Outer. this .data = 1 ;
}
}

// accessprivilegelevel:default
class Inner2{
// cannotdefinestaticfiled,method,classinmemberclass
// staticintj=1;

// but,"staticfinal"compoundisallowed
static final int CONSTANT = 1 ;
}

// accessprivilegelevel:private
private class Inner3{
public class Inner4{

}
}

// infact,Inner5isnotamemberclassbutastaticmemberclass
interface Inner5{
}

private static void staticMethod(){
// cannotcreateamemberclassinstancedirectlyinouterclass'staticmethod
// Inner1inner1=newInner1();
}

private void instanceMethod(){
// cancreateamemberclassinstanceinouterclass'instancemethod
Inner1inner1 = new Inner1();
}
}

class Test{
public Test(){
// cannotcreatememberclassinstancedirectlyinclassotherthanouterclass
// Outer.Inner2inner2=newOuter.Inner2();

// createamemberclassinstanceoutsideit'souterclass
Outerouter = new Outer();
Outer.Inner1inner1
= outer. new Inner1();
}
}

<!--[if !supportLists]-->2.1 <!--[endif]-->成员类特性

<!--[if !supportLists]-->· <!--[endif]-->类似于外部类的实例函数,成员类有public/private/default权限修饰符

<!--[if !supportLists]-->· <!--[endif]-->一个成员类实例必然所属一个外部类实例,成员类可访问外部类的任一个实例字段和实例函数。

<!--[if !supportLists]-->2.2 <!--[endif]-->成员类约束

  • 成员类不能与外部类重名

  • 不能在成员类中定义static字段、方法和类(static final形式的常量定义除外)。因为一个成员类实例必然与一个外部类实例关联,这个static定义完全可以移到其外部类中去
  • 成员类不能是接口(interface)。因为成员类必须能被某个外部类实例实例化,而接口是不能实例化的。事实上,如示例代码所示,如果你以成员类的形式定义一个接口,该接口实际上是一个静态成员类,static关键字对inner interface是内含(implicit)的。

<!--[if !supportLists]-->2.3 <!--[endif]-->新增语法

一个成员类实例必然所属于其外部类的一个实例,那么如何在成员类内部获得其所属外部类实例呢?如示例代码所示,采用“OuterClass.this”的形式。

<!--[if !supportLists]-->2.4 <!--[endif]-->指定内部类实例所属的外部类实例

内部类实例可在其外部类的实例方法中创建,此新创建内部类实例所属的外

部类实例自然就是创建它的外部类实例方法对应的外部类实例。

另外,如示例代码所示,对于给定的一个外部类实例outerClass,可以直接创建其内部类实例,语法形式为:

OuterClass.InnerClass innerClass = outerClass.new InnerClass();


<!--[if !supportLists]-->

2.5 <!--[endif]-->什么时候使用成员类

成员类的显著特性就是成员类能访问它的外部类实例的任意字段与方法。方便一个类对外提供一个公共接口的实现是成员类的典型应用。

JDK Collection类库为例,每种Collection类必须提供一个与其对应的Iterator实现以便客户端能以统一的方式遍历任一Collection实例。每种Collection类的Iterator实现就被定义为该Collection类的成员类。例如JDKAbstractList类的代码片断:

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> public abstract class AbstractList < E > extends AbstractCollection < E > implements List < E > {
private class Itr implements Iterator < E > {
………;
}

public Iterator < E > iterator(){
return new Itr();
}
}


因为定义在AbstractList中的Itr可访问AbstractList中的任意字段和方法,所以很方便实现Iterator,无需AbstractList对外暴露更多的接口。

试想,如果没有成员类机制,只有在AbastractList源码之外定义一个实现Iterator的类Itr,该类有一个AbstractList实例成员list,为了Itr能获取list的内部信息以便实现遍历,AbstractList必然要向Itr开放额外的访问接口。

<!--[if !supportLists]-->3 <!--[endif]-->Local class(局部类)

对一个静态成员类,去掉其声明中的“static”关键字,将其定义移入其外部类

的静态方法或静态初始化代码段中就成为了局部静态成员类。

对一个成员类,将其定义移入其外部类的实例方法或实例初始化代码中就成为了局部成员类。

局部静态成员类与静态成员类的基本特性相同。例如,都只能访问外部类的静态字段或方法,但不能访问外部类的实例字段和实例方法等。

局部成员类与成员类的基本特性相同。例如,局部成员类实例必属于其外部类的一个实例,可通过OuterClass.this引用其外部类实例等。

另外,局部类也有其自己的特性,如以下代码所示:


<!--[if !supportLists]-->3.1 <!--[endif]-->局部类特性

如示例代码所示,局部类能且只能访问其所属代码段中的声明为final的局部

变量。为什么只能访问声明为final的局部变量呢?我们知道,局部变量在其所属的代码段(譬如某个函数)执行完毕后就会被回收,而一个局部类的实例却可以在其类定义所属代码段执行完毕后依然存在,如果它可操控非final的局部变量,用户就可以通过该实例修改已不存在的局部变量,无意义。

<!--[if !supportLists]-->3.2 <!--[endif]-->局部类约束

  • 如示例代码所示,内部类只在定义它的代码段中可见,不能在它所属代码段之外的代码中使用;因此也就没有public/private/default权限修饰符(无意义)
  • 不能以局部类形式定义一个接口。局部类只在其所属代码段中可见,定义这样的接口无意义
  • 局部类类名不能与其外部类类名重复

<!--[if !supportLists]-->3.3 <!--[endif]-->什么时候使用局部类

局部类大部分以匿名类的形式使用。

<!--[if !supportLists]-->4 <!--[endif]-->Anonymous class(匿名类)

没有类名的局部类就是匿名类。用一条语句完成匿名类的定义与实例创建。例

如如下代码:

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> public class Outer{
public void instanceMethod(){
// defineanonymousclasswhichimplementsActioninterfaceandcreataninstanceofit
Actionaction = new Action(){
public void doAction(){
System.out.println(
" asimpleanonymousclassdemo " );
}};
action.doAction();

// defineanonoymousclasswhichextendsBaseClassandcreateaninstanceofit
new BaseClass( 5 ){
public void printData(){
System.out.println(
" data= " + getData());
}
}.printData();
// "data=5"willbeoutputed
}
}

interface Action{
void doAction();
}

class BaseClass{
private int data;

public BaseClass( int data){
this .data = data;
}

public int getData(){
return data;
}
}

<!--[if !supportLists]-->4.1 <!--[endif]-->匿名类特性与约束

匿名类是一种特殊的局部类。局部类的特性与约束都适用与它。

<!--[if !supportLists]-->4.2 <!--[endif]-->新增语法

<!--[if !supportLists]-->4.2.1 <!--[endif]-->继承自某个基类的匿名类

new class-name ( [ argument-list ] ) { class-body }

创建匿名类实例时,“argument-list将被传入其基类(即class-name)对应的构造函数。

<!--[if !supportLists]-->4.2.2 <!--[endif]-->实现某个接口的匿名类

new interface-name () { class-body }


<!--[if !supportLists]-->

4.3 <!--[endif]-->什么时候使用匿名类

  • 该类定义代码段很短
  • 只需要创建该类的一个实例
  • 类的定义代码与类的使用代码紧邻
  • 使用匿名不影响代码的易读性

譬如,如下实现类似与ccallback功能的代码就是匿名类的典型应用:

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> Filef = new File( " /src " ); // Thedirectorytolist

// Nowcallthelist()methodwithasingleFilenameFilterargument
// DefineandinstantiateananonymousimplementationofFilenameFilter
// aspartofthemethodinvocationexpression.
String[]filelist = f.list( new FilenameFilter(){
public boolean accept(Filef,Strings){ return s.endsWith( " .java " );}
});
// Don'tforgettheparenthesisandsemicolonthatendthemethodcall!

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> public class Outer{
private int instanceField;
private static int staticField;

// definealocalmemberclassininstancecodeblock
{
int localVirable1 = 0 ;
final int localVirable2 = 1 ;
class Inner1{
public Inner1(){
// canaccessitsouterclass'fieldandmethoddirectly
instanceField = 1 ;
// useOuterClass.thistogetitscorrespondingouterclassinstance
Outer. this .instanceField = 1 ;

// cannotaccessthenotfinallocalvirableinitscontainingcodeblock
// System.out.print(localVirable1);

// canaccessthefinallocalvirableinitscontainingcodeblock
System.out.print(localVirable2);
}
}

// localclasscannothaveprivilegemodifier
/* publicclassinner2{
}
*/
}

// definealocalstaticmemberclassinstaticcodeblock
static {
class Inner2{
public Inner2(){
staticField
= 1 ;
// cannotaccessinstancefieldandmethodinalocalstaticmemberclass
// intanceField=2;
}
}
}

public void intanceMethod(){
// definealocalclassinitsoutclass'instancemethod
class Inner3{
}

// localclassisvisibleonlyinitscontainningcodeblock
// Outer.Inner2inner2;
}

private static void staticMethod(){
// definealocalstaticmemberclassinitsoutclass'staticmethod
class Inner4{
public Inner4(){
staticField
= 2 ;
}
}

// cannotdefineainterfaceasalocalclass
/* interfaceI{
}
*/
}
}

你可能感兴趣的:(java,jdk,F#)