【Java】内部类的使用方法和使用特点

文章详细介绍了Java中的内部类,包括它们的访问特点,如内部类能直接访问外部类的所有成员,而外部类需通过实例访问内部类成员。内部类的使用主要是为了实现高内聚和低耦合。文章分别讨论了静态成员内部类和非静态成员内部类的创建和使用,以及局部内部类和匿名内部类的两种实现方式,并提供了相关代码示例。最后,文章通过两个练习展示了如何直接调用和使用反射调用匿名内部类的方法。
摘要由CSDN通过智能技术生成

内部类

一、访问特点

  • 内部类可以直接访问外部类成员,包括私有部分

image-20230524151300853

  • 外部类要访问内部类成员,必须创造对象
  • 与类的用法一致,关键词,接口,继承,修饰符等都完全一致

二、为什么要使用内部类

只有有需求的类才会使用,高内聚,低耦合

三、成员内部类

示例:

package Day10;
/*
 *项目名: OneDayLearn
 *文件名: Animal
 *创建者: SWY
 *创建时间:2023/5/24 下午2:19
 *描述: TODO
 */

public class Animal {

    class EatFool{
        public void eat(){
            System.out.println("正在吃东西");
        }
        public static void noteat(){
            System.out.println("没有吃饱");
        }
    }

    static class Drink{
        public void DrinkWater(){
            System.out.println("正在喝水");
        }
        
        public static void notDrink(){
            System.out.println("没有喝水");
        }
    }
}

1、静态成员内部类实例创建

使用static修饰符修饰

/**
* 静态内部类实例
*/
Animal.Drink dog = new Animal.Drink();
//静态内部类中的非静态方法
dog.DrinkWater();
//静态内部类中的静态方法
Animal.Drink.notDrink();

/** 运行结果 :
 *  正在喝水
 *  没有喝水

静态内部类是与外部类关联但具有独立存在的类。可以通过外部类的类名直接访问静态内部类,无需创建外部类的实例。因此,可以通过 Animal.Drink 来访问静态内部类 Drink

2、非静态成员内部类实例创建

/**
* 非静态内部类实例
*/
// Animal.EatFool cat = new Animal.EatFool();  //报错
Animal p = new Animal();
Animal.EatFool cat = p.new EatFool();
//非静态内部类中的非静态方法
cat.eat();
//非静态内部类中的静态方法
Animal.EatFool.noteat();

/** 运行结果 :
  * 正在吃东西
  * 没有吃饱

非静态内部类是依赖于外部类的实例存在的,它与外部类的实例有一定的关联性。因此,要创建非静态内部类的实例,需要先创建外部类的实例,然后通过外部类的实例来创建内部类的实例。

四、局部内部类

开发中的场景

1、非匿名内部类

a、方式1:提供了接口实现类的对象
package Day10_1;
/*
 *项目名: OneDayLearn
 *文件名: AnonyClass
 *创建者: SWY
 *创建时间:2023/5/24 下午4:02
 *描述: TODO
 */

import Day9_1.MyClass;

public class AnonyClass {

    /**
     * 实现了Comparable接口的类
     * 方式1:提供了接口的实现类的对象
     * @return
     */
    public Comparable getInstance(){

        //实现MyComparable类
        class MyComparable implements Comparable{
            //重构Comparable接口的compareTo方法
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
        MyComparable comparable = new MyComparable();
        return comparable;
    }

    public static void main(String[] args) {
        AnonyClass anonyClass = new AnonyClass();
        System.out.println(anonyClass.getInstance().getClass());
        /**
         * 输出结果:
         * class Day10_1.AnonyClass$1MyComparable
         */
    }

}
b、方式2:提供了接口的实现类的匿名对象
package Day10_1;
/*
 *项目名: OneDayLearn
 *文件名: AnonyClass
 *创建者: SWY
 *创建时间:2023/5/24 下午4:02
 *描述: TODO
 */

public class AnonyClass {

    /**
     * 实现了Comparable接口的类
     * 方式1:提供了接口的实现类的匿名对象
     * @return
     */
    public Comparable getInstance(){
        
        //实现MyComparable类
        class MyComparable implements Comparable{
            //重构Comparable接口的compareTo方法
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
        return new MyComparable();
    }

    public static void main(String[] args) {
        AnonyClass anonyClass = new AnonyClass();
        System.out.println(anonyClass.getInstance().getClass());
         /**
         * 输出结果:
         * class Day10_1.AnonyClass$1MyComparable
         */
    }

}

2、匿名内部类

a、方式2:提供了接口匿名实现类的对象
package Day10_1;
/*
 *项目名: OneDayLearn
 *文件名: AnonyClass
 *创建者: SWY
 *创建时间:2023/5/24 下午4:02
 *描述: TODO
 */

public class AnonyClass {

    /**
     * 实现了Comparable接口的类
     * 方式3:提供了接口的匿名实现类的对象
     * @return
     */
    public Comparable getInstance(){

        //利用了多态机制,进行向上转型,将子类引用赋给了父类
        Comparable comparable = new Comparable(){
            //重构Comparable接口的compareTo方法
            @Override
            public int compareTo(Object o) {
                return 0;
            }
            //因为此时还处于new的用法, 所以需要用;
        };
        return comparable;
    }

    public static void main(String[] args) {
        AnonyClass anonyClass = new AnonyClass();
        System.out.println(anonyClass.getInstance().getClass());
        /**
         * 输出结果:
         * class Day10_1.AnonyClass$1
         */
    }
}

b、方式4:提供了接口匿名实现类的匿名对象

该方式与方式3类似

package Day10_1;
/*
 *项目名: OneDayLearn
 *文件名: AnonyClass
 *创建者: SWY
 *创建时间:2023/5/24 下午4:02
 *描述: TODO
 */

public class AnonyClass {

    /**
     * 实现了Comparable接口的类
     * 方式4:提供了接口匿名实现类的匿名对象
     * @return
     */
    public Comparable getInstance(){
        //直接返回接口重构后的类
        return new Comparable(){
            //重构Comparable接口的compareTo方法
            @Override
            public int compareTo(Object o) {
                return 0;
            }
            //因为此时还处于return; 所以需要用;
        };
    }

    public static void main(String[] args) {
        AnonyClass anonyClass = new AnonyClass();
        System.out.println(anonyClass.getInstance().getClass());
        /**
         * 输出结果:
         * class Day10_1.AnonyClass$1
         */
    }
}

五、练习

编写一个匿名内部类,它继承Object类,并且在匿名内部类中,声明一个public void test() 方法打印:你好

1、常规方法直接调用

package Day10_1;
/*
 *项目名: OneDayLearn
 *文件名: Exercises
 *创建者: SWY
 *创建时间:2023/5/24 下午4:42
 *描述: 编写一个匿名内部类,它继承Object类,并且在匿名内部类中,声明一个`public void test()` 方法打印:你好
 */

public class Exercises {
    public  void printf(){
        new Object(){
            public void test(){
                System.out.println("你好");
            }
        }.test();
        //相当于new了一个对象A,然后进行了A.test();的操作
    }

    public static void main(String[] args) {
        Exercises exercises = new Exercises();
        exercises.printf();
        /**
         * 输出结果:
         * 你好
         */
    }

}

2、使用反射的方法寻找内部类

package Day10_1;
/*
 *项目名: OneDayLearn
 *文件名: Exercises
 *创建者: SWY
 *创建时间:2023/5/24 下午4:42
 *描述: 编写一个匿名内部类,它继承Object类,并且在匿名内部类中,声明一个`public void test()` 方法打印:你好
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Exercises {
    public  Object printf(){
        return new Object(){
            public void test(){
                System.out.println("你好");
            }
        };
    }

    public static void main(String[] args) throws InvocationTargetExceptionIllegalAccessException {
        Exercises exercises = new Exercises();
        
        //创建一个类内部类实例用于反射,由于该内部类是匿名状态因此无法直接
        //访问到test();方法
        Object obj = exercises.printf();

        //使用反射的方法输出
        Class anonyclass = obj.getClass();
        Method[] method = anonyclass.getDeclaredMethods();
        for(Method a: method){
            a.invoke(obj);
        }
        /**
         * 输出结果:
         * 你好
         */
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

摸鱼小小虫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值