面向对象基础
面向对象基础
本篇整理 Java 面向对象的基础内容:类与对象的概念、类的组成与对象的创建、方法重载、构造方法以及 this 关键字。
1. 类和对象
1.1 什么是对象
面向对象编程(Object Oriented Programming,OOP)的核心思想是:一切客观存在的事物(一辆车、一本书、一个人)都是对象,万事万物皆对象。任何对象,一定具有自己的特征和行为。
对象是实际存在的该类事物的每个个体,因而也称实例(instance)。
1.2 什么是类
类是对一类事物的描述,是抽象的、概念上的定义。
1.3 类和对象的关系

Java 的类用于描述现实生活中的事物。生活中,在车间通过图纸造汽车;Java 中通过类设计汽车,通过 new 关键字创建汽车。生活中的汽车在马路上跑,Java 中的汽车在内存中跑。
二者的对应关系:对象——汽车;类——汽车的设计图纸。
1.4 为什么设计类
基本数据类型无法满足程序设计的要求,我们需要自定义类型来满足程序设计的要求。类其实就是一种自定义的类型。
2. 类的组成与创建对象
[修饰符] class 类名 {
属性
[构造方法]
方法
}修饰符:可以省略,目前我们暂时填写 public。
类名:要符合标识符的命名规范。
属性描述了类所描述的事物具有的特性,代表有什么。
方法描述了类所描述的事物具有的动作,代表能做什么。
2.1 属性
[修饰符] 数据类型 属性名 [= 初始值];修饰符:可以省略,目前我们暂时填写 public。
数据类型:任意的数据类型,可以是基本数据类型,也可以是引用数据类型。
属性名:属性的名字,要符合标识符的命名规范。
初始值:在设计类时,可以为属性指定初始值,也可以不指定;如果不指定,属性会有默认的初始值。
属性有时也被称为成员变量、数据成员。
2.2 方法
[修饰符] 返回值类型 方法名(参数类型 参数名1, 参数类型 参数名2…) {
方法体;
return 返回值;
}修饰符:比较多,后面会详细介绍,目前我们暂时填写 public。
方法名:为了方便调用方法而起的名字,要符合标识符的命名规范,见名知意。
参数类型:限定调用方法时传入参数的数据类型。
参数名:接收调用方法时传入的参数,要符合标识符的命名规范,见名知意。
方法体:完成功能的代码。
return:结束方法,并返回方法指定类型的值。
返回值类型:用于限定返回值的数据类型。如果没有返回值,返回值类型为 void,此时 return 语句有两种写法:写 return;,或者不写 return 语句。
返回值:被 return 带回、返回给调用者的结果。
下面是一个完整的类定义示例:
package com.learn.test;
/*
* 类的定义
*
* 修饰符 class 类名 {
* 属性-----特性-----成员变量
* 构造方法
* 方法-----动作-----能做什么事情-----成员方法
* }
*
* 方法
* 修饰符 返回值类型 方法名(参数列表) {
* 方法体
* return 返回值;
* }
* 属性
* 修饰符 数据类型 属性名 = 初始值;
* */
// 表示人的类
public class Person {
public String name;// 姓名
public int age;// 年龄
public String gender;// 性别
public String id;// 身份证号
public String tel;// 电话
// 跑步
public void running() {
/*
* 类中的方法可以直接访问类的属性
*/
System.out.println(name + " running....");
}
// 学习
public void learn() {
System.out.println("learn....");
}
}2.3 对象的创建和使用
- 使用
new关键字创建一个新的对象; - 使用
对象名.对象成员的方式访问对象成员(包括属性和方法); - 如果创建了一个类的多个对象,对于类中定义的属性,每个对象都拥有各自的一套副本,且互不干扰。
对象创建后,属性会被赋初值,默认初始值如下:
| 数据类型 | 默认初始值 |
|---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0 |
double | 0.0 |
char | '\u0000' |
boolean | false |
| 引用数据类型 | null |
public class MyTest1 {
public static void main(String[] args) {
/*
* 如何根据类创建对象
* new+构造方法
* 构造方法-----方法名和类名相同
*
* new Person();
* */
int a = 10;
// 创建表示人的对象
/*
* p1、p2、p3----对象名、对象的引用
* 他们并不是对象本身
* */
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
/*
* 对象名.成员----访问对象中的属性和方法
* */
p1.name = "zhangsan";// 修改p1的name
/*
* 在不同类当中访问类的属性,需要先创建类的对象,然后根据类的对象访问属性
* */
System.out.println(p1.name);// 打印p1的name
p1.running();
p1.learn();
/*
* 每个对象是单独的个体,修改一个对象的属性后,其他对象的属性不受影响
* */
p2.name = "wangwu";
System.out.println(p1.name);
/*
* 对象创建之后,对象的属性会被赋初值
* int----0
* byte---0
* long---0
* short--0
* char---0
* double-0.0
* float--0.0F
* boolean---false
* 引用----null
* */
System.out.println(p3.name);
System.out.println(p3.age);
p3 = p1;
p3.name = "Tom";
System.out.println(p1.name);
p1 = null;
p2 = null;
int b = 0;
System.out.println(b);
int x = 10;
System.out.println(x);// 10
// 基本数据类型参数的传递
chg(x);
System.out.println(x);// 10
Demo dm = new Demo();
dm.x = 1;
System.out.println(dm.x);
// 引用数据类型参数传递
// d = dm
chg(dm);
System.out.println(dm.x);// 1000
Person p4 = new Person();
p4.age = 10;
p4.age = p4.age + 2; //通过引用修改堆中对象的属性
System.out.println(p4.age);
}
// a = x
public static void chg(int a) {
a = 1000;
}
public static void chg(Demo d) {
d.x = 1000;
}
}
// Demo类
public class Demo {
public int x;
}值传递(传值):当基本类型作为参数传入方法时,无论该参数(原型变量的一个值的拷贝)在方法内怎样被改变,外部的变量原型总是不变的。
引用传递:当引用作为参数传入方法时,通过引用在方法内部修改引用关联的数据,数据本身会被修改。
2.4 类的访问机制
在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。例外:static 方法访问非 static 成员,编译不通过。
在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员。
2.5 成员变量和局部变量
| 成员变量 | 局部变量 | |
|---|---|---|
| 定义位置 | 类的内部,方法的外部 | 方法或方法内的代码块中 |
| 默认值 | 有默认值,和数组元素默认值相同 | 没有默认值 |
| 生命周期 | 随着对象的创建而产生,随着对象的消失而消失 | 随着所属区域的执行而存在,随着区域的结束而释放 |
| 使用范围 | 定义在类中,整个类中都可以使用 | 定义在方法代码块中,只在所属的区域有效 |
3. 方法重载
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
方法重载的特点:
- 与返回值类型无关,只看方法名和参数列表;
- 在调用时,JVM 通过参数列表的不同来区分同名方法。
public class Person {
public String name;// 姓名
public int age;// 年龄
public String gender;// 性别
public String id;// 身份证号
public String tel;// 电话
// 跑步
public void running() {
/*
* 类中的方法可以直接访问类的属性
*/
System.out.println(name + " running....");
}
// 学习 - 方法重载
public void learn() {
System.out.println("learn....");
}
// 学习 - 方法重载
public void learn(String subject) {
System.out.println("learn..." + subject);
}
}测试方法重载:
public class MyTest2 {
public static void main(String[] args) {
// 创建对象
Person p1 = new Person();
// 调用方法
p1.learn();
// 调用方法
p1.learn("JavaSE");
}
}4. 构造方法
4.1 什么是构造方法
构造方法是类中的特殊方法,主要用于创建对象,在对象创建时被调用。
当一个类的实例对象刚产生时,这个类的构造方法就会被自动调用,我们可以在这个方法中加入要完成初始化工作的代码。
4.2 作用和特点
作用:给对象进行初始化。
特点:
- 方法名与类名相同;
- 不用定义返回值类型;
- 没有具体的返回值。
4.3 构造方法的相关细节
- 不管有没有显式定义构造方法,创建对象都必须要通过构造方法初始化;
- 一个类中如果没有定义过构造方法,那么该类中会有一个默认的空参数构造方法;
- 如果在类中定义了有参的构造方法,那么类中的默认构造方法会被覆盖;如果此时需要使用无参的构造方法,则要手动定义;
- 构造方法可以有多个,用于对不同的对象进行针对性的初始化;
- 多个构造方法在类中是以重载的形式来体现的。
public class Person {
public String name;// 姓名
public int age;// 年龄----私有的
public String gender;// 性别
public String id;// 身份证号
public String tel;// 电话
/* 构造方法
* 1.方法名和类名相同
* 2.不用定义返回值类型
* 3.在对象被创建的时候调用
* 4.不管有没有定义构造方法,创建对象时都会调用构造方法进行初始化
* 5.如果一个类中没有定义构造方法,那么该类中存在默认的无参的构造方法
* public Person() {
*
* }
* 6.如果在类中自定义了构造方法,那么默认的构造方法会被覆盖
* 如果想使用默认的构造方法要如何做?----自己手写一个默认的构造方法
* */
/*public Person() {
System.out.println("创建Person对象");
}*/
/*
* 默认的构造方法
* */
public Person() {
}
/*
* 带参数的构造方法
* */
public Person(String n) {
name = n;
}
// 带参数的构造方法
public Person(String n, int a, String g, String i, String t) {
name = n;
age = a;
gender = g;
id = i;
tel = t;
}
// 跑步
public void running() {
/*
* 类中的方法可以直接访问类的属性
*/
System.out.println(name + " running....");
}
// 学习 - 方法重载
public void learn() {
System.out.println("learn....");
}
// 学习 - 方法重载
public void learn(String subject) {
System.out.println("learn..." + subject);
}
}测试构造方法:
public class MyTest3 {
public static void main(String[] args) {
Person p = new Person("张三");
System.out.println(p.name);
Person p1 = new Person("ls", 20, "男", "111", "1111");
System.out.println(p1.name);
System.out.println(p1.age);
System.out.println(p1.gender);
System.out.println(p1.id);
System.out.println(p1.tel);
}
}5. this 关键字
this 关键字有两个功能:表示当前对象;表示构造方法。
5.1 表示当前对象
this 可以用来指代当前对象,当成员变量和局部变量重名时,可以用关键字 this 来区分。
package com.qfedu.bean;
public class Person {
public String name;// 姓名
public int age;// 年龄
public String gender;// 性别
public String id;// 身份证号
public String tel;// 电话
// 默认的构造方法 - 没有参数
public Person() {
}
// 带参数的构造方法
// 当成员变量和局部变量重名,可以用关键字this来区分
public Person(String name) {
this.name = name;
}
// 带参数的构造方法
// 当成员变量和局部变量重名,可以用关键字this来区分
public Person(String name, int age, String gender, String id, String tel) {
this.name = name;
this.age = age;
this.gender = gender;
this.id = id;
this.tel = tel;
}
// 跑步
public void running() {
System.out.println(this.name + " running....");
}
// 学习 - 方法重载
public void learn() {
System.out.println("learn....");
}
// 学习 - 方法重载
public void learn(String subject) {
System.out.println("learn..." + subject);
}
}5.2 表示构造方法
this 也可以表示构造方法,用于在构造方法中调用其他构造方法。
注
this(...) 调用其他构造方法时,只能定义在构造方法的第一行,因为初始化动作要先执行。
public class Person {
public String name;// 姓名
public int age;// 年龄
public String gender;// 性别
public String id;// 身份证号
public String tel;// 电话
// 默认的构造方法 - 没有参数
public Person() {
}
// 带参数的构造方法
/*
* 如果定义了带参数的构造方法,则默认的无参构造方法会被覆盖(此时默认的无参构造方法无法使用)
* 此时如果希望使用无参的构造方法,需要手动定义
* */
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
// this用于在构造方法中调用其他构造方法
this(name);
this.age = age;
}
public Person(String name, int age, String gender) {
// this用于在构造方法中调用其他构造方法
this(name, age);
this.gender = gender;
}
public Person(String name, int age, String gender, String id) {
// this用于在构造方法中调用其他构造方法
this(name, age, gender);
this.id = id;
}
// 带参数的构造方法
public Person(String name, int age, String gender, String id, String tel) {
// this用于在构造方法中调用其他构造方法
this(name, age, gender, id);
this.tel = tel;
}
// 跑步
public void running() {
/*
* 类中的方法可以直接访问类的属性
*/
System.out.println(this.name + " running....");
}
// 学习 - 方法重载
public void learn() {
System.out.println("learn....");
}
// 学习 - 方法重载
public void learn(String subject) {
System.out.println("learn..." + subject);
}
}