第七章 面向对象编程(基础)

一、类与对象

1. 类和对象的区别和联系

(1) 类是抽象的,概念的,代表一类事物, 比如人类、 猫类 ... 即它是数据类型。

(2) 对象是具体的,实际的,代表一个具体事物,即实例 。

(3) 类是对象的模板,对象是类的一个个体,对应一个实例。

2. 属性/成员变量/字段

属性是类的一个组成部分,一般是基本数据类型,也可以是引用类型 ( 对象,数组 )。

属性如果不赋值,有默认值。

3. 成员方法

(1)当程序执行到方法时,就会开辟一个独立的空间(栈空间)。

(2)当方法执行完毕,或者执行到 return 语句时,就会返回。

(3)返回到调用方法的地方。

(4)返回后,继续执行方法后面的代码。

(5)当 main 方法(栈)执行完毕,整个程序退出。

成员方法的定义:
访问修饰符  返回数据类型  方法名 (形参列表 .. ) {// 方法体
        语句;
        return 返回值 ;
}

成员方法的好处

  1. 提高代码的复用性
  2. 可以将实现的细节封装起来,然后供其他用户来调用即可

4. 类和对象的内存分配机制

Java 内存的结构分析

  1. 栈: 一般存放基本数据类型(局部变量)
  2. 堆: 存放对象(Cat cat , 数组等)
  3. 方法区:常量池(常量,比如字符串), 类加载信息

二、递归(P215)

递归重要规则

(1)执行一个方法时,就创建一个新的受保护的独立空间(栈空间)。

(2)方法的局部变量是独立的,不会相互影响,比如 n 变量。

(3)如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的数据。

(4)递归必须向退出递归的条件逼近,否则就是无限递归,出现 StackOverflowError

(5)当一个方法执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。

1. 阶乘

java 复制代码
public class Demo {
 
    public static void main(String[] args) {
        int res = factorial(5);
        System.out.println("5 的阶乘 res =" + res);
    }
 
    //factorial 阶乘
    public static int factorial(int n) {
        if (n == 1) {
            return 1;
        } else {
            return factorial(n - 1) * n;
        }
    }
 
}

2. 斐波那契数

java 复制代码
public class Demo {
 
    public static void main(String[] args) {
        int n = 7;
        System.out.println("当 n=" + n + " 对应的斐波那契数=" + fibonacci(n));
    }
 
    /**
     * 请使用递归的方式求出斐波那契数 1,1,2,3,5,8,13...给你一个整数 n,求出它的值是多
     */
    public static int fibonacci(int n) {
        if (n == 1 || n == 2) {
            return 1;
        } else {
            return fibonacci(n - 1) + fibonacci(n - 2);
        }
    }
 
}

3. 猴子吃桃子问题(P221)

java 复制代码
public class Demo {
 
    public static void main(String[] args) {
        //桃子问题
        int day = 1;
        int peachNum = peach(day);
        if (peachNum != -1) {
            System.out.println("第 " + day + "天有" + peachNum + "个桃子");
        }
    }
 
    /**
     * 猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!
     * 以后每天猴子都吃其中的一半,然后再多吃一个。当到第 10 天时,
     * 想再吃时(即还没吃),发现只有 1 个桃子了。问题:最初共多少个桃子?
     */
    public static int peach(int day) {
        if (day == 10) {//第 10 天,只有 1 个桃
            return 1;
        } else if (day >= 1 && day <= 9) {
            return (peach(day + 1) + 1) * 2;//规则,自己要想
        } else {
            System.out.println("day 在 1-10");
            return -1;
        }
    }
 
}

4. 老鼠迷宫( P222)

java 复制代码
public class Demo {
    public static void main(String[] args) {

        int[][] map = new int[8][7];
        //3. 将最上面的一行和最下面的一行,全部设置为 1
        for (int i = 0; i < 7; i++) {
            map[0][i] = 1;
            map[7][i] = 1;
        }
        //4.将最右面的一列和最左面的一列,全部设置为 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; //测试回溯
        // map[2][1] = 1;
        // map[2][2] = 1;
        // map[1][2] = 1;

        //输出当前的地图
        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();
        }

        findWay(map, 1, 1);

        // 找路地图
        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();
        }
    }

    // 0:可以走 1:障碍物 2:可以走 3:走过但是走不通
    // (6,5) = 2 说明成功
    // 策略 下 > 右 > 上 > 左
    public static 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 { // map[i][j] == 1,2,3
                return false;
            }
        }
    }
}

5. 汉诺塔

java 复制代码
public class Demo {
    public static void main(String[] args) {
        Tower tower = new Tower();
        tower.move(64, 'A', 'B', 'C');
    }
}

class Tower {

    //num 表示要移动的个数, a, b, c 分别表示 A 塔,B 塔, C 塔
    public void move(int num, char a, char b, char c) {

        if (num == 1) {
            System.out.println(a + "->" + c);
        } else {
            //如果有多个盘,可以看成两个 , 最下面的和上面的所有盘(num-1)
            //(1)先移动上面所有的盘到 b, 借助 c
            move(num - 1, a, c, b);
            //(2)把最下面的这个盘,移动到 c
            System.out.println(a + "->" + c);
            //(3)再把 b 塔的所有盘,移动到 c ,借助 a
            move(num - 1, b, a, c);
        }
    }
}

三、方法重载(OverLoad)

java 中允许同一个类中,多个同名方法的存在,但要求形参列表不一致!

注意事项和使用细节:

(1)方法名:必须相同

(2)形参列表:必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求)。

(3)返回类型:无要求

四、可变参数

java 允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。 就可以通过可变参数实现。

基本语法
访问修饰符 返回类型 方法名(数据类型... 形参名){

}
java 复制代码
public class Demo {
 
    public static void main(String[] args) {
        System.out.println(sum(1, 5, 100)); //106
        System.out.println(sum(1, 19)); //20
    }
 
    //1. int... 表示接受的是可变参数,类型是 int ,即可以接收多个 int(0-多)
    //2. 使用可变参数时,可以当做数组来使用 即 nums 可以当做数组
    //3. 遍历 nums 求和即可
    public static int sum(int... nums) {
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            res += nums[i];
        }
        return res;
    }
 
}

注意事项和使用细节

(1)可变参数的实参可以为 0 个或任意多个。

(2)可变参数的实参可以为数组。

(3)可变参数的本质就是数组。

(4)可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后。

(5)一个形参列表中只能出现一个可变参数。

五、构造方法/构造器

1. 基本语法

[ 修饰符 ] 方法名 ( 形参列表 ){
        方法体;
}

(1) 构造器的修饰符可以默认, 也可以是 public protected private。

(2) 构造器没有返回值。

(3) 方法名和类名字必须一样。

(4) 参数列表和成员方法一样的规则。

(5) 造器的调用, 由系统完成。

2. 基本介绍

构造方法又叫构造器 (constructor) ,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。它有几个特点:

(1) 方法名和类名相同

(2) 没有返回值

(3) 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化。

3. 注意事项和使用细节

(1)一个类可以定义多个不同的构造器,即构造器重载。

(2)构造器名和类名要相同。

(3)构造器没有返回值。

(4)构造器是完成对象的初始化,并不是创建对象。

(5)在创建对象时,系统自动的调用该类的构造方法。

(6)如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)。

(7)一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显式的定义一下。

4. 对象创建的流程分析

  1. 加载 Person 类信息(Person.class),只会加载一次
  2. 在堆中分配空间(地址)
  3. 完成对象初始化
  • 3.1 默认初始化age=0 name=null
  • 3.2 显式初始化 age=90 name=null
  • 3.3 构造器的初始化 age=20,name=小倩
  1. 在对象在堆中的地址,返回给p(p是对象名,也可以理解成是对象的引用)

六、this 关键字(P246)

Java 虚拟机会给每个对象分配 this,代表当前对象。

this 的注意事项和使用细节:

(1) this 关键字可以用来访问本类的属性、方法、构造器。

(2) this 用于区分当前类的属性和局部变量。

(3) 访问成员方法的语法:【this. 方法名 ( 参数列表 );】。

(4) 访问构造器语法:【 this( 参数列表 );】 注意只能在构造器中使用(即只能在构造器中访问另外一个构造器, 必须放在第一条语句)。

(5) this 不能在类定义的外部使用,只能在类定义的方法中使用。

相关推荐
Cloud-Future几秒前
Spring cloud 中使用 OpenFeign:让 http 调用更优雅
java·spring cloud·openfeign·feign
zhendianluli4 分钟前
Python魔法函数(Magic Methods简介
开发语言·python
passion更好14 分钟前
【matlab】【python】爬虫实战
爬虫·算法·matlab
YANG-Live23 分钟前
数据列表组件-报表
开发语言·javascript
Synaric28 分钟前
Android与Java后端联调RSA加密的注意事项
android·java·开发语言
Tech Synapse1 小时前
java 如何暴露header给前端
java·开发语言·前端
海涛高软1 小时前
python一堆数字相近的分成一组
开发语言·python
酷酷学!!!1 小时前
C++第二弹 -- C++基础语法下(引用 内联函数 auto关键字 范围for 指针空值)
开发语言·c++
从后端到QT1 小时前
Qt 线程 QThread类详解
开发语言·qt
长亭外的少年1 小时前
Java 8 到 Java 22 新特性详解
java·开发语言