Java面向对象(内部类)(枚举)(泛型)

痛定思痛。 2024-03-23 22:53 159阅读 0赞

内部类

内部类是五大成员之一(成员变量、方法、构造方法、代码块、内部类);

一个类定义在另一个类的内部,就叫做内部类;

当一个类的内部,包含一个完整的事物,且这个事务不必单独设计,就可以把这个事务设计为内部类;

  1. Public class Car{
  2. //内部类
  3. Public class Engine{
  4. }
  5. }

内部类的四种形式:

成员内部类; 静态内部类; 局部内部类;匿名内部类

成员内部类

定义在成员位置的类,叫做成员内部类;

  1. public class Outner {
  2. private String name = "科比";
  3. private int age = 43;
  4. //访问内部类的成员变量及方法
  5. public static void main(String[] args) {
  6. //创建内部类的对象
  7. Inner inner = new Outner().new Inner();
  8. inner.test();
  9. }
  10. //成员内部类
  11. public class Inner{
  12. private String name = "詹姆斯";
  13. private int age = 38;
  14. public void test(){
  15. //访问内部类的成员变量
  16. System.out.println(name);
  17. System.out.println(age);
  18. //访问内部类的成员变量
  19. System.out.println(Outner.this.name);
  20. System.out.println(Outner.this.age);
  21. }
  22. }
  23. }

创建内部类的对象:new 外部类().new 内部类();

在内部类中调用外部类的成员变量: 外部类.this.外部类的成员变量;

#
静态内部类

在内部类中用static修饰的内部类叫做静态内部类;

  1. public class Outner {
  2. static String name = "科比";
  3. private int age = 43;
  4. public static void main(String[] args) {
  5. //创建内部类的对象
  6. new Outner.Inner().test();
  7. }
  8. static class Inner{
  9. public void test(){
  10. //访问外部类的静态方法,非静态方法访问不到;
  11. System.out.println(Outner.name);
  12. // System.out.println(Outner.this.age); 报错
  13. }
  14. }
  15. }

静态内部类只能调用外部类的静态变量;

创建内部类对象:new 外部类.内部类();

局部内部类

局部内部类是定义在方法中的类,和局部变量一样,只能在方法中有效。所以局部内部类的局限性很强,一般在开发中是不会使用的。

  1. public class Outer{
  2. public void test(){
  3. //局部内部类
  4. class Inner{
  5. public void show(){
  6. System.out.println("Inner...show");
  7. }
  8. }
  9. //局部内部类只能在方法中创建对象,并使用
  10. Inner in = new Inner();
  11. in.show();
  12. }
  13. }

局部内部类只能在方法中创建对象,局限性比较强,所以开发中一般不会使用;

匿名内部类

匿名内部类是一种特殊的局部内部类,因为不需要声明名字,所以叫做匿名内部类;

  1. new 父类/接口(参数值){
  2. @override
  3. 重写父类或者接口的方法
  4. }

匿名内部类时间上是一个没有名字的子类对象,或者接口实现类的无名对象

  1. public class Dome01 {
  2. public static void main(String[] args) {
  3. //匿名内部类的实现
  4. new Animal(){//符合多态思想的:编译看左,运行看右思想;
  5. @Override
  6. public void cry() {
  7. System.out.println("狗叫旺旺旺");
  8. }
  9. }.cry();//匿名对象直接调用Animal的cry方法
  10. }
  11. }
  12. //创建一个动物的抽象类
  13. abstract class Animal{
  14. public abstract void cry();
  15. }

需要注意的是,匿名内部类在编写代码时没有名字,编译后系统会为自动为匿名内部类生产字节码,字节码的名称会以外部类$1.class的方法命名

7f42188e141c46e2b1a6c3c9917648e8.png

匿名内部类的作用:简化了创建子类对象、实现类对象的书写格式。

匿名内部类的应用场景

只有在调用方法时,当方法的参数是一个接口或抽象类时,为了简化书写代码,而直接传递匿名内部类给方法。

  1. public class Dome01 {
  2. public static void main(String[] args) {
  3. //匿名内部类对象1
  4. new Swimming(){
  5. @Override
  6. public void swim() {
  7. System.out.println("狗游泳飞快");
  8. }
  9. }.swim();
  10. //匿名内部类对象2
  11. new Swimming(){
  12. @Override
  13. public void swim() {
  14. System.out.println("猫不会游泳");
  15. }
  16. }.swim();
  17. }
  18. public void go(Swimming s){//将接口Swimming作为形参
  19. System.out.println("开始比赛");
  20. s.swim();
  21. System.out.println("结束比赛");
  22. }
  23. }
  24. interface Swimming{//接口
  25. public void swim();
  26. }

枚举

枚举是一种特殊的类,它的格式:

  1. Public enum A{
  2. X,Y,Z
  3. }

其中XYZ叫做枚举项,它属于枚举的一个对象。想要获得枚举对象只需要用枚举名调用;

  • 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象。
  • 枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象。
  • 枚举都是最终类,不可以被继承。
  • 枚举类中,从第二行开始,可以定义类的其他各种成员。 编译器为枚举类新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从enum类也会继承到一些方法。

    public class Test{

    1. public static void main(String[] args){
    2. //获取枚举A类的,枚举项
    3. A a1 = A.X;
    4. A a2 = A.Y;
    5. A a3 = A.Z;
    6. }

    }

通过反编译的形式来验证(需要用到反编译的命令,这里不能直接将字节码拖进idea反编译)

7a2d082c1d4b42c4bc0e2ffe3c4c4a08.png

枚举类A是用class定义的,说明枚举确实是一个类,而且X,Y,Z都是A类的对象;而且每一个枚举项都是被public static final修饰,所以可以类名调用,而且不能更改。

枚举类的应用场景

枚举一般表示一组信息,然后作为参数进行传输。

我们来看一个案例。比如我们现在有这么一个应用,用户进入应用时,需要让用户选择是女生、还是男生,然后系统会根据用户选择的是男生,还是女生推荐不同的信息给用户观看。

0aee6424ae5a49fab5f3b68febc65ed3.png

  1. public class Dome01 {
  2. public static void main(String[] args) {
  3. get(GENDER.BOY);
  4. get(GENDER.GIRL);
  5. }
  6. public static void get(GENDER gender){
  7. if (gender == GENDER.BOY){
  8. System.out.println("男生观看");
  9. }else {
  10. System.out.println("女生观看");
  11. }
  12. }
  13. }
  14. enum GENDER{
  15. BOY,GIRL
  16. }

最终再总结一下枚举的应用场景:枚举一般表示几个固定的值,然后作为参数进行传输

枚举设计单例设计模式

单例设计模型也可以使用枚举进行设计,

  1. public class dome01 {
  2. public static void main(String[] args) {
  3. Singleton instance1 = Singleton.INSTANCE;
  4. Singleton instance2 = Singleton.INSTANCE;
  5. System.out.println(instance2 == instance1);//判断两个对象的地址值,确定只能创建一个对象
  6. }
  7. }
  8. enum Singleton{
  9. INSTANCE;
  10. public void method(){
  11. System.out.println("我是一个单例");
  12. }
  13. }

泛型

认识泛型

所谓泛型就是在定义类、接口、方法的时候同时声明一个或者多个类型变量,称为泛型类,泛型接口,泛型方法。

d68b2bdcb29146bf93c07a41f0300427.png

  • 泛型的好处:在编译阶段可以避免出现一些非法的数据。
  • 泛型的本质:把具体的数据类型传递给类型变量。
自定义泛型
  1. //这里的<T,W>其实指的就是类型变量,可以是一个,也可以是多个。
  2. public class 类名<T,W>{
  3. }
ArrayList的底层实现
  1. //定义一个泛型类,用来表示一个容器
  2. //容器中存储的数据,它的类型用<E>先代替用着,等调用者来确认<E>的具体类型。
  3. public class MyArrayList<E>{
  4. private Object[] array = new Object[10];
  5. //定一个索引,方便对数组进行操作
  6. private int index;
  7. //添加元素
  8. public void add(E e){
  9. array[index]=e;
  10. index++;
  11. }
  12. //获取元素
  13. public E get(int index){
  14. return (E)array[index];
  15. }
  16. }

测试类,来测试自定义的泛型类MyArrayList是否能够正常使用

  1. public class Test{
  2. public static void main(String[] args){
  3. //1.确定MyArrayList集合中,元素类型为String类型
  4. MyArrayList<String> list = new MyArrayList<>();
  5. //此时添加元素时,只能添加String类型
  6. list.add("张三");
  7. list.add("李四");
  8. //2.确定MyArrayList集合中,元素类型为Integer类型
  9. MyArrayList<Integer> list1 = new MyArrayList<>();
  10. //此时添加元素时,只能添加String类型
  11. list.add(100);
  12. list.add(200);
  13. }
  14. }

发表评论

表情:
评论列表 (有 0 条评论,159人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java基础 :内部

    泛型提供了在编译阶段 约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常,保证所操作的数据类型的统一。定义类,接口,方法时,声明一...

    相关

        泛型:         jdk1.5版本之后出现的新特性,用于解决安全问题,是一个安全机制.         泛型格式;通过<>定义操作的引用数据类型,在jav