JavaSE-11 【内部类】

JavaSE-11 【内部类】

第一章 成员内部类和局部内部类

1.1 四种权限修饰符

  • 1、private:可以修饰成员变量和成员方法.被修饰的成员只能在本类中访问.其他类不能直接访问
  • 2、default:它是针对本包访问而设计的,任何处于本包下的类、接口、异常等,都可以相互访问
  • 3、protected: 当前类或子类可以访问,同时相同包内的其他类也可以访问protected成员;
  • 4、public: 它具有最大的访问权限,可以访问任何一个在类路径下的类、接口、异常等。

四种权限修饰符的访问权限

  • 在同一个类当中使用public、protected、(default)、private修饰的成员变量或者成员方法,都可以直接访问或调用类中的成员变量或者成员方法

  • 在同一个包中的两个不同类时,使用public、protected、(default)修饰的成员变量或者成员方法,可以直接访问或调用两个类中的成员变量或者成员方法

  • 在某一个类和不同包的子类,使用public、protected修饰的成员变量或者成员方法,可以直接访问或调用两个类中的成员变量或者成员方法

  • 在某一个类和不同包的非子类中,使用public修饰的成员变量或者成员方法,可以直接访问或调用两个类中的成员变量或者成员方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FwDLpdQ6-1687769389555)(photo/JavaSE11_内部类.assest/1664966769356.png)]

1.2 内部类的概念和分类

  • 内部类:如果一个事物的内部包含另一个事物,那么它就是一个类内部包含了另一个类
  • 分类:
    • 1、成员内部类
    • 2、局部内部类 (局部内部类包含匿名内部类)

1.3 成员内部类的定义格式

  • 定义格式
  修饰符 class 外部类名称{
      修饰符 class 内部类名称{
          //...
      }
     //...
  }
  • 访问规则:内用外,随意访问。外用内,需要内部类对象

1.4 成员内部类的使用

  • 使用成员内部类的两种方式
    • 1、间接方式:在外部类的方法中,使用内部类
    • 2、直接方式:直接使用成员内部类对象
  • 创建内部类对象的格式
    • 外部类名称.内部类名称 对象名称 = new 外部类名称().new 内部类名称();
public class OuterClassA {
    //成员属性
    private String name;
    //成员方法
    public void methodA(){
        System.out.println("我是外部类的方法");
        //在外部类的方法中创建内部类对象
        InnerClassA innerA = new InnerClassA();
        //调用内部类的方法
        innerA.methodB();
    }
    //成员内部类
    public class InnerClassA{
        //定义成员内部类的方法
        public void methodB(){
            System.out.println("我是成员内部类的成员方法");
            //内部类访问外部类的成员变量
            System.out.println("name的值是:"+name);
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
 /**  成员内部类的定义格式
 *  修饰符 class 外部类名称{
 *      修饰符 class 内部类名称{
 *          //...
 *      }
 *      //...
 *  }
 *  注意事项:内用外,随意访问。外用内,需要内部类对象
 *
 *  使用成员内部类的两种方式:
 *  1、间接方式:在外部类的方法中,使用内部类
 *  2、直接方式:直接使用成员内部类对象
 *      格式:外部类名称.内部类名称 对象名称 = new 外部类名称().new 内部类名称();
 */
public class TestInnerClassA {
    public static void main(String[] args) {
        //方式一:间接方式
        OuterClassA outerA = new OuterClassA();
        outerA.setName("Tom");
        //通过外部类的对象调用外部类的成员方法,同时间接调用方法中的内部类
        outerA.methodA();

        System.out.println("------------------");

        //方式二:直接使用
        //创建内部类对象吧
        OuterClassA outerB = new OuterClassA();
        outerB.setName("Anny");
        //OuterClassA.InnerClassA innerClassA = new OuterClassA().new InnerClassA();
        OuterClassA.InnerClassA innerClassA = outerB.new InnerClassA();
        //调用内部类的成员方法
        innerClassA.methodB();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Ce2qS0e-1687769389556)(photo/JavaSE11_内部类.assest/1664969746232.png)]

1.5 内部类的同名变量访问

  • 内部类的同名变量:即外部类的成员变量、内部类的成员变量、内部类的局部变量,三者重名
  • 内部类访问外部类的成员变量的格式 : 外部类名称.this.外部类成员变量名
public class OuterClassB {
    int num = 100;//外部类的成员变量
    //成员内部类
    public class InnerClassB{
        int num = 200;//内部类的成员变量
        public void methodInner(){
            int num = 300;//内部类的局部变量
            System.out.println("内部类局部变量:"+num);//局部变量 就近原则
            System.out.println("内部类成员变量:"+this.num);//内部类的成员变量
            System.out.println("外部类成员变量:"+OuterClassB.this.num);//外部了的成员变量
        }
    }
}
/**
 * 内部类的同名变量访问
 *  内部类访问外部类的成员变量的格式
 *  格式:外部类名称.this.变量名
 */
public class TestInnerClassB {
    public static void main(String[] args) {
        //创建内部类对象
        //外部类名称.内部类名称 对象名称 = new 外部类名称().new 内部类名称();
        OuterClassB.InnerClassB innerClassB = new OuterClassB().new InnerClassB();
        //调用内部类的方法
        innerClassB.methodInner();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EQ0CsXrJ-1687769389556)(photo/JavaSE11_内部类.assest/1664969934620.png)]

1.6 局部内部类定义

  • 概念:如果一个类是定义在外部类的成员方法中,那么这个类就是局部内部类
  • 作用域:外部类的成员方法内,且局部内部类的对象只能在外部类的成员方法内创建
  • 格式:
修饰符 class 外部类{
    修饰符 返回值类型 方法名(参数列表){
         class 局部内部类名称{
              //...
         }
    }
}
public class OuterA {
    //外部类的成员方法
    public void methodOuter(){
        //局部内部类
        class InnerA{
            //局部内部类成员变量
            int num = 100;
            //局部内部类成员方法
            public void methodInnerA(){
                System.out.println("我是局部内部类中的成员方法");
                System.out.println("局部内部类成员变量: "+num);//100
            }
        }

        //创建局部内部类对象(在外部类的成员方法范围内)
        InnerA innerA = new InnerA();
        //调用方法
        innerA.methodInnerA();
    }
}
public class TestOuterA {
    public static void main(String[] args) {
        //创建外部类对象
        OuterA outerA = new OuterA();
        //调用外部类的成员方法
        outerA.methodOuter();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bTrHi6VI-1687769389556)(photo/JavaSE11_内部类.assest/1664970599473.png)]

1.7 局部内部类的final问题

  • 局部内部类,如果想访问所在成员方法中的局部变量,那么这个局部变量必须是有效的final的
  • 从Java8开始,只要局部变量事实不变,那么final关键字可以省略
  • 原因
    • 1、new的对象存储在堆内存中
    • 2、局部变量跟着方法走。存储于栈内存中
    • 3、方法运行结束后,执行出栈操作,局部变量就会跟着立即消失
    • 4、但是new出来的对象会在堆内存中持续存在,直到垃圾回收器回收
    • 5、所以局部变量如果不用final修饰,那么在局部变量消失之后,局部内部类对象无法获取
    • 6、故而局部变量使用final修饰,存放在常量区,可以随时访问使用
public class OuterClass {
    public void methodA(){
        final int num1 = 100;
        int num2 = 100;//未改变,可以访问获取
        //num2 =200;//以改变 无法访问获取
        class InnerClass{
            public void methodB(){
                System.out.println(num1);
                System.out.println(num2);
            }
        }
    }
}

第二章 匿名内部类

2.1 匿名内部类

  • 匿名内部类
    • 如果接口的实现类,或者父类的子类,只需要使用一次
    • 那么这种情况下就可以省略掉实现类或子类的定义,改为使用匿名内部类
  • 匿名内部类定义格式:
   接口名称 对象名 = new 接口名称(){
       //覆盖重写所有的抽象方法
   };
  • 格式解析:
    • 1、new 代表创建接口实现类对象的动作
    • 2、接口名称就是匿名内部类需要实现的那个接口
    • 3、{…}才是匿名内部类的内容。也就是接口的无名称的实现类

2.2 匿名内部类的注意事项

  • 注意事项
    • 1、匿名内部类在创建对象的时候,只能使用唯一一次
    • 2、若果重写的抽象方法有多个,就不能使用简化写法
    • 3、匿名对象是匿名内部类的一个具体实现
/**
 * 定义接口以及抽象方法
 */
public interface AnonymousInnerInterface {
    public abstract void method1();
}
/**
 * 实现类
 */
public class AnonymousInnerInterfaceImpl implements AnonymousInnerInterface {
    @Override
    public void method1() {
        System.out.println("实现类重写了接口的抽象方法");
    }
}
public class TestAnonymousInner {
    public static void main(String[] args) {
        //普通方式
        AnonymousInnerInterfaceImpl impl1 = new AnonymousInnerInterfaceImpl();
        AnonymousInnerInterface impl2 = new AnonymousInnerInterfaceImpl();
        impl1.method1();
        impl2.method1();

        System.out.println("-------------------------------------------");

        //匿名内部类方式
        AnonymousInnerInterface impl3 = new AnonymousInnerInterface() {
            @Override
            public void method1() {
                System.out.println("使用匿名内部类的形式重写了抽象方法---AAA");
            }
        };
        //通过对象名,调用方法
        impl3.method1();

        System.out.println("--------------------------------------------");

        //匿名内部类简化写法--省略对象名接收
        new AnonymousInnerInterface(){
            @Override
            public void method1() {
                System.out.println("使用匿名内部类的形式重写了抽象方法---AAA");
            }
        }.method1();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aK0VCd08-1687769389557)(photo/JavaSE11_内部类.assest/1664975329586.png)]

2.3 类作为成员变量类型

**
* 类作为成员变量类型
*/
public class HeroRole {
   private String name;//英雄名称
   private int age;//英雄年龄
   private Arms arms;//武器

   public HeroRole() {
   }

   public HeroRole(String name, int age, Arms arms) {
       this.name = name;
       this.age = age;
       this.arms = arms;
   }

   //英雄攻击的方法
   public void attack(){
       System.out.println("英雄:"+name+",年龄:"+age+",使用武器是:"+arms.getArmsName());
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public Arms getArms() {
       return arms;
   }

   public void setArms(Arms arms) {
       this.arms = arms;
   }
}
public class Arms {
    private String armsName;//武器名称

    public Arms() {
    }

    public Arms(String armsName) {
        this.armsName = armsName;
    }

    public String getArmsName() {
        return armsName;
    }

    public void setArmsName(String armsName) {
        this.armsName = armsName;
    }
}
public class TestHero {
    public static void main(String[] args) {
        //创建英雄角色
        HeroRole heroRole = new HeroRole();
        //设置英雄名称
        heroRole.setName("金克斯");
        //设置英雄年龄
        heroRole.setAge(18);
        //创建武器对象
        Arms arms = new Arms("无尽之刃");
        //为英雄设置武器
        heroRole.setArms(arms);
        //调用攻击的方法
        heroRole.attack();
    }
}

2.4 接口作为成员变量类型

/**
 * 接口作为成员变量类型
 */
public class HeroRole {
    private String name;//英雄的名称
    private Skill skill;//英雄的技能

    public HeroRole() {
    }

    public HeroRole(String name, Skill skill) {
        this.name = name;
        this.skill = skill;
    }

    //英雄的攻击方法
    public void attack(){
        System.out.println("开始释放技能");
        skill.use();//释放的具体技能
        System.out.println("技能释放完成");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Skill getSkill() {
        return skill;
    }

    public void setSkill(Skill skill) {
        this.skill = skill;
    }
}
public interface Skill {
    //使用技能的方法
    public abstract void use();
}
public class SkillImpl implements Skill{
    @Override
    public void use() {
        System.out.println("释放的技能是:光之束缚");
    }
}
public class TestHero {
    public static void main(String[] args) {
        /*
            方式一:创建Skill的接口实现类重写方法,并创实现类的对象,
         */
        //创建英雄
        HeroRole heroRole = new HeroRole();
        //设置英雄的名称
        heroRole.setName("光辉女郎");
        //创建技能实现类对象
        SkillImpl skillImpl = new SkillImpl();
        //设置英雄的技能属性
        heroRole.setSkill(skillImpl);
        //调用英雄的攻击方法
        heroRole.attack();

        System.out.println("----------------------");

        /*
            方式二:使用匿名内部类实现
         */
        //创建英雄
        HeroRole heroRole1 = new HeroRole();
        //设置英雄的名称
        heroRole1.setName("亚索");
        //使用匿名内部类创建对象
        Skill skill = new Skill() {
            @Override
            public void use() {
                System.out.println("释放的技能是:风墙被动");
            }
        };
        //设置英雄的技能
        heroRole1.setSkill(skill);
        //调用英雄的攻击方法
        heroRole1.attack();

        System.out.println("-----------------------------");

        /*
            方式三:匿名内部类的简写
         */
        HeroRole heroRole2 = new HeroRole();
        heroRole2.setName("德邦总管");
        heroRole2.setSkill(new Skill() {
            @Override
            public void use() {
                System.out.println("释放的技能是:枪出如龙");
            }
        });
        heroRole2.attack();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kQhKmyyj-1687769389557)(photo/JavaSE11_内部类.assest/1664982505284.png)]

`

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值