第七章 链接
CSDNhttps://mp.csdn.net/mp_blog/creation/editor/134775022?spm=1001.2014.3001.9457
目录
6.1、类与对象(P192~201)
6.1.1、类与对象的引出(P192)
-
看一个养猫猫问题
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。请编写程序,当输入小猫名字时,就显示该猫的名字,年龄和颜色。如果用户输入的小猫名有错误,则显示张老太没有这只猫。
public class Object01 {
public static void main(String[] args) {
/*
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。
请编写程序,当输入小猫名字时,就显示该猫的名字,年龄和颜色。
如果用户输入的小猫名有错误,则显示张老太没有这只猫。
*/
//单独变量来解决 -----> 不利于管理(添加或删除猫的其它信息,个数)
//第一只猫的信息
String cat1Name = "小白";
int cat1Age = 3;
String cat1Color = "白色";
//第二只猫的信息
String cat2Name = "小花";
int cat2Age = 100;
String cat2Color = "花色";
/*
数组 -----> (1)数据类型体现不出来(年龄也设置成了String)
(2)不利于管理,只能通过下标获取猫的信息
*/
//第一只猫的信息
String cat1 = {{"小白"},{"3"},{"白色"}};
//第二只猫的信息
String cat2 = {{"小花"},{"100"},{"花色"}};
}
}
-
现有技术解决的缺点分析
1、不利于管理
2、效率低
-
Java设计者引入类与对象(OOP),根本原因就是现有的技术,不能完美的解决新的需求。
6.1.2、类与对象的概述(P193)
一个程序就是一个世界,有很多事物(对象[属性,行为])
例如:
下面图片中的狗,就是一个对象,有属性(如:年龄,颜色,体重...),有行为(如:跑,吃,叫...)
-
类与对象的关系示意图
-
类与对象的关系示意图(加强)
6.1.3、面向对象快速入门(P194)
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。请编写程序,当输出小猫名字,年龄和颜色。
import java.util.Scanner;
public class Object01 {
public static void main(String[] args) {
/*
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。
请编写程序,输出小猫名字,年龄和颜色。
*/
//使用OOP面向对象解决
//实例化一只猫(创建一只猫对象)
//1、new Cat();创建一只猫
//2、Cat cat1 = new Cat();把创建的猫赋给cat1
//3、cat1就是一个对象
Cat cat1 = new Cat();
cat1.name = "小白";
cat1.age = 3;
cat1.color = "白色";
cat1.weight = 10.5;
//创建第二只猫,并赋值给 cat2
Cat cat2 = new Cat();
cat2.name = "小花";
cat2.age = 100;
cat2.color = "花色";
cat2.weight = 17.7;
//访问对象的属性
System.out.println("第一只猫的名字为:" + cat1.name + ",年龄为:" + cat1.age +
"岁,颜色为" + cat1.color + ",体重为" + cat1.weight + "斤");
System.out.print("第二只猫的名字为:" + cat2.name + ",年龄为:" + cat2.age +
"岁,颜色为" + cat2.color + ",体重为" + cat2.weight + "斤");
}
}
class Cat {
//以下均是 属性/成员变量/字段
String name;
int age;
String color;
double weight;
}
输出结果为:
第一只猫的名字为:小白,年龄为:3岁,颜色为白色,体重为10.5斤
第二只猫的名字为:小花,年龄为:100岁,颜色为花色,体重为17.7斤
-
类和对象的区别和联系
通过上面代码可以看出:
1、类是抽象的,概念的,代表一类事物,比如人类,猫类...,即它是数据类型
2、对象是具体的,实际的,代表一个具体事物,即是实例
3、类是对象的模板,对象是类的一个个体,对应一个实例
6.1.4、对象内存布局(P195)
int类型会直接存放在堆里
String类型会存放在方法区里
在执行Cat cat = new Cat();时,方法区加载Cat类信息(1、属性,2、行为(方法信息))
6.1.5、属性概念(P196)
-
属性/成员变量
基本介绍
1、从概念或叫法上看,成员变量 = 属性 = field(字段) (即 成员变量是用来表示属性的,笔记中,统一叫属性)
代码演示
public class Object02 {
public static void main(String[] args) {
}
}
class Car {
String name;//属性,成员变量,字段,field
double price;
String color;
String[] master;//属性可以是基本数据类型,也可以是引用类型(对象,数组)
}
2、属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们前面定义猫类 的 int age 就是属性
6.1.6、属性注意细节(P197)
1、属性的定义语法同变量,示例:
访问修饰符 属性类型 属性名;
访问修饰符:控制属性的访问范围,有四种访问修饰符 public,protected,默认,private,后面会有介绍
2、属性的定义类型可以为任意类型,包含基本类型或引用类型
3、属性如果不赋值,有默认值,规则和数组一致。int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000(ASCII码中的空格) ,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("当前这个人的信息");
System.out.print("age=" + p1.age + " name=" + p1.name +
" sal=" + p1.sal + " isPass=" + p1.isPass);
}
}
class Person {
//四个属性
String name;
int age;
double sal;
boolean isPass;
}
输出结果为:
当前这个人的信息
age=0 name=null sal=0.0 isPass=false
6.1.7、创建对象访问属性(P198)
-
如何创建对象
1、先声明再创建
Cat cat;//声明对象cat
cat = new Cat();//创建
2、直接创建
Cat cat = new Cat();
-
如何访问属性
基本语法:
对象名.属性名;
如:
cat.name;
cat.age;
cat.color;
6.1.8、对象分配机制(P199)
-
类和对象的内存分配机制
看下面代码
public class Object03 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "小明";
p1.age = 18;
Person p2 = p1;
System.out.println(p2.age);
}
}
class Person {
String name;
int age;
}
输出结果为:
18
6.1.9、对象创建过程(P200)
-
类和对象的内存分配机制
Java内存的结构分析
1、栈:一般存放基本数据类型(局部变量)
2、堆:存放对象(Cat cat,数组等)
3、方法区:常量池(常量,比如字符串),类加载信息
Java创建对象的流程简单分析
1、先加载Person类信息(属性和方法信息,只会加载一次)
2、在堆中分配空间,进行默认初始化
3、把地址赋给p,p就指向对象
4、进行指定初始化,比如p.name = "jack"; p.age = 10;
6.1.10、对象机制练习(P201)
下面代码输出什么信息
public class Object03 {
public static void main(String[] args) {
// Person p1 = new Person();
// p1.name = "小明";
// p1.age = 18;
// Person p2 = p1;
// System.out.println(p2.age);
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);
System.out.println(b.age);//出现异常
}
}
class Person {
String name;
int age;
}
输出结果为:
小明
200
Exception in thread "main" java.lang.NullPointerException
at Object03.main(Object03.java:18)
6.2、方法(P202~210)
6.2.1、方法快速入门_1(P202)
-
基本介绍
在某些情况下,我们需要定义成员方法(简称方法)。比如人类:除了有一些属性外(年龄,姓名...),我们人类还有一些行为,比如:可以说话、跑步...,通过学习,还可以做算术题。这时就要用成员方法才能完成。
方法可以重复调用
-
成员方法快速入门
现在要求对Person类完善
(1)、添加spreak成员方法,输出 我是一个好人
public class Method01 {
public static void main(String[] args) {
//方法使用
//1.方法写好后,如果不去调用(使用),不会输出
//2.先创建对象,然后调用方法即可
Person p1 = new Person();
p1.speak();//调用方法
}
}
class Person {
String name;
int age;
//方法(成员方法)
//添加speak 成员方法 输出:我是一个好人
//1.public:表示方法是公开
//2.void:表示方法没有返回值
//3.speak():speak是方法名,()形参列表
//4.{}:方法体,可以写我们要执行的代码
//5.System.out.println("我是一个好人");:表示我们的方法就是输出一句话
public void speak() {
System.out.print("我是一个好人");
}
}
输出结果为:
我是一个好人
6.2.2、方法快速入门_2(P203)
(2)、添加cal01成员方法,可以计算从 1 + ... + 1000的结果
public class Method01 {
public static void main(String[] args) {
//方法使用
//1.方法写好后,如果不去调用(使用),不会输出
//2.先创建对象,然后调用方法即可
Person p1 = new Person();
p1.speak();//调用方法(1)
Person c1 = new Person();
c1.cal01();//调用方法(2)
}
}
class Person {
String name;
int age;
//方法(成员方法)
//(1)添加speak 成员方法 输出:我是一个好人
//1.public:表示方法是公开
//2.void:表示方法没有返回值
//3.speak():speak是方法名,()形参列表
//4.{}:方法体,可以写我们要执行的代码
//5.System.out.println("我是一个好人");:表示我们的方法就是输出一句话
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);
}
}
输出结果为:
我是一个好人
1-1000累加和为:500500
(3)、添加cal02成员方法,该方法可以接收一个数n,计算从 1 + ... + n的结果
import java.util.Scanner;
public class Method01 {
public static void main(String[] args) {
//方法使用
//1.方法写好后,如果不去调用(使用),不会输出
//2.先创建对象,然后调用方法即可
System.out.println("speak:");
Person p1 = new Person();
p1.speak();//调用方法(1)
System.out.println("cal01:");
Person c1 = new Person();
c1.cal01();//调用方法(2)
System.out.println("cal02:");
Scanner myScanner = new Scanner(System.in);
System.out.print("请输入一个数,表示从1加到:");
int n = myScanner.nextInt();
Person c2 = new Person();
c2.cal02(n);//调用方法(3)
System.out.print("请zai输入一个数,表示从1加到:");
n = myScanner.nextInt();
c2.cal02(n);//再次调用方法(3)
}
}
class Person {
String name;
int age;
//方法(成员方法)
//(1)添加speak 成员方法 输出:我是一个好人
//1.public:表示方法是公开
//2.void:表示方法没有返回值
//3.speak():speak是方法名,()形参列表
//4.{}:方法体,可以写我们要执行的代码
//5.System.out.println("我是一个好人");:表示我们的方法就是输出一句话
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的结果
public void cal02(int n) {//int n:形参列表,表示当前有一个形参n,可以接收用户输入
int sum = 0 ;
for (int i = 1; i <= n; i++) {
sum += i;
}
System.out.println("1-" + n + "累加和为:" + sum);
}
}
输出结果为:
speak:
我是一个好人
cal01:
1-1000累加和为:500500
cal02:
请输入一个数,表示从1加到:5
1-5累加和为:15
请zai输入一个数,表示从1加到:10
1-10累加和为:55
(4)、添加getSum成员方法,可以计算两个数的和。
import java.util.Scanner;
public class Method01 {
public static void main(String[] args) {
//方法使用
//1.方法写好后,如果不去调用(使用),不会输出
//2.先创建对象,然后调用方法即可
System.out.println("speak方法:");
Person p1 = new Person();
p1.speak();//调用方法(1)
System.out.println("cal01方法:");
Person c1 = new Person();
c1.cal01();//调用方法(2)
System.out.println("cal02方法:");
Scanner myScanner = new Scanner(System.in);
System.out.print("请输入一个数,表示从1加到:");
int n = myScanner.nextInt();
Person c2 = new Person();
c2.cal02(n);//调用方法(3)
System.out.print("请zai输入一个数,表示从1加到:");
n = myScanner.nextInt();
c2.cal02(n);//再次调用方法(3)
System.out.println("getSum:");
Person s1 = new Person();
//调用getSum方法,同时将5赋值给num1,将10赋值给num2
//sum接受getSum返回的值
int sum = s1.getSum(5, 10);//调用方法(4)
System.out.println("getSum = " + sum);
}
}
class Person {
String name;
int age;
//方法(成员方法)
//(1)添加speak 成员方法 输出:我是一个好人
//1.public:表示方法是公开
//2.void:表示方法没有返回值
//3.speak():speak是方法名,()形参列表
//4.{}:方法体,可以写我们要执行的代码
//5.System.out.println("我是一个好人");:表示我们的方法就是输出一句话
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的结果
public void cal02(int n) {//int n:形参列表,表示当前有一个形参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 num2):形参列表,2个形参,可以接受用户输入的两个参数
//5.return sun:表示把sum的值返回
public int getSum(int num1, int num2) {
int sum = num1 + num2;
return sum;
}
}
输出结果为:
speak方法:
我是一个好人
cal01方法:
1-1000累加和为:500500
cal02方法:
请输入一个数,表示从1加到:10
1-10累加和为:55
请zai输入一个数,表示从1加到:50
1-50累加和为:1275
getSum方法:
getSum = 15
6.2.3、方法调用机制(P204)
getSum执行过程
6.2.4、方法的妙用(P205)
-
为什么需要成员方法
看一个需求:请遍历一个数组,输出数组各个元素值。
解决思路1,传统的方法,就是使用单个for循环,将数组输出
public class Method02 {
public static void main(String[] args) {
//请遍历一个数组,输出数组的各个元素值
int[][] map = {{0,0,1},{1,1,1},{1,1,3}};
//遍历map数组
//传统的解决方式就是直接遍历
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
//如果要求再次遍历,相同代码太多,笨拙的粘贴拷贝,
}
}
解决思路2,定义一个类MyTools,然后写一个成员方法,调用方法实现。
public class Method02 {
public static void main(String[] args) {
//请遍历一个数组,输出数组的各个元素值
int[][] map = {{0,0,1},{1,1,1},{1,1,3}};
//遍历map数组
//传统的解决方式就是直接遍历
System.out.println("传统遍历输出为:");
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
//如果要求再次遍历,相同代码太多,笨拙的粘贴拷贝,
//将上面代码换为
MyTools tool = new MyTools();
System.out.println("方法遍历输出为:");
tool.printArr(map);//调用方法
}
}
//将输出的功能,写到一个类的方法中,然后调用该方法即可
class MyTools {
//方法:接收一个二维数组
public void printArr(int arr[][]) {//传来的参数是一个二维数组
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
输出结果为:
传统遍历输出为:
0 0 1
1 1 1
1 1 3
方法遍历输出为:
0 0 1
1 1 1
1 1 3
-
成员方法的好处
1、提高代码的复用性
2、可以将实现的细节封装起来,然后供其他用户来调用即可。
6.2.5、方法的定义(P206)
-
成员方法的定义
public 返回数据类型 方法名 (形参列表..) {
方法体语句;//可以有一条或多条
return 返回值;
}
1、形参列表:表示成员方法输入 cal(int n),getSum(int num1,int num2)
2、返回数据类型:表示成员方法输出,void表示没有返回值
3、方法主体:表示为了实现某一功能代码块
4、return 语句不是必需的
6.2.6、方法使用细节_1(P207)
-
注意事项和使用细节
1、访问修饰符的作用是:控制方法的使用范围。如果不写则为默认访问修饰符,修饰符有4种:public,protected,默认,private
2、返回数据类型
(1)一个方法最多有一个返回值,如果想要返回多个值,可以返回数组
public class MethodDetail {
public static void main(String[] args) {
int num1 = 2;
int num2 = 3;
AA a = new AA();
int compute[] = a.getSumAndSub(num1,num2);
System.out.println(num1 + " + " + num2 + " = " + compute[0]);
System.out.println(num1 + " - " + num2 + " = " + compute[1]);
}
}
class AA {
public int[] getSumAndSub(int num1, int num2) {
int arr[] = new int[2];
arr[0] = num1 + num2;
arr[1] = num1 - num2;
return arr;
}
}
输出结果为:
2 + 3 = 5
2 - 3 = -1
(2)返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)
(3)如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值(可以是具体的值、变量和表达式);而且要求返回的值必须和return的值类型一致或兼容(比如double类型兼容int类型)。
public double f1() {
double d1 = 1.1;
int n = 3;
return n;//这样也是可以的
}
(4)如果方法是void,则方法体中可以没有return语句,或者只写return;
方法名命名:
遵循驼峰命名法,最好见名知意,表达出该功能的意思即可,比如:得到两个数的和getSum
6.2.7、方法使用细节_2(P208)
-
注意事项和使用细节
形参列表:
1、一个方法可以没有参数,也可以有多个参数,中间用逗号隔开,比如:
getSum(int n1, int n2)
2、参数类型可以为任意类型,包含基本类型或引用类型,比如:
printArr(int[][] map)
3、调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数,比如:
public class waste {
public static void main(String[] args) {
byte num1 = 1;
byte num2 = 2;
AA a = new AA();
a.getSum(num1, num2);//正确,低精度类型的变量能赋值给高精度类型变量
//a.getSum(1.1, 2.2);//错误,高精度类型的变量不能赋值给低精度类型变量
}
}
class AA {
public int getSum(int num1, int num2) {
return num1 + num2;
}
}
4、方法定义时的参数称为形式参数,简称形参;方法调用时的传入参数称为实际参数,简称实参。实参和形参的类型要一致或兼容,个数、顺序也必须一致。
public class waste {
public static void main(String[] args) {
byte num1 = 1;
byte num2 = 2;
AA a = new AA();
a.getSum(num1, num2);//正确,低精度类型的变量能赋值给高精度类型变量
//a.getSum(1.1, 2.2);//错误,高精度类型的变量不能赋值给低精度类型变量
//a.getSum(100);//错误,个数不一致
a.f("tom",10);//正确
//a.f(10,"tom");//错误,实际参数和形式参数顺序不同
}
}
class AA {
public void f(String str, int n) {
}
public int getSum(int num1, int num2) {
return num1 + num2;
}
}
方法体不能嵌套定义:
里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但是方法里面不能再定义方法。即方法不能嵌套定义
public class waste {
public static void main(String[] args) {
}
}
class AA {
public void f(String str, int n) {
public void ff(int n) { //错误,不能嵌套定义
}
}
}
6.2.8、方法使用细节_3(P209)
-
注意事项和使用细节
方法调用细节说明
1、同一个类中的方法调用:直接调用即可。比如print(参数);
public class MethodDetail02 {
public static void main(String[] args) {
A a = new A();
a.sayOk();
}
}
class A {
//1、同一个类中的方法直接调用即可
public void print(int n) {
System.out.println("print()方法被调用,n = " + n);
}
public void sayOk() {//sayOk方法调用print方法
print(10);
System.out.println("继续执行sayOk()...");
}
}
输出结果为:
print()方法被调用,n = 10
继续执行sayOk()...
2、跨类中的方法A类调用B类方法:需要通过对象名调用。比如:对象名.方法名(参数);
public class MethodDetail02 {
public static void main(String[] args) {
A a = new A();
//a.sayOk();
a.m1();
}
}
class A {
//1、同一个类中的方法直接调用即可
public void print(int n) {
System.out.println("print()方法被调用,n = " + n);
}
public void sayOk() {//sayOk方法调用print方法
print(10);
System.out.println("继续执行sayOk()...");
}
//2、跨类中的方法A类调用B类方法:需要通过对象名调用。比如:对象名.方法名(参数);
public void m1() {
System.out.println("m1()方法被调用");
//创建B对象
B b = new B();
b.hi();
System.out.println("m1()继续执行");
}
}
class B {
public void hi() {
System.out.println("B类中的hi()被执行");
}
}
输出结果为:
m1()方法被调用
B类中的hi()被执行
m1()继续执行
3、特别说明以下:跨类的方法调用和方法的访问修饰符相关。后面详讲
6.2.9、方法练习题_1(P210)
1、编写类AA,有一个方法:判断一个数是奇数还是偶数,返回boolean
public class MethodExercise01 {
public static void main(String[] args) {
int num = 5;
AA judge = new AA();
boolean Odd = judge.ParityJudgment(num);
if(Odd == true) {
System.out.println("为偶数");
} else {
System.out.println("为奇数");
}
}
}
class AA {
//思路:
//1、方法的返回类型为boolean类型
//2、方法名字自己定义(这里定义为ParityJudgment)
//3、方法的形参为int num
//4、方法体为判断奇偶数
public boolean ParityJudgment(int num) {
// if(num % 2 == 0) {
// return true;
// } else {
// return false;
// }
//下面三目运算符代码等价于上面注释代码
//return num % 2 == 0 ? true : false;
//再简化上面代码
return num % 2 == 0;
}
}
2、根据行、列、字符打印对应行数和列数的字符,比如:行:4,列:4,字符:#,则打印相应的效果
public class MethodExercise02 {
public static void main(String[] args) {
//2、根据行、列、字符打印对应行数和列数的字符,比如:行:4,列:4,字符:#,则打印相应的效果
int row = 3;
int column = 3;
char c = '@';
Mytools run = new Mytools();
run.printchar(row,column,c);
}
}
//类名,方法名都没要求,自己定义
class Mytools {
//根据行、列、字符打印,故传参为int row, int column, int c
//没有要求返回值,所以返回类型为void
public void printchar(int row, int column, int c) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
System.out.print((char)c);
}
System.out.println();
}
}
}
输出结果为:
@@@
@@@
@@@
6.3、成员方法传参机制(重点)(P211~214)
6.3.1、方法传参机制_1(P211)
分析下面代码结果
public class MethodParameter01 {
public static void main(String[] args) {
int a = 10;
int b = 20;
AA obj = new AA();
obj.swap(a,b);
System.out.println("\nmain方法 a = " + a + " b = " + b);
}
}
class AA {
public void swap(int a, int b) {
System.out.println("\na和b交换前的值\na = " + a + "\t b = " + b);
int temp = a;
a = b;
b = temp;
System.out.println("\na和b交换后的值\na = " + a + "\t b = " + b);
}
}
输出结果为:
a和b交换前的值
a = 10 b = 20
a和b交换后的值
a = 20 b = 10
main方法 a = 10 b = 20
上面代码的传参过程为:
6.3.2、方法传参机制_2(P212)
-
引用数据类型的传参机制
1、B类中编写一个方法test100,可以接收一个数组,在方法中修改该数组,查看main方法中的数组是否发生变化
public class MethodParameter02 {
public static void main(String[] args) {
//1、B类中编写一个方法test100,
//可以接收一个数组,在方法中修改该数组,查看main方法中的数组是否发生变化
int arr[] = {1,2,3};
B b = new B();
b.test100(arr);
System.out.println("调用完test100方法后输出");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
class B {
public void test100(int arr[]) {
System.out.println("test100方法输出");
arr[0] = 200;
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
输出结果为:
test100方法输出
200 2 3
调用完test100方法后输出
200 2 3
上面代码的传参过程为:
2、B类中编写一个方法test200,可以接收一个Person(age,sal)对象,在方法中修改该对象属性,查看原来的对象是否发生变化
public class MethodParameter02 {
public static void main(String[] args) {
//2、B类中编写一个方法test200,可以接收一个Person(age,sal)对象,
//在方法中修改该对象属性,查看原来的对象是否发生变化
Person p = new Person();
p.name = "jack";
p.age = 18;
B b = new B();
b.test200(p);
System.out.println("main 的 p.age = " + p.age);
}
}
class Person {
String name;
int age;
}
class B {
public void test200(Person p) {
p.age = 10000;
System.out.println("test200 的 p.age = " + p.age);
}
}
输出结果为:
test200 的 p.age = 10000
main 的 p.age = 10000
上面代码的传参过程为:
6.3.3、方法传参机制_3(P213)
1、在方法中将传入的对象参数,改为空,是否会影响main方法中定义的属性
public class MethodParameter02 {
public static void main(String[] args) {
Person p = new Person();
p.name = "jack";
p.age = 18;
B b = new B();
b.test200(p);
System.out.println("main 的 p.age = " + p.age);
}
}
class Person {
String name;
int age;
}
class B {
public void test200(Person p) {
p = null;
}
}
输出结果为:
main 的 p.age = 18
上面代码的传参过程为:
2、方法的形参为对象,在方法的代码块中,重新定义对象,并对属性赋值,是否会影响mian方法中定义的属性
public class MethodParameter02 {
public static void main(String[] args) {
Person p = new Person();
p.name = "jack";
p.age = 18;
B b = new B();
b.test200(p);
System.out.println("main 的 p.age = " + p.age);
}
}
class Person {
String name;
int age;
}
class B {
public void test200(Person p) {
p = new Person();
p.age = 99;
p.name = "tom";
System.out.println("test200 的 p.age = " + p.age + ",p.name = " + p.name);
}
}
输出结果为:
test200 的 p.age = 99,p.name = tom
main 的 p.age = 18
上面代码的传参过程为:
6.3.4、克隆对象(P214)
编写一个方法copyPerson,可以赋值一个Person对象,返回复制的对象。克隆对象,注意:要求得到的新对象和原来的对象是两个独立的对象,只是它们的属性相同。
public class CloneObjects {
public static void main(String[] args) {
//编写一个方法copyPerson,可以赋值一个Person对象,返回复制的对象。
//克隆对象,注意:要求得到的新对象和原来的对象是两个独立的对象,只是它们的属性相同。
Person p = new Person();
p.name = "milan";
p.age = 18;
Mytools tools = new Mytools();
Person p2 = tools.copyPerson(p);
//至此 p 和 p2 是两个Person对象,但是是两个独立的对象,属性相同
System.out.println("p的属性 age = " + p.age + ",名字 = " + p.name);
System.out.println("p2的属性 age = " + p2.age + ",名字 = " + p2.name);
//通过对象比较查看是否为同一个对象
System.out.println(p == p2);
}
}
class Person {
String name;
int age;
}
class Mytools {
//思路
//1、方法的返回类型 Person
//2、方法的名字 copyPerson
//3、方法的形参 Person p
//4、方法体,创建一个新的对象,并复制属性,返回即可
public Person copyPerson(Person p) {
Person p2 = new Person();
p2.name = p.name;
p2.age = p.age;
return p2;
}
}
输出结果为:
p的属性 age = 18,名字 = milan
p2的属性 age = 18,名字 = milan
false
6.4、方法递归调用(P215~227)
6.4.1、递归解决什么问题(P215)
-
基本介绍
简单的说:递归就是方法自己调用自己,每次调用时传入的变量值不同,递归有助于编程者解决复杂问题,同时可以让代码变得简洁
-
递归能解决什么问题?
1、各种数学问题:如八皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题(google编程大赛)
2、各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等。
3、将用栈解决的问题----->递归代码比较简洁
6.4.2、递归执行机制_1(P216)
递归打印问题
public class Recursion01 {
public static void main(String[] args) {
int n = 4;
T t = new T();
t.test(n);
}
}
class T {
public void test(int n) {
if (n > 2) {
test(n - 1);
}
System.out.println("n = " + n);
}
}
输出结果为:
n = 2
n = 3
n = 4
上面代码的执行过程为:
6.4.3、递归执行机制_2(P217)
给上一节代码的test方法中,加上一条else语句,会输出什么
public class Recursion01 {
public static void main(String[] args) {
int n = 4;
T t = new T();
t.test(n);
}
}
class T {
public void test(int n) {
if (n > 2) {
test(n - 1);
} else {
System.out.println("n = " + n);
}
}
}
输出结果为:
n = 2
6.4.4、递归执行机制_3(P218)
阶乘问题
public class Factorial {
public static void main(String[] args) {
int num = 5;
Compute res = new Compute();
int result = res.factorial(num);
System.out.print(num + "的阶乘为:" + result);
}
}
class Compute {
public int factorial(int num) {
if (num == 1) {
return 1;
} else {
return factorial(num - 1) * num;
}
}
}
输出结果为:
5的阶乘为:120
代码执行流程图
6.4.5、递归执行机制_4(P219)
递归的重要规则
1、执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
2、方法的局部变量是独立的,不会相互影响,比如n变量
3、如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的数据。
4、递归必须向退出递归的条件逼近,否则就是无限递归,出现(StackOverflowError)
5、当一个方法执行完毕,或者遇到retrun,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
6.5.5、递归斐波那契数列(P220)
请使用递归的方式求斐波那契数1,1,2,3,5,8,13...给你一个整数n(n为数列第n个数),求出数列的值是多少
public class RecursionExercise01 {
public static void main(String[] args) {
int n = 7;
recursion r = new recursion();
int res = r.fibonacci(n);
if (res != -1) {
System.out.println("斐波那契第" + n + "个数为:" + res);
}
}
}
class recursion {
public int fibonacci(int num) {
if (num >= 1) {
if (num == 1 || num == 2) {
return 1;
} else {
return fibonacci(num - 1) + fibonacci(num - 2);
}
} else {
System.out.println("请输入一个 >= 1的数");
return -1;
}
}
}
输出结果为:
斐波那契第7个数为:13
6.5.6、猴子吃桃(P221)
猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半,并且再多吃了一个,以后猴子每天都吃剩下桃子的一半,然后再多吃一个。当到第10天时,想再吃时(即还没吃),发现只有1个桃子了。问题:最初共多少个桃子?
public class recursionExercise02 {
public static void main(String[] args) {
// 定义变量
int days = 10;// 天数
int peach = 1;// 桃子数
Count num = new Count();// 创建Count对象
int count = num.countPeach(days,peach);// 调用countPeach方法计算桃子数
System.out.println("第1天有" + count + "个桃子");// 输出结果
}
}
class Count {
// 计算第n天剩下的桃子数
// 每天剩下的桃子数都是前一天的一半再加上1
// days = 10 peach = 1
// days = 9 peach = (1 + 1) * 2 = 4
// days = 8 peach = (5 + 1) * 2 = 10
// ......
public int countPeach(int days, int peach) {
if (days == 1) {
return peach;// 第1天剩下的桃子数即为初始桃子数
} else {
return countPeach(--days, (peach + 1) * 2);// 递归调用countPeach方法计算前1天的桃子数
}
}
}
6.5.7、老输出迷宫_1(P222)
-
递归调用应用实例-迷宫问题
1、小球得到的路径,和程序员设置的找路径策略有关即:找路的上下左右的顺序相关
2、再得到小球的路径时,可以先使用(上下左右),再改成(上下左右),看看路径是不是有变化
3、测试回溯现象
4、扩展思考:如何求出最短路径?
public class MiGong {
public static void main(String[] args) {
//思路:
//1、先创建迷宫,用二维数组表示,int[][] map = new int[8][7]
//2、先规定 map 数组 的元素值:0 表示可以走, 1表示障碍物
int map[][] = new int[8][7];
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
6.5.8、老鼠出迷宫_2(P223)
老鼠找路策略为:下->右->上->左
public class MiGong {
public static void main(String[] args) {
//思路:
//1、先创建迷宫,用二维数组表示,int[][] map = new int[8][7]
//2、先规定 map 数组 的元素值:0 表示可以走, 1表示障碍物
System.out.println("-----开始制作迷宫-----");
int map[][] = new int[8][7];
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
System.out.println("-----开始走迷宫-----");
T t = new T();
t.findWay(map,1,1);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
class T {
//1、findWay方法就是专门来找出迷宫的路径
//2、如果找到,就返回true,否则返回false
//3、map 就是二维数组,即表示迷宫
//4、i,j就是老鼠的位置,初始化的位置为(1,1)
//5、因为我们是递归的找路,所以先定寻找规则,即map二维数组的各个值的含义
// 0 表示可以走,1表示障碍物,2表示可以走,但是走过来,3,表示走过,但是不可走
//6、当map[6][5] = 2时,就说明找到了出口,即递归结束,否则继续找
//7、老鼠找路策略为:下->右->上->左
public boolean findWay (int map[][], int i, int j) {
if (map[6][5] == 2) {//说明已找到出口,退出程序
return true;
} else {
if (map[i][j] == 0) {//当前这个位置0,说明可以走
map[i][j] = 2;
if (findWay(map, i + 1, j)) {//向下走
return true;
} else if (findWay(map, i, j + 1)) {//向右走
return true;
} else if (findWay(map, i - 1, j)) {//向上走
return true;
} else if (findWay(map, i, j - 1)) {//向左走
return true;
} else {//
map[i][j] = 3;
return false;
}
} else {
return false;
}
}
}
}
输出结果为:
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
-----开始走迷宫-----
1 1 1 1 1 1 1
1 2 0 0 0 0 1
1 2 2 2 0 0 1
1 1 1 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 2 2 1
1 1 1 1 1 1 1
6.5.9、老输出迷宫_3(P224)
老鼠找路策略为:上->右->下->左
public class MiGong02 {
public static void main(String[] args) {
//思路:
//1、先创建迷宫,用二维数组表示,int[][] map = new int[8][7]
//2、先规定 map 数组 的元素值:0 表示可以走, 1表示障碍物
System.out.println("-----开始制作迷宫-----");
int map[][] = new int[8][7];
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
System.out.println("-----开始走迷宫-----");
T t = new T();
t.findWay(map,1,1);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
class T {
//1、findWay方法就是专门来找出迷宫的路径
//2、如果找到,就返回true,否则返回false
//3、map 就是二维数组,即表示迷宫
//4、i,j就是老鼠的位置,初始化的位置为(1,1)
//5、因为我们是递归的找路,所以先定寻找规则,即map二维数组的各个值的含义
// 0 表示可以走,1表示障碍物,2表示可以走,但是走过来,3,表示走过,但是不可走
//6、当map[6][5] = 2时,就说明找到了出口,即递归结束,否则继续找
//7、老鼠找路策略为:上->右->下->左
public boolean findWay (int map[][], int i, int j) {
if (map[6][5] == 2) {//说明已找到出口,退出程序
return true;
} else {
if (map[i][j] == 0) {//当前这个位置0,说明可以走
map[i][j] = 2;
if (findWay(map, i - 1, j)) {//向上走
return true;
} else if (findWay(map, i, j + 1)) {//向右走
return true;
} else if (findWay(map, i + 1, j)) {//向下走
return true;
} else if (findWay(map, i, j - 1)) {//向左走
return true;
} else {//
map[i][j] = 3;
return false;
}
} else {
return false;
}
}
}
}
输出结果为:
-----开始制作迷宫-----
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
-----开始走迷宫-----
1 1 1 1 1 1 1
1 2 2 2 2 2 1
1 0 0 0 0 2 1
1 1 1 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 1 1 1 1 1 1
6.5.10、老输出迷宫_4(P225)
老鼠找路策略为:下->右->上->左
public class MiGong03 {
public static void main(String[] args) {
//思路:
//1、先创建迷宫,用二维数组表示,int[][] map = new int[8][7]
//2、先规定 map 数组 的元素值:0 表示可以走, 1表示障碍物
System.out.println("-----开始制作迷宫-----");
int map[][] = new int[8][7];
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
map[2][2] = 1;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
System.out.println("-----开始走迷宫-----");
T t = new T();
t.findWay(map,1,1);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
class T {
//1、findWay方法就是专门来找出迷宫的路径
//2、如果找到,就返回true,否则返回false
//3、map 就是二维数组,即表示迷宫
//4、i,j就是老鼠的位置,初始化的位置为(1,1)
//5、因为我们是递归的找路,所以先定寻找规则,即map二维数组的各个值的含义
// 0 表示可以走,1表示障碍物,2表示可以走,但是走过来,3,表示走过,但是不可走
//6、当map[6][5] = 2时,就说明找到了出口,即递归结束,否则继续找
//7、老鼠找路策略为:下->右->上->左
public boolean findWay (int map[][], int i, int j) {
if (map[6][5] == 2) {//说明已找到出口,退出程序
return true;
} else {
if (map[i][j] == 0) {//当前这个位置0,说明可以走
map[i][j] = 2;
if (findWay(map, i + 1, j)) {//向下走
return true;
} else if (findWay(map, i, j + 1)) {//向右走
return true;
} else if (findWay(map, i - 1, j)) {//向上走
return true;
} else if (findWay(map, i, j - 1)) {//向左走
return true;
} else {//
map[i][j] = 3;
return false;
}
} else {
return false;
}
}
}
}
输出结果为:
-----开始制作迷宫-----
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 1 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
-----开始走迷宫-----
1 1 1 1 1 1 1
1 2 2 2 0 0 1
1 3 1 2 0 0 1
1 1 1 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 2 2 1
1 1 1 1 1 1 1
6.5.11、汉诺塔(P226)
public class HanoiTower {
// 在main方法中,我们创建一个T类的对象t
public static void main(String[] args) {
T t = new T(); // 创建一个T类的对象t
t.move(3,'A','B','C'); // 调用t的move方法,将3个盘子从'A'柱移动到'C'柱,中间使用'B'柱作为辅助
}
}
// T类,包含move方法
class T {
// move方法接受4个参数:一个整数num表示盘子的数量,和三个字符a, b, c分别表示三个柱子的名称
public void move (int num, char a, char b, char c) {
// 如果盘子数量为1,直接将盘子从a柱移动到c柱
if (num == 1) {
System.out.println(a + "->" + c); // 输出移动的结果
} else {
// 递归调用move方法,将num-1个盘子从a柱移动到b柱,使用c柱作为辅助
move(num - 1, a, c, b);
// 输出移动的结果
System.out.println(a + "->" + c);
// 递归调用move方法,将num-1个盘子从b柱移动到c柱,使用a柱作为辅助
move(num - 1, b, a, c);
}
}
}
输出结果为:
A->C
A->B
C->B
A->C
B->A
B->C
A->C
6.5.12、八皇后(P227)
在8*8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后不能处于同一行,同一列或同一斜线上,问有多少种摆法?
不会写
6.5、方法重载(P228~233)
6.5.1、重载介绍(P228)
基本介绍:
Java中允许同一个类中,多个同名方法的存在,但要求形参列表不一致、
比如:System.out.println();out时PrintStream类型
public class OverLoad {
public static void main(String[] args) {
System.out.println(100);
System.out.println("hello world!");
System.out.println('h');
System.out.println(2.2);
System.out.println(true);
}
}
重载的好处:
1、减轻了起名的麻烦
2、减轻了记名的麻烦
6.5.2、重载快速入门(P229)
代码演示
public class OverLoad01 {
public static void main(String[] args) {
MyCalculator m = new MyCalculator();
System.out.println(m.calculate(1,1));
System.out.println(m.calculate(1,1.1));
System.out.println(m.calculate(2.2,1));
System.out.println(m.calculate(1,1,1));
}
}
class MyCalculator {
public int calculate(int n1, int n2) {
return n1 + n2;
}
public double calculate(int n1, double n2) {
return n1 + n2;
}
public double calculate(double n1, int n2) {
return n1 + n2;
}
public int calculate(int n1, int n2, int n3) {
return n1 + n2 + n3;
}
}
输出结果为:
2
2.1
3.2
3
6.5.3、重载使用细节(P230)
1、方法名必须相同
2、参数列表必须不同(参数类型或个数或顺序,至少有一样不同。参数名无要求)
3、返回类型无要求
6.5.4、重载课堂练习_1(P231)
6.5.5、重载课堂练习_2(P232)
1、编写程序,类Methods中定义三个重载方法并调用。方法名为m。三个方法分别接收一个int参数,两个int参数,一个字符串参数。分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。在主类的main()方法中分别用参数区别调用三个方法。
public class OverLoadExercise01 {
public static void main(String[] args) {
//1、编写程序,类Methods中定义三个重载方法并调用。方法名为m。
//三个方法分别接收一个int参数,两个int参数,一个字符串参数。
//分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。
//在主类的main()方法中分别用参数区别调用三个方法。
Methods method = new Methods();
System.out.println(method.m(5));
System.out.println(method.m(5,1));
method.m("123456");
}
}
class Methods {
public int m(int num) {
return num * num;
}
public int m(int num1, int num2) {
return num1 * num2;
}
public void m(String str) {
System.out.println(str);
}
}
输出结果为:
25
5
123456
6.5.6、重载课堂练习_3(P233)
2、在Methods类,定义三个重载方法max(),第一个方法,返回两个int值中最大的值;第二个方法,返回两个double值中的最大值;第三个方法,返回三个double值中的最大值,分别调用三个方法。
public class OverLoadExercise02 {
public static void main(String[] args) {
//2、在Methods类,定义三个重载方法max(),
//第一个方法,返回两个int值中最大的值;
//第二个方法,返回两个double值中的最大值;
//第三个方法,返回三个double值中的最大值,分别调用三个方法。
Methods m = new Methods();
System.out.println(m.max(6, 2));
System.out.println(m.max(6.6, 2.2));
System.out.println(m.max(6.66, 2.22,11));
}
}
class Methods {
public int max(int num1, int num2) {
return num1 > num2 ? num1 : num2;
}
public double max(double num1, double num2) {
return num1 > num2 ? num1 : num2;
}
public double max(double num1, double num2, double num3) {
System.out.println("使用double");
return num3 > (num1 > num2 ? num1 : num2) ? num3 : (num1 > num2 ? num1 : num2);
}
public double max(double num1, double num2, int num3) {
System.out.println("使用int");
return num3 > (num1 > num2 ? num1 : num2) ? num3 : (num1 > num2 ? num1 : num2);
}
}
输出结果为:
6
6.6
使用int
11.0
6.6、可变参数(P234~236)
6.6.1、可变参数使用(P234)
-
基本介绍:
Java允许将同一个类中多个同名、同功能,但参数个数不同的方法,封装成一个方法。就可以通过可变参数实现
-
基本语法:
访问修饰符 返回类型 方法名(数据类型... 形参名) {
}
-
使用可变参数解决问题
编写程序,类Methods中定义五个重载方法并调用。方法名为m。五个方法分别接收一个int参数,两个int参数,三个int参数,四个int参数,五个int参数。均执行求和运算并输出结果。在主类的main()方法中调用。
public class VarParameter01 {
public static void main(String[] args) {
//编写程序,类Methods中定义五个重载方法并调用。方法名为sum。
//五个方法分别接收一个int参数,两个int参数,三个int参数,四个int参数,五个int参数。
//均执行求和运算并输出结果。在主类的main()方法中调用。
Methods m = new Methods();
int result1 = m.sum(1,2,3,4,5);
System.out.println(result1);
int result2 = m.sum(3,4,5);
System.out.println(result2);
}
}
class Methods {
public int sum (int n1) {
return n1;
}
public int sum (int n1, int n2) {
return n1 + n2;
}
public int sum (int n1, int n2, int n3) {
return n1 + n2 + n3;
}
public int sum (int n1, int n2, int n3, int n4) {
return n1 + n2 + n3 + n4;
}
//...以上四个方法名称相同,功能、参数类型相同,参数个数不同
//可使用可变参数优化
//1、int... 表示接受的是可变参数,类型是int,即可以接收多个int(0~多)
//2、使用可变参数时,可以当作数组来使用,即将nums当作数组
//3、遍历nums求和即可
public int sum (int... nums) {
int res = 0;
for (int i = 0; i < nums.length; i++) {
res += nums[i];
}
return res;
}
}
输出结果为:
15
12
6.6.2、可变参数细节(P235)
-
注意事项和使用细节
1、可变参数的实参可以为0个或任意多个。
2、可变参数的实参可以为数组
public class VarParameterDetail {
public static void main(String[] args) {
T t = new T();
//2、可变参数的实参可以为数组
int arr[] = {1,2,3,4,5};
t.f1(arr);
}
}
class T {
public void f1(int... nums) {
System.out.println("数组长度为" + nums.length);
}
}
输出结果为:
数组长度为5
3、可变参数的本质就是数组
4、可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
5、一个形参列表中,只能出现一个可变参数
6.6.3、可变参数练习(P236)
有三个方法,分别实现返回姓名和两名课成绩(总分),返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。封装成一个可变参数的方法。类名HspMethod,方法名showScore
public class VarParameterExercise {
public static void main(String[] args) {
HspMethod h = new HspMethod();
System.out.println(h.showScore("milan",99.53,10.35));
System.out.println(h.showScore("Mike",99.53,10.35,7.2));
}
}
class HspMethod {
public String showScore (String name, double... score) {
double sum = 0;
for (int i = 0; i < score.length; i++) {
sum += score[i];
}
return name + "有" + score.length + "门课程,总分为:" + sum;
}
}
输出结果为:
milan有2门课程,总分为:109.88
Mike有3门课程,总分为:117.08
6.7、作用域(P237~239)
6.7.1、作用域基本使用(P237)
-
基本使用
1、在Java编程中,主要的变量就是属性(成员变量)和局部变量
2、我们说的局部变量一般是指在成员方法中定义的变量。
3、Java中作用域的分类:
全局变量:也就是属性,作用域为整个类。
局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中。
4、全局变量(属性)可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
代码演示
public class VarScope {
public static void main(String[] args) {
}
}
class Cat {
//全局变量:也就是属性,作用域为整个类。
int age = 10;
//全局变量(属性)可以不赋值,直接使用,因为有默认值
double weight;
public void eat() {
//局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中。
String name = "xiaobai";
//局部变量必须赋值后,才能使用,因为没有默认值。
String color;//这里会报错,因为color为局部变量
System.out.println("猫的颜色为:" + color);
}
}
6.7.2、作用域使用细节_1(P238)
-
注意事项和使用细节
1、属性和局部变量可以重名,访问时遵循就近原则。
public class VarScopeDetail {
public static void main(String[] args) {
Person p = new Person();
p.P1();
}
}
class Person {
String name = "Jack";
public void P1 () {
String name = "Mike";
System.out.println("P1()中的name = " + name);
}
}
输出结果为:
P1()中的name = Mike
2、在同一个作用域中,比如在同一个方法中,两个局部变量,不能重名。
3、属性声明周期长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量,声明周期短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁。即在一次方法调用过程中。
6.7.3、作用域使用细节_2(P239)
4、作用域范围不同
全局变量/属性:可以被本类使用,或者其他类使用(通过对象调用)
局部变量:只能在本类中对应的方法中使用
5、修饰符不同
全局变量/属性可以添加修饰符
局部变量不可以加修饰符
代码演示
public class VarScopeDetail {
public static void main(String[] args) {
Person p = new Person();
p.P1();
Test t = new Test();
t.test1();//第一种跨类访问对象属性的方式
t.test2(p);//第二种跨类访问对象属性的方式
}
}
class Test {
//全局变量/属性:可以被本类使用,或者其他类使用(通过对象调用)
public void test1 () {
Person p = new Person();
System.out.println(p.name);
}
public void test2 (Person PP) {
System.out.println(PP.name);
}
}
class Person {
String name = "Jack";
//5、全局变量/属性可以添加修饰符
private String color = "白色";
public void P1 () {
String name = "Mike";
System.out.println("P1()中的name = " + name);
}
}
输出结果为:
P1()中的name = Mike
Jack
Jack
6.8、构造方法/构造器(P240~244)
6.8.1、构造器基本介绍(P240)
-
看一个需求
前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值。如果现在要求,在创建人类的对象时,就直接指定这个对象的年龄和姓名,该怎么做?这时就可以使用构造器。
-
基本介绍
构造方法又叫构造器(constructor),是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。
-
基本语法
[修饰符] 方法名(形参列表) {
方法体;
}
说明:
1、构造器的修饰符可以为:默认、public、protected、private
2、构造器没有返回值,也不能写void
3、方法名和类名必须一样
4、参数列表和成员方法一样的规则
5、在创建对象时,系统会自动的调用该类的构造器完成对对象的初始化。
6.8.2、构造器快速入门(P241)
使用构造方法,在创建人类的对象时,就直接指定这个对象的姓名和年龄
public class Constructor01 {
public static void main(String[] args) {
//使用构造方法,在创建人类的对象时,就直接指定这个对象的姓名和年龄
Person p = new Person("Mike", 18);
System.out.println("构造方法的姓名" + p.name);
System.out.println("构造方法的年龄" + p.age);
}
}
class Person {
int age;
String name;
//(String Pname, int Page)是构造器形参列表,规则和成员方法一样
public Person(String Pname, int Page) {
System.out.println("调用构造方法");
name = Pname;
age = Page;
}
}
输出结果为:
调用构造方法
构造方法的姓名Mike
构造方法的年龄18
6.8.3、构造器使用细节_1(P242)
一个类可以定义多个不同的构造器,即构造器重载
比如:我们可以再给Person类定义一个构造器,用来创建对象的时候,只指定人名,不需要指定年龄。
public class ConstructorDetail {
public static void main(String[] args) {
Person p1 = new Person("Mike", 18);//第一个构造器
Person p2 = new Person("Jack");//第二个构造器
}
}
class Person {
String name;
int age;
public Person (String Pname, int Page) {
name = Pname;
age = Page;
}
public Person (String Pname) {
name = Pname;
}
}
6.8.4、构造器使用细节_2(P243)
6、如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器),比如Dog(){},使用javap指令 反编译查看。
public class ConstructorDetail {
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}
class Dog {
}
输出结果为:
7、一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器了,除非显示的定义一下,即:Dog(){}
public class ConstructorDetail {
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}
class Dog {
//一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器了
public Dog (String Dname) {
//...
}
//除非显示的定义一下,无参构造器,即:Dog(){}
Dog () {
}
}
输出结果为:
6.8.5、构造器课堂练习(P244)
在定义的Person类中,添加两个构造器:
第一个无参构造器:利用构造器设置所有人的age属性初始值都为18
第二个带pName和pAge两个参数的构造器:使得每次创建Person对象的同时,初始化对象的age属性值和name属性值。分别使用不同的构造器,创建对象。
public class ConstructorExercise {
public static void main(String[] args) {
Person p1 = new Person();
System.out.println("p1的name=" + p1.name + ",age=" + p1.age);
Person p2 = new Person("Mike", 20);
System.out.println("p2的name=" + p2.name + ",age=" + p2.age);
}
}
class Person {
String name;
int age;
//利用构造器设置所有人的age属性初始值都为18
Person() {
age = 18;
}
//使得每次创建Person对象的同时,初始化对象的age属性值和name属性值
public Person(String pName, int pAge) {
name = pName;
age = pAge;
}
}
输出结果为:
p1的name=null,age=18
p2的name=Mike,age=20
6.9、对象创建的流程分析(P245)
6.10、this(P246~251)
6.10.1、引出this(P246)
看段代码
public class this01 {
public static void main(String[] args) {
Dog d1 = new Dog("W", 2);
d1.info("白色");
}
}
class Dog {
String name;
int age;
public Dog(String dName, int dAge) {
name = dName;
age = dAge;
}
public void info(String color) {
System.out.println(name + "\t" + age + "\t" + color);
}
}
问题:构造方法的输入参数名不是非常的好,如果能将dName改成属性名一样(name)就好了,但是我们会发现按照变量的作用域原则,name的值就是null,age的值就是0。怎么解决?----->this
public class this01 {
public static void main(String[] args) {
Dog d1 = new Dog("W", 2);
d1.info("白色");
}
}
class Dog {
String name;
int age;
public Dog(String name, int age) {
name = name;
age = age;
}
public void info(String color) {
System.out.println(name + "\t" + age + "\t" + color);
}
}
输出结果为:
null 0 白色
6.10.2、this入门(P247)
-
什么是this
Java虚拟机会给每个对象分配this(我的),代表当前对象。
为上一小节代码添加this
public class this01 {
public static void main(String[] args) {
Dog d1 = new Dog("W", 2);
d1.info("白色");
}
}
class Dog {
String name;
int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public void info(String color) {
System.out.println(name + "\t" + age + "\t" + color);
}
}
输出结果为:
W 2 白色
6.10.3、this本质(P248)
public class this01 {
public static void main(String[] args) {
Dog d1 = new Dog("W", 2);
System.out.println("d1的hashCode值" + d1.hashCode());
//d1.info("白色");
Dog d2 = new Dog("S", 5);
System.out.println("d2的hashCode值" + d2.hashCode());
}
}
class Dog {
String name;
int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
System.out.println("this.hashCode=" + this.hashCode());
}
public void info(String color) {
System.out.println(name + "\t" + age + "\t" + color);
}
}
输出结果为:
this.hashCode=366712642
d1的hashCode值366712642
this.hashCode=1829164700
d2的hashCode值1829164700
6.10.4、this小结(P249)
简单来说,哪个对象调用,this就代表哪个对象
public class this01 {
public static void main(String[] args) {
Dog d1 = new Dog("W", 2);
System.out.println("d1的hashCode值" + d1.hashCode());
d1.info("白色");
Dog d2 = new Dog("S", 5);
System.out.println("d2的hashCode值" + d2.hashCode());
d2.info("花色");
}
}
class Dog {
String name;
int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
System.out.println("this.hashCode=" + this.hashCode());
}
public void info(String color) {
System.out.println("this.hashCode=" + this.hashCode());
System.out.println(name + "\t" + age + "\t" + color);
}
}
输出结果为:
this.hashCode=366712642
d1的hashCode值366712642
this.hashCode=366712642
W 2 白色
this.hashCode=1829164700
d2的hashCode值1829164700
this.hashCode=1829164700
S 5 花色
6.10.5、this使用细节(P250)
-
this的注意事项和使用细节
1、this关键字可以用来访问本类的属性、方法、构造器
public class thisDetail {
public static void main(String[] args) {
T t2 = new T();
t2.f3();
}
}
class T {
String name = "Jack";
int age = 25;
//1、this关键字可以用来访问本类的属性、方法、构造器
public void f3() {
String name = "Smith";
//传统方法按照就近原则访问常量
System.out.println("name=" + name + " age=" + age);
//this方法只访问属性
System.out.println("name=" + this.name + " age=" + this.age);
}
}
输出结果为:
name=Smith age=25
name=Jack age=25
2、this用于区分当前类的属性和局部变量
3、访问成员方法的语法:this.方法名(参数列表);
public class thisDetail {
public static void main(String[] args) {
T t = new T();
t.f2();
}
}
class T {
//3、访问成员方法的语法:this.方法名(参数列表);
public void f1() {
System.out.println("调用f1()方法");
}
public void f2() {
System.out.println("调用f2()方法");
f1();
this.f1();
}
}
输出结果为:
调用f2()方法
调用f1()方法
调用f1()方法
4、访问构造器语法:this(参数列表);注意只能在构造器中使用(即只能在构造器中访问另一个构造器)
注意:访问构造器语法:this(参数列表);必须放置在第一条语句
public class thisDetail {
public static void main(String[] args) {
T t1 = new T();
}
}
class T {
//4、访问构造器语法:this(参数列表);
//注意:1、只能在构造器中使用(即只能在构造器中访问另一个构造器)
// 2、访问构造器语法:this(参数列表);必须放置在第一条语句
public T() {
this("Mike", 18);
System.out.println("T()构造器");
}
public T(String name, int age) {
System.out.println("name=" + name + " age=" + age);
}
}
}
输出结果为:
name=Mike age=18
T()构造器
5、this不能在类定义的外部使用,只能在类定义的方法中使用
6.10.6、this课堂练习(P251)
定义Person类,里面有name、age属性,并提供compareTo比较方法,用于判断是否和另一个人相等,提供测试类TestPerson用于测试,名字和年龄完全一样,就返回true,否则返回false。
public class TestPerson {
public static void main(String[] args) {
//定义Person类,里面有name、age属性,并提供compareTo比较方法,
//用于判断是否和另一个人相等,提供测试类TestPerson用于测试,
//名字和年龄完全一样,就返回true,否则返回false。
Person p1 = new Person("Mike", 18);
Person p2 = new Person("Jack", 18);
System.out.println("p1和p2的比较结果为:" + p1.compareTo(p2));
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public boolean compareTo(Person p) {
return this.name.equals(p.name) && this.age==p.age ? true : false;
}
}
输出结果为:
p1和p2的比较结果为:false
6.11、本章作业(P252~262)
6.11.1、本章作业_1(P252)
1、编写类A01,定义方法max,实现求某个double数组的最大值,并返回。
public class Homework01 {
public static void main(String[] args) {
//1、编写类A01,定义方法max,实现求某个double数组的最大值,并返回。
//第一种
double arr[] = {64.2, 77,5, 99,2, 666.6, 6};
A01 a = new A01();
System.out.println("arr数组最大值为:" + a.max(arr));
//第二种
double arr1[] = null;
Double result = a.max(arr1);
if (result != null) {
System.out.println("arr1数组最大值为:" + a.max(arr1));
} else {
System.out.println("arr1数组为{},或者null");
}
//第三种
double arr2[] = {};
if (result != null) {
System.out.println("arr2数组最大值为:" + a.max(arr2));
} else {
System.out.println("arr2数组为{},或者null");
}
}
}
class A01 {
public Double max(double arr[]) {
if (arr != null && arr.length > 0) {
double maxNum = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > maxNum) {
maxNum = arr[i];
}
}
return maxNum;
} else {
return null;
}
}
}
输出结果为:
arr数组最大值为:666.6
arr1数组为{},或者null
arr2数组为{},或者null
6.11.2、本章作业_2(P253)
2、编写类A02,定义方法find,实现查找某字符串是否在字符串数组中,找得到返回索引,找不到,返回-1。
public class Homework02 {
public static void main(String[] args) {
//2、编写类A02,定义方法find,
//实现查找某字符串是否在字符串数组中,找得到返回索引,找不到,返回-1。
String arr[] = {"a", "b", "c", "d", "e", "f", "g", "h"};
String findString = "h";
A02 a = new A02();
int index = a.find(findString, arr);
if (index != -1) {
System.out.print("字符串在数组中的下标为:" + index);
} else {
System.out.print("未找到");
}
}
}
class A02 {
public int find(String findStr, String[] arr) {
int flag = -1;
for (int i = 0; i < arr.length; i++) {
if (findStr.equals(arr[i])) {
flag = i;
break;
}
}
return flag;
}
}
输出结果为:
字符串在数组中的下标为:7
6.11.3、本章作业_3(P254)
3、编写类Book,定义方法updatePrice,实现更改某书名的价格,具体:如果价格>150,则更改为150,如果价格>100,则更改为100,否则不变。
public class Homework03 {
public static void main(String[] args) {
//3、编写类Book,定义方法updatePrice,实现更改某书名的价格,
//具体:如果价格>150,则更改为150,如果价格>100,则更改为100,否则不变。
Book b = new Book("三国演义", 120);
b.print();
b.updatePrice();
b.print();
}
}
class Book {
String name;
double price;
public Book(String name, double price) {
this.name = name;
this.price = price;
}
public void updatePrice() {
//如果方法中没有与属性相同名称的局部变量,this可以省略
if (this.price > 150) {
this.price = 150;
} else if (this.price > 100) {
this.price = 100;
}
}
public void print() {
System.out.println("书名为:" + this.name + ",价格为:" + this.price);
}
}
输出结果为:
书名为:三国演义,价格为:120.0
书名为:三国演义,价格为:100.0
6.11.4、本章作业_4(P255)
4、编写类A03,实现数组的复制功能copyArr,输入旧数组,返回一个新数组,元素和旧数组一样
import java.util.Scanner;
public class Homework04 {
public static void main(String[] args) {
//4、编写类A03,实现数组的复制功能copyArr,
//输入旧数组,返回一个新数组,元素和旧数组一样
int oldArr[] = new int[5];
Scanner myScanner = new Scanner(System.in);
for (int i = 0; i < oldArr.length; i++) {
System.out.print("请输入第" + (i + 1) + "个元素:");
oldArr[i] = myScanner.nextInt();
}
A03 a = new A03(oldArr);
int newArr[] = a.copyArr();
System.out.println("将arr1的元素拷贝到arr2中");
for (int i = 0; i < oldArr.length; i++) {
System.out.print(newArr[i] + " ");
}
System.out.println("\n修改arr2数组arr2[1] = 99,并输出");
newArr[1] = 99;
for (int i = 0; i < oldArr.length; i++) {
System.out.print(newArr[i] + " ");
}
System.out.println("\n查看arr1数组元素:");
for (int i = 0; i < oldArr.length; i++) {
System.out.print(oldArr[i] + " ");
}
}
}
class A03 {
int arr[];
public A03(int arr[]) {
this.arr = arr;
}
public int[] copyArr() {
int arr[] = new int[this.arr.length];
for (int i = 0; i < this.arr.length; i++) {
arr[i] = this.arr[i];
}
return arr;
}
}
输出结果为:
请输入第1个元素:1
请输入第2个元素:2
请输入第3个元素:3
请输入第4个元素:4
请输入第5个元素:5
将arr1的元素拷贝到arr2中
1 2 3 4 5
修改arr2数组arr2[1] = 99,并输出
1 99 3 4 5
查看arr1数组元素:
1 2 3 4 5
6.11.5、本章作业_5(P256)
5、定义一个圆类Circle,定义属性:半径,提供显示圆周长功能的方法,提供显示圆面积的方法
public class Homework05 {
public static void main(String[] args) {
//5、定义一个圆类Circle,定义属性:半径,提供显示圆周长功能的方法,提供显示圆面积的方法
double r = 3;
Circle c = new Circle(r);
System.out.println("圆的周长为:" + c.perimeter());
System.out.print("圆的面积为:" + c.area());
}
}
class Circle {
double r;
public Circle(double r) {
this.r = r;
}
public double perimeter() {
return 2 * Math.PI * this.r;
}
public double area() {
return Math.PI * this.r * this.r;
}
}
输出结果为:
圆的周长为:18.84955592153876
圆的面积为:28.274333882308138
6.11.6、本章作业_6(P257)
6、编程创建一个Cale计算类,在其中定义2个变量表示两个操作数,定义四个方法实现求和、差、乘、商(要求除数为0的话,要提示)并创建两个对象,分别测试
(1)
public class Homework06 {
public static void main(String[] args) {
//6、编程创建一个Cale计算类,在其中定义2个变量表示两个操作数,
//定义四个方法实现求和、差、乘、商(要求除数为0的话,要提示)并创建两个对象,分别测试
int num1 = 12;
int num2 = 5;
Cale c = new Cale(num1, num2);
System.out.println("num1=" + num1 + ",num2=" + num2);
System.out.println("num1和num2的和为:" + c.Sum());
System.out.println("num1和num2的差为:" + c.Sub());
System.out.println("num1和num2的乘为:" + c.Mul());
if (c.Div() != null) {
System.out.print("num1和num2的商为:" + c.Div());
}
}
}
class Cale {
double num1;
double num2;
public Cale(int num1, int num2) {
this.num1 = num1;
this.num2 = num2;
}
public double Sum() {
return num1 + num2;
}
public double Sub() {
return num1 - num2;
}
public double Mul() {
return num1 * num2;
}
public Double Div() {
if (this.num2 == 0) {
System.out.print("num2输入错误!");
return null;
} else {
return num1 / num2;
}
}
}
输出结果为:
num1=12,num2=5
num1和num2的和为:17.0
num1和num2的差为:7.0
num1和num2的乘为:60.0
num1和num2的商为:2.4
(2)将num2改为0
public class Homework06 {
public static void main(String[] args) {
//6、编程创建一个Cale计算类,在其中定义2个变量表示两个操作数,
//定义四个方法实现求和、差、乘、商(要求除数为0的话,要提示)并创建两个对象,分别测试
int num1 = 12;
int num2 = 0;
Cale c = new Cale(num1, num2);
System.out.println("num1=" + num1 + ",num2=" + num2);
System.out.println("num1和num2的和为:" + c.Sum());
System.out.println("num1和num2的差为:" + c.Sub());
System.out.println("num1和num2的乘为:" + c.Mul());
if (c.Div() != null) {
System.out.print("num1和num2的商为:" + c.Div());
}
}
}
class Cale {
double num1;
double num2;
public Cale(int num1, int num2) {
this.num1 = num1;
this.num2 = num2;
}
public double Sum() {
return num1 + num2;
}
public double Sub() {
return num1 - num2;
}
public double Mul() {
return num1 * num2;
}
public Double Div() {
if (this.num2 == 0) {
System.out.print("num2输入错误!");
return null;
} else {
return num1 / num2;
}
}
}
输出结果为:
num1=12,num2=0
num1和num2的和为:12.0
num1和num2的差为:12.0
num1和num2的乘为:0.0
num2输入错误!
6.11.7、本章作业_7(P258)
7、设计一个Dog类,有名字、颜色和年龄属性,定义输出方法show()显示其信息。并创建对象,进行测试。提示:有this.属性
public class Homework07 {
public static void main(String[] args) {
//7、设计一个Dog类,有名字、颜色和年龄属性,
//定义输出方法show()显示其信息。并创建对象,进行测试。提示:有this.属性
String dogName = "小白";
String dogColor = "白色";
int age = 3;
Dog dogOne = new Dog(dogName, dogColor, age);
dogOne.show();
}
}
class Dog {
String name;
String color;
int age;
public Dog(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public void show() {
System.out.print("狗的名字为:" + this.name + ",颜色为" +
this.color + ",年龄为:" + this.age);
}
}
输出结果为:
狗的名字为:小白,颜色为白色,年龄为:3
8、给定一个Java程序的代码如下所示,则编译运行后,输出结果是
public class Test {//共有类
int count = 9;//属性
public void count1() {//Test类的成员方法
count = 10;//这个count就是属性,改为10。但不影响int count = 9;
System.out.println("count1=" + count);
}
public void count2() {//Test类的成员方法
System.out.println("count1=" + count++);
}
//这是Test类的main()方法,任何一个类,都可有main
public static void main(String[] args) {
//new Test()是匿名对象。匿名对象使用一次后,就不能再使用
//new Test().count1(); 匿名对象创建后,调用count1()方法
//因为只能使用一次,所以count = 10;不会影响属性count
new Test().count1();
Test t1 = new Test();
t1.count1();
t1.count2();
t1.count2();
}
}
输出结果为:
count1=10
count1=10
count1=10
count1=11
6.11.8、本章作业_8(P259)
9、定义Music类,里面有音乐名name、音乐时长times属性,并有播放play功能和返回本身属性信息的功能方法getInfo。
public class Homework09 {
public static void main(String[] args) {
//9、定义Music类,里面有音乐名name、音乐时长times属性,
//并有播放play功能和返回本身属性信息的功能方法getInfo。
Music music = new Music("笑傲江湖", 300);
music.play();
System.out.print("\n" + music.getInfo());
}
}
class Music {
String name;
double times;
public Music(String name, double times) {
this.name = name;
this.times = times;
}
public String getInfo() {
return "音乐" + this.name
+ ",时长为:" + this.times;
}
public void play() {
System.out.print("音乐" + this.name + "正在播放,"
+ "时长为:" + this.times);
}
}
输出结果为:
音乐笑傲江湖正在播放,时长为:300.0
音乐笑傲江湖,时长为:300.0
10、试写出下面代码的运行结果
public class Homework10 {
public static void main(String[] args) {
}
}
class Demo {
int i = 100;
public void m() {
int j = i++;
System.out.println("i=" + i);
System.out.println("j=" + j);
}
}
class Test {
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = d1;
d2.m();
System.out.println(d1.i);
System.out.println(d2.i);
}
}
输出结果为:
6.11.9、本章作业_9(P260)
11、在测试方法中,调用method方法,代码如下,编译正确,试写出method方法的定义形式,调用语句为:System.out.println(method(method(10.0, 20.0), 100));
public class Homework11 {
public static void main(String[] args) {
//11、在测试方法中,调用method方法,代码如下,编译正确,
//试写出method方法的定义形式,调用语句为:
//System.out.println(method(method(10.0, 20.0), 100));
MyTools myTools = new MyTools();
System.out.println(myTools.method(myTools.method(10.0, 20.0), 100));
}
}
class MyTools {
public double method(double num1, double num2) {
return num1 + num2;
}
}
输出结果为:
130.0
12、创建一个Employee类,属性有(名字,性别,年龄,职位,薪水),提供3个构造方法,可以初始化(1) (名字,性别,年龄,职位,薪水),(2)(姓名,性别,年龄),(3)(职位,薪水),要求充分复用构造器
public class Homework12 {
public static void main(String[] args) {
//12、创建一个Employee类,属性有(名字,性别,年龄,职位,薪水),
//提供3个构造方法,可以初始化(1) (名字,性别,年龄,职位,薪水),
//(2)(姓名,性别,年龄),(3)(职位,薪水),要求充分复用构造器
}
}
class Employee {
String name;
char sex;
int age;
String position;
double salary;
public Employee(String position, double salary) {
this.position = position;
this.salary = salary;
}
public Employee(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public Employee(String name, char sex, int age,
String position, double salary) {
this(name, sex, age);
this.position = position;
this.salary = salary;
}
}
6.11.10、本章作业_10(P261)
13、将对象作为参数传递给方法。
题目要求:
(1)定义一个Circle类,包含一个double类型的radius属性,代表圆的半径,findArea()方法返回圆的面积。
(2)定义一个PassObject类,在类中定义一个方法printAreas(),该方法的定义如下:
public void printAreas(Circle c, int times)
(3)在printAreas方法中打印输出1到times之间的每个整数半径值,以及对应的面积。
例如:times为5,则输出半径为1,2,3,4,5对应的圆的面积
(4)在main方法中调用printAreas()方法,调用完毕后输出当前半径值。程序运行结果如图所示。
6.11.11、本章作业_11(P262)
14、扩展题
有个人Tom设计他的成员变量.成员方法,可以电脑猜拳。
电脑每次都会随机生成0,1,2
0表示石头,1表示剪刀,2表示布
并要可以显示Tom输赢的次数(清单)
(1)自己写的
import java.util.Scanner;
public class Homework14 {
public static void main(String[] args) {
/*
14、扩展题
有个人Tom设计他的成员变量.成员方法,可以电脑猜拳。
电脑每次都会随机生成0,1,2
0表示石头,1表示剪刀,2表示布
并要可以显示Tom输赢的次数(清单)
int num = ((int)(Math.random() * 100) + 1) % 3;
*/
Scanner myScanner = new Scanner(System.in);
Guess gue = new Guess();
String stop = "yes";
int[] count = {0, 0, 0};
int printGuess;
while (stop.equals("yes")) {
System.out.println("请输入0表示石头,1表示剪刀,2表示布");
printGuess = myScanner.nextInt();
if (printGuess < 0 || printGuess > 2) {
System.out.println("用户输入错误!");
} else {
count = gue.guess(count, printGuess);
}
System.out.println("是否继续玩猜拳?输入yes继续,其他退出。");
stop = myScanner.next();
System.out.println();
}
System.out.println("猜拳结果为:");
System.out.println("赢的次数为:" + count[0]);
System.out.println("输的次数为:" + count[1]);
System.out.println("平局的次数为:" + count[2]);
}
}
class Guess {
public int[] guess(int[] count, int printGuess) {
//count[0]计赢得次数,count[1]计输的次数,count[2]计平局次数
//请输入0表示石头,1表示剪刀,2表示布
int num = ((int)(Math.random() * 100) + 1) % 3;
if (printGuess == 0) {
System.out.println("我出石头");
} else if (printGuess == 1) {
System.out.println("我出剪刀");
} else if (printGuess == 2) {
System.out.println("我出布");
}
if (num == printGuess) {
System.out.println("平局");
count[2]++;
return count;
} else if (num == 0 && printGuess == 1) {
System.out.println("系统出石头");
count[1]++;
return count;
} else if (num == 0 && printGuess == 2) {
System.out.println("系统出石头");
count[0]++;
return count;
} else if (num == 1 && printGuess == 0) {
System.out.println("系统出剪刀");
count[0]++;
return count;
} else if (num == 1 && printGuess == 2) {
System.out.println("系统出剪刀");
count[1]++;
return count;
} else if (num == 2 && printGuess == 0) {
System.out.println("系统出布");
count[1]++;
return count;
} else {
System.out.println("系统出布");
count[0]++;
return count;
}
}
}
输出结果为:
请输入0表示石头,1表示剪刀,2表示布
1
我出剪刀
系统出石头
是否继续玩猜拳?输入yes继续,其他退出。
yes
请输入0表示石头,1表示剪刀,2表示布
2
我出布
系统出石头
是否继续玩猜拳?输入yes继续,其他退出。
yes
请输入0表示石头,1表示剪刀,2表示布
0
我出石头
平局
是否继续玩猜拳?输入yes继续,其他退出。
no
猜拳结果为:
赢的次数为:1
输的次数为:1
平局的次数为:1
(2)韩
import java.util.Scanner;
import java.util.Random;
public class Homework14 {
public static void main(String[] args) {
//创建一个玩家对象
Tom t = new Tom();
//用来记录最后输赢的次数
int isWinCount = 0;
//创建一个二维数组,用来接收局数中Tom、电脑的出拳情况
int[][] arr1 = new int[3][3];
int j = 0;
//创建一个一维数组,用来接收输赢情况
String[] arr2 = new String[3];
Scanner myScanner = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
//获取玩家出的拳
System.out.println("请输入你要出的拳(0-石头,1-剪刀,2-布):");
int num = myScanner.nextInt();
t.setTomGuessNum(num);
int tomGuess = t.getTomGuessNum();
arr1[i][j + 1] = tomGuess;
//获取电脑出的拳
int comGuess = t.computerNum();
arr1[i][j + 2] = comGuess;
//将玩家与电脑出的拳进行比较
String isWin = t.vsComputer();
arr2[i] = isWin;
arr1[i][j] = t.count;
//
System.out.println("===========================");
System.out.println("局数\t玩家的出拳\t电脑的出拳\t输赢情况");
System.out.println(t.count + "\t" + tomGuess + "\t\t" + comGuess +
"\t\t" + t.vsComputer());
System.out.println("===========================");
System.out.println("\n\n");
isWinCount = t.winCount(isWin);
}
//对游戏的最终结果进行输出
System.out.println("局数\t玩家的出拳\t电脑的出拳\t\t输赢情况");
for (int a = 0; a < arr1.length; a++) {
for (int b = 0; b < arr1[a].length; b++) {
System.out.print(arr1[a][b] + "\t\t\t");
}
System.out.print(arr2[a]);
System.out.println();
}
System.out.println("你赢了" + isWinCount + "次");
}
}
class Tom {//核心代码
//玩家出拳的类型
int tomGuessNum;
//电脑出拳的类型
int comGuessNum;
//玩家赢的次数
int winCountNum;
//比赛的次数
int count = 1;
public void showInfo() {
//...
}
/**
* 电脑随机生成猜拳的数字的方法
* @return
*/
public int computerNum() {
Random r = new Random();
comGuessNum = r.nextInt(3);// 方法 返回 0-2的随机数
//System.out.println(comGuessNum)
return comGuessNum;
}
/**
* 设置玩家猜拳的数字的方法
* @param tomGuessNum
*/
public void setTomGuessNum(int tomGuessNum) {
if (tomGuessNum > 2 || tomGuessNum < 0) {
//抛出一个异常,李同学会写,没有处理
throw new IllegalArgumentException("数字输入错误");
}
this.tomGuessNum = tomGuessNum;
}
public int getTomGuessNum() {
return tomGuessNum;
}
/**
* 比较猜拳的结果
* @return 玩家赢返回true,否则返回false
*/
public String vsComputer() {
//比较
if (tomGuessNum == 0 && comGuessNum == 1) {
return "你赢了";
} else if (tomGuessNum == 1 && comGuessNum == 2) {
return "你赢了";
} else if (tomGuessNum == 2 && comGuessNum == 0) {
return "你赢了";
} else if (tomGuessNum == comGuessNum){
return "平手";
} else {
return "你输了";
}
}
/**
* 记录玩家赢的次数
* @return
*/
public int winCount(String s) {
count++;
if (s.equals("你赢了")) {
winCountNum++;
}
return winCountNum;
}
}
输出结果为:
请输入你要出的拳(0-石头,1-剪刀,2-布):
0
===========================
局数 玩家的出拳 电脑的出拳 输赢情况
1 0 1 你赢了
===========================
请输入你要出的拳(0-石头,1-剪刀,2-布):
1
===========================
局数 玩家的出拳 电脑的出拳 输赢情况
2 1 2 你赢了
===========================
请输入你要出的拳(0-石头,1-剪刀,2-布):
2
===========================
局数 玩家的出拳 电脑的出拳 输赢情况
3 2 2 平手
===========================
局数 玩家的出拳 电脑的出拳 输赢情况
1 0 1 你赢了
2 1 2 你赢了
3 2 2 平手
你赢了2次