Java笔记、第六章、面向对象编程(基础部分)

第七章 链接

CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/134775022?spm=1001.2014.3001.9457

目录

6.1、类与对象(P192~201)

6.1.1、类与对象的引出(P192)

6.1.2、类与对象的概述(P193)

6.1.3、面向对象快速入门(P194)

6.1.4、对象内存布局(P195)

6.1.5、属性概念(P196)

6.1.6、属性注意细节(P197)

6.1.7、创建对象访问属性(P198)

6.1.8、对象分配机制(P199)

6.1.9、对象创建过程(P200)

6.1.10、对象机制练习(P201)

6.2、方法(P202~210)

6.2.1、方法快速入门_1(P202)

6.2.2、方法快速入门_2(P203)

6.2.3、方法调用机制(P204)

6.2.4、方法的妙用(P205)

6.2.5、方法的定义(P206)

6.2.6、方法使用细节_1(P207)

6.2.7、方法使用细节_2(P208)

6.2.8、方法使用细节_3(P209)

6.2.9、方法练习题_1(P210)

6.3、成员方法传参机制(重点)(P211~214)

6.3.1、方法传参机制_1(P211)

6.3.2、方法传参机制_2(P212)

6.3.3、方法传参机制_3(P213)

6.3.4、克隆对象(P214)

6.4、方法递归调用(P215~227)

6.4.1、递归解决什么问题(P215)

6.4.2、递归执行机制_1(P216)

6.4.3、递归执行机制_2(P217)

6.4.4、递归执行机制_3(P218)

6.4.5、递归执行机制_4(P219)

6.5.5、递归斐波那契数列(P220)

6.5.6、猴子吃桃(P221)

6.5.7、老输出迷宫_1(P222)

6.5.8、老鼠出迷宫_2(P223)

6.5.9、老输出迷宫_3(P224)

6.5.10、老输出迷宫_4(P225)

6.5.11、汉诺塔(P226)

6.5.12、八皇后(P227)

6.5、方法重载(P228~233)

6.5.1、重载介绍(P228)

6.5.2、重载快速入门(P229)

6.5.3、重载使用细节(P230)

6.5.4、重载课堂练习_1(P231)

6.5.5、重载课堂练习_2(P232)

6.5.6、重载课堂练习_3(P233)

6.6、可变参数(P234~236)

6.6.1、可变参数使用(P234)

6.6.2、可变参数细节(P235)

6.6.3、可变参数练习(P236)

6.7、作用域(P237~239)

6.7.1、作用域基本使用(P237)

6.7.2、作用域使用细节_1(P238)

6.7.3、作用域使用细节_2(P239)

6.8、构造方法/构造器(P240~244)

6.8.1、构造器基本介绍(P240)

6.8.2、构造器快速入门(P241)

6.8.3、构造器使用细节_1(P242)

6.8.4、构造器使用细节_2(P243)

6.8.5、构造器课堂练习(P244)

6.9、对象创建的流程分析(P245)

6.10、this(P246~251)

6.10.1、引出this(P246)

6.10.2、this入门(P247)

6.10.3、this本质(P248)

6.10.4、this小结(P249)

6.10.5、this使用细节(P250)

6.10.6、this课堂练习(P251)

6.11、本章作业(P252~262)

6.11.1、本章作业_1(P252)

6.11.2、本章作业_2(P253)

6.11.3、本章作业_3(P254)

6.11.4、本章作业_4(P255)

6.11.5、本章作业_5(P256)

6.11.6、本章作业_6(P257)

6.11.7、本章作业_7(P258)

6.11.8、本章作业_8(P259)

6.11.9、本章作业_9(P260)

6.11.10、本章作业_10(P261)

6.11.11、本章作业_11(P262)


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次
​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值