内部类

10.2

为什么内部类能访问外部类的方法和字段/属性(包括private成员)?

  • 非静态的才可以

  • 当外部类对象创建了一个内部类对象时,编译器会在构造函数中传1个外部类对象的引用给内部类;

    访问外部类的成员时,就是用那个引用来访问的

10.3 .this 和.new的使用

  • .this

    如果(在内部类方法中)需要生成外部类对象的引用,可以这样OutterClass.this

  • .new

    如果需要告知某些其他对象,去创建其某个(非静态时)内部类的对象,需要在new表达式中提供对其他外部类对象的引用,就是必须使用外部类的对象来创建该内部类对象。

    Outter out = Outter out = new Outter();
      Outter.Inner inner = out.new Inner();

​ 外部类的静态方法要想new内部类对象,也得使用.new

  • 成员内部类可以用访问修饰符修饰,可以把他当成外部类的成员来看。不同包的子类访问父类的protected 成员内部类时,不能new对象是因为,此时是访问一个不相干类(不同包,没继承关系)的protected的构造方法。

10.4内部类与向上转型

当取得了一个指向基类或接口的引用时,甚至可能无法找出它的确切类型:

  • 方法返回的是接口的引用,方法中new的是内部类对象.

private内部类

  • private内部类给类的设计者提供了一种途径,通过这种方式可以完全阻止任何依赖于类型的编码,并且完全隐藏了实现的细节(private 内部类完全不可见),
  • 得到的只是基类或接口的引用,能够方便地隐藏实现细节.
//Contens.java
public interface Contents {
    public int value();
}
//Parcel4.java
public class Parcel4 {
   private class PContents implements Contents{
        private int i = 11;
        @Override
        public int value(){
            return i;
        }
    }

    public PContents contents(){
        return new PContents();
    }
}
//Test.java
public class Test {
    public static void main(String[] args) {
        Parcel4 p = new Parcel4();
        Contents c = p.contents();
        
     //   p.new PContents();会报错
    }
}

不同包的子类可以访问父类的protected成员,包括protected内部类,但是不能直接new protected修饰的内部类

10.5在方法和作用域内的内部类

  1. destination方法中的内部类PDestination ,并不意味着一旦 destination() 方法执行完毕,PDestination 就不可用了。

  2. 类被嵌入在 if 语句的作用域内,这并不是说该类的创建是有条件的,它其实与别的类一起编译过了。然而,在定义 Trackingslip 的作用域之外,它是不可用的,除此之外,它与普通的类一样。

这不是有矛盾吗?

10.6 匿名内部类

  1. 在匿名类中定义字段时,还能够对其执行初始化操作

  2. 访问外部类的对象时,外部类对象需加final修饰(有时省略掉也没问题,即使不加 final, Java 8 的编译器也会为我们自动加上 final)

  3. 在匿名类中不可能有命名(自己的类名)构造器(因为它根本没名字!),但通过实例初始化(就是{}代码块),就能够达到为匿名内部类创建一个构造器的效果,

10.7 嵌套类

10.8 为什么需要内部类

10.9 继承内部类 略掉。

10.10 局部内部类

  1. 局部内部类不能有访问说明符,因为它不是外围类的一部分;但是它可以访问当前代码块内的常量,以及此外围类的所有成员。

  2. 既然局部内部类的名字在方法外是不可见的,那为什么我们仍然使用局部内部类而不是匿名内部类呢?唯一的理由是,我们需要一个已命名的构造器,或者需要重载构造器,而匿名内部类只能用于实例初始化。

所以使用局部内部类而不使用匿名内部类的另一个理由就是,需要不止一个该内部类的对象。

2.局部内部类(用得少了解一下)

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

注意: 局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的。

image-20200521115544435

3.匿名内部类

匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。同样的,匿名内部类也是不能有访问修饰符和 static 修饰符的。

4.静态内部类

静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法:

​ 这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非 static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

静态内部类就像一个静态方法。

三.内部类的使用场景和好处

为什么在 Java 中需要内部类?总结一下主要有以下四点:

  • 1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多重继承的解决方案变得完整。
  • 2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
  • 3.方便编写事件驱动程序。
  • 4.方便编写线程代码。

静态(成员)内部类和成员内部类的区别:

  • 成员内部类不能有静态成员(属性和方法);

匿名内部类只能使用1次,只有1个引用。

外部类可以直接.内部类的私有成员,这是为什么?

内部类不能有静态成员,static修饰的才可以有。

package test;

public class C {

    public void father(){
        new Child().printChild();
    }
    class Child{

        private void printChild(){

        }
    }

}
 0 new # 0 new #2 
 3 dup
 4 aload_0
 5 invokespecial #3 >
 8 invokestatic #4 000>
11 return
static /* synthetic */ int access$000(Outer$static /* synthetic */ int access$000(Outer$Inner self) {
    return self.inProp;
  }

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!