一文读懂JAVA内部类

一个简单的内部类

public class OuterClazz {

    class InnerClazz{//inner class
        
    }
}
为什么要使用内部类
  • 提供一种方法把只在一个地方用的类逻辑分组
  • 增强封装(可以理解一种类似“多重继承”)
  • 容易维护

为什么说内部类可以实现类似的多重继承,Java是不需要class多重继承的,

想要实现类似多重继承的效果可以用内部类,比如Class B 已经继承了Class C 就没有办法继承Class A,

但是把B设计成A的内部类,就可以访问A的内部变量和方法了,就像是也继承了A。

public class ClazzA {

    private int age = 0;
    public void printFromA(){
        System.out.println("The age in ClazzA is "+age);
    }
    //ClazzB 可以直接调用ClazzA的方法和访问它的变量,
    class ClazzB extends ClazzC{//inner class
        public void print() {
            age++;
            printFromA();
        }
    }
    public static void main(String[] args) {
        ClazzB clazzB = new ClazzA().new ClazzB();
        clazzB.print();
    }
}

class ClazzC{
    
}

执行结果:

The age in ClazzA is 1

几种内部类

  1. 静态内部类
  2. 成员内部类
  3. 方法内部类(局部内部类)
  4. 匿名内部类
静态内部类

静态内部类是定义在另一个类里面用 static 修饰 class 的类,静态内部类不需要依赖于外部类(与类的静态成员属性类似)且无法使用其外部类的非 static 属性或方法(因为在没有外部类对象的情况下可以直接创建静态内部类的对象,如果允许访问外部类的非 static 属性或者方法就会产生矛盾)。

如果想访问外部类的变量和方法只能通过外部类的实例。

public class OuterClazz {

    private int age = 0;
    private static int intAge = 10;
    public void printAge(){
        System.out.println("The age in ClazzA is "+age);
    }
    
    //ClazzB 可以直接调用ClazzA的方法和访问它的变量,
    static class ClazzB {//inner class
        public void print() {
            System.out.println("The int age in Out class is "+intAge);
            OuterClazz outerClazz = new OuterClazz();
            outerClazz.age++;
            outerClazz.printAge();
        }
    }
    public static void main(String[] args) {
        ClazzB clazzB =  new OuterClazz.  ClazzB();
        clazzB.print();
    }
}

执行结果:

The int age in Out class is 10
The age in ClazzA is 1
成员内部类

成员内部类是没有用 static 修饰且定义在在外部类类体中的类,是最普通的内部类,可以看做是外部类的成员,可以无条件访问外部类的所有成员属性和成员方法(包括 private 成员和静态成员),而外部类无法直接访问成员内部类的成员和属性,要想访问必须得先创建一个成员内部类的对象然后通过指向这个对象的引用来访问;当成员内部类拥有和外部类同名的成员变量或者方法时会发生隐藏现象(即默认情况下访问的是成员内部类的成员,如果要访问外部类的同名成员需要通过 OutClass.this.XXX 形式访问);成员内部类的 class 前面可以有 private 等修饰符存在。

public class OuterClazz {

    private int age = 0;
    private static int intAge = 10;
    public void printAge(){
        System.out.println("The age in ClazzA is "+age);
    }
    
    //ClazzB 可以直接调用ClazzA的方法和访问它的变量,
     class ClazzB {//inner class
        public void print() {
            System.out.println("The int age in Out class is "+intAge);
            age++;
            printAge();
        }
    }
    public static void main(String[] args) {
        ClazzB clazzB =  new OuterClazz(). new  ClazzB();
        clazzB.print();
    }
}

执行结果和静态内部类相同。

方法内部类

方法内部类(局部内部类)是定义在一个方法里面的类,和成员内部类的区别在于方法内部类的访问仅限于方法内;方法内部类就像是方法里面的一个局部变量一样,所以其类 class 前面是不能有 public、protected、private、static 修饰符的,也不可以在此方法外对其实例化使用。

public class LocalClazz {

    public static void testLocalClazz() {
        int age =10;
        class InnerClazz {
            public void pringAge() {
                //age++; //Error: Local variable age defined in an enclosing scope must be final or effectively final
                System.out.println("this age is "+age);
            }
        }
        InnerClazz innerClazz = new InnerClazz();
        innerClazz.pringAge();
    }

    public static void main(String[] args) {
        testLocalClazz();
    }
}
匿名内部类

匿名内部类是一种没有构造器的类(实质是继承类或实现接口的子类匿名对象),由于没有构造器所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调,匿名内部类在编译的时候由系统自动起名为 OutClass$1.class,一般匿名内部类用于继承其他类或实现接口且不需要增加额外方法的场景(只是对继承方法的实现或是重写);匿名内部类的 class 前面不能有 pravite 等修饰符和 static 修饰符;匿名内部类访问外部类的成员属性时外部类的成员属性需要添加 final 修饰(1.8 开始可以不用)。

public class AnonymousInnerClazz {
    private Animal animal = new Animal() {
        
        @Override
        public void eat() {
            System.out.println("eat, eat, eat!");
            
        }
    };
    public static void main(String[] args) {
        new AnonymousInnerClazz().animal.eat();
    }
    

}
interface Animal{
    public void eat();
}

执行结果:

eat, eat, eat!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值