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天基本都是为了提升这个能力
-
类和对象
学员管理系统设计
-
学生
-
生活中通过表格来管理相同结构数据 → 学生都有姓名、年龄、班级名称、学号
姓名 | 年龄 | 班级名称 | 学号 |
---|---|---|---|
张光 | 22 | jsd2302 | 001 |
李林 | 23 | jsd2302 | 002 |
赵亮 | 21 | jsd2302 | 003 |
王鹏飞 | 24 | jsd2302 | 004 |
name1, age1, className1, stuld1
name2, age2, className2, stuld2
name3, age3, className3, stuld3
name4, age4, className4, stuld4
我们是可以把这些数据写成这样,但如果要写100个学生呢?数据就会大量重复,不成整体。我们该如何解决这个问题呢?
类和对象
-
类,变量和方法组成的一种新的数据类型 —— 引用类型
-
类中可以包含:
-
对象的属性/特征/数据,设计为成员变量
-
对象的行为/动作/功能,设计为方法
class 类名 { // 自己创造的数据类型 成员变量类型变量名; 修饰词 返回值类型方法名称([参数列表]) { 方法体 } }
如何理解面向对象?其实就像是我们造一个汽车,我们可以把汽车作为一个对象,它需要车门、车窗、发动机等,我们可以把它作为成员变量;车门可以开关,车窗可以上升下降、发动机可以被点火启动,我们就可以把它作为方法。
-
-
回到刚才的学生表,学生表中的每条记录其实都是一个对象,其中我们需要描述对象的功能就要使用到方法。下面我来写一段代码,可以根据表中内容参悟一下面向对象编程的感觉。
姓名 | 年龄 | 班级名称 | 学号 |
---|---|---|---|
张光 | 22 | jsd2302 | 001 |
李林 | 23 | jsd2302 | 002 |
赵亮 | 21 | jsd2302 | 003 |
王鹏飞 | 24 | jsd2302 | 004 |
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正在和张光一起玩...
*/
我们说,只要创建成员变量就会赋予一个初始值,none
及0
等
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("张光");
}
}