聊聊java的各种内部类

一、成员内部类

public class OutClass {
    private int age = 1;
    private static int staticAge = 2;
    private static void test(){
        System.out.println("静态的test");
    }
    class Inner{
        public void show(){
            System.out.println(age); //1
        }
    }
    static class staticInner{
        public void show(){
            System.out.println(age); //报错
            System.out.println(staticAge); //2
            test();
        }
    }
 
    public static void main(String[] args) {
        OutClass.Inner oi = new OutClass().new Inner();
        oi.show();
        OutClass.staticInner os = new OutClass.staticInner();
        os.show();
    }
}

成员内部类就是跟成员变量在同一位置的类

可以调用外部类所有的成员变量和成员方法,包括private修饰的

创建对象的时候,分成员内部类是否是静态的,根据上图代码可以看出区别,被静态修饰后,只能调用外部类的静态成员变量和静态成员方法

如果使用private修饰内部类,那么就无法使用其他类创建对象的方式来访问内部类(上图代码中是在本类中的main方法,这块说的是其他类)

应用场景:可以给内部类添加一个public的get方法,比如说参数可以是用户的角色,如果是普通用户就返回null,如果是管理员账户就返回内部类对象 

class Outer {
      public int age = 18;    
      class Inner {
          public int age = 20;    
          public viod showAge() {
              int age  = 25;
              System.out.println(age);//25
              System.out.println(this.age);//20
              System.out.println(Outer.this.age);//18
          }
      }
  }
 

二、静态内部类

public class TestStatic {
    private String str  = "不是静态的";
    private static String str2 = "静态的";
 
    static class testStaticClass{
        private void show(){
            System.out.println("静态内部类的方法输出");
            System.out.println(str); //报错,编译不通过
            System.out.println(str2);//正常输出
        }
    }
 
    public static void main(String[] args) {
        TestStatic.testStaticClass tts = new TestStatic.testStaticClass();
        tts.show();
    }
}

static是不能修饰类的,但是成员内部类相当于是一个成员,所以可以使用static进行修饰,被static修饰的成员内部类被称为静态内部类

不能使用外部类的非静态的成员变量和成员方法

非静态的内部类编译后会默认保存一个指向外部类的引用,而静态类没有

即使没有外部类对象,也可以创建静态内部类对象,而外部类的非static成员必须依赖于对象的调用,静态成员则可以直接使用类调用,不必依赖于外部类的对象,所以静态内部类只能访问静态的外部属性和方法。其实还是static的本身原因,static为类变量,类方法,而非static的是对象的变量和对象的方法,类的内容在类初始化的时候就已经加载了,所以调用外部非static的时候会报错

三、局部内部类

public class TestJuBu {
 
    private String str = "成员变量";
    public void test(){
        String str2 = "局部变量";
        class InnerClass{
            public void show(){
                System.out.println("局部的show");
                System.out.println(str);
                System.out.println(str2);
            }
        }
        InnerClass in = new InnerClass();
        in.show();
    }
 
    public static void main(String[] args) {
        TestJuBu t = new TestJuBu();
        t.test();
    }
}

定义在成员方法内部,跟局部变量同级的类就是局部内部类,在方法内部进行调用

为什么局部内部类访问局部变量必须加final修饰呢?    --->    用final修饰实际上就是为了保护数据的一致性。

这块的局部变量并没有使用final修饰,这是jdk1.8之后的语法糖,使用反编译软件查看后,还是有final修饰符

jdk1.8之前,局部内部类使用的局部变量如果没有加final,是无法编译通过的,主要是为了数据的一致性。通过反编译软件可以看到,局部内部类中的局部变量实际上是通过构造方法传入的,如果不用final进行修饰,那么这个变量的引用是可以改变的,局部内部类引入的时候,只是引入了地址或者值赋值给了新的变量,外面的引用变化之后,内部类并不知道这个值发生了变化,就会出现问题。

四、匿名内部类

一个没有名字的类,是内部类的简化写法

本质:其实是继承该类或者实现接口的子类匿名对象

public class TestNiMing {
    private void test(){
        new Outer(){
            public void show(){
                System.out.println("匿名内部类输出");
            }
        }.show();
    }
 
    public static void main(String[] args) {
        TestNiMing t = new TestNiMing();
        t.test();
    }
}
 
 
interface Outer{
    public abstract void show();
}

如果有多个方法:

public class TestNiMing2 {
    private void test(){
        Outer2 o = new Outer2(){
            public void show(){
                System.out.println("匿名内部类输出");
            }
 
            public void show2(){
                System.out.println("第二个输出");
            }
        };
        o.show();
        o.show2();
    }
 
    public static void main(String[] args) {
        TestNiMing2 t = new TestNiMing2();
        t.test();
    }
}
 
 
interface Outer2{
    public abstract void show();
    public abstract void show2();
}

举例: 

public class MyDemo{
    public void test(Demo demo){
        demo.demoMethod();
        System.out.println("test method");
    }
 
    public static void main(String[] args) {
        MyDemo md = new MyDemo();
        //这里我们使用匿名内部类的方式将接口对象作为参数传递到test方法中去了
        md.test(new Demo(){
            public void demoMethod(){
                System.out.println("具体实现接口");
            }
        });
    }
}
 
interface Demo {
    void demoMethod();
}

输出为:

具体实现接口
test method

参考链接: java中的各种内部类_aaa948771854的博客-CSDN博客 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值