前言
#面向对象 (Object Oriented)是一种编程设计的方法和编程规范,以对象作为程序的基本单位。面向对象编程强调将问题分解为对象与对象间的交互关系。面向对象程序设计包括抽象、封装、继承和多态等特点。
什么是类和对象?
类:指的是对客观事物的一种描述,是对现实生活中一类具有共同属性和行为的事物的抽象。通俗的讲就是某一事物的模板,通过这一模板我们可以实例化一个对象。
对象:用来描述客观事物的一个实体,由属性和行为构成。是通过类这个模板产生的一个实体。
一、类的定义和使用
1.类的定义
//类的定义
class 类名 {
//字段(属性/成员变量)
//行为(成员方法)
}
在Java中定义一个类要用到class关键字,由class+(空格)+类名+{类的主体}构成一个类,类中通常包括字段(属性/成员变量)和行为(成员方法)两部分。
2.类的实例化
用类创建对象的过程,称为类的实例化。
//实例对象的语法
类名 变量名 = new 类名();
2.1如何实例一个对象
在Java中我们可以通过new关键字配合类名来实例化对象。下面我们演示用new关键字实例化一个女朋友类的过程。
我们首先要定义一个女朋友类,只有通过这个共有的模板我们才能产生一个女朋友对象。
//定义一个女朋友类
class GirlFriend {
//女朋友的属性/成员变量
public String name;
public int age;
//女朋友所具有的行为
public void eat(){
System.out.println(this.name + "正在吃饭...");
}
public void sleep(){
System.out.println(this.name + "正在睡觉...");
}
public void play(){
System.out.println(this.name + "正在打豆豆...");
}
}
//在主类Main中实例一个女朋友类
public class Main {
public static void main(String[] args) {
//实例化一个女朋友对象
GirlFriend glf1 = new GirlFriend();
//我们可以通过引用.成员变量/成员方法
//来访问对象的成员变量/成员方法
glf1.name = "小红";
glf1.age = 18;
System.out.println("姓名:"+ glf1.name + " 年龄:" + glf1.age);
glf1.eat();
glf1.sleep();
glf1.play();
System.out.println("==========");
//不仅如此,我们可以通过new关键字实例化多个对象
GirlFriend glf2 = new GirlFriend();
glf2.name = "小黄";
System.out.println(glf2.name);
}
}
输出结果:
姓名:小红 年龄:18
小红正在吃饭…
小红正在睡觉…
小红正在打豆豆…小黄
注意事项:
new
关键字用来创建一个对象的实例- 引用+
.
来访问对象中的属性和方法 - 同一个类可以同时创建多个对象
- 类名通常采用大驼峰的形式来命名
- 类中的成员变量都有默认值(后面讲)
2.2this关键字
上述我们实例化了多个女朋友对象,那么当我们多个对象都在调用其中的成员方法时,方法中没有任何关于对象的说明。那么我们调用的方法该如何知道是哪个对象调用了它呢?
this
引用:
this
引用指向当前对象,也就是说this
引用其实就等同于引用当前对象的引用。
2.2.1形参名与成员变量名相同
我们在上面定义的女朋友类中新增一个setName()方法,方法实现如下:
//在方法中当出现同名变量的时候,局部变量会优先使用
public void setName(String name) {
name = name;//此时实现不了给成员变量赋值的需求
}
我们可以通过隐式传递的this
来访问成员变量,因此我们可以将setName()方法修改为:
public void setName(String name) {
this.name = name;//实现成员变量的赋值
}
2.2.2多个对象调用同一个方法
当出现多个对象调用一个方法的时候,方法怎么区分是哪个对象调用了它呢?
this
的特性:
this
是非静态成员方法中隐藏的第一个参数,编译器会自动传递,在成员方法执行的时候,编译器会负责将其传递给该成员方法this
只能在非静态方法中使用this
的类型对应类类型引用,即谁调用就是谁的引用类型
二、对象的构造及初始化
我们知道在Java方法内部定义一个局部变量时,必须对其初始化,否则会编译失败。那么我们该如何初始化一个对象呢?同时我们发现局部变量只有在初始化后才能使用,为什么类中的字段在声明之后没有”初始化“后依然可以使用呢?
#对象的实例化
其实在实例一个对象的时候,编译器会至少进行以下操作:
- 加载对应class文件
- 申明局部变量
- 在堆中开辟一块空间
- 默认初始化
- 就地初始化
- 构造方法初始化
- 将堆内存中的地址赋值给左边的变量
1.默认初始化
//日期类
public class Date {
//字段
public int year;
public int month;
public int day;
public static void main(String[] args) {
//实例化一个Date类对象
Date d = new Date();
System.out.println(d.year);//0
System.out.println(d.month);//0
System.out.println(d.day);//0
}
}
我们知道局部变量在使用时必须要初始化,而成员变量却可以不进行初始化,这是为什么呢?
其实对于堆中申请的空间,对象的成员会被默认初始化。
对于基本数据类型的变量会被默认初始化为对应的0
值,
对于引用类型的变量则会被赋值为null
2.就地初始化
什么叫就地初始化呢?在声明成员变量时,直接对成员变量进行赋值,这就是就地初始化。
//对于日期类
public class Date {
//字段
public int year = 1990;
public int month = 1;
public int day = 1;
public static void main(String[] args) {
//实例化一个Date类对象
Date d = new Date();
System.out.println(d.year);//输出:1990
System.out.println(d.month);//1
System.out.println(d.day);//1
}
}
3.构造方法
构造方法(也称为构造器)是一种特殊的成员方法,方法名必须与类名相同。构造方法在整个对象的生命周期内只调用一次,在创建对象时,由编译器自动调用。
3.1构造方法的的定义
以上面日期类为例:
public class Date {
//字段
public int year;
public int month;
public int day;
//构造方法:
//方法名与类名相同。 没有返回值类型,(void)也不可以
public Date(int year,int month,int day) {
this.year = year;
this.month = month;
this.day = day;
}
public static void main(String[] args) {
//实例化一个Date类对象
Date d = new Date();
System.out.println(d.year);//0
System.out.println(d.month);//0
System.out.println(d.day);//0
}
}
3.2构造方法的特点
- 构造方法可以进行重载
- 当用户没有显示定义构造方法时,编译器会生成一份默认的构造方法,生成的默认构造方法不带有任何参数。
- 需要注意的是,一旦用户定义构造方法,编译器将不再生成默认的构造方法
- 构造方法中,可以通过
this
调用其他的构造方法来简化代码(不能形成环)
public Date {
this(1990,1,1);//this()必须是构造方法中的第一句
}
public Date(int year,int month,int day) {
this.year = year;
this.month = month;
this.day = day;
}