【JavaSE】内部类讲解

目录

一、什么是内部类

二、内部类简单介绍

三、实例内部类

 (1)实例内部类的成员变量和方法的构建

 (2)实例内部类在类外创建

 (3)在内部类访问外部类的成员变量

 (4)总结 ​编辑

四、静态内部类

 (1)静态内部类的成员变量和方法的构建

 (2)静态内部类在实外创建

 (3)在静态内部类中访问外部类成员变量

 (4)总结

五、局部内部类

六、匿名内部类        

 (1)静态内部类在实外创建 

 (2)匿名内部类的成员变量和方法的构建

 (3)匿名内部类访问外部类的成员变量和局部变量

 (4)总结


一、什么是内部类

        一个类在另一个类的内部,这个就叫内部类。

        如下图,InnerClass 类就是内部类,而 OuterClass 类就叫外部类

二、内部类简单介绍

  在Java中,可以将一个类定义在另一个类或者一个方法的内部,前者为内部类,后者为外部类。

内部类是封装的一种体现

 创建内部类时,我们要明确两点:

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

class OuterClass{
    class InnerClass{

    }
}
public class Demo3 {
}

OuterClass 和 Demo3 彼此互相独立,不能为对方的内部类

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

内部类生成的字节码文件名:外部类$内部类.class

同时,内部类类型可以分为四种,分别为 实例内部类、静态内部类、本地内部类 (了解)、匿名内部类   ​​​​​,下面我将依依为大家介绍。

三、实例内部类

实例内部类是内部类中比较普通的,如下类型就是实例内部类

class Out{
    //实例内部类
    class Inner{
        
    }
}

 (1)实例内部类的成员变量和方法的构建

跟普通类的一样,实例内部类也能构建自己的成员变量和方法(包括构造方法)

class Out{

    class Inner{
        public int data2 = 3;
        private int data3 = 4;

        public void Inner(){
            System.out.println("实例内部类的构造方法");
        }

        public void InnerFunc(){
            System.out.println("实例内部类的普通方法");
        }
    }
}

需要注意: 

      ① 在实例内部类中,不能构建静态的成员变量,要想构建静态的成员变量,必须加 final 

    

      ② 在实例内部类中,不能构建静态的成员方法,就算加 final 也不行!!

 (2)实例内部类在类外创建

 由于内部类的特殊性,不能用类名实例化对象!!必须要借助外部类的实例化对象辅助,如下

外部类.内部类 变量名 = 外部类实例.new 内部类;
class Out{
    class Inner{
        public int data2 = 3;
        
        public void Inner(){
            System.out.println("实例内部类的构造方法");
        }
        public void InnerFunc(){
            System.out.println("实例内部类的普通方法");
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Out out = new Out();
        Out.Inner inner = out.new Inner();
        //也可以写为 Out.Inner inner = new Out().new Inner();
        inner.InnerFunc();
        System.out.println(inner.data2);
    }
}

为什么要借助外部类对象才能实例化内部类?

   我们可以把内部类Inner 当成外部类 Out 的一个实例成员,实例成员的调用都是依赖对象的。这也就是为啥要有 外部类对象才能获取 实例内部类的原因。

 注意:

      在外部类的方法中,能直接用内部类实例化成员变量,不必再借用外部类的实例化对象

class Out{
    class Inner{
        public void Inner(){
            System.out.println("实例内部类的构造方法");
        }
        public void InnerFunc(){
            System.out.println("实例内部类的普通成员方法");
        }
    }
    
    // 外部类 的成员方法 
    public void Func(){
        Inner inner = new Inner();
        inner.InnerFunc();
    }
}

 (3)在内部类访问外部类的成员变量

在内部类中可以访问外部类的成员变量

例如:

class Out{
    public int data1 = 1;
    private int data2 = 2;

    class Inner{
        public int data3 = 3;
        private int data4 = 4;

        public void InnerFunc(){
            System.out.println(data1);
            System.out.println(data2);
            System.out.println(data3);
            System.out.println(data4);
        }
    }
}

        

在内部类中访问外部类的成员变量都几条规则需要大家掌握:

      ① 当实例内部类的成员变量跟外部类的成员变量同名时,按就近原则访问

class Out{
    public int data1 = 1;

    class Inner{
        public int data1 = 11;

        public void InnerFunc(){
            System.out.println(data1);
        }
    }
}

 

       ② 访问同名的外部类成员变量 需要外部类名+this才能访问  Out.this.data1

class Out{
    public int data1 = 1;

    class Inner{
        public int data1 = 11;

        public void InnerFunc(){
            System.out.println(data1);
            System.out.println("外部类的data1:"+Out.this.data1);
        }
    }
}

       ③ 访问静态同名的外部类成员变量 需要外部类 才能访问 Out.data2

class Out{
    public int data1 = 1;
    public static int data2 = 2;

    class Inner{
        public int data1 = 11;
        public static final int data2 = 22;
        public void InnerFunc(){
            System.out.println(data2);
            System.out.println("外部类的data2:"+Out.data2);
        }
    }
}

 

 (4)总结 

四、静态内部类

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

class Out{
    //静态内部类
    static class Inner{
        
    }
}

(1)静态内部类的成员变量和方法的构建

跟实例内部类类似,静态内部类也可以创建成员变量和方法,唯一不同的是,静态内部类可以创建静态的方法静态的成员变量!!

静态内部类中的静态成员变量可以不被 final 修饰

class Out{
    //静态内部类
    static class Inner{
        public int data1 = 1;
        private int data2 = 2;
        public static int data3 = 3;
        
        public void Inner(){
            System.out.println("静态内部类的构造方法");
        }
        
        public void func1(){
            System.out.println("静态内部类的普通方法");
        }
        public static void func2(){
            System.out.println("静态内部类的静态方法");
        }
    }
}

(2)静态内部类在实外创建

 由于静态内部类是静态的,不依赖与外部类实例化对象,所以实例化就不需要创建外部类对象!!

外部类.内部类 变量名 = new 外部类.内部类;
class Out{
    //静态内部类
    static class Inner{
        
        public void Inner(){
            System.out.println("静态内部类的构造方法");
        }

        public void func1(){
            System.out.println("静态内部类的普通方法");
        }
        public static void func2(){
            System.out.println("静态内部类的静态方法");
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Out.Inner inner = new Out.Inner();
        inner.func1();
    }
}

 注意:在外部类中,实例化静态内部类也是直接用类名实例化!

(3)在静态内部类中访问外部类成员变量

 注意:在静态内部类中不能直接方法外部类中非静态的成员变量

class Out{
    public int data1 = 1;
    private int data2 = 2;
    public static int data3 = 3;
    //静态内部类
    static class Inner{
        public int data4 = 4;
        private int data5 = 5;
        public static int data6 = 6;
        public void Inner(){
            System.out.println("静态内部类的构造方法");
        }
        public void func1(){
            System.out.println("静态内部类的普通方法");
            System.out.println("外部类中静态成员变量 data3:"+data3);
            System.out.println(data4);
            System.out.println(data5);
            System.out.println(data6);
        }
    }
}

       ① 在静态内部类中访问外部类非静态的成员变量

    因为静态内部类是静态的,不依赖于外部类对象,所以我们要想在静态内部类中访问,就要构建一个外部类对象。

class Out{
    public int data1 = 1;
    private int data2 = 2;
    public static int data3 = 3;
    //静态内部类
    static class Inner{
        public void Inner(){
            System.out.println("静态内部类的构造方法");
        }
        public void func1(){
            Out out = new Out();
            System.out.println("外部类非静态成员变量 data1:"+out.data1);
            System.out.println("外部类非静态成员变量 data2:"+out.data2);
        }
    }
}

 (4)总结

五、局部内部类

局部内部类是在方法内部定义的内部类

public class Demo3 {
    public void Func(){
        /**
         * 局部内部类
         * 不能被 public static 修饰
         */
        class Inner{

        }
    }
    public static void main(String[] args) {
    }
}

注意:

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

      ② 不能被public、static等修饰符修饰

      ③ 因为局部内部类局限性很大,所以平时很少用   

六、匿名内部类        

        匿名类是一个没有类名的特殊内部类,也叫匿名内部类,适合于只使用一次的类。创建匿名内部类是须继承一个已有的父类或则实现一个接口

new 父类名/接口名(){
    //类体
};

(1)静态内部类在实外创建 

        因为匿名内部类既是一个类的定义,同时它本身也是一个对象,在类外创建是可以使用该继承的父类名或实现的接口名接收!

父类名/接口名 变量名 = new 父类名/接口名(){
    //类体
};

      ① 继承父类实现内部类

匿名内部类继承的父类可以是 普通类 也可以是 抽象类!

class B{
    public void func2(){

    };
}

abstract class C{
    abstract void func3();
}
public class Demo1 {
    public static void main(String[] args) {
       B b = new B(){
         public void func2(){
             System.out.println("继承普通类的匿名内部类"); 
         };
       };
       
        C c = new C() {
            @Override
            void func3() {
                System.out.println("继承抽象的匿名内部类");
            }
        };
        
        b.func2();
        c.func3();
    }
}

      ② 实现接口创建内部类

interface A{
    public abstract void func1();
}

public class Demo1 {
    public static void main(String[] args) {
        A a = new A() {
            @Override
            public void func1() {
                System.out.println("实现接口的匿名内部类");
            }
        };
        a.func1();
    }
}

         这里创建内部类的过程类似于,一个类实现了A接口,这不过这个类是没有名字的。

 (2)匿名内部类的成员变量和方法的构建

       匿名内部类由于本身没有名字,所以就不存在构造方法,同时也不能包含静态的成员!!但是普通的成员直接可以创建

A a = new A() {
            public int data1 = 1;
            @Override
            public void func1() {
                System.out.println("实现接口的匿名内部类");
            }

            public void func2(){
                System.out.println("匿名内部类的普通方法");
            }
        };

 注意:匿名内部类中可以有许多方法,但是在类外只能调用重写的方法!!

简而言之就是,与 继承的父类 或 实现的接口中方法 同名的,匿名内部类才能调用

 (3)匿名内部类访问外部类的成员变量和局部变量

  在匿名内部类中,可以直接访问外部类的静态成员变量和局部变量!

  非静态成员变量需要构建外部类实例才能访问

interface A{
    void func();
}
public class Out {
    public static int data1 = 1;
    public int data2 = 2;
    private int data3 = 3;
    public static void main(String[] args) {
        String name ="威威";
        A a = new A() {
           @Override
           public void func() {
               System.out.println(name);
               System.out.println(data1);
               
               Out out = new Out();
               System.out.println(out.data2);
               System.out.println(out.data3);
           }
       };
       a.func();
    }
}

 注意:外部其他类不能访问匿名内部类,因为匿名内部类实际上就是一个局部变量!!

 (4)总结

以上就是内部类的讲解,有错误的地方希望大家能批评指正,别忘了点赞👍+收藏⭐️哦 

      😜  关注我!带来等多精彩🎉🎉

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱躺平的威威

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

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

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

打赏作者

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

抵扣说明:

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

余额充值