Lesson09_类和对象

36 篇文章 0 订阅
33 篇文章 0 订阅

Lesson09_类和对象

面向过程和面向对象

​ 面向过程(Procedure Oriented)和面向对象(Object Oriented,OO)都是对软件分析、设计和开发的一种思想,它指导着人们以不同的方式去分析、设计和开发软件。早期先有面向过程思想,随着软件规模的扩大,问题复杂性的提高,面向过程的弊端越来越明显的显示出来,出现了面向对象思想并成为目前主流的方式。两者都贯穿于软件分析、设计和开发各个阶段,对应面向对象就分别称为面向对象分析(OOA)、面向对象设计(OOD)和面向对象编程(OOP)。C语言是一种典型的面向过程语言,Java是一种典型的面向对象语言。

面向过程思想思考问题时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。 这个适合简单任务,不需要过多协作的情况下。比如,如何开车?我们很容易就列出实现步骤:1. 发动车 2. 挂挡 3.踩油门 4. 走你

​ 面向过程适合简单、不需要协作的事务。 但是当我们思考比较复杂的问题,比如“如何造车?”,就会发现列出1234这样的步骤,是不可能的。那是因为,造车太复杂,需要很多协作才能完成。此时面向对象思想就应运而生了。

面向对象(Object)思想更契合人的思维模式。我们首先思考的是“怎么设计这个事物?” 比如思考造车,我们就会先思考“车怎么设计?”,而不是“怎么按步骤造车的问题”。这就是思维方式的转变。

一、面向对象思想思考造车,发现车由如下对象组成:

1. 轮胎

2. 发动机

3. 车壳

4. 座椅

5. 挡风玻璃

为了便于协作,我们找轮胎厂完成制造轮胎的步骤,发动机厂完成制造发动机的步骤;这样,发现大家可以同时进行车的制造,最终进行组装,大大提高了效率。但是,具体到轮胎厂的一个流水线操作,仍然是有步骤的,还是离不开面向过程思想!

因此,面向对象可以帮助我们从宏观上把握、从整体上分析整个系统。 但是,具体到实现部分的微观操作(就是一个个方法),仍然需要面向过程的思路去处理。

我们千万不要把面向过程和面向对象对立起来。他们是相辅相成的。面向对象离不开面向过程!

  • 面向对象和面向过程的总结
    • 都是解决问题的思维方式,都是代码组织的方式。
    • 解决简单问题可以使用面向过程
    • 解决复杂问题:宏观上使用面向对象把握,微观处理上仍然是面向过程。
  • 面向对象思考方式
    • 遇到复杂问题,先从问题中找名词,然后确立这些名词哪些可以作为类,再根据问题需求确定的类的属性和方法,确定类之间的关系。
  • 建议
    • 面向对象具有三大特征:封装性、继承性和多态性,而面向过程没有继承性和多态性,并且面向过程的封装只是封装功能,而面向对象可以封装数据和功能。所以面向对象优势更明显。
    • 一个经典的比喻:面向对象是盖浇饭、面向过程是蛋炒饭。盖浇饭的好处就是“菜”“饭”分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是“可维护性”比较好,“饭” 和“菜”的耦合度比较低。

对象的进化史

  • 数据无管理时代
    • 最初的计算机语言只有基本变量(类似我们学习的基本数据类型),用来保存数据。那时候面对的数据非常简单,只需要几个变量即可搞定;这个时候不涉及“数据管理”的问题。
    • 同理,就像在企业最初发展阶段只有几个人,不涉及管理问题,大家闷头做事就OK了。
  • 数组管理和企业部门制
    • 企业发展中,员工多了怎么办?我们很自然的想法就是归类,将类型一致的人放到一起;企业中,会将都做销售工作的放到销售部管理;会将研发软件的放到开发部管理
    • 同理在编程中,变量多了,我们很容易的想法就是“将同类型数据放到一起”, 于是就形成了“数组”的概念,单词对应“array”。 这种“归类”的思想,便于管理数据、管理人。
  • 对象和企业项目制
    • 企业继续发展,面对的场景更加复杂。一个项目可能需要经常协同多个部门才能完成工作;一个项目从谈判接触可能需要销售部介入;谈判完成后,需求调研开始,研发部和销售部一起介入;开发阶段需要开发部和测试部互相配合敏捷开发,同时整个过程财务部也需要跟进。在企业中,为了便于协作和管理,很自然就兴起了“项目制”,以项目组的形式组织,一个项目组可能包含各种类型的人员。 一个完整的项目组,麻雀虽小五脏俱全,就是个创业公司甚至小型公司的编制,包含行政后勤人员、财务核算人员、开发人员、售前人员、售后人员、测试人员、设计人员等等。事实上,华为、腾讯、阿里巴巴等大型公司内部都是采用这种“项目制”的方式进行管理。
    • 同理,计算机编程继续发展,各种类型的变量更加多了,而且对数据的操作(指的就是方法,方法可以看做是对数据操作的管理)也复杂了,怎么办?
    • 为了便于协作和管理,我们“将相关数据和相关方法封装到一个独立的实体”,于是“对象”产生了。 比如,我们的一个学生对象:
      • 属性:年龄、姓名、学号
      • 行为:学习、吃饭、考试
  • 总结
    • 对象说白了也是一种数据结构(对数据的管理模式),将数据和数据的行为放到了一起。
    • 在内存上,对象就是一个内存块,存放了相关的数据集合!
    • 对象的本质就一种数据的组织方式!

什么是类、什么是对象(举例)

  • 我们人认识世界,其实就是面向对象的(此对象可不是男女谈对象的彼对象呀)。比如现在让大家认识一下“龙”这个新事物,什么样的物种是龙呢,我们都没有见过实体,但是
  • 通过图片的认知,得知龙像蛟,有鱼鳞、鹿角等,那么我们只是看了几张图片,但是下次看到不同的图片依然人数。我们就死通过他们都具体的特性来认识的,也就是我们将初始的几个具体的个体,进行抽象。抽象出了一个龙的类,而我们后面见到的就是它的一个具体的个体。
  • 我们将类可以看做是一个模版,或者图纸,系统根据类的定义来造出对象。我们要造一个汽车,怎么样造?类就是这个图纸,规定了汽车的详细信息,然后根据图纸将汽车造出来。
  • 类:我们叫做class。对象我们叫做object或instance(实例),以后我们说起某个类的对象或某个类的实例,都是一样。
  • 总结:
    • 对象是具体的事物;类是对对象的抽象;
    • 类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
    • 类是用于描述同一类型的对象的一个抽象概念,类中定义了这一类对象所应具有的共同的属性、方法。
类					对象(实例)
手机				大海手里的荣耀5c
风扇				航天大厦53教前面的美的立式摇头扇
哈士奇			   吕锦幸枕边的那条二哈
计算机语言		  Java
笔				张诗楠手中旋转的那支中性笔
女朋友			   张超现在的女朋友
衣服				我穿的这件衣服
菜				何宇晨中午吃的第一盘宫保鸡丁
教室				航天大厦5层海同3教
电脑				钟瀚文面前的那台电脑
充电宝				我手中的充电宝
电脑包				孙杰左边的电脑包
乐器				吴家为20181111日花3w块钱买的那把小提琴
水杯				铮手里的水杯
星系				银河系
灯				孙海生头顶的那个灯棍
插座				讲台的插座
钱				黎焱钱包里唯一的那张十元钱
投影仪				航天大厦5层海同科技3教的投影仪
腾讯游戏			LOL
地铁站				上海市1号线漕宝路地铁站
软件				QQ v9.0.7
人				吴生有
音乐				beyond 海阔天空
飞机				凌佳文后院的歼-20
网址				吕锦幸刚刚发到群里的**链接
歌手				周杰伦
  • 类的定义

    • 类名

    • 属性(Field) 状态 n. 身高、体重、年龄、分数、性别、状态、段位、薪水

      • 属性用于定义该类或该类对象包含的数据或者说静态特征。属性作用范围是整个类体。

      • 在定义成员变量时可以对其初始化,如果不对其初始化,Java使用默认的值对其初始化。

      • 格式:

        [修饰符]  属性类型  属性名 = [默认值] ;
        
    • 方法(Method) 行为 v. 吃、睡、学习、玩

      • 方法用于定义该类或该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象。方法很类似于面向过程中的函数。面向过程中,函数是最基本单位,整个程序由一个个函数调用组成。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。
      • 定义格式
      [修饰符]  方法返回值类型  方法名(形参列表) {
          // n条语句
      }
      
    • 第一个类的定义

      实际上属性与行为与类的关系是直接属于类的,均称成员,成员变量,成员方法。以及后面会学习到成员内部类。

      public class SxtStu {
          //属性(成员变量)
          int id;
          String sname;
          int age;  
          //方法
          void study(){
              System.out.println("我正在学习!");
          }  
          //构造方法
         SxtStu(){
         }
      }
      
  • 对象的定义

    • 我们前面了解到类的创建,知道类的建模是一个抽象和封装的过程。
      • 抽象:去掉不关注的、次要的信息而保留重要的信息。
      • 封装:信息打包
      • 简单的来说,类的创建就是讲抽象出来的属性和行为包装在一个类中。封装相关的知识我们会在后面详细的讲解
    • 类中定义事物的属性和行为。而对象是通过描述的这个类,使用new关键字创建出来,通过对象就可以调用该对象具体的属性和功能了。
    • 对象是对类的一种具体化的客观存在,是对类的具体实例化。
    • 前面我们提到类可以理解为是某一类事物的抽象的模子,那对象就是这个模子实实在在的东西,比如说手机模子是一个类,那我们手中的手机就是一个实实在在的对象。
    • java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。对象即是该类事物实实在在存在的个体
    • 对象的创建
      • new 构造方法
  • 成员访问符

    • . 看上去是个小数点,其实就是小数点,含义不同:访问成员的符号——成员访问符
    • 属性、方法都是成员
  • 总结

    • 通过代码的描述,知道类的真正意义就是在描述事物。属性和功能统称为事物中的成员。 事物的成员分为两种:成员属性和成员功能。
    • 成员属性在代码中的体现就是成员变量
    • 成员功能在代码中的体现就是成员方法
    • 但是在这个类中没有主方法,无法独立运行。把写好的代码测试一下。需要一个可以独立运行类。
  • 类和对象的区别

    • 类是静态的定义,对象是动态的实列;
    • 程序代码操作的是对象而非类;
    • 建模得到的是类而非对象。
  • 类和对象的联系

    • 类是对象的定义;
    • 对象的产生离不开类这个模板;
    • 类存在的目的是为了实例化对象,或者类存在的目的是实例化得到对象。
  • 思考:先有类还是先有对象

    • 从我们人类的思维上来看,是先有对象后有类。人类认知过程,从不同对象中抽取出共同特征,忽略次要的信息。(会喵喵叫的是猫,和毛色没有关系),直观上来讲,类是有不同对象“组成的”。先有了对象之后,才会有对象“组成”类。
    • 从计算机的思维来看,是先有类后有对象,我们从前面了解到,类的存在的目的是实例化得到对象。说明是先有类后有对象的。
  • 类名作为形参和返回值,创建学生类与老师类实现。

变量作用域

  • 成员变量
    • 定义在类中,跟随对象,随着对象的创建而创建,消失而消失
    • 默认初始化,存在于对象的堆内存中
  • 局部变量
    • 定义在方法或语句块内部出作用域自动释放内存
    • 不会默认初始化,存在于栈中
  • 区别
    • 定义的位置不同定义在类中的变量是成员变量 定义在方法中或者{}语句里面的变量是局部变量。
    • 在内存中的位置不同 成员变量存储在对内存的对象中
      局部变量存储在栈内存的方法中。
    • 声明周期不同成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失 局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失。
    • 初始化不同成员变量因为在堆内存中,所有默认的初始化值 局部变量没有默认的初始化值,必须手动的给其赋值才可以使用

从声明的位置开始,到它所在的花括号结束。

这个范围叫做该变量的作用域。

出了这个范围,不可以访问该变量。

String创建和常见方法(P33)

  • String的创建

    • 字符串常量赋值

      String s1 = "abc";
      
    • new

      String s3 = new String("abc");
      
  • 注意

    • 直接赋值:String s=“123456”;先查找字符串池中是否有该字符串,若没有则创建一个对象,并返回。若有此字符串直接返回。【创建1个对象】
    • new创建:String s=new Stirng(“123456”);先查找字符串池中是否有该字符串,若有直接在堆中new一个对象并返回,没有就在字符串中先创建一个,然后再在堆中new一个返回。【创建2个对象】
    • +连接两个字符串:String s=“123”+“456”;分别判断字符串“123”和"456"在字符串池中是否存在,若不存在就创建一个。然后判断连接后的字符"123456"在字符串池中是否存在,若不存在就创建。【3个对象】
  • 总结:

    • String对象是不可变的
    • 类中每个看来会修改String值的方法,其实都创建了String对象(包含修改后的字符串内容)
    • String的只读特性使代码执行效率别较高
    • 字符串字面值存储于字符串池中,String对象优先指向字符串池,避免反复生成重复的字符串实例
    • 系统对字符串的非修改处理效率很高,远远高于另外两个字符串类StringBuilder和StringBuffer(后面会详细讲解)
  • 常用方法

    • length()

      String str  = "abc defg";//返回字符串长度
      System.out.println(str.length()); // 8
      
    • charAt(int index)

      char c = str.charAt(0); // 返回指定索引出处的char值 [0,str.length()-1]
      
    • concat(String str)

      String s2 = "abc";
      System.out.println(s2.concat("abc"));//将指定字符串连接到此字符串结尾
      
    • contains(xxx)**

      boolean res = str.contains("def");// 判断字符串str中是否包含"def"
      
    • equals(xxx)

      boolean res = str.equals("三国演义");// 比较字符串的内容是否相同
      
    • compareTo(xxx)

      String s1 = "a";
      String s2 = "abc";
      int res = s1.compareTo(s2); // 比较字符串的大小,按字典顺序比较
      System.out.println(res);
      /* 
      	res > 0;   s1 > s2
      	res == 0;  s1 == s2
      	res < 0;   s1 < s2
      */
      
      // addition:用冒泡算法对String[]升序排序
      String[] strs = {"EDG","IG","QGHappy","C9","LGD","RNG","OMG"};
      
    • indexOf(xxx)

      String str = "javaabc666java686java";
      int index = str.indexOf("java");// 0  从前往后数,第一次出现"java"的下标
      
    • lastIndexOf(xxx)

      String str = "javaabc666java686java";
      int index = str.lastIndexOf("java");//17 从后往前数,第一次出现"java"的下标
      
    • split(xxx)

      String str = "javaabc666java666java";
      String[] ss = str.split("666");
      for(int i = 0; i < ss.length; i ++){
          System.out.println("["+ss[i]+"]");
      }
      // 结果为:[javaabc] [java] [java]
      
      //--------------注意以下的坑-----------------
      String str = "javajavajavaabc666java666javajavajava";
      String[] ss = str.split("java");
      for(int i = 0; i < ss.length; i ++){
          System.out.println("["+ss[i]+"]");
      }
      // 结果为:[] [] [] [abc666] [666]
      
    • substring(int beginIndex, int endIndex)

      String str = "abcdefghijklmn";
      String substr = str.substring(6,10); // [6,10) 截取字符串的某一个区间
      System.out.println(substr);// ghij
      
    • toLowerCase() / toUpperCase()

      String res = str.toUpperCase(); // 把str的小写字符变为大写,将结果返回给res,注意,str本身不发生任何变化
      System.out.println("res = "+res); // res = ABCDEFGHIJKLMN
      System.out.println("str = "+str); // str = abcdefghijklmn
      
    • replace(xxx,xxx)

      String str = "java.test.hello666java.java";
      str = str.replace("java","kotlin"); // 把"java"替换为"kotlin"
      System.out.println(str);
      
    • startsWith(xxx)

      String str = "java.test.hello666java.java";
      boolean res = str.startsWith("java"); // 判断str是否是以"java"开头
      
    • endsWith(xxx)

      String str = "java.test.hello666java.java";
      boolean res = str.endsWith(".java"); // 判断str是否是以".java"结尾
      
    • trim()

      String str = "  abc def 666    ";
      str = str.trim(); // 去掉开头和结尾的空白(ASCII小于等于32的字符),中间的空白会保留
      System.out.println("["+str+"]");
      

面向对象优点(封装)

  • 面向对象思维方式是一种更符合人们思考习惯的思想面向对象思维方式是一种更符合人们思考习惯的思想
  • 面向过程思维方式中更多的体现的是执行者(自己做事情),面向对象中更多的体现是指挥者(指挥对象做事情)。
  • 面向对象思维方式将复杂的问题简单化。
  • 封装 --> 类 --> 对象
  • 信息隐藏
  • 可复用
  • 世界万物皆对象
  • 面向对象具有的特征:
    • 封装
    • 继承
    • 多态

Java内存

    • 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
    • JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
    • 栈属于线程私有,不能实现线程间的共享!
    • 栈的存储特性是“先进后出,后进先出”
    • 栈是由系统自动分配,速度快!栈是一个连续的内存空间!
    比较小,几M,方法调用时立刻开辟空间,方法结束时,立刻释放空间。
    
    • 堆用于存储创建好的对象和数组(数组也是对象)
    • JVM只有一个堆,被所有线程共享
    • 堆是一个不连续的内存空间,分配灵活,速度慢!
    比较大,几百M~G,创建对象时,在堆空间开辟,对象不再被引用时,该对象会被标记为垃圾,等待垃圾回收器的回收。申请和释放的效率比栈空间低很多。
    只要是new出来的对象,都是在堆空间中,数组也是在堆里。(将来可能会有变动)
    
  • 方法区

    • JVM只有一个方法区,被所有线程共享!
    • 方法区实际也是堆,只是用于存储类、常量相关的信息!
    • 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)
    存储的是类的信息(元数据),这个类中有哪些属性,哪些方法,父类是谁,直接父接口是谁……
    .class文件加载到内存中的对象
    常量池
    
  • 内存分配示例图

    1.png

    neicunfenxi.png

    垃圾回收机制(Garbage Collection)

    Java引入了垃圾回收机制,令C++程序员最头疼的内存管理问题迎刃而解。Java程序员可以将更多的精力放到业务逻辑上而不是内存管理工作上,大大的提高了开发效率。

    • 内存管理
      • Java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放。
      • 对象空间的分配:使用new关键字创建对象即可
      • 对象空间的释放:将对象赋值null即可。垃圾回收器将负责回收所有”不可达”对象的内存空间。
    • 垃圾回收过程
      • 任何一种垃圾回收算法一般要做两件基本事情:
      • 发现无用的对象
      • 回收无用对象占用的内存空间。
      • 垃圾回收机制保证可以将“无用的对象”进行回收。无用的对象指的就是没有任何变量引用该对象。Java的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。
    • 垃圾

      不再被引用的对象,就会被标记为"垃圾"
      Cat cat = new Cat("小白",2,"白色");
      cat = new Cat("小黑",5,"黑色"); // 此时,上一行的白猫在堆中无人问津,就会被标记为垃圾
      
    • 垃圾回收相关算法

      • 引用计数法

        堆中每个对象都有一个引用计数。被引用一次,计数加1. 被引用变量值变为null,则计数减1,直到计数为0,则表示变成无用对象。优点是算法简单,缺点是“循环引用的无用对象”无法别识别。s1和s2互相引用对方,导致他们引用计数不为0,但是实际已经无用,但无法被识别。

      • 引用可达法

        程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。

    • 总结

      • 垃圾回收器只能回收“”空间中的垃圾
      • 垃圾回收器不具有实时性,可以通过System.gc()催一下垃圾回收器快来回收,但是要看它心情。实际就是通知JVM,但具体什么时候做就不知道。
      • finalize方法,是Java提供给程序员用来释放对象或资源的方法,但是尽量少用。
    • 通用的分代垃圾回收机制

      • 分代垃圾回收机制,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。我们将对象分为三种状态:年轻代、年老代、持久代。JVM将堆内存划分为 Eden、Survivor 和 Tenured/Old 空间。

        1. 年轻代

          所有新生成的对象首先都是放在Eden区。 年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是Minor GC,每次 Minor GC 会清理年轻代的内存,算法采用效率较高的复制算法,频繁的操作,但是会浪费内存空间。当“年轻代”区域存放满对象后,就将对象存放到年老代区域。

        2. 年老代

          在年轻代中经历了N(默认15)次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。年老代对象越来越多,我们就需要启动Major GC和Full GC(全量回收),来一次大扫除,全面清理年轻代区域和年老代区域。

        3. 持久代

          用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著影响。

      • 垃圾清理

        1. Minor GC:用于清理年轻代区域。Eden区满了就会触发一次Minor GC。清理无用对象,将有用对象复制到“Survivor1”、“Survivor2”区中(这两个区,大小空间也相同,同一时刻Survivor1和Survivor2只有一个在用,一个为空)
        2. Major GC:用于清理老年代区域。
        3. Full GC:用于清理年轻代、年老代区域。 成本较高,会对系统性能产生影响。
      • 垃圾回收过程

        1. 新创建的对象,绝大多数都会存储在Eden中,
        2. 当Eden满了(达到一定比例)不能创建新对象,则触发垃圾回收(GC),将无用对象清理掉,然后剩余对象复制到某个Survivor中,如S1,同时清空Eden区
        3. 当Eden区再次满了,会将S1中的不能清空的对象存到另外一个Survivor中,如S2,
        4. 同时将Eden区中的不能清空的对象,也复制到S1中,保证Eden和S1,均被清空。
        5. 重复多次(默认15次)Survivor中没有被清理的对象,则会复制到老年代Old(Tenured)区中,
        6. 当Old区满了,则会触发一个一次完整地垃圾回收(FullGC),之前新生代的垃圾回收称为(minorGC)
      • 回收算法

        定期扫描,将没有被引用的对象加上标记,统一清除
        对象数组

        1. 标记-清除
        2. 标记整理
    • JVM调优

      对JVM调优的过程中,很大一部分工作就是对于Full GC的调节。有如下原因可能导致Full GC:

      1. 年老代(Tenured)被写满
      2. 持久代(Perm)被写满
      3. System.gc()被显式调用(程序建议GC启动,不是调用GC)
      4. 上一次GC之后Heap的各域分配策略动态变化
    • 开发中容易造成内存泄漏的操作

      • 创建大量无用对象
      • 静态集合类的使用,如HashMap、Vector等
      • 各种连接对象,如IO流、数据库连接对象,网络连接等
      • 监听器的使用,释放对象时,没有删除相应的监听器。

总结

  1. 面向对象可以帮助我们从宏观上把握、从整体上分析整个系统。 但是具体到实现部分的微观操作(就是一个个方法),仍然需要面向过程的思路去处理。
  2. 类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
  3. 对于一个类来说,一般有三种常见的成员:属性field、方法method、构造器constructor。
  4. 构造器也叫构造方法,用于对象的初始化。构造器是一个创建对象时被自动调用的特殊方法,目的是对象的初始化。构造器的名称应与类的名称一致。
  5. Java引入了垃圾回收机制,令C++程序员最头疼的内存管理问题迎刃而解。Java程序员可将更多的精力放到业务逻辑上而不是内存管理工作,大大提高开发效率。

作业

一、选择题

  1. 以下语句中关于Java构造方法的说法错误的是( )。(选择一项)

    A.构造方法的作用是为创建对象进行初始化工作,比如给成员变量赋值

    B.一个Java类可以没有构造方法,也可以提供1个或多个构造方法

    C.构造方法与类同名,不能书写返回值类型

    D.构造方法的第一条语句如果是super(),则可以省略,该语句作用是调用父类无参数的构造方法

  2. 在Java中,以下程序编译运行后的输出结果为( )。(选择一项)

    public class Test {
        int x, y;
        Test(int x, int y) {
            this.x = x;
            this.y = y;
        }
        public static void main(String[] args) {
            Test pt1, pt2;
            pt1 = new Test(3, 3);
            pt2 = new Test(4, 4);
            System.out.print(pt1.x + pt2.x);
        }
    }
    

    A.6 B.34 C.8 D.7

  3. 在Java中关于静态方法,以下说法中正确的是( )。(选择二项)

    A.静态方法中不能直接调用非静态方法

    B.非静态方法中不能直接调用静态方法

    C.静态方法可以用类名直接调用

    D.静态方法里可以使用this

  4. 下列选项中关于Java中类方法的说法错误的是( )。(选择二项)

    A.在类方法中可用this来调用本类的类方法

    B.在类方法中调用本类的类方法时可直接调用

    C.在类方法中只能调用本类中的类方法

    D.在类方法中调用实例方法需要先创建对象

  5. 分析如下Java程序的代码所示,则编译运行后的输出结果是( )。(选择一项)

    public class Test {
        int count=9;
        public void count1(){
            count=10;
            System.out.print("count1="+count);
        }
        public void count2(){
            System.out.print("count2="+count);
        }
        public static void main(String[ ] args) {
            Test t=new Test();
            t.count1();
            t.count2();
        }
    }
    

    A.count1=9; count2=9;

    B.count1=10;count2=9;

    C.count1=10; count2=10;

    D.count1=9; count2=10;

二、简答题

  1. 面向过程和面向对象的区别。
  2. 类和对象的关系
  3. 构造方法的作用和特征
  4. this关键字的作用和用法
  5. 简述static关键字的作用。

三、代码题

  1. 编写 Java 程序_用于显示人的姓名和年龄。定义一个人类Person。 该类中应该有两个私有属性: 姓名 (name) 和年龄 (age) 。定义构造方法用来初始化数据成员。再定义显示(display()) 方法将姓名和年龄打印出来。在 main 方法中创建人类的实例然后将信息显示。

  2. 定义一个圆类——Circle,在类的内部提供一个属性:半径®,同时 提供 两个 方 法 : 计算 面积 ( getArea() ) 和 计算 周长(getPerimeter()) 。 通过两个方法计算圆的周长和面积并且对计算结果进行输出。最后定义一个测试类对 Circle 类进行使用。

  3. 构造方法与重载:定义一个网络用户类,信息有用户 ID、用户密码、 email 地址。在建立类的实例时把以上三个信息都作为构造函数的参数输入, 其中用户 ID 和用户密码时必须缺省时 email地址是用户 ID 加上字符串"@gameschool.com"。

  4. 定义“书”类,Book,包含以下成员:

    名称,作者,出版社,出版日期(String),单价,成员方法有showMe方法,打印出所有属性的值。

;

二、简答题

  1. 面向过程和面向对象的区别。
  2. 类和对象的关系
  3. 构造方法的作用和特征
  4. this关键字的作用和用法
  5. 简述static关键字的作用。

三、代码题

  1. 编写 Java 程序_用于显示人的姓名和年龄。定义一个人类Person。 该类中应该有两个私有属性: 姓名 (name) 和年龄 (age) 。定义构造方法用来初始化数据成员。再定义显示(display()) 方法将姓名和年龄打印出来。在 main 方法中创建人类的实例然后将信息显示。

  2. 定义一个圆类——Circle,在类的内部提供一个属性:半径®,同时 提供 两个 方 法 : 计算 面积 ( getArea() ) 和 计算 周长(getPerimeter()) 。 通过两个方法计算圆的周长和面积并且对计算结果进行输出。最后定义一个测试类对 Circle 类进行使用。

  3. 构造方法与重载:定义一个网络用户类,信息有用户 ID、用户密码、 email 地址。在建立类的实例时把以上三个信息都作为构造函数的参数输入, 其中用户 ID 和用户密码时必须缺省时 email地址是用户 ID 加上字符串"@gameschool.com"。

  4. 定义“书”类,Book,包含以下成员:

    名称,作者,出版社,出版日期(String),单价,成员方法有showMe方法,打印出所有属性的值。

预习

封装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
输入: 201 202 203 1 zhang 67 88 92 2 li 44 77 99 3 wang 76 82 95 4 zhao 63 82 86 输出: Student wang got the highest average score as 84.3333 Student li got the lowest average score as 73.3333 Student id:3 Student name:wang lesson_id 201 202 203 Average scores 76 82 95 84.3333 The student didn't fail. ------华丽的分割线-------- Student id:1 Student name:zhang lesson_id 201 202 203 Average scores 67 88 92 82.3333 The student didn't fail. ------华丽的分割线-------- Student id:4 Student name:zhao lesson_id 201 202 203 Average scores 63 82 86 77 The student didn't fail. ------华丽的分割线-------- Student id:2 Student name:li lesson_id 201 202 203 Average scores 44 77 99 73.3333 The student failed. ------华丽的分割线-------- 程序部分代码如下,请补充完整。 #include <iostream> #include <iomanip> #include <string.h> #include <cmath> #define M 3 // 课程门数 #define N 4 //学生数组中的学生个数 using namespace std; class Student { public: Student() {} Student(const Student&); void input_info() { cin>>id; cin>>name; for(int i=0; i<3; i++) cin>>score[i]; isFail=false; for(int i=0; i<3; i++) if(score[i]<60) isFail=true; } void input_lesson_ids() { for(int i=0; i<M; i++) cin>>lesson_id[i]; } void show_info() { cout<<"Student id:"<<id<<endl; cout<<"Student name:"<<name<<endl; cout<<setw(10)<<"lesson_id "; for(int i=0; i<M; i++) cout<<setw(10)<<lesson_id[i]; cout<<setw(10)<<"Average"; cout<<endl; cout<<setw(10)<<"scores "; for(int i=0; i<M; i++) cout<<setw(10)<<score[i]; cout<<setw(10)<<ave(); cout<<endl; if(isFail) cout<<"The student failed."<<endl; else cout<<"The student didn\'t fail."<<endl; cout<<"------华丽的分割线--------"<<endl; } float ave()//求平均成绩 { //实现求平均成绩并返回 ...... } string get_name() { return name; } private: int id; string name; bool isFail; static int lesson_id[M]; float score[M]; }; int Student::lesson_id[M]; Student::Student(const Student& s) { //完成拷贝构造函数的实现,拷贝出的对象和原对象一致 ...... } int main() { Student cs[N]; cs[0].input_lesson_ids();// 用一个学生对象对静态数组成员赋值 for(int i=0; i<N; i++) cs[i].input_info(); //求出最高平均成绩并按要求格式输出相关语句 ...... //求出最低平均成绩并按要求格式输出相关语句 ...... //按照平均成绩的高低对学生数组进行排序 ...... for(int i=0; i<N; i++)//输出排序后的结果 cs[i].show_info(); return 0; }
最新发布
06-07

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值