当前位置:   article > 正文

什么叫类与对象? 详解~

类与对象

类与对象

1. 面向过程和面向对象

大一刚开始学编程的时候,老师说一定要了解面向过程开发和面向对象开发。

我当时心想:“学校还能分配个对象给我?让我天天面向她?”后来发现是我多想了。

我于是下意识去百度一下:什么是面向对象

我发现百度的解释跟我大学老师一样:高深莫测,不能通俗易懂。

后来我头悬梁锥刺股去学,终于弄懂了。

下面我会用通俗易懂的小案例来告诉大家这两者的区别。


案例一:打王者荣耀

面向过程:

    1. 打开王者荣耀的 app
    1. 登录账号
    1. 选择5V5的游戏模式
    1. 选择英雄
    1. 开始游戏
    1. 游戏结束

面向对象:

    1. 创建三个对象:人、手机、王者荣耀游戏
    1. 给人对象增加方法:打开手机、操作王者荣耀
    1. 给手机对象增加方法:运行王者荣耀
    1. 给王者荣耀对象增加方法:登录、设置游戏模式、设置英雄、符文、开始游戏、判定游戏输赢等。
    1. 人打开手机
    1. 手机运行王者荣耀
    1. 人玩王者荣耀游戏
    1. 王者荣耀通过人的操作判定输赢

案例二:把大象装进冰箱

面向过程:

    1. 打开冰箱门
    1. 把大象装进去
    1. 关闭冰箱门

面向对象:

    1. 创建两个对象:冰箱、大象
    1. 给冰箱新增方法:开门()、装大象()、关门()
    1. 冰箱开门:冰箱.开门()
    1. 冰箱装大象:冰箱.装大象(大象)
    1. 冰箱关门:冰箱.关门()

案例三:洗衣机洗衣服

面向过程:

    1. 打开洗衣机
    1. 把脏衣服放进去
    1. 倒点洗衣液
    1. 拧开水龙头加水
    1. 开始洗衣服
    1. 洗完衣服关掉洗衣机

面向对象:

    1. 创建两个对象:人、洗衣机
    1. 给人增加方法:操作洗衣机、放脏衣服、打开水龙头、加洗衣液
    1. 给洗衣机增加方法:洗衣服
    1. 人打开洗衣机:人.打开洗衣机()
    1. 人放入脏衣服:人.放脏衣服()
    1. 人加洗衣液:人.加入洗衣液(洗衣液)
    1. 人打开水龙头:人.打开水龙头()
    1. 洗衣机洗衣服:洗衣机.洗衣服()

1.1 面向过程

通过以上例子我们知道面向过程是把一件事情分成好几个步骤去做,强调做事的过程。

比如要想学会降龙十八掌,需要先学第一式,再学第二式......最后学第十八式,每一式与每一式之间的关联性很强,只有依次学完每一式,才能练成。

优点:性能比面向对象高,因为面向对象还要先创建对象,比较消耗计算机的内存,所以更适合小型项目。

缺点:每一个步骤之间的关联性太强,耦合度高,不容易扩展。

1.2 面向对象

通过以上例子我们知道面向对象是强调对象的重要性,把所有的东西都看成对象,把跟他相关的东西都封装在一起。就好比用洗衣机洗衣服那个案例:

  1. 人{
  2. 打开洗衣机()
  3. 放脏衣服()
  4. 加入洗衣液(洗衣液)
  5. }
  6. 冰箱{
  7. 洗衣服()
  8. }
  9. 复制代码

把一件事情的完成分成一个个对象,给对象赋予一定的功能,然后由对象之间分工协作。

优点:代码可复用、容易维护和开发、可扩展性强(比如洗衣服不想用洗衣液了可以换成洗衣粉),所以更适合大型项目。

缺点:比面向过程的性能低

总结:

  • 面向过程:强调过程。
  • 面向对象:强调对象、分工和协作。

2. 类与对象

类:类是一个抽象的概念,在现实世界中不存在。

类本质上是在现实世界中具有共同特征的事物,通过提取这些共同特征形成的概念叫做“类”,比如人类、动物类、汽车类、鸟类等。

类其实就是一个模板,类中描述的是所有对象的“共同特征”。

对象:对象是一个具体的概念,在现实世界中真实存在的。比如李白、爱迪生、贝克汉姆都是对象,他们都属于人类。对象就是通过类创建出的真实的个体。

2.1 抽象

将具有相同特征的对象抽取共同特征的过程叫做“抽象”。

2.2 实例化

对象还有一个别名叫做“实例”,通过类创建对象的过程叫做“实例化”。

3. 类的定义

我们都知道类具有相同的特征,特征包含静态的和动态的。

鸟类的静态特征是长着一双翅膀,动态特征是会飞。狗类的静态特征是嗅觉灵敏,动态特征是会“汪汪”叫......

所以,类 = 属性 +方法

3.1 java 定义类的语法格式

  1. [修饰符] class 类名 {
  2. 属性 + 方法
  3. }
  4. 注:这里修饰符可以省略,后面会讲解。
  5. 复制代码

案例一:用 java 代码创建人类

  1. public class Person {
  2. // 姓名
  3. private String name;
  4. // 年龄
  5. private int age;
  6. // 性别 0-女 1-男
  7. private int sex;
  8. // 身份证
  9. private String idCard;
  10. // 吃饭方法
  11. public void eat(){
  12. System.out.printf("人要吃饭");
  13. }
  14. }
  15. 复制代码

在上面的例子中,属性以“变量”的形式存在。为什么呢?

因为属性是静态特征,属性包含的是数据,比如年龄18岁,性别男,身高180。所以在 java 程序中有关属性的数据只能存在于变量中。

案例二:用 java 代码创建动物类

  1. public class Animal {
  2. // 体重
  3. private int weight;
  4. public void sleep(){
  5. System.out.println("动物要睡觉");
  6. }
  7. }
  8. 复制代码

注:在 java 中凡是用 class 定义的类型都是引用类型,他的类型就是类名本身。

3.2 实例变量

实例变量:把对象共同的静态特征抽取出来存放在类中的变量里面,比如人类中的年龄、性别、身高等。

上面类中的变量就是实例变量,因为对象又叫做实例,所以实例变量就是对象级别的变量。

4. 对象的创建和使用

4.1 创建对象

我们学会定义类之后,该如何创建对象呢?

很简单,new 一下。

语法格式:

  1. 类名 变量名 = new 类名();
  2. 复制代码

我们 new 出来的对象也需要用一个变量来接收,例如:

  1. Student student = new Student();
  2. People people = new People();
  3. Animal animal = new Animal();
  4. 复制代码

4.2 使用对象

创建对象之后,我们怎样使用对象?怎样获取对象的属性?怎样访问对象的方法?

对象.属性 对象.方法

  1. public class Person {
  2. // 姓名
  3. private String name;
  4. // 年龄
  5. private int age;
  6. // 性别 0-女 1-男
  7. private int sex;
  8. // 身份证
  9. private String idCard;
  10. // 吃饭方法
  11. public void eat(){
  12. System.out.printf("人要吃饭");
  13. }
  14. public static void main(String[] args) {
  15. Person person1 = new Person();
  16. System.out.println("1号人类姓名:"+person1.name);
  17. System.out.println("1号人类年龄:"+person1.age);
  18. System.out.println("1号人类身份证:"+person1.idCard);
  19. person1.eat();
  20. System.out.println("-----------------------");
  21. Person person2 = new Person();
  22. System.out.println("2号人类姓名:"+person2.name);
  23. System.out.println("2号人类年龄:"+person2.age);
  24. System.out.println("2号人类身份证:"+person2.idCard);
  25. person2.eat();
  26. }
  27. }
  28. 复制代码

运行结果:

我们都知道一个类可以创建很多对象,但是上面人类创建的对象的年龄为什么是0?身份证为什么是null?

这是因为在 java 中,我们在创建对象的时候如果没有给变量手动赋值,系统会对实例变量默认赋值。默认值如下所示:

数据类型默认值
byte0
short0
int0
long0L
float0.0f
double0.0
引用类型null

5. 画个内存图

为什么要学习 JVM 内存图?

因为 JVM 内存图可以加深你对 Java 运行机制的理解。

Java 虚拟机在运行 java 程序时,会将自己管理的内存划分为几个区域,每个区域都有自己的用途,他们的创建时间和销毁时间也不一样。

JVM 内存很复杂,这里我们主要关注三个区域:栈、堆、方法区。

栈:主要存放方法信息,比如 main 方法。

堆:主要存放对象实例,你可以想象成这里“堆满了对象”。

方法区:这里主要用来存储类的信息、静态变量、常量以及编译器编译后的代码。

前面的例子中,我们创建了两个 Person 类的对象 person1 和 person2。

person1 和 person2 实际上存储的是堆中对象的内存地址:ox00001 和 ox00002,所以他们分别指向了堆中的两个对象。

所以当我们访问对象的实例变量时,先根据对象变量存储的内存地址找到该对象,再获取该对象的实例变量存储的数据。

6. 空指针异常

有时候我们会遇到空指针异常,例如

  1. public class Student {
  2. // 姓名
  3. private String name;
  4. public static void main(String[] args) {
  5. Student student = null;
  6. System.out.println("学生姓名:"+student.name);
  7. }
  8. }
  9. 复制代码

运行结果:

为什么会有空指针异常?通过下面的内存图就能明白:

你新建了空的对象变量 student,它里面没有存任何对象的内存地址。所以当你去访问它的实例变量时,它找不到堆中的对象,就会抛出空指针异常。

7. 构造方法

构造方法是啥?通过“构造”的字面意思隐隐约约感觉它是造东西用的。可是造啥呢?

对,造对象用的。

当你 new 对象的时候是通过调用构造方法来完成对象的创建,以及对象属性的初始化操作。

也就是说在创建对象之前会先调用构造方法。

注:

    1. 当类中没有提供任何构造方法,系统默认提供一个无参数的构造方法。
    1. 当类中手动的提供了构造方法,那么系统将不再默认提供无参数构造方法。

7.1 定义构造方法

语法格式:

  1. [修饰符列表] 构造方法名(形式参数列表){
  2. 方法体;
  3. }
  4. 复制代码

注:

  1. 构造方法名和类名一致
  2. 构造方法没有返回值
  3. 一个类中可以定义多个构造方法,这些构造方法其实是方法的重载

例如:

  1. public class Student {
  2. // 姓名
  3. private String name = "一颗雷布斯";
  4. public Student() {
  5. System.out.println("我是一个没有参数的构造方法");
  6. }
  7. public static void main(String[] args) {
  8. Student student = new Student();
  9. }
  10. }
  11. 复制代码

运行结果:

7.2 定义多个构造方法

  1. public class Student {
  2. // 姓名
  3. private String name;
  4. public Student() {
  5. System.out.println("我是构造方法1");
  6. }
  7. public Student(String name) {
  8. System.out.println("我是构造方法2");
  9. }
  10. public static void main(String[] args) {
  11. Student student1 = new Student();
  12. Student student2 = new Student("一颗雷布斯");
  13. }
  14. }
  15. 复制代码

运行结果:

7.3 使用构造方法初始化实例变量

例如:

  1. public class Student {
  2. // 姓名
  3. private String name;
  4. public Student() {
  5. System.out.println("我是构造方法1");
  6. }
  7. public Student(String name) {
  8. System.out.println("我是构造方法2");
  9. this.name = name;
  10. }
  11. public static void main(String[] args) {
  12. Student student = new Student("一颗雷布斯");
  13. System.out.println("姓名:"+student.name);
  14. }
  15. }
  16. 复制代码

运行结果:

7.4 this

上面的例子中我们使用了 this 关键字,那么为什么要用 this?

我们先把上面例子中的构造方法改一下:

  1. public Student(String name) {
  2. name = name;
  3. }
  4. 复制代码

看完是不是懵逼了?哪个是我要传递的参数?哪个是对象的实例变量?

所以这里 this 用来区分局部变量和实例变量。

注:

    1. this 是一个关键字,是一个引用,保存了当前对象的内存地址。
    1. this 出现在实例方法中代表的是当前对象。
    1. this 不能使用在静态方法中。
    1. 当用来区分局部变量和实例变量时,this 不能省略。
    1. this 既可以出现在构造方法中,也可以出现在实例方法中。

例如:

  1. public class Student {
  2. // 姓名
  3. private String name;
  4. public Student(String name) {
  5. this.name = name;
  6. }
  7. public void printName(){
  8. System.out.println(this.name);
  9. }
  10. public static void main(String[] args) {
  11. Student student = new Student("一颗雷布斯");
  12. student.printName();
  13. }
  14. }
  15. 复制代码

运行结果:

8. 封装

封装是面向对象的三大特征之一,但是什么是封装?为什么要封装?

我们先看下面的例子:

  1. public class Student {
  2. String name;
  3. String phone;
  4. public Student(String name, String phone) {
  5. this.name = name;
  6. this.phone = phone;
  7. }
  8. }
  9. public class StudentTest {
  10. public static void main(String[] args) {
  11. Student student = new Student("一颗雷不斯","18888888888");
  12. System.out.println("电话:"+student.phone);
  13. student.phone = "110";
  14. System.out.println("电话:"+student.phone);
  15. }
  16. }
  17. 复制代码

运行结果:

上面的 Student 类没有进行封装,其中的姓名和电话都是对外暴露的,很不安全,很容易就被篡改了。

所以为了保证数据的安全性,需要对类进行封装。

那 java 语言如何做封装?

    1. 属性必须私有化,即使用 private 关键字修饰,只有本类中才能访问。
    1. 对外提供 set 和 get方法。外部程序只能通过调用该对象的 set 方法设置值,调用该对象的 get 方法获取值。
    1. set 和 get 方法的修饰符必须是 public, 也就是公共的,在其他类中也能访问。

封装之后的例子:

  1. public class Student {
  2. private String name;
  3. private String phone;
  4. public Student(String name, String phone) {
  5. this.name = name;
  6. this.phone = phone;
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public String getPhone() {
  15. return phone;
  16. }
  17. public void setPhone(String phone) {
  18. this.phone = phone;
  19. }
  20. }
  21. 复制代码

发现错误提示:不能访问私有属性

改为通过 get 方法获取值、set 方法设置值:

  1. public class StudentTest {
  2. public static void main(String[] args) {
  3. Student student = new Student("一颗雷不斯","18888888888");
  4. System.out.println("电话:"+student.getPhone());
  5. student.setPhone("119");
  6. System.out.println("电话:"+student.getPhone());
  7. }
  8. }
  9. 复制代码

运行结果:

9. 面向对象三大特征

  • 封装
  • 继承
  • 多态

这三个特征互相关联,任何一个面向对象的编程语言都包括这三个特征。后面会接着讲解继承和多态。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/1011080
推荐阅读
相关标签
  

闽ICP备14008679号