avatar

java内部类

可以将一个类的定义放在另一个类的定义内部,这就是内部类。内部类对象是以外部类对象存在为前提的

为什么要使用内部类

一般说来,内部类继承自某个类或实现某个接口,内部类的代码操作创建它的外围类的对象。所以可以认为内部类提供了某种进人其外围类的窗口。
内部类必须要回答的一个问题是:如果只是需要一个对接口的引用,为什么不通过外围类实现那个接口呢?答案是:“如果这能满足需求,那么就应该这样做。”那么内部类实现一个接口与外围类实现这个接口有什么区别呢?答案是:后者不是总能享用接口带来的方便,有时需要用到接口的实现。所以,使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
如果没有内部类提供的、可以继承多个具体的或抽象的类的能力,一 些设计 与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。也就是说,内部类允许继承多个非接口类型(译注:类或抽象类)
内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对象的信息相互独立。
在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。 举个例子,如果Sequenc.java不使用内部类,就必须声明“Sequence是一个Selector,对于某个特定的Sequence只能有一个Selector.然而使用内部类很容易就能拥有另一个方法reverseSelector() , 用它来生成一个反方向遍历序列的Selector.只有内部类才有这种灵活性
创建内部类对象的时刻并不依赖于外围类对象的创建。
内部类并没有令人迷惑的”is-a” 关系;它就是一个独的实体。
闭包是一个可调用的对象,他记录了一些信息,这些信息来自于创建他的作用域。通过这个定义,可以看出内部类是面向对象的闭包,,因为它不仅仅包含外围类对象的信息,还自动拥有一个指向外围类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private成员.回调的价值在于它的灵活性,在运行时状态决定调用什么方法,通过回调,对象能够携带一些信息,这些信息允许他在某个时刻调用初始的对象

静态内部类

定义在类内部的静态类,就是静态内部类。其实真正意义上是静态嵌套类。可以单独使用不依赖于外部类

public class Out {
private static int a;
private int b;
public static class Inner {
public void print() {
System.out.println(a);
}
}
}
  • 静态内部类可以访问外部类所有的静态变量和方法,即使是 private 的也一样。
  • 静态内部类和一般类一致,可以定义静态变量、方法,构造方法等。
  • 其它类使用静态内部类需要使用“外部类.静态内部类”方式,如下所示:Out.Inner inner = new Out.Inner();inner.print();
  • Java集合类HashMap内部就有一个静态内部类Entry。Entry是HashMap存放元素的抽象,HashMap 内部维护 Entry 数组用了存放元素,但是 Entry 对使用者是透明的。像这种和外部类关系密切的,且不依赖外部类实例的,都可以使用静态内部类。

成员内部类

定义在类内部的非静态类,就是成员内部类。成员内部类不能定义静态方法和变量(final 修饰的除外)。这是因为成员内部类是非静态的,类初始化的时候先初始化静态成员,如果允许成员内部类定义静态变量,那么成员内部类的静态变量初始化顺序是有歧义的。

public class Out {
private static int a;
private int b;
public class Inner {
public void print() {
System.out.println(a);
System.out.println(b);
}
}
}

局部内部类 ( 定义在方法中的类)

定义在方法中的类,就是局部类。如果一个类只在某个方法中使用,则可以考虑使用局部类。

public class Out {
private static int a;
private int b;
public void test(final int c) {
final int d = 1;
class Inner {
public void print() {
System.out.println(c);
}
}
}
}

匿名内部类

匿名内部类我们必须要继承一个父类或者实现一个接口,当然也仅能只继承一个父类或者实现一个接口。同时它也是没有class关键字,这是因为匿名内部类是直接使用new来生成一个对象的引用。

abstract class Bird {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract int fly();
}
public class Main {
public void test(Bird bird){
System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米");
}
public static void main(String[] args) {
Main test = new Main();
test.test(new Bird() {
public int fly() {
return 10000;
}
public String getName() {
return "大雁";
}
});
}
}
[详解 Java 内部类](https://blog.csdn.net/hacker_zhidian/article/details/82193100)
文章作者: zenshin
文章链接: https://zlh.giserhub.com/2020/03/18/cl35o0mpi001dp4tgfc65hkul/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 zenshin's blog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论