20155303 2016-2017-2 《Java程序设计》第八周学习总结

20155303 2016-2017-2 《Java程序设计》第八周学习总结

目录

学习内容总结(Linux命令)

——《Linux 基础入门(新版)》第四节:Linux 目录结构及文件基本操作

说明:本节主要介绍了Linux路径问题(绝对路径和相对路径)和Linux文件的基本操作(增删改查、复制、移动、编辑、查看等)。接下来总结了实验楼本节介绍的命令,并添加了一些实际实验操作过程中补充的命令以及注意事项。

『一、Linux 目录结构』

  • tree:查看(当前目录下)的目录结构。如果想查看根目录下的目录结构,则用tree /命令。

  • cd:切换目录(Linux下,.表示当前目录,..表示上级目录,-表示上次所在目录,~表示当前用户的home目录)。

  • pwd:查看当前路径信息(绝对路径)。

    绝对路径:简单地说就是以根" / "目录为起点的完整路径,以所要到的目录为终点,如/usr/local/bin

    相对路径:相对于当前的目录的路径,相对路径是以当前目录.为起点,以所要到的目录为终点,如../../

『二、Linux 文件的基本操作』

  • touch:创建空白文件。

    「注意」:想多说的一点是,课程中提到,“touch命令主要作用是来更改已有文件的时间戳的(比如,最近访问时间,最近修改时间)”,但并没有具体介绍,所以在此稍作补充:

    实例一:创建不存在的文件。如使用touch test1命令,创建一个名为“test1”的文件;

    实例二:更新时间戳。如使用touch -r test1 test2命令,即把test2的时间戳改为与test1相同;

    实例三:设定文件的时间戳。如使用touch -t 201704140810.20 test命令,可以更改时间戳。(说明:-t time使用指定的时间值 time 作为指定文件相应时间戳记的新值.此处的time规定为如下形式的十进制数:[[CC]YY]MMDDhhmm[.SS],比如本例表示:2017年4月14日8:10:20)

  • mkdir:新建目录(mkdir -p father/son/grandson:同时创建多级目录)

  • cp <文件名> <路径信息>:将文件复制到制定目录下。

  • cp -r <目录一> <目录二>:将目录一移入目录二下(也可使用-R参数)。

  • rm <文件名>:删除文件(如果文件有权限等,可以使用rm -f <文件名>强制删除)。

  • rm -r <目录名>:删除目录(同样可以使用-R参数)。

  • mv <源目录文件> <目的目录>:移动文件至指定目录下。

  • mv <旧的文件名> <新的文件名>:重命名。

  • cat/tac:打印文件内容到标准输出(终端),其中cat为正序显示,tac为倒序显示。(加上参数-n显示行号)。

  • nl:添加行号并打印,这是个比cat -n更专业的行号打印命令。

  • tail -n <行数n> <路径信息>:打印前n行。(注意不是第n行!)

  • file <文件名>:查看文件信息,如类型。

  • vi <文件名>:编辑文件,如果没有该文件,则先创建再编辑。

『注意』:1、批量新建文件或删除文件时,可以使用正则表达式,将匹配的文件全部进行该操作。

2、使用mv移动命令时,同一目录下的重名文件,后者自动覆盖前者。

3、df -h命令可以查看文件大小。

返回目录

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

  • 『问题一』:区分==equals()matches()contains()的用法。

  • 『问题一解决』

本周学习了String类的matches()方法,回顾之前学过的==equals()以及相关的contains()方法,试比较它如何使用呢?

编写以下程序查看结果,即可明白:

import static java.lang.System.out;
public class CompareDemo {
    public static void main(String[] args) {
        String s1 =  "Let'sJava";
        String s2 = new String("Let'sJava");//新建一个与s1内容相同的对象
        String s3 = "Let's.*";//这其实是一个正则表达式
        String s4 = "Let's";
        out.println(s1 == s2);//"=="的用法。s1与s2不是一个对象,false。
        out.println(s1.equals(s2));//"equals"的用法。s1与s2的值相同,true。
        out.println(s1.matches(s3));//"matches"用法。s1符合正则表达式s3,true。
        out.println(s1.contains(s3));//"contains"用法。s1不包含s2的内容,false。
        out.println(s1.contains(s4));//"contains"用法。s4是s1的子串,true。
    }
}
  • 『问题二』:查询API文档时发现,join()方法有以下两种传参方式:

具体怎么使用呢?

  • 『问题二解决』

第一种:join(分隔符,字符串1,字符串2...),如下:

String message = String.join("-", "Java", "is", "cool");
     // message returned is: "Java-is-cool"

第二种:join(分隔符,Iterable操作对象),如下:

Set<String> strings = new LinkedHashSet<>();
     strings.add("Java"); strings.add("is");
     strings.add("very"); strings.add("cool");
     String message = String.join("-", strings);
     //message returned is: "Java-is-very-cool"
  • 『问题三』:正则表达式的构造需要注意哪些问题?参考以下几个示例:

    • 偶数?

    • 模式为(xxx)xxx-xxxx的电话号码?

    • Java中的标识符?

  • 『问题三解决』:我在第六周博客中记录了正则表达式的相关学习内容。这次借助这个机会再进行巩固,加深理解。

    • 偶数:[\ \d*] [02468]

    • 模式为(xxx)xxx-xxxx的电话号码: \ \([\ \d]{3} ) [\ \d]{3}-[\ \d]{4}

    『注意』括号()在正则表达式中是特殊字符,即分组。如需表示电话号码前三位的括号,需要利用转义符“\”。而在Java中,“\”也是特殊字符,需要再次转义,也就 是“\\”。

    • Java中的标识符:首先,标识符必须以字母、下划线( _ )或美元符号($)组成。其次,标识符是包含数字,字母、下划线( _ )或美元符号($)的字符序列。因此可以描述为:[a-zA-Z_$] [\ \w$]*

    『注意』\w表示词的一个字符,即[a-zA-Z_0-9]。

  • 『问题四』:为什么要记录日志?日志的基本用法有哪些?对于程序员来说,又需要注意什么呢?(参考书籍:JAVA核心技术(卷1)

  • 『问题四解决』

    • 对于一些有问题的程序,我们常常在代码中插入一些调用System.out.println方法的语句来帮助观察程序运行的操作过程。但发现问题后删除这些代码变得异常繁琐,所以记录日志API就是为了解决这个问题产生的。

    • 日志管理系统中名为Logger.global的默认日志记录器可以代替System.out,并通过调用info方法记录日志信息。『注意』:记录自动包含时间、调用的类名和方法名。

    • main方法开始处调用Logger.global.setLevel(Level.OFF)将会取消所有日志,免去了很多麻烦。

    • 通常有以下七个日志记录器级别:SEVERWARNINGINFOCONFIGFINEFINERFINEST默认情况下,只记录前三个级别。也可以设置其他级别,如logger.setlevel(Level.FINE)。另外,还可以使用Level.ALL开启所有级别的记录,用Level.OFF关闭所有级别的记录。使用log方法可以指定级别:logger.log(Level.FINE,message)

    • 记录日志的常见用途是记录不可预料的异常,如以下程序:

    try
    {
    ...
    }
    catch(SomeException e)
    {
     logger.log(Level.FINE, "explanation", e)
     }
    
    • 需要注意的是,所有级别为SEVERWARNINGINFO的消息都会被打印到控制台上。因此,最好只将对程序用户有意义的消息设置为这三个级别。而对于程序员想要的日志记录,可以设定为FINE

返回目录

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

  • 『问题一』:运行课本P493的程序时,对end()方法的使用产生疑问:以0开始,为什么调用end()方法打印的不是最后一个字符所在处的索引?而是所在处索引+1?

  • 『问题一解决』

编写以下程序查看start()end()打印的结果:

import java.util.regex.*;
public class endDemo {
    public static void main(String []args){
        Pattern pt = Pattern.compile(".*?foo");
        Matcher mc = pt.matcher("xfooxxxxxfoo");
        while(mc.find()) {
            String s =  String.format("从索引 %d 到索引 %d 找到符合文字: \"%s\"%n",mc.start(),mc.end(),mc.group());
            System.out.println(s);
        }
    }
}

原因如下图:

start()从索引0开始,这个没问题;当不断寻找,直到索引12发现find()方法返回值为false,即查找失败,此时索引返回值即为end()返回值,所以是12。

也就是说,start()end()同时使用时,是包含头不包含尾的。

  • 『问题二』:显式类型转换、隐式类型转换与instanceof

  • 『问题二解决』

①隐式类型转换:Object o = new Student()由于Student的实例自动为Object的实例,所以该语句是合法的。

②显式类型转换:Student s = (Student) oObject对象不一定是Student的实例,所以必须使用显式类型转换,告诉编译器。

instanceof:在进行转换时要确保该对象是另一个对象的实例,一个好习惯就是使用运算符instanceof来完成。比如以下代码:

class Person {
}
class Student extends Person {
}
class Postgraduate extends Student {
}
class Animal {
}
public class Ex_instanceOf {
    public static void main(String[] args) {
        instanceofTest(new Student());//建立了类Student的实例
    }
    public static void instanceofTest(Person p) {
        //if(p instanceof Animal)System.out.println("p是类Animal的实例");//p 和 Animal类型不一样,彼此之间没有继承关系,会发生实时异常ClassCaetException
        if (p instanceof Postgraduate) System.out.println("p是类Postgraduate的实例");//false
        if (p instanceof Person) System.out.println("p是类Person的实例");//true
        if (p instanceof Student) System.out.println("p是类Student的实例");//true
        if (p instanceof Object) System.out.println("p是类Object的实例");//true
    }
}

Person类所在的继承树是:Object<--Person<--Student<--Postgraduate。p是类Student的实例,所以p instanceof Postgraduate返回值为false,其他均为true。

  • instanceof运算符用法

运算符是双目运算符,左面的操作元是一个对象,右面是一个类.当左面的对象是右面的类创建的对象时,该运算符运算的结果是true,否则是false 。

说明:

(1)一个类的实例包括本身的实例,以及所有直接或间接子类的实例 

(2)instanceof左边操作元显式声明的类型与右边操作元必须是同种类或右边是左边父类的继承关系 

(3)不同的继承关系下,编译出错  
  • 『问题三』:关于toString()方法的一点疑问...

toString()Object中一个重要的方法,一般情况下返回值为getClass().getName() + '@' + Integer.toHexString(hashCode()),即返回类名(对象是该类的一个实例)+ @ + 此对象哈希码的无符号十六进制表示。并且,只要对象与一个字符串通过操作符“+”连接起来,Java编译就会自动调用toString方法,以便获得这个对象的字符串描述。也就是说,调用x.toString()方法的地方可以用""+x代替。

但是,问题在于,Arrays和Point都继承了toString方法,而Arrays的打印结果却不是字符串表示呢?如以下代码:

public class toStringDemo {
    public static void main(String[] args){
        int[] Numbers = {1, 2, 3};
        Point p = new Point(1, 2);
        String s1 = ""+Numbers;
        String s2 = ""+p;
        System.out.println(s1);//运行结果:[I@74a14482
        System.out.println(s2);//运行结果:java.awt.Point[x=1,y=2]
    }
}
  • 『问题三解决』

查阅相关资料了解到,数组必须调用静态方法Arrays.toString,也就是将以上程序中的String s1 = ""+Numbers;改为String s1 = Arrays.toString(Numbers);。如果要打印多维数组,则需要调用Arrays.deepToString方法。

返回目录

代码托管

返回目录

上周考试错题总结

  • 『问题一』下面哪些Linux 命令可以ASCII码和16进制单字节方法输出Hello.java的内容?(BC)

A .od -b -tx1 Hello.java

B .od -tcx1 Hello.java

C .od -tc -tx1 Hello.java

D .od -tbx1 Hello.java

『考点』本题涉及到Linux下od命令,其使用方法简单总结如下:

od命令用于将指定文件内容以八进制、十进制、十六进制、浮点格式或ASCII编码字符方式显示,通常用于显示或查看文件中不能直接显示在终端的字符。od命令系统默认的显示方式是八进制。

  • 命令格式:od [<选项><参数>] [<文件名>]

  • -t:选择输出格式。格式为:-t [acdfoux][size].

    a:每个ASCII码对应的名字。

    b:用八进制字节表示的字符对应的ASCII码值

    d:有符号数值,SIZE个字节

    f:浮点数,SIZE个字节

    o:八进制数,SIZE个字节

    u:无符号数值,SIZE个字节

    x:十六进制数,size个字节(-tx1为单字节输出,-tx2为双字节输出)

本题要求以ASCII码和16进制单字节方法输出,即可以表示为od -tcx1 Hello.javaod -tc -tx1 Hello.java

  • 『问题二』When applied to instance variables, the ________________ visibility modifier enforces encapsulation(当应用到实例变量时,____可见性修饰符强制执行封装).(A)

A .static

B .final

C .public

D .private

E .none of the above

『考点』私有可见性修饰符防止不适当的数据访问,因此促进封装。选项A和B不是可见性修饰符,而选项C是可见性修饰符,允许对对象数据的公共访问,这违背了封装的原则。

  • 『问题三』When an object is passed to a method, the actual and formal parameters become aliases(当把对象传递给方法时,实参和形参互为别名).(√)

『考点』实际参数是传到方法中的数据。方法定义中使用了形式参数。当对象被传到一个方法时,这些值都是引用,它们成为彼此的别名。

  • 『问题四』Given the following, which answers can correctly fill in the blank? (Choose all that apply.)针对下面的代码,()中应填入哪个选项?(ABF)
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.now();
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = ZonedDateTime.of(dateTime, zoneId);
long epochSeconds = 0;
Instant instant = (              );

A .Instant.now()

B .Instant.ofEpochSecond(epochSeconds)

C .date.toInstant()

D .dateTime.toInstant()

E .time.toInstant()

F .zonedDateTime.toInstant()

『考点』选项A正确创建当前瞬间。选项B正确地转换从秒到瞬间。选项F也是一个适当的转换。选项C、D和E是不正确的,因为对象没有包含时区,java不知道什么时候使用。

  • 『问题五』What is the output of the following code?(下面代码的运行结果是?)(B)
LocalDate date = LocalDate.of(2018, Month.APRIL, 30);
date.plusDays(2);
date.plusYears(3);
System.out.println(date.getYear() + " "
+ date.getMonth() + " "+ date.getDayOfMonth());

A .2018 APRIL 2

B .2018 APRIL 30

C .2018 MAY 2

D .2021 APRIL 2

E .2021 APRIL 30

F .2021 MAY 2

G .A runtime exception is thrown.

『考点』:plusDays()是对时间运算的一种方法,但要注意本题中的程序没有返回值。若改为:

		date = date.plusDays(2);
        date = date.plusYears(3);

则选项F正确。

返回目录

结对及互评

卢梓杰
罗佳琪
张旭
朱玥
苏黄永郦

结对对象:20145202马超
结对学习内容:解决对方学习过程中遇到的问题

返回目录

学习感悟及思考

  • 本学期学习进程过半,借着本周蓝墨云“学习情况反馈”的机会,我对自己的学习状态进行了深刻的反思。有些值得保持,存在的问题则需要改正。感悟及思考大致总结如下:

『关于写博客』:

这是一种全新的学习方式。总结一周的学习成果,老师进行在线评论,同学之间在线互动。虽然老师的工作量大大增加,但对于学生来说百利而无一害。

程序员中有一种很流行的“小黄鸭调试法”,当程序出现bug时,对着桌上的小黄鸭叨叨一番,分析分析错误,往往问题就迎刃而解了。在我看来,写博客也能达到同样的效果。有了疑问贴到博客上,接着就要思考怎么解决呢?最佳方法是什么呢?怎样才能让叙述更加清晰明了呢?如果能让有同样疑问的人看过之后都明白,这才算是真正透彻地理解了。

另外,每周完成上万字的博客也是提高写作水平的绝佳手段,尤其对于我们而言。如果能在分享知识的同时稍微斟酌一下词句,公文写作的能力也能得到锻炼。

『关于如何解决问题』:

每周学习都会产生很多大大小小的疑惑,包括教材学习过程中发现的,也有调试代码时遇到的。我根据自己的理解,将解决问题的方式分成了以下三种:

第一,上网或查阅书籍资料以及查询API文档解决。这种方式效率很高,基本上很快就能释疑,对于简单的问题不失为一种高效的方法。 第二,动手编程验证。就我而言,印象最深的,是第七周解决由clone()产生的关于“深层复制”和“浅层复制”的疑问。疑问越挖越多,查询了很多资料还是觉得没有真正理解掌握,决定自己编写程序,尝试各种拷贝方式并查看打印结果,最终才理解了DeepCopy与ShallowCopy的真正含义。 第三,请教老师或同学。这种方法最容易,最靠谱,往往可以直接得到答案。一些根本没有思路,或是通过查询资料和动手编程都不能解决的问题,可以向他人求助。不过得到解答并不应该是最终目的,回去之后应该结合自己解决问题的尝试过程再深入分析,看看自己的理解究竟哪里出了偏差。这样才能有所提高。

『关于学习心态与自我调整』:

自学过程道阻且艰,特别是第一次接触如此彻底的自学。刚开始内容比较简单,虽然多不过稍用点心就能get到课本的知识点。但越学越深,渐渐接触到Java思想的内涵和精髓,理解起来难度也就逐渐加大了。

尤其是最近几周,我常常为纷繁的念头烦扰,比如不熟悉类的各种构造方法以至于不能灵活使用,比如随堂测试成绩不理想,比如翻了翻BAT招聘面试题发现没几道会的,比如...噼里啪啦涌现出各种问题。所以越学越觉得自己菜,知识网的漏洞也一个一个暴露出来。

不过还好这些都只是一闪而过的念头,每次状态不佳都会逼自己钻进书本,不断产生疑问并解决疑问的过程才是最充实的。遇到问题就解决,方法欠妥就修正,正视自己存在的不足,迎难而上,我想没有什么做不到吧:)

『关于学习的深度与广度』:

不得不说,课本内容不仅新,而且非常适合初学者。比如关于对象及对象的引用的介绍就生动形象,易于理解。但课本仅仅领我们进了门,要想深入理解还需要参考其他资料。像机械工业出版社的《Java语言程序设计基础篇》,像老师在蓝墨云上传的《Head First Java》电子版等等,包括CSDN网站上的博客,以及维基百科,都是非常优秀的资料,值得我们借鉴学习。所以,学习的道路前辈已为我们铺好,而在Java这条路上能走多远,能领略多少风景,就在于我们自己。

  • 最后,再次感谢各位不吝赐教的前辈,也要感谢与我并肩作战、探讨问题的同学,希望我们都能走到更广阔的天地,欣赏更美丽的风景:)

返回目录

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 16/16 1/1 18/18 初步认识了Java
第二周 219/235 1/2 28/46 学习了Java的基本语法知识
第三周 766/1001 1/3 23/69 了解对象与参考的关系,以及封装的概念与实现
第四周 984/1985 1/4 18/87 学习了继承与多态的关系,以及接口的多态操作
第五周 866/2851 1/5 12/99 学习了异常处理,学会使用Collection收集对象
第六周 664/3515 1/6 15/114 认识字节流和字符流的继承架构,学习线程与并行API
第七周 469/3984 1/7 13/127 认识Date与Calender
第八周 315/4299 1/8 15/142 学习了NIO、日志、正则表达式等内容,复习第六章“继承与多态”和“Linux 目录结构及文件基本操作”

尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。

参考:软件工程软件的估计为什么这么难软件工程 估计方法

  • 计划学习时间:10小时

  • 实际学习时间:15小时

(有空多看看现代软件工程课件:软件工程师能力自我评价表)

返回目录

参考资料

posted @ 2017-04-14 21:05  0x14b7狄  阅读(939)  评论(4编辑  收藏  举报