Java嵌套类(Nested Classes)总结

Nested Classes定义

在java语言规范里面,嵌套类(Nested Classes)定义是:

A nested class is any class whose declaration occurs within the body of another class or interface. A top level class is a class that is not a nested class. 

说的简单一点,就是定义在类里面的类。一般把定义内部类的外围类成为包装类(enclosing class)或者外部类

 

嵌套类分类

根据nested class定义的地方,可以分为member nested class,local nested class , anonymous nested class

member nested class(成员嵌套类) :成员嵌套类 作为 enclosing class 的成员定义的,成员嵌套类有enclosing class属性

local nested class (局部嵌套类): 局部嵌套类定义在 enclosing class 的方法里面,局部嵌套类有enclosing class 属性和enclosing method 属性

anonymous nested class(匿名嵌套类):匿名嵌套类没有显示的定义一个类,直接通过new 的方法创建类的实例。一般回调模式情况下使用的比较多

 

member nested class 可以使用public,private,protected访问控制符,也可以用static,final关键字

local nested class 可以使用final关键字

anonymous nested class 不使用任何关键字和访问控制符

见下面的代码

public class EnclosingClass
{

 

    public static final class NestedMemberClass
{

 

    }

 

    public void nestedLocalClass()
{

 

        final class NestedLocalClass
{

 

        }

    }

 

    public void nestedAnonymousClass()
{

 

        new Runnable()
{

 

            @Override

            public void run()
{

            }

        };

    }

}

 如果你想学习java可以来这个群,首先是二二零,中间是一四二,最后是九零六,里面有大量的学习资料可以下载

在大多数情况下,一般把nested classes 分为两种:

Static Nested Classes(静态嵌套类): 就是用static修饰的成员嵌套类

InnerClass:静态嵌套类之外所有的嵌套类的总称,也就是没有用static定义的nested classes,Inner Classes 不能定义为static,不能有static方法和static初始化语句块。在JLS(java语言规范)里面是这么定义的:

An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member inter- faces 

 

其中Inner Class又可以分为三种:

1 inner member classes :没有用static 修饰的成员内部类

2 local inner classes : 定义在方法里面的内部类,方法可以是static的也可以是非static的,也可以是构造器方法。

3 anonymous inner classes :定义在方法里面匿名类,方法可以是static的也可以是非static的

嵌套类访问规则

Static Nested Classes 以及 inner classes 有一些限制规则,下面介绍一下这些规则。

  • Static Nested Classes访问规则

用Static修饰的Nested Classes,只能访问外部类的非static变量。对于public 的 static Nested Classes 可以用 new 外部类.内部类()的方式直接创建。而默认的static Nested Classes 可以在同一包名下,用 new 外部类.内部类()的方式创建。其实和外部类的方式差不多。静态成员类可以使用访问控制符,可以使用static修饰,可以是abstract抽象类

 

public class StaticNestedClass
{

 

    //
私有局部

    private int i
=
0;

 

    //
静态

    public static int j
=
0;

 

    //
不变值

    private final int k
=
0;

 

    //
static final

    private static final int m
=
0;

 

    //
静态嵌套内,这里不是innerclass,可以直接new出来

    public static class PublicNestedClass
{

 

        private void test1()
{

            //
System.out.println(i); 非innerClass不能访问enclosing类的非static属性

            System.out.println(j);

            System.out.println(m);

            //
System.out.println(k); 非innerClass不能访问enclosing类的非static属性

        }

 

        //
可以定义static方法

        private static void test2()
{

 

        }

    }

 

    //
静态嵌套内,这里不是innerclass,由于是私有的,不可以直接new出来

    private static class PrivateNestedClass
{

 

    }

}

  

下面的例子演示了static Nested class的创建

public class TestClass
{

 

    public static void main(String[]
args) {

         

        //任何地方都可以创建

        StaticNestedClass.PublicNestedClass
publicNestedClass =
new StaticNestedClass.PublicNestedClass();

         

        //可以在同一package下创建

        StaticNestedClass.DefaultNestedClass
defaultNestedClass =
new StaticNestedClass.DefaultNestedClass();

        //编译错误,无法访问内部内

        //StaticNestedClass.PrivateNestedClass
privateNestedClass = new StaticNestedClass.PrivateNestedClass();

    }

}

  

  • Inner Class访问规则

inner member classes(内部成员类) 可以访问外部类的所有实例属性,静态属性。因为内部成员类持有一个外部对象的引用,内部类的实例可以对外部类的实例属性进行修改。如果是public的 inner  member classes,可以通过 外部类实例.new 内部类()的方式进行创建,当调用内部类的构造器的时候,会把当前创建的内部类对象实例中持有的外部对象引用赋值为当前创建内部类的外部类实例。内部成员类可以是使用访问控制符,可以定义为final,也可以是抽象类。

 

  

public class MemberInnerClass
{

 

    //
私有局部

    public int i
=
0;

 

    //
静态

    private static int j
=
0;

 

    //
不变值

    private final int k
=
0;

 

    //
static final

    private static final int m
=
0;

 

    public class PublicMemberInnerClass
{

        //
enclosing Class的属性都可以访问

        public void test()
{

            System.out.println(i);

            System.out.println(j);

            System.out.println(m);

            System.out.println(k);

        }

 

        public MemberInnerClass
getOutterClass() {

            return MemberInnerClass.this;

        }

        //
这里会报错,不允许定义static方法

        //
private static final void test();

    }

 

    //
私有的innerclass 外部不能访问

    private class PrivateMemberInnerClass
{

    }

 

    //
公开局部类,外部可以访问和创建,但是只能通过OutterClass实例创建

 

    class DefaultMemberInnerClass
{

        public MemberInnerClass
getOutterClass() {

            return MemberInnerClass.this;

        }

    }

 

}

  

下面例子演示了内部成员类的创建

public class TestClass
{

 

    public static void main(String[]
args) {

 

        //
任何地方都可以创建

        MemberInnerClass
t =
new MemberInnerClass();

 

        //
可以创建,pmic里面保存对t的引用

        MemberInnerClass.PublicMemberInnerClass
pmic = t.
new PublicMemberInnerClass();

 

        //
可以在同一package下创建,dmic保存对t的引用

        MemberInnerClass.DefaultMemberInnerClass
dmic = t.
new DefaultMemberInnerClass();

 

        //
编译错误,无法访问内部内

        //
MemberInnerClass.PrivateMemberInnerClass pmic = t.new

        //
PrivateMemberInnerClass();

 

        //
下面验证一下outterClass是同一个对象

        System.out.println(pmic.getOutterClass()
== t);

        System.out.println(dmic.getOutterClass()
== t);

 

    }

}

 运行程序,打印结果:

true

true

  

2 local inner classes(局部类)

局部类 定义在类方法里面。这个方法既可以是静态方法,也可以是实例方法,也可以是构造器方法或者静态初始化语句块。

局部类可以定义在一个static上下文里面 和 非static上下文里面。局部类不能有访问控制符(private,public,protected修饰),可以是抽象的,也可以定义为final

定义在static上下文(static 字段初始化,static初始化块,static方法)里面的local inner classes 可以访问类的静态属性,如果定义在静态方法里面的局部类,还可以方法里面定义的final变量。在static上下文定义的局部类,没有指向父类实例变量的引用,因为static方法不属于类的实例,属于类本身。而且局部类不能在外部进行创建,只能在方法调用的时候进行创建

 

public class LocalInnerClass
{

 

    //
私有局部

    private int i
=
0;

 

    //
静态

    public static int j
=
0;

 

    //
不变值

    private final int k
=
0;

 

    //
static final

    private static final int m
=
0;

 

    public static void test()
{

        final int a
=
0;

        int b
=
0;

        //
local inner class不能够有访问控制符 比如public private

        abstract class LocalStaticInnerClass
{

            //
local inner class不能定义静态属性

            //
private static int c;

            private int d
=
0;

            public LocalStaticInnerClass()
{

                //
可以访问方法里面定义的final 变量

                System.out.println(a);

                //
不能访问b 因为b不是final

                //
System.out.println(b);      

                //
定义在static上下文里面的local inner class 不能访问外部类的非static字段

                //
System.out.println(i);

                //
System.out.println(k);

                System.out.println(j);

                System.out.println(m);

            }

            //
local inner class不能定义静态方法

            //
public static void test(){}

        }

    }

 

    public void test2()
{

        final int a
=
0;

        int b
=
0;

        final class LocalNonStaticInnerClass{  

            public LocalNonStaticInnerClass()
{

                //定义在非static上下文的local
inner class 可以访问外部类的所有属性

                System.out.println(i);

                System.out.println(k);

                System.out.println(j);

                System.out.println(m);

            }

        }

    }

 

}

 

 3 anonymous inner classes (匿名类)也是定义在方法里面,匿名类和局部类访问规则一样,只不过内部类显式的定义了一个类,然后通过new的方式创建这个局部类实例,而匿名类直接new一个类实例,没有定义这个类。匿名类最常见的方式就是回调模式的使用,通过默认实现一个接口创建一个匿名类然后,然后new这个匿名类的实例。

public class AnonymousInnerClass
{

    //访问规则和局部类一样

    public void test()
{

         

        //匿名类实现

        new Thread(new Runnable()
{

 

            @Override

            public void run()
{

 

            }

        }).start();

         

        //非匿名类实现

        class NoneAnonymousClassimplements Runnable{

            public void run()
{

 

            }

        }  

        NoneAnonymousClass
t =
new NoneAnonymousClass();

        new Thread(t).start();

    }

}

嵌套类的层次

嵌套类是可以有层次的,也就是说嵌套类里面还是定义类,成为嵌套类中的嵌套类。虚拟机如何保证嵌套类正确的嵌套层层次?

对于merber class,内部嵌套类的可以表示为 A$B 其中A为外部类,B为内部成员类 ,如果B里面又有成员为C的嵌套类,那么C就可以表示为A$B$C,如果A定义了两个同名member class,那么编译器就会报错。如果B里面又包含了为名B的nested class,则编译器会报错.

对于local inner Class,局部类可以表示为A$1B的方式,其中A为外部类,B为第一个局部类 如果在不同的方法里面定义了同名的局部类B,编译器是可以编译通过的,那么定义的第二个局部类B可以表示为A$2B,如果在同一个方法里面同定义两个相同的局部类B,那么编译错是要报错的。如果B里面又定义了同名的成员类,则可以表示为A$1B$B。

对于anonymous inner classes,匿名类可以表示为A$1的方式,代表程序里面有一个匿名类。如果有N个,可以表示为A$N的方式(N为自然数).

看看下面的例子

public class NestedClassLevel
{

 

    class A
{

        //
编译器会报错,A里面不能在定义名为A的nested classes

        //
class A{}

        public void test()
{

            class B
{

            }

        }

    }

 

    //可以在继续定义B

    class B
{

        public void test(){

            //可以无限定义匿名类

            new Runnable()
{

                public void run()
{

                    //可以无限定义匿名类

                    new Runnable()
{           

                        public void run()
{        

                        }

                    };

                }

            };

        }

    }

 

    //
只能定义一个B

    //
class B{}

 

    public void test()
{

        //
可以定义A

        class A
{

            public void test()
{

                //可以有同名的局部类B和成员类B

                class B
{

                    public void test()
{

                         

                    }

                }

                //局部类A里面不能在定义A

                //class
A{}

            }

        }

        //可以有同名的局部类B和成员类B

        class B
{

 

        }

    }

 

}

 

对于定义在非static上下文里面的nested类层次,比如A$B$1C ,则最内层的嵌套类C有一个指向B实例的引用,B有一个指向A实例的引用,最终最内层的嵌套类可以访问A中的属性可以方法,一般把B成为A的直接嵌套类。但是A不可以访问B或者C中属性或者方法。

nested interface

由于interface默认是定义为一个 public static的特殊类,所以interface可以直接作为 static member class。可以通过A.B的方式进行访问。

 

nested class的应用

在java提供的基本类库里面,大量使用nested classes。比如我们知道的map类。其中 Map类里面有一个定义了Entry类abstract inner class。所以我们在遍历map的时候,一般使用

for (Map.Entry entry:map.entrySet()){

}

 

总结:nested类是java里面比较复杂的一个概念,必须详细了解jvm中对于嵌套类的实现以及java编译器对嵌套类的处理才可以深入了解嵌套类细节。

时间: 2024-09-14 06:43:16

Java嵌套类(Nested Classes)总结的相关文章

java嵌套类和内部类详解

可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner).嵌套类 从JDK1.1开始引入.其中inner类又可分为三种: 其一.在一个类(外部类)中直接定义的内部类: 其二.在一个方法(外部类的方法)中定义的内部类: 其三.匿名内部类. java嵌套类(Nested Classes)总结 http://www.cnblogs.com/aigongsi/a

深入理解Java嵌套类和内部类

一.什么是嵌套类及内部类? 可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它 有两种类型: 静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套 类,也即是被称作为内部类(inner).嵌套类从JDK1.1开始引入.其中inner类又 可分为三种: 其一.在一个类(外部类)中直接定义的内部类; 其二.在一个方法(外部类的方法)中定义的内部类; 其三.匿名内部类. 下面,我将说明这几种嵌套类的使用及注意事项. 二.静态嵌套类 如下所示代码为定义一个

对Java嵌套类的讨论

摘要:与字段和方法类似,Java允许类是其它类的成员.在这里,我们将嵌套类分为4种--嵌套顶级类(nested top-level classes),成员内部类(instance inner classes),本地内部类(local inner classes)和匿名内部类(anonymous inner classes). 在教授Java时,我经常发现学生尝试在方法中声明其它的方法.不过,与Pascal语言不同--Pascal允许嵌套声明过程procedures(与方法类似),而Java是不允

Java嵌套类和内部类详解_java

一.什么是嵌套类及内部类?     可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型: 静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为 内部类(inner).嵌套类从JDK1.1开始引入.其中inner类又可分为三种:     其一.在一个类(外部类)中直接定义的内部类:     其二.在一个方法(外部类的方法)中定义的内部类;     其三.匿名内部类. 下面,我将说明这几种嵌套类的使用及注意事项. 二.静态嵌

Java嵌套类的作用、用法和调用机制是怎么样的?

问题描述 请问Java语言中有关嵌套类的作用.用法和调用机制是怎么样的?最好能给个PPT之类的资料参考下,先谢谢了.....邮箱:hongxingcslg@vip.qq.com 解决方案 解决方案二:嵌套类????你指的是匿名内部类或者是内部类吧?这些资料都可以上网上找的,google一下吧.解决方案三:仅供参考解决方案四:其实很简单,这种类仅仅在某个类内部使用,外面不用,写在外面影响美观,所以就写到里面了

浅析Java中的嵌套类和内部类

以前看<Java编程思想>的时候,看到过嵌套类跟内部类的区别,不过后来就把它们的概念给忘了吧.昨天在看<数据结构与算法分析(Java语言版)>的时候,又遇到了这个概念,当时就很大的疑惑:嵌套类跟内部类有什么区别?只有是否有关键字static的区别吗? 所以今天找了个时间查了一下两者的详细区别,总结在这篇博客中,既方便自己的复习和学习,也启示他人吧. 1,概念: 定义在一个类内部的类,叫作"嵌套类".嵌套类分为两种:static的和非static的.后者又有一个专

Java进阶07 嵌套类

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!   到现在为止,我们都是在Java文件中直接定义类.这样的类出现在包(package)的级别上.Java允许类的嵌套定义. 这里将讲解如何在一个类中嵌套定义另一个类.  嵌套 内部类 Java允许我们在类的内部定义一个类.如果这个类是没有static修饰符,那么这样一个嵌套在内部的类称为内部类(inner class). 内部类被认为是外部对象的一个成员.在定义内部类时,我们同样

Java进阶学习(七) 嵌套类

到现在为止,我们都是在Java文件中直接定义类.这样的类出现在包(package)的级别上.Java允许类的嵌套定义. 这里将讲解如何在一个类中嵌套定义另一个类. 嵌套 内部类 Java允许我们在类的内部定义一个类.如果这个类是没有static修饰符,那么这样一个嵌套在内部的类称为内部类(inner class). 内部类被认为是外部对象的一个成员.在定义内部类时,我们同样有访问权限控制(public, private, protected). 在使用内部类时,我们要先创建外部对象.由于内部类是

java当中类里面嵌套类是内部类,那么方法嵌套方法是内部方法吗

问题描述 java当中类里面嵌套类是内部类,那么方法嵌套方法是内部方法吗 java当中类里面嵌套类是内部类,那么方法嵌套方法是内部方法吗内部类和内部方法有什么特点 解决方案 没有方法嵌套方法这种说法,方法只能相互调用,方法的定义只能在类中.内部类是依附外部类而存在的,通常是为了隐藏类的某些信息,没有听说过内部方法这个概念啊. 解决方案二: Java类的嵌套:外部类的方法不能访问内部类的变量Java 中的方法内部类[Java]内部类及其调用方法 解决方案三: 没有方法嵌套方法这种说法,方法只能相互