【JavaSE】匿名内部类

阅读: 评论:0

【JavaSE】匿名内部类

【JavaSE】匿名内部类

文章目录

  • 1. 匿名内部类的使用
  • 2. 匿名内部类发注意事项
  • 3. 匿名内部类的最佳实践

1. 匿名内部类的使用

(1)本质是类
(2)内部类
(3)该类没有名字(名字不是能直接看到的,实际上是系统取的
(4)同时还是一个对象

  • 说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
  1. 匿名内部类的基本语法
new 类或接口(参数列表) {类体
}
  • 传统方法实现 ,写一个类,实现该接口,并创建对象
public class AnonymouseInnerClass {public static void main(String[] args) {Outer04 outer04 = new Outer04();hod();}
}class Outer04 {//外部类private int n1 = 10;public void method() {//基于接口的匿名内部类//解读://1.需求:使用IA接口,并创建对象//2.传统方式,写一个类,实现该接口,并创建对象IA tiger = new Tiger();();}
}interface IA {//接口public void cry();
}class Tiger implements IA {@Overridepublic void cry() {System.out.println("老虎叫唤...");}
}class Father {public Father(String name) {}public void test() {}
}

  • 如果 Tiger 这个对象只用一次,后面不再使用了,如果再定义一个 Dog 类,而且也只用一次,这种情况下就会定义很多类,这种情况有可能很多只用一次的情况,创建对象浪费资源

  • 解决方案:这个时候就可以使用 匿名内部类 来简化开发

  • 需求:既不去创建 Tiger 对象,又能去调用 Tiger 类中的方法

  • 接口是不能直接 new 的,但是后面重写的方法相当于在 Tiger 类中重写的方法

  • 匿名内部类实现

public class AnonymouseInnerClass {public static void main(String[] args) {Outer04 outer04 = new Outer04();hod();}
}class Outer04 {//外部类private int n1 = 10;public void method() {//1.可以使用匿名内部类来开发//2.tiger的编译类型是 IA//3.tiger的运行类型是 匿名内部类/** 看底层 类名*  class XXX implements IA {*      @Overridepublic void cry() {System.out.println("老虎叫唤...");}* }* XXX = Outer04$1* * 系统会分配 类名 Outer04$1**/// 4. jdk底层在创建匿名内部类 Outer04$1 ,马上就创建了 Outer04$1 实例,并且把地址返回给 tiger // 5. 匿名内部类使用一次,就不能再使用了IA tiger = new IA(){@Overridepublic void cry() {System.out.println("老虎叫唤...");}};();System.out.println("tiger运行类型=" + Class());}}interface IA {//接口public void cry();
}
  • 可以看到使用匿名内部类也能达到同样的效果,并且不会创建该类,而是以匿名的方式创建的
  • 可以看底层系统给匿名内部类分配的类名,jdk底层在创建匿名内部类 Outer04$1 ,马上就创建了 Outer04$1 实例,并且把地址返回给 tiger ,匿名内部类使用一次,就不能再使用了。但是 tiger 对象可以使用。
class XXX implements IA {@Overridepublic void cry() {System.out.println("老虎叫唤...");}}XXX 类名 = Outer04$1
就是等于在外部类的基础上 加上 $1

  • 查看匿名内部类分配的名字
class XXX implements IA {@Overridepublic void cry() {System.out.println("老虎叫唤...");}
}
System.out.println("tiger运行类型=" + Class());
  • 由上述可知,XXX 类名为 Outer04$1,是系统分配的类名。jdk底层在创建匿名内部类 Outer04$1 ,马上就创建了 Outer04$1 实例,并且把地址返回给 tiger
  • 上面是基于接口的匿名内部类实现。

案例演示:基于类的匿名内部类的实现

//分析
//1.father编译类型 Father
//2.father运行类型 Outer04$2
//3.底层会创建匿名内部类
/*class Outer04$2 extends Father{@Overridepublic void test() {System.out.println("匿名内部类重写了test()");}}*/
//4,同时也直接返回了 匿名内部类 Outer04$2 的对象
Father father = new Father("jack"){@Overridepublic void test() {System.out.println("匿名内部类重写了test()");}
};System.out.println("father运行类型=" + Class());
st();class Father {public Father(String name) {}public void test() {}
}
  • 也可以直接查看的到匿名内部类的类名

  • 基于抽象类的匿名内部类,编译类型是 Animal,运行类型是匿名内部类

//基于抽象类的匿名内部类
Animal animal = new Animal(){@Overridevoid eat() {System.out.println("小狗吃骨头...");}
};
animal.eat();
//查看系统分配给匿名内部类的 类名abstract class Animal {abstract void eat();
}

2. 匿名内部类发注意事项

  1. 匿名内部类的语法比较奇特,请大家注意,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
public class AnonymousInnerClassDetail {public static void main(String[] args) {Outer05 outer05 = new Outer05();outer05.f1();}
}class  Outer05 {private int n1 = 99;public void f1() {//创建一个基于类的匿名内部类Person person = new Person(){@Overridepublic void hi() {System.out.println("匿名内部类重写了 hi 方法");}};person.hi(); //动态绑定,运行类型是 Outer05$1//也可以直接调用, 匿名内部类本身也是返回对象// class 匿名内部类 extends Person{}new Person(){@Overridepublic void hi() {System.out.println("匿名内部类重写了 hi 方法,1111");}@Overridepublic void ok(String str) {super.ok(str);}}.ok("xdr");}
}
class Person {public void hi() {System.out.println("Person hi()");}public void ok(String str) {System.out.println("Person ok()" + str);}
}

  1. 可以直接访问外部类的所有成员,包含私有的
public class AnonymousInnerClassDetail {public static void main(String[] args) {Outer05 outer05 = new Outer05();outer05.f1();}
}class  Outer05 {private int n1 = 99;public void f1() {//创建一个基于类的匿名内部类Person person = new Person(){@Overridepublic void hi() {//可以直接访问外部类的所有成员,包含私有的System.out.println("匿名内部类重写了 hi 方法 n1=" + n1);}};person.hi(); //动态绑定,运行类型是 Outer05$1class Person {public void hi() {System.out.println("Person hi()");}
}

  1. 不能添加访问修饰符,因为它的地位就是一个局部变量。

  2. 作用域:仅仅在定义它的方法或代码块中。

  3. 匿名内部类——>访问——>外部类成员【访问方式:直接访问】

  4. 外部其他类——不能访问——>匿名内部类【因为匿名内部类地位是一个局部变量】

  5. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则如果想访问外部类的成员,则可以使用【外部类名.this.成员】去访问

  • 如果想访问同名外部类的话,可以使用 【外部类名.this.成员】去访问

  • 上面的 Outer05.this 就是调用 f1 的对象,谁调用 f1 对象,这个 Outer05.this 就是谁

  • 可以看到都是同一个对象,所以对象外部类去访问 n1 ,指的就是外部类的属性

3. 匿名内部类的最佳实践

  1. 当做实参直接传递,简洁高效。
  • 传统方法实现
public class InnerClassExercise01 {public static void main(String[] args) {//传统方法f1(new Picture());}//静态方法,形参是接口类型public static void f1(IL il) {il.show();}
}//类->实现IL => 编程领域 (硬编码)
class Picture implements IL {@Overridepublic void show() {System.out.println("这是一副名画...");}
}

  • 匿名内部类实现
public class InnerClassExercise01 {public static void main(String[] args) {//当做实参直接传递,简洁高效f1(new IL() {@Overridepublic void show() {System.out.println("这是一副名画~~...");}});}//静态方法,形参是接口类型public static void f1(IL il) {il.show();}
}
//接口
interface IL {void show();
}

  1. 案例2
1.有一个铃声接口Bell,里面有个ring方法。(右图)
2. 有一个手机类Cellphone,具有闹钟功能alarmclock,参数是Bell类型(如下图)
3. 测试手机类的闹钟功能,通过匿名内部类(对象)作为参数,打印:懒猪起床了
4. 再传入另一个匿名内部类(对象),打印:小伙伴上课了

  • 思路:匿名内部 (1) 继承 (2) 多态 (3) 动态绑定 (4) 内部类
public class InnerClassExercise02 {public static void main(String[] args) {CellPhone cellPhone = new CellPhone();//解读://1. 传递的是实现了 Bell接口的匿名内部类 InnerClassExercise02$1//2. 重写了 ring//3. Bell bell = new Bell() {//            @Override//            public void ring() {//                System.out.println("懒猪起床了");//            }//        }cellPhone.alarmClock(new Bell() {@Overridepublic void ring() {System.out.println("懒猪起床了");}});cellPhone.alarmClock(new Bell() {@Overridepublic void ring() {System.out.println("小伙伴上课了");}});}
}
interface Bell{ //接口void ring();//方法
}
class CellPhone{//类public void alarmClock(Bell bell){//形参是Bell接口类型System.out.Class());bell.ring();//动态绑定}
}

本文发布于:2024-01-29 17:13:23,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170651960516949.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:部类   JavaSE
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23