【JAVA OOP】Day07 类和对象、this关键字、构造方法、成员变量与局部变量的区别、方法的重载、对象内存


Day07目标:

  • 理解什么是类?什么是对象?类和对象的关系

  • 掌握如何创建类、如何创建对象

  • 掌握如何访问类中成员

  • 掌握this的作用及用法

  • 掌握构造方法的作用及用法

  • 代码量:220行


类和对象

面向对象引言

面向过程与面向对象

  • 面向过程:

    • 方法为单位来解决问题的编程方式

    • 适合简单的业务(把大象装进冰箱、去银行取钱…)

  • 面向对象:

    • 对象为单位来解决问题的编程方式

    • 适合复杂的业务(造个汽车、造个航母…)

OO、OOA、OOD、OOP

  • OO(Object - Oriented):面向对象 —— 面向对象大牛 - LEVEL MAX

  • OOA(Object-Oriented Analysis):面向对象分析 —— 再升级 - LEVEL3

  • OOD(Object-Oriented Design):面向对象设计 —— 有经验了升级 - LEVEL2

  • OOP(Object-Oriented Programming):面向对象编程 —— 要参与的 - LEVEL1

高质量代码要素

  • 要求:→ 拿年薪

    • 性能好

    • 可读性好

    • 健壮性好

    • 移植性好

    • 维护性好

    • 扩展性好

    • 复用性好 —— OOP一共学习5天基本都是为了提升这个能力

类和对象

学员管理系统设计

  • 学生

  • 生活中通过表格来管理相同结构数据 → 学生都有姓名、年龄、班级名称、学号

姓名年龄班级名称学号
张光22jsd2302001
李林23jsd2302002
赵亮21jsd2302003
王鹏飞24jsd2302004
name1, age1, className1, stuld1
name2, age2, className2, stuld2
name3, age3, className3, stuld3
name4, age4, className4, stuld4

我们是可以把这些数据写成这样,但如果要写100个学生呢?数据就会大量重复,不成整体。我们该如何解决这个问题呢?

类和对象

  • 类,变量和方法组成的一种新的数据类型 —— 引用类型

  • 类中可以包含:

    • 对象的属性/特征/数据,设计为成员变量

    • 对象的行为/动作/功能,设计为方法

      class 类名 { // 自己创造的数据类型
        成员变量类型变量名;
          
        修饰词 返回值类型方法名称([参数列表]) {
          方法体
        }
      }
    

    如何理解面向对象?其实就像是我们造一个汽车,我们可以把汽车作为一个对象,它需要车门、车窗、发动机等,我们可以把它作为成员变量;车门可以开关,车窗可以上升下降、发动机可以被点火启动,我们就可以把它作为方法。

  • 回到刚才的学生表,学生表中的每条记录其实都是一个对象,其中我们需要描述对象的功能就要使用到方法。下面我来写一段代码,可以根据表中内容参悟一下面向对象编程的感觉。

姓名年龄班级名称学号
张光22jsd2302001
李林23jsd2302002
赵亮21jsd2302003
王鹏飞24jsd2302004
package day07;

// 学生类
public class Student {

    // 成员变量 ———— 用来描述对象的属性  // 表头对应成员变量
    String name;
    int age;
    String className;
    String stuId;

    // 方法 ———— 用于描述对象的行为
    void study() {
        System.out.println(name + "在学习...");
    }

    void sayHi() {
        System.out.println("大家好,我叫" + name + "今年" + age + "岁了,所在班级为" + className + "学号为:" + stuId);
    }

    void playWith(String anotherName) {
        System.out.println(name + "正在和" + anotherName + "一起玩...");
    }
}

表格中的每一条我们叫做记录,前文我们提到了,表中的每条记录我们都称之为对象,如果我们现在要创建一个对象,例如说:张光这条记录,那我先就需要创建对象,我们称这种方式为实例化,实例化的语法格式为:

    // new 类名();
    new Student();

引用类型变量

  • 为了能够对实例化的对象进行访问控制,需要使用一个特殊的变量 —— 引用类型变量

      数据类型 引用  指向      对象
      Student student = new Student();
    // 句意:声明了Student类类型的引用student,指向了一个对象
    

访问对象的成员变量、调用方法

  • 通过引用名打点来访问对象的成员变量或调用方法:
  Student zg = new Student();
  zg.name = "张光";
  zg.age = 22;
  zg.className = "jsd2302";
  zg.stuld = "001";
  zg.study();
  // 这样我们就成功的给张光对象赋予了他的数据了
  • 如何实践操作试试成功了吗?我们首先需要给Student类创建一个测试类(也就是main方法),右击day07包,创建一个StudentTest类,写入主方法,例如下面的代码:
package day07;

// Student类的测试类
public class StudentTest {
    public static void main(String[] args) {
        // 创建一个Student对象
        Student zg = new Student();
        // 访问成员变量
        zg.name = "张光";
        zg.age = 22;
        zg.className = "jsd2302";
        zg.stuId = "001";
        // 调用方法
        zg.study();
        zg.sayHi();
        zg.playWith("李林");
    }
}

我们要注意一个问题,如果我们不给成员变量值的话,会自动获取其类型的默认值,我们刚才没有做初始化工作,但一样可以输出,只会有点奇怪,示例如下:

package day07;

// Student类的测试类
public class StudentTest {
    public static void main(String[] args) {
        zl.study();
        zl.sayHi();
        zl.playWith("张光");
    }
}
// 我们发现一样不报错可以输出,但结果很奇怪

/*

大家好,我叫null今年0岁了,所在班级为null学号为:null
null正在和张光一起玩...

*/

我们说,只要创建成员变量就会赋予一个初始值,none0

this与构造方法

this的作用

  • 只能用在方法中,方法中访问成员变量之前默认都有this
  class Student{
    String name;
    int age;
    String className;
    String stuId;
    
    void study() {
      System.out.println(this.name + "在学习...");
    }
  }
  • this指代当前对象,哪个对象调用方法,this指的就是哪个对象。
Student zg = new Student();
zg.name = "张光";
......
zg.study();  // study()中的this指代的是zg所指代的对象

Student ll = new Student();
ll.name = "李林";
......
ll.study();  // study()中的this指代的是ll所指代的对象
  • 这样好像太难理解了,下面我给大家来一个更生动地例子:
package day07;

// 学生类
public class Student {

    String name;
    int age;
    String className;
    String stuId;

  // 有没有注意到一个问题,我们这里造方法的时候没有参数,为什么会把值传过来
  // 其实在Java中,我们创建的无参方法,默认会给我们一个参数
    void study() {
      // 其实这个位置的name,在Java中指的是this.name,只不过Java帮我们自动隐藏了
      // 其实这里的this指的就是你要在测试类中给定的变量,我们以zg为例,这个位置其实本身的意思就是:
      //                    zg.name
        System.out.println(this.name + "在学习...");
    }

    void sayHi() {
      // 同理                               zg.name              zg.age
        System.out.println("大家好,我叫" + this.name + "今年" + this.age + "岁了,所在班级为" + this.className + "学号为:" + this.stuId);
    }

    void playWith(String anotherName) {
        System.out.println(this.name + "正在和" + anotherName + "一起玩...");
    }
}

// 这是两个类,不是同一个文件,上面是我们自己建的Student类,下面是主方法的测试类

package day07;

// Student类的测试类
public class StudentTest {
    public static void main(String[] args) {
        Student zg = new Student();
        zg.name = "张光";  // 所以我们这里可以去把zg这个引用变量带入到参数this中
        zg.age = 22;
        zg.className = "jsd2302";
        zg.stuId = "001";
        zg.study();
        zg.sayHi();
        zg.playWith("李林");
    }
}

构造方法的作用

  • 作用:给成员变量赋初始值,构造方法也叫构造函数、构造器、构建器。
  Student zg = new Student();
  zg.name = "张光";
  zg.age = 25;
  zg.className = "jsd2302";
  zg.stuId = "001";

  Student ll = new Student();
  zg.name = "李林";
  zg.age = 23;
  zg.className = "jsd2302";
  zg.stuId = "002";

我们发现刚才写的这段代码下面都是重复的,我们为了避免这种情况,所以要使用构造方法去使代码清晰简单。

  • 语法:与类同名,没有返回值类型(连void都没有)
  class Student {
    String name;
    int age;
    String className;
    String stuId;
    
    // 这就是创建了一个构造方法,想构造哪些就给哪些加构造方法
    Student() {
    }
    
    void study() {
      System.out.println(this.name + "在学习......");
    }
  }

实际上,我们应该这样写:

  class Student {
    String name;
    int age;
    String className;
    String stuId;
    
    // 不需要变的不加参,谁变加谁,这里被使用的数据一直在变,所以全部加入构造方法
    Student(String name1, int age1, String className1, String stuId1) {
      // 内部要给这四个要被赋值的成员变量赋值
      this.name = name1;
      this.age = age1;
      this.className = className1;
      this.stuId = stuId1;
      // 在这里会出现一个问题,就是我们在写完这段代码后,上面会提示出现三个关联错误,这时候我们不必理会,关联错误是指由于我们这段代码导致其他文件中有语句报错,是因为我们这里传入了参数,但是没有通过调用构造方法给入参数,在我们的测试类中出错
    }
    
    void study() {
      System.out.println(this.name + "在学习......");
    }
  }
  • 调用:在创建(new)对象时被自动调用
  Student zs = new Student();  // 这是我们之前在主方法中用于创建实例化的代码,这里我们调用Student的构造方法的代码,没修改时报错,是由于刚刚我们在构造方法中设计了参数,但这里没有参数,所以我们需要在这里传入参数,就会结束报错
  
  // 当我们在测试类这样写,就做到了对Student类中的构造方法传入了参数,给了每一个成员变量初始值
  Student zs = new Student("张光", 25, "jsd2302", "001");
  Student zs = new Student("李四", 24, "jsd2302", "002");
  • 若自己不写构造方法,则编译器默认提供一个无参构造方法

  • 若自己写了构造方法,则不再默认提供

  • 那如果我又想写有参,又想写无参怎么办?—— 构造方法可以重载

  class Student {
    String name;
    ......
    Student() {  // 无参的
    ......
    }
    // 有参的
    Student (String name1, int age1, String className1, String stuId1) {
      this.name = name1;
      this.age = age1;
      this.className = className1;
      this.stuId = stuId1;
    }
    void study() {
      System.out.println(this.name + "在学习");
    }
  } 
  • 我们可以再次新建一个测试类,起名为ConsDemo,更清晰的观察两种调用构造方法:
package day07;

// 构造方法的演示 - 新的测试类
public class ConsDemo {
    public static void main(String[] args) {
        // 调用Student类 - 无参构造方法
        Student zg = new Student();
        zg.name = "张光";
        zg.age = 25;
        zg.className = "jsd2304";
        zg.stuId = "001";

        zg.study();
        zg.sayHi();
              
        System.out.println("———————————————————————————————————————————");

        // 调用Student()类 - 有参构造方法
        Student ll = new Student("李林", 24, "jsd2304", "002");
        // 同理
        Student zl = new Student("赵亮", 21, "jsd2304", "003");

        ll.study();
        ll.sayHi();
        zl.study();
        zl.sayHi();
    }
}

成员变量与局部变量

  • 方法外的变量叫做成员变量,方法内的变量叫做局部变量。

  • 成员变量和局部变量是可以同名的,虽然可以同名,但是它们的作用域不同。

    • 成员变量可以作用于整个类中

    • 局部变量是能在当前方法中使用。

  • 使用的时候默认采取的是就近原则

    • 如果我们要在方法中使用成员变量时,this不能省略,如果加了this则是访问成员变量。
package day07;

// 学生类
public class Student {

    // 成员变量
    String name;
    int age;
    String className;
    String stuId;

    // 构造方法同名时,this不能省略
    Student(String name, int age, String className, String stuId) {  // 局部变量
        this.name = name;  // 这里指的是:成员变量 = 局部变量
        this.age = age;  // 这里指的是:成员变量 = 局部变量
        this.className = className;  // 这里指的是:成员变量 = 局部变量
        this.stuId = stuId;  // 这里指的是:成员变量 = 局部变量
    }

    void study() {
        System.out.println(this.name + "在学习...");  // 这里指的是成员变量
    }

    void sayHi() {
        System.out.println("大家好,我叫" + name + "今年" + age + "岁了,所在班级为" + className + "学号为:" + stuId);  // 这里指的是成员变量,name变量前面的(this.)完全可以省略
    }

    void playWith(String anotherName) {
        System.out.println(name + "正在和" + anotherName + "一起玩...");  //这里也是
    }
}

this的用法

  • this.成员变量名 ———— 访问成员变量

    • 因为我们要区分成员变量和局部变量,所以常用
  • this.方法名() ———— 调用方法 (很少用到)

    • 方法绝对不可能出现一样的,所以没有必要加
  • this() ———— 调用构造方法

    • 这种方法也不常用,一般用于Java开发者创造构造方法,方便再构造中调用构造来节省代码。
package day07;

public class Student {

    String name;
    int age;
    String className;
    String stuId;

    Student(String name, int age, String className, String stuId) {
        this.name = name;
        this.age = age;
        this.className = className;
        this.stuId = stuId;
    }
    
    Student() {
        this("无名氏", 1, "未知", "未知");  // 在无参构造中调用有参构造
    }

    void study() {
        System.out.println(this.name + "在学习...");
    }

    void sayHi() {
        System.out.println("大家好,我叫" + name + "今年" + age + "岁了,所在班级为" + className + "学号为:" + stuId);
    }

    void playWith(String anotherName) {
        System.out.println(name + "正在和" + anotherName + "一起玩...");
    }
}

面向对象编程实战


需求:

  • 类名:Car汽车类

  • 成员变量:品牌(brand)、颜色(color)、价格(price)

  • 构造方法:Car()Car(3个参数)

  • 方法:启动start()、跑run()、停stop()

  • 要求方法中输出:

    • ???牌子的???颜色的???块的汽车启动了…

    • ???牌子的???颜色的???块的汽车开始跑了…

    • ???牌子的???颜色的???块的汽车停止了…


方法类:(Car.java

package day07;

public class Car {
    // 定义成员变量
    String brand;
    String color;
    double price;

    // 构造方法 - 无参构造
    Car() {

    }

    // 构造方法 - 有参构造
    Car(String brand, String color, double price) {
        this.brand = brand;
        this.color = color;
        this.price = price;
    }

    // 功能1:启动  输出:???牌子的???颜色的???块的汽车启动了...
    void start() {
        System.out.println(this.brand + "品牌的" + this.color + "颜色的" + this.price + "块的汽车启动了...");
    }

    // 功能2:跑  输出:开始跑了
    void run() {
        System.out.println(this.brand + "品牌的" + this.color + "颜色的" + this.price + "块的汽车开始跑了......");
    }

    // 功能3:停  输出:停止了
    void stop() {
        System.out.println(this.brand + "品牌的" + this.color + "颜色的" + this.price + "块的汽车停止了......");
    }

}

测试类:(CarTest.java

package day07;

public class CarTest {
    public static void main(String[] args) {
        // 使用无参构造方法
        Car car1 = new Car();
        car1.brand = "奥迪";
        car1.color = "黑";
        car1.price = 20000000;
        car1.start();
        car1.run();
        car1.stop();

        System.out.println("———— 间 ——— 隔 ————");

        // 使用有参构造方法
        Car audi = new Car("奥迪", "黑", 20000000);
        audi.start();
        audi.run();
        audi.stop();
    }
}

对象内存

内存管理(了解)

  • Java内存都是由JVM(Java虚拟机)来管理的;

    • 堆:new出来的所有对象(包括实例变量 —— 成员变量、数组的元素、方法的地址)

    • 栈:局部变量(包括方法的参数)

    • 方法区:.class字节码文件(包括所有方法、静态变量)

在这里插入图片描述

本节代码:

student.java

package day07;

// 学生类
public class Student {

    // 成员变量 ———— 用来描述对象的属性
    String name;
    int age;
    String className;
    String stuId;

    // 构造方法 - 有参构造
    Student(String name1, int age1, String className1, String stuId1) {
        this.name = name1;
        this.age = age1;
        this.className = className1;
        this.stuId = stuId1;
    }

    // 构造方法 - 无参构造, 加入以后,报错消失
    Student() {

    }

    // 方法 ———— 用于描述对象的行为
    void study() {
        System.out.println(name + "在学习...");
    }

    void sayHi() {
        System.out.println("大家好,我叫" + name + "今年" + age + "岁了,所在班级为" + className + "学号为:" + stuId);
    }

    void playWith(String anotherName) {
        System.out.println(name + "正在和" + anotherName + "一起玩...");
    }
}

StudentTest.java

package day07;

// Student类的测试类
public class StudentTest {
    public static void main(String[] args) {
        // 创建一个Student对象
        Student zg = new Student();
        // 访问成员变量
        zg.name = "张光";
        zg.age = 22;
        zg.className = "jsd2302";
        zg.stuId = "001";
        // 调用方法
        zg.study();
        zg.sayHi();
        zg.playWith("李林");

        Student ll = new Student();
        ll.name = "李林";
        ll.age = 23;
        ll.className = "jsd2302";
        ll.stuId = "002";

        ll.study();
        ll.sayHi();
        ll.playWith("张光");

        Student zl = new Student();

        zl.study();
        zl.sayHi();
        zl.playWith("张光");
    }
}

ConsDemo.java

package day07;

// Student类的测试类
public class StudentTest {
    public static void main(String[] args) {
        // 创建一个Student对象
        Student zg = new Student();
        // 访问成员变量
        zg.name = "张光";
        zg.age = 22;
        zg.className = "jsd2302";
        zg.stuId = "001";
        // 调用方法
        zg.study();
        zg.sayHi();
        zg.playWith("李林");

        Student ll = new Student();
        ll.name = "李林";
        ll.age = 23;
        ll.className = "jsd2302";
        ll.stuId = "002";

        ll.study();
        ll.sayHi();
        ll.playWith("张光");

        Student zl = new Student();

        zl.study();
        zl.sayHi();
        zl.playWith("张光");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值