自学内容网 自学内容网

java面向对象编程--高级(二)

目录

一、内部类

1.1 成员内部类

1.1.1 静态和非静态

1.1.2 调用外部类的结构

1.2 局部内部类

1.2.1 非匿名和匿名

1.2.2 比较

1.2.3 练习

二、枚举类

2.1 枚举类讲解

2.2 代码实现

三、包装类

3.1 包装类与基本数据类型

3.2 练习

3.3 补充

四、自动生成单元测试


一、内部类

1.什么是内部类?

  • 将一个类A定义在另一个类B里面,里面的那个类A就称为`内部类(Innerclass)',类B则称为`外部类(0uterClass)

2.为什么需要内部类?

  • 当一个事物A的内部,还有一个部分需要一个完整的结构B进行描述,而这个内部的完整的结构B又只为外部事物A提供服。
  • 遵循`高内聚、低耦合'的面向对象开发原则。

3.内部类的分类

声明位置:

  • 成员内部类:直接声明在外部类中
  • 局部内部类:声明在方法内,构造器内,代码块内

1.1 成员内部类

成员内部类的理解:定义在外部类中的一个类。它可以访问外部类的所有成员,包括私有成员。

1.1.1 静态和非静态

要创建成员内部类的实例,首先需要创建外部类的实例,然后通过这个实例创建内部类的实例。

//非静态成员内部类
class Outer {
    private String Field = "外部";

    class Inner {
        void display() {
            System.out.println("访问: " + Field);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer(); // 创建外部类实例

        Outer.Inner inner = outer.new Inner(); // 创建内部类实例

        inner.display(); // 调用内部类的方法
    }
}

静态内部类不依赖于外部类的实例,可以直接通过外部类的类名来创建

//静态成员内部类
class Outer {
    private static String Field = "静态外部类";

    static class Inner {
        void display() {
            System.out.println("访问: " + Field);
        }
    }
}

public class Main {
    public static void main(String[] args) {

        Outer.Inner Inner = new Outer.Inner(); // 直接通过外部类名创建

        Inner.display(); // 调用静态内部类的方法
    }
}

1.1.2 调用外部类的结构

public class Outer {
    private String Field = "外部类的私有字段";

    // 成员内部类
    class Inner {
        void display() {
            // 直接访问外部类的私有成员
            System.out.println("访问外部类的字段: " + Field);
        }
    }

    public void createInner() {
        Inner inner = new Inner();
        inner.display();
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.createInner(); // 创建内部类并调用方法
    }
}

1.2 局部内部类

1.2.1 非匿名和匿名

package test3;

public class OuterClassTest {
    public void mathod() {
        class A {//局部内部类
            //声明属性和方法
        }
    }

    //1.提供接口实现类的对象
    public Comparable getInstance() {

        class MyComparable implements Comparable{

            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
        MyComparable myComparable =  new MyComparable();
        return myComparable;

    //2.提供接口实现类的匿名对象
   /* public Comparable getInstance() {
        class MyComparable implements Comparable{ 
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
        return new MyComparable();
    }*/
        //3.提供接口的匿名实现类的对象
        /*Comparable m = new Comparable() {

            @Override
            public int compareTo(Object o) {
                return 0;
            }
        };
        return 0;*/
        
        //4.提供接口的匿名实现类的匿名对
        /*return new Comparable(){
            @Override
            public int compareTo(Object o) {
                return 0;
            }
       };*/

    }
}

1.2.2 比较

  • 非匿名局部内部类:有名字,可以创建多个实例,可以访问方法的局部变量(需要是final或effectively final)。
  • 匿名局部内部类:没有名字,通常只用一次,方便快捷,适用于临时的任务或事件处理。

1.2.3 练习

创建一个匿名内部类,继承于Object,在其中声明一个 public void test() 打印猪八戒

public class OuterClassTest {
    public static void main(String[] args) {
        new Object(){
            public void test(){
                System.out.println("猪八戒");
            }
        }.test();

    }
}

二、枚举类

2.1 枚举类讲解

理解:枚举(enum)是一种特殊的类,用于表示一组常量。

使用:

  • 开发中,如果针对于某个类,其实例是确定个数的。则推荐将此类声明为枚举类。
  • 如果枚举类的实例只有一个,则可以看做是单例的实现方式。

枚举类实现接口的操作

  • 枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是同一个方法
  • 让枚举类的每一个对象重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是不同的实现的方法。

2.2 代码实现

例子:枚举类中创建四个季节,春夏秋冬,并实现接口操作

package test4;

import static java.time.chrono.JapaneseEra.values;

public class seasonTest {
    public static void main(String[] args) {

        Season[] values = Season.values();
        for (int i = 0; i < values().length; i++) {
            values[i].show();
        }

    }
}

interface info{
    void show();
}
enum Season implements info{//默认的父类为Object,不需要特意声明
    //枚举类开头声明变量
    SPRING("春天","生机勃勃"){
        @Override
        public void show() {
            System.out.println("春天在哪里");
        }
    },
    SUMMER("夏天","夏日炎炎"){
        @Override
        public void show() {
            System.out.println("夏天吃雪糕");
        }
    },
    AUTUMN("秋天","秋高气爽"){
        @Override
        public void show() {
            System.out.println("秋天的第一别奶茶");
        }
    },
    WINTER("冬天","白雪皑皑"){
        @Override
        public void show() {
            System.out.println("冬天吃东北烤鸡架");
        }
    };
    private final String name;
    private final String Desc;

    Season(String name, String desc) {
        this.name = name;
        Desc = desc;
    }

    public String getName() {
        return name;
    }

    public String getDesc() {
        return Desc;
    }

    @Override
    public String toString() {
        return "季节{" +
                "name='" + name + '\'' +
                ", Desc='" + Desc + '\'' +
                '}';
    }

    //情况1 :枚举类中直接重写,调用时全部一样
   /* @Override
    public void show() {
        System.out.println("这是季节中的一个");
    }*/
}

结果:

三、包装类

3.1 包装类与基本数据类型

1.为什么要使用包装类?

  • 为了使得基本数据类型的变量具备引用数据类型变量的相关特征(比如:封装性、继承性、多态性),我们给各个基本数据类型的变量都提供了对应的包装类。

2. 有哪些包装类:

3.2 练习

如何转换:
(装箱)基本数据类型--->包装类:

  • 使用包装类的构造器
  • (建议)调用包装类的value0f(xxxxX)

(拆箱)包装类--->基本数据类型: 调用包装类的xxxValue()
注意:

  • 原来使用基本数据类型变量的位置,改成包装类以后,对于成员变量来说,其默认值变化了!

1. 基本数据类型转换为包装类(装箱)

public class BoxingExample {
    public static void main(String[] args) {
        // 使用构造函数装箱
        int primitiveInt = 10;
        Integer wrappedInt = new Integer(primitiveInt);
        
        // 使用静态方法装箱
        Integer wrappedInt2 = Integer.valueOf(primitiveInt);

        System.out.println("装箱结果: " + wrappedInt);
        System.out.println("使用静态方法装箱结果: " + wrappedInt2);
    }
}

2. 包装类转换为基本数据类型(拆箱)

public class UnboxingExample {
    public static void main(String[] args) {
        // 装箱
        Integer wrappedInt = Integer.valueOf(10);
        
        // 使用方法拆箱
        int primitiveInt = wrappedInt.intValue();

        // 自动拆箱
        int autoUnboxedInt = wrappedInt; // Java 会自动转换

        System.out.println("拆箱结果: " + primitiveInt);
        System.out.println("自动拆箱结果: " + autoUnboxedInt);
    }
}

3. 自动装箱与自动拆箱

  • 自动装箱:当基本数据类型赋值给包装类时,Java 自动将其转换为相应的包装类对象。
  • 自动拆箱:当包装类对象赋值给基本数据类型时,Java 自动将其转换为相应的基本数据类型。
public class numberTest {
    int i1 = 10;
    Integer i11 = i1;
    Integer ii2 = i1+1;
     Boolean b1 = true;
     Float f1 = 12.4F;
     //上述都是自动装箱
    //下述是自动拆箱
    int i2 = i11;
    boolean b2 = b1;
    float f2 = f1;

}

3.3 补充

如下图示:

基本数据类型、包装类 ---> String类型:

  • ① 调用String的重载的静态方法value0f(xxx xx)
  • ② 基本数据类型+ " "

String类型 ---> 基本数据类型、包装类:

  • 调用包装类的静态方法:parseXxx()

代码示例:

public class numberTest {

  @Test//String类型转成基本数据类型 包装类
  public void test1(){
      String i1 = "123";
      int  a1 = Integer.parseInt(i1);
      System.out.println(a1 + 10);

      String B1 = "true";
      boolean b2 = Boolean.parseBoolean(B1);
      System.out.println(b2);

      //错误类型
      /*String  c1 = "123b";
      Integer d1 = Integer.parseInt(c1);
      System.out.println(d1);*/

  }

  @Test
  public void test2(){
      //方式1
      Integer i1 = 11;
      String i2 = String.valueOf(i1);
      System.out.println(i2);

      Boolean B1 = true;
      String b2 = String.valueOf(B1);
      System.out.println(b2);

      //方式2
      String C1 = i2+"";
      String C2 = b2+"";
      System.out.println(C2);
      System.out.println(C1);

  }

}

四、自动生成单元测试

联网的情况下,输入 @Test,出现红灯并点击,选择Junit4.x下载

由于测试单元的格式是固定的,可以在IDEA中直接设计自动生成单元测试的模板。

找到文件,点击设置

进入设置后,点击编辑器,找到实时模板

有+号点击,先生成一个模板组,命名自拟

 

选中新建的组,点击+号,生成实时模板,缩写为test,描述:自动生成单元测试提示

然后点击更改,选中java,点击确定,即可

回到IDEA中测试一遍,实验成功


原文地址:https://blog.csdn.net/m0_72047169/article/details/142891047

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!