内部类与静态内部类

本文详细介绍了Java中的非静态内部类和静态内部类。非静态内部类可以访问外部类的所有成员,包括私有成员,而静态内部类不能访问外部类的实例成员,只能访问类成员。非静态内部类实例中隐含持有对外部类实例的引用,而静态内部类没有。文章通过实例展示了内部类的使用,并探讨了它们的特殊语法规则和应用场景。
摘要由CSDN通过智能技术生成

  世上只有一种英雄主义,就是在看清生活的真相之后,依然热爱生活。


前言

内部类是定义在另外一个类中的类,主要原因有:
  内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据内部类可以对同一个包的其他类隐藏。
  静态内部类和非静态内部类最大的区别是:非静态内部类编译后隐式保存着外部类的引用(就算外部类对象没用了也GC不掉),但是静态内部类没有。


一、非静态内部类

1.1 定义

       内部类定义语法格式如下:

class OuterClass {
    ...
    class NestedClass {
        ...
    }
}

       我们直接先看来一个例子吧,在Human类里定义了一个HumanLeg非静态内部类,并且在HumanLeg类的实例方法中直接访问外部类的private访问权限的实例变量和类变量。

/**
 * 人类 - 外部类
 *
 * @author 47Gamer
 */
public class Human {

    private static final int eyes = 2;

    private static void count() {
        System.out.println("I can count number");
    }

    private int teeth = 10;

    private void say() {
        System.out.println("Hello world");
    }

    /**
     * 人腿 - 非静态内部类
     */
    public class HumanLeg {
        private Double length;

        public HumanLeg(Double length) {
            this.length = length;
        }

        public void test() {
            say();
            count();
            System.out.println("I have " + eyes + " eyes");
            System.out.println("I have " + teeth + " teeth");
            System.out.println("My leg has " + length.toString() + "cm long");
        }
    }

    public static void main(String[] args) {
        Human human = new Human();
        HumanLeg humanLeg = human.new HumanLeg(100D);
        humanLeg.test();
    }
}

       由此看出,非静态内部类可以直接访问外部类的实例变量、类变量、实例方法、类方法。这是因为在非静态内部类对象里,保存了一个它所寄生的外部类对象的引用(非静态内部类实例必须寄生在外部类实例里)。也就是说,非静态内部类对象总有一个隐式引用,指向了创建它的外部类对象。我们来画一张示意图来理解一下:

在这里插入图片描述
       非静态内部类的成员只是在非静态内部类范围是可知的,并不能被外部类直接使用,如果要访问非静态内部类的成员必须显示创建非静态内部类对象来调用访问!
根据静态成员不能访问非静态成员的规则,外部类的静态方法不能访问非静态内部类。
非静态内部类不允许定义静态成员。如下面例子所示:

public class Test {

    class Inner{
        static {
            
        }
        
    }

    // 静态成员无法访问非静态成员
    public static void main(String[] args) {
        new Inner();
    }
}

1.2 内部类的特殊语法规则

如果非静态内部类方法访问某个变量,其顺序为

  1. 该方法是否有该名字的成员变量 - 直接用该变量名
  2. 内部类中是否有该名字的成员变量 - 使用this.变量名
  3. 外部类中是否有该名字的成员变量 - 使用外部类的类名.this.变量名

接下来看一个例子:

/**
 * @author 47Gamer
 */
public class Outer {

    private int i = 1;

    public class Inner {
        private int i = 2;

        public void print() {
            int i = 3;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Outer.this.i);
        }
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        Inner inner = outer.new Inner();
        inner.print();
    }
}

运行结果
3
2
1

二、静态内部类

2.1 定义

       如果用static来修饰一个内部类,那么就是静态内部类。这个内部类属于外部类本身,但是不属于外部类的任何对象。因此使用static修饰的内部类称为静态内部类。静态内部类有如下规则:
       静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。
       外部类可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象访问其实例成员。

public class StaticInnerTest {
    private int x = 1;
    private static int y = 2;

    public void test(){
        System.out.println(new InnerClass().a);
        System.out.println(InnerClass.b);
    }

    static class InnerClass {
        private int a = 3;
        private static int b = 4;

        public void test(){
            //无法访问
//            System.out.println(x);
            System.out.println(y);
        }
    }

    public static void main(String[] args) {
        StaticInnerTest staticInnerTest = new StaticInnerTest();
        staticInnerTest.test();

        InnerClass innerClass = new InnerClass();
        innerClass.test();
    }
}

参考

转载自:
[1]: https://www.cnblogs.com/47Gamer/p/13848028.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值