Java内部类

什么是内部类?

把类定义在其他类的内部,这个类就被称为内部类,内部类可以定义在类内部包括类中的任何位置,甚至在方法中也可以定义内部类

内部类的访问特点

  1. 内部类可以直接访问外部的成员,包括私有

  2. 外部类要访问内部类的成员必须创建对象

  3. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许其他类访问该类

  4. 匿名内部类适合用于创建哪些仅需要一次使用的类

  5. 可以由public、private、protected权限修饰符修饰

  6. 可以使用static修饰内部类

成员内部类

在成员位置(在类中,方法、构造器、代码块以外)定义的类,被称为成员内部类

成员内部类又分为静态内部类和非静态内部类

静态内部类

静态内部类是由static修饰的内部类,当使用static修饰内部类,则内部类属于外部类本身,与静态成员变量类似,在类加载时加载

为什么外部类不支持使用static修饰?
因为外部类的上级程序单位是包,内部类的上级程序单元是外部类

静态内部类的实现及外部类访问:

public class MemberClass {
    private String id;
    //静态内部类
    private static class InnerStaticClass{
        private static String name;
        private String age;
        
        private void play(){
            //无法直接访问
//            String str = id;
            System.out.println(members+"私有方法");
        }
    }
    //非私有静态内部类
    static class StaticClass{
        private static String name;
        private String age;
  
        private void play(){
            //无法直接访问
//            String str = id;
            System.out.println(members+"私有方法");
        }
        public void test(){
            System.out.println("静态内部类测试方法");
        }
    }

    public void show(){
        InnerStaticClass innerStaticClass = new InnerStaticClass();
        innerStaticClass.age="50";
        innerStaticClass.play();
        System.out.println(innerStaticClass.age);
    }
    
    //获取内部类对象方法
    public StaticClass getStaticClass(){
        return new StaticClass();
    }
}

外部类访问自身静态内部类的特点:

  1. 静态内部类支持定义static修饰的静态成员变量和普通成员变量

  2. 外部类方法可以直接访问静态内部类中的任何内容,包括私有

  3. 内部类无法访问外部类的普通成员,但是可以访问静态成员

静态内部类的其他类访问:

public static void main(String[] args) {
    //通过外部类访问内部类中的数据
    MemberClass memberClass = new MemberClass();
    memberClass.show();
    //通过外部类的方法获取内部类的对象--私有静态内部类不可使用以下方法
    MemberClass.StaticClass staticClass = memberClass.getStaticClass();
    MemberClass.StaticClass staticClass1 = new MemberClass.StaticClass();
}

其他类访问静态内部类的特点

  1. 调用者可以通过外部类的公有方法,获取静态内部类中的数据

  2. 如果内部类定义为private,则无法再通过其他方式访问

  3. 如果内部类定义为public或default,则可以通过直接new对象,或者使用公有方法

非静态内部类

非静态内部类不通过static修饰的内部类,属于类的实例,在初始化时创建

非静态内部类实现及外部类的访问:

public class MemberClass {
    //私有非静态内部类
    private class InnerClass{
        //非静态内部类不支持定义静态成员变量
//        private static String sex;
        private String hobby;
        public void play(){
            String str= id;
            System.out.println(str+members+"非静态内部类方法");
        }
    }
    //非私有非静态内部类
    class PublicClass{
        //非静态内部类不支持定义静态成员变量
//        private static String sex;
        private String hobby;
        public void play(){
            String str= id;
        }
    }

    public void showInner(){
        InnerClass innerClass = new InnerClass();
        innerClass.hobby="打球";
        innerClass.play();
        System.out.println(innerClass.hobby);
    }
}

外部类访问自身非静态内部类的特点:

  1. 非静态内部类不支持定义static修饰的静态成员变量

  2. 外部类方法可以直接访问非静态内部类中的任何内容,包括私有

  3. 内部类可以访问外部类的普通成员和静态成员

非静态内部类的其他类访问:

public static void main(String[] args) {
    //通过外部类访问内部类中的数据
    MemberClass memberClass = new MemberClass();
    memberClass.showInner();
    //通过外部类的方法获取内部类的对象--私有非静态内部类不可使用以下方法
    MemberClass.PublicClass publicClass = memberClass.getPublicClass();
    MemberClass.PublicClass publicClass1 = new MemberClass().new PublicClass();
}

其他类访问非静态内部类的特点

  1. 调用者可以通过外部类的公有方法,获取非静态内部类中的数据

  2. 如果内部类定义为private,则无法再通过其他方式访问

  3. 如果内部类定义为public或default,则可以通过直接new对象,或者使用公有方法

成员内部类的修饰符:

  1. 一般内部类是不让外界直接访问的

  2. private为了保证数据的安全性

  3. static为了方便访问数据

局部内部类

在局部位置(方法、代码块、构造器中)定义的类,被称为局部内部类,局部内部类不支持定义静态内部类

代码块中定义内部类

public class LocalClass {
    //局部内部类
    {
        class InnerLocalClass{
            private String name;
//            private static String age;
        }
    }
    //不支持在静态代码块中定义静态内部类
    static {
//        static class InnerLocalClass{
//            private String name;
            private static String age;
//        }
    }
}

代码块中内部类的特性:

  1. 在内部类中不支持定义静态成员变量

  2. 在静态内部类中也不支持定义静态局部内部类

  3. 局部内部类只在当前代码块有效

  4. 局部内部类可以直接访问外部类的成员

  5. 在局部位置,可以创建内部类对象,通过对象调用内部方法,来使用局部内部类功能

局部内部类一般很少有人使用,代码块和其他成员中的内部类都是相似的特性

匿名内部类

匿名内部类适合创建一次性使用的类,创建一个匿名内部类时会立即创建一个该类的实例,这个类定义后立即消失,是一次性的不支持重复使用

匿名内部类的实现1:匿名内部类继承一个普通类

public class AnonymousClass {
    public void test(){
        System.out.println("写入一个父类的代码");
    }
}
public static void main(String[] args) {
    //匿名内部类
    //此时的匿名内部类可以看作是继承了AnonymousClass类的一次性类,我们可以重写一些方法来实现一次性的操作
    new AnonymousClass(){
        @Override
        public void test(){
            System.out.println("写入一个子类的代码");
        }
    }.test();
}

匿名内部类的实现2:匿名内部类实现一个接口

public interface AnonymousInterface {
    void show();
}
public static void main(String[] args) {
    //此时的匿名内部类可以看作是实现了AnonymousInterface接口的一次性实现类,我们可以实现一些方法来完成某些一次性的操作
    //也可以不要=和前面的部分,这里只是想表明,可以使用接口的实例来接收匿名内部类
    AnonymousInterface a=new AnonymousInterface(){
        @Override
        public void show() {
            System.out.println("我实现了AnonymousInterface的show方法");
        }
    };
    a.show();
}

匿名内部类的实现3:匿名内部类继承一个抽象类

public abstract class AnonymousAbstract {
    public abstract void play();
}
public static void main(String[] args) {
    //此时的匿名内部类可以看作是实现了AnonymousAbstract抽象类的一次性子类,我们可以实现/重写一些方法来完成某些一次性的操作
    new AnonymousAbstract(){
        @Override
        public void play() {
            System.out.println("实现抽象类中的抽象方法");
        }
    };
}

匿名内部类的常用用法:作为参数进行传递

public class AnonymousClass {
    private String name;
    private Integer price;

    public String getName() {
        return name;
    }

    public Integer getPrice() {
        return price;
    }
}

public class InnerTest {
    public void test1(AnonymousClass anonymousClass){
        System.out.println("小明买了一个"+anonymousClass.getName()+"花费"+anonymousClass.getPrice()+"元");
    }
    public static void main(String[] args) {
        //其他实现类如下面操作,需要注意的是,如果接口/抽象类中有多个抽象方法,需要一一实现
        //因此以接口的方式声明匿名内部类最优的方式是只有一个抽象方法,这也是lambda表达式的由来
        InnerTest innerTest = new InnerTest();
        innerTest.test1(new AnonymousClass(){
            @Override
            public Integer getPrice() {
                return 52;
            }

            @Override
            public String getName(){
                return "影片";
            }
        });
    }
}
输出结果:小明买了一个影片花费52元

匿名内部类的特点:

  1. 匿名内部类不能是抽象类[//]: # (但是可以继承抽象类),因为匿名内部类会立即创建实例,抽象类不允许创建实例,因此不允许将匿名内部类定义为抽象类

  2. 匿名内部类不允许定义构造器,由于匿名内部类没有类名,所以无法定义构造器,如果需要初始化可以定义初始化代码块,通过实例初始化来完成构造器所需要完成的事情

  3. 匿名内部类只能一次性使用,不能多次使用,一般用于输出/处理数据:例如传参,处理外部数据等

  4. 匿名内部类必须实现接口/抽象类中的所有抽象方法

  5. 匿名内部类的父类中如果存在有参构造器,则需要传递参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Carl·杰尼龟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值