【JavaSE】类和对象

面向对象概述

面向对象编程(简称POP),其核心思想就是参照现实中的事物,将事物的属性特征、行为特征抽象出来,使用类来表示,当涉及到一个具体的实例时,就将类进行实例化,使用一个对象来表示。

简而言之,计算机是一个不能独立思考的物品。当使用者赋予某种权利的同时,计算机才能获得并使用该种权利。因此程序员想要计算机呈现某种事物时,就需要将此种事物的特征给抽象出来,而这些特征就会构造成一个整体,这个整体程序员使用类来形容。于是,当使用者进行使用时,直接去调用它的特征即可。此时需要考虑的一个问题就是每个人拥有相同的特征,但是特征的内容不尽相同,例如人们都拥有身份证,但是内容却不相同。对于此类问题,既然某种事物拥有相同的特征,那么就使用这种特征来表示这类事物,对于这类事物的个体,将这些特征实例化,每个具体的个体使用一个对象来表示即可。

举例:对与CSDN这个系统来说,其核心事物就是用户,因此可以将其抽象成类:用户类。对于用户类来说,其属性特征就是用户名、用户密码以及文章数等其他,其行为特征就是看文章、写文章以及修改文章等其他。对于我们使用者来说,都是用户,因此我们的属性特征和行为特征正是上述内容,但是其特征的内容对于每个人来说都不相同,因此一个用户使用CSDN时,都会使用上述事物来构建成一个对象,每个用户属于一个对象。所谓的类和对象,就是面向对象的核心概念。

类和对象

类和对象是面向对象的核心概念。对于Java来说,面向对象的程序设计思想贯穿始终,无论是现在学习的JavaSE,还是后续学习的JavaEE,都离不开类和对象。

什么是类?

类是具有相同特征事物的抽象描述,是抽象的、概念上的定义。

什么是对象?

对象是实际存在的该类事物的具体个体,是具体的。因此也被称为实例。

类的成员概述

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

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

  •  现实世界中的生物体,大到鲸鱼、小到蚂蚁,都是由最基本的细胞构成的。同理,Java代码世界是由诸多个不同功能的类构成的。
  • 现实生物世界中的细胞又是由什么构成的呢?细胞核、细胞质 ... 
  • Java中用类class来描述事物也是如此。类,是一组相关属性和行为的集合,这也是类两个最基本的成员之一。

        a. 属性:该类事物的状态信息。对应类中的成员变量。

        b. 行为:该类事物要做什么操作,或者基于事物的状态能做什么。对应类中的成员方法。

public class Person {// 属性,也被称为成员变量public String name; // 姓名public int age; // 年龄public char gender; // 性别// 行为,也被称为成员方法public void sayHi() {System.out.println("早上好!");}public void sing() {System.out.println("我非常喜欢唱歌!");}public void dance() {System.out.println("我非常喜欢跳舞!");}}

类的实例化

类表示的是一类事物的特征,而对象就是类实例化的产物。

格式:类型   对象名   =   new   类型()   ;

面向对象完成具体功能的三步骤

步骤一:创建类,并设计类的内部成员。

步骤二:创建类的对象。

步骤三:通过对象,调用其内部的属性或方法。

内存解析

JVM中使用到的内存区域

虚拟机栈:用于存储局部变量等。局部变量表存放了编译器可知长度的各种基本数据类型和对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完,自动释放。

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

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

创建类的一个对象

创建类的多个对象

通过上述的内存解析,可以看出,对象和数组的内存位置大致相同。两者都是在虚拟机栈中存放数组名/类名的地址,然后地址再对应到堆内存中存放具体的数据。对于这种存放方式,导致的一个问题就是如果不new一个新的空间,那么可能存在几个变量对应的都是一个地址,即同一个对象。这使得若多个变量对应一个地址,那么进行修改时,其他变量的值也会同时被改变。

创建类的多个对象时,每个对象在堆空间中会有一个对象实体。每个对象实体中保存着一份类的属性,也就是成员变量、这里就包含着一个成员变量和局部变量的区别:成员变量会有一个默认初始值,初始值的大小和数组的一致;局部变量则没有默认初始值。

属性/成员变量

成员变量是类的成员之一,描述的是事物的状态信息。例如在用户类中的用户名、密码以及年龄等都属于成员变量。

变量的分类

按照数据类型来分:基本数据类型(8种),引用数据类型(6种)。

按照变量在类中声明的位置不同:成员变量,局部变量(方法内、方法形参、构造器内、构造器形参以及代码块内)。

成员变量 VS 局部变量

概念

成员变量:在方法体外、类体内声明的变量。

局部变量:在方法体内部等位置声明的变量。

public class User {// 成员变量private String username; // 姓名private String password; // 密码private int age; // 年龄private String gender; // 性别public void sleep(int hour) { // 形参,相当于是局部变量System.out.println(username + "的睡眠时间是" + hour + "小时!");}public void eat() {String food = "鱼香肉丝"; // 局部变量System.out.println("我最喜欢吃的菜是" + food + "!");}}

相同点

1. 变量声明的格式相同:数据类型   变量名   =   变量值;

2. 变量都有其有效的作用域,出了作用域就失效了;

3. 变量必须先声明,后赋值,再使用。

不同点

1. 声明的位置不同

    成员变量:方法体外,类体内。

    局部变量:声明在方法内、方法形参、构造器内、构造器形参、代码块内。

2. 内存位置不同

    成员变量:随着对象的创建,存储在堆内存中。

    局部变量:存储在栈空间中。

3. 生命周期不同

    成员变量:随着对象的创建而创建,随着对象的消亡而消亡。

    局部变量:随着方法对应的栈帧入栈,局部变量会在栈中进行分配,随着方法对应的栈帧出栈,局部变量消亡。

4. 作用域不同

    成员变量:在整个类的内部都是有效的。

    局部变量:仅限于声明此变量所在的方法(或构造器内、或代码块内)。

5. 权限修饰符不同

    成员变量:可以使用权限修饰符。

    局部变量:不可以使用权限修饰符。

6. 默认值不同

    成员变量:存在初始默认值。

    局部变量:没有初始默认值。

    换句话说,如果没有给成员变量进行显式初始化赋值,则会有默认初始化值;而使用局部变量之前,必须要显式的赋值,否则报错。

方法

成员方法是类的成员之一,描述的是该类事物对应的操作。例如用户类可以修改自己的信息,可以进行吃饭的动作等行为。在Java中,方法是必定包含在某个类中的,即使程序的入口:main方法也是包含在Main类中,因此方法即是成员方法(个人理解)。

方法 / 函数的理解

方法是用来完成某个功能操作。在某些语言中也被称为函数或者过程。

通俗的讲:方法是对某个功能的封装。例如在某个游戏中,攻击是一个重复性极高的操作,如果每次攻击都写一段新的代码。显而易见,代码将会非常冗余。但是如果进行封装,将攻击的操作封装成一个方法,当使用攻击操作时,直接调用方法,此时代码就会变得简练许多。

将功能封装为方法的目的是,可以实现代码调用、减少冗杂、优化代码。

Java中方法不能独立存在,所有方法必须定义在类里。

方法声明的格式

修饰符 返回类型 方法名(形参列表) throws 异常列表 { // 方法头// 方法体}

1. 一个完整的方法 = 方法头 + 方法体

2. 修饰符不仅包括权限修饰符,还包括其他例如static、abstract、native、final、sychronized等。

方法调用的内存解析

public static void main(String[] args) {Person person = new Person();person.name = "王彬泽";person.age = 21;person.gender = '男';person.eat();person.sleep(6);person.interests("编程"); 
} 

由于main方法是程序的入口,因此对于方法调用来说,一定是从main方法开始,最后从main方法结束。学过数据结构的对栈都有一定的了解——先后进出,虚拟机栈也是如此。程序开始时,main方法先进入虚拟机栈中,由于new了一个Person类,因此会在相应堆内存中分配空间。调用eat方法,那么eat方法就会进入虚拟机栈中,当eat方法调用完毕之后,出栈。后续操作仿照进行。sleep方法进栈,并且自身还带着hour局部变量,功能完成之后出栈。然后interests方法进栈出栈,最后main方法出栈,程序执行完毕。

方法重载(overload)

概念

在同一个类中,允许存在一个以上的同名方法,只要他们的参数列表不同即可。参数列表不同,意味着参数类型和参数个数的不同。

特点

只看参数列表,且参数列表必须不同(参数类型和参数个数)。调用时,根据方法参数列表的不同来区别。

如何判断两个方法是否相同?

方法名相同,且形参列表相同。

编译器是如何确定调用某个具体的方法?

先通过方法名确定了一波重载的方法,进而通过不同的形参列表,确定具体的方法。

形参个数可变的方法

JDK5.0

使用场景

在调用方法时,可能会出现形参的类型是确定的,但是参数的个数不确定。

格式

(参数类型   ...   参数名)

说明

1. 该方法在调用时,针对可变的形参赋的实参值可以是0个、1个 ... N个。

2. 该方法重载有其他方法时,先针对确定参数个数的方法进行调用,如果没有再调用形参个数不确定的方法。

3. 该方法不能重载数据类型相同的数组方法。因为从某一方面论证来说该方法的形参本质就是数组。在使用时,使用方法也和数组的使用方法一致。

4. 若某方法存在参数个数可变的形参,那么必须将此形参放在最后一位,并且参数个数可变的形参在一个方法中只能存在一个。

5. 如下图:若存在多个参数,那么多个参数类型一致的重载方法不能存在,编译器不知道调用哪个方法合适。例如方法一、三和四,参数类型都是int,那么调用print时,编译器认为方法一三四都可以调用,但没有一个最合适的方法,因而报错。

使用举例

方法的值传递机制

对于方法内声明的局部变量来说,如果出现赋值操作:

如果是基本数据类型的变量,则将此变量保存的数据值传递出去;

如果是引用数据类型的变量,则将此变量保存的地址值传递出去。

基本概念

形参:在定义方法时,方法名后面括号中声明的变量称为形式参数,简称形参。

实参:在调用方法时,方法名后面括号中使用的变量/值/表达式称为实际参数,简称实参。

方法参数的传递机制

值传递。

规则

实参给形参赋值的过程:

如果形参是基本数据类型的变量,则将实参保存的数据值赋给形参;

如果形参是引用数据类型的变量,则将实参保存的地址值赋给形参。

内存解析

形参是基本数据类型的变量:

如图所示,由于形参是基本数据类型的变量。因此只是将变量值赋给a与b,并非地址,这也导致最终m和n并不会进行交换。

形参是引用数据类型的变量:

public class Data {public int a;public int b;}
public class Test {public static void main(String[] args) {Data data = new Data();data.a = 10;data.b = 20;Test.swap(data);}public static void swap(Data data) {int temp = data.a;data.a = data.b;data.b = temp;}}

如图所示,由于形参是引用数据类型的变量。因此会在堆内存中分配空间,当给swap方法传递形参时,传递的是地址,从而使得操作的是同一块内存空间,最后的结果也使得值成功交换。

对于类和对象的叙述就到这里,下篇文章就正式步入面向对象三大特性的介绍,应该是分别用三篇文章进行介绍,这样即可以有较多的篇幅来对每一个特性进行解释,也可以文章使脉络清晰,读起来更加流程。 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2.18 day5 C++

以下是一个简单的比喻,将多态概念与生活中的实际情况相联系:比喻:动物园的讲解员和动物表演 想象一下你去了一家动物园,看到了许多不同种类的动物,如狮子、大象、猴子等。现在,动物园里有一位讲解员,他会为每种动物表演…

聊聊xinput1_3.dll丢失的几种修复方式,xinput1_3.dll文件的作用和重要性

xinput1_3.dll丢失是一个常见且令人困扰的问题。xinput1_3.dll是一个重要的动态链接库文件,用于支持在Windows操作系统上运行的许多游戏和应用程序。当这个文件丢失或损坏时,用户可能会面临无法启动游戏或应用程序的困境。接下来就和大家聊聊xinput1_3.d…

常用类与基础API-String的理解和不可变性

1.String类的理解 1.1类的声明 public final class String >final :String是不可继承的。 >Serializable :可序列化的接口,凡是实现此接口的类的对象就可以通过网络或本地流进行数据的传输 >comparable:凡是实现此接口的类,其对象都可以比较大小. 1.…

【数据结构与算法】手搓JDK底层ArrayList底层 - 动态数组

数组 在介绍数组之前,我们先来看一段chatGPT给出的对于数组描述: 数组(Array)是一种线性数据结构,它由一组连续的内存空间组成,用来存储相同类型的数据元素。数组具有固定的大小,一旦创建后&a…

Selenium Grid分布式测试环境搭建

Selenium Grid简介 Selenium Grid实际上是基于Selenium RC的,而所谓的分布式结构就是由一个hub节点和若干个node代理节点组成。Hub用来管理各个代理节点的注册信息和状态信息,并且接受远程客户端代码的请求调用,然后把请求的命令转发给代理节…

DoRA(权重分解低秩适应):一种新颖的模型微调方法

来自:小互 DoRA(权重分解低秩适应):一种新颖的模型微调方法 DoRA在LoRA的基础上进一步发展,通过将预训练权重分解为“幅度”和“方向”两个部分进行微调。 这种权重分解方法允许DoRA更精细地控制模型的学习过程&…

模型训练 —— AI算法初识

一、背景 AI算法中模型训练的主要目的是为了让机器学习算法从给定的标注数据中学习规律、特征和模式,并通过调整模型内部参数,使模型能够对未见过的数据进行准确预测或决策。具体来说: 1. **拟合数据**:模型通过训练来识别输入数…

Kafka(二)

第 4 章 Kafka Broker 4.1 Kafka Broker 工作流程 4.1.1 Zookeeper 存储的 Kafka 信息 (1)启动 Zookeeper 客户端。 bin/zkCli.sh (2)通过 ls 命令可以查看 kafka 相关信息。 ls /kafka 4.1.2 Kafka Broker 总体工作流程…

图像接入协议之LVDS

LVDS (Low-Voltage Differential Signaling) 是一种高速串行通信协议,用于在电子设备之间传输数据。它通常用于连接液晶显示屏、摄像头、显示器、模拟数字转换器(ADC)等设备。 LVDS具有以下特点 差分信号传输 LVDS使用差分信号传输数据&am…

K8s进阶之路-控制器无状态服务:

RC/RS/Deployment 控制器 deployment无状态(最常用): nginx和Apache statefulset有状态: mysql和redis damonset初始化 job一次性任务 cronjob任务计划 1无状态:不会对本地环境产生依赖如:nginx和Apache …

Docker 镜像是什么?常用的镜像命令有哪些?

docker 镜像仓库相关的命令:Docker 镜像仓库是什么?有哪些镜像仓库命令?-CSDN博客 1. Docker 镜像 Docker 镜像是一个轻量级、独立、可执行的软件包,它包含了运行特定应用程序所需的所有内容:代码、运行时环境、系统工…

【uCore 操作系统】1. 应用程序与基本执行环境

文章目录 【 1. 代码框架简述 】1.1 OS 是怎么跑起来的?1.1.1 qemu 的作用1.1.2 rustsbi.bin 的作用 1.2 qemu 是怎么跑起来的?1.3 OS 文件夹1.3.1 kernel.ld1.3.2 entry.S1.3.3 main.c1.3.4 sbi.c 1.4 bootloader 文件夹 【 2. makefile 和 qemu 】2.1 …