在我Java的数据类型与变量的开篇我提到过,面向对象的编程语言真的拥有其独一无二的魅力,那么到底什么是对象?什么是面向对象呢?今天我们就来一探究竟~
面向对象的基本概念
很多编程入门课程在讲述面向对象的概念时,都会用到“洗衣服”这个很“烂”但是又很经典的例子。关于这个例子,老师们会这样讲:
1.传统洗衣服
传统的方式:注重的是洗衣服的过程,少了一个环节可能都不行。 而且不同衣服洗的方式,时间长度,拧干方式都不同,处理起来就比较麻烦。如果将来要洗鞋子,那就是另 一种放方式。
按照该种方式来写代码,将来扩展或者维护起来会比较麻烦。
2.而对于现代洗衣服则是面向对象的
以面向对象方式来进行处理,就不关注洗衣服的过程,具体洗衣机是怎么来洗衣服,如何来甩干的,用户不用去关 心,只需要将衣服放进洗衣机,导入洗衣粉,启动开关即可,通过对象之间的交互来完成的。
其实一开始听到这个例子的时候,给我脑海里植入的概念完全是相反的——我认为手洗衣服难道不应该是更针对衣服这个对象吗?哈哈~换一种思路去理解这个问题或许就会豁然开朗了:比如说,你的衣服上有一块儿油,如果你用手洗的话,是不是应该先找到这块儿油,然后针对着搓洗,这是不是有先后顺序?这就是面向过程,但如果你用洗衣机(无敌牛逼的那种,一洗就干净),那你把衣服丢进去就不用管了,这就是面向对象!
当然,在这里还是要提一句:面向过程和面相对象并不是一门语言,而是解决问题的方法,没有那个好坏之分,都有其专门的应用场景。
类定义和使用
类是什么东西?
在一门学科里,总是会把一些简单的东西说得高大上,这样才会显得学科更有逼格!简单来说,类就是一个实体对象的属性,用来描述一个对象的特点。比如说一个人的身高,体重,年龄,我们转换成计算机语言以后(用类去描述),计算机就可以成功识别了!
类的定义格式
在Java中定义类时需要用到class关键字~
class ClassName{
field;
method;
}
class是定义类的关键字,ClassName为类的名字,{}中为类的主体。
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。
方法主要说明类具有哪些功能,称为类的成员方法。
eg:定义一个dog类
public class blog0402 {
class Dog {
public String name;
public String color;
public void barks(){
System.out.println(name+"wolfwolf~~~");
}
public void wag(){
System.out.println(name+"摇尾巴~");
}
}
}
看看这个简单的小栗子:首先我们使用class关键字创建了一个Dog类,注意奥——类名一定要用大驼峰,所以这里的dog的d要大写。接下来定义的name和color都是我们上面提到的成员属性(成员变量),而下面创建的public void 是不是跟我们创建方法的语句一样呢?这里就是类的成员方法。能够简单的对应起来之后,我们接着往下看吧~
类的实例化
定义了一个类,就相当于在计算机中定义了一种新的类型,与int,double类似,只不过int和double是java语言自带的内置类型,而类是用户自定义了一个新的类型,比如上述的:Dog类。这就是类(一种新定义的类型)有了这些自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。
用类类型创建对象的过程,称为类的实例化,Java中采用new关键字来配合实例化的过程。就好比每次初始化一个变量,我们是不是会写类似 int a = 10;这样的语句?是一样的,只不过现在是在用户自己创建的类型里面实例化你的对象,我们需要约束语法。
- new关键字用于创建一个对象的实例
用new关键字创建的时候我们其实可以类比Scanner的用法,我们是不是经常会写到下面这几句话:
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
这其实就是一个实例化的过程,我们用new关键字创建了一个Scanner类的一个新实例,而Scanner类的构造函数接受了一个参数System.in,表示从键盘读入数据。
Scanner sc声明一个Scanner类型的变量sc,并将新创建的Scanner实例赋值给它。
- 我们一般使用**"** . "来访问对象中的属性和方法(可以类比我们Math.()的用法)
- 同一个类可以创建多个实例**(就好像可以用相同的图纸造出不完全相同的房子,Dog类里也能创建不同品种的狗狗)**
this引用
this引用指向当前对象,在成员方法中所有成员变量的操作,都是通过该引用去访问。 看一段简单的示例:
public class Date {
public static void main(String[] args) {
Date d = new Date();
d.setDay(2020,9,15);
d.printDate();
}
public int year;
public int month;
public int day;
public void setDay(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);
}
}
这里的this.year等就是为了指明:我现在调用的year是类里面的成员变量,而后面那个不加this的year是形式参数。
this类的使用特性
- this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
- this只能在"成员方法"中使用
- 在"成员方法"中,this只能引用当前对象,不能再引用其他对象,这句话的意思就是:
class MyClass {
void myMethod() {
MyClass otherObject = new MyClass();
this = otherObject; // 不能将 this 指向其他对象
}
}
对象的构造及初始化
通过前面知识点的学习知道,在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。那么我们的对象又该如何进行初始化呢?——那就要提到我们的构造方法了。
构造方法
- 名字必须与类名相同
- 没有返回值类型,设置为void也不行
- 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
- 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
看栗子:
public 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,int,int)方法被调用了");
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
// 此处创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
}
}
重点来啦!!!—— 如果用户没有显式定义构造方法,那么编译器会生成一份默认的构造方法,且生成的默认构造方法一定是无参的。 看下面↓
public class Date {
public int year;
public int month;
public int day;
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
Date d = new Date();
d.printDate();
}
}
上述Date类中,没有定义任何构造方法,编译器就会默认生成一个不带参数的构造方法Date(),所以我们在实例化Date的时候才能如此顺利。
在一个构造方法中我们还可以用this来调用其他的构造方法,但是注意:this的调用语句必须在构造方法的第一行。
public class Date {
public int year;
public int month;
public int day;
public Date(){
//System.out.println(year);
this(1900, 1, 1); //必须在第一行
//this.year = 1900;
//this.month = 1;
//this.day = 1;
}
// 带有三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
我们在无参的构造方法Date()中用this调用含有三个参数的构造方法。
默认初始化
为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?
public 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 static void main(String[] args) {
int a;
System.out.println(a);
// 此处a没有初始化,编译时报错:
// Error:(24, 28) java: 可能尚未初始化变量a
Date d = new Date(2021,6,9);
}
}
其实在我们运用new关键字的时候,在jvm层面进行了很多操作:
- 检测对象对应的类是否加载了,如果没有加载则加载
- 为对象分配内存空间
- 处理并发安全问题
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突 - 初始化所分配的空间
- 设置对象头信息
- 调用构造方法,给对象中各个成员赋值
这里我们就简单了解一下,总的来说就是在我们进行new关键字操作的时候,对象中包含的成员已经进行了一个默认的初始化操作,也就是已经初始化过了,并不是没有初始化。
这篇文章总体介绍了一下类和对象的基本概念,以及this的使用和构造方法,我们在类与对象的第二篇就来看看封装的概念以及”包“。希望对你有点点的帮助!