Java内部类到底是什么

什么是内部类?

内部类是定义在另一个类中的类,就是该类的定义定义在另一个类中。广义上将内部类分为四种:成员内部类、局部(方法)内部类、静态内部类、匿名内部类。

//外部类(相对内部而言)
public class Outer {
    //内部类
    class Inner{
        //code
    }
}

为什么使用内部类

  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据
  • 内部类可以对同一个包中的其他类隐藏起来
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷
  • 可以借助内部类继承从而实现类的多继承

内部类优点

  1. 内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
  2. 内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
  3. 内部类提供了更好的封装,除了该外围类,其他类都不能访问。
  4. 创建内部类对象的时刻并不依赖于外围类对象的创建。

在使用内部类时,编译器会吧内部类翻译成$用以分割外部类名和内部类名的常规类文件,与虚拟机无关

内部类的特殊语法规则

内部类中声明的所有静态域都必须是final,同时,内部类引用的外部成员一般也是用final修饰
原因:对于每个外部对象,会分别有一个单独的内部类实例,我们希望一个静态域只有一个实例,如果这个域不是final的,那他可能就不是唯一

成员内部类

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

class Circle {
    double radius = 0;
     
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println("drawshape");
        }
    }
}

局部内部类

  • 局部内部类可以直接访问外部类的成员。
  • 局部内部类在局部位置可以创建内部类对象,通过内部类对象调用内部类方法,来使用局部内部类功能。
  • 局部内部类访问局部变量,局部变量必须加final修饰。为什么呢?
    因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,局部对象还要使用这个局部变量。为了让数据还能继续被使用,就用fianl修饰局部变量,
  • 局部类不能用public或private访问修饰符进行声明,他的作用域被限定在声明的这个局部类块中,下面栗子中除了method方法外,没有任何方法知道该内部类Inner的存在
//外部类(相对内部而言)
public class Outer {
    private int num = 10;
    public void method(){
        final int num2 = 20;//局部类使用final修饰
        //内部类
        class Inner{
            public void show(){
                System.out.println(num);
                System.out.println(num2);
            }
        }
        //局部内部类可以直接访问外部类成员
        Inner i = new Inner();
        i.show();
    }
}
class TestInner{
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();//10 20
    }
}

匿名内部类

在只需创建这个类的一个对象时,就不需要命名,称为匿名内部类
使用最多的场景是在Frame中加入Listener

public class QFrame extends Frame {    
     public QFrame() {    
            this.setTitle(\"my application\");    
   
            addWindowListener(new WindowAdapter() {    
                    public void windowClosing(WindowEvent e) {    
                    dispose();   
                    System.exit(0);    
				 }   
             });    
           this.setBounds(10,10,200,200);    
      }   
 }   

其他栗子

//外部类(相对内部而言)
public class Outer {
    public void method(){
        System.out.println("1");
    }
    public static void main(String[] args) {
       new Outer().method();
       //匿名内部类
       new Outer(){
           public void method(){
               System.out.println("111");
           }
       }.method();
    }
}

一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

静态内部类

有时候使用内部类是为了将一个类隐藏在另一个类中,并不需要内部类的引用外围类对象,可以使用static,取消产生的引用

//外部类(相对内部而言)
public class Outer {
    public Outer(){
        System.out.println("Outer");
    }
    //静态内部类
    static class Inner{
        public Inner(){
            System.out.println("Inner");
        }
    }
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();//Inner
    }
}

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值