• Java类和对象:类是对象的模板,对象是类的实例化


    在这里插入图片描述

    • 👑专栏内容:Java
    • ⛪个人主页:子夜的星的主页
    • 💕座右铭:前路未远,步履不停


    嘿!在开始之前,我们先通过一个小栗子认识一下什么是面向对象吧!

    面向过程的编程中,你饿了,想吃饭就需要你自己亲自执行做饭的每个步骤,例如准备食材、点火、烹饪、摆盘等。每次吃饭的时候都必须要做一遍这些工作,你掌握了做饭的所有的细节和步骤。

    而在面向对象编程中,你找了个“厨师”对象来帮你做饭。这个“厨师”对象负责处理所有与做饭相关的事务。你只需告诉这个对象你想吃什么,它会负责准备食材、烹饪、摆盘等过程,你不需要了解到底如何做饭。

    嘿嘿!神奇吧~下面让我们来一起学习面向对象。
    在这里插入图片描述

    一、类

    1、类的定义

    在面向对象编程中,类(Class)是一种定义对象的模板类描述了一个对象具有的属性和方法,它是创建对象的基础,所有具有相同属性和方法的对象都属于同一个类。类通常包含数据成员(属性)和函数成员(方法)。属性是类中的变量,描述了对象的基本信息,而方法是类中的函数,用于实现对象的各种行为。

    Java中定义类时需要用到class关键字,具体语法如下:

    // 创建类
    class ClassName{
        field; // 字段(属性) 或者 成员变量(定义在类中,但是在方法的外面)
        method; // 行为 或者 成员方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • class是Java语言中用于定义类的关键字
    • ClassName是要定义的类的名称,命名规则和Java语言的标识符命名规则相同,采用大驼峰命名法
    • { }中是类的主体,包含了类的所有属性和方法
    • 类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法

    在这里插入图片描述
    image-20230706144649292

    举个例子吧。我们现在要创建一个厨师类时,我们可以定义该类的属性包括厨师的姓名、特长菜系,方法有制作拿手菜。

    class Chef {
        // 属性
        private String name;
        private String cuisineSpecialty;
        
        // 方法:制作拿手菜
        public void cookSpecialtyDish() {
            System.out.println(name + "正在制作拿手菜:" + cuisineSpecialty);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意事项:

    • 一般一个文件当中只定义一个类

    • main方法所在的类一般要使用public修饰(注意:Eclipse默认会在public修饰的类中找main方法)

    • public修饰的类必须要和文件名相同

    2、类的实例化

    类的实例化是指根据一个类创建一个具体的对象,这个对象就是该类的一个实例。在面向对象编程中,类是一种抽象的概念,而对象则是具体的实体。通过类的实例化,我们可以创建多个不同的对象,每个对象都有自己独立的属性和方法。

    在Java中,我们通过使用new关键字来创建一个类的实例,例如:

    Chef myChef = new Chef();
    
    • 1

    上面的代码就创建了一个Chef类的实例,并将其赋给一个变量myChef。通过该变量,我们可以访问这个具体的Chef对象的属性和方法,这个myChef变量是一个引用变量,它包含了指向实际Chef对象的内存地址。

    在这里插入图片描述

    在Java中,对象是存储在堆内存中的,而变量是存储在栈内存中的。当使用new关键字创建一个对象时,Java会在堆内存中分配一块新的内存空间,并返回该对象的引用。这个引用可以被存储在一个变量中,以便在程序中引用该对象。

    上面的这段Java代码,其实就是创建了一个名为myChef的引用变量,并使用new关键字在堆内存中创建了一个新的Chef对象,然后将该对象的引用赋值给了myChef变量。

    注意事项

    • new 关键字用于创建一个对象的实例

    • 使用 . 来访问对象中的属性和方法

    • 同一个类可以创建对个实例

    在这里插入图片描述

    3、类和对象具体说明

    类是对象的模板,对象是类的实例化

    类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员。

    类是一种自定义的类型,可以用来定义变量。一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量类定义了对象的结构和行为,而对象是类的一个具体实例,具有自己独立的属性和方法。

    打个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间。

    image-20230505212813507

    4、类的设计技巧

    下面传授给你一些类的设计技巧。

    图片描述

    • 一定要保证数据私有

    • 一定要对数据初始化

    Java不对局部变量进行初始化,但会对对象的实力域进行初始化。最好不依赖系统的默认值。

    • 不要在类中使用过多的基本类型

    用其他的类代替多个相关的基本类型的使用。这样会让类更加易于理解且易于修改。

    • 不是所有的域都需要独立的域访问器或者域更改器
    • 将职责过多的类进行分解
    • 类名和方法名要体现它们的职责
    • 优先使用不可变的类

    二、this引用

    1、为什么要有this引用

    举个例子,就能明白了。猜一下,下面这段代码的运行结果是什么?

    public class Date {
        public int year;
        public int month;
        public int day;
        public void setDay(int year, int month, int day){
            year = year;
            month = month;
            day = day;
        }
        public void printDate(){
            System.out.println(year + "/" + month + "/" + day);
        }
        public static void main(String[] args) {
            // 构造三个日期类型的对象 d1 d2 d3
            Date d1 = new Date();
            Date d2 = new Date();
            Date d3 = new Date();
            // 对d1,d2,d3的日期设置
            d1.setDay(2020,9,15);
            d2.setDay(2020,9,16);
            d3.setDay(2020,9,17);
            // 打印日期中的内容
            d1.printDate();
            d2.printDate();
            d3.printDate();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    在这里插入图片描述
    为什么会这样???上面的代码定义了一个日期类,然后main方法中创建了三个对象,并通过Date类中的成员方法对对象进行设置和打印,代码整体逻辑非常简单,没有任何问题。但是细思之下有以下两个疑问:

    1. 形参名不小心与成员变量名相同
    public void setDay(int year, int month, int day){
    	year = year;
    	month = month;
    	day = day;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    那函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?成员变量参数?

    1. 三个对象都在调用setDateprintDate函数,但是这两个函数中没有任何有关对象的说明,setDateprintDate函数如何知道打印的是那个对象的数据呢?
      image-20230505213724485

    2、什么是this引用

    this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

    this引用的作用就是区分成员变量和局部变量:当一个方法的参数名和对象的成员变量名相同时,使用this关键字可以指明是使用对象的成员变量,还是方法的局部变量。

        public int year;
        public int month;
        public int day;
        public void setDay(int year, int month, int day){
            this.year = year;
            this.month = month;
            this.day = day;
        }
        public void printDate(){
            System.out.println(year + "/" + month + "/" + day);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注意:this引用的是调用成员方法的对象。对象是类的实例,每个对象都有自己的一组属性和方法。当对象调用自己的成员方法时,this 关键字用于引用调用该方法的当前对象,即调用该方法的对象实例。

    public static void main(String[] args) {
        Date d = new Date();
        d.setDay(2020,9,15);
        d.printDate();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    image-20230505213912951

    3、 this引用的特性

    1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
    2. this只能在"成员方法"中使用
    3. 在成员方法中,this只能引用当前对象,不能再引用其他对象
    4. this是成员方法第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收。

    在代码层面来简单演示—>注意:下图右侧中的Date类也是可以通过编译的:

    image-20230505214024408
    在这里插入图片描述

    三、对象构造及初始化

    1、如何初始化对象

    public static void main(String[] args) {
        Date d = new Date();
        d.printDate();
        d.setDate(2021,6,9);
        d.printDate();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过上面的代码我们可以知道,设置一个SetDate方法就可以轻松的将具体的日期设置到对象中。

    但是通过上述例子我们发现两个问题:

    1. 每次对象创建好后调用SetDate方法设置具体日期,比较麻烦,那对象该如何初始化?

    为了避免这种问题,我们可以在对象的构造方法中设置初始值,这样对象一旦创建,就会立即拥有完整的状态。在 Java 中,我们可以使用构造方法来完成对象的初始化工作。

    1. 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?

    在Java中,局部变量必须在使用之前先进行初始化,否则编译器会报错。这是因为局部变量的生命周期只在其所在的方法内部,而且局部变量的值是不可靠的,如果没有初始化就使用它,可能会导致程序出现异常。

    而类成员变量(字段)则不同,它们在类的实例化过程中被分配内存空间并赋予默认值,因此即使没有给字段初始化也可以使用。具体来说,Java会为不同类型的字段设置默认值:

    数据类型默认值
    byte0
    short0
    int0
    long0L
    float0.0f
    double0.0
    booleanfalse
    char‘\u0000’ (null字符)
    引用类型(类、接口、数组等)null

    当然,如果我们需要的话,我们也可以在字段声明的时候给它们赋初值。这样做可以保证程序的健壮性,避免不必要的错误。

    2、什么是构造方法

    构造方法是一种特殊的方法,用于在创建对象时执行必要的初始化操作。当你通过关键字 new 来实例化(创建)一个类的对象时,构造方法会自动调用。

    public class Date {
        public int year; // 成员变量:年
        public int month; // 成员变量:月
        public int day; // 成员变量:日
    
        // 构造方法:
        // 名字与类名相同,没有返回值类型,设置为void也不行
        // 一般情况下使用public修饰
        // 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
        public Date(int year, int month, int day){
            this.year = year; // 使用this关键字访问对象的成员变量,并为其赋初值
            this.month = month;
            this.day = day;
            System.out.println("Date(int,int,int)方法被调用了"); // 构造方法执行完毕,输出消息
        }
    
        // 普通方法:打印当前日期的字符串表示
        public void printDate(){
            System.out.println(year + "-" + month + "-" + day);
        }
    
        public static void main(String[] args) {
            // 此处创建了一个Date类型的对象,并没有显式调用构造方法
            Date d = new Date(2021,6,9); // 调用构造方法,传入三个整数参数
            // 上述代码相当于调用了以下语句:
            // Date d = new Date(); // 创建一个空对象
            // d.year = 2021; // 给成员变量赋值
            // d.month = 6;
            // d.day = 9;
            // 但是,使用构造方法的方式更加简洁和安全,可以保证对象的状态正确初始化
            d.printDate(); // 调用对象的方法,输出对象的状态
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    图片描述

    为什么没有写构造函数进行初始化,代码也没有报错呢?

    在Java中,如果你的构造方法一个都没写,编译器则会为你自动生成一个默认的无参构造方法。这个默认构造方法会接受所有类型的参数,并将它们设置为默认值(例如,int类型的参数会被设置为0,布尔类型的参数会被设置为false等)。

    3、构造方法的特性

    • 名字必须与类名相同
    • 没有返回值类型,设置为void也不行
    • 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
    • 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)

    在Java中,重载是指在同一个类中,有多个方法具有相同的名称但参数列表不同的情况。

    每个构造方法必须具有唯一的参数列表,因此当我们需要创建多个具有不同参数的构造方法时,就需要进行重载。重载的构造方法可以使用不同的参数数量、类型和顺序,从而在实例化对象时,根据传递的参数来调用不同的构造方法。

    public class Date {
        public int year; // 年份
        public int month; // 月份
        public int day; // 日期
    
        // 无参构造方法,将日期初始化为1900年1月1日
        public Date(){
            this.year = 1900;
            this.month = 1;
            this.day = 1;
        }
    
        // 带有三个参数的构造方法,根据参数设置日期
        public Date(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
        }
    
        // 打印日期的方法
        public void printDate(){
            System.out.println(year + "-" + month + "-" + day);
        }
    
        public static void main(String[] args) {
            Date d = new Date(); // 创建一个日期对象,使用无参构造方法
            d.printDate(); // 调用打印日期的方法
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载。

    在构造方法中,可以通过this调用其他构造方法来简化代码:

    public class Date {
        public int year;
        public int month;
        public int day;
        // 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
        // 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
        // 但是this(1900,1,1);必须是构造方法中第一条语句
        public Date(){
            //System.out.println(year); 注释取消掉,编译会失败
            this(1900, 1, 1);
            //this.year = 1900;
            //this.month = 1;
            //this.day = 1;
        }
        // 带有三个参数的构造方法
        public Date(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    图片描述

    每一个构造方法都需要我们自己写嘛?

    我们可以自己写,也可以用 idea 生成构造方法。
    在这里插入图片描述


    类和对象就说到这里了,相信大家对于类和对象的概念已经有了更清晰的认识。我们下次再见!

    图片描述

  • 相关阅读:
    各种注意力机制,Attention、MLP、ReP等系列的PyTorch实现,含核心代码
    springBoot 过滤器去除请求参数前后空格(附源码)
    Go For Web:踏入Web大门的第一步——Web 的工作方式
    Python 多线程 DNS 搜索性能优化
    Vue中的方法和事件绑定
    突破编程_C++_面试(STL 编程 vector )
    vue3中实现响应式原理Proxy 和 Reflect。代码演示
    Ubuntu20.04+GTX1060+显卡驱动+CUDA11.8+cuDNN8.5.0
    记录一次项目中的《Recyclerview的优化》
    基于若依(SpringBoot前后分离版-vue)的WebSocket消息推送实现
  • 原文地址:https://blog.csdn.net/weixin_61084441/article/details/133758901