chapter6面向对象程序编程
一、类和对象
1.引入
张老太养了两只猫:一只叫小白,今年3岁,白色。还有一只小花,今年100岁,花色。
编写一个程序,当用户输入的小猫名时,显示该猫的名字, 年龄,颜色。如果用户输入小猫名有误,则显示 张老太没有这只猫
//使用单独变量解决
//不利于数据的管理 把一只猫的信息拆解
String cat1Name = "小白";
String cat2Name = "小花";
int cat1Age = 3;
int cat2Age = 100;
String cat1Color = "白色";
String cat2Color = "花色";
//数组
//1.数据类型体现不出来
//2.只能用下标获取信息,变量名字和内容对应关系不明确
//3.不能体现猫的行为
String[] cat1 = {"小白", "3", "白色"};
String[] cat2 = {"小花", "100", "花色"};
java设计者引入 类与对象(oop) ,就是因为现有技术不能完美契合新需求
2.对象([属性,行为])
对象:小狗
属性:年龄,颜色,体重…
行为:跑,叫,吃…
3.类和对象关系示意图
1.从猫类到对象,目前有几种说法:1.创建一个对象、2.实例化一个对象、3.把类实例化... 2.上面的猫类同样可以修改成不同的鱼、狗、人...可以根据需求修改类,Java最大的特点就是面向对象
public class Object01 {
//编写一个main方法
public static void main(String[] args) {
/*
张老太养了两只猫:一只叫小白,今年3岁,白色。
还有一只小花,今年100岁,花色。
编写一个程序,当用户输入的小猫名时,显示该猫的名字, 年龄,颜色。
如果用户输入小猫名有误,则显示 张老太没有这只猫
*/
//使用面向对象的方式类解决
//使用一个对象可以管理多种属性,且增加行为时,可以更方便
//实例化一只猫(创建一只猫对象)
Cat cat1 = new Cat();//把创建的猫赋给cat1
cat1.name = "小白";
cat1.age = 3;
cat1.color = "白色";
Cat cat2 = new Cat();//(new的东西是实际的对象,堆区中的cat2指向的对象空间才是真正对象)
//cat2 就是一个猫对象(引用/对象名)
cat2.name = "小花";
cat2.age = 100;
cat2.color = "花色";
//访问对象的属性
System.out.println("第一只猫的信息" + cat1.name
+ " " + cat1.age + " " + cat1.color);
System.out.println("第二只猫的信息" + cat2.name
+ " " + cat2.age + " " + cat2.color);
}
}
//定义一个猫类 Cat --> 自定义的数据类型
class Cat {
//属性
String name;//名字
int age;//年龄
String color;//颜色
}
4.类和对象关系
- 类是抽象的,概念的,代表一类事物,它是数据类型
- 对象是具体的,实际的,代表一个具体事物,是实例
- 类是对象的模板,对象是类的一个个体,对应的一个实例
5.对象在内存中的存在形式
Cat cat = new Cat();
cat.name = "小白";
cat.age = 12;
cat.color = "白色";
6.成员变量
- 从概念或叫法上看:成员变量 = 属性 = field(字段) (即 成员变量时用来表示属性的)
- 属性是从类的一个组成部分,一般是基本数据类型,也可以是引用类型(对象,数组)。
7.属性注意事项
-
属性的定义语法同变量一致
e.g:访问修饰符 属性类型 属性名
访问修饰符是用来控制属性的访问范围
public、protected、默认、private -
属性的定义类型可以是任意类型,包括基本类型和应用类型
-
属性如果不赋值,有默认值,规则和数组一致
int 0,
short 0,
byte 0,
long 0,
float 0.0,
double 0.0,
char \u0000,
boolean false,
String null;public class ObjectDetail { //编写一个main方法 public static void main(String[] args) { Person p = new Person(); System.out.println("\n输入当前这个人信息"); System.out.println("age = " + p.age + " name = " + p.name + " sal = " + p.sal + " isPass = " + p.isPass); } } class Person { int age; String name; double sal; boolean isPass; }
8.对象的创建
- 先声明再创建
Cat cat;//首先声明对象 cat
cat = new Cat(); - 直接创建
Cat cat = new Cat(); - 访问属性
基本语法:对象名.属性名
9.类和对象内存分配机制
Person p1 = new Person();
p1.age = 10;
p1.name = "小明;
Person p2 = p1;
//把p1赋给p2,让p2指向p1
System.out.println(p2.age);
10.Java内存结构分析
1.栈
一般存放基本数据类型(局部变量)
2.堆
存放对象(Cat cat、数组等)
3.方法区
常量池(常量如:字符串等),类加载信息
e.g:
Person p = new Person();
p.name = "jack";
p.age = 10;
- 先加载类信息(属性和方法信息,只会加载一次)
- 在堆区中分配空间(根据对象的结构创建空间大小),进行默认初始化,
- 把地址赋给p,p就指向对象
- 进行指定初始化,p.name = “jack”;p.age = 10;
Person a = new Person();
a.age = 10;
a.name = "小明";
Person b;
b = a;
System.out.println(b.name);//小明
b.age = 200;
b = null;
System.out.println(a.age);//200
System.out.println(b.age);//报出空指针异常
二、成员方法
1.基本介绍
在某些情况下,我们需要定义成员方法(简称方法),比如人类:除了有一些属性外(年龄,姓名)…还有一些行为:比如:可以说话、跑步,还可以通过学习,做出算术题。这时就需要用成员方法才能完成。
public class Method01 {
//编写一个main方法
public static void main(String[] args) {
//方法的使用
//Person类添加speak成员方法,输出"我是一个好人"
//添加cal01成员方法,可以计算从1 + 2 + ... + 1000 的计算结果
//添加cal02成员方法,接受一个数n,计算1 + 2 + ... + n
//添加getSum成员方法,可以计算两个数的和
//方法写好后,如果不调用,不会有任何效果
Person p1 = new Person();
p1.speak();//调用方法
p1.cal01();
p1.cal02(5);
int returnRes = p1.getSum(10,20);
System.out.println("getSum返回的值是" + returnRes);
}
}
class Person {
String name;
int age;
public void speak() {
System.out.println("我是一个好人");
}
public void cal01() {
int res = 0;
for(int i = 1; i <= 1000; i++) {
res += i;
}
System.out.println("计算结果:" + res);
}
public void cal02(int n) {
nt res = 0;
for(int i = 1; i <= n; i++) {
res += i;
}
System.out.println("cal02计算结果:" + res);
}
public int getSum(int num1, int num2) {
int ret = num1 + num2;
return ret;
}
}
2.方法的调用机制
Person p1 = new Person();
int returnRes = p1.getSum(10,20);
System.out.println("getSum方法的返回值=" + returnRes);
public int getSum(int num1, int num2) {
int res = num1 + num2;
return res;
}
方法调用小结
1.当程序执行到方法时,就会开辟一个独立的空间(栈空间)
2.当方法执行完毕,或者直行道return语句时,就会返回
3.返回到调用方法的地方
4返回后,继续执行方法后面的代码
5.当main方法(栈)执行完毕,整个程序退出
3.方法的妙处
public class Method02 {
//编写一个main方法
public static void main(String[] args) {
//请遍历一个数组,输出数组各个元素值
int[][] map = {{0, 0, 1}, {1, 1, 1}, {1, 1, 3}};
//常规方法使用for循环来遍历
// for(int i = 0; i < map.length; i++) {
// for(int j = 0; j < map[i].length; j++) {
// System.out.println(map[i][j]);
// }
// System.out.println();
// }
//代码冗余度高
//使用方法解决
MyTools tool = new MyTools();//创建一个MyTools对象
tool.printArr(map);//调用方法
}
}
//把输出的功能,写到一个类的方法中,然后调用该方法即可
//这样就能使代码根据需求修改时不需要重复修改相同的内容
class MyTools {
public void printArr(int[][] map) {
//对传入的map数组遍历
for(int i = 0; i < map.length; i++) {
System.out.println("==============");
for(int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
1.提高代码的复用性
2.可以将实现的细节封装起来,然后供其他用户来调用即可
4.成员方法定义
public 返回数据类型 方法名 (形参列表...) {//方法体
//public(访问修饰符)
语句;
return 返回值;
}
1.形参列表
表示成员方法输入
2.返回数据类型
表示成员方法输出,void表示没有返回值
3.方法主体
表示为了实现某一功能的代码块
4.return语句
不是必须,表示返回数据
5.注意事项
1.访问修饰符
作用是控制方法使用的范围
如果不写 默认访问
public protected private 默认
2.返回数据类型
1.返回值
一个方法最多只有一个返回值
如果想要返回多个值,可以返回数组
e.g:设计一个方法,返回输入两值的和与差
public class MethodDetail {
//编写一个main方法
public static void main(String[] args) {
XX x = new XX();
int[] res = x.getSumAndSub(1, 4);
System.out.println("和 = " + res[0] + " 差 = " + res[1]);
}
}
class XX {
public int[] getSumAndSub(int n1, int n2) {
int[] resArr = new int[2];//创建一个数组
resArr[0] = n1 + n2;
resArr[1] = n1 - n2;
return resArr;
}
}
2.返回类型
返回类型可以为任意类型,包含基本类型和引用类型(数组、对象)
3.返回值要求
如果方法要求有返回数据类型,则方法体重最后的执行语句必须为return 值,而且要求返回值类型必须和return的值类型一只或兼容,如果方法时void,则方法体中可以没有return语句,或者只写return。
4.方法名
使用驼峰法命名 要求见名知义
E.g: getSum(int,int)
3.参数列表
1.参数
一个方法可以没有参数,也可以有多个参数,中间用逗号隔开
2.参数类型
参数类型可以是任何类型,包括基本类型和引用类型
3.调用
调用带参数的方法时,一定要对应着参数列表传入相同类型或兼容类型的参数
4.形参&实参
方法定义时的参数称为形式参数,简称形参,方法调用时传入的参数称为实际参数,简称实参,实参和形参的类型要一直或兼容,个数顺序必须一致
4.方法体
方法体重写完成功能的具体语句,可以为输入,输出,变量,运算,分支,循环,方法调用,但里面不能再定义方法,即方法不能嵌套定义。
可以放到同一个类当中,但是不能再方法体中
5.方法调用
1.同类方法调用
直接调用方法即可
2.跨类调用
A类调用B类方法:需要通过对象名调用。
3.说明
跨类的方法调用和方法的访问修饰符以及是否在同一个包相关
6.方法调用练习
1.编写类AA 方法:判断一个数是奇数还是偶数,返回boolean
public class MethodExercise01 {
//编写一个main方法
public static void main(String[] args) {
//编写类AA 方法:判断一个数是奇数还是偶数,返回boolean
AA a = new AA();
if(a.isOdd(1)) {//a.isOdd(2) -->是一个偶数
System.out.println("是一个奇数");
} else {
System.out.println("是一个偶数");
}
}
}
class AA {
public boolean isOdd(int num) {
return num % 2 != 0 ? true : false;
}
}
2.根据行、列、字符打印,对应行数和列数的字符
比如:行:4,列:4,字符 #,则打印相应的效果
####
####
####
####
public class MethodExercise01 {
//编写一个main方法
public static void main(String[] args) {
//编写类AA 方法:判断一个数是奇数还是偶数,返回boolean
AA a = new AA();
// if(a.isOdd(1)) {
// System.out.println("是一个奇数");
// } else {
// System.out.println("是一个偶数");
// }
a.print(3, 4, '$');
}
}
class AA {
public boolean isOdd(int num) {
return num % 2 != 0 ? true : false;
}
//根据行、列和字符打印
//如4行4列#
//####
//####
//####
//####
public void print(int row, int col, char c) {
for(int i = 0 ; i < row; i++) {
for(int j = 0; j < col; j++) {
System.out.print(c);
}
System.out.println();
}
}
}
7.方法的传参机制
public class MethodParameter01 {
//编写一个main方法
public static void main(String[] args) {
AA obj = new AA();
int a = 10;
int b = 20;
obj.swap(a, b);
System.out.println("main方法中a = " + a + " b = " + b);//10 20
}
}
class AA {
public void swap(int a, int b) {//参数是基本数据类型,即单独在swap栈空间内交换两个值的大小
//故并不会影响main方法中的值大小
System.out.println("\na和交换前的值 a = " + a + "\tb = " + b);//10 20
int temp = a;
a = b;
b = temp;
System.out.println("\na和交换后的值 a = " + a + "\tb = " + b);//20 10
}
}