`
longgangbai
  • 浏览: 7331051 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】Java内部类

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

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

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


public class  Outer{
    //just like static method, static member class has public/private/default access privilege levels
    
    //access privilege level: public 
    public static class Inner1 {
        public Inner1() {
            //Static member inner class can access static method of outer class
            staticMethod();    
            //Compile error: static member inner class can not access instance method of outer class
            //instanceMethod();  
        }
    }
    
    //access privilege level: default 
    static class Inner2 {
        
    }
    
    //access privilege level: private 
    private static class Inner3 {
        //define a nested inner class in another inner class 
        public static class Inner4 {    
        }
    }

    private static void staticMethod() {
        //cannot define an inner class in a method
        /*public static class Inner4() {
        }*/
    }
    
    private void instanceMethod() {
        //private static member class can be accessed only in its outer class definition scope
        Inner3 inner3 = new Inner3();
        //how to use nested inner class
        Inner3.Inner4 inner4 = new Inner3.Inner4();
    }
}

class Test {
    Outer.Inner1 inner1 = new Outer.Inner1();
    //Test and Outer are in the same package, so Inner2 can be accessed here
    Outer.Inner2 inner2 = new Outer.Inner2(); 
    //Compile error: Inner3 cannot be accessed here
    //Outer.Inner3 inner3 = new Outer.Inner3(); 
}

 

1.1      静态成员类特性

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

1.2      静态成员类约束

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

1.3      新增语法

    如示例代码所示,可以以“OuterClass.InnerClass”的方式来引用某个内部类。
1.4      什么时候使用静态成员类

B为A的辅助类,且只为A所用时,可将B定义为A的静态成员类。例如JDK中的LinkedList类就有Entry静态成员类:
public class LinkedList<E> extends AbstractSequentialList<E> 
   …;
   private static class Entry<E> {
    E element;
    Entry<E> next;
    Entry<E> previous;

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

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

 
2          Member class(成员类)

一个静态成员类,若去掉“static”关键字,就成为成员类。如下示例代码,Inner1/Inner2/Inner3/Inner4就是Outer的四个成员类
 
public class Outer {
    //just like instance method, member class has public/private/default access privilege levels
    private int data;
    
    //access privilege level: public 
    public class Inner1 {
        private int data;
        private int data1;
        public Inner1() {
            //member class can access its outer class' instance field directly
            data1 = 1;
            //itself data field
            data = 1;
            //its outer class instance field
            Outer.this.data = 1;
        }
    }
    
    //access privilege level: default
    class Inner2 {
        //can not define static filed, method, class in member class
        //static int j = 1;
        
        //but, "static final" compound is allowed 
        static final int CONSTANT = 1;
    }
    
    //access privilege level: private 
    private class Inner3 {
        public class Inner4 {
            
        }
    }
    
    //in fact, Inner5 is not a member class but a static member class
    interface Inner5 {
    }
    
    private static void staticMethod() {
        //can not create a member class instance directly in outer class' static method
        //Inner1 inner1 = new Inner1();
    }
    
    private void instanceMethod() {
        //can create a member class instance in outer class' instance method
        Inner1 inner1 = new Inner1();
    }
}

class Test {
    public Test() {
        //cannot create member class instance directly in class other than outer class
        //Outer.Inner2 inner2 = new Outer.Inner2();
        
        //create a member class instance outside it's outer class
        Outer outer = new Outer();
        Outer.Inner1 inner1 = outer.new Inner1();
    }
}

 

 
2.1      成员类特性

·        类似于外部类的实例函数,成员类有public/private/default权限修饰符

·        一个成员类实例必然所属一个外部类实例,成员类可访问外部类的任一个实例字段和实例函数。
2.2      成员类约束

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

2.3      新增语法

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

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

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

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

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


2.5      什么时候使用成员类

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

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

 
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开放额外的访问接口。
3          Local class(局部类)

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

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

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

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

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

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

 

 
3.1      局部类特性

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

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

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

3.3      什么时候使用局部类

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

           
4          Anonymous class(匿名类)

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

如如下代码:
public class Outer {
    public void instanceMethod() {
        //define a nonymous class which implements Action interface and creat an instance of it
        Action action = new Action() {
            public void doAction() {
                System.out.println("a simple anonymous class demo");
            }};
        action.doAction();
        
        //define a nonoymous class which extends BaseClass and create an instance of it
        new BaseClass(5) {
            public void printData(){
                System.out.println("data = " + getData());
            }
        }.printData(); //"data = 5" will be outputed
    }
}

interface Action {
    void doAction();
}

class BaseClass {
    private int data;
    
    public BaseClass (int data) {
        this.data = data;
    }
    
    public int getData() {
        return data;
    }
}

 
4.1      匿名类特性与约束

匿名类是一种特殊的局部类。局部类的特性与约束都适用与它。
4.2      新增语法
4.2.1      继承自某个基类的匿名类

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

 

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

new interface-name () { class-body }



4.3      什么时候使用匿名类

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

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

 
File f = new File("/src");      // The directory to list

// Now call the list() method with a single FilenameFilter argument
// Define and instantiate an anonymous implementation of FilenameFilter
// as part of the method invocation expression. 
String[] filelist = f.list(new FilenameFilter() {
  public boolean accept(File f, String s) { return s.endsWith(".java"); }
}); // Don't forget the parenthesis and semicolon that end the method call!

public class Outer {
    private int instanceField; 
    private static int staticField; 
    
    //define a local member class in instance code block
    {
        int localVirable1 = 0;
        final int localVirable2 = 1;
        class Inner1 {
            public Inner1() {
                //can access its outer class' field and method directly
                instanceField = 1;
                //use OuterClass.this to get its corresponding outer class instance
                Outer.this.instanceField = 1;
                
                //can not access the not final local virable in its containing code block
                //System.out.print(localVirable1);
                
                //can access the final local virable in its containing code block
                System.out.print(localVirable2);
            }
        }        
        
        //local class can not have privilege modifier 
        /*public class inner2 {            
        }*/
    }
    
    // define a local static member class in static code block
    static {
        class Inner2 {
            public Inner2() {
                staticField = 1;
                //can not access instance field and method in a local static member class 
                //intanceField = 2;
            }
        }
    }
    
    public void intanceMethod() {
        //define a local class in its out class' instance method
        class Inner3 {
        }
        
        //local class is visible only in its containning code block
        //Outer.Inner2 inner2;
    }
    
    private static void staticMethod() {
        //define a local static member class in its out class' static method
        class Inner4 {    
            public Inner4() {
                staticField = 2;
            }
        }
        
        //can not define a interface as a local class
        /*interface I {
        }*/
    }
}

 

分享到:
评论

相关推荐

    java基础第七章内部类与异常类.doc

    Java 基础第七章内部类与异常类 Java 语言支持在一个类中定义另一个类,这样的类称做内部类。内部类和外嵌类之间存在着紧密的关系:内部类可以访问外嵌类的成员变量和方法,而外嵌类也可以使用内部类声明的对象作为...

    java 匿名内部类的使用规范

    Java匿名内部类是Java语言中一个独特且强大的特性,它允许我们在不需要定义一个单独的类的情况下创建类的实例。这在处理回调、事件监听、单例模式以及其他需要短时间内定义一个简单类的情况时非常有用。本篇文章将...

    把wsdl文件转换成java类 使用wsdl2Java工具

    为了在Java环境中与这些Web服务交互,我们需要将WSDL文件转换为Java类,这就是`wsdl2java`工具的作用。 `wsdl2java`是Apache Axis项目的一部分,它是一个强大的工具,可以自动生成Java客户端和服务端代码,这些代码...

    java和kotlin的内部类静态嵌套类

    Java内部类是一种定义在另一个类内部的类,它可以访问外部类的所有成员,包括私有成员。内部类分为四种类型:成员内部类、局部内部类、匿名内部类和静态嵌套类。其中,静态嵌套类是与外部类关联但不持有对外部类的...

    java中的匿名内部类总结

    Java 中的匿名内部类总结 Java 中的匿名内部类是一种特殊的内部类,它没有名字,因此也称为匿名类。匿名内部类是一种简洁的编程方式,能够简化代码编写,但它也有一些限制和特点。 匿名内部类的定义 匿名内部类是...

    JAVA内部类

    ### JAVA内部类详解 #### 引言 自Java1.1版本起,内部类的引入为面向对象编程提供了更为灵活的封装机制。然而,如同所有强大的特性,内部类的不当使用可能导致代码复杂度的增加,甚至产生维护上的困难。本文旨在...

    驼峰转下划线、下划线转驼峰的java工具类

    简单易用:这两个方法都是静态方法,可以直接在类内部或外部任何地方调用,无需创建实例。 正则表达式高效:利用Java的正则表达式快速完成匹配和替换,性能较好。 适应性强:能够处理大多数常见的驼峰和下划线...

    VB.NET转JAVA工具

    VB.NET转JAVA工具的出现,主要是为了帮助开发者将已有的VB.NET项目迁移到Java环境中,或者便于那些熟悉VB.NET语法但需要在Java平台上工作的开发者。这个工具包含说明文档和源代码,意味着用户不仅可以直接使用转换...

    CLASS转JAVA

    某些高级优化、匿名内部类、lambda表达式以及编译器生成的额外代码可能导致反编译结果与原始源代码有所差异。此外,注释和变量命名通常无法恢复。 5. **使用场景**: - **学习和调试**:当没有源代码可用时,反...

    Java精华版 chm Java API、嵌套类和内部类、与时间有关的类Date,DateFormat,Calendar、文件与流、Java变量类型间的相互转换、Java与Web、用连接池提高Servlet访问数据库的效率、Java扩展、应用服务器的集群策略及Java EE 5.0、Java IO 包中的Decorator模式等

    本Java精华内容深入Java API、嵌套类和内部类、与时间有关的类Date,DateFormat,Calendar、文件与流、Java变量类型间的相互转换、Java与Web、用连接池提高Servlet访问数据库的效率、Java扩展、应用服务器的集群策略及...

    华为java内部培训讲义

    ### 华为Java内部培训讲义知识点概览 #### 一、Java环境配置 - **JAVA_HOME**: 配置JDK的安装目录。这一步非常重要,因为其他环境变量的设置通常依赖于JAVA_HOME的值。 - **CLASSPATH**: 指定Java运行时查找类路径...

    java 旋转中的风扇

    Java 内部类是 Java language 中的一种机制,用于定义一个类inside另一个类。Java 内部类可以用于实现某些功能,例如事件处理、数据封装等。 在本实验中,我们使用 Java 内部类来实现某些功能,例如 MySlider 类和 ...

    java学习资料抽象类,接口,内部类

    在这个Java学习资料中,我们重点探讨抽象类、接口和内部类。 首先,抽象类是一种不能实例化的类,它主要用于被其他类继承。在Java中,使用`abstract`关键字来定义一个抽象类。抽象类可以包含抽象方法(无方法体的...

    反射私有内部类的例子

    ### 反射私有内部类的例子 #### 一、引言 在Java编程语言中,反射(Reflection)是一项强大的功能,允许程序在运行时检查和修改自身结构与行为。通过反射,可以动态地获取类的信息并操作其字段、方法以及构造器等。...

    java基础第七章-内部类与异常类.doc

    Java 基础第七章 -内部类与异常类 本章节主要讲解 Java 的内部类和异常类的概念、特点、使用方法和注意事项。 内部类 ------ 内部类是 Java 支持的一种特殊类,定义在另一个类的内部。内部类和外嵌类之间存在关系...

    java(Day12)---内部类

    Java中的内部类是一种特殊的类,它可以被定义在一个外部类的内部。这种设计允许内部类访问外部类的所有成员,包括私有成员,增强了代码的封装性和灵活性。内部类主要有四种类型:成员内部类、静态内部类、局部内部类...

    内部类知识总结3--匿名内部类

    内部类是Java编程语言中一个独特且强大的特性,它允许我们在一个类的内部定义另一个类。内部类可以是静态的,也可以是非静态的,而匿名内部类则是一种没有名字的内部类,通常用于快速实现简单的回调或者接口实现。这...

    内部类的使用

    内部类在Java编程中是一种强大的特性,它允许我们在一个类的内部定义另一个类。这种设计模式使得代码更加紧凑,能够更好地封装和隐藏实现细节。本文将深入探讨内部类的使用,包括其分类、特点以及如何与外部类进行...

    Java工具类之Apache的Commons Lang和BeanUtils

    Java工具类是开发过程中不可或缺的一部分,它们提供了许多实用的功能,帮助开发者提高代码的效率和可维护性。Apache Commons Lang和BeanUtils是两个非常著名的Java工具库,由Apache软件基金会开发和维护。这两个库...

    JAVA类的特性资料

    11. **内部类**:Java支持类的嵌套,内部类可以作为外部类的成员,有成员内部类、局部内部类、匿名内部类和静态内部类等。内部类可以访问外部类的私有成员,增加了代码的复杂性和灵活性。 12. **包(package)**:...

Global site tag (gtag.js) - Google Analytics