day06_类与对象

面向对象_day01

学习目标:

1. 面向过程与面向对象编程思想
2. 类的定义与对象的创建
3. 匿名对象
4. 类的成员详细讲解

视频教程:https://www.bilibili.com/video/BV1RF411N7LU?spm_id_from=333.999.0.0

一、面向过程与面向对象

面向过程与面向对象是两种编程思想;什么是编程思想呢?编程思想就是编程的思维方式;面向过程的编程思维方式与面向对象的思维方式是截然不同的。

面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

例如:解决吃饭问题,面向过程与面向对象实现思路如下:

  • 面向过程:考虑买什么菜,做什么饭,怎么做,做多少,然后吃饭,洗碗;重心在于如何完成这件事。

  • 面向对象:考虑谁会做饭,找到这个人;去饭店吃饭;重心在于调用谁完成这件事。

例如:解决洗衣服问题,面向过程与面向对象实现思路如下:

  • 面向过程:考虑用什么洗,凉水洗还是热水洗,洗完是甩干,还是晾晒;重心在于如何完成这件事。

  • 面向对象:考虑谁会洗衣服,找到这个人完成这件事;去干洗店洗衣服;重心在于调用谁完成这件事。

例如:解决出行问题,面向过程与面向对象实现思路如下:

  • 面向过程:考虑是开车还是步行还是骑行,考虑最佳路线,是否堵车;重心在于如何完成这件事。

  • 面向对象:告诉助理,我要去哪里,我要几点去,几点到,剩下的交给助理去做;重心在于调用谁完成这件事。

二、类与对象

上面讲了,面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

那么什么是类?什么是对象呢?

2.1 类与对象的关系

类是指一类事物的抽取,一类事物的概括。比如:人是一类事物。动物是一类事物。宠物狗是一类事物。对象:具体的实例。比如小红是对象。北京动物园的那只老虎。楼上的那条京巴。 类与对象的关系:类是一类事物的总结概括,对象是该类中具体实例,个体。

类(Class)和对象(Object)是面向对象的核心概念。

  • 类是对一类事物的描述,是抽象的、概念上的定义

  • 对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。

在这里插入图片描述

可以理解为: 类 类 = 抽象概念的人;象 对象 = 实实在在的某个人、悟空、八戒、沙僧

面向对象程序设计的重点是 类的设计

2.2 类的设计与对象的创建

类的设计, 其实就是类的成员的设计

2.2.1 类的成员

类是指一类事物的抽取,我们拿人这个类举例,我们可以抽取出人的体重 身高,性别等属性,还可以抽取出学习、吃饭、睡觉等行为。所以抽取类中的成员可以抽取出类的属性和行为。

定义类的格式如下

在这里插入图片描述

Java中用类class来描述事物也是如此。常见的类的成员有

  • 属 性:对应类中的成员变量
  • 行 为:对应类中的成员方法

定义类的具体语法:

在这里插入图片描述

其中:属性又叫成员变量,也叫字段,定义的方式和定义变量的方式一样,只是位置不同。

定义方法的语法:

在这里插入图片描述

其中 :

  • 修饰符:public, 缺省,private, protected等等
  • 返回值类型:
    • 没有返回值:void
    • 有返回值,声明出返回值的类型。与方法体中“ “return ” 返回值” 搭配使用。返回值类型可以是基本类型和引用类型。
  • 方法名 :属于标识符,命名时遵循标识符命名规则和规范,“ 见名知意”
  • 形参列表:可以包含零个,一个或多个 参数。多个参数时,中间用“, ”隔开
  • 返回值:方法在执行完毕后返还给调用它的程序的数据

示例1:定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。

参考答案:

/**
 * 定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。
 */
public class Person {
    //定义成员变量/字段/属性
    //姓名
    String name;
    //性别 0 代表男,1代表女
    int sex;
    //身高
    int height;
    //体重
    int weight;

    //定义方法
    //定义学习方法
    void study(){
        System.out.println("胖叔讲Java,一路相伴");
    }
    // 定义吃饭方法
    void eat(){
        System.out.println("吃的是北京烤鸭");
    }
    // 定义睡觉方法
    void sleep(){
        System.out.println("早睡早起身体好");
    }
}

2.2.2 对象的创建与使用

对象是类的具体实现实例;所以使用类必须根据类创建对象,然后调用对象的属性和方法。

创建对象的语法:

在这里插入图片描述

调用属性和方法的语法:

在这里插入图片描述

示例1:根据上边定义的Person类创建对象,调用属性和方法

/**
 * 定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。
 */
public class Person {
    //定义成员变量/字段/属性
    //姓名
    String name;
    //性别 0 代表男,1代表女
    int sex;
    //身高
    int height;
    //体重
    int weight;

    //定义方法
    //定义学习方法
    void study(){
        System.out.println("胖叔讲Java,一路相伴");
    }
    // 定义吃饭方法
    void eat(){
        System.out.println("吃的是北京烤鸭");
    }
    // 定义睡觉方法
    void sleep(){
        System.out.println("早睡早起身体好");
    }

    /*程序入口*/
    public static void main(String[] args) {
        //定义person对象
        Person person = new Person();
        //给属性赋值(调用属性)
        person.name="胖叔讲java";
        person.sex=0;
        person.height=168;
        person.weight=185;
        //查看属性(调用属性)
        System.out.println(person.name);
        System.out.println(person.sex);
        System.out.println(person.height);
        System.out.println(person.weight);
        //调用方法
        person.study();
        person.eat();
        person.sleep();
    }
}

问题分析?上面的学习方法存在问题,到底收获了哪些知识,没有返回结果;吃饭方法也存在问题,不可能天天吃烤鸭,方法体代码写死了,代码不灵活;接下来我们优化代码

参考答案:


/**
 * 定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。
 */
public class Person {
    //定义成员变量/字段/属性
    //姓名
    String name;
    //性别 0 代表男,1代表女
    int sex;
    //身高
    int height;
    //体重
    int weight;

    //定义方法
    //定义学习方法
    String study(){
        System.out.println("胖叔讲Java,一路相伴");
        return "类与对象";
    }
    // 定义吃饭方法
    void eat(String food){
        System.out.println("吃的是:"+food);
    }
    // 定义睡觉方法
    void sleep(){
        System.out.println("早睡早起身体好");
    }

    /*程序入口*/
    public static void main(String[] args) {
        //定义person对象
        Person person = new Person();
        person.eat("鸡蛋西红柿");
        person.eat("肉夹馍");
        String result = person.study();
        System.out.println(result);
    }
}

2.3 对象的生命周期

在学习完类的设计与对象的创建语法之后,接下来我们讲解对象在jvm中运行的生命周期;首先我们完成一个示例,让后根据示例讲解jvm内存运行过程。

示例1:定义User类,类中有属性:id、name、age、phone;方法有showMessage展示用户信息

参考代码:

/**
 定义User类,类中有属性:id、name、age、phone;方法有showMessage展示用户信息
 */
public class User {
    // 用户唯一标识
    int id;
    // 姓名
    String name;
    // 年龄
    int age;
    // 手机号
    String phone;

    //展示用户信息
    void showMessage(){
        System.out.println("id:"+id+",name:"+name+",age:"+age+",phone:"+phone);
    }

    /*程序入口*/
    public static void main(String[] args) {
        //创建对象
        User user = new User();
        //赋值
        user.id = 1;
        user.name = "小红";
        user.age = 18;
        user.phone = "138389438";
        //查看信息
        user.showMessage();

        //创建对象2
        User user2 = new User();
        //赋值
        user2.id = 2;
        user2.name = "小明";
        user2.age = 19;
        user2.phone = "138389538";
        //查看信息
        user2.showMessage();
    }
}

在讲解user对象jvm运行过程之前,我们先复习以下jvm的内存结构

在这里插入图片描述

每块内存负责的职责如下:

  1. Java虚拟机栈(Java Virtual Machine Stacks):描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame),栈帧中存储着局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,会对应一个栈帧在虚拟机栈中入栈到出栈的过程。与程序计数器一样,Java虚拟机栈也是线程私有的。

    局部变量和引用地址都是在栈内存中。

  2. 堆:此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。

  3. 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区存放的数据只有一份。

  4. 本地方法栈(Native Method Stack):与Java虚拟机栈作用很相似,它们的区别在于虚拟机栈为虚拟机执行Java方法(即字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。例如调用本地c/c++的方法。

  5. 程序计数器:程序计数器是记录当前线程所执行指令的行数。

user对象的生命周期如下

在这里插入图片描述

2.4 练习

练习1:定义一个钟表类,属性有秒针,分钟针,时针。方法有runSecond(),runMinute(),runHour()来描述指针的运行,要求最后完成钟表正常运行。

参考答案:

public class Clock {
    //1.定义秒针
    int second;
    //2.定义分钟针
    int minute;
    //4.定义小时针
    int hour;
    //5.定义运行秒针方法
    void runSecond(){
        second++;
        if(second==60) {
            second = 0;
            //minute++;
            runMinute();
        }
    }
    //6.定义分钟针运行
    void runMinute() {
        minute++;
        if(minute==60) {
            minute=0;
            //hour++;
            runHour();
        }
    }
    //7.定义小时
    void runHour() {
        hour++;
        if(hour==24) {
            hour = 0;
        }
    }
    public static void main(String[] args) {
        //1.创建钟表对象
        Clock clock = new Clock();
        //2.初始化值
        clock.second = 10;
        clock.minute = 51;
        clock.hour = 15;
        //3.打印时钟
        while(true) {
            //4.后面详细讲这个代码,这里只是测试,让程序听1000毫秒在执行
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("时钟:"+clock.hour+":"+clock.minute+":"+clock.second);
            clock.runSecond();
        }
    }
}

类的访问机制:

  • 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量和成员方法。
  • 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员

2.5 小节

  1. 类与对象的关系
  2. 类的定义与对象的创建
  3. 对象在jvm的运行过程
  4. 类的访问机制

三、匿名对象

3.1 什么是匿名对象

像这种new Person()不保存对象内存地址的对象叫匿名对象

示例:

/**
 * 匿名对象
 */
public class AnonymousObject {
    void study(){
        System.out.println("胖叔讲java");
    }

    /*程序入口*/
    public static void main(String[] args) {
        //匿名对象调用方法
        new AnonymousObject().study();
        // == 比较基本类型比较的是内容是否相等,比较引用类型比较的是地址是否相等
        // 匿名对象是两个对象,所以地址不相等
        System.out.println(new AnonymousObject()==new AnonymousObject());
    }
}

jvm运行过程

在这里插入图片描述

3.2 应用场景

匿名对象的应用场景

  • 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
  • 我们经常将匿名对象作为实参传递给一个方法调用

示例:

public class AnonymousObject2 {
    int id = 1;
    String name = "张三";
    int age = 18;
}
public class AnonymousObject2Use {

    public void useAnonymousObject2(AnonymousObject2 anonymousObject2){
        System.out.println("id:"+anonymousObject2.id+",name:"+anonymousObject2.name+",age:"+anonymousObject2.age);
    }

    public static void main(String[] args) {
        //匿名对象当作参数使用
        AnonymousObject2Use anonymousObject2Use = new AnonymousObject2Use();
        anonymousObject2Use.useAnonymousObject2(new AnonymousObject2());
    }
}

四、类的成员详解

上边讲了类与对象的基本使用,我们在类中定义类属性和方法;其实类的成员包含很多内容,如下所示:

在这里插入图片描述

本章节详细讲解成员变量、方法、构造方法、其他类的成员会在后面章节详细讲解。

4.1 成员变量

4.1.1 成员变量与局部变量的区别

在方法体外,类体内声明的变量称为成员变量。在方法体内部声明的变量称为局部变量。成员变量和局部变量的区别如下:

在这里插入图片描述

示例1:成员变量与局部变量区别

/**
 * 成员变量与局部变量的区别
 */
public class VariableDemo {
    //成员变量可以被private、public、static、final修饰,这些修饰符含义后面详细讲解
    private int id;
    private String name;

    /*程序入口*/
    public static void main(String[] args) {
        //局部变量只能用final修饰
        //private int i; //报错
        int j = 1;
        //局部变量必须初始化才能使用
        System.out.println(j);
        //创建对象,成员变量有默认值
        VariableDemo variableDemo = new VariableDemo();
        System.out.println(variableDemo.id);
        System.out.println(variableDemo.name);

    }
}

4.1.2 成员变量的默认值

当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了 基本数据类型之外的变量类型都是引用类型。具体默认值如下:

在这里插入图片描述

示例2:成员变量默认值

/**
 * 成员变量默认值
 */
public class VariableDemo2 {
    byte v1;
    short v2;
    int v3;
    long v4;
    float v5;
    double v6;
    char v7;
    boolean v8;

    /*程序入口*/
    public static void main(String[] args) {
        VariableDemo2 variableDemo2 = new VariableDemo2();
        System.out.println(variableDemo2.v1);
        System.out.println(variableDemo2.v2);
        System.out.println(variableDemo2.v3);
        System.out.println(variableDemo2.v4);
        System.out.println(variableDemo2.v5);
        System.out.println(variableDemo2.v6);
        System.out.println(variableDemo2.v7);
        System.out.println(variableDemo2.v8);
    }
}

4.2 方法

什么是方法?

  • 方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数或过程。
  • 将功能封装为方法的目的是,可以实现代码重用,简化代码
  • Java里的方法不能独立存在,所有的方法必须定义在类里

4.2.1 方法的基本应用

定义方法的语法如下:
在这里插入图片描述

其中 :

  • 修饰符:public, 缺省,private, protected等等
  • 返回值类型:
    • 没有返回值:void
    • 有返回值,声明出返回值的类型。与方法体中“ “return ” 返回值” 搭配使用;返回值类型可以是基本类型和引用类型。
  • 方法名 :属于标识符,命名时遵循标识符命名规则和规范,“ 见名知意”
  • 形参列表:可以包含零个,一个或多个 参数。多个参数时,中间用“, ”隔开
  • 返回值:方法在执行完毕后返还给调用它的程序的数据。

方法 的分类:按照是否有形参及返回值

在这里插入图片描述

注意:无返回的方法也可以使用return关键字,代表结束方法的执行。具体使用参照下面示例:

示例1:方法的分类演示

/**
 * 方法定义的分类
 */
public class MethodDemo {
    // 无参数,无返回值方法
    void method1(){
        System.out.println("胖叔讲java,一路相伴");
    }
    // 有参数,无返回值方法
    void method2(String arg){
        System.out.println("有参数无返回值方法,参数是:"+arg);
    }
    // 无参数,有返回值方法
    String method3(){
        return "结果"; //返回的内容必须和返回类型保持一致
    }
    // 有参数,有返回值方法
    String method4(String arg){
        System.out.println("有参数有返回值方法,参数是:"+arg);
        return "结果2";
    }

    public static void main(String[] args) {
        //创建对象
        MethodDemo methodDemo = new MethodDemo();
        //调用方法
        methodDemo.method1();
        methodDemo.method2("小红");
        String result = methodDemo.method3();
        System.out.println(result);
        String result2 = methodDemo.method4("小明");
        System.out.println(result2);
    }

}

示例2:无返回值方法使用return关键字

/**
 * 无返回值方法使用return关键字
 */
public class MethodDemo2 {
    /**
     * 需求:从1打印到指定目标数
     *
     * return 结束该方法运行。 返回值类型是void return 后面不加值,直接写分号。
     */
    public void method1(int target){
        int i = 1;
        while(true){
            System.out.println(i);
            if(i==target){
                return;
            }
            i++;

        }
    }

    public static void main(String[] args) {
        MethodDemo2 methodDemo2 = new MethodDemo2();
        methodDemo2.method1(1100);
    }
}

小结:

  • 方法被调用一次,就会执行一次
  • 没有具体返回值的情况,返回值类型用关键字void表示,那么方法体中可以不必使用return语句。如果使用,仅用来结束方法。
  • 定义方法时,方法的结果应该返回给调用者,交由调用者处理。
  • 方法中只能调用方法或属性,不可以在方法内部定义方法。

4.2.2 方法的重载

重载的概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

重载的特点:与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。

示例:返回两个数字/三个数字的和

package top.psjj.demo1;

/**
 * 方法的重载,求两个数的和
 */
public class OverloadMethod {
    int sum(int a,int b){
        return a+b;
    }
    int sum(int a,int b,int c){
        return a+b+c;
    }
    double sum(double a,double b){
        return a+b;
    }
    double sum(double a,double b ,double c){
        return a+b+c;
    }

    public static void main(String[] args) {
        //创建对象
        OverloadMethod overloadMethod = new OverloadMethod();
        //调用方法:方法重载,优点:感觉上像是调用一个方法实现了多个功能,实际还是调用了多个方法。
        int result = overloadMethod.sum(1, 2);
        System.out.println(result);
        double result2 = overloadMethod.sum(1.1, 2.2);
        System.out.println(result2);
        int result3 = overloadMethod.sum(1, 2, 3);
        System.out.println(result3);
        double result4 = overloadMethod.sum(1.1,2.2,3.3);
        System.out.println(result4);
    }
}

练习题1:编写程序,定义三个重载方法并调用。方法名为mol。三个方法分别接收一个int参数、两个int参数、一个字符串参数。分别 执行平方运算并输出结果,相乘并输出结果,输出字符串信息。 在主类的main ()方法中分别用参数区别调用三个方法。

练习题2:定义三个重载方法max(),第一个方法求两个int值中的最大值,第二个方 法求两个double值中的最大值,第三个方法求三个double值中的最大值, 并分别调用三个方法。

4.2.3 方法的可变参数

什么是可变参数?

JavaSE 5.0 中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参

可变参数语法:

  • 声明格式:**方法名(参数的类型名 …参数名) **
  • 可变参数:传递实参的个数是可变的,可以是0个,1个 ,2个 …
  • 可变个数形参的方法与同名的方法之间,彼此构成重载
  • 可变参数方法的使用与方法参数部分使用数组是一致的
  • 方法的参数部分有可变形参,需要放在形参声明的最后
  • 在一个方法的形参位置,最多只能声明一个可变个数形参

示例:通过可变参数计算n个数的最大值,最小值。

/**
 * 可变参数:通过可变参数计算n个数的最大值,最小值。
 */
public class NumberUtils {
    //args 代表参数
    void printMaxAndMin(double... args) {
        //1.可变参数的数据全部存放在args的数组中
        double min;
        double max;
        if(args.length>0) {
            //2.如果传入参数就初始化最大值和最小值
            min = args[0];
            max = args[0];
            for(int i=0;i<args.length;i++) {
                if(min>args[i]) {
                    min = args[i];
                }
                if(max<args[i]) {
                    max = args[i];
                }
            }
            //3.打印最大值和最小值
            System.out.println("最大值:"+max);
            System.out.println("最小值:"+min);
        } else {
            System.out.println("没有传递参数无法计算最大值和最小值");
        }

    }
    public static void main(String[] args) {
        NumberUtils numberUtils = new NumberUtils();
        numberUtils.printMaxAndMin(-1.1,2.2,3.3,9.3);
        numberUtils.printMaxAndMin();
    }
}

示例2:

/**
 * 求n个整数的和,至少传入一个参数
 */
public class SumDemo {
    //1.只可以有一个可变参数而且必须在最后
    int sum(int number,int... args) {
        int sum = 0;
        sum+=number;
        if(args.length>0) {
            for(int i=0;i<args.length;i++) {
                sum+=args[i];
            }
        }
        return sum;
    }
    public static void main(String[] args) {
        SumDemo sumDemo = new SumDemo();
        int result = sumDemo.sum(1,2,3);
        System.out.println(result);
    }
}

练习题:通过可变参数计算n个数的最大值,最小值,和,平均值。

4.2.4 方法的值的传递机制

Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。

  • 形参是基本数据和String类型:将实参基本数据类型变量的“数据值”传递给形参
  • 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参

示例1:测试方法参数传递是传递实际参数的副本

public class MethodDemo {
    //Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
    void method1(int i){
        //改变参数值
        i++;
        System.out.println(i);
    }
    //Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
    void method2(User user){
        //改变参数的地址
        user = new User();
        //给新地址重新赋值
        user.id = 2;
        user.name = "李四";
        user.show();
    }

    public static void main(String[] args) {
        //创建对象
        MethodDemo methodDemo = new MethodDemo();
        //将变量i传入method1方法中,是将i的副本传入方法中i的值不受影响
        int i = 5;
        methodDemo.method1(i);
        System.out.println(i);
        //将user对象传入method2方法中,是将user对象的内存地址副本传入方法中
        User user = new User();
        user.id = 1;
        user.name = "张三";
        // method2对传入的副本的地址更改了,对原来地址内容没有影响
        methodDemo.method2(user);
        user.show();

    }
}
class User {
    int id;
    String name;
    void show(){
        System.out.println("id:"+id+",name:"+name);
    }
}

示例2:当实际参数是基本类型和引用类型的区别

/**
 * 值传递,基本类型和引用类型的区别
 */
public class MethodDemo2 {
    //传递基本类型传递的是值的副本,方法体内改变参数的值不会影响外部变量
    void method1(int i){
        //改变参数值
        i++;
        System.out.println(i);
    }
    //传递引用类型传递的是值的副本,但是值的副本和外部变量却指向堆内存同一块内存地址
    //所以改变改变user地址的内容,外部的对象的属性也就变了
    void method2(User user){
        user.id = 2;
        user.name = "李四";
        user.show();
    }

    public static void main(String[] args) {
        MethodDemo2 methodDemo2 = new MethodDemo2();
        //传递基本类型传递的是值的副本,方法体内改变参数的值不会影响外部变量
        int i = 1;
        methodDemo2.method1(i);
        System.out.println(i);
        //传递引用类型传递的是值的副本,但是值的副本和外部变量却指向堆内存同一块内存地址
        //所以改变改变user地址的内容,外部的对象的属性也就变了
        User user = new User();
        user.id = 1;
        user.name = "张三";
        methodDemo2.method2(user);
        user.show();

    }
 

}
class User {
    int id;
    String name;
    void show(){
        System.out.println("id:"+id+",name:"+name);
    }
}

练习题:定义一个数组工具类数组反转,数组排序。

小结:java参数传递机制只有一种,值传递,既将实参的复制品的值传入参数;如果是基本类型和String传递的数数据值,对外部变量没有影响;如果传递是引用类I型那个,传递的是地址值,可能堆外部变量有影响。

4.2.5 方法的递归

什么是递归?递归就是方法本身调用方法本身。

示例1:用方法打印1-100的数;

public class RecursiveDemo  {
	//1.用递归的方式:从1打印到100
	void print(int i) {
		if(i<=100) { 
			System.out.println(i);
			i++;
			print(i);
		}
	}
	public static void main(String[] args) {
		RecursiveDemo recursiveDemo = new RecursiveDemo();
		recursiveDemo.print(1);
	}
}

示例2:递归必须指定程序出口,否者报错:StackOverflowError 栈溢出错误

public class RecursiveDemo2 {
    //递归调用没有指定方法出口,无限调用
    void print(int i) {
        System.out.println(i);
        i++;
        print(i);
    }
    public static void main(String[] args) {
        RecursiveDemo2 recursiveDemo2 = new RecursiveDemo2();
        recursiveDemo2.print(1);
    }
}

练习题1:请用递归计算出1-100的和

练习题2:请用Java写出递归求阶乘(n!)的算法

4.3 构造方法

4.3.1 构造方法的基本使用

在java类中定义的构造方法是用来创建对象的,它的定义语法如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G7N3U0eZ-1658146485325)(assets/14.png)]

示例1:在User类型中定义构造方法并使用

public class User {
    int id;
    String name;
    int age;
    //定义构造方法
    User(int userId,String userName,int userAge){
        id = userId;
        name = userName;
        age = userAge;
    }

    public static void main(String[] args) {
        //使用构造方法创建对象
        User user = new User(1,"张三",21);
        //查看user信息
        System.out.println("id:"+user.id+",name:"+user.name+",age:"+user.age);
    }
}

4.3.2 构造方法的重载

构造方法是一种特殊的方法,也可以进行方法的重载;

示例1:

public class User {
    int id;
    String name;
    int age;
    //定义构造方法
    User(int userId,String userName,int userAge){
        id = userId;
        name = userName;
        age = userAge;
    }
    //构造方法的重载
    User(int userId,String userName){
        id = userId;
        name = userName;
    }
    User(){

    }

    public static void main(String[] args) {
        //使用构造方法创建对象
        User user = new User(1,"张三",21);
        //查看user信息
        System.out.println("id:"+user.id+",name:"+user.name+",age:"+user.age);

        //创建对象,查看用户信息
        User user2 = new User(2,"李四");
        System.out.println("id:"+user2.id+",name:"+user2.name+",age:"+user2.age);

        //创建对象,查看用户信息
        User user3 = new User();
        System.out.println("id:"+user3.id+",name:"+user3.name+",age:"+user3.age);
    }
}

4.3.3 默认构造方法

在一个类中如果没定义构造方法,系统会默认定义一个无参数的构造方法;在一个类中如果定义了构造方法,系统将不会默认定义构造方法

示例1:

public class Person {
    int id;
    String name;

    /**
     * 当类中没有定义构造方法时,系统会默认定义如下构造方法
     */
    /*public Person(){

    }*/
    /**
     * 当类中定义了构造方法时,系统不会默认定义构造方法
     */
    public Person(int personId,String personName){
        id = personId;
        name = personName;
    }
    public static void main(String[] args) {
        //创建对象
        Person person = new Person();

    }
}

4.3.4 构造方法注意事项

使用构造方法时需要注意以下几点:

  • 它具有与类相同的名称
  • 它不声明返回值类型。(与声明为void不同)
  • 不能被static、final、synchronized、abstract 等修饰,不能有 return语句返回值
  • 构造方法是一种特殊的方法,支持重载

4.4 小结

  1. 成员变量与局部变量的区别

  2. 成员变量的默认值

  3. 方法的重载

  4. 可变参数

  5. 方法的值传递机制

  6. 方法的递归

  7. 构造方法

五、this关键字

5.1 this关键字概述

在Java中,this关键字比较难理解,它的作用和其词义很接近。单词含义是这个 的意思 。this关键字可以使用在方法和构造方法体内。

  • 它在方法内部使用,即这个方法所属对象的引用;
  • 它在构造器内部使用,表示该构造器正在初始化的对象。
  • this 可以调用类的属性、方法和构造器

5.2 this 入门案例

我们先看如下案例,发现构造方法的参数名不能和成员变量名一样,否者无法初始化;示例代码如下:

public class User {
    int id;
    String name;
    int age;

    /**
     *java 使用变量有就近原则 从当前最近{} 范围查找变量,找到就是使用,找不到才去成员变量找
     * 所以,这里面的id=id name = name age=age其实是参数给参数自己赋值,根本没有调用成员变量
     */
   /* User(int id,String name,int age){
        id = id;
        name = name;
        age = age;
    }*/
    // this关键字,表示该构造方法正在初始化的对象
    User(int id,String name,int age){
        this.id = id;
        this.name = name;
        this.age = age;
    }
    void show(){
        System.out.println("id:"+id+",name:"+name+",age:"+age);
    }
    /*程序入口*/
    public static void main(String[] args) {
        User user = new User(1,"张三",18);
        user.show();
        User user2 = new User(2,"李四",19);
        user2.show();

    }
}

5.3 this关键字应用场景

this关键字可以使用在方法和构造方法体内。

  • 它在方法内部使用,即这个方法所属对象的引用;
  • 它在构造器内部使用,表示该构造器正在初始化的对象。
  • this 可以调用类的属性、方法和构造器

示例1:this在构造方法中应用

public class User {
    int id;
    String name;
    int sex;
    User(int id,String name,int sex){
        //this代表当前正在初始化的user对象,
        // 含义是user.id = id; user.name = name user.sex = sex;
        //但此时只能通过this引用正在初始化的对象。
        this.id = id;
        this.name = name;
        this.sex = sex;
    }
    User(int id,String name){
        // this(参数列表)调用的是构造方法 调用的上面的构造方法
        this(id,name,0);
        // 代表当前正在初始化的user对象 this.show()等价于user.show(),但此时只能通过this引用正在初始化的对象。
        this.show();
    }
    void show(){
        System.out.println("id:"+id+",name:"+name+",sex:"+sex);
    }

    /*程序入口*/
    public static void main(String[] args) {
        User user = new User(1,"张三");

    }
}

示例2:this在普通方法中应用

public class User {
    int id;
    String name;
    int sex;

    User(int id, String name, int sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }
    void method1(){
        System.out.println("方法");
    }
    void show(){
        //在方法中不可以调用构造器,不能使用this(1,"张三",1);
        //当前方法所属对象调用method1()
        this.method1();
        //当前方法所属对象 id name sex 属性
        System.out.println("id:"+this.id+",name:"+this.name+",sex:"+this.sex);
    }

}

5.4 小结

this可以使用在构造器和方法中,在构造器中可以使用

  • this.属性
  • this.方法
  • this(构造方法参数列表)

在普通方法中可以使用

  • this.属性
  • this.方法

六、总结

  1. 类与对象
  2. 成员变量
  3. 成员方法
  4. 方法重载
  5. 可变参数
  6. 值传递
  7. 递归
  8. 构造方法
  9. this关键字应用
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值