文章目录
- JavaSE-11 【内部类】
- 第一章 成员内部类和局部内部类
- 1.1 四种权限修饰符
- 1.2 内部类的概念和分类
- 1.3 成员内部类的定义格式
- 1.4 成员内部类的使用
- 1.5 内部类的同名变量访问
- 1.6 局部内部类定义
- 1.7 局部内部类的final问题
- 第二章 匿名内部类
- 2.1 匿名内部类
- 2.2 匿名内部类的注意事项
- 2.3 类作为成员变量类型
- 2.4 接口作为成员变量类型
JavaSE-11 【内部类】
第一章 成员内部类和局部内部类
1.1 四种权限修饰符
- 1、private:可以修饰成员变量和成员方法.被修饰的成员只能在本类中访问.其他类不能直接访问
- 2、default:它是针对本包访问而设计的,任何处于本包下的类、接口、异常等,都可以相互访问
- 3、protected: 当前类或子类可以访问,同时相同包内的其他类也可以访问protected成员;
- 4、public: 它具有最大的访问权限,可以访问任何一个在类路径下的类、接口、异常等。
四种权限修饰符的访问权限
-
在同一个类当中使用public、protected、(default)、private修饰的成员变量或者成员方法,都可以直接访问或调用类中的成员变量或者成员方法
-
在同一个包中的两个不同类时,使用public、protected、(default)修饰的成员变量或者成员方法,可以直接访问或调用两个类中的成员变量或者成员方法
-
在某一个类和不同包的子类,使用public、protected修饰的成员变量或者成员方法,可以直接访问或调用两个类中的成员变量或者成员方法
-
在某一个类和不同包的非子类中,使用public修饰的成员变量或者成员方法,可以直接访问或调用两个类中的成员变量或者成员方法
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();
}
}
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();
}
}
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();
}
}
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();
}
}
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();
}
}
`