HashMap匿名初始化和日期的時區問題
實際開發中遇到了一些奇怪的問題在這裡記錄下:
一、HashMap初始化
先來看段程式碼:
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map<String,Object> map = new HashMap<String, Object>(){{
put("key1","val1");
put("key2","val2");
}};
String str = new Gson().toJson(map);
System.out.println("str: "+str);
}
}
輸出:
str: null
初始化HashMap時,這裡的雙括號到底什麼意思代表什麼呢?先來看段程式碼
public class Test {
public Test() {
System.out.println("Constructor called:構造器被呼叫");
}
static {
System.out.println("Static block called:靜態塊被呼叫");
}
{
System.out.println("Instance initializer called:例項初始化塊被呼叫");
}
public static void main(String[] args) {
new Test();
System.out.println("=======================");
new Test();
}
}
輸出:
Static block called:靜態塊被呼叫
Instance initializer called:例項初始化被呼叫
Constructor called:構造器被呼叫
=======================
Instance initializer called:例項初始化被呼叫
Constructor called:構造器被呼叫
也就是說第一層括弧實際是定義了一個匿名內部類 (Anonymous Inner Class),第二層括弧實際上是一個例項初始化塊 (instance initializer block),這個塊在內部匿名類構造時被執行。這個塊之所以被叫做“例項初始化塊”是因為它們被定義在了一個類的例項範圍內。
上面程式碼如果是寫在 Test 類中,編譯後你會看到會生成 Test$1.class 檔案,反編譯該檔案內容:
import java.util.HashMap;
class Test$1 extends HashMap // 建立了一個 HashMap 的子類
{
Test$1()
{ // 第二個 {} 中的程式碼放到了構造方法中去了
put("key1","val1");
put("key2","val2");
}
}
匿名內部類寫法的潛在問題
文章開頭提到的寫法的好處很明顯就是一目瞭然。這裡來羅列下此種方法的壞處,如果這個物件要序列化,可能會導致序列化失敗。
1.此種方式是匿名內部類的宣告方式,所以引用中持有著外部類的引用。所以當序列化這個集合時外部類也會被不知不覺的序列化,當外部類沒有實現serialize介面時,就會報錯。
2.上例中,其實是宣告瞭一個繼承自HashMap的子類。然而有些序列化方法,例如要通過Gson序列化為json,或者要序列化為xml時,類庫中提供的方式,是無法序列化HashSet或者HashMap的子類的,從而導致序列化失敗。解決辦法:重新初始化為一個HashMap物件
new HashMap(map)
這種寫法,推而廣之,在初始化 ArrayList、Set 的時候都可以這麼玩,比如你還可以這麼玩:
List<String> names = new ArrayList<String>() {
{
for (int i = 0; i < 10; i++) {
add("A" + i);
}
}
};
System.out.println(names.toString()); // [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9]
二、時區問題
背景:在操作日期時經常會出現比資料庫多或少8小時的情況
原因:不同軟體或系統的預設時區不一致導致的
幾個時間名詞:
- GMT:格林威治標準時間
- UTC:世界協調時間
- DST:夏日節約時間
- CST:中國標準時間
其中GMT時間可以近似認為和UTC時間是相等的,但從精度上來說UTC時間更精確。其誤差值必須保持在0.9秒以內
CST= GMT + 8 =UTC + 8
2.1、ES的當前時區
預設儲存時間的格式是UTC時間,如果我們查詢es然後獲取時間日期預設的資料,會發現跟當前的時間差8個小時,這其實是正常的,因為es預設儲存是用的UTC時間,所以我們需要做的就是讀取long型時間戳,然後重新格式化成下面的時間戳,即可獲得正確的時間 :
yyyy-MM-dd HH:mm:ss
2.2、Mysql 當前時區
檢視mysql當前時間,當前時區
show variables like "%time_zone%";
MySQL中datetime和timestamp的區別及使用
1.對於timestamp,它把客戶端插入的時間從當前時區轉化為UTC(世界標準時間)進行儲存。查詢時,將其又轉化為客戶端當前時區進行返回;而對於datetime,不做任何改變,基本上是原樣輸入和輸出。
2.datetime佔用8個位元組,timestamp佔用4個位元組。timestamp利用率更高。
3.二者範圍不一樣。timestamp範圍:‘1970-01-01 00:00:01.000000’ 到 ‘2038-01-19 03:14:07.999999’; datetime範圍:’1000-01-01 00:00:00.000000’ 到 ‘9999-12-31 23:59:59.999999’。原因是,timestamp佔用4位元組,能表示最大的時間毫秒為2的31次方減1,也就是2147483647,換成時間剛好是2038-01-19 03:14:07.999999。
2.3、Linux當前時區
檢視當前時區
命令 : "date -R"
.Java8中基本只能通過當前位置所在城市名來獲取時區
ZoneId defaultZone = ZoneId.systemDefault(); System.out.println(defaultZone);
相關文章
- 2個例項幫你弄清Python的時間和日期問題Python
- PHP最佳實踐之日期、時間和時區PHP
- Odoo和其他SprinBoot框架同時存在時時區問題Odooboot框架
- 遇到的編碼問題、時區問題整理
- [20180608]asmcmd顯示檔案的日期時間問題ASM
- Java 8 的日期與時間問題解決方案Java
- Linux時區問題Linux
- Oracle的時區問題Time ZoneOracle
- beego orm中時區的問題GoORM
- Django的時區設定問題Django
- mysql的時區錯誤問題MySql
- 三,TreeMap和HashMap,TreeSet和HashMap的區別以及方法使用上的不同HashMap
- 日期和時間
- NSDate 時間比較中的時區問題.
- 日期格式化時註解@DateTimeFormat無效的問題分析ORM
- 日期初始化
- 日期元件初始化元件
- C#中Hashtable和HashMap的區別C#HashMap
- Django(13)django時區問題Django
- ganglia bogon(匿名使用者)問題Go
- Python 日期和時間Python
- Java日期和時間Java
- 日期和時間格式
- datetime日期和時間
- ArrayList,HashMap,LinkedList 初始化大小和 擴容機制HashMap
- JAVA系列:HashMap常見問題JavaHashMap
- 藍橋杯-日期問題
- HashMap解析(主要JDK1.8,附帶1.7出現的問題以及區別)HashMapJDK
- Docker容器中部署Django的時區問題DockerDjango
- 字串和日期時間的處理字串
- Java 8 日期和時間的APIJavaAPI
- MySQL 的日期和時間函式MySql函式
- java複習之HashMap和Hashtable的區別JavaHashMap
- [20180403]關於時區問題.txt
- 關於問問題和時間管理的感悟
- Java 類載入之匿名類和主類相互依賴問題Java
- Laravel MongoDB 時間區間查詢的問題LaravelMongoDB
- 使用 pytz 處理 Python 中的時區問題Python