嵌套类的认识和使用

**嵌套类(nested class)的概念:**是指被定义在一个类内部的类,所以也称为内部类,它在java中被广泛的应用,嵌套类有四种:成员内部类、静态内部类、匿名内部类、局部内部类

一、成员内部类
成员内部类又被称为非静态内部类,顾名思义,就是定义在类内部没有被static修饰的普通类,可以将之看成一个类的成员对象,如下:

public class Outer {
    public class Inner{
        
    }
}

成员内部类的特点:
1.成员内部类可以被权限修饰符所修饰,eg:private、public、default(不写)、protected
2.成员内部类可以访问外部类的所有成员,包括private成员
3.成员内部类是默认包含了一个指向外部类对象的引用
4.可以继承其他类,或者其他接口
5.除常量(static final)外,不能包含静态变量/方法。
6.当内部类的变量或方法与外部类一样时,可以用Outer.this.name指定访问外部类的成员或方法,设计时应尽量避免这种情况。
7.在第三方类中,不允许单独的普通内部类对象存在,需要先创建外部类的对象,才能创建内部类的对象。
8.编译后名称是:外部类名+$+内部类名

内部类类对象的创建方式

  Outer outer= new Outer();
  Outer.Inner inner=outer.new Inner();

编译后的格式:
在这里插入图片描述

二、静态内部类
静态内部类又被称为静态成员类,顾名思义,就是用static修饰的内部类,如下:

public class Outer {
    public static class Inner{


    }
}

静态内部类的特点:
1.可以定义静态成员或者非静态成员
2.不能直接访问外部类的非静态成员,可通过外部类的对象访问外部类的非静态成员
3.可以直接访问外部类的静态成员
4.外界(第三方类)可以通过静态内部类的类名访问其静态成员,通过对象访问其非静态成员
5.外界(第三方类)只能通过外部类才可以访问到静态嵌套类,并创建对象,不需要外部类的对象。
6.是四种类中唯一一个不包含对外部类对象引用的内部类
7.可以继承其他类或者实现其他接口

代码示例:

public class Outer {
    private String id="007";
    static String name="小明";
    int number=12;
    
    public static class Inner extends Thread{  //可以继承其他类
        public static int a;//可以有静态成员
        public int b;//可以有非静态成员
        public void innerMethod(){
           System.out.println(name);//可以直接访问外部类静态成员
            Outer outer=new Outer();
            System.out.println(outer.number);//只能通过外部类的对象访问外部类非静态成员
            System.out.println(outer.id);//可以访问外部类私有成员
        }
    }

    public static void main(String[] args) {
        Inner inner=new Inner();//在外部类中对象创建方式与普通类一致
    }
}

/*=====================================================================================*/


class Three{
    public static void main(String[] args) {
        Outer.Inner inner=new Outer.Inner();//在第三方类中的对象的创建方式

    }
}

编译后的文件名与普通内部类一致
在这里插入图片描述

三、匿名内部类
匿名内部类是与继承合并在一起没有名字的类

匿名内部类的特点:
1.没有正式的类名
2.没有构造函数,能使用父类或者父接口的构造函数,可以带参数,可以继承,重写,扩展父类、父接口的方法
3.除常量(static final)外,内部不可以定义静态成员,
4.可以访问外部类的成员变量和方法,包括private
5.如果定义在静态方法中,也只能访问外部类的静态成员
6.外部类和第三方类都无法访问匿名内部类
7.编译后的文件名:外部类名+$+数字编号+.class
8.没有类名,也没有引用指向它,所以只能使用一次

实现方式

父类名/接口名 对象名=new 父类名/接口名{
重写或者实现父类中的方法
}

代码实例:

public class Outer {
    public static void Method(){
        //实现接口
        //使用方式1
        InterfaceTest it=new InterfaceTest() {
            @Override
            public void test() {
                System.out.println("A");
            }
        };
        it.test();

        //使用方式二
        new InterfaceTest() {
            @Override
            public void test() {
               System.out.println("B");
            }
        }.test();
        //继承抽象类
        AbstractTest at=new AbstractTest() {
        };
        at.normalMethod();//可以继承父类中的方法
    }

    public static void main(String[] args) {
        Method();
    }
}

/*=====================================================================================*/


interface InterfaceTest{
    public void test();
}
abstract class AbstractTest{
    public void normalMethod(){
        System.out.println("C");
    }
}

编译后的文件:
在这里插入图片描述

匿名类的作用:
1.简单便捷,当我们想使用一个接口或者抽象类定义的方法时,但是并不是重复利用,可能只是使用很少的次数,就可用匿名内部类,这样做的好处是,不用特意构造一个类去继承抽象类/接口,然后创建对象去使用,而是直接创建匿名内部类使用父类中的方法。只针对重写一个方法时使用,需要重写多个方法时不建议用匿名内部类。
2.安全封装,由于外部无法访问到匿名内部类,增强了封装性。

四、局部内部类
局部内部类是定义在方法或者作用域中类。如下

public class Outer {
    public static void Method(){
        class Inner{
            
        }
    }
}
    

局部内部类的特点
1.局部内部类不能有访问权限符,有构造方法
2.局部内部类不能被定义为static,
3.局部内部类不能含有静态成员
4.局部内部类默认包含了外部类对象的引用
5.如果定义在普通方法中,局部内部类可以使用Outer.this的语法访问外部类成员
6.局部内部类想要使用方法或域中变量。该变量必须是final的,但在java8之后,有了effectively final,变量可以不用final修饰,一个变量定值后没有被修改过
7.可以继承其他类,或者实现接口,但是本身不能是一个接口
8.如果定义在静态方法中,只能访问外部类静态成员
9.编译后名称:外部类名+$+序号+内部类名+.class
编译后文件:
在这里插入图片描述
局部内部类的作用
局部内部类的作用其实和匿名内部类的作用差不多,当我们在设计类时,可能一些方法内,需要创建一个类或者需要实现某些接口/抽象类来使用,就可以通过创建局部内部类的方式。因为在实际使用过程中我们可能需要多个内部类对象,由于局部内部类有类名,有构造器,可以创建对象,这是匿名内部类办不到的。

五、内部类究竟有什么作用(静态/成员内部类)
1.解决多继承的问题,当我们设计类时有可能会涉及到需要多继承时,就可以用创建多个内部类来继承我们需要的抽象类供自己使用。
2.隐藏封装,当我们不想内部类轻易被人访问,可以选择private来修饰内部类,只留一个接口供外部使用,隐藏了内部方法的具体实现。
3.可以无条件的访问外部类的成员,可以对外部类的私有成员做处理,这是第三方类无法做到的。
4.解决在同时继承类和实现接口中有同名方法不好区分的问题。

六、为什么匿名/局部内部类只能使用外部被final修饰的变量
这是由于局部变量和局部内部类对象的生命周期不同,局部变量所处的方法在执行结束后就死亡了,但是局部内部类的对象只要有引用指向,它就会一直存在,这样就会出现一种尴尬的现象,内部类的引用指向一个不存在的变量,所以就需要用final修饰,将这个变量变成常量,储存在常量区。但是自从java1.8之后,这个局部变量可以不用被final修饰,实际上底层自动帮忙加上了final,所以说看起来没有被final修饰的变量,当我们试图修改这个变量值时,编译器就会报错,这样的变量只能被使用,而不能被修改。

七、变量遮蔽
在这里插入图片描述

总结
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值