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

教材学习内容总结

认识时间与日期

时间的度量

1.格林威治时间(GMT):通过观察太阳而得,因为地球公转轨道为椭圆形且速度不一,本身自传减速而造成误差。

2.世界时(UT):通过观测远方星体跨过子午线而得,受地球自转速度影响有误差。

3.国际原子时(TAI):将秒的国际单位定义为铯原子辐射振动9192631770周耗费的时间。

4.世界协调时间(UTC):保持TAI和UT时间误差不要过大采用了闰秒修正。

5.Unix时间:Unix系统时间表示法,定义为UTC时间1970年1月1日为起点经过的秒数,不考虑闰秒修正。

6.epoch:某个特定时间开始,时间轴上的某一瞬间。

年历

1.儒略历:现今公历的前身,修正了罗马历隔三年设置一闰年的错误,改采四年一闰。

2.格里高利历:改革了儒略历,将儒略历1582年10月4号星期四的隔天,订为格里高利历1582年10月15日星期五。

3.ISO 8601标准:统一时间日期的数据交换格式,例如:yyyy-mm-ddTHHH:MM:SS.SSS等。
时区

1.UTC偏移:精度每15度偏移1小时,通常表示Z符号。

2.日观节约时间:夏、冬日照时间差异很大时实施。

认识Date与Calendar

Date与DateFormat

1Date:取得系统时间,方法之一就是使用System.currentTimeMillis()方法,返回long类型整数,代表1970年1月1日0时0分0秒0毫秒至今经过的毫秒数。Date有两个构造函数可以使用,一个可使用epoch毫秒数构建,另一个为无自变量构造函数,内部亦是使用System.currentTimeMillis()取得毫秒数,调用getTime()可取得内部保存的epoch毫秒数值。

例:p429DateDemo.java运行结果image

DateFormat:DateFormat是个抽象类,其操作类是java.text.SimpleDateFormat,可以处理字符串时间格式。可以通过DateForm的各种静态方法进行格式化,使用模式字符串自定义格式,使用parse()方法将指定的字符串剖析为Date实例。

例:p430DateFormatDemo.java运行结果image

Calendar: 时间的运算

1.Calendar:想要取得某个时间日期信息,或者是对时间日期进行操作,可以使用Calendar实例。Calendar是个抽象类,java.util.GregorianCalendar是其子类,操作了儒略历与格里高利历的混合历。可以设定时间日期等字段,使用add()方法改变Calendar的时间,使用roll()方法加减日期中某个字段,使用after()或before()方法比较两个Calendar的时间日期先后。

2.TimeZone:Calendar时会使用默认时区,可以使用java.util.TimeZone的getDefault()来取得默认时区信息。

JDK8新时间日期API

机器时间 Instant

许多开发者并不知道过去有过日光节约时间,在取得Date实例后,被名称Date误导,认为他们代表日期,真正可靠的信息只有内含epoch毫秒数。所以不应该使用Data实例来得知人类观点的时间信息,可以使用Instant的静态方法now()取得代表Java epoch毫秒数的Instant实例。

人类时间(ISO8601 标准)

1.LocalDateTime:包括日期与时间。

2.LocalDate:只有日期,设定不存在的日期时会抛出DateTimeException错误。

3.LocalTime:只有时间。

4.ZonedDateTime:当补上时区信息后组合起来的时间实际上不存在时,ZonedDateTime会自动更正。

5.OffsetdateTime:单纯代表UTC偏移量,使用ISO 8601。

6.Year、YearMonth、Month、MonthDay:如果只想要表示年或月,使用Year或Month;如果想要表示年月或月日,使用YearMonth或MonthDay。

对时间的运算

1.TemporalAmount:TemporalAmount的操作类是Period和Duration。ofPattern()是java.time.format.DateTimeFormatter的静态方法,对于年、月、星期、日的日期差使用Period类定义,plus()方法可以接受Duration实例来计算,对于时间计量,类Duration来定义。

2.TemporalUnit:plus()方法另一重载版本接受java.time.temporal.TemporalUnit实例,java.time.temporal.ChronoUnit是TemporalUnit实作类,使用enum实作,定义了between()等方法。

3.TemporalAccessor:定义了只读的时间对象读取操作,实际上Temporal是TemporalAccessor子接口,增加了对时间的处理操作,像是plus()、minus()、with()等方法。

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

  • xx1问题:如下代码
import java.util.*;
import static java.lang.System.*;

public class a {
    public static void main(String[] args) {
        Date date1 = new Date(currentTimeMillis());
        Date date2 = new Date();

        out.println(date1.getTime());
        out.println(date2.getTime());
        out.println(System.currentTimeMillis());
    }
}

我将书中的代码稍微作了些修改,得到的结果与原来不同。如下图:image想知道为什么会这样。并且如果在代码末尾再多加入几个相同的

out.println(System.currentTimeMillis());

语句,即可得到相同的结果,与之前的结果不相同,如下图image

  • xx1解决方案
  • xx2问题:如何获得程序运行时间。
  • xx2解决方案:写出如下代码
import java.util.*;
import java.text.*;

public class c {
    public static void main(String[] args) throws Exception {
        long starTime=System.currentTimeMillis();
        Date begin = new Date();
        System.out.print("输入出生年月日(yyyy-mm-dd):");
        DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
        Date birthDate = dateFormat.parse(new Scanner(System.in).nextLine());
        Date currentDate = new Date();
        long life = currentDate.getTime() - birthDate.getTime();
        System.out.println("你今年的岁数为:" +
                (life / (365 * 24 * 60 * 60 * 1000L)));
        Date end = new Date();
        long endTime=System.currentTimeMillis();
        long Time=endTime-starTime;
        System.out.println(Time);
        long duration = end.getTime() - begin.getTime();
        System.out.println(duration);
    }
}

运行结果如图:image

  • 问题3:书上P439页代码输出如下image
    不理解第一行是如何生成的。
  • 解决方案:书上说如果组合起来的时间不存在,ZoneDateTime会自动更正。修改代码如下
LocalTime localTime = LocalTime.of(0, 0, 0);
        LocalDate localDate = LocalDate.of(1998, 4, 1);

得到如下输出image
故可知第一个时间是自己输入的时间,第二个时间是时差,我们在东八区故时差为8小时。

  • 问题4:对于ZoneOffset.UTC不太理解。输出为image
  • 解决:协调世界时(英:Coordinated Universal Time ,法:Temps Universel Coordonné),又称世界统一时间,世界标准时间,国际协调时间。英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。

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

  • xx1问题:如下代码:
import static java.lang.System.out;
import java.util.Calendar;

public class e {
    public static void main(String[] args) {
        Calendar birth = Calendar.getInstance();
        birth.set(1975, Calendar.MAY, 26);
        Calendar now = Calendar.getInstance();
        out.printf("岁数:%d%n", yearsBetween(birth, now));
        out.printf("天数:%d%n", daysBetween(birth, now));
    }

    public static long yearsBetween(Calendar begin, Calendar end) {
        Calendar calendar = (Calendar) begin.clone();
        long years = 0;
        while (calendar.before(end)) {
            calendar.add(Calendar.YEAR, 1);
            years++;
        }
        return years - 1;
    }

    public static long daysBetween(Calendar begin, Calendar end) {
        Calendar calendar = (Calendar) begin.clone();
        long days = 0;
        while (calendar.before(end)) {
            calendar.add(Calendar.DATE, 1);
            days++;
        }
        return days - 1;
    }
}

其中为什么调用clone()?

  • xx1解决方案:将clone()方法去掉后发现输出错误,如下图:image,是因为要在Calender实力上进行add()操作,这回修改Calender的值,故要在两个方法之前都加上clone()语句保证值不变。
  • xx2问题:如何运行一下代码
import java.time.*;
import java.util.Scanner;
import static java.lang.System.out;

public class HowOld2 {
    public static void main(String[] args) {
        out.print("输入出生年月日(yyyy-mm-dd):");
        LocalDate birth = LocalDate.parse(new Scanner(System.in).nextLine());
        LocalDate now = LocalDate.now();
        Period period = Period.between(birth, now);
        out.printf("你活了 %d 年 %d 月 %d 日%n", 
                period.getYears(), period.getMonths(), period.getDays());
    }
}


  • xx2解决方案
  • ...

代码托管

  • 代码提交过程截图:
    • 运行 git log --pretty=format:"%h - %an, %cd : %s" 并截图
  • 代码量截图:
    • 运行 find src -name "*.java" | xargs cat | grep -v ^$ | wc -l 并截图image

上周考试错题总结

  • 错题:下面哪条命令可以把 f1.txt 复制为 f2.txt ?(AC)

A .cp f1.txt f2.txt

B .copy f1.txt f2.txt

C .cat f1.txt > f2.tx

D .cp f1.txt | f2.tx

E .copy f1.txt | f2.tx

  • 理解情况:cat f1.txt > f2.tx 通过输出重定向实现了复制。
  • 错题2:What are some reasons to use a character stream, such as Reader/Writer, over a byte stream, such as InputStream/OutputStream? (Choose all that apply.)

在下列哪些情况下使用字符流(比如Reader/Writer)而不使用字节流(比如InputStream/OutputStream)?(AC)

A .More convenient code syntax when working with String data

B .Improved performance

C .Automatic character encoding

D .Built-in serialization and deserialization

E .Character streams are high-level streams

F .Multi-threading support

  • 理解情况:A:字符流包含能够非常便利处理字符串数据的方法,所以A是正确的;C:字符流有其特有的编码方式,能够自动处理字符编码问题,C也是正确的。
  • 错题:错题4:Which of the following are not java.io classes? (Choose all that apply.)
    A .BufferedReader

B .BufferedWriter

C .FileReader

D .FileWriter

E .PrintReader

F .PrintWriter

  • 理解情况:选E。经过查询书本,除了c选项剩下的都是java.io classes。
  • 错题下面代码中共有()个线程?
public class ThreadTest {
    public static void main(String args[]){
        MyThread myThread =new MyThread();
        Thread t1=new Thread(myThread);
        Thread t2=new Thread(myThread);
        t1.start();
        t2.start();
    }
}
class MyThread extends Thread {
    ...
}

A .1
B .2
C .3
D .4
正确答案: C

  • 理解情况:除了t1,t2还有main()主函数,但还应该有垃圾处理这一线程才对呀?
  • 错题:如果有以下代码段:
    Thread thread = new Thread(new ________________() {
    public void run() {...}
    });
    空白部分指定哪些类型可以通过编译?
    A .
    Runnable
    B .
    Thread
    C .
    Future
    D .
    Executor
  • 理解情况:
    答案: A B,解析:Thread类的构造方法中,需要一个实现了Runnable接口的对象,而new就是生成了个Runnable接口下的一个实例对象。而Thread 也实现了 Runnable 接口。
  • 结对及互评

评分标准

  1. 正确使用Markdown语法(加1分):

    • 不使用Markdown不加分
    • 有语法错误的不加分(链接打不开,表格不对,列表不正确...)
    • 排版混乱的不加分
  2. 模板中的要素齐全(加1分)

    • 缺少“教材学习中的问题和解决过程”的不加分
    • 缺少“代码调试中的问题和解决过程”的不加分
    • 代码托管不能打开的不加分
    • 缺少“结对及互评”的不能打开的不加分
    • 缺少“上周考试错题总结”的不能加分
    • 缺少“进度条”的不能加分
    • 缺少“参考资料”的不能加分
  3. 教材学习中的问题和解决过程, 一个问题加1分

  4. 代码调试中的问题和解决过程, 一个问题加1分

  5. 本周有效代码超过300分行的(加2分)

    • 一周提交次数少于20次的不加分
  6. 其他加分:

    • 周五前发博客的加1分
    • 感想,体会不假大空的加1分
    • 排版精美的加一分
    • 进度条中记录学习时间与改进情况的加1分
    • 有动手写新代码的加1分
    • 课后选择题有验证的加1分
    • 代码Commit Message规范的加1分
    • 错题学习深入的加1分
    • 点评认真,能指出博客和代码中的问题的加1分
    • 结对学习情况真实可信的加1分
  7. 扣分:

    • 有抄袭的扣至0分
    • 代码作弊的扣至0分
    • 迟交作业的扣至0分

点评模板:

  • 博客中值得学习的或问题:

    • xxx
    • xxx
    • ...
  • 代码中值得学习的或问题:

    • xxx
    • xxx
    • ...
  • 基于评分标准,我给本博客打分:XX分。得分情况如下:xxx

  • 参考示例

点评过的同学博客和代码

  • 本周结对学习情况
    • 20155224
    • 结对照片image
    • 结对学习内容
      • 上周错题的理解与掌握。
      • 第十三章教材学习中遇到的问题进行讨论。
      • 第十三章代码调试中遇到的问题进行讨论。
  • 上周博客互评情况

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 120/120 1/4 16/16 开始了JAVA学习的第一步!
第二周 346/466 1/5 23/36 了解并学习了Java基础语法
第三周 364/830 1/6 21/57 进一步了解java设计语句
第四周 570/1300 2/8 20/77 初步学习了继承与多态,接口与多态知识。
第五周 1056/2356 1/9 23/100 了解Java的异常处理,学习Collection和Map架构
第六周 960/3100 1/10 22/122 了解串流设计和线程
第七周 427/3527 2/12 20/144 了解Java中的时间,完成第二次实验

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

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

参考资料