Java内部类

一、Inner Class
Inner Class 即内部类,也即C++和C#中的Nested Class。但Java 的Inner Class 与 C++和C#最大的不同之处在于,内部类包含一个指向其容器类的引用,可以访问容器类的成员。以下代码演示了这一点:

public class Container {
    String Name;
    class InnerClass
    {
        InnerClass(){};
        public void func()
        {
            System.out.println(Name);
        }
    }
public Container(String name){
       Name=name;
        InnerClass a=new InnerClass();
    }
    public static void main(String [] arg)
    {
        Container a=new Container(“ContainerA");
        InnerClass b=a.new InnerClass();   //注意此处
        InnerClass c=(new Container(“ContainerB")).new InnerClass(); //本质上等价于上一句
              a.func();
              c.func();
    }
}


注意其中独特的new语法,在静态函数要创建一个Inner Class,必须有一个其容器类的实例。如果直接创建InnerClass b=new InnerClass();则会导致编译出错。

而在Container的构造函数中,创建InnerClass时,自动将this作为InnerClass的引用。在Inner Class 中使用容器类的成员,不需指定实例,自动指向创建它的容器类。这是一个很有用的语法特征,编译器替我们省了许多事。

本例的输出是:
ContainerA
ContainerB

还可以看到,Inner Class 可以访问容器类的任何成员,不管是public、private或protected的成员全是透明的。反之则不然,容器类只能访问Inner Class的public成员。

二、Static Inner Class
即在内部类的前面增加了static修饰符(modifier)。注意,仅仅只有内部类能够被声明为static类型,通常我们声明一个普通类的时候不能使用static,否则编译出错。

前面讲过,编译器会自动给内部类加上一个reference,指向产生它的那个外部类的对象,如果不想要或者说不需要这个reference,那么我们就可以把这个内部类声明为static,禁止这个reference的产生。除此之外静态类的使用与普通的静态类是一样的。

public class StaticInnerClassTest {
       public StaticInnerClassTest() {
              super();
       }
       public static void main(String[] args) {
        double d[]=new double[20];
        for(int i=0;i<d.length;i++)d[i]=100*Math.random();
        //FindMinMax test=new FindMinMax();
        FindMinMax.Pair pair=FindMinMax.getMinMax(d);
        System.out.println("最小值是:"+pair.getFirst());
        System.out.println("最大值是:"+pair.getSecond());

       }
}
class FindMinMax{
       static double min=Double.MAX_VALUE;
       static double max=Double.MIN_VALUE;

       public static Pair getMinMax(double d[]){
              for(double value:d){
                     if(min>value) min=value;
                     if(max<value) max=value;
              }
              return new Pair(min,max);
       }

       public static class Pair{
            private double first;
              private double second;
              public Pair(double first,double second){
                     this.first=first;
                     this.second=second;
              }
              public double getFirst(){
                     return this.first;
              }
              public double getSecond(){
                     return this.second;
              }
       }
}


下面是又一例子:

内部类
public class Test {

class A{
public void setA(){

}
}

public static void main(String[] args){
Test t=new Test();

}
}

调用方式:
public class Test2 {

public static void main(String[] args){
Test test=new Test();
Test.A t=test.new A();
t.setA();
}
}

静态内部类
调用静态内部类的非静态方法:
public class Test {

static class A{
public void setA(){

}
}
}

public class Test2 {

public static void main(String[] args){
Test.A a=new Test.A();
a.setA();
}
}

调用静态内部类的静态方法:
public class Test {

static class A{
static public void setA(){

}
}
}

public class Test2 {

public static void main(String[] args){
Test.A.setA();
}
}

new Outer.Inner(); // 可以
new Inner(); // 在Outer类内部可以
new foo.Outer.Inner(); // 在包外做内部类实例化, 或者先导包再像第一个那样写.

三、Anonymous Inner Class
匿名内部类(Anonymous Inner Class),顾名思义,就是没有名字的内部类,这是Java为了方便我们编写程序而设计的一个机制。因为有时候有的内部类只需要创建一个它的对象就可以了,以后再不会用到这个类,这时候使用匿名内部类就比较合适,而且也免去了给它取名字的烦恼。

匿名类的语法,如下所示:
new SuperType(){
    内部类的方法和域;
}

注意,这里的SuperType指超类,它可以是一个接口(interface)或者是一个类(Class),当它是一个接口的时候就不能有构造参数(Construction parameters)了。匿名类的语法相对于Java的其他部分来说稍微复杂一点,我们可以按如下方式理解:

1.SuperType为接口
例子:Interface1() test=new Interface1(){

          要实现的的方法;

          Interface1的域;

          内部类的域以及方法;

}
我们可以如下理解:
先声明了如下一个类,
      class Anonymous1 implements Interface1{
          要实现的的方法;
          Interface1的域;
          内部类的域以及方法;
}
然后,Interface1() test=new Anonymouse1();
这样就比较容易理解了。

2.SuperType为类
例子:Class2 test=new Class2(Construction parameters){

          内部类的域以及方法;

}
我们可以如下理解:
先声明了如下一个类,
      class Anonymous2 extends Class2{

          public Anonymous2(Construction parameters){

    super(Construction parameters);

}
内部类的域以及方法;

}
然后,Class2 test=new Anonymouse2(Construction parameters);

四、Local Inner Class
在方法中定义的内部类称为局部内部类。与局部变量类似,局部内部类不能有访问说明符,因为它不是外围类的一部分,但是它可以访问当前代码块内的常量,和此外围类所有的成员。

局部内部类不需要任何access modifier(private,public,pretected...),否则编译出错,它的作用域一般都被限制在它所在的block中。局部内部类有如下两个优点:
1.它对外面的所有类来说都是隐藏的,即时是它所属的外部类,仅有它所在的方法知道它;
2.它不仅可以访问它所属外部类中的数据,还可以访问局部变量,不过局部变量必须生命为final类型

public class OuterC {
     private String name="hehe";

     public void useLocalInner(){
          final int id=10;
          class LocalInner{
               public void accessMethod(){//只能访问外部方法的final属性
                      System.out.println(id);
               }
               public void accessOuter(){//可以访问外部类的属性和方法
                     System.out.println(name);
              }
          };
          LocalInner localInner = new LocalInner();
          localInner.accessMethod();
          localInner.accessOuter();
    }


}

你可能感兴趣的:(java,C++,c,C#,Access)