内部类的四种形式

目录

成员内部类

静态内部类

局部内部类

匿名内部类


在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。内部类本身就是类的一个属性,与其他属性定义方式一致。

根据内部类的位置可以分为:

成员内部类

public class Demo {
     
      private int i = 1;
 

      class Inner{
       
          public void show(){
              System.out.println(i);
          }
      }

}

 那该如何访问内部类方法呢?

在访问类中的方法 ,一般是new 一个对象,通过对象.方法();但这里发现会编译报错。因为内部类外面还有一个外部类,那我们来大胆假设一下,是否可以通过外部类对象.内部类对象来获取到内部对象的引用在调用方法

外部类.内部类 变量a= new 外部类(). new 内部类();

public class Test {
    public static void main(String[] args) {
        Demo.Inner inner = new Demo().new Inner();
        inner.show();
    }

}

静态内部类

既然有成员内部类,那在假设修饰符static就可以有静态内部类

public class Demo {
      private int i = 1;
      private static  String str = "你好中国";

        static   class StaticInner{
              public void hello(){
                  System.out.println(str);
              }
          }
}

那该如何调用静态内部类方法呢? 外部类名.静态内部类类名 = new 外部类.静态内部类()

 在编写测试类

public class Test {
    public static void main(String[] args) {
        Demo.StaticInner inner = new Demo.StaticInner();
        inner.hello();
    }

}

注意:静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量 

局部内部类

顾名思义就是在外部类的方法中

public class Demo {
      private int i = 1;
    public void method(){
        class Inner{
            public  void show(){
                System.out.println(i);
            }
        }
    }
}

先编写测试类,看看是否能调用到局部内部类方法

public class Test {
    public static void main(String[] args) {
       Demo demo = new Demo();
       demo.method();
    }

}

编译不报错,但允许没有打印出成员变量i的值。那我们想一下,这里只是在调用了Demo对象的方法,并没有调用到内部类的方法,而且内部类的对象也并没有创建。

既然都申明了内部类,那我们大胆尝试一下通过直接new 内部类创建对象,最后得到如下代码

    public void method(){
        class Inner{
            public  void show(){
                System.out.println(i);
            }
        }
        Inner i = new Inner();
        i.show();
    }

发现编译通过,在修改测试类的调用方式,如下,最终调用成功

public class Test {
    public static void main(String[] args) {
       Demo demo = new Demo();
        demo.method();
    }

}

匿名内部类

 它是属于局部内部类的一种特殊形式,它有一下特点

  1.  没有名字
  2. 必须继承一个抽象类或者实现一个接口
  3. 它连类名都没有,就不能通过类名.静态成员/静态方法

根据它的规则我们先创建一个接口

public interface Inter {
    void show();
}

 然后在编写一个外部类,根据之前写过的2中内部类形式,可以大胆猜测一下匿名内部类的写法

public class Demo {
      private int i = 1;


    public void test (){

        new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类");
            }
        };
    }

}

通过测试类发现并没有打印输出 

public class Test {
    public static void main(String[] args) {
       Demo demo = new Demo();
        demo.test();
    }

}

到底什么地方出问题了呢??? 我们一定要清醒的记住,内部类只是一个类,并没有通过对象调用方法。而匿名内部类这里已经使用new关键字,那我们大胆假设在定义的匿名内部类通过.show() 看是否可行。最后发现可以调用到匿名内部类的方法

public class Demo {
      private int i = 1;


    public void test (){

        new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类");
            }
        }.show(); //直接调用方法
    }
}

 在执行测试类,发现成功打印。

这里要说明一点,内部类不会因为外面的类或者方法销毁而销毁。 比如上面的调用了Demo对象的test() 方法,并不会因为test()结束,内部类Inter也一定会跟着销毁。

匿名内部类还有以下特点:

  • 匿名内部类必须继承一个抽象类或者实现一个接口。
  • 匿名内部类不能定义任何静态成员和静态方法。
  • (局部内部类和匿名内部类)当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。为什么要加final呢?是因为生命周期不一致, 局部变量存储在jvm栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错。加了final,可以确保局部内部类使用的变量与外层的局部变量区分开
  • 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值