中南林业科技大学Java实验报告六:类的特性

实验6:类的特性

6.1 实验目的

  1. 掌握类的私有成员和共有成员的定义;
  2. 掌握类的私有成员的访问方法;
  3. 理解类的构造方法的作用和执行过程;
  4. 掌握类的构造方法的定义和关键词this的使用;
  5. 类的静态变量;
  6. 掌握方法的重载。

6.2 实验内容

由实验一到实验三构建的完整Bamboo类,后面实验中用到的核心代码会单独提出来:

public class Bamboo {
    /**
     * 竹子名字
     */
    private String name;
    /**
     * 竹子年龄
     */
    private int age;
    /**
     * 高度
     */
    private float height;
    /**
     * 直径
     */
    private double diameter;
    /**
     * 设置不能超过的最大年龄
     */
    public final static int MAX_AGE = 20;
    /**
     * 类变量
     */
    public static String temp;

    /**
     * 无参构造器
     */
    public Bamboo() {
        System.out.println("无参构造器被调用");
    }

    /**
     * 全参构造器
     *
     * @param name     名字
     * @param age      年龄
     * @param height   高度
     * @param diameter 直径
     */
    public Bamboo(String name, int age, float height, double diameter) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.diameter = diameter;
        System.out.println("全参构造器被调用");
    }

    /**
     * 拷贝构造器
     *
     * @param bamboo 被拷贝的对象
     */
    public Bamboo(Bamboo bamboo) {
        this(bamboo.getName(), bamboo.getAge(), bamboo.getHeight(), bamboo.diameter);
        System.out.println("拷贝构造器被调用");
    }

    /**
     * 静态方法对实例变量和类变量进行赋值
     */
    public static void staticAssignment(){
        temp = "静态方法赋值的静态变量";
        //静态方法是在类加载时期生成的,实例变量是在类对象创建时期生成的
        //根据先后关系,我们不能直接在静态变量中赋值
        //因此在这里我们选择先创建一个对象再赋值
        Bamboo bamboo = new Bamboo();
        bamboo.name = "静态方法中创建的对象的名字";
        System.out.println("静态赋值方法中的实例变量赋值:" + bamboo.name);
    }

    /**
     * 实例方法对实例变量和类变量进行赋值
     */
    public void instanceAssignment(){
        this.name = "实例方法赋值的名字";
        temp = "实例方法赋值的静态变量";
    }

    public double volume() {
        return Math.PI * diameter / 2 * diameter / 2 * height;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > MAX_AGE) {
            System.out.println("生长年限错误");
        } else {
            this.age = age;
            System.out.println("姓名:" + this.name + " 年龄:" + this.age);
        }
    }

    public float getHeight() {
        return height;
    }

    public void setHeight(float height) {
        this.height = height;
    }

    public double getDiameter() {
        return diameter;
    }

    public void setDiameter(double diameter) {
        this.diameter = diameter;
    }
}

6.2.1 编写一个Java程序,在程序中将实验5的Bamboo(竹子)类,的成员变量age改为私有成员变量,分别编写age的set和get方法,在main方法中新建该类的对象,设置name和age,如果所设置的年龄大于20,则输出”生长年限错误”,否则输出name和age;

【前提引入】

成员变量age改为私有成员变量,并通过get和set方法进行操作,这里就体现了Java这门纯面向对象OOP语言的一个特性:封装

那这里就好好提提封装:

  • 介绍

    封装就是把抽象除的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作才能对数据进行操作

  • 好处

    1. 隐藏实现细节
    2. 可以对数据进行验证,保证安全合理性
  • 封装实现步骤

    1. 将属性进行私有化 private
    2. 提供一个公共的 set 方法,用于对属性判断并赋值
    3. 提供一个公共的 get 方法,用于获取属性的值

【Bamboo类相关核心代码】

    /**
     * 竹子名字
     */
    private String name;

    /**
     * 竹子年龄
     */
    private int age;

    /**
     * 设置不能超过的最大年龄
     */
    public final static int MAX_AGE = 20;

    /**
     * 无参构造器
     */
    public Bamboo() {
        System.out.println("无参构造器被调用");
    }

    public void setAge(int age) {
        if(age > MAX_AGE){
            System.out.println("生长年限错误");
        }else {
            this.age = age;
            System.out.println("姓名:" + this.name + " 年龄:" + this.age);
        }
    }

【运行流程】

年龄正常情况:

    public static void main(String[] args) {
        Bamboo bamboo = new Bamboo();
        bamboo.setName("正常年龄的小竹子");
        bamboo.setAge(16);
    }

年龄不正常情况:

    public static void main(String[] args) {
        Bamboo bamboo = new Bamboo();
        bamboo.setName("不正常年龄的小竹子");
        bamboo.setAge(25);
    }

image-20220927194554868

6.2.2 为Bamboo类添加三个构造方法:其中无参构造方法为输出“Bamboo()构造方法被调用”;以及带有与所有成员变量参数个数和类型相同的构造方法;参数为Bamboo类自身的拷贝构造方法,该法采用this关键字调用第2个构造方法(具体构建参照PPT)。同时在每个构造方法中要输出“XXX构造方法被调用”。最后在main方法中分别调用三种构造方法创建类的对象。

【前提引入】

1️⃣ 构造方法又叫构造器,是类的一种特殊方法,它的主要作用是完成对新对象的初始化

[访问修饰符] 方法名(形参列表){
    方法体;
}

🌿 说明:

  1. 构造器的修饰符可以默认
  2. 构造器没有返回值
  3. 方法名和类名必须一样
  4. 构造器的调用,是系统自动完成的(new 时)

🌿 细节说明:

  1. 一个类可以有多个构造器,即构造器重载

  2. 如果程序员没有自定义类的构造器,那么系统会自动给类生成一个默认的无参构造器,也叫默认构造器

    💬 这里我们用javap反编译指令演示一下

    • 定义一个HelloWorld类,我们就来一个空类,免麻烦

      class HelloWorld{
          
      }
      
    • 使用 javac编译指令生成字节码二进制文件 HelloWorld.class

      image-20221004202749154

    • 使用 javap反编译指令 查看代码,就可以看到生成的无参构造器了(红色框框)

      image-20221004203123275

  3. 一旦程序员定义了自己的构造器,默认的无参构造器就被覆盖了,就不能再使用默认的无参构造器了,除非程序员自己显示的定义一下

2️⃣ 讲到构造器,就又可以谈谈与涉及到构造器的对象创建流程

  1. 类加载:方法区中加载类信息(只会加载一次)
  2. 在堆中分配空间(地址)
  3. 完成对象初始化
    1. 默认初始化
    2. 显示初始化
    3. 构造器初始化
  4. 将对象在堆中的地址返回给栈中的对象引用

【Bamboo类相关核心代码】

    /**
     * 无参构造器
    */
    public Bamboo() {
        System.out.println("无参构造器被调用");
    }

	/**
     * 全参构造器
     *
     * @param name     名字
     * @param age      年龄
     * @param height   高度
     * @param diameter 直径
     */
    public Bamboo(String name, int age, float height, double diameter) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.diameter = diameter;
        System.out.println("全参构造器被调用");
    }

    /**
     * 拷贝构造器
     *
     * @param bamboo 被拷贝的对象
     */
    public Bamboo(Bamboo bamboo) {
        this(bamboo.getName(), bamboo.getAge(), bamboo.getHeight(), bamboo.diameter);
        System.out.println("拷贝构造器被调用");
    }

【运行流程】

    public static void main(String[] args) {
        //调用无参构造器
        Bamboo bamboo1 = new Bamboo();
        //调用全参构造器
        Bamboo bamboo2 = new Bamboo("小竹子", 18, 5.0f, 0.5);
        //调用全参构造器和拷贝构造器
        Bamboo bamboo3 = new Bamboo(bamboo2);
    }

image-20220927195215381

6.2.3 在Bamboo类中增加一个类变量,新建一个无参的静态方法对实例变量和类变量进行赋值,新建一个无参的对象方法对实例变量和类变量进行赋值,在main方法中分别调用上面两个方法,并分别显示其值(无需对Bamboo类中的所有实例变量进行赋值)。

【前提引入】

1️⃣ 类变量

类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,去到的都是相同的值,同样任何一个类的对象去修改它时,修改的也是同一个变量。

🌿 定义类变量

访问修饰符 static 数据类型 变量名;

🌿 访问类变量

类名.变量名 //推荐

对象名.变量名

2️⃣ 类方法

当方法中不涉及到任何和对象相关的成员,则可以将方法设计为静态方法,提高开发效率。

在程序实际开发中,往往会将一些通用的方法,设计成静态方法,这样就不需要创建对象就可以使用了,比如对数组排序,完成某个计算任务等

🌿 定义类方法

访问修饰符 static 返回值数据类型 方法名(形参列表){
    
}

🌿 访问类方法

类名.方法名(实参列表); //推荐

对象名.方法名(实参列表);

3️⃣ 注意事项

  • 类方法,类变量和普通方法都是随着类的加载而加载,将结构信息存储在方法去。类方法中无this参数,普通方法中含有。而普通属性(也叫成员属性)是随着对象的创建而创建,随着对象的销毁而销毁。

  • 类方法中只能访问当前本类的类方法或静态变量,普通成员方法即可以访问非静态成员,也可以访问静态成员。

    其实也很理解为什么类方法不能访问当前本类的成员属性,因为类方法是在类加载时期就生成了,而成员属性是在对象创建时才生成。所以你想想,如果类加载时期在类方法中有了成员属性,但对象是在类加载之后才可以生成,这不很矛盾吗,这个成员属性该属于哪个对象呢?类加载时期对象还没生成呢!

【Bamboo类相关核心代码】

    /**
     * 竹子名字
     */
    private String name;

    /**
     * 类变量
     */
    public static String temp;

    /**
     * 静态方法对实例变量和类变量进行赋值
     */
    public static void staticAssignment(){
        temp = "静态方法赋值的静态变量";
        //静态方法是在类加载时期生成的,实例变量是在类对象创建时期生成的
        //根据先后关系,我们不能直接在静态变量中赋值
        //因此在这里我们选择先创建一个对象再赋值
        Bamboo bamboo = new Bamboo();
        bamboo.name = "静态方法中创建的对象的姓名";
    }

    /**
     * 实例方法对实例变量和类变量进行赋值
     */
    public void instanceAssignment(){
        this.name = "实例方法赋值的名字";
        temp = "实例方法赋值的静态变量";
    }

【运行流程】

    public static void main(String[] args) {
        Bamboo bamboo = new Bamboo();
        bamboo.instanceAssignment();
        System.out.println("实例方法 —— name:" + bamboo.getName() + " temp:" + Bamboo.temp);
        System.out.println("=========================================");
        bamboo.staticAssignment();
        System.out.println("实例方法 —— temp:" + Bamboo.temp);
    }

image-20220927202128009

6.2.4 编写一个Java程序,构造一个类,分别用方法的重载计算长方体体积,圆柱体和球体的体积,并在main方法中设置和输出结果。

【前提引入】

谈谈 方法重载

1️⃣ 基本介绍

Java中允许一个类中多个同名方法的存在,但要求形参列表不一致。

2️⃣ 重载的好处

  • 减轻了记名的麻烦
  • 减轻了起名的麻烦

3️⃣ 注意事项

  • 方法名:必须相同
  • 形参列表:必须不相同——形参类型或个数或顺序至少有一个不同,参数名相不相同无所谓,即方法重载与参数名无关
  • 返回类型:无要求,如参数名一样,可相同可不同

【构建的类代码】

public class Util {
    /**
     * 计算长方体的体积
     *
     * @param length 长
     * @param width  宽
     * @param height 高
     * @return 长方体体积
     */
    public static double cal(double length, double width, double height) {
        return length * width * height;
    }

    /**
     * 计算圆柱体的体积
     *
     * @param r      半径
     * @param height 高
     * @return 圆柱体体积
     */
    public static double cal(double r, double height) {
        return Math.PI * r * r * height;
    }

    /**
     * 计算球体的体积
     *
     * @param r 半径
     * @return 球体体积
     */
    public static double cal(double r) {
        return Math.PI * r * r * r * 4 / 3;
    }
}

【运行流程】

public static void main(String[] args) {
    //求长2,宽3,高4的长方体体积
    System.out.println("长方体体积:" + Util.cal(2, 3, 4));
    //求半径2,高3的圆柱体体积
    System.out.println("圆柱体体积:" + Util.cal(2, 3));
    //求半径为2的球体的体积
    System.out.println("球体体积:" + Util.cal(2));
}

image-20221004205900035

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是谢添啊

感谢你的支持,我会继续加油的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值