文章目录
一、面向对象的初步认识
1.1 什么是面向对象
在《Java编程思想》中提到“万物皆为对象”的概念。它将对象视为一种奇特的变量,它除了可以存储数据之外还可以对它自身进行操作。它能够直接反映现实生活中的事物,例如人、车、小鸟,猫,狗等,将其表示为程序中的对象。每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法),java就是通过对象之间行为的交互来解决问题的。
1.2 面向过程与面向对象
(1)自己做饭和点外卖
自己做饭:出门->去菜市场->选菜->付钱->回到家->洗菜->煮饭->起锅烧菜
点外卖:打开手机点餐APP->选择美食->下单付钱->等待外卖
(2)对比发现
• 通过自己做饭是面向过程的,更注重于做饭的过程在整个过程中要经过一系列的操作才能吃上一口热乎的饭。
• 通过手机点外卖是面向对象的,不需要自己一步步去操作做饭的过程,完全不用考虑饭是怎么做的,只需要通过手机点餐APP就能吃上一口热乎的饭。
二、类的定义和简单的使用
2.1 什么是类
对象是现实生活中的实体,在现实生活中描述一个人需要知道他的名字身高体重外貌爱好等等,而计算机并不认识现实生活中的对象,所以就需要通过类来描述对象的属性(外貌、形状、特征等)来告诉计算机什么是对象,类是创造对象的模型。
2.2 类的定义和使用
(1)类的定义,在Java中类的定义需要用到class关键字
注: 类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。这里介绍了类的定义方法,下面我们来试着定义并使用它吧。
(2)定义一个类并使用它
首先定义一个学生类
class Student{
public String name;//姓名
public int age; //年龄
public double height;//身高
public double weight;//体重
//行为
public void eat() {
System.out.println(name+"正在吃饭!");
}
public void sleep() {
System.out.println(name+"又在睡觉!");
}
public void playgame() {
System.out.println(name+"居然还在玩游戏!");
}
}
• 注意事项
1、一般一个文件当中只能定义一个public类
2、main方法所在的类一般要使用public修饰(非强制要求)
3、public修饰的类必须要和文件名相同(硬性要求)
4、 不要轻易去修改public修饰的类的名称,如果要修改,通过开发工具修改
2.3 类的实例化
定义了一个类,就相当于在计算机中定义了一个新的类型 与int , float等类似,只不过这些是Java 语言内置类型。而类是用户自定义的新类型!
用类类型创建对象的过程,称为类的实例化。 在Java 中 采用 new 关键字,配合类名来实例化对象。
定义了类,那我们就要来使用它,我们常常在Java学习中,听到别人调侃程序员:"没对象了怎么办,简单呀,“new"一个对象”。那么new关键字到底如何使用呢?请看如下例子:
class Student{
public String name;//姓名
public int age; //年龄
public double height;//身高
public double weight;//体重
//行为
public void eat() {
System.out.println(name+"正在吃饭!");
}
public void sleep() {
System.out.println(name+"又在睡觉!");
}
public void game() {
System.out.println(name+"居然还在玩游戏!");
}
}
public class Myclass {
public static void main(String[] args) {
//实例化第一个学生
Student student1 = new Student();
student1.name = "小茗同学";
student1.eat();
student1.sleep();
student1.game();
System.out.println("===========");
//实例化第二个学生对象
Student student2 = new Student();
student2.name = "喜洋洋";
student2.eat();
student2.sleep();
student2.game();
}
}
在本例中 Student student=new Student(); 的作用就是
1.加载Student.class文件进内存。
2.在栈内存为student1和student2开辟空间
3.在堆内存为学生对象开辟空间
4.对学生对象的成员变量进行默认初始化
5.学生对象初始化完毕,把对象变量赋值给student变量
通过上面的实现,我们可以得到以下结论
• new 关键字用于创建一个对象的实例.
• 使用 . 来访问对象中的属性和方法.
• 同一个类可以创建多个实例.
简单描述一下对象在内存中是如何分配的
2.4 类和对象的总结
类是对象的蓝图,它会告诉虚拟机如何创建某种类型的变量。根据某类创建出的对象都会有自己的实例变量。举例来说,你可以使用动物类来创造许多不同的动物,如猫科,犬科,熊科,哺乳类动物等等。
三、 this引用
来看如下代码:
class Student{
public String name;//姓名
public int age; //年龄
public double height;//身高
public double weight;//体重
public void set(String name, int age, double height,double weight){
name = name;
age = age;
height = height;
weight = weight;
}
public void print(){
System.out.println(name+" "+"年龄:"+age+"身高:"+"体重:"+weight);
}
}
public class Myclass {
public static void main(String[] args) {
Student stu = new Student();
stu.set("张三",20,176.5,135);
stu.print();
System.out.println("==========");
Student stu1 = new Student();
stu.set("李三",15,170.5,115);
stu.print();
}
}
代码创建了两个学生对象,并且都传入了参数,打印结果却令人大失所望,这是为什么呢?我们明明已经传入参数了啊?
stu和stu1都在调用set和print函数,但是这两个函数中没有任何有关对象的说明,set和 print函数如何知道打印的是那个对象的数据呢?到底谁给谁赋值?编译器也搞不清楚。所以出现下面这种情况。
这些问题都和this有关,让我们来揭开它神秘的面纱吧。
3.1 到底什么是this引用
其实类的每个成员方法的第一个参数默认是this引用,this代表的是对当前对象的引用,谁调用了这个方法,谁就是这个引用。
加上this后,再次运行:
public void set(String name, int age, double height,double weight){
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
}
运行结果:
结果发生了翻天覆地的变化,这是为什么?
这就需要了解到this的作用了
3.2 this作用
1.this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
2.this只能在"成员方法"中使用(后面介绍)
3.在"成员方法"中,this只能引用当前对象,不能再引用其他对象
4.this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收
5.正是由于this这些特性的存在,使得我们可以精准的找到每个对象对应的成员方法。即便是成员方法的形参名与成员变量名相同时只要我们在变量前加上this.即可
四、构造方法
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 d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
}
}
4.2 构造方法特性
1.名字必须与类名相同 没有返回值类型,设置为void也不行
2.创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
3.创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
4.构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
5.构造方法中,可以通过this调用其他构造方法来简化代码
public class Date {
public int year;
public int month;
public int day;
// 无参构造方法
public Date(){
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;
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
Date d = new Date();
d.printDate();
}
}
上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载
如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。
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();
}
}
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;
}
上述Date类中,没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。
注意:一旦用户定义,编译器则不再生成。
构造方法中,可以用this简化代码
public class Date {
public int year;
public int month;
public int day;
// 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
// 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
// 但是this(2001,12,13);必须是构造方法中第一条语句
public Date(){
this(2001, 12, 13);
}
// 带有三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
注意:this(…)必须是构造方法中第一条语句,不能形成环。
public Date(){
this(1900,1,1);
}
public Date(int year, int month, int day) {
this();
}
/*
无参构造器调用三个参数的构造器,而三个参数构造器有调用无参的构造器,形成构造器的递归调用
编译报错:Error:(19, 12) java: 递归构造器调用
*/
今天的讲解就到这里了,谢谢参观。