内部类详解(转)

内部类( inner class

1. 定义

是定义在另一个类中的类。

也可以在接口中定义,内部类可以继承某类或实现某接口;

内部类是一种编译时的语法,编译后生成的两个类是独立的两个类。内部类配合接口使用,来强制做到弱耦合(局部内部类,或私有成员内部类)。

注意:当类与接口(或者是接口与接口)发生方法命名冲突的时候,此时必须使用内部类来实现。这是唯一一种必须使用内部类的情况。
用接口不能完全地实现多继承,用接口配合内部类才能实现真正的多继承。

Ø 枚举和接口可以在类的内部定义,但不能在方法内部定义

2. 意义和特性

Ø 内部类方法可以访问该外部类定义所在的作用域中的数据,包括私有的数据;

但外部类不能直接访问内部类的成员;

Ø 可以对同一包中的其他类隐藏起来;封装类型:把标准公开,把标准的实现者作为内部类隐藏起来

Ø 当想要定义一个回调函数而不想编写大量代码时,实用匿名内部类比较便捷;

注:所有使用内部类的地方都可以不使用内部类;使用内部类可以使程序更加的简洁(但牺牲可读性),便于命名规范和划分层次结构。

Ø 内部类和外部类在编译时是不同的两个类,内部类对外部类没有任何依赖;

编译后文件Outer.class Outer$Inner.class

Ø 内部类可用 static、protected private 修饰

而外部类只能使用 public default

3. 分类:

包括:成员内部类、局部内部类、静态内部类、匿名内部类

注意:前三种内部类与变量类似,可以对照参考变量

3.1 成员内部类(实例内部类)

作为外部类的一个成员存在,与外部类的属性、方法并列;可看作外部类的实例变量。示例:Outer

public class Outer {

private String name;

public Outer(String name) {

this.name = name;

}

//私有内部类

private class Inner {

public void hello(){

//引用外部类对象

System.out.println("直接引用" + name);

System.out.println("this引用" + Outer.this.name);

}

}

public void start(){

Inner o = this.new Inner();

o.hello();

}

}

示例:

public static void main(String[] args) {

Outer outer = new Outer("张三");

outer.start();

}

结果:

直接引用:张三

This引用:张三

Ø 隐式引用:内部类的对象有个隐式引用,它引用了实例化该内部对象的外围对象,通过这个指针,可以访问外围对象的全部状态;

编译后:final Outer this$0 引用外围对象 可使用 this 直接引用外围类对象

内部类中访问实例变量:this.属性 直接引用 属性

在内部类访问外部类的实例变量:外部类名.this.属性。Outer.this.属性】

编译上面的Inner类,命令:javap private Outer$Inner

Ø 不可以有静态属性和方法(final 的除外),因为 static 在加载类的时候创建,这时内部类还没被创建

Ø 在创建成员内部类的实例时,外部类的实例必须存在:

Ø 在外部类的内部可以直接使用Inner inner = new Inner(); 因为外部类知道 inner 是哪个类。

Ø 而在外部类的外部,要生成一个内部类对象,需要通过外部类对象生成。

Outer outer = new Outer();

Outer.Inner inner = outer.new Inner();

Outer.Inner inner = new Outer().new Inner();

错误的定义:Outer.Inner inner = new Outer.Inner();

3.2 静态内部类

在内部类不需要访问外围类对象时,应该使用静态内部类,内部类声明为static

Ø 静态内部类定义在类中,在任何方法外,用 static 定义

Ø 静态内部类能直接访问外部类的静态成员;

Ø 不能直接访问外部类的实例成员;

Ø 静态内部类里面可以定义静态成员(其他内部类不可以)

Ø 生成(new)一个静态内部类不需要外部类成员,这是静态内部类和成员内部类的区别。
静态内部类的对象可以直接生成: Outer.Inner in = new Outer.Inner()
对比成员内部类:Outer.Inner in = outer.new Inner();

Ø 静态内部类不可用 private 来进行定义

Ø 声明在接口中的内部类自动成为 static public

3.3 局部内部类

在方法中定义的内部类称为局部内部类。

Ø 能用 publicprotected private 进行声明,其范围为定义它的代码块

Ø 可以访问外部类的所有成员;

Ø 可以访问局部变量(含参数),但局部变量必须被声明为final

Ø 在类外不可直接生成局部内部类,保证局部内部类对外是不可见的,即对外部是完全隐藏的;

Ø 在方法中才能调用其局部内部类;

Ø 局部内部类不能声明接口和枚举;

3.4 匿名内部类

Ø 由于构造器的名字必须和类名相同,而匿名类没有类名,所以,匿名内部类不能有构造器,将构造器参数传递给超类构造器,尤其是在内部类实现接口的时候,不能有任何构造参数;

Ø 用于构造对象的任何参数都要被放在超类后面的()内,语法为

new SuperType (construction parameters){

inner class methods and data

}

Ø 通过匿名类实现接口,大部分情况都是为了实现接口的回调;

new InterfaceType(){

inner class methods and data

}

Ø 匿名内部类在编译的时候由系统自动起名Outer$1.class

Ø 其为特殊局部内部类,所以局部内部类的所有限制都对其生效。

4. 其他

4.1 内部接口:

Ø 在一个类中也可以定义内部接口

Ø 在接口中可以定义静态内部类,此时静态内部类位于接口的命名空间中。

Ø 在接口中还可以定义接口,这种接口默认也是public static

Map.Entry就是这种接口

Ø 接口里面还可以定义多重接口和类。

示例:OutInterface

package core.z6.inner.test3;

public interface OutInterface {

void hello(String name);

interface InnerInterFace {

void hello(String name);

};

abstract class InnerAbstractClass implements InnerInterFace{

}

class InnerClass implements InnerInterFace{

public void hello(String name) {

System.out.println(this.getClass().getName() + ": Hello " + name);

}

}

}

示例:OutClass

package core.z6.inner.test3;

public class OutClass implements OutInterface {

public void hello(String name) {

System.out.println(this.getClass().getName() + ": Hello " + name);

}

}

示例:Test2

package core.z6.inner.test3;

import core.z6.inner.test1.OutInterface.InnerClass;

public class Test3 {

public static void main(String[] args) {

OutInterface obj = new OutClass();

obj.hello("李四"); //外部接口的hello()方法

OutInterface.InnerInterFace o = new InnerClass();

o.hello("张三"); //内部部接口的hello()方法

}

}

结果

core.z6.inner.test1.OutClass: Hello 李四

core.z6.inner.test1.OutInterface$InnerClass: Hello 张三

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值