✨本节目标:
- 掌握类的定义方式以及对象的实例化
- 掌握类中的成员变量和成员方法的使用
- 掌握对象的整个初始化过程
- 掌握封装特性
- 掌握代码块
- 掌握内部类
接下来让我们开始学习Java中类和对象的学习吧!
👩🏻🏫作者: 初入编程的菜鸟哒哒
📚系列文章目录:一、TvT——JavaSE(1)–Java的数据类型与变量
二、TvT——JavaSE(2)–Java的运算符
三、TvT——JavaSE(3)–Java的逻辑控制
四、TvT——JavaSE(4)–Java方法的使用
五、你真的学会了JavaSE中数组的定义与使用吗?
📜刷题笔记:
1️⃣TvT——C语言进阶の刷题【1】:指针进阶
文章目录
前言
类和对象: 比较抽象的东西,需要以后我们做点东西,然后慢慢就懂了。
1.什么是面向对象
Java语言来说/c++ : 面向对象的语言。 OOP。
面向对象:完成这件事情的时候只需要和对象进行交互,那么这件事情就可以完成。
只需要 我、秘书、手机、网站四个对象之间交互就可以完成,我具体不需要关心秘书是如何买手机的。
面向过程:每一件事都亲历亲为。
2. 类定义和使用
面相对象程序设计关注的是对象,而对象是现实生活中的实体,比如:洗衣机。但是洗衣机计算机并不认识,需要开发人员告诉给计算机什么是洗衣机。
上图左侧就是对洗衣机简单的描述,该过程称为对洗衣机对象(实体)进行抽象(对一个复杂事物的重新认知),但是这些简化的抽象结果计算机也不能识别,开发人员可以采用某种面相对象的编程语言来进行描述,比如:Java语言。
2.1 简单认识类
类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。
比如:洗衣机,它是一个品牌,在Java中可以将其看成是一个类别。 属性:产品品牌,型号,产品重量,外观尺寸,颜色…
功能:洗衣,烘干、定时…
在Java语言中,如何对上述的洗衣机类来进行定义呢?
2.2 类的定义格式
定义一个类(类型:int byte)【定义的类型】
1.字段 /属性【成员变量】 (比如在这个类中字段就是洗衣机的属性),在类的内部,方法的外部。
class WashMachine{
//1.字段 /属性【成员变量】 (比如在这个类中字段就是洗衣机的属性) 类的内部,方法的外部
public String brand; // 品牌
public String type; // 型号
public double weight; // 重量
public double lenght; // 长
public double weidth; // 宽
public double height; // 高
public String color; // 颜色
}
2.行为 /方法【成员方法】
class WashMachine{
//2.行为 /方法【成员方法】
public void washClothes(){
// 洗衣服
System.out.println("洗衣功能");
}
public void dryClothes(){
// 脱水
System.out.println("脱水功能");
}
public void setTime(){
// 定时
System.out.println("定时功能");
}
}
❗ 注意事项:
- 类名注意采用大驼峰定义
- 成员前写法统一为
public
,后面会详细解释 - 此处写的方法不带
static
关键字. 后面会详细解释
我们再重新定义一个狗类:
class Dog {
public String name;
public int age;
public String color;
public void wag() {
System.out.println(name+"摇尾巴!");
}
public void bark() {
System.out.println(name+"汪汪!");
}
}
注意事项:
- 一般一个文件当中只定义一个类
main
方法所在的类一般要使用public
修饰(注意:Eclipse默认会在public
修饰的类中找main
方法)public
修饰的类必须要和文件名相同- 不要轻易去修改
public
修饰的类的名称,如果要修改,通过开发工具修改。
2.3 类的实例化
由类产生对象的过程->实例化对象
通过new
关键字实例化了一个对象:
在内存里的储存方式类似数组:
如何访问对象里面的数据:
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(dog.name);
System.out.println(dog.age);
System.out.println(dog.color);
}
为什么执行结果是这样的?
局部变量在使用之前一定要初始化。
成员变量不需要,因为成员变量有一个初始值。
1.引用数据类型 -> null
2.基本数据类型 -> 0
boolean -> false
char -> 00000000
如何调用成员方法:
通过.
:
public static void main(String[] args) {
Dog dog = new Dog();
dog.wag();
dog.bark();
}
还可以赋值:
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "初一";
dog.color = "白色";
dog.wag();
dog.bark();
}
}
3. this引用
什么是this
?
this
其实是一个引用:代表当前对象的引用。
那么当前对象是怎么确定的?
比如我们新创建一个
Data
类:public class Date { public int year; public int month; public int day; public void setDate(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) { Date date1 = new Date(); Date date1 = new Date(); date1.printDate(); Date date2 = new Date(); date2.setDate(2021,5,8); date2.printDate(); Date date3 = new Date(); date3.setDate(2022,5,8); date3.printDate(); } }
里面的
setDate
方法的形参名和成员变量的名字是一样的:year, int month, int day) { year = year; month = month; day = day; }
❓ 那还可以通过调用
setDate
方法来给成员变量赋值吗?
来看看结果:
💌答案是赋值失败了。因为在方法里面局部变量的优先级要高于成员变量,所以这里的
year = year;
、month = month;
、day = day;
语句其实就是给形参赋形参的值(自己给自己赋值),而成员变量的值没有改变。
💞而成员变量没有赋值时的默认值上面有讲。
而使用this.
就可以解决这个问题:
把代码加上
this.
:public class Date { public int year; public int month; public int day; public void setDate(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 date1 = new Date(); Date date1 = new Date(); date1.printDate(); Date date2 = new Date(); date2.setDate(2021,5,8); date2.printDate(); Date date3 = new Date(); date3.setDate(2022,5,8); date3.printDate(); } }
现在运行这个代码就没问题了~
那么this
代表什么?
这就表明了this
是代表当前对象的引用。
拿这条代码举例:
date1.setDate(2020,5,8);
跳到setDate
方法里面的时候,此时的this
就是代表的date1
:public void setDate(int year, int month, int day) { this.year = year; this.month = month; this.day = day; }
我们就可以把这里面的
this.year
理解成data1.year
这样就可以修改成员变量的值了。
我们推荐把能用this
的地方都用上this
,这样代码更不易出错。
💌this总结:
1️⃣this.属性
访问当前对象的属性。
2️⃣this()
调用当前对象的构造方法
- 必须放到构造方法里面
- 必须放在构造方法的第一行
- 调用不能够形成环的调用
4️⃣this.func();
调用当前对象的方法
4.构造方法
4.1构造方法构造对象
现在我们不想直接赋值也不想通过setDate
赋值那还有没有其他办法能赋值?
构造方法也可以。
构造方法用于构造对象。
构造方法:这个方法名和类名是一样的,这个方法很特殊,没有返回值。
比如我们自己写一个构造方法:
public Date() {
System.out.println("啥也没有");
}
在实例化这个对象的时候会调用这个构造方法。
假如现在我只在main
函数里new
一个Date
:
public static void main(String[] args) {
Date date1 = new Date();
}
运行一下:
如果没有自己写构造方法,那么编译器就会自行帮忙提供一个不带参数的构造方法。
构造一个这样的:
public Date() {
}
一旦自己提供了构造方法,编译器就不会在自行帮忙提供构造方法了。
并且构造方法中可以使用this.
:
这时就实现了使用构造方法初始化对象。
实例化一个对象分为2步:【基本的】
1️⃣为这个对象分配内存
2️⃣调用合适的构造方法(构造方法不止一个)
对象的生成一定会调用构造方法。
构造方法也可以有参数:
4.2构造方法实现方法的重载
举个栗子:
执行这个代码:
public class Date {
public int year;
public int month;
public int day;
public Date() {
this.year = 1992;
this.month = 9;
this.day = 13;
System.out.println("没有参数的构造函数 : ");
}
public Date(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("调用三个参数的构造函数: ");
}
public static void main(String[] args) {
Date date1 = new Date();
date1.printDate();
Date date2 = new Date(1998,5,10);
date2.printDate();
}
}
运行结果:
因为构造函数满足重载的三个条件:
- 方法名相同
- 参数列表不同:个数、类型、顺序
- 与返回类型无关
IDEA自动生成构造方法:
目前对于成员的赋值:: |
1️⃣定义字段的时候,同时初始化 就地初始化
2️⃣不初始化 0值
3️⃣通过对象的引用 直接赋值dog.name = "haha";
4️⃣通过构造方法初始化
截止到现在的重点总结: |
1️⃣如何创建类:通过
class
2️⃣字段、成员变量 | 方法 成员方法
3️⃣如何创建对象:通过new
关键字进行实例化对象
Dog dog = new Dog();
4️⃣通过对象的引用dog.
属性dog.
方法
5️⃣实例化对象其实调用的是构造方法。多个构造方法就构成了重载。
5. 封装
5.1 封装的概念
面向对象有三个比较重要的思想 :封装 继承 多态
这篇博客主要研究封装的特点。
什么是封装:套壳屏蔽细节
不想让类外看到类具体的实现细节,所以通过技术手段,将这些细节进行封装。
提供公开的一些接口,让你来交互进行即可。
对这个类的细节进行隐藏。
对于使用这个类的人来说,不必关心这个类的实现细节只需要关心这个类的提供的公开的接口进行交互就好了。
封装概念:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行 交互
5.2 访问修饰限定符
public:在任何地方,都可以访问它修饰的成员。
protected :主要是用在继承中,继承部分详细介绍
default:什么都不写时的默认权限
private:只能在当前类当中访问
我们此时把year改成私有的:
再新建一个Tast1类:
这个时候我们发现,无法访问year
这个成员对象了!
因为我们对year
进行了封装,此时year
是私有的,只能在它自己的当前类访问。
这就是实现了封装。
使用private
隐藏了类的细节。
那我们还怎么拿到year
呢?
为year
提供一个公开的接口:
这样做就可以对year
进行操作了~
IDEA对成员提供get
和set
接口的方法:
我们不用每一个都自己写。
6. 包
6.1 IDEA如何自定义一个包
一般包名都是公司网址的倒写,并且最好小写。
6.2 导包
package com.yuanyuan.www;
import java.util.Arrays;
import java.util.Date;
public class TestDemo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(Arrays.toString(arr));
Date date = new Date();
}
}
这里就是导包。
也可这样写:
package com.yuanyuan.www;
import java.util.*;
public class TestDemo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(Arrays.toString(arr));
Date date = new Date();
}
}
这个是在用到的时候自动监测,然后再进包里找类。
但是Date
很麻烦。
我们可以看到Date
类在很多包里面都包括了,如果我们这样写就会报错:
因为编译器不了解你到底想使用哪个包里面的Date
,必须指定具体的方法:
也可以使用import static
导入包中静态的方法和字段。
举个栗子:
正常我们使用sqrt函数
这样用:
import java.lang.Math;
public class Test {
public static void main(String[] args) {
double x = 30;
double y = 40;
double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
System.out.println(result);
}
}
用静态的方法使用:
//导入这个Math类的静态方法
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
double x = 30;
double y = 40; // 静态导入的方式写起来更方便一些,就可以不使用Math.了
double result = sqrt(pow(x, 2) + pow(y, 2));
System.out.println(result);
}
}
6.3 常见的包
常见的包:
java.lang
:系统常用基础类(String、Object),此包从JDK1.1后自动导入。java.lang.reflect
:java 反射编程包; 3.java.net
:进行网络编程开发包。java.sql
:进行数据库开发的支持包。java.util
:是java提供的工具程序包。(集合类等) 非常重要java.io
:I/O编程开发包。