《Java程序设计》第七次学习总结

《Java程序设计》第七次学习总结

目录

教材学习内容总结

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

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

其他(感悟、思考等,可选)

正文

教材学习内容总结

学习了第十一章“异常”和第十二章“递归”。自己思考后总结如下:

  • 第十一章
    • 异常就是那些有可能出现错误的情况,而不是一定就是错误。
    • 异常分为两类:“必检异常”和“非必检异常”,在有可能会抛出“必检异常”的方法名后面得加上 throws() 关键字,方法体中用throw 来抛出可能发生的异常。
    • try()catch(){} 语句块中可以有多个 catch(){} 字段,分别来对应处理可能会出现的错误。
    • 如果有try()catch(){}字段,则代表:对相应的异常进行了捕获并处理 ,那么异常发生后面的程序也可以被执行。反之,如果没有try...catch 字段则一遇到异常就会终止这段程序的运行,如果是被调用的则转向调用的方法那里,如果是main方法就直接结束整个程序了,并且打印出栈调用的轨迹和相应的异常信息。
    • 不论是正常退出try块,还是因抛出一个异常而退出try块,都要执行finally字句。
  • 第十二章 : recursion
    • 递归的思想:自己调用自己来解决问题。有个例子是:用decorate 来解释decarate的意思。包括自己在学c语言时候就知道的用递归的方法来解决阶乘的问题。

    • 关于递归,新的收获有:其实一个递归有两部分组成:

      • 基础情形:base case;
      • 调用自身的过程。
    • 这里的基础情形可以让调用自身这个过程不会无休止的进行下去(即:不会产生无穷递归),当自身调用自身过程到了base condition时,就会执行base condition 并且沿着一开始调用自身的“路径”,开始往回“走”,一层一层的返回得到的值,只到回到最初的那个调用自身的开始处。

    • 由上面那个递归由两部分构成这个结论,可以想到:实现递归最基本的结构就是 if-else 语句,用if-else其中某个分支来处理基础情形(base case)的情况,另外一个分支负责来调用自身。

    • 每次调用自身,都会导致方法中的局部变量重新被更新,而且,在往回走的时候局部变量会自动回到上一次调用它时候的值,概念就是:形参在函数内的变化不会传递到调用这个函数的实参上。

    • 直接递归和间接递归。

    • 关于递归的书上的例子说明:

回到目录

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

  • 问题一:关于 throws关键字和throw的区别,还有try-catch语句块。问题的详细描述如下:什么时候需要用到throws?用在哪里?throw关键字也是有同样的问题?很明显的一个就是,好像在使用java自带的又可能出现异常的方法的时候就不需要用到throwsthrow关键字了,如果要捕获异常得用到try-catch语句块。但是,如果你自己编程序来自定义一个自己想要的必检异常,那么则需要用到throws关键字来附加到函数名字的尾部,同时,在会发生异常的部分来使用throw关键字来抛出异常。同理捕获得用那个语句块。
  • 解决方法:上面自己的想法,大部分是对的。理一下:异常分为系统给出的异常,以及你自定义的异常。
    • 系统给出的异常中有必检和非必检两大类,在调用这个有可能会出现异常的方法时,必须得在try语句块中调用,否则会报错“未报告异常错误”。
    • 自定义异常时就是得同时用到throwsthrow,这两个关键字。
      throws是用在方法名的后面 throws xxxxException,这个方法就是那个可能会出现异常的方法。而throw关键字是用在这个方法体之中,通常是在一个if-else的某一个分支中,这个分支对应了出现了异常时应该进行的操作,即:使用throw关键字来抛出异常类对象。异常类是你自己自定义的异常类xxxxException。定义这个异常类时注意是用到extend关键字来继承Exception类的。

回到目录

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

  • 问题一:在编程时出现了,以前遇到过的“无限循环”的情形,明明输入了停止字符串,但是依然不能够终止程序的运行。代码如下:
  • 解决方法:就如自己所感受到的,明明输入了"DONE"但是程序并不会停止运行,其实应该很自然的想到是控制循环的条件出了问题,但是我是通过在IDEA中进行Debug来发现是控制循环的条件 "DONE" != str_input有问题的,我发现我输入的"DONE"字符串str_input根本和不等号的右边 "DONE" 是不等的。然后就知道了,什么是对象的别名,什么是对象的引用,我上图程序中的做法是在比较 str_input这个 “门牌号” 会不会等于DONE,这当然永远不等啊!而我的初衷是想比较 str_input这个“门牌号”对应的房间里住着的内容是不是DONE,不是来比较“门牌号”的。 所以正确的做法如下图:

这里充分体现了“门牌号”的概念,而且我自己编了一个程序,所以对书上之前讲的一点内容有了更深入的理解:自己编的程序如下图所示:

实际上,字符串常量str3就是一个给门牌号赋值的过程,它使得str3这个门牌号就是Hello,而不是像str1或者str2那样的数字门牌号,所以那一条语句才是真的。
书上的内容如下:

由此可见:在比较对象时,“ == ” 是用来判断这个关系操作符左右两边的“门牌号”是否是贴在一个房间的门上,如果这两个门牌号对应是两个单独的房间则是不等的,只有两个门牌号贴在同一个房间上才是等的。

所以,比较字符串对象内容是否是相等的,只能调用方法equals(),不能用关系操作符 “==”, 这是和面向过程编程不同的!

  • 问题二:递归调用时:成员变量和局部变量的差别。
  • 解决方法:这个问题出现的主要愿意是在编pp12.9时出现的,原来的程序如下图:

length 是一个局部变量,每次递归调用时都会重新初始化,并且返回时,也能够正常返回到原来的初始值。但是 n 就不一样了,n是一份成员变量,我每次递归调用getValue()方法时,n的确初始值是对的,因为有 n = number,每次递归调用时的 number是在变化的,但是递归返回时,就有问题了,递归返回时,因为n 是成员变量,所以你在 getValue()方法中对 n 进行的操作都会被保存着,它并不像形参 number 那样对实参没有影响,n并不能回到调用它时侯的方法。
这一点通过Debug也能看出来,所以,在用递归编程时候,尽量去用局部变量,而不是去用成员变量。

  • 问题三:是在做pp11.1时候出现的,关于Scanner类中的方法next()
  • 解决方法:要知道,每使用一次scan.next()方法一次,就是相当于调用了一次这个方法了,这样的话就是相当于要用户输入了两次。但是我的初衷只是,在第二次用scan.next() 时把第一次调用该方法的值得到。所以,正确的做法是,把第一次调用next()方法,得到的值保存在一个门牌号对应的房间里。然后,后面在用这个房间里的东西来进行比较。下面是一开始的错误代码:

  • 改正以后就出现了上面第一张图里的str_input变量名。

回到目录

其他(感悟、思考等,可选)

这一次的学习让我对递归有了更深的了解,同时也反映了我以前基础不扎实的事实。但是,自己能够编写程序来验证自己的猜想,是一个很不错的做法。就是想自己来猜想 ==这个运算符的时候,一开始还没有反应过来这是门牌号的差异。所以就想着自己编个简单的程序来验证一下 == 真的不能用来比较相等吗?一编程序,发现真的不对,然后就去反思了。所以,以后出现了问题,真的可以尝试编一个简单的小程序来验证自己的想法。

关于IO流,因为教材并没有细致的讲,所以自己也没有很全面的总结过,但是在三金哥的博客里有相应的资料,可以后面在学习的时候,遇到了问题在来看看吧。下面是一张自己觉得关于IO流不错的图。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第七次 2329/5000 1/18 无记录 递归和验证的方法思想
[回到目录](#index)

回到目录

参考资料

  • [Java程序设计(第8版)]
  • [《Java程序设计基础(第2版)》耿祥义]
  • PPFrame
  • 三金哥
原文地址:https://www.cnblogs.com/alan6y/p/10263368.html