1、类与对象
1.1、养猫小案例
张三养了两只猫猫:一只名字叫小白,今年 3 岁,白色。还有一只叫小花,今年 100 岁,花色。请编写一个程序,当用户 输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示
张三没有这只猫猫。
1.1.1、使用现有技术解决
- 单独的定义变量解决
- 使用数组解决
1.1.2、现有技术解决的缺点分析
不利于数据的管理 效率低 ===> 引出我们的新知识点 类与对象 哲学, 道家思想 java 设计者 引入 类与对象(OOP) ,根本原因就是现有的技术,不能完美的解决新的新的需求
1.1.3、传统方式实现
public static void main(String[] args) {
// 张三养了两只猫猫:一只名字叫小白,今年 3 岁,白色。
// 还有一只叫小花,今年 100 岁,花色。
// 请编写一个程序,当用户 输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示
// 张三没有这只猫猫。
// 单独变量来解决 => 不利于数据的管理(你把一只猫的信息拆解)
// 第 1 只猫信息
String cat1Name = "小白";
int cat1Age = 3;
String cat1Color = "白色";
//第 2 只猫信息
String cat2Name = "小花";
int cat2Age = 100;
String cat2Color = "花色";
//数组 ===> (1)数据类型体现不出来 (2)只能通过[下标]获取信息,造成变量名字和内容的对应关系不明确 (3)不能体现猫的行为
//第 1 只猫信息
String[] cat1 = {"小白", "3", "白色"};
//第 2 只猫信息
String[] cat2 = {"小花", "100", "花色"};
}
1.1.4、使用OOP面向对象解决
public class objectClass_ {
public static void main(String[] args) {
// (1) 实例化一只猫[创建一只猫对象]
// (2) 把创建的猫赋给 cat1
// (3) cat1 就是一个对象
// 第一只猫的信息
Cat cat1 = new Cat();
cat1.name = "小白";
cat1.age = 10;
cat1.color = "白色";
cat1.weight = 10;
// 第二只猫的信息
Cat cat2 = new Cat();
cat2.name = "小花";
cat2.age = 100;
cat2.color = "花色";
cat2.weight = 20;
System.out.println("第1只猫信息" + cat1.name + " " + cat1.age + " " + cat1.color + " " + cat1.weight);
System.out.println("第2只猫信息" + cat2.name + " " + cat2.age + " " + cat2.color + " " + cat2.weight);
}
}
class Cat {
String name;
int age;
String color;
double weight;
}
1.2、类与对象的关系
1.3、类和对象的区别和联系
- 类是抽象的,概念的,代表一类事物,比如人类,猫类…, 即它是数据类型.
- 对象是具体的,实际的,代表一个具体事物, 即是实例.
- 类是对象的模板,对象是类的一个个体,对应一个实例
1.4、对象在内存中存在形式
1.5、类与对象属性/成员变量/字段
- 从概念或叫法上看: 成员变量 = 属性 = field(字段) (即 成员变量是用来表示属性的,授课中,统一叫 属性)
- 属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们前面定义猫类 的 int age 就 是属性
public class objectClass_ {
// 编写一个 main 方法
public static void main(String[] args) {
}
}
class Car {
String name; // 属性, 成员变量, 字段 field
double price;
String color;
String[] master; // 属性可以是基本数据类型,也可以是引用类型(对象,数组)
}
注意事项和细节说明
- 属性的定义语法同变量,示例:访问修饰符 属性类型 属性名; 这里老师简单的介绍访问修饰符: 控制属性的访问范围 有四种访问修饰符 public, proctected, 默认, private
- 属性的定义类型可以为任意类型,包含基本类型或引用类型
- 属性如果不赋值,有默认值,规则和数组一致。具体说: int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000, boolean false,String null
public class PropertiesDetail {
public static void main(String[] args) {
//创建 Person 对象
// p1 是对象名(对象引用)
// new Person() 创建的对象空间(数据) 才是真正的对象
Person p1 = new Person();
// 对象的属性默认值,遵守数组规则:
// int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
System.out.println("\n 当前这个人的信息");
System.out.println("age=" + p1.age + " name=" + p1.name + " sal=" + p1.sal + " isPass=" + p1.isPass); // age=0 name=null sal=0.0 isPass=false
}
}
class Person {
//四个属性
int age;
String name;
double sal;
boolean isPass;
}
1.6、创建对象
- 先声明再创建
Cat cat ; //声明对象 cat
cat = new Cat(); // 创建- 直接创建
Cat cat = new Cat();
1.7、访问属性
对象名.属性名;
cat.name ;
cat.age;
cat.color;
1.8、类和对象的内存分配机制
定义一个人类(Person)(包括 名字,年龄)。
1.9、类和对象的内存分配机制
Java 内存的结构分析
- 栈: 一般存放基本数据类型(局部变量)
- 堆: 存放对象(Cat cat , 数组等)
- 方法区:常量池(常量,比如字符串), 类加载信息
Java 创建对象的流程简单分析
Person p = new Person();
p.name = “jack”;
p.age = 10
说明:
- 先加载 Person 类信息(属性和方法信息, 只会加载一次)
- 在堆中分配空间, 进行默认初始化(看规则)
- 把地址赋给 p , p 就指向对象
- 进行指定初始化, 比如 p.name =”jack” p.age = 10
2、成员方法
2.1、方法使用
在某些情况下,我们要需要定义成员方法(简称方法)。比如人类:除了有一些属性外( 年龄,姓名…),我们人类还有一些行为比如:可以说话、跑步…, 通过学习,还可以做算术题。这时就要用成员方法才能完成。
- 添加 speak 成员方法,输出 “我是一个好人”
- 添加 cal01 成员方法,可以计算从 1+…+1000 的结果
- 添加 cal02 成员方法,该方法可以接收一个数 n,计算从 1+…+n 的结果
- 添加 getSum 成员方法,可以计算两个数的和
public class PropertiesDetail {
public static void main(String[] args) {
// 1. 方法写好后, 如果不去调用(使用), 不会输出
// 2. 先创建对象, 然后调用方法即可
Person person = new Person();
person.speak();
person.cal01();
person.cal02(100);
System.out.println(person.getSum(10, 20));
}
}
class Person {
String name;
int age;
// 1) 添加 speak 成员方法,输出 “我是一个好人”
// 1. public: 表示方法是公开
// 2. void: 表示方法没有返回值
// 3. speak(): speak是方法名, () 形参列表
// 4. {}: 方法体, 可以写我们要执行的代码
public void speak() {
System.out.println("我是一个好人");
}
// 2) 添加 cal01 成员方法,可以计算从 1+..+1000 的结果
public void cal01() {
int sum = 0;
for (int i = 1; i <= 1000; i++) {
sum += i;
}
System.out.println("1+..+1000 的结果是" + sum);
}
// 3) 添加 cal02 成员方法,该方法可以接收一个数 n,计算从 1+..+n 的结果
// (int n) 形参列表, 表示当前有一个形参 n, 可以接收用户输入
public void cal02(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
System.out.println("1+..+n 的结果是" + sum);
}
// 4) 添加 getSum 成员方法,可以计算两个数的和
// 1. public: 表示方法是公开的
// 2. int: 表示方法执行后,返回一个 int 值
// 3. getSum: 方法名
// 4. (int num1, int num1): 形参列表, 2个形参, 可以接收用户传入的两个数
// 5. return res; 表示把 res 的值, 返回
public int getSum(int num1, int num2) {
int res = num1 + num2;
return res;
}
}
2.2、方法的调用机制原理
2.3、成员方法的好处
- 提高代码的复用性
- 可以将实现的细节封装起来,然后供其他用户来调用即可
2.4、成员方法的定义
访问修饰符 返回数据类型 方法名(形参列表..) { // 方法体
// 语句;
// return 返回值;
}
- 形参列表:表示成员方法输入 cal(int n) , getSum(int num1, int num2)
- 返回数据类型:表示成员方法输出, void 表示没有返回值
- 方法主体:表示为了实现某一功能代码块
- return 语句不是必须的
2.5、成员方法的注意事项
- 调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数
- 实参和形参的类型要一致或兼容、个数、顺序必须一致
- 方法不能嵌套定义
2.6、返回数据类型
- 一个方法最多有一个返回值 [思考,如何返回多个结果 返回数组 ]
- 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)
- 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值; 而且要求返回值类型必须和 return 的 值类型一致或兼容
- 如果方法是 void,则方法体中可以没有 return 语句,或者 只写 return
2.7、方法名
遵循驼峰命名法,最好见名知义,表达出该功能的意思即可, 比如 得到两个数的和 getSum, 开发中按照规范
2.8、成员方法传参机制
2.8.1、基本数据类型的传参机制
public class MethodParameter {
public static void main(String[] args) {
int a = 10;
int b = 20;
new AA().swap(a, b);
}
}
class AA {
public void swap(int a, int b) {
int tmp = a;
a = b;
b = tmp;
System.out.println("a 和 b 交换后的值 a=" + a + "\tb=" + b);
}
}
2.8.2、引用数据类型的传参机制
B 类中编写一个方法 test100,可以接收一个数组,在方法中修改该数组 会变化
B 类中编写一个方法 test200,可以接收一个 Person(age,sal)对象,在方法中修改该对象属性 会变化
public class MethodParameter {
public static void main(String[] args) {
B b = new B();
int[] arr = {1, 2, 3};
b.test100(arr);
System.out.println(" main 的 arr 数组 ");
// 遍历数组
System.out.println(" test100 的 arr 数组 ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t"); // 200 2 3
}
System.out.println();
Person person = new Person();
person.name = "jack";
person.age = 10;
b.test200(person);
}
}
class B {
// test100,可以接收一个数组,在方法中修改该数组,在方法中修改该数组
public void test100(int[] arr) {
arr[0] = 200; // 修改元素
// 遍历数组
System.out.println(" test100 的 arr 数组 ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t"); // 200 2 3
}
System.out.println();
}
// test200,可以接收一个 Person(age,sal)对象,在方法中修改该对象属性
public void test200(Person p) {
p.age = 10000; // 修改对象属性
p = new Person();
p.name = "tom";
p.age = 99;
}
}
class Person {
String name;
int age;
}
引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参
p=null 和 p = new Person(); 对应示意图
2.9、成员方法返回类型是引用类型应用
- 编写 MyTools 类
- 编写一个方法 copyPerson,可以复制一个 Person 对象,返回复制的对象。克隆对象, 注意要求得到新对象和原来的 对象是两个独立的对象,只是他们的属性相同
// 1) 编写类 MyTools 类
// 2) 编写一个方法 copyPerson,可以复制一个 Person 对象,返回复制的对象。
// 克隆对象, 注意要求得到新对象和原来的 对象是两个独立的对象,只是他们的属性相同
public class MethodExercise {
public static void main(String[] args) {
Person person = new Person();
person.name = "张三";
person.age = 18;
MyTools myTools = new MyTools();
Person newPerson = myTools.copyPerson(person);
System.out.println("person的name=" + person.name + ", person的age=" + person.age);
System.out.println("newPerson的name=" + newPerson.name + ", newPerson的age=" + newPerson.age);
System.out.println(person == newPerson);
}
}
class Person {
String name;
int age;
}
class MyTools {
public Person copyPerson(Person p) {
Person p2 = new Person();
p2.name = p.name;
p2.age = p.age;
return p2;
}
}