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();//通过变量名调用
    }
}
相关推荐
Naix15731 分钟前
Eclipse运行main函数报 launch error
java·ide·eclipse
qq_454384713 分钟前
Maven的安装与配置
java·maven·intellij idea
小悟空GK10 分钟前
Filter和Listener
java
randy.lou10 分钟前
GRPC使用之ProtoBuf
java·rpc
小悟空GK14 分钟前
Http介绍
开发语言
虫小宝22 分钟前
解决Spring Boot中的安全漏洞与防护策略
java·spring boot·后端
502胶水20524 分钟前
腾讯地图异步调用
开发语言·ios·swift
SwBack34 分钟前
【pearcmd】通过pearcmd.php 进行GetShell
android·开发语言·php
Lingoesforstudy34 分钟前
c#中的超时终止
开发语言·笔记·c#
LXMXHJ35 分钟前
Java-Redis-Clickhouse-Jenkins-MybatisPlus-Zookeeper-vscode-Docker
java·redis·java-zookeeper