第十章 内部类

可以将一个类的定义放在另一个类的定义内部,这就是内部类。

1、创建内部类

public class test1 {
	class Contents {
		private int i = 1;
		public int value() {
			return i;
		}
	}
}

如果想从外部类的非静态方法之外的任意位置创建某个内部类对象,那么必须具体地指明这个对象的类型:OuterClassName.InnerClassName;

2、链接到外部类

  • 内部类拥有其外部类的所有元素的访问权;
  • 内部类如何做到拥有对外部类所有元素的访问权:当某个外围类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用;

3、使用.this和.new

  • 如果要生成对外部对象的引用,可以使用外部类的明智后面紧跟圆点和this;
  • 有时需要告知某些其他对象去创建某个内部类对象:. new;
  • 想要直接创建内部类的对象,必须使用外部类的对象来创建内部类对象;
  • 如果创建的是嵌套类(内部静态类),那么它就不需要对外部类对象的引用;

4、方法或者作用域内的内部类

在方法中的内部类,称为局部内部类;

package innerclasses;

public class Parcel5 {
    public Destination destination(String s) {
        // 在方法中的内部类,局部内部类
        class PDestination implements Destination {
            private String label;
            private PDestination(String whereTo) {
                label = whereTo;
            }
            @Override
            public String readLabel() {
                return label;
            }
        }
        return new PDestination(s);
    }

    public static void main(String[] args) {
        Parcel5 p = new Parcel5();
        Destination d = p.destination("Tasmania");
    }
}

5、匿名内部类

return new Base() {
	{ print("实例初始化"); }
	public void f() {
		print("方法f()");
     }
}

★ 优先使用类而非接口;

6、嵌套类

  1. 如果不需要内部类对象与其外围类对象之间有联系,那么可以将内部类声明为static;
  2. 普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象;
  3. 当内部类为static(即嵌套类)
    • 要创建嵌套类的对象,并不需要其外围类的对象;
    • 不能从嵌套类的对象中访问非静态的外围类;
  4. 普通内部类的字段与方法,只能放在类的外部层次上,所以普通的内部类不能由static数据和static字段,也不能包含嵌套类.但嵌套类可以包含所有这些东西;
  5. 嵌套类没有特殊的this引用,类似于static方法;

7、接口内部的类

  1. 嵌套类可以作为接口的一部分,因为接口中的任何类都是自动是public和static的,所以其作用就是将嵌套类置于接口的命名空间内.
  2. 一般用在:想要创建某些公共代码,使得它们可以被某个接口的所有不同实现所共用.

8、为什么需要内部类

  • 内部类继承自某个类或实现某个接口,内部类的代码操作创建他的外围类的对象,所以可以认为内部类提供了某种进入外围类的窗口;
  • 优点:每个内部类都能独立地继承一个接口的实现,所以无论外围类是否已经继承了某个接口的实现,对于内部类都没有影响;
  • 如果拥有的是抽象的类或具体的类,而不是接口,那就只能使用内部类才能实现多重继承;
class D{}
abstract class E {} 
class Z extends D {
	E makeE() { return new E() {}; }
}

public class test1 {
	static void takeD(D d) {}
	static void takeE(E e) {}
	public static void main(String[] args) {
		Z z = new Z();
		takeD(z);
		takeE(z.makeE());
	}
}

9 、闭包与回调

  • 闭包(closure)是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域;
  • 通过闭包的定义可以知道内部类是面向对象的闭包.; 

10、内部类的继承

 

class WithInner {
    class Inner {

    }
}

public class InheritInner extends WithInner.Inner{
    //! InheritInner() {} // Won't compile
    InheritInner(WithInner wi) {
        wi.super();
    }

    public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner ii = new InheritInner(wi);
    }
}

可以看到,InheritInner只继承内部类,而不是外部类,但是当要生成一个构造器时,默认构造器并不算好,而且不能只是传递一个指向外部类的对象的引用,此外,构造器内必须使用如下语法:

              enclosingClassReference.super();        

这样才提供了必要的引用,编译才能通过。

11、内部类可以被覆盖吗?

  • 如果创建一个内部类,然后继承其外围类并重新定义内部类时,不会覆盖原有的内部类,两个同名的内部类是完全独立的两个实体;
  • 当继承某个外围类的时候,内部类并没有发生什么特别的变化;

12、局部内部类

  • 典型的方式是在一个方法体里面创建;
  • 局部内部类不能有访问说明符,因为不是外围类的一部分;
  • 可以访问当前代码块内的常量,以及此外围类的所有成员;
  • 使用局部内部类而不使用匿名内部类:需要不止一个该内部类对象;

13、 内部类标识符

  • 每个类都会产生一个 .class 文件,命名规则:外围类的名字+ $ + 内部类的名字
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值