20145221《Java程序设计》第四章-认识对象 总结

教材学习内容总结

类与对象

  • 定义:对象是Java语言中重要的组成部分,之前学过的C语言是面向过程的,而Java主要是面向对象的。Java中变量有2种类型,一个是基本类型,另一个则是类类型。使用Java撰写程序几乎都是在使用对象,要产生对象必须先定义类,类是对象的设计图,对象是类的实例。
  • 特点:
  1. 有别于C语言的程序编写,在用Java编写中,如果需要什么功能,我们就可去找一个对象,而这个对象就包含这个功能,然后通过new建立对象,通过“.”来调用该类的一些功能。
  2. 其中要能理解对象的含义,例如Clothes c1 = new Clothes();,其中c1是在栈内存中产生,而对象c1则是产生在堆内存中,c1可以近似看成指向堆内存中的指针。
  3. 书上提供了一个很好的方法正确理解其中的本质,那就是画图,形象又直观,所以在涉及对对象的理解时,一是可以画图,二是可以把相关代码贴在电脑上运行一下。还有一些常用的标准类Scanner,BigDecimal等都大大方便了我们编程过程。
  • 注意:对象相等性,首先要明白对于类类型的变量来说==和基本类型中的==有本质上的区别,因为是类类型,所以==表示的是这个类产生的2个对象是否是同一个对象,如果是同一个对象,那么==的返回值才是true,否则为false;如果想要比较2个对象的内含值,应该要用a.equals(b);。其实理解其最好的方法就是画图,例如课本P89页中的代码,以及后面相关知识的介绍,都是通过画图来理解的。

基本类型打包器

  • 概述:在上一章已经学习了基本类型的变量,但是对于Java程序语言来说,基本类型的变量效率往往不高效,Java的特点在于面向对象,所以我们也可以把这些基本类型的变量打包成对象之中,这样我们就可以像操作对象那样操作这些原本是“基本类型”的变量了。
  • 特点:
  1. 开始在学习这一节内容的时候,不能理解,明明是基本类型了,为什么还要把大费周章地又打包成类类型。在最后编写本章的操作题时,我就明白了,编写Java时一定要把固有的“面向过程”的思想转化为“面向对象”,对象可以提供我们许多功能,简化我们的编程,这在后续学习中会更加明白。
  2. 除了打包,J2SE 5.0之后,还能自动装箱、自动拆箱,在我的理解看来,就是不需要严格的像一般建立对象那样,可以简便一些(自动装箱与拆箱的功能事实是编译程序蜜糖),例如:
Integer wrapper = 10;    // 自动装箱
int foo = wrapper; // 自动拆箱
  • 注意:既然打包为了对象,当然也要满足对象的特点,尤其是判断“相等”。作为编程者,一定要弄明白我们的目的。在建立对象之后,如果是想比较这2个对象的内含值,则一定一定要使用a.equals(b);这种形式的比较方式,只要把握了这一点,就可以避免课本P97这样的错误。

数组对象

  • 概述:数组在Java中就是对象,牢牢把握这个概念。
  • 特点:对象的一些特点性质都可以在数组中使用。定义数组的方法,如果知道是哪些具体的数,则可以如课本P95一样,不知道具体的数可以像P98一样。在定义二维数组时,也可以仿照一维数组进行定义,总之,数组就是对象,这是数组最大的特点。
  • 注意:
  1. 既然数组是对象,那么对象需要注意的性质,数组都要注意。对于数组本身来说,不能超过其索引范围,不然会报错:ArrayIndexOutOfBoundsException(编译时不会报,运行时会报错)。
  2. 注意各种类型的数组初值情况(课本P98)。
  3. 再就是要理解二维数组的本质,二维数组,其实是在数组的基础上对于每个元素,再建立一个数组(对象),只是在很多编程实例中体现出了“二维”、“矩阵”等形式,本质还是在数组的每个元素上再建立数组。认识到这一点,加上课本的图4.5、4.6、4.7、4.8理解起来就容易多了。
  4. 数组的复制,首先由2个方法可以用System.arraycopy()Arrays.copyof(),可以通过这些类快速复制一个数组,不过在调用时要注意括号中参变量的含义,类型内容都要一致。在使用了上述方法后,要明白一点我们进行的都是“浅层复制”,是没有连同对象一起复制的。如果想要深层复制,则需自己操作,敲代码完成自行复制元素,如课本P106。

字符串对象

  • 概述:字符串本质是打包字符数组的对象,是java.lang.String类的实例。
  • 特点:既然是对象,当然也会有很多功能,length(),charAt(),toUpperCase()等。通过一些方法Byte.parseByte(number)等还可以将字符串剖析为基本类型。
  • 注意:
  1. 字符串池:如果直接将一串字符指定给2个字符串变量,则这2个字符串变量会参考到同一对象。因为在Java中,为了效率考虑,只要""包括的字符串内容相同,无论在程序代码中出现多少次,JVM都只会建立一个String实例,并在字符串池中维护。
  2. 不可变动字符串:必须知道的是:在Java中,字符串对象一旦建立,就无法更改对象中的任何内容,对象上没有任何一个方法可以更改字符串内容。使用+字符可以达到这样的效果,不过根据反编译的过程,可以发现,实际上是产生了新的字符串对象。而大量的产生新对象又是不希望看到的,所以我们可以用StringBuilder来改善,它的特点在于每次调用完后都会返回原有的StringBuilder对象,这样可以避免产生多个对象。

查询Java API文件

  • 概述:从本章的实际操作题和课本上的范例程序中,都会发现每个程序几乎都使用了不同的类,如java.util.Scanner、java.math.BigDecimal、基本类型打包器等等。在以后的编程中,如果我们想用某一个类的某一功能,但不知道如何调用,或者想了解一下某一个类具体有哪种功能等内容,就必须要通过查询Java API文件了。
  • 方法:
  1. 通过Java官方网站
  2. 直接通过搜索引擎搜索相应的类,就会显示对应的文件说明了;
  3. 以上2种方法都是在线查询Java API文件,还可以离线查询。在Windows下可以下载CHM格式的Java API。如图,这样会更加的方便。

教材学习中的问题和解决过程

  1. 其实这一章内容开始不是很好理解,因为之前对对象没有一个概念。所以学的有点慢,但是按照老师说的方法,一个是认真看课本,另一个就是学编程必须要养成的习惯,勤敲代码。可能开始对书上给的一些代码,还不能理解,面对书上画的图,也不能透彻明白。但是好记性不如烂笔头,编程也一样,只要把这些代码敲一遍,编译运行一编,看看结果,这样印象可能会深一点,对于代码的领悟可能更也更好一些。

  2. 在最开始接触对象时,有一种感觉就是感觉“类”有点似曾相识,感觉和C语言中的结构体很像。不过我知道C语言是面向过程的,Java是面向对象的,所以我认为结构体和类还是应该有本质区别的。翻开原来的C语言书,发现结构体好像只是把不同类型的变量打包在了一个“新的类型变量中”,并不能在结构中定义功能,而类中还可以构造函数。类的功能应该更强大更灵活。

  3. 按照老师的指导,对书中P112的效率进行了测试:

    (1). 代码(只展示第一种,后两种只是将“测试代码段”用课本上的填充进去):

    public class TestJavaClass{
    public static void main(String[] args){
    //获取开始时间
    long startTime = System.currentTimeMillis();
    //测试代码段
    for(int i=1; i<101; i++){
    System.out.print(i);
    if(i != 100){
    System.out.print('+');
    }
    }
    System.out.println();
    //获取结束时间
    long endTime = System.currentTimeMillis();
    System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
    }
    }

    (2). 运行结果:

    第一种:

    第二种:

    第三种:

    (3). 结论:通过上述操作,确实可以发现第三种的效率最高。

代码调试中的问题和解决过程

课后操作题

Fibonacci数列:

  1. 代码:

    import java.util.Scanner;
    
    public class Fibonacci{
    public static void main(String[] args){
    System.out.printf("求几个费氏数?");
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    if(n == 1)
    System.out.print(0);
    else{
    int[] fiboNums = new int[n];
    fiboNums[1] = 1;
    System.out.print(0 + " " + 1);
    for(int i=2; i<n; i++){
    fiboNums[i] = fiboNums[i-2] + fiboNums[i-1];
    System.out.print(" " + fiboNums[i]);
    }
    }
    System.out.println();
    /*
    fiboNums[1] = 1;
    for(int i=2; i<n; i++){
    fiboNums[i] = fiboNums[i-2] + fiboNums[i-1];
    }
    for(int fiboNum : fiboNums){
    System.out.print(fiboNum + " ");
    }
    System.out.println();
    */
    }
    }
  2. 运行结果:

  3. 结论:第一次编译该程序的时候出现了乱码,可能跟我这个代码要打印汉字有关吧。经过查找了相关资料,只要在编译时输入-encoding utf-8即可解决。斐波那契数列不算难,不断迭代就可解决。程序中被注释的代码是最开始编的,最后想到也可以用一个for循环解决,不过感觉2个for循环看起来结构更清楚一些,可读性更强一些。

洗牌:

  1. 代码:

    public class Shuffle{
    public static void main(String[] args){
    String[] pokers = {
    "梅1","梅2","梅3","梅4","梅5","梅6","梅7","梅8","梅9","梅10","梅J","梅Q","梅K",
    "砖1","砖2","砖3","砖4","砖5","砖6","砖7","砖8","砖9","砖10","砖J","砖Q","砖K",
    "桃1","桃2","桃3","桃4","桃5","桃6","桃7","桃8","桃9","桃10","桃J","桃Q","桃K",
    "心1","心2","心3","心4","心5","心6","心7","心8","心9","心10","心J","心Q","心K"
    };
    //定义一个0-51的随机数(不重复)数组。
    int[] numbers = new int[pokers.length];
    //赋初值,简化判断是否有重复随机数的循环次数。
    for(int i=0; i<pokers.length; i++){
    numbers[i] = -1;
    }
    int num;
    boolean flag;
    for(int i=0; i<pokers.length; i++){
    //产生随机数。
    while(true){
    flag = true;
    num = (int) (Math.random() * pokers.length);
    //凡是搜索到了-1就表示已经搜索完毕。
    for(int j=0; numbers[j]!=-1 ;j++){
    if(numbers[j] == num){
    flag = false;
    break;
    }
    }
    //不重复,就向随机数数组中赋值。
    if(flag){
    numbers[i] = num;
    break;
    }
    }
    }
    /*
    调代码时用到,用以判断是否成功生成了0-51的不重复随机数。
    for(int number : numbers){
    System.out.print(number + " ");
    }
    System.out.println();
    */
    for(int i=0; i<pokers.length; i++){
    System.out.printf("%-4s",pokers[numbers[i]]);
    if((i+1)%13 == 0)
    System.out.println();
    }
    }
    }
  2. 运行结果:

  3. 结论:拿到这个题目,想了一会,考虑怎样才能让52张扑克牌随机输出。最后想到了可以用随机数产生的方法,0-51个随机数对应的其实就是“扑克牌数组”的角标,因为角标的随机,实现了出牌的随机。当然因为编写不熟悉,输出的扑克牌有重复的,为了能更加看清楚随机数(不重复)是否成功产生,打印了52个随机数(代码中被注释的片段)。最后发现过然是随机数产生有问题,逆推回去,发现了第二个for循环中判断的条件原来写的是“numbers[j]!=0”,当时的想法是如果碰到0了,说明已经搜索完了(int型数组默认赋初值为0),不用往后搜了,但是忽略了一点,产生的随机数也含有0,如果采取这样的方法判断,就会出现重复的情况。所以在前面加了一句,将数组中的元素赋初值为1。最后打印时发现,“梅10”“心10”等这4张牌多占一个字符的宽度,所以为了打印美观,将输出格式控制为%-4s

排序:

  1. 代码:

    import java.util.Arrays;
    
    public class BubbleSort{
    public static void main(String[] args){
    int[] number = {70, 80, 31, 37, 10, 1, 48, 60, 33, 80};
    /*
    冒泡排序代码:
    int temp;
    for(int j=0; j < number.length-1; j++){
    for(int i=0; i < number.length-1-j; i++){
    if(number[i] > number[i+1]){
    temp = number[i];
    number[i] = number[i+1];
    number[i+1] = temp;
    }
    }
    }
    */
    Arrays.sort(number);
    for(int num : number){
    System.out.printf("%3d",num);
    }
    System.out.println();
    }
    }
  2. 运行结果:

  3. 结论:排序题其实在C语言中也接触了不少,代码中被注释的片段用到的就是冒泡排序,可以说比较简单高效。但因为Java面向对象的特性,可以用Arrays.sort(number);,一句代码,直接将原来的数组从小到大排列,更加简单。既然再学Java,就要多使用对象,这样可以提高编程技能和效率。

查询:

  1. 代码:

    (1)产品代码:

    import java.util.Scanner;
    
    public class Search{
    public static void main(String[] args){
    int[] number = {1, 10, 31, 33, 37, 48, 60, 70, 80};
    Scanner scanner = new Scanner(System.in);
    int num = scanner.nextInt();
    System.out.println(binary(number,num));
    }
    public static int binary(int[] array, int value){
    int low = 0;
    int high = array.length - 1;
    int middle;
    while(low <= high){
    middle = (low + high) / 2;
    if(value == array[middle])
    return middle;
    if(value > array[middle])
    low = middle + 1;
    if(value < array[middle])
    high = middle - 1;
    // System.out.println(middle);
    }
    return -1;
    }
    }

    (2)测试代码:

    public class SearchTest{
    public static void main(String[] args){
    int[] number = {1, 10, 31, 33, 37, 48, 60, 70, 80};
    if(Search.binary(number,1) != 0)
    System.out.println("test failed 1!");
    else if(Search.binary(number,10) != 1)
    System.out.println("test failed 2!");
    else if(Search.binary(number,31) != 2)
    System.out.println("test failed 3!");
    else if(Search.binary(number,33) != 3)
    System.out.println("test failed 4!");
    else if(Search.binary(number,37) != 4)
    System.out.println("test failed 5!");
    else if(Search.binary(number,48) != 5)
    System.out.println("test failed 6!");
    else if(Search.binary(number,60) != 6)
    System.out.println("test failed 7!");
    else if(Search.binary(number,70) != 7)
    System.out.println("test failed 8!");
    else if(Search.binary(number,80) != 8)
    System.out.println("test failed 9!");
    else if(Search.binary(number,0) != -1)
    System.out.println("test failed 10!");
    else if(Search.binary(number,40) != -1)
    System.out.println("test failed 11!");
    else if(Search.binary(number,100) != -1)
    System.out.println("test failed 12!");
    else
    System.out.println("test passed!");
    }
    }
  2. 运行(测试)结果:

  3. 结论:二分法之前也接触过,这次将其运用到了Java程序中。根据毕老师的视频,学到了自定义函数的一些皮毛,就尝试着用函数的功能编写了一个可以查找数组中某个数的方法。其实这一点跟C语言中的知识比较类似,同一个类中,最多只允许一个main函数,它是代码的入口,执行代码先找main函数,先执行main函数;自定义的函数也和原来学的差不多,注意形参的类型个数,注意函数类型、有无返回值等情况。

其他

  • 之前就听说过面向过程、面向对象,但不知道具体指的是什么。经过这一章的学习,要把面向对象这个观念牢记心中,这是区别C语言等其它面向过程语言的不二法宝。
  • 对于对象的理解还要更加加深理解,要在平时的编程练习中巩固加强。熟能生出百巧来,只有熟练了,才能提高自己的编程技术,理清自己的编程思路,升华自己的编程思想。

参考资料

《Java程序设计》第四章-认识对象的更多相关文章

  1. Java核心技术第四章——3.对象构造

    重载: 如果多个方法(包含构造方法)有相同的名字.不同的参数,便产生重载.编译器必须挑选出具体执行哪个方法,它通过用各个方法给出的参数类型与特定方法调用所使用的值类型进行匹配挑选出相对应的方法. 如果 ...

  2. “全栈2019”Java多线程第四章:设置和获取线程名称

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  3. “全栈2019”Java异常第四章:catch代码块作用域详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  4. “全栈2019”Java第九十四章:局部内部类详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. “全栈2019”Java第十四章:二进制、八进制、十六进制

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. “全栈2019”Java第二十四章:流程控制语句中决策语句switch下篇

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  7. Java程序设计第四次实验报告

    北京电子科技学院(BESTI) 实     验    报     告 课程:java程序设计 班级:1352  姓名:何伟钦  学号:20135223 成绩:            指导教师:娄嘉鹏 ...

  8. JAVA基础第四章-集合框架Collection篇

    业内经常说的一句话是不要重复造轮子,但是有时候,只有自己造一个轮子了,才会深刻明白什么样的轮子适合山路,什么样的轮子适合平地! 我将会持续更新java基础知识,欢迎关注. 往期章节: JAVA基础第一 ...

  9. JQuery制作网页—— 第四章JavaScript对象及初识面向对象

    1.对象:在JavaScript中,所有事物都是对象,如字符串.数值.数组.函数等. JavaScript中的基本数据类型: number(数值类型)   string(字符串类型)  boolean ...

随机推荐

  1. eclipse的.properties文件中文显示问题

    eclipse的.properties文件,默认的编码方式是iso-8859-1. 所以中文显示有问题. 按照下面的方式,把Default Encoding修改成UTF-8就可以了.

  2. String.Join重载String.Join 方法 (String, String[], Int32, Int32)

    https://msdn.microsoft.com/zh-cn/library/tk0xe5h0 String.Join 方法 (String, String[], Int32, Int32) 官方 ...

  3. 设计模式之工厂方法模式(Java实现)

    “我先来”,“不,老公,我先!”.远远的就听到几个人,哦不,是工厂方法模式和抽象工厂模式俩小夫妻在争吵,尼妹,又不是吃东西,谁先来不都一样(吃货的世界~).“抽象工厂模式,赶紧的自我介绍,工厂方法模式 ...

  4. 使用openssl生成RSA公钥和私钥对

    在ubuntu上要使用openssl的话需要先进行安装,命令如下: sudo apt-get install openssl 安装完成就可以使用openssl了. 首先需要进入openssl的交互界面 ...

  5. applicationContext.xml的文件位置就可以有两种默认实现

    ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息.因为它实现了ServletContextListener这个接口,在web ...

  6. ThinkPHP如果表名有下划线需要用Model应该怎么做?

    最近遇到一个问题,在用TP做系统的时候,我建立的表是 “tp_admin_user” 但是要用到的模型是 “AdminUserModel.model.class.php”,应该如何做? 解决方法: & ...

  7. 手机联系人信息获取(contacts) ---- HTML5+

    模块:contacts Contacts模块管理系统通讯录,用于可对系统通讯录进行增.删.改.查等操作.通过plus.contacts获取系统通讯录管理对象. 对象:联系人对象(属性:电话,地址等)针 ...

  8. postgresql架构基础(转)-(1)

    PostgreSQL使用一种客户端/服务器的模型.一次PostgreSQL会话由下列相关的进程(程序)组成: 一个服务器进程,它管理数据库文件.接受来自客户端应用与数据库的联接并且代表客户端在数据库上 ...

  9. mybatis-spring-boot-autoconfigure

    mybatis-spring-boot-autoconfigure – MyBatis Sring-BootStarter | Reference Documentation http://www.m ...

  10. Spring 体系结构

    https://www.w3cschool.cn/wkspring/dcu91icn.html 体系结构 Spring 有可能成为所有企业应用程序的一站式服务点,然而,Spring 是模块化的,允许你 ...