【Java SE语法篇】7.面向对象——类和对象

在这里插入图片描述

📚博客主页:爱敲代码的小杨.

✨专栏:《Java SE语法》

❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️

文章目录

  • 1. 面向对象程序设计概述
    • 1.1 类
    • 1.2 对象
    • 1.3 类之间的关系
  • 2. 类的定义和使用
    • 2.1 简单认识类
    • 2.2 类的定义格式
    • 2.3 自定义类
      • 2.3.1 定义一个狗类
  • 3.类的实例化
    • 3.1 什么是实例化
    • 3.2 类和对象的说明
  • 4. this 引用
    • 4.1 为什么要使用this引用
    • 4.2 什么是this引用
    • 4.3 this引用的特性
  • 5. 对象的构造及初始化
    • 5.1 如何初始化对象
    • 5.2 构造方法
      • 5.2.1 概念
      • 5.2.2 特性
    • 5.3 默认初始化
    • 5.4 就地初始化

1. 面向对象程序设计概述

面向对象程序设计(object-oriented programming,OOP),是当今主流的程序设计范畴,它取代了20世纪70年代的”结构化“或过程式编程技术。

面向对象的程序是由对象组成的,每个对象包含对用户公开的特点功能部分和隐藏的实现部分。

image-20231111184011676

1.1 类

(class)是构造对象的模板或蓝图。由类构造(construct)对象的过程称为类的实例(instance)。

封装(encapsulation,有时称为数据隐藏)是处理对象的一个重要概念。封装就是将数据和行为组合在一个包中,并对对象的使用者隐藏具体的实现方式。对象的数据称为实例字段(instance field),操作数据的过程称为方法(method)。

实现封装的关键在于,绝对不能让类中的方法直接访问其他类的实例字段。程序只能通过对象的方法与对象数据进行交互。封装给对象赋予了“黑盒”特征,这是提高重用性和可靠性的关键。这意味着一个类可以完全改变存储数据的方式,只要仍旧使用同样的方法操作数据,其他对象就不会知道也不用关心这个类所发生的变化。

1.2 对象

要想使用OOP,一定要清楚对象的三个主要特性:

  • 对象的行为(behavior)——可以对对象完成哪些操作,或者可以对对象应用哪些方法?
  • 对象的状态(state)—当调用那些方法时,对象会如何响应?
  • 对象的标识(identity)——如何区分具有相同行为与状态的不同对象?

同一个类的所有对象实例,由于支持相同的行为而具有家族式的相似性。对象的行为是可调用的方法来定义的。

1.3 类之间的关系

在类之间,最常见的关系有:

  • 依赖(uses-a);
  • 聚合(has-a);
  • 继承(is-a)。

​ 依赖(dependence),即“uses-a”关系,是一种最明显、最常见的关系。如果一个类的方法使用或操纵另一个类的对象,我们就说一个类依赖于另一个类。

​ 聚合(aggregation),即“has-a”关系,很容易理解,因为这种关系很具体。包含关系意味着类A的对象包含类B的对象。

​ 继承(inheritance),即“is-a”关系,表示一个更特殊的类与一个更一般类之间的关系。

2. 类的定义和使用

面向对象程序设计关注的是对象,而对象是现实生活中的实体。

2.1 简单认识类

类是用来对一个实体(对象)来进行描述,主要描述该实体(对象)具有哪些属性,哪些功能,描述完成后计算机就可以识别了。

2.2 类的定义格式

java中定义 类需要使用class关键字,具体语法如下:

class ClassName{
    field;// 字段 或 成员变量
    method;// 方法 或 成员方法
}

class为定义类的关键字,ClassName为类的名字,{}中为类的主体。

类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类**成员变量**。方法主要说明类具有哪些功能,称为类的成员方法

2.3 自定义类

2.3.1 定义一个狗类

class Dog {
    // 狗的属性
    public String name;// 狗的名字
    public String color;// 狗的颜色

    // 狗的行为
    public void barks() {
        System.out.println(name + "在旺旺叫");
    }

    public void wag() {
        System.out.println(name + "在摇尾巴");
    }
}

注意事项:

  1. 一般一个文件当中只定义一个类。
  2. main方法所在的类一般要使用public修饰。
  3. public修饰的类必须要和文件相同。

3.类的实例化

3.1 什么是实例化

定义一个类,就相当于在计算机中定义了一种新的类型,与intdouble类似,只不过intdoublejava语言自带的内置类型,而类是用户自定义了一个新的类型,比如上述的Dog类。它就是类(一种新定义的类型)有了这些自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。

用类类型创建对象的过程,称为类的实例化,在java采用new关键字,配合类名来实例化对象。

image-20231119213926920

public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        dog1.name = "大黄";
        dog1.color = "黄色";
        dog1.barks();
        dog1.wag();

        Dog dog2 = new Dog();
        dog2.name = "哈士奇";
        dog2.color = "白黑色";
        dog2.barks();
        dog2.wag();
    }
}

// 运行结果:
大黄在旺旺叫
大黄在摇尾巴
哈士奇在旺旺叫
哈士奇在摇尾巴

注意事项

  1. new 关键字用于创建一个对象的实例。
  2. 使用.来访问对象中属性和方法。
  3. 同一个类可以创建多个实例。

3.2 类和对象的说明

  1. 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员。
  2. 类是一种自定义的类型,可以用来定义常量
  3. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量
  4. 做个比方,类的实例化出对象就像现实中使用建筑设计圈造出房子,类就是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化的对象才能实际存储数据,占用物理空间。

4. this 引用

4.1 为什么要使用this引用

先看一个日期类的例子:

class Date{
    public int year;
    public int month;
    public int day;

    public void setDate(int y, int m, int d){
        year = y;
        month = m;
        day = d;
    }

    public void printDate(){
        System.out.println(year + "/" + month + "/" + day);
    }
}

public class Test2 {
    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();
    }
}

以上代码定义了一个日期类,然后main方法中创建了三个对象,并通过Date类中的成员方法对对象进行设置和打
印,代码整体逻辑非常简单,没有任何问题。

但是细思之下有以下两个疑问:

  1. 形参名不小心与成员变量名相同

    public void setData(int year, int month, int day){
            year = year;
            month = month;
            day = day;
    }
    

    那函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?成员变量参数?估计
    自己都搞不清楚了。

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

image-20231119223242915

4.2 什么是this引用

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

public void setData(int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;
}

注意:this引用的是调用成员方法的对象

public class Test {
    public static void main(String[] args) {
        Date d = new Date();
        d.setData(2020,9,15);
        d.printDate();
    }
}

image-20231119224228827

4.3 this引用的特性

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

5. 对象的构造及初始化

5.1 如何初始化对象

java方法内部定义一个局部变量,必须初始化,否则就会编译失败。

image-20231120090702710

要上诉代码编译成功,只需要是在使用a之前,给a设置一个初始值。如果是对象:

public class Test {
    public static void main(String[] args) {
        Date d = new Date();
        d.setData(2020,9,15);
        d.printDate();
    }
}
// 代码正常通过编译

需要调用之前写的setDate方法才可以将具体的日期设置到对象中。通过上述例子发现两个问题:

  1. 每次对象创建好后调用setDate方法设置具体日期,比较麻烦,那对象该如何初始化?
  2. 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?

5.2 构造方法

5.2.1 概念

构造方法(也称为构造器)是一种特殊的成员方法,名字必须与类名相同,在创建对象时,编译器自动调用并且在整个对象的生命周期内调用一次

class Date{
    public int year;
    public int month;
    public int day;

    // 构造方法
    public Date(int year, int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;
        System.out.println("Date(int year, int month, int day)被调用了");
    }

    public void printDate(){
        System.out.println(this.year + "/" +this.month + "/" + this.day);
    }
}

public class Test {
    public static void main(String[] args) {
        Date d = new Date(2020,9,15);
        d.printDate();
    }
}

注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。

5.2.2 特性

  1. 构造器与类同名
  2. 每一个类可以有一个以上的构造器
  3. 构造器可以有0个、1个或多个参数
  4. 构造器没有返回值
  5. 构造器总是伴随着new操作符一起调用
  6. 构造方法可以重载
class Date{
    public int year;
    public int month;
    public int day;

    // 构造方法
    // 无参构造方法
    public Date() {
    }

    // 带3个参数的构造方法
    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public void printDate(){
        System.out.println(this.year + "/" +this.month + "/" + this.day);
    }
}

public class Test {
    public static void main(String[] args) {
        Date d = new Date(2020,9,15);
        d.printDate();
    }
}
// 上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载。
  1. 如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的

    class Date{
        public int year;
        public int month;
        public int day;
    
        public void printDate(){
            System.out.println(this.year + "/" +this.month + "/" + this.day);
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Date d = new Date();
            d.printDate();
        }
    }
    
    

    上述Date类,没有定义任何构造方法,编译器会默认生成一个无参构造器。

    注意:一旦用户定义,编译器就不会生成
    image-20231120094411241

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

    class Date{
        public int year;
        public int month;
        public int day;
    
        public Date() {
            this(2005,5,9);// 必须是构造方法的第一条语句
        }
    
        public Date(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
        }
    
        public void printDate(){
            System.out.println(this.year + "/" +this.month + "/" + this.day);
        }
    }
    
    public class Test2 {
        public static void main(String[] args) {
            Date d = new Date();
            d.printDate();
        }
    }
    

    注意:this(…)必须是构造方法的第一条语句

5.3 默认初始化

在上文中提出的第二个问题:为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?

class Date{
    public int year;
    public int month;
    public int day;

    public Date(int year, int month, int day) {
        // 成员变量在定义时,并没有给初始值, 为什么就可以使用呢?
        System.out.println(this.year);
        System.out.println(this.month);
        System.out.println(this.day);
    }

    public void printDate(){
        System.out.println(this.year + "/" +this.month + "/" + this.day);
    }
}

public class Test2 {
    public static void main(String[] args) {
        Date d = new Date(2023,9,17);
    }
}

image-20231120101405474

要搞清楚这个过程,就需要知道new 关键字背后所发生的一些事情:

 Date d = new Date(2023,9,17);

在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍一下:

  1. 检测对象对应的类是否加载了,如果没有加载则加载

  2. 为对象分配内存空间

  3. 处理并发安全问题

    比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突

  4. 初始化所分配的空间

    即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:

    数据类型默认值
    byte0
    char‘\u0000’
    short0
    int0
    long0L
    booleanfalse
    float0.0f
    double0.0
    referencenull
  5. 设置对象头信息

  6. 调用构造方法,给对象中各个成员赋值

5.4 就地初始化

在声明成员变量的时候,就可以给出初始值。

class Date{
    public int year = 2021;
    public int month = 5;
    public int day = 19;

    public Date() {
    }

    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public void printDate(){
        System.out.println(this.year + "/" +this.month + "/" + this.day);
    }
}

public class Test2 {
    public static void main(String[] args) {
        Date d = new Date(2023,9,17);
        d.printDate();
        Date d1 = new Date();
        d1.printDate();

    }
}
// 运行结果
// 2023/9/17
// 2021/5/19

注意:代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/315620.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5 实现RPG游戏操作控制

在UE5以后,epic抛弃了之前的那一套操作输入系统,使用了一套新的增强输入作为替代,目的主要是解决经常切换操作时的问题(操作人物上车以后,可以直接切换成操作汽车的一套输入)接下来,将实现如何使…

用React给XXL-JOB开发一个新皮肤(三):实现登录页和Layout骨架

目录 一. 简述二. 接口服务调整 2.1. 登录接口2.2. 登出接口2.3. 修改密码接口2.4. 修改配置文件 三. 前端HTTP 请求四. 登录页面 4.1. 搭建登录页面4.2. 对接登录接口 五. Layout 骨架 5.1. 搭建骨架5.2. Header5.3. 修改密码5.4. 退出登录 六. 其他 一. 简述 上一篇文章我…

Android代码混淆

Android之代码混淆 代码混淆的作用设置混淆1. 在模块目录下的 build.gradle 文件中配置以下代码2. 在 proguard-rules.pro 文件中添加混淆规则 通用混淆规则常用匹配符常用命令注意事项如何查看是否已混淆 代码混淆的作用 1.令 APK 难以被逆向工程,即很大程度上增加…

Nightingale 夜莺监控系统 - 监控篇(2)

Author:rab 官方文档:https://flashcat.cloud/docs/content/flashcat-monitor/categraf/3-configuration/ 目录 前言一、Categraf 配置文件二、Input 插件配置文件2.1 插件说明2.2 通用配置2.2.1 配置采集频率 interval2.2.2 配置采集实例 instances2.2…

Spring Boot - Application Events 的发布顺序_ContextRefreshedListener

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的,它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…

AI语音识别模块--whisper模块

1.下载 ffmpeg,挑一个自己电脑系统的版本,下载,如我win64: 地址: Releases BtbN/FFmpeg-Builds GitHub 下载压缩包zip,到本地 解压安装,其实无需安装,只需把对应的目录下的bin&…

2024年第1周,第一期技术动态

大家好,才是真的好。 今天周五,我们继续介绍与Domino相关产品新闻,以及互联网或其他IT行业动态等。 一、Notes/Domino V9和V10技术支持结束和假消息 今年2024年6月1号,HCL将结束IBM Notes/Domino 9.0.x和10.0.x产品的技术支持声…

制作 CentOS Stream9 的U盘系统启动盘

一、简述 注:请勿用于商用,如有版权纠纷,于博主无任何关系。(仅用于学习研究使用) 由于CentOs Linux 7和CentOs Stream8终止日期是2024年,需要将系统升级到最新版本的CentOs Stream9,下面是刻录系统盘的操…

用js做个转盘

样式 <style>.wheel {position: relative;width: 400px;height: 400px;border: 1px solid black;border-radius: 50%;overflow: hidden;margin: auto;}.slice {position: absolute;left: 0;top: 0;width: 0;height: 0;border: 200px solid red;/* border-width: 100px 10…

Linux/SwagShop

Enumeration nmap 仍然一样&#xff0c;先使用nmap探索目标开放端口情况 看到开启了22端口和80端口&#xff0c;还是一样的&#xff0c;先从80端口开始探索&#xff0c;从nmap给出的结果&#xff0c;我们可以看到有一个域名&#xff0c;因此在/etc/hosts中添加域名到IP的映射…

ODBC 在指定的DSN中,驱动程序和应用程序之间的体系结构不匹配

常规办法就是64位或32位匹配&#xff0c;如果解决不了&#xff0c;往下看。 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓解决方案↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 解压AccessDatabaseEngine_X64.exe&#xf…

【C++】C++11中的常见语法(下)

C11 一、可变参数模板1. 递归函数方式展开参数包2. 逗号表达式展开参数包3. STL容器中的 empalce 相关接口函数 二、lambda 表达式1. C98 中的一个例子2. 使用 lambda 表达式3. lambda 表达式语法&#xff08;1&#xff09;lambda 表达式各部分说明&#xff08;2&#xff09;捕…

池化、线性、激活函数层

一、池化层 池化运算是深度学习中常用的一种操作&#xff0c;它可以对输入的特征图进行降采样&#xff0c;从而减少特征图的尺寸和参数数量。 池化运算的主要目的是通过“收集”和“总结”输入特征图的信息来提取出主要特征&#xff0c;并且减少对细节的敏感性。在池化运算中…

基于SSM的电脑测评系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的电脑测评系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

Python教父推荐:《Python基础教程》(第3版) 中文PDF电子版限免

《Python基础教程 第3版》包括Python程序设计的方方面面&#xff1a;首先&#xff0c;从Python的安装开始&#xff0c;随后介绍了Python的基础知识和基本概念&#xff0c;包括列表、元组、字符串、字典以及各种语句&#xff1b;然后循序渐进地介绍了一些相对高-级的主题&#x…

旅游数据可视化大屏:一屏掌控,畅游数据之海

随着旅游业的蓬勃发展&#xff0c;如何有效地管理和分析旅游数据成为行业关注的焦点。旅游数据可视化大屏作为一种新兴的技术手段&#xff0c;为旅游业带来了前所未有的机遇和挑战。 旅游数据可视化大屏集成了丰富的数据资源&#xff0c;通过直观的图表、图像和交互界面&#x…

MySQL面试题 | 03.精选MySQL面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

基于面向对象编程,C++实现单链表

链表&#xff1a;在内存空间中是非连续存储 组成&#xff1a;链表是由一个个节点组成的&#xff0c;每个节点都包含两个元素&#xff1a;数据和指针 节点头文件&#xff1a; 建立一个ListNode.h头文件 #pragma once class ListNode { public:int value;ListNode* next;Lis…

web前端算法简介之队列

队列 队列基本操作 入队&#xff08;enqueue&#xff09;&#xff1a;将元素添加到队列的尾部。出队&#xff08;dequeue&#xff09;&#xff1a;从队列的头部移除元素。队首&#xff08;front&#xff09;&#xff1a;获取队列头部的元素&#xff0c;但不移除它。队尾&#x…

【机器学习300问】5、什么是强化学习?

我将从三个方面为大家简明阐述什么是强化学习&#xff0c;首先从强化学习的定义大家的了解强化学习的特点&#xff0c;其次学习强化学习里特殊的术语加深对强化学习的理解&#xff0c;最后通过和监督学习与无监督学习的比较&#xff0c;通过对比学习来了解强化学习。 一、强化…