各种内部类的使用

 分类

一、成员内部类

当某个类除了他的外部类,不会被其他类使用时,使用成员内部类。这种情况下,内部类依附于外部类而存在,原因可能有: 1. 不可能有其他类使用该内部类。 2. 该内部类不能被其他类使用,可能会导致错误。这是内部类使用比较多的一个场景。

1) 外部类可以直接访问内部类的成员和方法,但是必须先创建一个内部类的对象,再通过该对象使用其成员和方法。

2) 内部类可以访问外部类的成员和方法,但是要注意,当内部类拥有和外部类相同的成员或方法时,会发生隐藏现象,默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式访问:外部类.this.成员变量/方法

3) 内部类只是一个编译时的概念,一旦编译成功,就会成为完全不同的两个类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类,编译完后会生成Outer.class和Outer$Inner.class两个类

4) 成员内部类与普通的成员没什么区别,可以与普通成员一样进行修饰和限制

 1 public class Outer {
 2     private int num = 1;
 3     private int num1 = 10;
 4 
 5     public class Inner {
 6         private int num = 2;
 7         public void func () {
 8             System.out.println(Outer.this.num);
 9             System.out.println(num1);
10         }
11     }
12 
13     public static void main(String[] args) {
14         Outer outer = new Outer();
15         Inner inner = outer.new Inner();
16         inner.func();
17     }
18 }

 

二、局部内部类

 局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。局部内部类就像方法里面的局部变量一样,是不能有public、protected、private及static修饰符的。

public class Outer {
    private int num = 1;
    private int num1 = 10;

    public void func () {
        class Inner {
            private int num = 2;
        }
        Inner inner = new Inner();
        System.out.println(inner.num);
    }


    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.func();
    }
}

 

三、静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,它不持有指向外部类对象的引用this,并且它不能使用外部类的非static成员或方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体对象。它唯一的作用就是随着类的加载(而不是随着对象的产生)而产生。 

public class Outer {

    static class Inner {
        public Inner () {

        }
    }

    public static void main(String[] args) {
        Outer.Inner innner = new Outer.Inner();
    }
}

 

四、匿名内部类

匿名内部类应该是平时我们编写代码时用的最多的,在编写事件监听的代码时匿名内部类不但方便,而且使代码更加容易维护。匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outer$1.class。一般来说,匿名内部类用于集成其他类或者实现接口,并不需要增加额外的方法,只是对集成方法的实现或是重写。

public class Outer {

    public void func () {
        System.out.println("1");
    }


    public static void main(String[] args) {
        Outer inner = new Outer() {
            public void func () {
                System.out.println("2");
            }
        };
        inner.func();
    }
}


总结:

1. 每个内部类都能独立的集成一个接口的实现,所以无论外部类是否已经集成了某个(接口)实现,对于内部类都没有影响。内部类使得多重集成的解决方案变得完整。

2. 方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。

3. 方便编写时间驱动程序。

4. 方便编写线程代码。

 

为什么要有内部类和静态内部类

首先,我们需要明白,为什么要设计Java内部类?然后再去探究为何又将内部类设计为静态与非静态两种。

将一个类设计成内部类,我觉得有两方面因素:

  1. 在一个类内部,需要操作某种属性,而这个属性需要涉及的面又很广,我们可以考虑,将这些属性设计为内部类。
  2. 好比你设计类 B 的目的只是为了给类 A 使用,那么,我们就可将其设定为内部类,没有必要将类 B 设置成单独的 Java 文件,防止与其他类产生依赖关系。

然后我们再来说说为什么又将内部类设计为静态内部类与内部类:

  1. 首先来看一下静态内部类的特点:我是静态内部类,只不过是想借你的外壳用一下。本身来说,我和你没有什么“强依赖”上的关系。没有你,我也可以创建实例。那么,在设计内部类的时候我们就可以做出权衡:如果我内部类与你外部类关系不紧密,耦合程度不高,不需要访问外部类的所有属性或方法,那么我就设计成静态内部类。而且,由于静态内部类与外部类并不会保存相互之间的引用,因此在一定程度上,还会节省那么一点内存资源,何乐而不为呢~~
  2. 既然上面已经说了什么时候应该用静态内部类,那么如果你的需求不符合静态内部类所提供的一切好处,你就应该考虑使用内部类了。最大的特点就是:你在内部类中需要访问有关外部类的所有属性及方法,我知晓你的一切... ...

总结:首先需要知道为什么会有内部类,什么时候应该使用内部类,我们再去讨论,为什么 Java 的设计者们又将内部类设计为静态与非静态,这样就很清晰了。

posted @ 2021-10-28 21:20  机械公敌  阅读(434)  评论(0编辑  收藏  举报