Java中的内部类

本文深入探讨Java中的内部类,包括成员内部类和静态内部类。成员内部类可以直接使用外部类的所有信息,但不能有静态成员。静态内部类则独立于外部类对象,可以直接通过外部类名访问。文章通过代码示例解析了两种内部类的使用和特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
最近在工作中常用到内部类,对这方面的知识点总是模凌两可,所以趁着现在需求不是很忙想好好总结一下这部分的知识点,这也是我毕业后的第一篇博客,莫名怀念上学的时候。
这次的博客我想做一些改变,以前都是对一个知识点进行总结,然后逐个分析,这样我发现当再次看的时候不便于阅读,所以这次我想尝试先分析每一种情况,然后最后再做总结,要是谁看到我的博客发现写错了或者其他的建议欢迎留言。废话少说,直接进入正题。
一、成员内部类
1、顾名思义,这种内部类直接定义在外部类(相对内部类而言)之中,和外部类的成员属性和成员方法一个级别,就像是外部类的一个成员。直接上代码
(1)在外部类之中定义方法内部类,并且互相调用对方的属性和方法

package methodInner;

public class Outer {
    private int outerA ;
    private int outerB ;
    private static int outerC = 300;
    private int publicD;

    public Outer() {

    }

    public Outer(int outerA, int outerB, int publicD) {
        this.outerA = outerA;
        this.outerB = outerB;
        this.publicD = publicD;
    }

    public void outPrint() {
        System.out.println("这是外部类的outPrint");
    }

    public void outerWrite() {
        System.out.println("这是外部类的outerWrite");
    }

    public class Inner{
        private int innerA;
        private int innerB;
        private int publicD;
        //方法内部类中不可以有静态变量
        //private static int innerC;
        public Inner() {

        }
        public Inner(int innerA, int innerB, int publicD) {
            this.innerA = innerA;
            this.innerB = innerB;
            this.publicD = publicD;
        }

        public void print() {
            System.out.println("外部的变量直接访问");
            System.out.println("outerA:" + outerA);
            System.out.println("outerA:" + outerB);
            System.out.println("outerC:" + outerC);
            System.out.println("当外部变量和内部变量重名的话,直接用到变量名指的是内部类的变量");
            System.out.println("内部publicD:" + publicD);
            System.out.println("当外部变量和内部变量重名的话,访问外部类的对象可以'类名.this.变量名'");
            System.out.println("外部publicD:" + Outer.this.publicD);
            System.out.println("可以直接访问外部类的方法");
            outPrint();
            outerWrite();
        }

        public void innerWrite() {
            System.out.println("这是内部类的innerWrite");
        }

    }

    public void printInnerQuality() {
        System.out.println("外部类想访问内部类的属性和方法需要new内部类对象,打点访问");
        Inner inner = new Inner(100,200,300);
        System.out.println("外部类访问内部变量:" + inner.innerA + ","+ inner.innerB + ","+ inner.publicD);
        System.out.println("外部类访问内部方法:");
        inner.innerWrite();
    }
}

(2)在其他类中进行测试

package methodInner;

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer(500,600,700);
        System.out.println("其他类想访问外部类的时候,需要利用外部类创建内部类的对象");
        Outer.Inner inner = outer.new Inner(800,900,950);
        outer.printInnerQuality();
        inner.print();

    }
}

2、结果分析,以上代码最终的运行结果如下:
在这里插入图片描述
对于成员内部类的总结:
(1)他和其他类一样,该继承就继承,该实现接口就实现接口,该重写重写,该重载重载,this和super随便用。
(2)内部类的内部不能有静态信息。
(3)内部类可以直接使用外部类的任何信息,如果属性或者方法发生冲突,调用外部类.this.属性或者方法,否则默认重名调用的是内部类的信息。
(4)外部类如果想调用内部类的信息,需要创建内部类的对象(参考外部类中printInnerQuality()方法),然后打点访问。
(5)除了外部类其他类想访问内部类,需要先创建外部类的对象,然后再利用外部类的对象去创建内部类的对象(参考测试代码)。
3、单独解释下为什么成员内部类不能有静态成员和变量?
在解释这个原因之前,想聊一聊我们熟知的类的成员属性(方法)与对象之间的关系。
我们知道类是对一类事物的抽象,比如人就是一个类,那么小明,小红,小刚都是人这个类的具体实例(也就是对象)。
那么在人这个类中定义一个成员属性,比如年纪,然后还有一个成员方法,比如编程。这两个成员都是依附于对象的,比如小明25岁,会写代码;小红22岁不会写代码,小刚25岁不会写代码。也就是不同的对象会有不同的结果。但是对于人这类而言,还有些成员不用依附于对象,比如人都有的成员属性(手),都有的成员方法(拿东西),这两个成员是跟对象无关的,也就是说不依附于对象,是每个对象都有的,或者说这两个成员是属于类本身。可能我举的例子不是很恰当,但是我想表达的就是。对于一个类中的无论是成员属性还是成员方法,有一部分是依附于具体对象存在的,而另一部分是这个类所有对象都共有的,那么这部分类中所有对象共有的成员其实是依附于类本身。
那么在java中,这些依附于类本身的成员,都叫做静态成员,也就是用static修饰。这些成员在类加载的时候就存在于内存中了,所以即使没有创建对象,也可以直接用类名打点的方式来访问。在了解了这些之后,我们在会过头看一下我们要解释的这个问题。
既然成员内部类可以看作是类的一个成员,且没有被static修饰,那么就说明这个内部类的是依附于外部类的具体对象存在的,我们在其他类中使用这个内部类的时候也验证了这一点,先创建外部类对象,再用外部类的对象创建内部类的对象。
所以既然成员内部类依附于外部类的对象,那么在成员内部类中如果还有静态的成员和方法就是自相矛盾的。可以这样想,如果有的话,那么在外部类加载时候,这些内部类的静态的成员变量或者方法就被存在内存了,但是这个时候外部类还没有创建对象,所以内部类还没有被加载(如上解释的成员内部类依附于外部类的对象),所以就是说此时内部类还没有加载,但是它的部分属性和方法却可以用了,这显然是不可以的,所以成员内部类中不可以用静态成员属性和方法。
二、静态内部类
既然刚才解释了既然成员内部类没有被static修饰,就不可以在内部有静态成员,那么在这里就让内部类用static修饰,也就是静态内部类,当内部类用static修饰,就可以这个内部类独立于外部类的对象,而直接依附于外部类。(这很好理解吧,对比上面的成员内部类)。直接上代码。
(1)在外部类中定定义静态内部类,并且互相调用

package staticInner;

import jdk.swing.interop.SwingInterOpUtils;

public class Outer {
    private int outerA;
    private int outerB;
    private static int outerC = 100;
    private static int publicD = 200;

    public Outer() {}
    public Outer(int outerA, int outerB) {
        this.outerA = outerA;
        this.outerB = outerB;
    }

    static {
        System.out.println("外部类的静态代码块被执行了");
    }

    private void outerPrint() {
        System.out.println("这是外部类的outerPrint方法");
    }

    private static void outerWrite() {
        System.out.println("这是外部类的静态outerWrite方法");
    }

    static class Inner {
        private int innerA;
        private int innerB;
        private static int innerC = 300;
        private static int publicD = 400;

        public Inner() {}
        public Inner(int innerA, int innerB) {
            this.innerA = innerA;
            this.innerB = innerB;
        }

        static {
            System.out.println("内部类的静态代码块被执行了");
        }

        public void innerPrint() {
            System.out.println("静态内部类可以直接访问外部类的静态成员,但是不可以访问非静态成员");
            System.out.println("outerC:" + outerC );
            outerWrite();
            System.out.println("当外部变量和内部变量重名的话,直接用到变量名指的是内部类的变量");
            System.out.println("内部publicD:" + publicD);
            System.out.println("当外部变量和内部变量重名的话,访问外部类的对象可以'类名.变量名'");
            System.out.println("外部publicD:" + Outer.publicD);
            System.out.println("静态内部类如果想访问外部类的非静态成员,就需要先创建外部类的对象");
            Outer outer = new Outer(500,600);
            System.out.println("outerA:" + outer.outerA);
            System.out.println("outerB:" + outer.outerB);
            outer.outerPrint();
        }

        public static void innerWrite() {
            System.out.println("这是内部类的innerWrite");
        }


    }
    public void printInnerQuality() {
        System.out.println("外部类调用内部类的静态成员的时可以直接使用内部类名.成员名");
        System.out.println("innerC:" + Inner.innerC);
        System.out.println("innerD:" + Inner.publicD);
        Inner.innerWrite();
        System.out.println("外部类调用内部类的非静态成员的时需要先创建内部类的对象");
        Inner inner = new Inner(700,800);
        System.out.println("innerA:" + inner.innerA);
        System.out.println("innerB:" + inner.innerB);
    }

}

(2)在外部类中使用静态内部类

package staticInner;

public class Test {
    public static void main(String[] args) {
        System.out.println("其他类访问静态内部类的静态方法");
        Outer.Inner.innerWrite();
        System.out.println("其他类访问静态内部类的非静态方法,需要先创建内部类的实例");
        Outer.Inner inner = new Outer.Inner();
        inner.innerPrint();
        Outer outer = new Outer(1000,2000);
        outer.printInnerQuality();
    }
}

结果分析:以上的代码的最终结果如下所示:
在这里插入图片描述
为了和成员内部类做一个对比,所以下面在列出静态内部类的性质的时候都会和成员内部类做个比较。

成员内部类静态内部类
属于外部类的某一个对象 ,和外部类的非静态成员一个级别属于外部类本身,不属于外部类的某一个对象,和外部类的静态成员一个级别
成员内部类不可以包含静态属性和方法静态内部类既可以包含静态属性和方法,也可以包含非静态的
成员内部类可以访问外部类的所有成员属性和方法,当有重名的时候想访问外部类的成员的时候,用外部类.this.成员名静态内部类只可以访问外部类的静态成员,无论是在静态还是非静态的发法中,如果重名想访问外部类的成员,用外部类名.成员名
外部类想访问成员内部类,需要创建内部类实例,然后通过打点的方式外部类想访问静态内部类,如果是静态的,直接内部类.静态成员,如果是非静态的,需要先创建内部类实例,然后再通过打点的方式
其他类想访问成员内部类的成员,需要先创建外部类的对象,然后再根据外部类的实例创建成员内部类的实例,然后再通过打点的方式其他类想访问静态内部类的成员,如果是静态的,直接外部类.内部类.成员,如果是非静态的,创建内部类实例(和成员内部类不同,参考上面的例子)

我觉得他们之间的所有差距都是因为
静态内部类不属于外部类的任何对象,它是属于外部类本身的。所以想使用它,只需用到外部类名就好,不需要为他创建外部类对象。
三、匿名内部类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值