一、面向对象的介绍
面向对象(Object-Oriented Pogramming)并不是一个技术,而是一种编程的指导思想。
以什么形式 组织代码
以什么思路 解决问题
二、类和对象
1. 类与对象的关系
类是一种抽象的数据类型,它是对某一类事物整体的描述(定义),但是并不能代表某一个具体的事物,例如动物、植物、手机、电脑等等。
对象是抽象概念的具体实例,例如张三就是人的一个具体实例。
关系:在 Java 中需要根据类创建对象;一个类可以创建出多个对象。
2. 类的组成
属性:在代码中使用成员变量表示,成员变量与之前定义变量格式一样,但位置需放在类中方法外
方法:在代码中使用成员方法表示,成员方法与之前定义方法格式一样,但需去掉 static 关键字
3. 创建对象
对象是由类创建的,所以首先创建一个学生类:
public class Student {
//属性
String name;
int age;
//方法
public void study(){
System.out.println("学生学习...");
}
}
创建对象的格式:类名 对象名 = new 类名();
使用对象成员变量的格式:对象名.成员变量;
使用对象成员方法的格式:对象名.成员方法;
在 main 方法中创建对象进行测试:
//一个项目只有一个main方法
public class Application {
public static void main(String[] args) {
//创建对象
Student student = new Student();//这里的对象student就是类Student的一个具体实例
//使用对象成员变量并对其初始化
student.name = "张三";
student.age = 18;
System.out.println(student.name);
System.out.println(student.age);
//使用对象成员方法
student.study();
}
}
运行结果为:
张三
18
学生学习...
4. 对象内存图
单个对象内存图
先是 TestStudent.class 字节码文件进入方法区,因为其内部存在主方法。继续执行主方法内部的语句,创建了对象 stu ,此时 Student.class 字节码文件进入方法区,该字节码文件中包含了 Student 类中成员变量和成员方法的声明,随后通过 new 创建的类在堆内存中开辟空间,并根据类的字节码文件形成了其成员变量和成员方法,成员变量 name 和 age 默认值分别为 null 和0,然后该类将其地址交给栈内存中的 stu 变量,所以接下来打印的便是类的地址和成员变量的默认值,最后给类的成员变量赋值,打印赋值后的成员变量的值。
接着调用类中的成员方法,变量 stu 通过地址在堆内存中找到了该类,通过成员方法引用地址找到了字节码文件中的成员方法,然后调动方法,study 方法进入栈内存,运行该方法打印其内部的输出语句,方法运行结束方法即出栈,继续调用 eat 方法,运行过程与 study 方法一样,最后所有语句运行完成,主方法出栈,程序结束。
两个对象内存图
其运行过程与单个对象运行过程类似,但是需要注意的是类创建了几个对象,在堆内存中就要开辟几个空间来存放,其次不同对象在调用相同的成员方法时其实调用的是同一份成员方法。
两个引用指向相同内存图
在创建对象 stu2 时,stu1 将其类的地址复制了一份交给了 stu2 变量,所以对对象 stu2 操作也就是对对象 stu1 操作,所以最终打印输出的内容是一样的。
三、成员变量和局部变量的区别
四、this 关键字
1. this 关键字介绍
代表当前类对象的引用(地址)。
2. this 关键字的作用
this 关键字可以区分局部变量和成员变量的重名问题。
this 关键字可以调用本类成员:
-
this.本类成员变量
如果不涉及变量重复,this.可省略 -
this.本类成员方法();
没有前提条件,this.可以直接省略
下面举一个例子方便理解,首先构建一个简单的学生类:
public class Student {
String name;//成员变量
public void sayHello(String name){//局部变量
//可以发现此处成员变量和局部变量重名,Java使用就近原则
System.out.println(name);//根据就近原则,会打印局部变量lisi
System.out.println(this.name);//this关键字可以调用本类的成员变量zhangsan
}
}
再构建一个主方法用来测试:
public class StudentTest {
public static void main(String[] args) {
Student stu = new Student();//创建对象
stu.name = "zhangsan";//成员变量初始化
stu.sayHello("lisi");
}
}
运行结果为:
lisi
zhangsan
3. this 内存图
当打印局部变量时,与堆内存中的类没有任何的地址联系,所以打印的只能是局部变量的值。
当打印成员变量时,哪一个对象调用的方法,方法中的 this 就代表哪一个对象的地址,对象 stu 调用的方法,那么 this 就代表 stu 的地址,stu 通过地址能够建立与堆内存中的类的联系,所以打印成员变量的值。
五、构造方法
1. 构造方法介绍
即构造器,构建、创造对象的时候,所调用的方法。
格式:
a. 方法名与类名相同,大小写也要一致
b. 没有返回值类型,连 void 都没有
c. 没有具体的返回值(不能由 return 带回数据结果)
构造方法的执行时机:
a. 在创建对象的时候被调用执行,且每创建一次对象,就会执行一次构造方法
b. 不能手动调用构造方法
例如:
public class Student { //Student学生类
public Student(){ //构造方法
System.out.println("Student类的构造方法");
}
}
测试:
public class StudentTest {
public static void main(String[] args) {
Student stu1 = new Student();//创建对象时会调用构造方法
Student stu2 = new Student();
Student stu3 = new Student();
}
}
运行结果为:
Student类的构造方法
Student类的构造方法
Student类的构造方法
2. 构造方法的作用
最本质的作用当然是创建对象,但除此以外,结合构造方法执行时机,在创建对象的时候,可以给对象中的属性(成员变量)进行初始化。
例如:
public class Student {
String name;
int age;
public Student(String name, int age){//调用构造方法时给数据初始化
this.name = name;
this.age = age;
}
}
测试:
public class StudentTest {
public static void main(String[] args) {
Student stu1 = new Student("张三",18);
System.out.println(stu1.name + "---" + stu1.age);
Student stu2 = new Student("李四",19);
System.out.println(stu2.name + "---" + stu2.age);
}
}
运行结果为:
张三---18
李四---19
3. 构造方法注意事项
a. 构造方法的创建
- 如果没有定义构造方法,系统将给出一个默认的无参构造方法
- 如果定义了构造方法,系统将不再提供默认的构造方法
b. 构造方法的重载
- 构造方法也是方法,允许重载关系出现
c. 推荐的使用方式
- 无参构造方法,和带参构造方法,都自己手动给出