Java:内部类

目录

1.内部类介绍

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么这个内部的完整结构最好使用内部类。在 Java 中,**可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。**内部类也是封装的一种体现。
注意事项

1.定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类,举例如下

java 复制代码
public class A{  
}
class B{ 
}
// A 和 B是两个独立的类,彼此之前没有关系

2.内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件。如下说示:

java 复制代码
class OuterClass{
    public int data1=1;
    private int data2=2;
    class InnerClass{
        public int data1=100;
        public int data3=3;

    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
    }
}

编译后产生的字节码文件

2.实例内部类

代码形式

java 复制代码
class OuterClass{
    public int data1=1;
    private int data2=2;
    class InnerClass{
        public int data1=100;
        public int data3=3;
    }
}

1.外部类中的任何成员都可以在实例内部类方法中直接访问

java 复制代码
class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);    
    }
    class InnerClass{
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(data1);
            System.out.println(data2);
            //直接调用外部类的data1和data2并打印
        }
    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        innerClass.test1();
    }
}

运行结果

2.实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束

使用private修饰后,下面实例化的时候就会报错,如下所示

被public修饰就不展示了
3.在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员 来访问

java 复制代码
class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    class InnerClass{
        public int data1=100;//与外部类同名成员
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(this.data1);
            System.out.println(data2);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        innerClass.test1();
    }
}

运行结果

如果要想访问到外部类的同名方法,修改如下

java 复制代码
public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(OuterClass.this.data1);
            System.out.println(data2);
        }

运行结果

4.实例内部类对象必须在先有外部类对象前提下才能创建

下面提供两种实例化方式

java 复制代码
public static void main(String[] args) {
// 要访问实例内部类中成员,必须要创建实例内部类的对象
// 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        OuterClass.InnerClass innerClass1=new OuterClass().new InnerClass();
    }

5.实例内部类的非静态方法中包含了一个指向外部类对象的引用

java 复制代码
class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    class InnerClass{

        public void test1(){
            OuterClass out=new OuterClass();
  //在内部类方法中创建一个外部类对象,通过这个对象调用外部类成员方法
            out.test();
            System.out.println("=================");
            System.out.println("InnerClass::test()");
            System.out.println(data1);
            System.out.println(data2);
        }

    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        innerClass.test1();
    }
}

运行结果

6.外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。

java 复制代码
class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        OuterClass.InnerClass innerClass=new InnerClass();
        //在外部类中实例化了一个内部类对象调用内部类成员
        innerClass.test1();
        System.out.println("===================");
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    class InnerClass{
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(data1);
            System.out.println(data2);
        }

    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        out.test();
    }
}

运行结果

3.静态内部类

1.在静态内部类中只能访问外部类中的静态成员

java 复制代码
class OuterClass{
    public int data1=1;
    private int data2=2;
    static int data3=3;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    static class InnerClass{
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(data1);//非静态成员,会报错
            System.out.println(data2);//非静态成员,会报错
            System.out.println(data3);//静态成员正常访问
        }
    }
}

如果确实想访问,我们该如何做?
在内部类方法里实例化一个外部类方法

java 复制代码
static class InnerClass{
        public void test1(){
            OuterClass out=new OuterClass();
            System.out.println("InnerClass::test()");
            System.out.println(out.data1);
            System.out.println(out.data2);
            System.out.println(data3);
        }

运行结果

2.创建静态内部类对象时,不需要先创建外部类对象

java 复制代码
public class Test {
    public static void main(String[] args) {
        OuterClass.InnerClass innerClass=new OuterClass.InnerClass();
        //直接通过外部类调用就可创建静态内部类的对象
        innerClass.test1();
    }
}

4.局部内部类

定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少,此处简单了解下语法格式。
1.局部内部类只能在所定义的方法体内部使用

java 复制代码
class OuterClass{
    public void method() {
        int data1=1;
        class InnerClass{
            void test1(){
                System.out.println("InnerClass::test1()");
                System.out.println(data1);
            }
        }
        //只能在方法体内部使用
        InnerClass innerClass=new InnerClass();
        innerClass.test1();
    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        out.method();
    }
}

运行结果

如果在方法题外部使用会出现报错

2.不能被public、static等修饰符修饰

报错结果如下

3.编译器也有自己独立的字节码文件,命名格式:外部类名字$数字内部类名字.class

4.几乎不会使用

5.匿名内部类

匿名内部类可以用来实现一个接口并创建一个新的线程,举例如下

java 复制代码
interface ITestable{
    void test();
}
public class Test {
    public static void main(String[] args) {
        new ITestable(){//直接实现这个接口
            @Override
            public void test() {
                System.out.println("hello zzuli");
            }
        };
    }
}

上面的代码相当于下面通过implments来实现一个接口

java 复制代码
interface ITestable{
    void test();
}
class A implements ITestable{

    @Override
    public void test() {
        System.out.println("hello zzuli");
    }
}
public class Test {
    public static void main(String[] args) {
        A a=new A();
    }
    
}

我们通过匿名内部类来实现接口,那么我们应该怎么使用接口里的方法呢?

下面提供两种方法

方法一:直接通过.来调用,代码如下

java 复制代码
interface ITestable{
    void test();
}
public class Test {
    public static void main(String[] args) {
        new ITestable(){
            @Override
            public void test() {
                System.out.println("hello zzuli");
            }
        }.test();//直接调用
    }
}

方法二:通过创建一个变量来调用(推荐使用)

java 复制代码
interface ITestable{
    void test();
}
public class Test {
    public static void main(String[] args) {
        ITestable I=new ITestable(){
            @Override
            public void test() {
                System.out.println("hello zzuli");
            }
        };
        I.test();//通过变量名调用
    }
}
相关推荐
鬼手点金2 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
爱上网的小舟2 小时前
星际战士2启动错误怎么办?5种游戏报错解决方法
开发语言·php
paopaokaka_luck3 小时前
滑雪场管理系统(AI智能助手流式对话,ECharts 运营数据分析、教练、雪具与场地一体化预约,钱包支付退款、订单核销与服务评价)
java·人工智能·spring boot·网络协议·数据分析·echarts
阿里嘎多学长3 小时前
2026-10-12 GitHub 热点项目精选
开发语言·程序员·github·代码托管
Wang's Blog3 小时前
Java 项目实战: 交友项目 - Dubbo 的内部结构与一次调用的完整链路
java·dubbo
Wang's Blog3 小时前
Java 项目实战: 交友项目 - Dubbo 入门引导
java·dubbo·交友
wangchunyu1144 小时前
Python 数据可视化实战入门教程
开发语言·python·信息可视化
蜗牛互联网4 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python
SL_staff4 小时前
当规则引擎开始‘懂业务’:JVS-Rules金融风控四大原生能力拆解
java·python·全栈
Shaoshing4 小时前
前缀和与差分
java·数据结构·算法·前缀和·差分