【JavaSE】类和对象(三)——内部类

目录

1. 何为内部类

2. 内部类的分类

    2.1 静态内部类

        2.1.1 如何实例化静态内部类的对象?

        2.1.2 外部类与静态内部类如何相互访问? 

    2.2 非静态内部类/实例内部类

        2.2.1  非静态内部类不能定义静态的成员变量以及方法

        2.2.2 非静态内部类的实例化 

        2.2.3 外部类与非静态内部类的互相访问

        2.2.4 当内外部类的成员变量名字相同时 

    2.3 局部内部类

    2.4 匿名内部类


1. 何为内部类

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

2. 内部类的分类

2.1 静态内部类

被 static 修饰的内部成员类称为静态内部类。

class OutClass {

     //静态内部类:

    static class InnerClass{

    }

}

2.1.1 如何实例化静态内部类的对象?

    public static void main(String[] args) {
        //实例化一个内部类对象;
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
    }

2.1.2 外部类与静态内部类如何相互访问? 

1. 静态内部类访问外部类成员:

class OuterClass{
    public int a = 1;
    private int b = 2;
    public static int c = 3;
    static class InnerClass {
        public int d = 4;
        private int e = 5;
        public static int f = 6;

        public void func(){
            System.out.println("static->InnerClass::func");
            System.out.println(a); //红字报错!!
            System.out.println(b); //红字报错!!
            System.out.println(c);
            System.out.println(d);
            System.out.println(e);
            System.out.println(f);
        }
    }
}

由前面学过的知识可知,所有 static 修饰的,都不依赖于对象,但如果没有 static 修饰,就一定得实例化对象之后才能访问。所以在静态内部类内部直接访问外部类的非静态成员是不行的,得实例化对象才行:

            //将上述代码注释处修改为:
            OuterClass outerClass = new OuterClass();
            System.out.println(outerClass.a);
            System.out.println(outerClass.b);

调用 func 方法:

    public static void main(String[] args) {
        //实例化一个内部类对象;
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        innerClass.func();
    }

2. 外部类访问静态内部类成员:

在外部类中,写这样一个方法:

 发现,外部类方法直接访问内部类成员,全部红字报错,该如何修改?

    public void outerFunc(){
        System.out.println("OuterClass::outerFunc");
        InnerClass innerClass = new InnerClass();
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(innerClass.d); //d 为静态内部类非静态成员变量 
        System.out.println(innerClass.e); //e 为静态内部类非静态成员变量 
        System.out.println(InnerClass.f); //f 是静态内部类的静态成员变量,通过类名便可访问
    }

注意:内部类和外部类共用同一个 java 源文件,但是经过编译之后,内部类会形成单独的字节码文件:

2.2 非静态内部类/实例内部类

public class OutClass {

    class InnerClass{

    }

}

// OutClass是外部类

// InnerClass是非静态内部类

2.2.1  非静态内部类不能定义静态的成员变量以及方法

 但如果非要有,加个 final :

 加了 final ,f 变成常量,而常量在程序编译过程中,是一个确定的值。

2.2.2 非静态内部类的实例化 

    public static void main(String[] args) {
        OuterClass1 outerClass = new OuterClass1();
        OuterClass1.InnerClass1 innerClass1 = outerClass.new InnerClass1();
        System.out.println(innerClass1.d);
    }

在此也可以看出,非静态内部类相较静态内部类麻烦, 需要实例化外部类的对象。一般情况下,使用静态内部类较多。

2.2.3 外部类与非静态内部类的互相访问

1. 非静态内部类访问外部类:

class OuterClass1{
    public int a = 1;
    private int b = 2;
    public static int c = 3;
    class InnerClass1{
        public int d = 4;
        private int e = 5;
        public static final int f = 6;
        public void func(){
            System.out.println("InnerClass1::func");
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
            System.out.println(d);
            System.out.println(e);
            System.out.println(f);
        }
    }
}

public class Text {
    public static void main(String[] args) {
        OuterClass1 outerClass = new OuterClass1();
        OuterClass1.InnerClass1 innerClass1 = outerClass.new InnerClass1();
        innerClass1.func();
    }
}

2. 外部类访问非静态内部类:

    public void func1(){
        System.out.println("OuterClass1::func1");
        InnerClass1 innerClass1 = new InnerClass1();
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(innerClass1.d);
        System.out.println(innerClass1.e);
        System.out.println(innerClass1.f);
    }

2.2.4 当内外部类的成员变量名字相同时 

class OuterClass2{
    public int a = 4;
    class InnerClass2{
        public int a = 444444;
        public void func(){
            System.out.println(a);
        }
    }
}

调用 func 时会输出 444444

那如果非要输出外部类的 a ,该如何?

System.out.println(OuterClass2.this.a);

在非静态外部类中,包含两个 this,一个是自己的 this ,一个是代表外部类对象的引用,像上面代码写的,OuterClass2.this.a

2.3 局部内部类

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

class OutClass3{
    public void func(){
            class InnerClass3{
                public int a = 8;
                public void fun(){
                    System.out.println("hello!");
                }
        }
        InnerClass3 innerClass3 = new InnerClass3();
            innerClass3.fun();
    }
}
public class Text {
    public static void main(String[] args) {
        OutClass3 outClass3 = new OutClass3();
        outClass3.func();
    }
}

【注意事项】

1. 局部内部类只能在所定义的方法体内部使用

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

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

4. 几乎不会使用

2.4 匿名内部类

接口是不能实例化的,需要借助一个具体类,如:

interface IA{
    void func();
}

class AA implements IA{
    public void func(){
        System.out.println("hehehe");
    }
}

public class Text {
    public static void main(String[] args) {
        IA ia = new AA();
        ia.func();
    }
}

而匿名内部类可以实现跟 class AA 一样的功能:

    public static void main(String[] args) {
        new IA(){
            @Override
            public void func() {
                System.out.println("呜呜呜~");
            }
        };
    }

匿名内部类也意味着,这是一个实现了 IA 这个接口,并且重写了 func 方法的类。

那如何调用呢?很简单:

    public static void main(String[] args) {
        new IA(){
            @Override
            public void func() {
                System.out.println("呜呜呜~");
            }
        }.func();
    }

此时的匿名内部类是没有字节码文件的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值