20172317 2017-2018-2 《程序设计与数据结构》第四周学习总结

时间:2021-04-25 22:15:57

20172317 2017-2018-2 《程序设计与数据结构》第四周学习总结

教材学习内容总结

这一周,或者确切地说,一周加三天,学习了类的编写,以及类中的各种方法的写法,了解了可见性修饰符、静态类成员的意义,实践了一些方法设计的例题。..........但是即使是过了这么久,感觉这一方面的只是还是只是学到了一点皮毛,尤其是到了具体的方法设计的时候经常会陷入困惑中。

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

  • 问题1:public?private?
  • 问题1解决方案:在之前敲代码的时候总是能见到public这个词,比如public class xxx或者是public static void main(String[] args)之类的,而学到现在还出现了要用private的情况,弄清楚public 和private之间的区别时十分必须的。一如既往地,书上的解释还是理解不了。自己实践了一下,把第四章的Die.java的private int faceValue;private改成了public,试图直接在RollingDice.java中用System.out.println(faceValue);来获得faceValue的值,因为看书上说“public 可以允许类外部的代码访问或修改类中的数据值”,然而这样子做却在RollingDice.java的编译中出错了....很疑惑,我怀疑是我的代码没有用正确的方法去访问这个数值的原因。因此换了一个方法:把getFaceValue()改成了private,理论上因为private方法不能由类的外部引用,所以会出现错误,实际上也的确输出了错误“getFaceValue() has private access in Die"。
  • 问题2:void?return?
  • 问题2解决方案:“void”这个词如同"public"一般,也是属于在前面看到过了很多次但是不知道什么意思的一个词。void的字面意思是“空”,上网去进一步了解后,了解到了void在这里有“无类型”之意,并且如果函数没有返回值,则要声明为void类型。刚开始并不是特别能理解这段话,尤其是不懂“返回值”为何物,后面接触了更多的代码之后,发现了一个共通点:

    方法的编写除了构造方法外,都是遵循这样的结构:可见性修饰符 + 返回值类型 + 方法名(参数啥的乱七八糟的东西,可以不写){方法的具体代码}

    经观察,void都是出现在返回值类型这个地方的,对比一下书上的各个实例,会发现另外一个特点,那就是返回值类型这地*是诸如int,double,String之类的,方法的具体代码最后总会有个return啥啥啥;而如果是void则不会有return。这样折腾之后大概明白了void和返回值都具体指的是什么:方法实现了条件输入和结果输出的过程,而如果想要显示(不知道该怎么形容)方法的结果,就不能用void,而是要写上相应的数值类型,再return;如果不需要显示,则用void。顺带一提经过测试方法的返回值最多只能有一个,不能返回多个值
  • 问题3:static?
  • 问题3解决方案:还是一样的....经常能看见,就是不知道啥意思的一个词,书上的解释也感觉有些迷糊,只好求助于网络
    对于静态变量,网上是这样解释的:static修饰的变量,叫静态变量或类变量;没有被static修饰的变量,叫实例变量。对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。 对于实例变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。所以一般在需要实现这两个功能时使用静态变量:1.在对象之间共享值;2.方便访问变量时;
    而至于静态方法,由于第七章有Slogan.java,所以就自己去试了一下,把里面的static去掉看看会发生什么:出现的两种错误分别是“non-static method getCount() cannot be referenced from a static context”和“ error: non-static variable count cannot be referenced from a static context”,前面的错误是去掉getCount()前的static产生的,后面的错误是去掉count = 0前面的static产生的。在上网查了时候还得到了以下一段话:“静态方法是类内部的一类特殊方法,只有在需要时才将对应的方法声明成静态的,一个类内部的方法一般都是非静态的;静态方法可以直接通过类名调用。”

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

  • 问题1:unexpected return value和missing return statement
  • 问题1解决方案:这两个错误信息都是由于返回值类型的错误而产生的。前一条错误是出现在比如在本应返回void的方法里面加上了return;而后面的那个错误是出现在本应该有返回值的方法里却没有return的情况,没有什么特别值得说的。
    其实关于返回值类型还有这样的一种可能:返回的值的类型和在方法上面写的返回值类型不一致,这时候会出现两种情况:第一种是编译成功,没什么奇怪的事情发生;第二种是出现错误“incompatible types: xxx cannot be converted to xxx”。我仍旧是在Slogan.java上试的,把public static int getCount()的int改成了String就出现了错误,而改成long就正常编译。我的猜想是在这个地方如果方法中的返回值类型与return的值的类型不同,将会进行一次强制性转化,所以改成String的时候才会出现错误,而改成long的时候反而能编译成功,当然这只是我的猜测,我在网上也没有找到答案。
  • 问题2:关于PP4.5
  • 问题2解决方案:其实问题主要集中在isAntique方法上,由于没有学第五六章,所以一下子就蒙了。于是粗略了看了一下第五章后开始了充满混乱的尝试之路:第一次是写成了这样的...

    public boolean isAntique();
    {
      if (2018-factoryYear > 45)
       return boolean true;
      else
       return boolean false;
    }

    ...我知道,的确是错的离谱,首先最明显的错误isAntique()后面竟然加了一个“;” ...其次是错的都不知道从哪地方说起的return boolean true,这个地方的代码后面改了很多遍,也都是各种离谱,比如return boolean或者return true之类的...中间其实还有很多其他的错误,然而时间有点远了所以记不太清了,只好记下几个有印象的错误...最后还是去问了一下老师写成了这样的正确代码:

    public boolean isAntique()
    {
     boolean antique;
     if (2018-factoryYear>45)
      antique = true;
     else
      antique = false;
     return antique;
    }
  • 问题3:输出些奇怪的结果?
  • 问题3解决方案:经常的,会有些奇奇怪怪的结果的输出,比如这样...
    20172317 2017-2018-2 《程序设计与数据结构》第四周学习总结

    ....啥玩意?但是仔细一看代码会发现
    20172317 2017-2018-2 《程序设计与数据结构》第四周学习总结

    (这里将toString()方法变成注释所以不会被编译)你会发现这个Bulb.java缺少了toString()方法。至于为什么缺了这个方法就会输出这个玩意嘛...我听到了老师向其他人的解释“这是输出了一个地址”,我估计这个应该就是解释...吧。
  • 问题4:关于修改器(mutator)的一个小问题
  • 问题4解决方案:所谓修改器就是那些setXXX()的那些方法,有些时候设置方法的时候是设成这样的setModel(String model),而你在驱动类里如果写成了像setModel(MODEL 2)这样子是会出现错误的。我猜因为括号里是“String model”的原因,所以括号里只接受String类型的,因此最开始我改成了setModel(MODEL2)但是并没有什么用,然后改成了setModel(“MODEL 2”)就没问题了,我估计如果想要括号里的东西被当做是String,就必须要加上引号。
  • 问题5:PP4.9!
  • 问题5解决方案:的确很棘手,算是对java的难度第一次有了一个认识。
    由于时间有点久,很多问题都忘得差不多了...只记下了印象最深的几个问题:但是还是记得不太清啊...
    首先第一个问题,这个问题比较愚蠢:由于题目中的要求是“PairOfDice这个类由两个Die对象组成”,所以我进行了一个令人智熄的操作:我只在PairOfDice()这个构造方法里面定义了die1,die2这两个对象,所以十分显而易见的,在剩下的定义方法的语句里所有出现了“die1”“die2”的地方都出现了“cannot find symbol”的错误。为了解决这个问题,我用了一个更加令人智熄方法:我在所有用到Die类方法的方法里都加了一个Die die1 = new Die()Die die2 = new Die(),尽管这个智熄操作的确使PaieOfDice.java没有错误的编译成功了,但是在驱动类RollingDice2的测试下发现die1和die2的面值永远都是1。最后的做法是:把创建对象的两条语句放在了最前面的地方(和创建变量一块的地方),最终编译成功。
    由于之前出现的各种各样的错误,编译成功了之后,我下意识的在驱动类RollingDice2.java里对PairOfDice类里的访问器方法getValue1()进行了一次测试(这段代码里public class啥啥的省略了):

    PairOfDice twoDice = new PairOfDice();
    twoDice.setValue1(4);//setValue1是设置第一个骰子的值的方法
    System.out.println("die1=4?" + twoDice.getValue1());

    很明显,正常来说应该是显示die1=4?4才对,然而最终却输出了die1=4?1。这里就是我要讲到的第二个问题:访问器不能输出正确的数值
    脑子里第一反应是die1的数值被重新设为1了,重新回去看PairOfDice的代码。刚开始并不能找到错误的原因,后面一想估计是setValue1()的方法里有问题了,这是当时setValue方法的代码:

    public void setValue1(int value1Alt)
    {
      value1 = value1Alt;
    }

    这下情况就变得稍微有意思些了,因为似乎这个代码是完美无缺的,然而配上getValue1(),问题就显现了,这是getValue方法的代码:

    public int getValue1()
    {
      value1 = die1.getFaceValue();
      return value1;
    }

    看到病根了?getValue1()是先用了Die类里的getFaceValue()来给value1赋值,再返回value1的值。而在前面的测试中先用setValue1(4)给value1赋值4,但是getValue1()里又一次的给value1赋值,赋的值是die1.getFaceValue()的值,而这个值又是在Die类里决定的:在new PairOfDice()之后,新建了Die类的对象die1,根据Die类的性质,可以知道die1在Die类里的faceValue为1。因此,getValue1()的value1 = die1.getFaceValue()就使value1又等于1了。绕,真绕
    尽管已找到了问题的根源,要修改还是不那么的容易。修改应该不是从getValue1()方法处入手,所以只好在setValue这里解决。在经历了很长的一段试验之后,终于将setValue改成了这样:

    public void setValue1(int value1Alt)
     {
       die1.setFaceValue(value1Alt);
       value1 = die1.getFaceValue();
     }

    最后测试,没有任何错误,问题解决。

  • 问题6:PP7.1....
  • 问题6解决方案:这个题目看似十分短,以为会是比较简单的题,然而“题目越短的题越难”这个定律在java依旧奏效。
    这题本来不该困扰我的,然而由于看到了书上的例题7.4,所以以为这个地方会需要用到类似于7.4那样子的方式来做所以试了大量的诸如:

    public Account newAccount(String name,long acctNumber)
    {
      String NAME = name;
      long ACCTNUMBER = acctNumber;
      Account NEW = new Account(NAME, ACCTNUMBER, 0);
      return NEW;
    }

    之类的现在看起来特别蠢的代码,在绝望中试了两天之后终于求救于老师,结果这个困扰了我很久的题目竟然只需要稍微方法重载一下就可以了:

    public Account (String name, long acctNumber)
    {
      this.name = name;
      this.acctNumber = acctNumber;
      balance = 0;
    }
    由于在这之前一直没弄懂方法重载的意思,所以也没用这样的方法,当然在这之后不仅解决了问题,也把方法重载搞懂了,可喜可贺。
  • 问题7:PP7.4....
  • 问题7解决方案:问题依旧不少,不过最大的问题“怎么使用Comparable接口”被老师解决了,而且这个问题也基本上人人知道解决方法,所以就没有再重复一遍的价值了。但这里有个特别的问题,首先看下这里compareTo方法的代码:

    public int compareTo(Object obj)
    {
    RationalNumber objNUM = (RationalNumber)obj;
    double num1, num2, difference;
    num1 = this.numerator / this.denominator;
    num2 = objNUM.getNumerator() / objNUM.getDenominator();
    difference = num1 - num2;
     if (difference > 0.0001)
      return 1;
     else
      if ((difference < 0.0001) && (difference != 0))
       return -1;
      else
       return 0;

    看似是没有什么问题的,但是这样子比较两个分数却永远显示两个分数是相同的,但是如果两分数之间的差值比较大,比如:1/3和4/3比较的时候却又能正常的运算。由于实在是没有头绪,只好去找同学帮忙,尽管两个人的代码几乎是相同的,但是他却在num1和num2那地方的式子的右边多加了一个东西1.0 *,我估计这是转化成浮点型值,而之前是整型值?

代码托管

20172317 2017-2018-2 《程序设计与数据结构》第四周学习总结

(statistics.sh脚本的运行结果截图)

上周考试错题总结

  • Which properties are true of String objects?
    A.Their lengths never change
    B.The shortest string has zero length
    C.Individual characters within a String may be changed using the replace method
    D.The index of the first character in a string is one
    E.Only A and B are true
    正确答案为E,我选的是C。
    从这次考试开始起,主要的难点就转移到英语上了。无论如何,题目大概问的是“下列哪个是String对象的属性”。C选项的大意是“String字符串里的单个字词可以通过replace来进行替换”,但是replace(char oldChar, char newChar)这个方法事实上是将字符串的所有oldChar替换成newChar之后,构成新的字符串对象返回,而不是直接修改字符串。对于A选项,书上有原话“一旦创建了String对象,该对象的长度就不可再修改,并且也不能修改对象中的任何一个字符”。而至于B选项....我是有些许的怀疑的,因为不清楚选项中所说的“最短的字符串”具体指的是什么,当然,解析里说“ The shortest length string is ""”那这样的话B显然就是对了
    总觉得这题错的很蠢

  • What happens if you attempt to use a variable before it has been initialized?
    A.A syntax error may be generated by the compiler
    B.A runtime error may occur during execution
    C.A "garbage" or "uninitialized" value will be used in the computation
    D.A value of zero is used if a variable has not been initialized
    E.Answers A and B are correct
    正确答案为E,我选的是A
    看到了A是对的,毫不犹豫的选了A,谁知B也是对的,所以E是对的
    ....上面那段话看的是不是很别扭?我也这么觉得,但是像“A和B都对”的这种选项,我更觉得像是就是来逗你玩的
  • What is the function of the dot operator?
    A.It serves to separate the integer portion from the fractional portion of a floating point number
    B.It allows one to access the data within an object when given a reference to the object
    C.It allows one to invoke a method within an object when given a reference to the object
    D.It is used to terminate commands (much as a period terminates a sentence in English)
    E.Both B and C are correct
    正确答案为E,我选的是A
    和上题是一样的错法....略
  • In Java, "instantiation" means
    A.noticing the first time something is used
    B.creating a new object of the class
    C.creating a new alias to an existing object
    D.launching a method
    E.none of the above
    正确答案为B,我选的是D
    “instantiation”是实例化的意思,使用new运算符创建对象的行为,被称为实例化
  • Which of the following will yield a pseudorandom number in the range [ -5, +5 ) given the following:
    Random gen = new Random( );
    A.gen.nextFloat( ) * 5
    B.gen.nextFloat( ) * 10 - 5
    C.gen.nextFloat( ) * 5 - 10
    D.gen.nextInt( ) * 10 - 5
    E.gen.nextInt(10) - 5
    正确答案是B,我选的是C
    对于Random类来说,有一个比较特殊的方法nextFloat(),这个与nextInt()有点不同,nextFloat()返回一个分布在[0.0,1.0)区间的浮点随机数,所以对于B选项来说gen.nextFloat()*10-5先是得到[0,10)的范围,再减去5得到[-5,5)的范围
  • The advantages of the DecimalFormat class compared with the NumberFormat class include
    A.precise control over the number of digits to be displayed
    B.control over the presence of a leading zero
    C.the ability to truncate values rather than to round them
    D.the ability to display a % automatically at the beginning of the display
    E.only A and B
    正确答案是E,我选的是A
    ......好,我下次会留意这些可能的双选答案
  • When comparing any primitive type of variable, == should always be used to test to see if two values are equal.
    A.true
    B.false
    正确答案是B,我选的是A
    这一题确实一下子把我打蒙了,“==”是什么?似乎没有见过?事实上“==”是在第五章里讲的,这个运算符和另外一个运算符“!=”一起被称为“相等性运算符”,分别用于判断两个值是相等还是不相等,比如说a==b得到的结果就是false,而a!=b得到的结果就是true。
    然而....即使是了解了这个运算符究竟是什么意思,这题还是错了,难道不就是用“==”来测试两个值是不是相等的?这时候只能求助于解析。解析上是这样解释的:对于int,short,byte,long,char和boolean这类的确实是如此,然而对于double和float就不一样了,假设两个double型的x和y,测试(x==y),除非最后一位小数是完全相同的,否则结果为false。因此对于浮点型之间的比较,通常允许微小的误差
    例如:假设一个绝对误差THETA = 0.0000001,那么比较两个浮点型的值x和y可以这样:(x-y<=THETA)(运算符“<=”是关系运算符,用于判断左边的数是否小于或等于右边的数,如果是那么条件为真,这也是第五章才学的....Sensei!这题目超纲了!)

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

感悟:在时间仅仅多出了三天的情况下,就多学一章,而且实际上还包含了很多第五章的东西,而且这两章刚好是重难点,相当的麻烦,相当的麻烦,病入膏肓
似乎学java到了一个瓶颈了,这地方的东西还需要更多的练习,感觉这里决定着java能不能学好的关键(而我似乎做的还不够好),希望突破了这里的难关之后能给我继续学下去的勇气吧
顺便随便写条遗言:哪一天如果我猝死在了电脑前,请各位继续前进吧,以我为戒
噢,忘记了One Thing One Commit.....咳,下次会注意的

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 91/91 1/1 20/20
第二周 284/375 1/2 18/38
第三周 由于上周试验的原因代码量异常 2/4 22/60
第四周 ???/2354 1/5 30/90 *你感觉你会有段糟糕的时光
  • 计划学习时间:20小时

  • 实际学习时间30小时

  • 改进情况:似乎没有什么进步,似乎还有退步的迹象,咳,往好处想,这可以促使人进步牵强的解释

参考资料