Java 内部类使用详解

这个系列是帮助复习 Java 的基础知识的,但是并不会按照一个特定的顺序。现在开始复习下内部类的相关知识。

0. 简介

内部类的定义很简单,它其实就是在一个类里面定义了另一个类,但是这个定义还是有很多细节需要掌握的。

1. 非静态内部类

1.1 定义

非静态内部类就是在一个类的内部里面定义了一个没有用 static 修饰的类。

1.2 访问控制符

内部类的访问控制符 访问范围
private 同一个类
default 同一个类,同一包中
protected 同一个类,子类,同一包中
public 任何位置

1.3 非静态内部类访问外部类元素

非静态内部类是可以访问外部类的任何实例变量和方法,包括 private 修饰的成员变量。现在用一个例子来说明一下,代码如下:

public class Outer {

    private int a = 10;

    private void innerCall() {

        System.out.println("Inner Call");

    }

    private class Inner {

        public void printInfo() {
            System.out.println("a = " + a);
            innerCall();
        }

    }

    public void test() {

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

    }

    public static void main(String[] args) {

        Outer outer = new Outer();
        outer.test();

    }

}

输出结果:

a = 10
Inner Call

从输出的结果就可以看到,非静态内部类是可以访问到外部类的任何实例变量和方法的。
那为什么内部类可以直接访问外部类的实例变量和方法呢?因为内部类里面是持有外部类的实例引用,一个非静态内部类创建时必然会有其外部类实例的引用。也就是说上面的 printInfo() 方法也可以写成如下:

public void printInfo() {
    System.out.println("a = " + Outer.this.a);
    Outer.this.innerCall();
}

上述代码中的 Outer.this 就是非静态内部类持有外部类的实例引用。

1.3.1 非静态内部类方法访问某个变量的检查顺序

当非静态内部类的方法访问某个变量是按一定顺序来查找的,顺序如下

  1. 在该方法的局部变量找
  2. 方法所在的内部类找
  3. 内部类所在的外部类找
  4. 如果都没有则编译报错

举个例子,代码如下:


public class Outer {

    private int a = 10;

    private class Inner {

        private int a = 9;

        public void printInfo(int a) {
            System.out.println("a = " + a);
        }

    }

    public void test() {

        Inner inner = new Inner();
        inner.printInfo(8);

    }

    public static void main(String[] args) {

        Outer outer = new Outer();
        outer.test();

    }

}

以上代码的输出结果就是 a = 8。
如果把 printInfo(int a) 的形参 a 去掉,则输出的结果为 a = 9。
再把 Inner 类中的成员变量 a 去掉,则输出的结果为 a = 10。
各位可以自己尝试一下,这里就不再讲解。

## 1.4 外部类访问非静态内部类的元素
外部类不能直接访问非静态内部类的实例变量和方法,如果想要访问的话,必须要创建非静态内部类的实例进而调用该实例的成员。如下代码所示:



public class Outer {

    private int a = 10;

    private class Inner {

        public void printInfo() {
            System.out.println("a = " + a);
        }

    }

    public void test() {

        //这句会编译错误
        printInfo();

    }

    public static void main(String[] args) {

        Outer outer = new Outer();
        outer.test();

    }

}

以上代码会编译错误,如果想要访问的话只能创建 Inner 的实例访问该方法,这里有两种方式,一种就是在 test() 方法里面创建 Inner 对象,另一种就是在 main 方法创建,以下两种方法都用代码试一下:

public class Outer {

    private int a = 10;

    private class Inner {

        public void printInfo() {
            System.out.println("a = " + a);
        }

    }

    public void test() {

        new Inner().printInfo(); 

    }

    public static void main(String[] args) {

        Outer outer = new Outer();
        outer.new Inner().printInfo();
        outer.test();

    }

}

从以上代码可以看到,test() 方法里面直接 new Inner() 即可调用 Inner 方法。不过在 main 方法里要先创建 Outer 对象才可以再调用 new Inner()。

1.4.1 外部类的静态方法不可以创建非静态内部类

根据 Java 的规则,静态成员是不可以访问非静态成员的。非静态内部类其实就是类实例中的一个成员,所以在外部类的静态方法不可以创建非静态内部类,现用代码举例:


public class Outer {

    private int a = 10;

    private class Inner {

        public void printInfo() {
            System.out.println("a = " + a);
        }

    }

    public static void main(String[] args) {

        //这句代码会编译报错
        Inner inner = new Inner();

    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值