最新Java基础系列课程--Day06-类和对象

作者主页:编程指南针

作者简介:Java领域优质创作者、CSDN博客专家
、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师

主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互助

收藏点赞不迷路 关注作者有好处

文末获取源码

​# day04——类与对象

各位同学,恭喜大家!!!大家学习完前面的课程后,说明Java的基础语法就全掌握了。

接下来,我们要学习的是Java中最核心的课程——面向对象编程

一、面向对象入门

各位同学,为什么说面向对象是Java最核心的课程呢?因为写Java程序是有套路的,而面向对象就是写Java程序的套路;你如果不知道面向对象编程,那么你Java语言就算白学了。

那这种编程套路是咋回事呢? 接下来,我们通过一个案例快速的认识一下。

现在假设我们需要处理的是学生的姓名、语文成绩、数学成绩这三个数据,要求打印输出这个学生的总成绩,和平均成绩。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7U6xSjhd-1689819787582)(assets/1662209848898.png)]

遇到这样的需求,我们以前都会定义方法来做,如下图所示

注意:这里每一个方法有三个参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Tlc8oi2-1689819787584)(assets/1662209886046.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SVJhv793-1689819787585)(assets/1662209899008.png)]

定义好方法之后,我们调用方法的时候,需要给每一个方法传递三个实际参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vrf0g0YC-1689819787586)(assets/1662210110729.png)]

在上面案例中,这种编程方式是一种面向过程的编程方式。所谓面向过程,就是编写一个的方法,有数据要进行处理就交给方法来处理。

但是实际上姓名、语文成绩、数学成绩三个数据可以放在一起,组合成一个对象,然后让对象提供方法对自己的数据进行处理。这种方式称之为面向对象编程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lArUyEjC-1689819787587)(assets/1662210587156.png)]

总结一些:所谓编写对象编程,就是把要处理的数据交给对象,让对象来处理。

二、深刻认识面向对象

好的各位同学,在上一节课我们已经用面向对象的编程套路,处理了学生数据。接下来我们就要搞清楚,面向对象的几个最核心问题了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tl7xiwh1-1689819787588)(assets/1662211382446.png)]

我们把这三个问题搞明白,那么你对面向对象的理解就很到位。

2.1 面向对象编程有什么好处?

先来看第一个问题,面向对象编程到底有什么好处呢? 那就不得不谈,Java的祖师爷对这个世界的理解了。

Java的祖师爷,詹姆斯高斯林认为,在这个世界中 **万物皆对象!**任何一个对象都可以包含一些数据,数据属于哪个对象,就由哪个对象来处理。

这样的话,只要我们找到了对象,其实就找到了对数据的处理方式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hjo7kNvS-1689819787589)(assets/1662211620054.png)]

所以面向对象编程的好处,用一句话总结就是:面向对象的开发更符合人类的思维习惯,让编程变得更加简单、更加直观。

2.2 程序中对象到底是个啥?

说完面向对象编程有什么好处之后,这里有同学可能会有问题了,你刚才举的例子中,“汽车”、“手机”、“蔡徐坤”是一个实实在在的东西,你说是一个对象好理解。那我们程序中的对象到底是个啥呢?

对象实质上是一种特殊的数据结构。这种结构怎么理解呢?

你可以把对象理解成一张表格,表当中记录的数据,就是对象拥有的数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EZERhU2w-1689819787590)(assets/1662212402342.png)]

这就是程序中的对象到底是个啥! 一句话总结,对象其实就是一张数据表,表当中记录什么数据,对象就处理什么数据。

2.3 对象是怎么出来的?

刚刚我们讲到对象就是一张数据表,那么这个数据表是怎么来的呢?这张表是不会无缘无故存在的,因为Java也不知道你这个对象要处理哪些数据,所以这张表需要我们设计出来。

用什么来设计这张表呢?就是类(class),类可以理解成对象的设计图,或者对象的模板。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SpRHcwgO-1689819787591)(assets/1662213156309.png)]

我们需要按照对象的设计图创造一个对象。设计图中规定有哪些数据,对象中就只能有哪些数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oxb36LDy-1689819787592)(assets/1662213268590.png)]

一句话总结:对象可以理解成一张数据表,而数据表中可以有哪些数据,是有类来设计的。

三、对象在计算机中的执行原理

各位同学,前面我们已经带同学写了面向对象的代码,也知道对象到底是咋回事。如果我们再搞清楚对象在计算机中的执行原理,那我们对面向对象的理解就更加专业了。

按照我们之前讲的数组的执行原理,数组变量记录的其实数数组在堆内存中的地址。其实面向对象的代码执行原理和数组的执行原理是非常类似的。

其实Student s1 = new Student();这句话中的原理如下

  • Student s1表示的是在栈内存中,创建了一个Student类型的变量,变量名为s1

  • new Student()会在堆内存中创建一个对象,而对象中包含学生的属性名和属性值

    同时系统会为这个Student对象分配一个地址值0x4f3f5b24

  • 接着把对象的地址赋值给栈内存中的变量s1,通过s1记录的地址就可以找到这个对象

  • 当执行s1.name=“播妞”时,其实就是通过s1找到对象的地址,再通过对象找到对象的name属性,再给对象的name属性赋值为播妞;

搞明白Student s1 = new Student();的原理之后,Student s2 = new Student();原理完全一样,只是在堆内存中重新创建了一个对象,又有一个新的地址。s2.name是访问另对象的属性。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RCwlakKC-1689819787593)(assets/1662213744520.png)]

四、类和对象的创建和使用

4.1 类的定义

定义类(声明类)实际就是定义类的静态属性和动态属性(方法)。用户定义一个类实际上就是定义一个新的抽象数据类型.使用类之前,必须先定义它,然后才可利用所定义的类来声明相应的变量,并创建对象.

定义类的基本语法结构:

[类修饰符] class 类名称
       {  //声明成员变量
           [修饰符] 数据类型   变量名;
           //声明成员方法
           [修饰符] 返回值类型 方法名(参数表){…}                
       }

类修饰符的作用:

 1、公共类修饰符 public : Java 语言中类的可访问控制符只有一个: public 即公共的。每个 Java 程序的主类都必须是 public 类作为公共工具。供其它类和程序使用的应定义为 public 类。

 2 、抽象类修饰符 abstract :凡是用 abstract 修饰符修饰的类,被称为抽象类。所谓抽象类是指这种类没有具体对象的一种概念类。这样的类就是 Java 语言的 abstract 类。

 3、最终类修饰符 final :当一个类不可能有子类时可用修饰符 final 把它说明为最终类。被定义为 final 的类通常是一些有固定作用、用来完成某种标准功能的类。

 4、类缺省访问控制符:如果一个类没有访问控制符,说明它具有缺省的访问控制符特性。此时,这个类只能被同一个包中的类访问或引用。这一访问特性又称为包访问性。

成员修饰符的作用:

  1、公共访问控制符 public :用 public 修饰的域称为公共域。如果公共域属于一个公共类,则可以被所有其它类所引用。由于 public 修饰符会降低运行的安全性和数据的封装性,所以一般应减少 public 域的使用。

  2、私有访问控制符 private : 用 private 修饰的成员变量 ( 域 ) 只能被该类自身所访问,而不能被任何其它类 ( 包括子类 ) 所引用。

  3、保护访问控制符 protected :用 protected 修饰的成员变量可以被三种类所引用:①该类自身;②与它在同一个包中的其它类;③在其它包中的该类的子类。使用修饰符 protected 的主要作用是允许其它包中它的子类来访问父类的特定属性。

  4、私有保护访问控制符 private protected :用修饰符 private protected 修饰的成员变量可以被该类本身或该类的子类两种类访问和引用。

  5、静态域修饰符 static :用 static修饰的成员变量仅属于类的变量,而不属于任何一个具体的对象,静态成员变量的值是保存在类的内存区域的公共存储单元,而不是保存在某一个对象的内存区间。任何一个类的对象访问它时取到的都是相同的数据;任何一个类的对象修改它时 , 也都是对同一个内存单元进行操作。

   6、最终域修饰符 final :最终域修饰符 final 是用来定义符号常量的。一个类的域 ( 成员变量 ) 如果被修饰符 final 说明,则它的取值在程序的整个执行过程中都是不变的。

   7、易失 ( 共享 ) 域修饰符 volatile :易失 ( 共享 ) 域修饰符 volatile是用来说明这个成员变量可能被几个线程所控制和修改。也就是说在程序运行过程中,这个成员变量有可能被其它的程序影响或改变它的取值。因此,在使用中要注意这种成员变量取值的变化。通常 volatile 用来修饰接受外部输入的域。

   8、暂时性域修饰符 transient :暂时性域修饰符 transient 用来定义一个暂时性变量。其特点是:用修饰符transient 限定的暂时性变量,将指定 Java虚拟机认定该暂时性变量不属于永久状态,以实现不同对象的存档功能。否则,类中所有变量都是对象的永久状态的一部分,存储对象时必须同时保存这些变量。

类的成员变量描述了该类的内部信息,一个成员变量可以是简单变量,也可以是对象、数组等其他结构型数据。成员变量的格式如下:

  [修饰符] 变量类型  **变量名** [=初值];

类的方法是用来定义对类的成员变量进行操作的,是实现类内部功能的机制,同时也是类与外界进行交互的重要窗口。声明方法的语法格式如下:

 [修饰符] 返回值的数据类型 方法名(参数列表)
{

  语句序列;

  return [表达式];
}

类的定义示例:

class Cylinder   //定义圆柱体类Cylinder
{
    
    
    double radius;     //声明成员变量radius
    int height;        //声明成员变量height
    double pi=3.14;   //声明数据成员pi并赋初值
    void area( ) {
    
      //定义成员方法area(),用来计算底面积
      System.out.println("圆柱底面积="+ pi*radius* radius);
     }
     void volume( ) {
    
      //定义成员方法volume (),用来计算体积
        System.out.println("圆柱体体积="+((pi*radius* radius)*height);
     }
}

4.2 对象的创建

可以将对象理解为一种新型的变量。
对象之间靠互相传递消息而相互作用,消息传递的结果是启动方法,完成一些行为或者修改接受消息的对象的属性。
对象完成工作后,将被销毁,所占用的资源将被系统回收。
一个对象的生命周期:创建 -> 使用 -> 销毁

创建对象的步骤
1、声明指向“由类所创建的对象”的变量;
2、利用new创建新的对象,并指派给前面所声明 的变量。
举例:创建圆柱体类Cylinder的对象,可用下列的语法来创建:

   Cylinder  volu;         //声明指向对象的变量volu
   volu = new Cylinder();   //利用new创建新的对象,并让变volu指向它

通过对象来引用对象成员的格式如下:

对象名.对象成员
如, volu.radius = 2.8;    
    volu.height = 5;

如果引用的是成员方法,只要在成员方法名的圆括号内提供所需参数即可,如果方法不需要参数,则用空括号。

如:volu.area()

*一个类多个对象,它们的成员变量分配在不同的内存,因此修改某一对象的成员变量时其他不受影响。

4.3 方法参数的传递

类的方法既可以有返回值也可以带参数。
1、以变量为参数调用方法

调用方法并传递参数时,参数其实就是方法的自变量,所以参数要放在方法的括号内来进行传递。括号内的参数可以是数值型、字符串型,甚至是对象。方法的参数属于局部变量。
若在通过方法调用,将外部传入的参数赋值给类的成员变量,方法的形式参数与类的成员变量同名时,则需用this来标识成员变量。

Class Cylinder
{
    
    
   double radius;

   void SetCylinder(double radius)
    {
    
    
        this.radius = radius;    
    }
  
}

2、以数组作为参数或返回值的方法调用

传递数组:指明参数是一个数组,实参只给出数组名。
返回值为数组类型的方法。若返回一个一维整型数组,则方法前加int[]。
当参数是基本数据类型时,采用传值方式调用;当参数是引用型的变量时,则是传址方式调用。

Class Cylinder
{
   int[] scores;

   void setScores(int[] scores)
    {
        this.scores = scores;    
    }
  
}

3.可变参数

方法中接收不固定个数的参数称为可变参数,方法接收可变参数的语法格式如下:

返回值类型 方法名(固定参数列表,数据类型…可变参数名)  // ... 为可变参数
     {
        方法体
     }

4.4 注意的地方

我把这些注意事项已经列举在下面了,我们把几个不好理解的解释一下就可以了(标记方框),其他的大大家一看就能理解。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VXpkyPFu-1689819787594)(assets/1662213891968.png)]

第一条:一个代码文件中,可以写多个class类,但是只能有一个是public修饰,且public修饰的类必须和文件名相同。

假设文件名为Demo1.java,这个文件中假设有两个类Demo1类和Student类,代码如下

//public修饰的类Demo1,和文件名Demo1相同
public class Demo1{
    
    
    
}

class Student{
    
    
    
}

**第二条:**对象与对象之间的数据不会相互影响,但是多个变量指向同一个对象会相互影响。

如下图所示,s1和s2两个变量分别记录的是两个对象的地址值,各自修改各自属性值,是互不影响的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tJFoNstr-1689819787595)(assets/1662214650611.png)]

如下图所示,s1和s2两个变量记录的是同一个对象的地址值,s1修改对象的属性值,再用s2访问这个属性,会发现已经被修改了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G77TvoNQ-1689819787596)(assets/1662215061486.png)]

五、this关键字

各位同学,接下来我们学习几个面向对象的小知识点,这里我们先认识一下this关键字是什么含义,再说一下this的应用场景。

this是什么呢?

this就是一个变量,用在方法中,可以拿到当前类的对象。

我们看下图所示代码,通过代码来体会这句话到底是什么意思。哪一个对象调用方法方法中的this就是哪一个对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r7TUu1nP-1689819787597)(assets/1662301823320.png)]

上面代码运行结果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cJs2dvWc-1689819787598)(assets/1662302089326.png)]

this有什么用呢?

通过this在方法中可以访问本类对象的成员变量。我们看下图代码,分析打印结果是多少
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zl5ymzJD-1689819787600)(assets/1662303676092.png)]

分析上面的代码s3.score=325,调用方法printPass方法时,方法中的this.score也是325; 而方法中的参数score接收的是250。执行结果是

在这里插入图片描述

关于this关键字我们就学习到这里,重点记住这句话:哪一个对象调用方法方法中的this就是哪一个对象

六、构造器

好同学们,接下来我们学习一个非常实用的语法知识——叫做构造器。

关于构造器,我们掌握下面几个问题就可以了:

  1. 什么是构造器?
  2. 掌握构造器的特点?
  3. 构造器的应用场景?
  4. 构造器有哪些注意事项?

我们一个问题一个问题的来学习,先来学习什么是构造器?

  • 什么是构造器?

    构造器其实是一种特殊的方法,但是这个方法没有返回值类型,方法名必须和类名相同。

    如下图所示:下面有一个Student类,构造器名称也必须叫Student;也有空参数构造器,也可以有有参数构造器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xRl9AOn7-1689819787602)(assets/1662304435504.png)]

认识了构造器之后,接着我们看一下构造器有什么特点。

  • 构造器的特点?

    在创建对象时,会调用构造器。

    也就是说 new Student()就是在执行构造器,当构造器执行完了,也就意味着对象创建成功。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jB50rifJ-1689819787605)(assets/1662304779863.png)]

    当执行new Student("播仔",99)创建对象时,就是在执行有参数构造器,当有参数构造器执行完,就意味着对象创建完毕了。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Qd1sPzR-1689819787607)(assets/1662304859276.png)]

关于构造器的特点,我们记住一句话:new 对象就是在执行构造方法

  • 构造器的应用场景?

    其实构造器就是用来创建对象的。可以在创建对象时给对象的属性做一些初始化操作。如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2xFoTmdR-1689819787609)(assets/1662305406056.png)]

  • 构造器的注意事项?

    学习完构造器的应用场景之后,接下来我们再看一下构造器有哪些注意事项。

    1.在设计一个类时,如果不写构造器,Java会自动生成一个无参数构造器。
    2.一定定义了有参数构造器,Java就不再提供空参数构造器,此时建议自己加一个无参数构造器。
    

关于构造器的这几个问题我们再总结一下。掌握这几个问题,构造方法就算完全明白了。

1.什么是构造器?
	答:构造器其实是一种特殊的方法,但是这个方法没有返回值类型,方法名必须和类名相			同。
	
2.构造器什么时候执行?
	答:new 对象就是在执行构造方法;

3.构造方法的应用场景是什么?
	答:在创建对象时,可以用构造方法给成员变量赋值

4.构造方法有哪些注意事项?
	1)在设计一个类时,如果不写构造器,Java会自动生成一个无参数构造器。
	2)一定定义了有参数构造器,Java就不再提供空参数构造器,此时建议自己加一个无参数构		造器。

七、封装性

面向对象的基本特征

封装性:利用抽象数据类型将数据和基于数据的操作封装在一起,保护数据并隐蔽具体的细节,只保留有限的接口与外界联系。

继承性:使特殊类(子类)的对象拥有一般类 (父类)的全部属性与方法,同时可以增添自身的属性和方法。

多态性:一个程序中同名的多个不同方法共存的情况。常用重载和覆盖。

各位同学,接下来我们再学习一个面向对象很重要的特征叫做——封装性。

1. 什么是封装呢?

所谓封装,就是用类设计对象处理某一个事物的数据时,应该把要处理的数据,以及处理数据的方法,都设计到一个对象中去。

比如:在设计学生类时,把学生对象的姓名、语文成绩、数学成绩三个属性,以及求学生总分、平均分的方法,都封装到学生对象中来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-038M3qiH-1689819787611)(assets/1662305928023.png)]

现在我们已经知道什么是封装了。那我们学习封装,学习个啥呢? 其实在实际开发中,在用类设计对事处理的数据,以及对数据处理的方法时,是有一些设计规范的。

封装的设计规范用8个字总结,就是:合理隐藏、合理暴露

比如,设计一辆汽车时,汽车的发动机、变速箱等一些零件并不需要让每一个开车的知道,所以就把它们隐藏到了汽车的内部。

把发动机、变速箱等这些零件隐藏起来,这样做其实更加安全,因为并不是所有人都很懂发动机、变速箱,如果暴露在外面很可能会被不懂的人弄坏。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a0N6lJcj-1689819787612)(assets/1662306602412.png)]

在设计汽车时,除了隐藏部分零件,但是还是得合理的暴露一些东西出来,让司机能够操纵汽车,让汽车跑起来。比如:点火按钮啊、方向盘啊、刹车啊、油门啊、档把啊… 这些就是故意暴露出来让司机操纵汽车的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P3j6g9Aj-1689819787631)(assets/1662306879230.png)]

好了,到现在我们已经理解什么是封装的一些规范了。就是:合理暴露、合理隐藏

2. 封装在代码中的体现

知道什么是封装之后,那封装在代码中如何体现呢?一般我们在设计一个类时,会将成员变量隐藏,然后把操作成员变量的方法对外暴露。

这里需要用到一个修饰符,叫private,被private修饰的变量或者方法,只能在本类中被访问。

如下图所示,private double score; 就相当于把score变量封装在了Student对象的内部,且不对外暴露,你想要在其他类中访问score这个变量就,就不能直接访问了;

如果你想给Student对象的score属性赋值,得调用对外暴露的方法setScore(int score),在这个方法中可以对调用者传递过来的数据进行一些控制,更加安全。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-idMJDjau-1689819787634)(assets/1662335204398.png)]

当你想获取socre变量的值时,就得调用对外暴露的另一个方法 getScore()

关于封装我们就学习到这里了。

八、实体JavaBean

接下来,我们学习一个面向对象编程中,经常写的一种类——叫实体JavaBean类。我们先来看什么是实体类?

1. 什么是实体类?

实体类就是一种特殊的类,它需要满足下面的要求:

在这里插入图片描述

接下来我们按照要求,写一个Student实体类;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5DCIc0XF-1689819787636)(assets/1662335451401.png)]

写完实体类之后,我们看一看它有什么特点? 其实我们会发现实体类中除了有给对象存、取值的方法就没有提供其他方法了。所以实体类仅仅只是用来封装数据用的。

知道实体类有什么特点之后,接着我们看一下它有哪些应用场景?

2. 实体类的应用场景

在实际开发中,实体类仅仅只用来封装数据,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离。如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KxFchPj1-1689819787637)(assets/1662336287570.png)]

在实际应用中,会将类作为一种数据类型使用。如下图所示,在StudentOperator类中,定义一个Student类型的成员变量student,然后使用构造器给student成员变量赋值。

然后在Student的printPass()方法中,使用student调用Student对象的方法,对Student对象的数据进行处理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cu3BsBz-1689819787639)(assets/1662337507608.png)]

到这里,我们已经学习了JavaBean实体类的是什么,以及它的应用场景,我们总结一下

1.JavaBean实体类是什么?有啥特点
	JavaBean实体类,是一种特殊的;它需要私有化成员变量,有空参数构造方法、同时提供		getXxx和setXxx方法;
	
	JavaBean实体类仅仅只用来封装数据,只提供对数据进行存和取的方法
 
2.JavaBean的应用场景?
	JavaBean实体类,只负责封装数据,而把数据处理的操作放在其他类中,以实现数据和数		据处理相分离。

九、成员变量和局部变量的区别

各位同学,面向对象的基础内容咱们已经学习完了。同学们在面向对象代码时,经常会把成员变量和局部变量搞混。所以现在我们讲一讲他们的区别。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I1s40T8f-1689819787643)(assets/1662353340190.png)]

如下图所示,成员变量在类中方法外,而局部变量在方法中。

在这里插入图片描述


到这里,我们关于面向对象的基础知识就学习完了。面向对象的核心点就是封装,将数据和数据的处理方式,都封装到对象中; 至于对象要封装哪些数据?对数据进行怎样的处理? 需要通过类来设计。

需要注意的是,不同的人,对同一个对象进行设计,对象封装那些数据,提供哪些方法,可能会有所不同;只要能够完成需求,符合设计规范,都是合理的设计。

十、匿名对象的使用

以当一个对象被创建之后,在调用该对象的方法时,也可以不定义对象的引用变量(也就是没有变量名),而直接调用这个对象的方法,这样的对象叫做匿名对象。

示例:

将
      Cylinder volu=new Cylinder();
      volu.SetCylinder(2.5, 5,3.14);
改写为:
      new Cylinder().SetCylinder(2.5, 5,3.14);
则Cylinder()就是匿名对象。

以使用匿名对象通常有如下两种情况:
如果对一个对象只需要进行一次方法调用。
将匿名对象做为实参传递给一个方法调用。
示例:

一个程序中有一个getSomeOne()方法要接收一个MyClass类对象作为参数,方法的定义如下:
    public static void getSomeOne (MyClass c)
    {
        ……
     }

​ 可以用下面的语句调用这个方法。

 getSomeOne(new MyClass( ) );  //此时的参数就是匿名对象

十一、面向对象综合案例

学习完面向对象的语法知识之后。接下来,我们做一个面向对象的综合案例——模仿电影信息系统。

需求如下图所示

1. 想要展示系统中全部的电影信息(每部电影:编号、名称、价格)

  	2. 允许用户根据电影的编号(id),查询出某个电影的详细信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UXpURphW-1689819787645)(assets/1662351774659.png)]

运行程序时,能够根据用户的选择,执行不同的功能,如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cFZcxLOM-1689819787646)(assets/1662351990387.png)]

按照下面的步骤来完成需求

1. 第一步:定义电影类

首先每一部电影,都包含这部电影的相关信息,比如:电影的编号(id)、电影的名称(name)、电影的价格(price)、电影的分数(score)、电影的导演(director)、电影的主演(actor)、电影的简介(info)。

为了去描述每一部电影,有哪些信息,我们可以设计一个电影类(Movie),电影类仅仅只是为了封装电影的信息,所以按照JavaBean类的标准写法来写就行。

public class Movie {
    
    
    private int id;
    private String name;
    private double price;
    private double score;
    private String director;
    private String actor;
    private String info;

    public Movie() {
    
    
    }

    public Movie(int id, String name, double price, double score, String director, String actor, String info) {
    
    
        this.id = id;
        this.name = name;
        this.price = price;
        this.score = score;
        this.director = director;
        this.actor = actor;
        this.info = info;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public double getPrice() {
    
    
        return price;
    }

    public void setPrice(double price) {
    
    
        this.price = price;
    }

    public double getScore() {
    
    
        return score;
    }

    public void setScore(double score) {
    
    
        this.score = score;
    }

    public String getDirector() {
    
    
        return director;
    }

    public void setDirector(String director) {
    
    
        this.director = director;
    }

    public String getActor() {
    
    
        return actor;
    }

    public void setActor(String actor) {
    
    
        this.actor = actor;
    }

    public String getInfo() {
    
    
        return info;
    }

    public void setInfo(String info) {
    
    
        this.info = info;
    }
}

2. 第二步:定义电影操作类

前面我们定义的Movie类,仅仅只是用来封装每一部电影的信息。为了让电影数据和电影数据的操作相分离,我们还得有一个电影操作类(MovieOperator)。

因为系统中有多部电影,所以电影操作类中MovieOperator,需要有一个Movie[] movies; 用来存储多部电影对象;

同时在MovieOperator类中,提供对外提供,对电影数组进行操作的方法。如printAllMovies()用于打印数组中所有的电影信息,searchMovieById(int id)方法根据id查找一个电影的信息并打印。

public class MovieOperator {
    
    
    //因为系统中有多部电影,所以电影操作类中,需要有一个Movie的数组
    private Movie[] movies;
    public MovieOperator(Movie[] movies){
    
    
        this.movies = movies;
    }

    /** 1、展示系统全部电影信息 movies = [m1, m2, m3, ...]*/
    public void printAllMovies(){
    
    
        System.out.println("-----系统全部电影信息如下:-------");
        for (int i = 0; i < movies.length; i++) {
    
    
            Movie m = movies[i];
            System.out.println("编号:" + m.getId());
            System.out.println("名称:" + m.getName());
            System.out.println("价格:" + m.getPrice());
            System.out.println("------------------------");
        }
    }

    /** 2、根据电影的编号查询出该电影的详细信息并展示 */
    public void searchMovieById(int id){
    
    
        for (int i = 0; i < movies.length; i++) {
    
    
            Movie m = movies[i];
            if(m.getId() == id){
    
    
                System.out.println("该电影详情如下:");
                System.out.println("编号:" + m.getId());
                System.out.println("名称:" + m.getName());
                System.out.println("价格:" + m.getPrice());
                System.out.println("得分:" + m.getScore());
                System.out.println("导演:" + m.getDirector());
                System.out.println("主演:" + m.getActor());
                System.out.println("其他信息:" + m.getInfo());
                return; // 已经找到了电影信息,没有必要再执行了
            }
        }
        System.out.println("没有该电影信息~");
    }
}

3. 第三步:定义测试类

最后,我们需要在测试类中,准备好所有的电影数据,并用一个数组保存起来。每一部电影的数据可以封装成一个对象。然后把对象用数组存起来即可。

public class Test {
    
    
    public static void main(String[] args) {
    
    
        //创建一个Movie类型的数组
        Movie[] movies = new Movie[4];
        //创建4个电影对象,分别存储到movies数组中
        movies[0] = new Movie(1,"水门桥", 38.9, 9.8, "徐克", "吴京","12万人想看");
        movies[1] = new Movie(2, "出拳吧", 39, 7.8, "唐晓白", "田雨","3.5万人想看");
        movies[2] = new Movie(3,"月球陨落", 42, 7.9, "罗兰", "贝瑞","17.9万人想看");
        movies[3] = new Movie(4,"一点就到家", 35, 8.7, "许宏宇", "刘昊然","10.8万人想看");
        
    }
}

准备好测试数据之后,接下来就需要对电影数据进行操作。我们已经把对电影操作先关的功能写到了MovieOperator类中,所以接下来,创建MovieOperator类对象,调用方法就可以完成相关功能。

继续再main方法中,接着写下面的代码。

// 4、创建一个电影操作类的对象,接收电影数据,并对其进行业务处理
MovieOperator operator = new MovieOperator(movies);
Scanner sc = new Scanner(System.in);
while (true) {
    
    
    System.out.println("==电影信息系统==");
    System.out.println("1、查询全部电影信息");
    System.out.println("2、根据id查询某个电影的详细信息展示");
    System.out.println("请您输入操作命令:");
    int command = sc.nextInt();
    switch (command) {
    
    
        case 1:
            // 展示全部电影信息
            operator.printAllMovies();
            break;
        case 2:
            // 根据id查询某个电影的详细信息展示
            System.out.println("请您输入查询的电影id:");
            int id = sc.nextInt();
            operator.searchMovieById(id);
            break;
        default:
            System.out.println("您输入的命令有问题~~");
    }
}

到这里,电影信息系统就完成了。 小伙伴们,自己尝试写一下吧!!

猜你喜欢

转载自blog.csdn.net/whirlwind526/article/details/131824466