文章目录
- 前言
- 1. 什么是面向对象?
- 1.2面向过程和面向对象
- 2.类的定义和使用
- 2.1什么是类?
- 2.2类的定义格式
- 2.3类的实例化
- 2.3.1什么是实例化
- 2.3.2类和对象的说明
- 3.this引用
- 3.1为什么会有this
- 3.2this的含义与性质
- 3.3this的特性
- 4.构造方法
- 4.1构造方法的概念
- 4.2构造方法的性质
- 4.3成员变量初始化
- 4.3.1默认初始化
- 4.3.2就地初始化
- 4.4构造方法快速创建
- 5.封装
- 5.1封装的概念
- 5.2封装如何实现
- 6.封装扩展之包
- 6.1什么是包
- 6.2怎么打开包(导入包的类)
- 6.3自定义包
- 7.static成员
- 7.1再谈学生类
- 7.2static修饰成员变量
- 7.3static修饰成员方法
- 7.4static成员变量初始化
- 8.代码块
- 8.1代码块概念及分类
- 8.2普通代码块
- 8.3 构造代码块
- 8.4静态代码块
- 结语
前言
咬咬牙学了一段时间Java慢慢掌握基础知识,今天我们来学习熟悉又陌生的类和对象的相关内容。我们会了解static和public究竟是什么,意义是什么等等,会对Java的基本逻辑有更深刻的了解,还能让我们更加熟练多变的使用Java语言。话不多说,让我们开始吧!!
1. 什么是面向对象?
要知道什么是类之前,我们要先了解所谓的面向对象
的Java语言。
我们知道,Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。
1.2面向过程和面向对象
我们的C语言就是一种面向过程的语言,基本上什么都需要我们自己来编写,结合现实生活我们可以举个例子。
〚洗衣服〛
现在我们来试试细分一下洗衣服的步骤:
拿盆——放水——放衣服——放洗衣液——搓衣服——换水——再洗——拧干——晾衣服
这是我们传统情况下的洗衣服,注重的是洗衣服的过程。
而当我们用洗衣机洗衣服的时候就完全不一样了。
〚洗衣机洗〛
分析一下啊:
人拿衣服——打开洗衣机——放衣服——放洗衣粉——开启洗衣机——拿衣服——晾衣服
经过细致到人的拆解一共就仅仅以上几小步,并没有洗衣服的过程。在其中总共只有四个对象:人、衣服、洗衣粉、洗衣机,以面向对象的方式来进行处理,就不关注洗衣服的过程,用户只需要通过对象之间的交互来完成〚洗衣服〛这件事就可以了,这就是面向对象的特点。
注意:面向过程和面向对象并不是一门语言,而是解决问题的办法,并没有好坏之分,都有对应的应用场景,理解万岁!
2.类的定义和使用
2.1什么是类?
Java中的类和C语言中的结构体有些相似,都是用多种类型数据来描述一个复杂事物。
面向对象程序设计关注的是对象,而对象是现实生活中的实体,比如洗衣机等,但洗衣机计算机并不知道它的特点,就需要开发人员进行具体描述。
类是用来对一个实体(对象)来进行描述的,主要描述其具有哪些属性,哪些功能。
还是洗衣机,可以看成一个对象
属性:尺寸,品牌,重量,颜色等
功能:甩干,定时等
那么在Java语言中如何描述呢?
2.2类的定义格式
在Java中定义类时需要用到class关键字
class ClassName{
field;//字段(属性)或者成员变量
method;//行为 或者叫成员方法
}
class为关键字
ClassName为类名
{}中为类的主体
类中包含的内容就称为类的成员,属性是用来描述类的,称之为类的成员属性或者成员变量。方法主要说明类具有哪些功能,称为类的成员方法。
class Dog{//狗类(注意命名是大驼峰定义)
String name;//狗名
int age;//年龄
String color;//毛色
public void bark(){
System.out.println(this.name + "正在汪汪叫...");
}
public void eat(){
System.out.println(this.name + "正在吃吃吃....");
}
2.3类的实例化
2.3.1什么是实例化
定义了一个类,就相当于定义了一种新的类型,和基本类型int、double等类似,不过类属于用户自定义的一种新的类型。
而用类的类型创对象的过程,就叫类的实例化。我们在Java中使用关键字new
来实现实例化。
public class test {
public static void main(String[] args) {
Dog dog1 = new Dog("dahuang",11,"huangse");
dog1.name = "阿黄";
dog1.color = "黑黄";
dog1.bark();
dog1.eat();
}
输出结果:
2.3.2类和对象的说明
总结来看:
- 类像一个设计图,用来对一个实体进行抽象概括描述,限定了类中有哪些成员,是一种自定义类型。
- 一个类可以实例化出多个对象,对象就是具体的实体,有自身独有的数据,实例化出的对象占据实际的物理空间,来存储成员变量。
3.this引用
3.1为什么会有this
在介绍之前我们先来看一段代码。
class Date {
public int year;
public int month;
public int day;
public void setDay(int y, int m, int d) {
year = y;
month = m;
day = d;
}
}
自定义了一个日期类,在main中实例化就可以写日期了,看起来很完美,也确实很完美。
但我们要是这样改一下还可以实现正常的功能吗?
public void setDay(int year, int month, int day) {
year = year;//形参名和成员变量名相同,并没有报错
month = month;
day = day;
}
如果这样在使用的时候到底函数传入进来的数据是谁在给谁赋值就搞不清楚了,像这个时候就需要我们的this关键字登场了!
3.2this的含义与性质
this的含义:引用指向当前对象,即成员方法运行时调用该成员方法的对象。
(简单说就是指名道姓,谁(对象)调用这个成员方法,this就指向这个“谁”)
在成员方法中的所有成员变量的操作,都是由this引用去访问。
3.3this的特性
- this的类型:对应类类型引用,哪个对象调用就是那个对象的引用类型
- this只能在成员方法中使用
- 在“成员方法”中,this只能引用当前对象,不可引用其他任何对象。
- this其实是“成员方法”中第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用的成员方法的对象的引用传递给成员方法,this相当于变量负责来接收。
4.构造方法
上面代码发现每次都要一个个的引用成员变量来实例化对象,感觉很麻烦,有没有那种一次搞定的?
4.1构造方法的概念
【构造方法】,其实是一个特殊的成员方法,方法名字必须与类名相同,在实例化对象时自动调用,并在整个对象的生命周期中只调用一次。
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.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 date = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
date.printDate(); // 2021-6-9
}
}
4.2构造方法的性质
构造方法有如下几种性质:
- 构造方法只负责对成员变量进行初始化,并不开辟空间
- 名字必须与类名相同
- 没有返回值类型,设置void也不行
- 构造方法是可以重载的(参数不同即可)
- 如果用户没有设置构造方法,编译器会自动生成一份默认(不带参数)的构造方法(一旦用户定义了构造方法,编译器就不再生成)
4.3成员变量初始化
那要是这样就有一个问题出现了:
“为什么成员变量不初始化使用时不会报错,而局部变量会报错呢????为什么为什么为什么??????”
(接下来就会揭晓了!)
4.3.1默认初始化
要搞清楚这个问题,我们就要去探究new
这个关键字发挥作用的过程。
Date date = new Date(2023,12,4);//实例化对象
String date = "2023/12/4"//局部变量初始化
在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:
- 检测对象对应的类是否加载了,如果没有加载则加载
- 为对象分配内存空间
- 处理并发安全问题
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突 - 初始化分配的空间,如下:(这是不会报错的关键)
数据类型 | 初始值 |
---|---|
byte | 0 |
char | “u0000” |
short | 0 |
int | 0 |
long | 0L |
boolean | false |
float | 0.0f |
double | 0.0 |
reference | null |
- 设置对象头信息
- 调用构造方法,给对象中各个成员赋值
4.3.2就地初始化
这个很好理解,就是在声明成员变量时,直接手动设置了初始值。
public class Date {
public int year = 1900;
public int month = 1;
public int day = 1;
public Date(){
}
public Date(int year, int month, int day) {
}
public static void main(String[] args) {
Date d1 = new Date(2021,6,9);
Date d2 = new Date();
}
}
4.4构造方法快速创建
IDEA中有快速创建成员变量构造方法的操作。
操作步骤
1. 在IDEA中创建新的类和几个成员变量
class cat{
String name;
int age;
String sex;
}
2.创建构造方法:右键代码空白处->选择generate
->选择Constructor
3.在弹出的对话框中按住CTRL选择你想要构造的成员变量:
4.成功!!
5.封装
5.1封装的概念
面向对象程序三大特性:封装、继承、多态。 而类和对象阶段,主要研究的就是封装特性。何为封装呢?
简单来说
就是套壳屏蔽细节。
5.2封装如何实现
Java中主要通过类和访问权限来实现封装:类可以将各类数据以及封装数据的方法结合在一起,而访问权限用来控制方法或者字段能否直接在类外使用。因此,Java提供了以下四种访问限定符:
private、public、protected、default
一般情况下成员变量一般设置为private,成员方法设置为public。
6.封装扩展之包
6.1什么是包
在面向对象体系中,提出了软件包的概念,即:
为了更好的管理类,把多个类收集在一起为一组,称为软件包,也有点类似于目录。
在Java中也引入了包,包是对类、接口等的封装机制的体线,是一种对类或者接口等很好的组织方式。
包还有一个重要作用:在同一个工程中允许存在相同名称的类,只要各自在不同的包中即可。
6.2怎么打开包(导入包的类)
Java中已经提供了很多线程的类供我们使用,例如Date类:可以使用java.util.Date
导入java.util
这个包中的Date
类。
public class Test {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
System.out.println(date.getTime());
}
}
但是这样写要是多起来每次都要写一遍太麻烦了,可以使用import语句导包。
import java.util.Date;
public class Test {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.getTime());
}
}
如果需要使用java.util
中的其他类,可以使用import java.util.*
import java.util.*;
public class Test {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.getTime());
}
}
可以使用import static
导入包中静态的方法和字段
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
double x = 30;
double y = 40;
double result = sqrt(pow(x, 2) + pow(y, 2));
System.out.println(result);
}
}
6.3自定义包
基本规则
- 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
- 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1 )
- 包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储
代码. - 如果一个类没有 package 语句, 则该类被放到一个默认包中.
操作步骤
-
在IDEA中先新建一个包:右键src -> 新建 -> 包
-
在弹出的对话框中输入包名,例如
com.test.demo1
-
在包中创建类, 右键包名 -> 新建->类,然后输入类名即可
-
此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了
-
同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句
7.static成员
7.1再谈学生类
使用前文中介绍的学生类实例化三个对象s1、s2、s3,每个对象都有自己特有的名字、性别,年龄,学分绩点等成员信息,这些信息就是对不同学生来进行描述的,如下所示:
public class Student{
// ...
public static void main(String[] args) {
Student s1 = new Student("Li leilei", "男", 18, 3.8);
Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
Student s3 = new Student("Jim", "男", 18, 2.6);
}
}
假设三个同学是同一个班的,那么他们上课肯定是在同一个教室,那既然在同一个教室,那能否给类中再加一个成员变量,来保存同学上课时的教室呢?答案是不行的。
之前在Student类中定义的成员变量,每个对象中都会包含一份(称之为实例变量),因为需要使用这些信息来描述具体的学生。而现在要表示学生上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所有的学生来共享。在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。
7.2static修饰成员变量
static修饰的成员变量,称为静态成员变量,该变量最大的特征就是:不属于某个具体的对象,是所有对象所共享的
【静态成员变量特性】
- 不属于某个具体对象,是类的属性,所有对象共享的,不存储在某个对象的空间中(存在方法区中)
- 既可以通过对象访问,也可以通过类名访问(一般更推荐后者)
- 生命周期伴随类的一生(随类的加载而创建,随类的卸载而销毁)
7.3static修饰成员方法
上面的学习我们知道一般类中的成员变量都设置为private,而成员方法设置为public,那设置之后,Student中的classRoom属性如何在类外访问呢?
在Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。
静态成员一般是通过静态方法来访问的(普通方法也可以访问)
【静态方法特性】
- 不属于某个具体的对象,是类的方法
- 可以通过对象调用,也可以通过
类名.静态方法名
方式调用(更推荐后者) - 不能!在静态方法中访问任何非静态成员变量
- 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时无法传递this引用
7.4static成员变量初始化
注意!静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性
静态成员变量的初始化分为两种:就地初始化和静态代码块初始化。
- 就地初始化
就地初始化指的就是:在定义是直接给初始值
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom = "430";
}
- 静态代码块初始化
这里就到了代码块了,我们接着往下看就好了。
8.代码块
8.1代码块概念及分类
【基础概念】
使用{}
定义的一段代码称为代码块。
根据代码块定义的位置以及关键字,又可以分为以下四种:
- 普通代码块
- 构造块
- 静态块
- 同步代码块(这里先不讨论)
8.2普通代码块
这个很好理解,就是定义在方法中的代码块。
public class Main{
public static void main(String[] args) {
{ //直接使用{}定义,普通方法块
int x = 10 ;
System.out.println("x1 = " +x);
}
int x = 100 ;
System.out.println("x2 = " +x);
}
}
// 执行结果
x1 = 10
x2 = 100
8.3 构造代码块
构造块:定义在类中的代码块(不加修饰符)。
也叫:实例代码块。构造代码块一般用于初始化实例成员变量
public class Student{
//实例成员变量
private String name;
private String gender;
private int age;
private double score;
public Student() {
System.out.println("I am Student init()!");
}
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
8.4静态代码块
static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
//实例代码块
{
this.name = "bit";
this.age = 12;
this.gender = "man";
System.out.println("I am instance init()!");
}
// 静态代码块
static {
classRoom = "bit306";
System.out.println("I am static init()!");
}
}
【注意事项】
- 静态代码不管生成多少个对象,只会执行一次
- 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
- 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
- 实例代码块只有在创建对象时才会执行
结语
好了以上就是本篇“【Java】类和对象详解总结”博客的全部内容啦,感谢各位的阅读=v=,如有不足之处欢迎在评论区指出哦!!
觉得可以的话别忘了点赞三连支持一下欧!拜托啦这对我真的很重要o(>ω< )o!!!