Java内部类,看这一篇就够了!

闻道梅花坼晓风

雪堆遍满四山中


目录

 内部类的概念

成员内部类

内部类访问外部类

外部类访问内部类

内部类中同名变量的优先级

小结:

静态内部类

内部类访问外部类

 小结:

局部内部类

小结:

匿名内部类

 

 内部类的概念

在 Java 中,我们通常将不同的类组织到一个包下,对于一个包中的类来说,它们是同一个层次,可以说在没有使用继承等条件下,类与类之间是没有联系的。还有一种类,它是定义在另一个类或者一个方法的内部,这样的类叫做内部类。内部类也是封装的一种体现 ~ 

//A是外部类
class A{
    //B是内部类
    class B{
        
    }
}

注意: 

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

一般来说,内部类分为成员内部类、局部内部类、匿名内部类和静态内部类

成员内部类

成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

//外部类
class A{
    public int a = 10;
    private int b = 20;
    static int c = 30;
    //内部类
    class B{ 
        public int d = 10;
    }

}

看起来 内部类 B 就好像 A 的一个成员,成员内部类可以无限制访问外部类的所有成员属性

 

内部类访问外部类

//外部类
class A{
    public int a = 10;
    private int b = 20;
    static int c = 30;

    public void PrintA(){
        System.out.println("PrintA()");
    }
    //内部类
    class B{
        public int d = 10;
        void PrintB(){
            System.out.println("a = "+a);
            System.out.println("b = "+b);
            System.out.println("c = "+c);
            PrintA();
        }
    }
}

class Test{
    public static void main(String[] args) {
        A a = new A();
        A.B b= a.new B();
        b.PrintB();
    }
}

注意:我们要初始化内部类的对象时,必须先初始化外部类的对象,因为内部类是依附于外部类的

不然编译器就会报错

下面这段代码的意思是:先创建 外部类A 的对象a ,再 [.] 符号引用外部类中 内部类B 的成员,最后在初始化内部类 B

        A a = new A();
        A.B b= a.new B();

 

外部类访问内部类

虽然内部类访问可以随意的访问外部类,但是外部类想要访问内部类可就没那么容易了

我们发现外部类想要访问内部类是不能直接访问的,那该怎么访问呢?---  可以先创建一个成员内部类的对象,再通过这个对象来访问:

//外部类
class A{
    public int a = 10;
    private int b = 20;
    static int c = 30;

    public void PrintA(){
        System.out.println("PrintA()");
    }
    
    public void PrintA_B(){
        B b = new B();
        System.out.println(b.d);
        System.out.println("-------------");
        b.PrintB();
    }
    
    //内部类
    class B{
        public int d = 10;
        void PrintB(){
            System.out.println("a = "+a);
            System.out.println("b = "+b);
            System.out.println("c = "+c);
            PrintA();
        }

    }
}

class Test{
    public static void main(String[] args) {
        A a = new A();
        A.B b= a.new B();
        a.PrintA_B();
    }
}

 

内部类中同名变量的优先级

如果外部类与内部类相同的属性,如下图中的 a,那么我们调用 PrintB 时访问的是哪个 a 呢?

class A{
    public int a = 10;
    class B{
        public int a = 40;
        void PrintB(){
            System.out.println("a = "+a);
        }
    }
}

class Test{
    public static void main(String[] args) {
        A a = new A();
        A.B b= a.new B();
        b.PrintB();
    }
}

所以:如果是同名变量,优先访问内部类中的

问:要是这种情况,该怎么访问外部类中的 a 呢?
 

System.out.println("a = "+ A.this.a);

PrintB 在内部类B中 ,所以 this.a = 当前 内部类B 对象的 this 引用,A.this.a = 外部类A 的 this 引用

这种创建内部类的方式在实际开发中并不常用,因为内部类和外部类紧紧地绑定在一起,使用起来非常不便

小结:

外部类中的任何成员都可以在实例内部类方法中直接访问
实例内部类对象必须在先有外部类对象前提下才能创建
实例内部类的非静态方法中包含了一个指向外部类对象的引用
外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象

 

静态内部类

静态内部类其实就是在原来的内部类的基础上用 “static” 修饰,你看不要小看这个 static,加上后还是有不小的改变的

内部类访问外部类

以上面的代码为例,我们直接给内部类加上 static 修饰后:就不能只能访问外部类非静态成员,原因是静态的 内部类B 没有 外部类A 的 this 引用,那么有没有什么访问的方法呢?

-- 还是与之前一样,创建一个外部类对象,再进行调用

class A{
    public int a = 10;
    private int b = 20;
    static int c = 30;

    public void PrintA(){
        System.out.println("PrintA()");
    }

    static class B{
        public int d = 40;
        void PrintB(){
            A a1 = new A();
            System.out.println("a = "+a1.a);
            System.out.println("b = "+a1.b);
            System.out.println("c = "+c);
            System.out.println("d = "+d);
            a1.PrintA();
        }
    }
}

class Test{
    public static void main(String[] args) {
     A.B b = new A.B();
     b.PrintB();
    }
}

     A.B b = new A.B();

生成静态的内部类的时候,不需要外部类的引用,也就是说:我们可以不用先初始化外部类

 小结:

在静态内部类中只能访问外部类中的静态成员
创建静态内部类对象时,不需要先创建外部类对象

局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,所以局部内部类的生命周期仅限于作用域内

class A {
    public int a = 0;

    public void PrintA(){
        class B {
            public int b;
        }

    }
}

注意,局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的

class A {
    public int a = 10;

    public void PrintA(){
        class B {
            public int b = 20;
            public void PrintB(){
                System.out.println("a = "+a);
                System.out.println("b = "+b);
            }
        }
        B b = new B();
        b.PrintB();
    }
}

class Test {
    public static void main(String[] args) {
       A a = new A();
       a.PrintA();
    }
}

切记 ~ 局部内部类只能在当前方法内部使用,出了该方法则不能被使用

小结:

局部内部类只能在所定义的方法体内部使用
不能被 public、protected、private 以及 static 修饰符修饰
编译器也有自己独立的字节码文件,命名格式:外部类名字$数字内部类名字 .class

匿名内部类

匿名内部类应该是平时我们编写代码时用得最多的,尤其是启动多线程的时候,会经常用到,并且 IDEA 也会帮我们自动生成。

 匿名对象一般运用于接口中,请看下面这段代码:

interface A{
    void Test();
}

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

 

这里相当于一个类实现了这个 A接口 同时重写了 Test() 方法,但是你不知道这个类叫什么,所以这就是匿名对象

[.Test()] 是一种调用方式

匿名内部类的作用主要是用来继承其他类或者实现接口,并不需要增加额外的方法,方便对继承的方法进行实现或者重写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烟雨长虹,孤鹜齐飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值