前言:
🌈✨前面小怡给大家分享了数组的小练习,今天小怡给大家分享Java的类和对象的小知识。
1.面向对象的初步认知
1.1 什么是面向对象
Java是一门纯面向对象的语言,在面向对象的世界里,一切皆为对象,对象是一个真正存在的实体。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。
1.2 面向对象和面向过程
1.传统洗衣服过程
步骤是拿盆,放水,放衣服,放洗衣粉,手搓,换水,放洗衣粉,手搓,拧干,晒衣服。
传统的方式:注重的是洗衣服的过程,少了一个环节都可能不行。而且不同衣服洗的方式,时间长度,拧干方式都不同,处理起来就比较麻烦。按照该种方式写代码,将来扩展或者维护起来会比较麻烦。
2.现代洗衣服过程
总共有 四个对象:人、衣服、洗衣粉、洗衣机。
洗衣服的过程:人将衣服放进洗衣机、倒入洗衣粉、启动洗衣机、衣服洗好且甩干。
整个过程主要是四个对象之间交互完成,人不需要关心洗衣机具体是如何洗衣的,是如何甩干的。面向对象就是对象与对象之间协作完成。关注的是对象:1.找对象;2.创建对象;3.使用对象。
注意:面向对象和面向过程并不是一门语言,而是解决问题的方法,没有好坏之分,都有其专门的应用场景。
2.类定义和使用
2.1 简单认识类
类是用来对一个实体(对象)进行描述的,而对象是一个真正存在的实体,主要描述该实体(对象)具有哪些属性,哪些功能。
2.2 类的定义格式
在Java中定义类时需要用到class关键字,具体语法如下:
class Name{
field;//字段(属性)或者成员变量,定义在类里,方法定义在外
method;//行为或成员方法
}
clss为关键字,Name为类的名字,{}为类的主体。
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。
代码示例:
注意事项:
- 类名注意采用大驼峰定义。
- 成员前写法统一为public。
- 此处写的方法不带static关键字。
- 一般一个文件当中只定义一个类。
- main方法所在的类一般要用public修饰。
- public修饰的类必须要和文件名相同;
- 不要轻易修改public修饰的类。
3.类的实例化
3.1 什么是实例化
定义了一个类,就相当于在计算机中定义了一个新的类型。用类类型创建对象的过程,称为类的实例化,在Java中采用new关键字,配合类名来实例化对象。
注意事项:
- new关键字用于创建一个对象的实例。
- 使用 . 来访问对象中的属性和方法 。
- 同一个类可以创建多个实例。
- 成员变量会有一个默认值,遵守的规则:1.引用类型,默认为null;2.基本数据类型,默认为对应的0值。
- 成员变量定义在方法外,局部变量定义在方法里,要初始化。
- 通过对象的引用,可以去访问对象的成员变量,同时也可以访问对象的成员方法。
3.2 类和对象的说明
- 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员。
- 类是一种自定义的类型,可以用来定义变量。
- 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。
- 做个比方,类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同时类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间。
4.this引用
4.1 为什么要有this引用
举个例子:
结果会出来0年0月0日。
setDay是怎么知道要设置哪个对象的呢,printDate是如何知道要打印哪个对象的呢。三个对象都在调用这两个函数,但是两个函数中没有任何关于对象的说明。所以这个时候我们就会使用this引用。
4.2 什么是this引用
this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问的。只不过所有的操作对用户都是透明的,即用户不需要来传递,编译器自动完成。
对象的成员方法和对象的成员变量都是通过对象的引用+点号来访问的。
this 引用的是调用成员方法的对象。
this的三种用法:
1.可以通过this访问,当前对象的成员变量,this.成员变量
2.可以通过this访问,当前对象的非静态成员方法,this.成员方法
3.可以通过this访问,当前对象的其他构造方法,this()当前对象的构造方法
4.3 this的特性
1.this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型;
2.this只能在“成员方法”中使用,不能在静态中;
3.在"成员方法"中,this只能引用当前对象,不能再引用其他对象;
4.this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收。
5.对象的构造及初始化
5.1 如何初始化对象
在使用之前,给设置一个初始值就可以,但是会有两个问题:
1.每次对象创建好后调用setDay方法来设置具体日期,比较麻烦,那对象如何初始化?
2.局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?
5.2 构造方法 (可发生重载)
5.2.1 概念
构造方法(也称为构造器,是一个特殊的成员方法),名字在必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用 一次。
普通方法:
返回值 方法名 (形参列表){
方法体
}
构造方法:
方法名(形参列表){
方法体
}
eg:
public setDay(int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
System.out.println("这个是带参数的构造方法")
}
也可以不带参数~
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
5.2.2 特性
- 名字必须与类名相同;
- 没有返回值类型,设置成void也不行;
- 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次;
- 构造方法可以重载(根据自己的需要提供不同参数的构造方法)
public setDay(int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
System.out.println("这个是带参数的构造方法")
}
public setDay(){
this.year=2024;
this.month=7;
this.day=10;
System.out.println("这个是带不参数的构造方法")
}
上面两个构造方法:名字相同,参数列表不同,因此构成了方法重载。
一个对象的生成 至少有两步很重要:
1.为对象分配内存;
2.调用合适的构造方法。
5.如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认方法一定是无参的,注意:一旦用户定义,编译器则不再生成。
6.绝大多数情况下使用public来修饰,特殊场景下会被privata修饰;
7.构造方法中,可以通过this调用其他构造方法来简化代码。
public Date(){
this(2024,7,31);
}
注意:
1.this(...)必须是构造方法中的第一条语句;
2.不能形成环
5.3 默认初始化
为什么局部变量在使用时必须要初始化,而成员变量不用呢?
要搞清这个过程,就需要知道new关键字背后所发生的一些事情:
Date d=new Date(2024,7,31);
在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍一下:
1.检测对象对应的类是否加载了,如果没有加载则加载,Java优点:之前加载过的类,不会重复加载了;
2.为对象分配空间;
3.处理并发安全问题,比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突;
4.初始化所分配的空间,即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:
数据类型 | 默认值 |
---|---|
byte | 0 |
char | ‘\u0000’ |
short | 0 |
int | 0 |
long | 0L |
boolean | false |
float | 0.0f |
double | 0.0 |
reference | null |
5.设置对象的信息;
6.调用构造方法,给对象中各个成员赋值。
5.4 就地初始化
在声明成员变量时,就直接给出了初始值。
puclic int year=2024;
注意:代码编译完成后,编译器会将所有成员初始化的这些语句添加到各个构造函数中。
6. 封装 (隐藏类的属性和实现细节)
6.1 封装的概念
面向对象的三大特征:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
总结:就是对成员变量或者成员方法使用private进行修饰。
达到的效果,就是该成员变量或者成员方法,此时只能在当前类中使用,不能在其他类中使用。
6.2 访问限定符
Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法 结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:
No | 范围 | private | default | protected | public |
---|---|---|---|---|---|
1 | 同一包中的同一类 | ✔ | ✔ | ✔ | ✔ |
2 | 同一包中的不同类 | ✔ | ✔ | ✔ | |
3 | 不同包中的子类 | ✔ | ✔ | ||
4 | 不同包中的非子类 | ✔ |
比如:
public:可以理解为一个人的外貌特征,谁都可以看到;
default:对于自己家族中(同一个包)不是什么秘密,对于其他人来说就是隐私了;
privata:只有自己知道,别人都不知道。
【说明】
- protected主要是用在继承中。
- default权限:什么都不写时的默认权限。
- 访问权限除了可以限定类中成员的可见性,也可以控制类的可见性;
- 一般情况下,成员变量设置为private,成员方法设置为public。
6.3 封装扩展之包
6.3.1 包的概念
在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。
在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如,一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
6.3.2 导入包中的类
Java中已经提供很多线程的类供我们使用,例如Date类:可以使用 java.util.Date 导入java.util 这个包中的Date类
java.util.Date date=new java.util.Date();
但是这个写法比较麻烦,可以使用import语句导入包
import.java.util.Date;
如果需要使用 java.util 中的其他类,可以使用 import java.util.*
import java.util.*;
但是我们更建议显式的指定要导入的类名,否则还是容易出现冲突的情况。
6.3.3 自定义包 (小驼峰)
基本规则:
- 在文件的最上方加上一个packge语句指定该代码在哪个包中;
- 包名需要尽量指定成唯一的名字,通常会用公司的域名的颠倒形式;
- 包名要和代码路径相匹配;
- 如果一个类没有package语句,则该类会被放到一个默认包中。
操作步骤:
1.在IDEA中先新建一个包:右键-->新建-->包;
2.在弹出的对话框中输入包名;
3.在包中创建类,右键包名-->新建-->类,然后输入类名就可以;
4.此时我们可以看到我们的磁盘上的目录结构已经被IDEA自动创建出来了;
5.同时我们也看到了,在新建的文件最上方,出现了一个package语句。
6.3.4 常见的包
1. java.lang :系统常用基础类(String、Object);
2.java.lang.reflect :Java反射编程包;
3.Java.net :进行网络编程开发包;
4.java.sql :进行数据库开发的支持包;
5.java.util :是Java提供的工具程序包;
6.java.io :I/O编程开发包。
7.static成员
7.1 static修饰成员变量
static修饰的成员变量,称为静态成员变量,也可以称为类成员。静态成员变量最大的特征:不属于某个具体的对象,,是所有对象所共享的。
【静态成员变量特性】
- 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中;
- 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问;
- 类变量存储在方法区当中;
- 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)。
静态成员变量可以直接通过类名访问。
也可以通过对象访问,但是Name是多个对象共享的。
7.2 static修饰成员方法
被static修饰的成员方法,是类的方法,不依赖于对象,不是某个对象所特有的。
在静态方法中,不能够直接调用非静态方法。因为静态方法不依赖于对象,可以直接通过类名进行访问,但是非静态方法依赖对象,需要通过对象的引用访问。非静态当中可以直接调用静态方法。
【静态方法特征】
- 不属于某个具体的对象,是类方法;
- 可以通过对象调用,也可以通过类名,静态方法名……方式调用,更推荐后者;
- 不能在静态方法中访问任何非静态成员变量。
- 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用。
- 静态方法无法重写,不能用来实现多态。
public static String getClassRoom(){
System.out.println(this);
return classRoom;
}
7.3 static成员变量初始化
注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性。
静态成员变量初始化分为两种:就地初始化和静态代码块初始化
1.就地初始化
就地初始化:在定义时直接给出初始值
2.静态代码块初始化
那什么是代码块呢,往后看……
8.代码块
8.1 代码块概念以及分类
使用{ }定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可以分为四种:
- 普通代码块
- 构造块
- 静态块
- 同步代码块 (后面讲)
8.2 普通代码块
public class Main{
public static void main(String[] args){
int x=10;
System.out.println(x);
}
}
8.3 构造代码块
构造代码块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量 。
public Student(){
System.out.println("i am instance init()!");
}
{
this.name="bit";
this.age=12;
}
8.4 静态代码块
static{
classRoom="336";
System.out.println("i am static init()");
}
注意事项:
- 静态代码块不管生成多少个对象,其只会执行一次;
- 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的;
- 如果一个类包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并);
- 实例代码块只有在创建对象时才会执行。
9.对象的打印
🌈✨今天的分享到这里结束啦,还有一个内部类,小怡后面给大家补充,小怡和大家一起学习一起进步,“有志的人战天斗地,无志的人怨天恨地” 。