java基礎(chǔ)-時(shí)間相關(guān)(篇二 java8)

接前一篇 java基礎(chǔ)-時(shí)間相關(guān)(篇一 java7)

這一篇我們講一下java8中時(shí)間類(lèi)的基本使用,順便講一下final修飾符的作用。

基于java7中時(shí)間類(lèi)的諸多問(wèn)題仲墨,在Java8中進(jìn)行了改進(jìn)

首先勋磕,還是一個(gè)常規(guī)使用的代碼悼枢,可以和java7進(jìn)行對(duì)比狂男。

 //@Test
    public void java8DateTest(){
        //日期
        LocalDate date = LocalDate.now();
        System.out.println(date.toString());
        //output 2019-11-20

        //分別獲取年月日
        System.out.printf("年=%d  月=%d  日=%d",date.getYear(),date.getMonthValue(),date.getDayOfMonth());
        System.out.println(" ");
        //output 年=2019  月=11  日=20

        //時(shí)間
        LocalTime time = LocalTime.now();
        System.out.println(time.toString());
        //output 17:58:08.508


        LocalDateTime now = LocalDateTime.now();
        System.out.println(now.toString());
        //output 2019-11-20T18:17:24.565
        System.out.println(now.toLocalDate());
        //output 2019-11-20
        System.out.println(now.toLocalTime());
        //output 18:17:24.565

        //日期和字符串轉(zhuǎn)換
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 日期時(shí)間轉(zhuǎn)字符串
        String nowText = now.format(formatter);
        System.out.println("nowText= " + nowText);
        //output nowText= 2019-11-20 18:19:35

        // 字符串轉(zhuǎn)日期時(shí)間
        String datetimeText = "2019-11-20 23:59:59";
        LocalDateTime datetime = LocalDateTime.parse(datetimeText, formatter);
        System.out.println(datetime);
        //output 2019-11-20T23:59:59

        long timeStamp = 1574245577429L;
        Instant instant = Instant.ofEpochMilli(timeStamp);
        String timeToStr = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).format(formatter);
        System.out.println(timeToStr);
        //output 2019-11-20 18:26:17

        long timeStamp2 = now.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        System.out.println(timeStamp2);
        //output 1574245919701

        now = LocalDateTime.now();
        System.out.println(now.toLocalTime());
    }

上一篇我們講到综看,java7的SimpleDateFormat有線程安全的問(wèn)題,java8里怎么解決的呢岖食。
首先红碑,如果不使用format,在java8里泡垃,直接把時(shí)間戳轉(zhuǎn)化為字符串

    @Test
    public void timestampToStr(){
        long times = System.currentTimeMillis();
        Instant instant = Instant.ofEpochMilli(times);
        ZoneId zone = ZoneId.systemDefault();
        System.out.println(LocalDateTime.ofInstant(instant, zone));
    }

得到的字符串是

2020-03-12T18:33:00.041

這個(gè)比java7的格式友好一些析珊,基本能用了
如果需要format呢,添加一個(gè)format即可

    @Test
    public void timestampToStr(){
        long times = System.currentTimeMillis();
        Instant instant = Instant.ofEpochMilli(times);
        ZoneId zone = ZoneId.systemDefault();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(formatter.format(LocalDateTime.ofInstant(instant, zone)));
    }

得到的輸出格式是

2020-03-12 18:38:37

首先蔑穴,DateTimeFormatter 不會(huì)再犯 SimpleDateFormat 中的錯(cuò)誤忠寻,放一個(gè)公共變量在里面,讓不同的線程都能修改存和。DateTimeFormatter 中的公共變量奕剃,都使用了 final修飾,final修飾有啥用呢捐腿,我們寫(xiě)個(gè)demo來(lái)測(cè)試一下纵朋。

首先,不去思考final的正確用法茄袖,我們一步一步的來(lái)操软。
按照常規(guī)的思維,寫(xiě)一個(gè)類(lèi)

public class FinalDemo {
   private final Integer number;
   
   public void setNumber(Integer number){
       this.number = number;
   }

}

這個(gè)寫(xiě)出來(lái)后宪祥,idea提示了兩個(gè)錯(cuò)誤
第一個(gè)是

private final Integer number;

提示錯(cuò)誤:number沒(méi)有被初始化

第二個(gè)是

this.number = number;

提示錯(cuò)誤:不能給final變量number賦值聂薪。

根據(jù)上面的錯(cuò)誤提示,我們知道

  1. final變量需要初始化蝗羊。
  2. final變量在第一次賦值后胆建,不能修改。

DateTimeFormatter 中的公共變量肘交,都是final修飾的笆载,首先保證了一點(diǎn),在第一次賦值之后涯呻,不能修改凉驻。

我們繼續(xù)研究一下final,既然說(shuō)到這里复罐,就把這個(gè)搞清楚涝登。
我們修改一下demo。

public class FinalDemo {
    public final Integer number = 3;

    public Integer getNumber(){
        return number;
    }

}

然后效诅,我們寫(xiě)一個(gè)測(cè)試方法胀滚,去使用它

@Test
    public void finalTest(){
        FinalDemo finalDemo = new FinalDemo();
        System.out.println(finalDemo.number);
    }

可以拿到number的值趟济,我們?cè)谶@里進(jìn)行修改呢

@Test
    public void finalTest(){
        FinalDemo finalDemo = new FinalDemo();
        System.out.println(finalDemo.number);
        finalDemo.number = 5;
        System.out.println(finalDemo.number);
    }

會(huì)提示報(bào)錯(cuò)

Error:(95, 18) java: 無(wú)法為最終變量number分配值

也就是final的值,在第一次賦值后咽笼,無(wú)法修改顷编。
接下來(lái),我們修改一下代碼

public class FinalNumberDemo {
    private final Integer number;

    FinalNumberDemo(Integer number){
        this.number = number;
    }

    public Integer getNumber(){
        return this.number;
    }

    public void setNumber(Integer number){
        this.number = number;
    }
}

這里剑刑,我們?cè)跇?gòu)造函數(shù)里給number賦值媳纬,這里,沒(méi)有在聲明number的地方報(bào)錯(cuò)施掏,因?yàn)樵跇?gòu)造函數(shù)中賦值钮惠,就保證了number在使用的時(shí)候,就已經(jīng)有初始值了七芭。
同時(shí)素挽,我們加入了get和set方法。在idea中狸驳,會(huì)提示set方法有錯(cuò)毁菱,不能改變final變量的值,我們不管锌历,寫(xiě)一個(gè)方法來(lái)調(diào)用看看贮庞。

    @Test
    public void finalTest(){
        FinalNumberDemo finalNumberDemo = new FinalNumberDemo(3);
        System.out.println(finalNumberDemo.getNumber());
        finalNumberDemo.setNumber(4);
        System.out.println(finalNumberDemo.getNumber());
    }

執(zhí)行起來(lái)也是會(huì)報(bào)錯(cuò)的。
好了究西,我們對(duì)final的特性有了一些了解窗慎,繼續(xù)看下面的demo。
首先卤材,我們創(chuàng)建一個(gè)用戶類(lèi)


public class User {
  private Long id;
  private String name;
  
  User(Long id,String name){
      this.id = id;
      this.name = name;
  }

  public Long getId() {
      return id;
  }

  public void setId(Long id) {
      this.id = id;
  }

  public String getName() {
      return name;
  }

  public void setName(String name) {
      this.name = name;
  }
}

非常簡(jiǎn)單的一個(gè)類(lèi)遮斥,記錄一個(gè)用戶的信息。
然后扇丛,我們用final來(lái)聲明它术吗。

public class FinalDemo {
 private final User user;

 FinalDemo(User user){
     this.user = user;
 }

 public User getUser(){
     return this.user;
 }

}

在這個(gè)demo中,我們?cè)跇?gòu)造函數(shù)里給user賦值帆精,符合final的要求较屿。
我們現(xiàn)在來(lái)使用這個(gè)demo

@Test
    public void finalTest(){
        User user = new User(1L,"Joe");
        FinalDemo finalDemo = new FinalDemo(user);
        User somebody = finalDemo.getUser();
        System.out.println(somebody.getId());
        System.out.println(somebody.getName());
        System.out.println("==========magic=========");
        user.setName("Li");
        System.out.println(somebody.getId());
        System.out.println(somebody.getName());
    }

我們先設(shè)置一個(gè)user進(jìn)去,然后卓练,修改user自己隘蝎,沒(méi)有去修改demo類(lèi)里面的user,結(jié)果會(huì)怎么樣呢

1
Joe
==========magic=========
1
Li

user的名字被修改了襟企。
為什么呢嘱么?
前面我們確定了final保證他指向的數(shù)據(jù)在第一次賦值之后是不可修改的
但是,引用類(lèi)型顽悼,本身存儲(chǔ)的是實(shí)際數(shù)據(jù)的地址曼振。
我們?nèi)绻麑⒁妙?lèi)型設(shè)定為final几迄,只保證了這個(gè)地址不變,但是地址指向的內(nèi)容是否變動(dòng)冰评,是保證不了的映胁。
用圖來(lái)簡(jiǎn)單說(shuō)明一下
首先,創(chuàng)建一個(gè)userA對(duì)象

image.png

在userA這個(gè)變量里面存儲(chǔ)的集索,是實(shí)際數(shù)據(jù)的地址屿愚。
如果這個(gè)時(shí)候汇跨,我們通過(guò)= 的方式务荆,賦值給userB

        User userA = new User();
        User userB = userA;

這樣操作,實(shí)際上是把userA里存的數(shù)據(jù)地址賦值給了userB穷遂,也就是說(shuō)函匕,userA和userB指向的是相同的數(shù)據(jù)


image.png

Talk is cheap. Show me the code.

        User userA = new User();
        userA.setId(1L);
        userA.setName("John");
        User userB = userA;
        System.out.println("userB id==>"+userB.getId());
        System.out.println("userB name==>"+userB.getName());
        System.out.println("================");
        userA.setName("John Snow");
        System.out.println("userB id==>"+userB.getId());
        System.out.println("userB name==>"+userB.getName());

輸出結(jié)果是:

userB id==>1
userB name==>John
================
userB id==>1
userB name==>John Snow

我們修改A的名字,B的名字跟著改了蚪黑,這下明白了吧盅惜。

好了,引用類(lèi)型的大致基本原理我們搞清楚了忌穿。
當(dāng)我們用final來(lái)修飾引用類(lèi)型的時(shí)候抒寂,保證的是,這個(gè)數(shù)據(jù)地址不可變掠剑,無(wú)法保證實(shí)際數(shù)據(jù)被修改屈芜。如果不了解這一點(diǎn),可能會(huì)搞出bug朴译。

好了井佑。java8的時(shí)間類(lèi),還有很多用法以及細(xì)節(jié)眠寿,不清楚的可以查看文檔或者百度躬翁。我們這里結(jié)合java7和java8的時(shí)間類(lèi)進(jìn)行對(duì)比,實(shí)際更多的是希望大家了解一下線程安全性相關(guān)問(wèn)題盯拱,在寫(xiě)代碼的時(shí)候盒发,有這么一個(gè)概念,不致于寫(xiě)出bug之后狡逢,找不到原因迹辐。如果后面有時(shí)間,我會(huì)繼續(xù)寫(xiě)線程相關(guān)的文章甚侣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末明吩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子殷费,更是在濱河造成了極大的恐慌印荔,老刑警劉巖低葫,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異仍律,居然都是意外死亡嘿悬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)水泉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)善涨,“玉大人,你說(shuō)我怎么就攤上這事草则「峙。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵炕横,是天一觀的道長(zhǎng)源内。 經(jīng)常有香客問(wèn)我,道長(zhǎng)份殿,這世上最難降的妖魔是什么膜钓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮卿嘲,結(jié)果婚禮上颂斜,老公的妹妹穿的比我還像新娘。我一直安慰自己拾枣,他們只是感情好沃疮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著放前,像睡著了一般忿磅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凭语,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天葱她,我揣著相機(jī)與錄音,去河邊找鬼似扔。 笑死吨些,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炒辉。 我是一名探鬼主播豪墅,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼黔寇!你這毒婦竟也來(lái)了偶器?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屏轰,沒(méi)想到半個(gè)月后颊郎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霎苗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年姆吭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唁盏。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡内狸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厘擂,到底是詐尸還是另有隱情昆淡,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布驴党,位于F島的核電站瘪撇,受9級(jí)特大地震影響获茬,放射性物質(zhì)發(fā)生泄漏港庄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一恕曲、第九天 我趴在偏房一處隱蔽的房頂上張望鹏氧。 院中可真熱鬧,春花似錦佩谣、人聲如沸把还。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吊履。三九已至,卻和暖如春调鬓,著一層夾襖步出監(jiān)牢的瞬間艇炎,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工腾窝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缀踪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓虹脯,卻偏偏與公主長(zhǎng)得像驴娃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子循集,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Win7下如何打開(kāi)DOS控制臺(tái)唇敞? a:開(kāi)始--所有程序--附件--命令提示符 b:開(kāi)始--搜索程序和文件--cmd...
    逍遙嘆6閱讀 1,587評(píng)論 4 12
  • 1、一個(gè)".java"源文件中是否可以包括多個(gè)類(lèi)(不是內(nèi)部類(lèi))?有什么限制疆柔?答:可以有多個(gè)類(lèi)蕉世,但只能有一個(gè)publ...
    岳小川閱讀 908評(píng)論 0 2
  • 開(kāi)篇問(wèn)題 為什么需要內(nèi)部類(lèi)? 為什么內(nèi)部類(lèi)婆硬,會(huì)持有外部類(lèi)的引用狠轻? 為什么匿名內(nèi)部類(lèi)使用到外部類(lèi)方法中的局部變量時(shí)需...
    奔向?qū)W霸的路上閱讀 225評(píng)論 0 0
  • ORACLE自學(xué)教程 --create tabletestone ( id number, --序號(hào)usernam...
    落葉寂聊閱讀 1,066評(píng)論 0 0
  • Java內(nèi)部類(lèi),相信大家都用過(guò)彬犯,但是多數(shù)同學(xué)可能對(duì)它了解的并不深入向楼,只是靠記憶來(lái)完成日常工作,卻不能融會(huì)貫通谐区,遇到...
    三好碼農(nóng)閱讀 951評(píng)論 0 3