目录
内容提要
- 理解面向对象的思想
- 理解类与对象的关系、如何定义一个类、如何创建一个对象并访问类中成员
- 关键字private
- 关键字this
- 类的构造方法
面向对象(OOP)
面向对象简介
概述
众所周知,Java是一种面向对象的编程语言,何谓面向对象?简言之,参照现实中的事物,抽象出它的行为和特征并描述成计算机事件的设计思想,强调通过对象的行为实现功能,而不是实现功能的具体步骤(面向过程)。例如洗衣服,面向过程是将洗衣服的所有过程诸如寻找洗衣服器皿、加水、加洗衣粉、浸泡、揉搓洗、漂洗、拧干、晾晒等,而面向对象则相当于直接找到一个洗衣机让机器洗,我们只需要使用洗衣机,而不去关注洗衣机如何洗干净衣服。
三大特征
面向对象三大特征,封装(encapsulation)、继承(inheritance)、多态。
类和对象
类(class)
- 类:一类事物的模板,一组相关属性和行为的集合,构造(construct)对象的模板和蓝图
- 例如:一个学生类,拥有姓名、学号、年龄(属性),能够上课、写作业、考试(行为)——抽象
对象(object)
- 对象:对象是类的实例(instance),是类的体现
- 例如:一个18岁的学生Susan,学号23333今晚参加考试(一个具体的学生即学生实例)——具体
- 对象的三个特性:
- 标识(identity)——如何辨识不同的对象?
- 行为(behavior)——能对对象进行哪些操作?(施加方法)
- 状态(state)——施加方法对象如何相应?
类的定义
前面提到类是属性和行为的集合,其中的属性就用成员变量描述,行为用成员方法描述。定义格式如下:
public class ClassName {
//成员变量
//成员方法
}
- 成员变量:定义与之前提到的变量定义方法一致,位置发生改变,定义在类当中、类的成员方法之外。
- 成员方法:定义与之前也一致,修饰符略去static,后面还会提到static的作用
- 举例:
public class Student {
//成员变量,直接定义在类当中,在方法外面
//成员方法,不需要写static关键字
String name;
int age;
public void study() {
System.out.println("Learning!");
}
public void sleep() {
System.out.println("Sleeping!");
}
}
创建一个对象
创建对象格式:
ClassName objectName = new ClassName();
使用对象访问类的成员:
objectName.MemberVariable;
objectName.MemberMmethod(parameter);
使用举例:
package ObjectOriented;//这是自动导入的包名,可以自行定义包名
/*
* 1.导包:import 包名称.类名称(同一个package下可省略)
* 2.创建:类名称 对象名 = new 类名称()
* 3.使用:使用成员变量-->对象名.成员变量名;使用成员方法-->对象名.成员方法名(参数)
* */
public class ObjectOriented01Class {
public static void main(String[] args) {
Student stu = new Student();
//使用默认值
System.out.println("Name: " + stu.name + " Age: " + stu.age);//Name: null Age: 0
stu.name = "Susan";
stu.age = 18;
System.out.println("Name: " + stu.name + " Age: " + stu.age);//Name: Susan Age: 18
stu.sleep();//Sleeping!
stu.study();//Learning!
}
}
成员变量的默认值
注意到上述代码main函数第二行代码中没有对对象的属性进行赋值,依然能够打印出一些数据,可见成员变量具有默认值,具体情况如下:
数据类型 | 默认值 | |
基本数据类型 | 整型——byte、short、int、long | 0 |
浮点型——float、double | 0.0 | |
字符型——char | '\u0000' | |
布尔型——boolean | false | |
引用数据类型 | 字符串、数组、类、接口等 | null |
成员变量与局部变量的区别
局部变量与成员变量的差异:
- 前者在方法内部定义,后者在方法外部,直接在类中定义
- 前者只适用于方法中,后者可以在整个类中通用
- 前者没有默认值,只有赋值后才能使用,后者采取与数组相同的默认值
- 前者位于栈内存,后者位于堆内存
- 前者随方法压栈产生方法退栈消失,后者随对象创建而产生对象被JVM回收而消失
封装(encapsulation)
封装简介
概述
通过前面的学习,我们了解到Java是面向对象编程的,从上面关于类的定义中可以看出对象的属性可以被随意修改,这意味着这是不安全的,所以我们需要设定屏障防止类的代码和数据被其他类随意访问,封装应运而生。
思想
思考将类的属性隐藏起来,只能使用特定方法对其访问。
使用封装
关键字private
在学习如何封装之前,先来了解一个权限修饰符private。
-
private是一个权限修饰符,代表最小权限
-
private能修饰成员变量和成员方法,修饰后的成员变量和方法只能被本类访问
封装步骤
步骤
- 使用private修饰成员变量
- 使用getter、setter方法获取和设定变量值
使用格式
private DataType VariableName;
获取和修改被private修饰的变量:对于变量xxx,使用getXxx方法获取变量值(boolean使用命名采用isXxx),使用setXxx方法设定变量值。
问题
观察代码:
public class Student {
private String name;
private int age;
public void setName(String name) {
name = name;
}
public void setAge(int age) {
age = age;
}
}
通过测试发现,成员变量赋值失败,问题在于set方法的形参与成员变量名重复,成员变量被隐藏而无法访问,于是我们使用this关键字来解决重名问题。
关键字this
含义
this代表所在类当前对象的引用(地址值)
使用格式
this.VariableName
构造方法(constructor)
含义
对象被创建时,使用构造方法初始化,给成员变量赋初始值,通过new创建对象时,实际上就是在调用Constructor
使用格式
public ClassName (param_type param, ...) {
Method Body
}
可以通过编写适当的Constructor实现对对象成员变量的初始化,但仍然需要getter/setter方法修改成员变量
注意
- Constructor的名称必须与类名称完全一致
- Constructor不需要写return type,也不能有具体的return value
- 如果没有编写Constructor,系统自动补全一个Constructor,没有parameter、method body即public ClassName{},如果编写至少一个Constructor,编译器将不再补全
- Constructor也可以进行重载
实例
package ObjectOriented;
/*
* private:本类中可以随意访问该变量,其他类无法直接访问;间接访问变量必须设定getter、setter方法
* getter:不能有参数,返回值类型与成员变量一致,方法命名规则-getXxx
* 如果类型是boolean,则命名规则修改为isXxx
* setter:不能有返回值,参数类型与成员变量一致,方法命名规则-SetXxx
* this:当方法局部变量与类的成员变量重名时,根据“就近原则”,优先使用局部变量
* 如果需要访问本类当中的成员变量,需要使用:this.成员变量名
* 谁调用的方法,谁就是this
* */
public class Person {
String name;
private int age;
private boolean male;
public Person() {
}
public Person(String name, int age, boolean male) {
this.name = name;
this.age = age;
this.male = male;
}
//获取age数据
public int getAge() {
return age;
}
//向age设定数据,手动编写
public void setAge(int num) {
if (num > 0 && num < 120) {
age = num;
}
System.out.println("Error!");
}
//boolean类型变量使用isXxx
public boolean isMale() {
return male;
}
public void setMale(boolean male) {
this.male = male;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sayHello(String name) {
System.out.println("Hello, " + name + "I'm " + this.name);
}
}
标准代码——JavaBean
学习到这里,你已经掌握了关于类的绝大多数内容,现在我们学习一下如何定义一个标准类——符合JavaBean规范的类。
标准类定义要求
- 所有member variable都要使用private修饰
- 所有member variable都有一对getter/setter方法
- 编写一个无参Constructor
- 编写一个全参Constructor
快捷键
手动编写getter、setter和构造方法是极为繁琐且效率低下的,IDEA提供了自动补全功能,快捷键为Alt+Insert
Alt+Insert调出自动补全菜单
选中构造函数功能
选中无选择(Select None)生成无参构造方法
按住Ctrl或Shift点选所有变量生成全参构造方法
选中Getter和Setter功能
按住Ctrl或Shift点选所有变量后点击确定生成所有变量的Getter和Setter方法
注意:快捷键生成均为标准格式,你仍然可以自己编写适宜的方法来适配你的需求
实例
package ObjectOriented;
public class ObjectOriented06StandardClass {
/*
* 一个standard class包括:
* 1.所有member variable都要使用private修饰
* 2.所有member variable都有一对getter/setter方法
* 3.编写一个无参Constructor
* 4.编写一个全参Constructor
* */
private String param1;
private int param2;
private double param3;
private boolean param4;
public ObjectOriented06StandardClass() {
}
public ObjectOriented06StandardClass(String param1, int param2, double param3, boolean param4) {
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
this.param4 = param4;
}
public String getParam1() {
return param1;
}
public void setParam1(String param1) {
this.param1 = param1;
}
public int getParam2() {
return param2;
}
public void setParam2(int param2) {
this.param2 = param2;
}
public double getParam3() {
return param3;
}
public void setParam3(double param3) {
this.param3 = param3;
}
public boolean isParam4() {
return param4;
}
public void setParam4(boolean param4) {
this.param4 = param4;
}
}