Java中的内部类(Nested Classes)
一、概念
前几天面试过程中遇到了一个关于匿名内部类的问题,当时不太明白,现在着重理解一下。甲骨文官方释意:
Nested classes are divided into two categories: non-static and static. Non-static nested classes are called inner classes. Nested classes that are declared
static
are called static nested classes.
1. 普通内部类(Inner Class)
内部类(Inner)就是放在另外一个类的内部定义的类。通常它这样写
class OuterClass {
...
class InnerClass {
...
}
}
- 内部类可以访问并且修改外部类的
private
字段,例如
class Outer{
private String info = "hello, i'm info";
class Inner{
public void run(){
System.out.println("hello, i'm inner");
//修改外部类的private字段
info = "hello, i have changed by inner class method";
//Outer.this.info = "hello, i have changed by inner class method";
System.out.println(info);
}
}
}
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.run();
}
}
// Result:
/**
hello, i'm inner
hello, i have changed by inner class method
**/
- 在内部类中,由于内部类实例依附于外部类实例,为了区分两者的同名属性,通常用
this
指代当前内部类实例本身,而通过Outer.this
指代外部类实例,例如:
class Outer{
private String info = "hello, i'm out";
class Inner{
private String info = "hello i'm inner";
public void run(){
System.out.println(this.info); //this 指向
Outer.this.info = "hello, i have changed by inner class method";
System.out.println(Outer.this.info);
}
}
}
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.run();
}
}
// result:
/**
hello i'm inner
hello, i have changed by inner class method
**/
另外,有两种特殊的Inner classed
,分别为local classes
和 anonymous classes
具体可看special inner class
2. 静态嵌套类(Static Nested Class)
在内部类中,也可以用static
修饰内部类,我们称之为Static Nested Class
静态内部类, 例如ThreadLocal
中:
public class ThreadLocal<T> {
//....
static class ThreadLocalMap {
}
}
一个有趣的事情是:Oracle官方将普通内部类称作Inner Classes
, 而将静态嵌套类称作Nested Class
, 嵌套就是你我毫不相干,所以静态内部类不依附于外部类实例,所以可以作为一个独立的类存在,而且它可以访问外部类private
修饰过的静态字段和静态方法,如果将其移动到外部,那么就失去了这种效果
class A {
static private int a1 = 1;
private int a2 = 2;
static class B{
public static void say(){
System.out.println(a1); //right result : 1
System.out.println(a2); //wrong 不可访问外部非静态对象
}
}
public static void main(String[] args) {
}
}
public class Test{
public static void main(String[] args) {
A.B.say(); //调用正确
new A.B().say(); //调用正确
}
}
二、作用
1. 实现多继承
由于Java
支持单继承,但是我们可以通过匿名内部类来实现多继承,例如:
class dad {
public String body(){
return "I have strong body";
}
}
class mom {
public String hair(){
return "I have black hair";
}
}
//实现了多重继承
class Son{
private class test1 extends dad {
@Override
public String body() {
return "I have stronger body";
}
}
private class test2 extends mom {
@Override
public String hair() {
return "I have more black hair";
}
}
public String getInfo(){
return new test1().body() + " and " + new test2().hair();
}
}
//Result
/**
I have stronger body and I have more black hair
**/
三、总结
- 嵌套类包括
Inner classes
(内部类)和static nested classes
(静态内部类) - 其中
Inner classes
又包括simple inner class
、local classes
andanonymous classes
- 内部类优点:
- 如果一个子类只被外部类自己使用,那么就没有必要将内部类变成
top-level classes
, 通过添加这样的“辅助类”可以使包结构变得简洁干练 - 增加了封装,考虑两个顶级类A和B,其中B需要访问A的成员,通过将类B隐藏在类A中,可以将A的成员声明为私有,B可以访问它们。此外,B本身可以对外界隐藏。
- 代码可读性和可维护性增加:嵌套类的代码和外部类的代码距离变得更近。
- 如果一个子类只被外部类自己使用,那么就没有必要将内部类变成