Java中的四种内部类

目录

局部内部类

匿名内部类(重点!!!!!)

成员内部类

静态内部类

总结


在学习Java中的内部类之前,需要先搞清楚:外部其它类,外部类,内部类之间的关 系:

  内部类就是定义在类的内部的类;外部类指包含有内部类的类;外部其它类是针对包含InnerClass类的OuterClass之外的类。

内部类可以分为两大类,四小类:

  • 定义在外部类的局部位置上的:局部内部类、匿名内部类
  • 定义在外部类的成员位置上的:成员内部类和静态内部类

局部内部类

局部内部类是指定义在外部类的局部位置(通常是方法,还包括代码块)内的有名称的类。

局部内部类的使用需要注意:

  • 局部内部类可以直接访问外部类的所有属性和方法,包括私有的。局部内部类本质上一个类
  • 局部内部类不能添加访问修饰符,因为它的地位就是一个局部变量,但是可以使用final修饰符
  • 局部内部类的作用域只在方法内或者代码块内
  • 外部类在包含该内部类的方法中,可以创建局部内部类对象,然后调用该局部内部类的方法
  • 外部类和局部内部类重名时,访问遵循就近原则。如果在局部内部类中访问外部类中的变量,可以使用"外部类名.this.属性"(外部类名.this指的是外部类对象)

局部内部类的实例:

//外部类
class Outer {
    private int money = 14000;
    private void m1() {
        System.out.println("Outer m1()");
    }
    public void m2() {
        //局部内部类
        final class Inner {
            private int money = 12000;
            public void m3() {
                System.out.println("Inner m3()");
                System.out.println("Outer" + Outer.this.money + "   Inner" + money);
                m1();
            }
        }
        Inner in = new Inner();//在方法中创建了一个Inner对象
        in.m3();
    }
}
//外部其它类
public class InnerClassOfPart {
    public static void main(String[] args) {
        /*
        创建一个Outer对象,访问m2方法,在m2方法的颞部创建了一个局部
        内部类,调用该局部内类的m3()方法,该局部内部类的m3()方法中又调用了外部类中的私有成员变量
        money和成员方法m1
         */
        Outer out = new Outer();
        out.m2();
    }
}

匿名内部类(重点!!!!!)

匿名内部类和局部内部类类似,使用匿名内部类需要注意:

  • 不能添加访问修饰限定符,因为他是一个局部变量
  • 匿名内部类的作用域为定义它的方法内部或者代码块内部
  • 外部其它类不能访问匿名内部类,因为匿名内部类的地位是一个局部变量
  • 在匿名内部类中可以直接访问外部类的所有成员,访问方法使用"外部类名.this.成员"
  • 匿名内部类的使用应该注意语法,匿名内部类既是一个类的定义,同时本身也是一个对对象的引用;因此既有定义类的特征,也有创建对象的特征

假设现在有一个接口IBell,在接口的内部有一个ring()方法,在开发的过程中需要用这个接口中的ring方法在屏幕中输出"该上课了",那么传统的方法是再定义一个类来实现这个接口,然后覆写该抽象方法。这种做法当然可行,但是如果每次输出的内容都不同,就需要每次都使用不同的类来实现接口,覆写方法吗?匿名内部类的出现就解决了这个问题。

基于接口的匿名内部类定义和使用:

interface IBell {
    void ring();//默认为public abstract void ring()

}
class Cellphone {
    public void alarmclock(IBell bell) {
        bell.ring();
    }
}
public class InnerClassExercise02 {
    public static void main(String[] args) {
        Cellphone cellphone = new Cellphone();
        //使用基于接口的匿名内部类
        cellphone.alarmclock(new IBell() {
            @Override
            public void ring() {
                System.out.println("懒猪起床了");
            }
        });
        cellphone.alarmclock(new IBell() {
            @Override
            public void ring() {
                System.out.println("小伙伴上课了");
            }
        });
    }
}

在上述基于接口的匿名对象类的使用过程中,调用Cellphone类中的alarmclock方法传入的实参即为匿名内部类,对于该种使用方法,在底层其实创建了一个名为InnerClassExercise02$1的实体类,并且在该类实现了接口,覆写了接口中的ring()方法。

class InnerClassExercise02$1 implements IRing {
    @Override
    public void ring() {
        System.out.println("上课了!");
    }
}

在这个过程中发生的调用关系为:

基于类的匿名内部类定义和使用:

假如说现在有一个Stu类和一个Certificate类,Stu类的内部含有一个属性male默认为male,有一个f2方法。Certificate类里的含有一个输出证书奖项名称的print方法。但是这时候学生的群体中有一个学生获得了省级一等奖,另一个学生获得了省级二等奖,而其他同学获得的都是省级三等奖。这个时候需要输出获得省级一等奖、二等奖的这两个学生的奖项,按照传统的方法,就是在分别定义两个类继承Cretificate并且覆写print()方法,这样会显得很繁琐。使用基于类的匿名内部类可以解决这个问题,如下:

class Stu {
    private String male = "male";

    public void f1() {
        System.out.println("我是f1");
    }

    public void f2() {
        //anonymous类的使用
        new Certificate() {
            @Override
            public void print() {
                System.out.println("XXX省级二等奖");
//                System.out.println(Stu.this.male);匿名内部类中可以直接访问外部类中的所有成员
            }
        }.print();
        //匿名类的使用
        Certificate certificate = new Certificate() {
            @Override
            public void print() {
                System.out.println("XXX省级一等奖");
            }
        };
        certificate.print();//调用的是匿名类中覆写过的方法
    }
}

class Certificate {

    public void print() {
        System.out.println("XXX省级三等奖");
    }
}

public class AnonymousInnerClass {
    public static void main(String[] args) {
        Stu stu = new Stu();
        stu.f2();
    }
}
//输出:
//XXX省级二等奖
//XXX省级一等奖

在上述基于类的匿名对象类的使用过程中,实际上在底层创建了一个名为Stu$2的继承自Certificate的类并且覆写了父类中的print方法:

class Stu$2 extends Certificate {
    @Override
    public void print() {
        System.out.println("XXX省级X等奖");
    }
}

在这个过程中发生的调用关系为:

成员内部类

成员内部类是指定义在外部类的成员位置山的类。本质上是一个成员,具有成员的属性,因此使用成员内部类需要注意:

  • 成员内部类可以直接访问内部类的所有成员
  • 成员内部类的作用域为外部类内
  • 成员内部类可以添加任意一种访问修饰限定符,因为它本质上是作为一个成员存在
  • 外部类实例化成员内部类有两种方法:
    ①先实例化外部类成员变量,再实例化成员内部类
    ②在外部类中提供getInstance返回成员内部类的实例
class Dog {
    private int age = 6;
    private String name = "huahua";

    //定义成员内部类
    public class DogOfJack {
        int gg;
        public void print() {
            System.out.println("Jack's Dog " + Dog.this.name +" 的内部类");
        }
    }
    public void f1() {
        new DogOfJack().print();
    }
    public DogOfJack getInstance() {
        return new DogOfJack();
    }
}

public class MemberInnerClass {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Dog.DogOfJack dogOfJack1 = new Dog().new DogOfJack();
        dogOfJack1.print();
        Dog.DogOfJack dogOfJack2 = dog.getInstance();
        dogOfJack2.print();
    }
}

静态内部类

静态内部类与成员内部类相似,不过被static关键字修饰。但是其本质还是作为一个成员存在,使用静态内部类的注意事项:

  • 在静态内部类中只能访问外部类中的静态变量,因为其本身被static关键字修饰
  • 作为成员,静态内部类可以添加任意的访问修饰限定符
  • 外部其它类实例化静态内部类:使用类名.属性实例化静态内部类
class Dog {
    private static int age = 6;
    private String name = "huahua";

    //定义成员内部类
    static public class DogOfJack {
        int gg;
        public void print() {
            System.out.println("Jack's Dog " + Dog.age +" 的内部类");
        }
    }
    public void f1() {
        new DogOfJack().print();
    }
    public DogOfJack getInstance() {
        return new DogOfJack();
    }
}

public class MemberInnerClass {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Dog.DogOfJack dogOfJack = new Dog.DogOfJack();
        dogOfJack.print();
    }
}
//输出:Jack's Dog 6 的内部类

总结

Java中的内部类有四种,可以根据其分别定义在外部类的局部位置上、成员位置上将内部类分为局部内部内、匿名内部类和成员内部类、静态内部类,其中使用最多的为匿名内部类。

  • 局部内部类:定义在外部类的方法或者代码块中,作为类存在。作用域为方法或者代码块内部。局部内部类可以直接访问外部类的所有成员,通过外部类名.this.属性的方法访问外部类中的属性。
  • 匿名内部类:定义在外部类的方法或者代码块中。匿名内部类分为基于接口的匿名内部类和基于对象的匿名内部类,在使用匿名内部类时要注意继承、多态和动态绑定。匿名内部类的作用域和局部内部类相同,注意匿名内部类具有类的特征也具有对象的特征,外部类无法访问。匿名内部类可以直接访问外部类的所有属性,通过外部类名.this.属性访问。
  • 成员内部类:定义在外部类的成员位置上,作为一个成员存在,作用域为外部类内。可以访问外部类中的所有属性,通过外部类名.this.属性访问。
  • 静态内部类:与成员内部类类似,位于外部类的成员位置上,在类内不能使用this关键字,同时在类的内部只能通过类名.属性访问外部类中的静态变量
  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小s的s

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

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

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

打赏作者

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

抵扣说明:

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

余额充值