-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
943 lines (592 loc) · 103 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>小宇宙</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="不忘初心,方得始终">
<meta property="og:type" content="website">
<meta property="og:title" content="小宇宙">
<meta property="og:url" content="http://sw926.github.io/index.html">
<meta property="og:site_name" content="小宇宙">
<meta property="og:description" content="不忘初心,方得始终">
<meta property="og:locale">
<meta property="article:author" content="sunwei">
<meta name="twitter:card" content="summary">
<link rel="alternate" href="/atom.xml" title="小宇宙" type="application/atom+xml">
<link rel="icon" href="/favicon.ico">
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/css/style.css">
<meta name="generator" content="Hexo 5.4.2"></head>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">小宇宙</a>
</h1>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="Search"></a>
</nav>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="http://sw926.github.io"></form>
</div>
</div>
</div>
</header>
<div class="outer">
<section id="main">
<article id="post-ADB-命令整理" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2020/05/14/ADB-%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/" class="article-date">
<time datetime="2020-05-14T02:45:27.000Z" itemprop="datePublished">2020-05-14</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Android/">Android</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/05/14/ADB-%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/">ADB 命令整理</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="显示当前的-Activity-栈"><a href="#显示当前的-Activity-栈" class="headerlink" title="显示当前的 Activity 栈:"></a>显示当前的 Activity 栈:</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell dumpsys activity activities | sed -En -e <span class="string">'/Running activities/,/Run #0/p'</span></span><br></pre></td></tr></table></figure>
<h2 id="设置-prop"><a href="#设置-prop" class="headerlink" title="设置 prop"></a>设置 prop</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell setprop <name> <value></span><br></pre></td></tr></table></figure>
<p>Firebase 是使用这个来控制是否开启 DebugView</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell setprop debug.firebase.analytics.app <package_name></span><br></pre></td></tr></table></figure>
<p>读取的使用 getprop</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell getprop debug.firebase.analytics.app</span><br></pre></td></tr></table></figure>
<p>在代码里面也可以读取:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">readProp</span><span class="params">(prop: <span class="type">String</span>)</span></span>: String? {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">val</span> process = Runtime.getRuntime().exec(<span class="string">"getprop <span class="variable">$prop</span>"</span>)</span><br><span class="line"> <span class="keyword">val</span> ir = InputStreamReader(process.inputStream)</span><br><span class="line"> <span class="keyword">val</span> input = BufferedReader(ir)</span><br><span class="line"> <span class="keyword">return</span> input.readLine()</span><br><span class="line"> } <span class="keyword">catch</span> (e: IOException) {</span><br><span class="line"> e.printStackTrace()</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">} </span><br></pre></td></tr></table></figure>
<p>这样就可以通过 adb 命令来控制某个功能的开关</p>
<h2 id="获取设备版本号"><a href="#获取设备版本号" class="headerlink" title="获取设备版本号"></a>获取设备版本号</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2020/05/14/ADB-%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/" data-id="cleghn5zz006tbbs6eo7gcoys" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2020/05/14/ADB-%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Android/" rel="tag">Android</a></li></ul>
</footer>
</div>
</article>
<article id="post-Kotlin-补坑" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2020/04/27/Kotlin-%E8%A1%A5%E5%9D%91/" class="article-date">
<time datetime="2020-04-27T03:50:37.000Z" itemprop="datePublished">2020-04-27</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Kotlin/">Kotlin</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/04/27/Kotlin-%E8%A1%A5%E5%9D%91/">Kotlin 补坑</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>Kotlin 的 Iterable 遍历基本上都是使用 forEach,在 for 语句中可以方便的使用 break 跳出循环,但是 forEach 代码块中不能使用 break,之前一直以为使用 <code>return@forEach</code> 能够跳出遍历,起到和 break 一样的作用,其实这是非常错误的,<code>return@forEach</code> 只能跳出本次 forEach 的代码块,相当于 continue。</p>
<p>究其原因,先看 forEach 的函数声明:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">inline</span> <span class="function"><span class="keyword">fun</span> <span class="type"><T></span> Iterable<span class="type"><T></span>.<span class="title">forEach</span><span class="params">(action: (<span class="type">T</span>) -> <span class="type">Unit</span>)</span></span>: <span class="built_in">Unit</span> {</span><br><span class="line"> <span class="keyword">for</span> (element <span class="keyword">in</span> <span class="keyword">this</span>) action(element)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>forEach 是一个 inline 函数,action 是一个高阶函数,<em>Kotlin的 return 只能返回具名函数或者匿名函数,并且在 Lambda 表达式内禁止使用 return</em>,但是如果 Lambda 表达式是内敛的,return 也可以内敛,那么就可以使用 return,不过这个 return 也只能跳出具名函数或者匿名函数,要跳出 Lambda,需要使用 return 加标签的形式,也就是 <code>return@forEach</code> 的形式,例如:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> listOf(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>).forEach {</span><br><span class="line"> <span class="keyword">if</span> (it == <span class="number">3</span>) {</span><br><span class="line"> <span class="keyword">return</span><span class="symbol">@forEach</span></span><br><span class="line"> }</span><br><span class="line"> println(it)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>return@forEach</code> 的标签 forEach 是编译器自动生成的,有一定的误导性,如果我们自己加标签的话就是:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> listOf(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>).forEach <span class="symbol">action@</span>{</span><br><span class="line"> <span class="keyword">if</span> (it == <span class="number">3</span>) {</span><br><span class="line"> <span class="keyword">return</span><span class="symbol">@action</span></span><br><span class="line"> }</span><br><span class="line"> println(it)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>return@action</code> 跳出的是 <code>inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit</code> 的 action 的 匿名函数,如果把 action 单独声明,就更加明了:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">val</span> action = <span class="function"><span class="title">fun</span><span class="params">(item: <span class="type">Int</span>)</span></span> {</span><br><span class="line"> <span class="keyword">if</span> (item == <span class="number">3</span>) {</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> }</span><br><span class="line"> println(item)</span><br><span class="line"> }</span><br><span class="line"> listOf(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>).forEach(action)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>action 中的 return 是结束本次的匿名函数,是不可能跳出 forEach 遍历的。</p>
<p>如果先结束遍历,可以再外层添加一个匿名函数,用 return加 Label 来返回这个函数</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">run {</span><br><span class="line"> listOf(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>).forEach <span class="symbol">action@</span>{</span><br><span class="line"> <span class="keyword">if</span> (it == <span class="number">3</span>) {</span><br><span class="line"> <span class="keyword">return</span><span class="symbol">@run</span></span><br><span class="line"> }</span><br><span class="line"> println(it)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2020/04/27/Kotlin-%E8%A1%A5%E5%9D%91/" data-id="cleghn5zq0058bbs64taigmae" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2020/04/27/Kotlin-%E8%A1%A5%E5%9D%91/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Kotlin/" rel="tag">Kotlin</a></li></ul>
</footer>
</div>
</article>
<article id="post-Kotlin的非空断言调用" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2020/04/22/Kotlin%E7%9A%84%E9%9D%9E%E7%A9%BA%E6%96%AD%E8%A8%80%E8%B0%83%E7%94%A8/" class="article-date">
<time datetime="2020-04-22T01:08:33.000Z" itemprop="datePublished">2020-04-22</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Kotlin/">Kotlin</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/04/22/Kotlin%E7%9A%84%E9%9D%9E%E7%A9%BA%E6%96%AD%E8%A8%80%E8%B0%83%E7%94%A8/">Kotlin的非空断言调用</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>Kotlin 中使用 if 进行判空后就可以在 if 代码块中安全使用了,但这只针对 val 类型的变量,非空的 var 类型变量在 代码块中使用还是会显示编译错误,但是在 let 代码块内就可以安全使用,原因有可能是变量可以在其他线程置为 null,例如:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.concurrent.ThreadLocalRandom</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Foo</span> {</span><br><span class="line"> <span class="keyword">val</span> name = <span class="string">"bar"</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> foo: Foo? = Foo()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> Thread(Runnable {</span><br><span class="line"> test1()</span><br><span class="line"> }).start()</span><br><span class="line"> Thread.sleep(<span class="number">1000</span>)</span><br><span class="line"> foo = <span class="literal">null</span></span><br><span class="line"> Thread.sleep(<span class="number">3000</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">test1</span><span class="params">()</span></span> {</span><br><span class="line"> foo?.let {</span><br><span class="line"> Thread.sleep(<span class="number">2000</span>)</span><br><span class="line"> println(it.name)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>在 <code>println(foo!!.name)</code> 一定会抛出空指针异常。<br>如果把 if 换成 let, 程序就能正常打印了:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">fun test2() {</span><br><span class="line"> foo?.let {</span><br><span class="line"> Thread.sleep(2000)</span><br><span class="line"> println(it.name)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>通过反编译来生成 Java 代码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span> (foo != <span class="literal">null</span>) {</span><br><span class="line"> Thread.sleep(<span class="number">2000L</span>);</span><br><span class="line"> <span class="type">Foo</span> <span class="variable">var10000</span> <span class="operator">=</span> foo;</span><br><span class="line"> <span class="keyword">if</span> (var10000 == <span class="literal">null</span>) {</span><br><span class="line"> Intrinsics.throwNpe();</span><br><span class="line"> }</span><br><span class="line"> <span class="type">String</span> <span class="variable">var0</span> <span class="operator">=</span> var10000.getName();</span><br><span class="line"> System.out.println(var0);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">test2</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Foo</span> <span class="variable">var10000</span> <span class="operator">=</span> foo;</span><br><span class="line"> <span class="keyword">if</span> (var10000 != <span class="literal">null</span>) {</span><br><span class="line"> <span class="type">Foo</span> <span class="variable">var0</span> <span class="operator">=</span> var10000;</span><br><span class="line"> Thread.sleep(<span class="number">2000L</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">var5</span> <span class="operator">=</span> var0.getName();</span><br><span class="line"> System.out.println(var5);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>两个方法的主要区别是 <code>test2()</code> 首先执行了一次赋值 <code>Foo var10000 = foo;</code>,我的理解是 Foo 对象是保存在堆上,foo 是一个静态的引用,<code>Foo var10000 = foo;</code> 这一步操作确保了在函数使用的是函数内的临时变量,不会被修改。</p>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2020/04/22/Kotlin%E7%9A%84%E9%9D%9E%E7%A9%BA%E6%96%AD%E8%A8%80%E8%B0%83%E7%94%A8/" data-id="cleghn5zo0050bbs64ugjbsbu" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2020/04/22/Kotlin%E7%9A%84%E9%9D%9E%E7%A9%BA%E6%96%AD%E8%A8%80%E8%B0%83%E7%94%A8/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Kotlin/" rel="tag">Kotlin</a></li></ul>
</footer>
</div>
</article>
<article id="post-Java-Time" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/11/02/Java-Time/" class="article-date">
<time datetime="2019-11-01T16:05:11.000Z" itemprop="datePublished">2019-11-02</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Java/">Java</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/11/02/Java-Time/">Java Time</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="Java-Time-简介"><a href="#Java-Time-简介" class="headerlink" title="Java Time 简介"></a>Java Time 简介</h2><p>Java Time 是 Java8 新加入的一个包,用来替换 Calendar、Date 这些 Java 类。Java Time 符合 JSR310 规范,JSR310 实际上有两个日期概念。第一个是Instant,它大致对应于<code>java.util.Date</code>类,因为它代表了一个确定的时间点,即相对于标准Java纪元(1970年1月1日)的偏移量;但与<code>java.util.Date</code>类不同的是其精确到了纳秒级别。第二个对应于人类自身的观念,比如<code>LocalDate</code>和<code>LocalTime</code>。他们代表了一般的时区概念,要么是日期(不包含时间),要么是时间(不包含日期),类似于<code>java.sql</code>的表示方式。此外,还有一个<code>MonthDay</code>,它可以存储某人的生日(不包含年份)。每个类都在内部存储正确的数据而不是像<code>java.util.Date</code>那样利用午夜12点来区分日期,利用<code>1970-01-01</code>来表示时间。</p>
<p>Java Time 中所有的时间对象都是 <strong>Immutable</strong> 的,是不可变的,和 <code>String</code> 一样,对象一旦生成就不能修改它的属性,这个保证了它们都是线程安全的。</p>
<p>在 Android 开发中使用 Java Time 需要 minSdkVersion 最低 Android O,api level 26,这基本是不可能的,现阶段使用 Java Time 需要使用替代方案,这个推荐两种:joda-time 和 Threetenabp。joda-time 的开发者也是 JSR310 的制定者,和 JSR310 api 基本一致,有少许差别,Threetenabp 是一个 backport 版本,和 JSR310 api 完全一致。为了以后迁移方便,最好还是使用 Threetenabp。Threetenabp 引入方法很简单,添加 dependencies</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">implementation <span class="string">'com.jakewharton.threetenabp:threetenabp:1.2.3'</span></span><br></pre></td></tr></table></figure>
<p>在 Application 中进行初始化</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onCreate</span><span class="params">()</span> {</span><br><span class="line"> <span class="built_in">super</span>.onCreate();</span><br><span class="line"> AndroidThreeTen.init(<span class="built_in">this</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="Java-Time-使用"><a href="#Java-Time-使用" class="headerlink" title="Java Time 使用"></a>Java Time 使用</h2><p>Java Time 由5个包组成:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">java.time <span class="comment">// 基础包</span></span><br><span class="line">java.time.chrono <span class="comment">// 年表,用于不同的日历系统</span></span><br><span class="line">java.time.format <span class="comment">// 格式化和解析时间和日期</span></span><br><span class="line">java.time.temporal <span class="comment">// 包括底层框架和扩展特性</span></span><br><span class="line">java.time.zone <span class="comment">// 包含时区支持的类</span></span><br></pre></td></tr></table></figure>
<p>我们主要使用的是基础包和 format,如果要使用农历、伊斯兰历会用到 chrono。我们从最常用的类开始介绍。</p>
<h3 id="LocalDateTime、LocalDate、LocalTime"><a href="#LocalDateTime、LocalDate、LocalTime" class="headerlink" title="LocalDateTime、LocalDate、LocalTime"></a>LocalDateTime、LocalDate、LocalTime</h3><p>这三个类都是无时区的本地时间,分别表示时间日期、日期、时间,最简单的构造方法是通过 <code>now()</code> 方法:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> localDateTime = LocalDateTime.now() <span class="comment">// 当前日期和时间 2020-04-21T09:55:27.429053</span></span><br><span class="line"><span class="keyword">val</span> localDate = LocalDate.now() <span class="comment">// 当前日期 2020-04-21</span></span><br><span class="line"><span class="keyword">val</span> localTime = LocalTime.now() <span class="comment">// 当前时间 09:55:27.429661</span></span><br></pre></td></tr></table></figure>
<p>它们之间可以通过一些方法转换:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">localDateTime.toLocalDate() <span class="comment">// LocalDateTime 转 LocalDate</span></span><br><span class="line">localDateTime.toLocalTime() <span class="comment">// LocalDateTime 转 LocalTime</span></span><br><span class="line"></span><br><span class="line">localDate.atTime(localTime) <span class="comment">// LocalDate 转 LocalDateTime</span></span><br><span class="line">localTime.atDate(localDate) <span class="comment">// LocalTime 转 LocalDateTime</span></span><br></pre></td></tr></table></figure>
<p>简单来说就是 LocalDateTime 可以提取时间和日期,LocalDate 填上时间成为 LocalDateTime, LocalTime 填上日期成为 LocalDateTime。</p>
<p>日期操作可以总结为以下几个:</p>
<ul>
<li>加 plus</li>
<li>减 minus</li>
<li>设置 with</li>
<li>转换 to</li>
<li>结合 at</li>
</ul>
<h3 id="at-系列方法"><a href="#at-系列方法" class="headerlink" title="at 系列方法"></a>at 系列方法</h3><p><code>localDate.atTime(localTime)</code> 就是一个日期结合时间成为一个 LocalDateTime,同样,LocalDateTime 结合时区成为 ZonedDateTime :</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> localDateTime = LocalDateTime.now()</span><br><span class="line">println(localDateTime)</span><br><span class="line"><span class="keyword">val</span> zonedDateTime = localDateTime.atZone(ZoneId.of(<span class="string">"UTC"</span>))</span><br><span class="line">println(zonedDateTime)</span><br></pre></td></tr></table></figure>
<p>ZonedDateTime 的输出就有时区了:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">2020-04-21T10:16:44.938773</span><br><span class="line">2020-04-21T10:16:44.938773Z[UTC]</span><br></pre></td></tr></table></figure>
<p>at 系列方法就是对内容的扩展。</p>
<h3 id="plus-x2F-minus-系列方法"><a href="#plus-x2F-minus-系列方法" class="headerlink" title="plus/minus 系列方法"></a>plus/minus 系列方法</h3><p>使用 plus/minus 开头的方法是对当前对象加/减一个单位生成一个新的对象,例如:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> localDateTime = LocalDateTime.now()</span><br><span class="line"><span class="keyword">val</span> nextMonth = localDateTime.plusMonths(<span class="number">1</span>) <span class="comment">// 加一个月</span></span><br><span class="line"><span class="keyword">val</span> yesterday = localDateTime.minusDays(<span class="number">1</span>) <span class="comment">// 减一天</span></span><br><span class="line"><span class="keyword">val</span> preHour = localDateTime.minusHours(<span class="number">1</span>) <span class="comment">// 减一小时</span></span><br></pre></td></tr></table></figure>
<h3 id="with-系列方法"><a href="#with-系列方法" class="headerlink" title="with 系列方法"></a>with 系列方法</h3><p>with 开头的方法是设置对应的属性的值生成一个新的对象,例如:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> localDateTime = LocalDateTime.now()</span><br><span class="line"><span class="keyword">val</span> jan = localDateTime.withMonth(<span class="number">1</span>) <span class="comment">// 设置为一月</span></span><br></pre></td></tr></table></figure>
<h3 id="to-系列方法"><a href="#to-系列方法" class="headerlink" title="to 系列方法"></a>to 系列方法</h3><p>to 开头的方法是转换的操作,例如:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> localDate = localDateTime.toLocalDate()</span><br></pre></td></tr></table></figure>
<p>转换只能是同级或者向下转换,例如同级转换:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> nanoOfDay = LocalTime.now().toNanoOfDay()</span><br><span class="line"><span class="keyword">val</span> epocSecond = ZonedDateTime.now().toEpochSecond()</span><br></pre></td></tr></table></figure>
<p>LocalTime 只能转换为从今天0点开始的多少纳秒,ZonedDateTime 可以转换为 epoc 时间戳。</p>
<p><strong>需要注意,所有对象都是 Immutable 的,以上的操作都是在原始对象的基础上生成一个新的对象,不会修改原来的对象。</strong></p>
<h3 id="时间对比"><a href="#时间对比" class="headerlink" title="时间对比"></a>时间对比</h3><p>Java Time 都实现了 equals 方法和 Comparable,想比较两个时间的先后,可以直接通过 <code>compareTo()</code> 方法:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> dateTime1 = LocalDateTime.now()</span><br><span class="line"><span class="keyword">val</span> dateTime2 = dateTime1.minusNanos(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">dateTime2.compareTo(dateTime1) <span class="comment">// 0 相等,负数 dateTime2 在 dateTime1 之前,正数 dateTime2 在 dateTime1 之后</span></span><br></pre></td></tr></table></figure>
<p>使用 Kotlin 的话就更加直观:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (dateTime1 > dateTime2) {</span><br><span class="line"> <span class="comment">// dateTime1 在 dateTime2 之后</span></span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (dateTime1 == dateTime2) {</span><br><span class="line"> <span class="comment">// dateTime1 dateTime2 相同</span></span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// dateTime1 在 dateTime1 之前</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="计算时间差"><a href="#计算时间差" class="headerlink" title="计算时间差"></a>计算时间差</h3><p>时间差可以使用 <code>ChronoUnit</code> 计算:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> localDate = LocalDate.of(<span class="number">2012</span>, <span class="number">12</span>, <span class="number">1</span>)</span><br><span class="line"><span class="keyword">val</span> localDate2 = LocalDate.of(<span class="number">2012</span>, <span class="number">11</span>, <span class="number">1</span>)</span><br><span class="line"><span class="keyword">val</span> days = ChronoUnit.DAYS.between(localDate2, localDate)</span><br><span class="line"><span class="keyword">val</span> months = ChronoUnit.MONTHS.between(localDate2, localDate)</span><br><span class="line"><span class="keyword">val</span> years = ChronoUnit.YEARS.between(localDate2, localDate)</span><br></pre></td></tr></table></figure>
<p>这个时间差计算的是绝对的时间差,一个月是一年的时间除以12,2012-12-1和2012-11-1月份相差1,2012-12-1和2012-11-10月份相差0。</p>
<h3 id="考虑时区的转换"><a href="#考虑时区的转换" class="headerlink" title="考虑时区的转换"></a>考虑时区的转换</h3><p>如果不考虑时区,LocalDateTime、LocalDate、LocalTime 这三个类已经够用了,如果考虑时区,就会遇到这样的问题:</p>
<ul>
<li>服务器接口是 UTC 时间,客户端需要转换为用户本地的世界</li>
<li>用户输入的时间是当前时区的时间,服务器接口要求是 UTC 时间</li>
<li>等等 …</li>
</ul>
<p>这就涉及到一些比较复杂的转换规则,我们先给 Java Time 的类按照包含内容的丰富程度拍个序,从小到大依次为:</p>
<ol>
<li>LocalDate/LocalTime</li>
<li>LocalDateTime/Instant</li>
<li>OffsetDateTime</li>
<li>ZonedDateTime</li>
</ol>
<p>Instant 是指从 0时区1970-01-01 0点的偏移时间,它能表示绝对时间,可以通过打印看一下它和 LocalDateTime 的区别:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> ms = System.currentTimeMillis()</span><br><span class="line"><span class="keyword">val</span> instant = Instant.ofEpochMilli(ms)</span><br><span class="line"></span><br><span class="line">println(<span class="string">"<span class="variable">$instant</span>"</span>)</span><br><span class="line">println(<span class="string">"<span class="subst">${LocalDateTime.now()}</span>"</span>)</span><br></pre></td></tr></table></figure>
<p>输出为:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">2020-04-21T04:03:53.886Z</span><br><span class="line">2020-04-21T12:03:53.947636</span><br></pre></td></tr></table></figure>
<p>Instant 多了一个 <code>Z</code>,用来表示是 UTC 时间,看样子 Instant 的内容应该丰富些,但是 Instant 不能进行日期计算,而且通过 LocalDateTime 获取 Instant 使用的是 <code>toInstant()</code>,从 api 命名也显示它们是一个平级的关系。</p>
<p>回到第一个问题,服务器的时间格式如果是标准的 iso 字符串,例如 <code>2020-04-21T04:03:53.886Z</code>,我们直接用 <code>Instant.parse()</code> 就可以,如果是时间戳,使用 <code>Instant.ofEpochMilli()</code> 或者 <code>Instant.ofEpochSecond()</code>,如果是 <code>2012-12-01 12:30:10</code>,使用如下方法:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> instant = LocalDateTime</span><br><span class="line"> .parse(<span class="string">"2012-12-01 12:30:10"</span>, DateTimeFormatter.ofPattern(<span class="string">"yyyy-MM-dd HH:mm:ss"</span>))</span><br><span class="line"> .toInstant(ZoneOffset.UTC)</span><br></pre></td></tr></table></figure>
<p>这样我们成功将服务器接口里面的时间转换为了 Instant 对象,下一步就可以将 Instant 转换为 LocalDateTime 来使用:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">LocalDateTime.ofInstant(instant, ZoneId.systemDefault()) // 默认时区</span><br><span class="line">LocalDateTime.ofInstant(instant, ZoneOffset.ofHours(8)) // 指定时区</span><br></pre></td></tr></table></figure>
<p>同理,用户输入的时间为转换为 UTC,假设用户在东8区</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> now = LocalDateTime.now()</span><br><span class="line"><span class="keyword">val</span> instant = now.toInstant(ZoneOffset.ofHours(<span class="number">8</span>))</span><br></pre></td></tr></table></figure>
<p>还有一种简单的方法:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">OffsetDateTime.now().toInstant()</span><br></pre></td></tr></table></figure>
<h3 id="OffsetDateTime-和-ZonedDateTime-区别"><a href="#OffsetDateTime-和-ZonedDateTime-区别" class="headerlink" title="OffsetDateTime 和 ZonedDateTime 区别"></a>OffsetDateTime 和 ZonedDateTime 区别</h3><p>OffsetDateTime 和 ZonedDateTime 都能表示绝对时间,都带有时区和时间日期。</p>
<p>我们的知道时区的概念,0 时区 0 点的时候,北京时间是 8 点,OffsetDateTime 对象中就带有这个偏移量,打印 OffsetDateTime:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">println(OffsetDateTime.now())</span><br></pre></td></tr></table></figure>
<p>输出为:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2020-04-21T13:00:40.823521+08:00</span><br></pre></td></tr></table></figure>
<p>当前时间是东八区下午一点,如果打印 ZonedDateTime:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">println(ZonedDateTime.now())</span><br></pre></td></tr></table></figure>
<p>输出为:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2020-04-21T13:02:56.629844+08:00[Asia/Shanghai]</span><br></pre></td></tr></table></figure>
<p>多了一个 ZoneId,通过这个 ZoneId,同一个时区下也可能时间不同,例如澳大利亚是是实行夏时令的,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。澳大利亚夏时令时间为 10-7 到 4-1,我们测试一下:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> zoneId = ZoneId.of(<span class="string">"Australia/Sydney"</span>)</span><br><span class="line">println(Instant.parse(<span class="string">"2018-05-01T08:00:00.000Z"</span>).atZone(zoneId))</span><br><span class="line">println(Instant.parse(<span class="string">"2018-11-01T08:00:00.000Z"</span>).atZone(zoneId))</span><br></pre></td></tr></table></figure>
<p>输出的结果为:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">2018-05-01T18:00+10:00[Australia/Sydney]</span><br><span class="line">2018-11-01T19:00+11:00[Australia/Sydney]</span><br></pre></td></tr></table></figure>
<p>同一个城市,UTC时间都是早上8点,但是5月1号悉尼是18点,11月1号悉尼是19点。这也说明了 ZonedDateTime 包含的内容要比 OffsetDateTime 多。</p>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2019/11/02/Java-Time/" data-id="cleghn5zp0053bbs6cip009fz" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2019/11/02/Java-Time/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Java-Time/" rel="tag">Java Time</a></li></ul>
</footer>
</div>
</article>
<article id="post-Tips-Java-Thread" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/07/03/Tips-Java-Thread/" class="article-date">
<time datetime="2019-07-03T04:35:25.000Z" itemprop="datePublished">2019-07-03</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Java/">Java</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/07/03/Tips-Java-Thread/">Tips:Java Thread</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="先看一个经典的多线程的例子:"><a href="#先看一个经典的多线程的例子:" class="headerlink" title="先看一个经典的多线程的例子:"></a>先看一个经典的多线程的例子:</h2><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">var</span> value = <span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">fun</span> <span class="title">increase</span><span class="params">()</span></span> {</span><br><span class="line"> value++</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">fun</span> <span class="title">printValue</span><span class="params">()</span></span> {</span><br><span class="line"> println(<span class="string">"value = <span class="variable">$value</span>"</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">val</span> a = A()</span><br><span class="line"> <span class="keyword">for</span> (i <span class="keyword">in</span> <span class="number">0</span> until <span class="number">100</span>) {</span><br><span class="line"> Thread(Runnable {</span><br><span class="line"> <span class="keyword">for</span> (j <span class="keyword">in</span> <span class="number">0</span> until <span class="number">100000</span>) {</span><br><span class="line"> a.increase()</span><br><span class="line"> }</span><br><span class="line"> }).start()</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 等待所有线程执行完,activeCount 根据环境不同,为 1 或 2</span></span><br><span class="line"> <span class="keyword">while</span> (Thread.activeCount() > <span class="number">2</span>) { </span><br><span class="line"> Thread.yield()</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> a.printValue()</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>输出的结果可能每次都不一样<br>同步的方法:</p>
<ul>
<li>synchronized</li>
<li>lock</li>
<li>使用 Atomic</li>
</ul>
<p>加上时间的统计,测试一下速度:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">val</span> start = System.currentTimeMillis()</span><br><span class="line"> <span class="keyword">val</span> a = A()</span><br><span class="line"> <span class="keyword">for</span> (i <span class="keyword">in</span> <span class="number">0</span> until <span class="number">100</span>) {</span><br><span class="line"> Thread(Runnable {</span><br><span class="line"> <span class="keyword">for</span> (j <span class="keyword">in</span> <span class="number">0</span> until <span class="number">100000</span>) {</span><br><span class="line"> a.increase()</span><br><span class="line"> }</span><br><span class="line"> }).start()</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (Thread.activeCount() > <span class="number">2</span>) {</span><br><span class="line"> Thread.yield()</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> a.printValue()</span><br><span class="line"> println(<span class="string">"spent: <span class="subst">${System.currentTimeMillis() - start}</span>ms"</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="首先使用-synchronized"><a href="#首先使用-synchronized" class="headerlink" title="首先使用 synchronized"></a>首先使用 synchronized</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">@Synchronized</span><br><span class="line">fun increase() {</span><br><span class="line"> value++</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>花费时间 <code>550ms</code> 左右。</p>
<p>还有一种方式是使用同步代码块:</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">val</span> lock = Any()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">increase</span><span class="params">()</span></span> {</span><br><span class="line"> synchronized(lock) {</span><br><span class="line"> value++</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>花费时间比使用 synchronized 函数要少一点,在 <code>480ms</code> 左右。</p>
<h2 id="使用-Lock"><a href="#使用-Lock" class="headerlink" title="使用 Lock"></a>使用 Lock</h2><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">val</span> lock = ReentrantLock()</span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">increase</span><span class="params">()</span></span> {</span><br><span class="line"> lock.lock()</span><br><span class="line"> value++</span><br><span class="line"> lock.unlock()</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>花费时间 <code>310ms</code> 左右</p>
<h2 id="最后使用-Atomic"><a href="#最后使用-Atomic" class="headerlink" title="最后使用 Atomic"></a>最后使用 Atomic</h2><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">var</span> value = AtomicLong()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">increase</span><span class="params">()</span></span> {</span><br><span class="line"> value.incrementAndGet()</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>花费时间 <code>230ms</code> 左右。</p>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2019/07/03/Tips-Java-Thread/" data-id="cleghn5zn004wbbs641dh3ku7" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2019/07/03/Tips-Java-Thread/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Java-Thread/" rel="tag">Java Thread</a></li></ul>
</footer>
</div>
</article>
<article id="post-Tips-sdkman" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/06/11/Tips-sdkman/" class="article-date">
<time datetime="2019-06-11T02:32:37.000Z" itemprop="datePublished">2019-06-11</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Other/">Other</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/06/11/Tips-sdkman/">Tips:sdkman</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><p><code>https://sdkman.io/install</code></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ curl -s <span class="string">"https://get.sdkman.io"</span> | bash</span><br><span class="line">$ <span class="built_in">source</span> <span class="string">"<span class="variable">$HOME</span>/.sdkman/bin/sdkman-init.sh"</span></span><br><span class="line">$ sdk version</span><br></pre></td></tr></table></figure>
<h1 id="安装-JDK"><a href="#安装-JDK" class="headerlink" title="安装 JDK"></a>安装 JDK</h1><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sdk list java</span><br></pre></td></tr></table></figure>
<p>输出:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">================================================================================</span><br><span class="line">Available Java Versions</span><br><span class="line">================================================================================</span><br><span class="line"> 19.0.0-grl 11.0.2-zulufx 1.0.0-rc-16-grl</span><br><span class="line"> 13.ea.24-open 10.0.2-zulu</span><br><span class="line"> 12.0.1-sapmchn 10.0.2-open</span><br><span class="line"> 12.0.1-zulu 9.0.7-zulu</span><br><span class="line"> 12.0.1-open 9.0.4-open</span><br><span class="line"> 12.0.1.j9-adpt 8.0.212-zulu</span><br><span class="line"> 12.0.1.hs-adpt 8.0.212-amzn</span><br><span class="line"> 12.0.1-librca 8.0.212.j9-adpt</span><br><span class="line"> 11.0.3-librca 8.0.212.hs-adpt</span><br><span class="line"> 11.0.3-sapmchn 8.0.212-librca</span><br><span class="line"> 11.0.3-zulu 8.0.202-zulu</span><br><span class="line"> 11.0.3-amzn 8.0.202-amzn</span><br><span class="line"> 11.0.3.j9-adpt 8.0.202-zulufx</span><br><span class="line"> 11.0.3.hs-adpt 7.0.222-zulu</span><br><span class="line"> 11.0.2-open 7.0.181-zulu</span><br><span class="line"></span><br><span class="line">================================================================================</span><br><span class="line">+ - <span class="built_in">local</span> version</span><br><span class="line">* - installed</span><br><span class="line">> - currently <span class="keyword">in</span> use</span><br><span class="line">================================================================================</span><br></pre></td></tr></table></figure>
<p>大部分人应该都是使用的 Oracle 版本的 JDK,各个版本的区别可以参考文章:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://www.oschina.net/news/99836/time-to-look-beyond-oracles-jdk</span><br></pre></td></tr></table></figure>
<p>然后安装:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sdk install java 8.0.212-zulu</span><br></pre></td></tr></table></figure>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2019/06/11/Tips-sdkman/" data-id="cleghn5zl004pbbs6he1x65ly" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2019/06/11/Tips-sdkman/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/sdkman/" rel="tag">sdkman</a></li></ul>
</footer>
</div>
</article>
<article id="post-Tips-SpringBoot-Properties" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/05/16/Tips-SpringBoot-Properties/" class="article-date">
<time datetime="2019-05-16T02:11:04.000Z" itemprop="datePublished">2019-05-16</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Java/">Java</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/05/16/Tips-SpringBoot-Properties/">Tips:SpringBoot Properties</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>新建项目里面都有一个 <code>application.properties</code>,我们可以在这个文件中添加一些属性,</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">test.foo=Hello</span><br><span class="line">test.bar=World </span><br></pre></td></tr></table></figure>
<p>在组件中可以通过添加 <code>@Value</code> 注解来读取</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping("/test")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestController</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Value("${test.foo}")</span></span><br><span class="line"> <span class="keyword">private</span> String foo;</span><br><span class="line"> <span class="meta">@Value("${test.bar}")</span></span><br><span class="line"> <span class="keyword">private</span> String bar;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@GetMapping("/hello")</span></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">hello</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> foo + <span class="string">" "</span> + bar;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>test/hello</code> 接口输出的是 <code>Hello World</code>,我们可以通过 Java 的 JVM Args 在运行的时候覆盖这些属性:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -Dtest.bar=bar -jar xxx.jar</span><br></pre></td></tr></table></figure>
<p>这样 <code>test/hello</code> 接口输出的是 <code>Hello bar</code>,那么 SystemProperties 有没有这些属性呢,实验一下,修改 <code>hello()</code> 为</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping("/hello")</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">hello</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> foo + <span class="string">" "</span> + bar + <span class="string">", from system: "</span> + SystemProperties.get(<span class="string">"test.foo"</span>) + <span class="string">" "</span> + SystemProperties.get(<span class="string">"test.bar"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>输出结果为:<code>Hello bar, from system: null bar</code>,看来 <code>application.properties</code> 是不会写入 SystemProperties 的,另外 <code>@Value</code> 不是直接读取 <code>application.properties</code> 的值,而是好几个源,有优先级的。<br><code>@Value</code> 可以注入一下的资源:</p>
<ul>
<li>注入普通字符串</li>
<li>注入操作系统属性</li>
<li>注入表达式结果</li>
<li>注入其他Bean属性:注入beanInject对象的属性another</li>
<li>注入文件资源</li>
<li>注入URL资源</li>
</ul>
<p>示例:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Value("normal")</span></span><br><span class="line"><span class="keyword">private</span> String normal; <span class="comment">// 注入普通字符串</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Value("#{systemProperties['os.name']}")</span></span><br><span class="line"><span class="keyword">private</span> String systemPropertiesName; <span class="comment">// 注入操作系统属性</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Value("#{ T(java.lang.Math).random() * 100.0 }")</span></span><br><span class="line"><span class="keyword">private</span> <span class="type">double</span> randomNumber; <span class="comment">//注入表达式结果</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Value("#{valueTestBean.name}")</span></span><br><span class="line"><span class="keyword">private</span> String fromAnotherBean; <span class="comment">// 注入其他Bean属性:注入beanInject对象的属性another,类具体定义见下面</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Value("classpath:resources/static/value_test.dat")</span></span><br><span class="line"><span class="keyword">private</span> Resource resourceFile; <span class="comment">// 注入文件资源</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Value("http://www.baidu.com")</span></span><br><span class="line"><span class="keyword">private</span> Resource testUrl; <span class="comment">// 注入URL资源</span></span><br></pre></td></tr></table></figure>
<p>Properties 的加载顺序可以查看官方文档</p>
<p><a target="_blank" rel="noopener" href="https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#boot-features-external-config">https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#boot-features-external-config</a></p>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2019/05/16/Tips-SpringBoot-Properties/" data-id="cleghn5zm004tbbs6fnyq7wck" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2019/05/16/Tips-SpringBoot-Properties/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Spring-Boot/" rel="tag">Spring Boot</a></li></ul>
</footer>
</div>
</article>
<article id="post-Tips-Mysql-显示-BIT" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/05/15/Tips-Mysql-%E6%98%BE%E7%A4%BA-BIT/" class="article-date">
<time datetime="2019-05-15T01:41:17.000Z" itemprop="datePublished">2019-05-15</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Other/">Other</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/05/15/Tips-Mysql-%E6%98%BE%E7%A4%BA-BIT/">Tips:Mysql 显示 BIT</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>在数据库中创建一个表,添加一个 <code>is_new</code> 的 column,类型为 <code>BIT</code>:</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `test_table`</span><br><span class="line">(</span><br><span class="line"> `id` <span class="type">BIGINT</span> <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT <span class="keyword">PRIMARY</span> KEY,</span><br><span class="line"> `is_new` BIT <span class="keyword">NOT</span> <span class="keyword">NULL</span> <span class="keyword">DEFAULT</span> b<span class="string">'0'</span></span><br><span class="line">);</span><br></pre></td></tr></table></figure>
<p>插入一条数据库:</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `test_table` <span class="keyword">SET</span> `is_new`<span class="operator">=</span><span class="number">1</span>;</span><br></pre></td></tr></table></figure>
<p>然后查询所有的数据:</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> `test_table`;</span><br></pre></td></tr></table></figure>
<p>显示结果为:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql> select * from test_table;</span><br><span class="line">+----+--------+</span><br><span class="line">| <span class="built_in">id</span> | is_new |</span><br><span class="line">+----+--------+</span><br><span class="line">| 1 | |</span><br><span class="line">+----+--------+</span><br><span class="line">1 row <span class="keyword">in</span> <span class="built_in">set</span> (0.00 sec)</span><br></pre></td></tr></table></figure>
<p>数据插入成功了,但是 <code>is_new</code> 的值不显示,换个图形化工具,可以查到这个值是 <code>1</code>,那么在命令行怎么查看呢?两种方法:</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> `id`, bin(`is_new`) <span class="keyword">FROM</span> `test_table`;</span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> `id`, ord(`is_new`) <span class="keyword">FROM</span> `test_table`;</span><br></pre></td></tr></table></figure>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">mysql> SELECT `id`, bin(`is_new`) FROM `test_table`;</span><br><span class="line">+----+---------------+</span><br><span class="line">| id | bin(`is_new`) |</span><br><span class="line">+----+---------------+</span><br><span class="line">| 1 | 1 |</span><br><span class="line">+----+---------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql> SELECT `id`, bin(`is_new`) FROM `test_table`;</span><br><span class="line">+----+---------------+</span><br><span class="line">| id | bin(`is_new`) |</span><br><span class="line">+----+---------------+</span><br><span class="line">| 1 | 1 |</span><br><span class="line">+----+---------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br></pre></td></tr></table></figure>
<p>结果都是一样的,但是这两个函数有什么区别呢?首先是 <code>BIN</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">BIN(N)</span><br><span class="line">返回N的二进制值的字符串表示,其中N是一个长(BIGINT)数字。这等同于CONV(N,10,2)。返回NULL,如果N为NULL。</span><br></pre></td></tr></table></figure>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql> select bin(2);</span><br><span class="line">+--------+</span><br><span class="line">| bin(2) |</span><br><span class="line">+--------+</span><br><span class="line">| 10 |</span><br><span class="line">+--------+</span><br></pre></td></tr></table></figure>
<p>2 显示成了二进制形式 10。</p>
<p><code>ORD()</code> 有点复杂:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ORD(str)</span><br><span class="line">如果字符串str的最左边的字符是一个多字节字符返回该字符,用这个公式其组成字节的数值计算的代码:</span><br><span class="line"> (1st byte code)</span><br><span class="line">+ (2nd byte code . 256)</span><br><span class="line">+ (3rd byte code . 2562) ...</span><br><span class="line">如果最左边的字符不是一个多字节字符,ORD()返回相同的值如ASCII()函数。</span><br></pre></td></tr></table></figure>
<p>**<em>这个函数接受的是字符串</em>,我们就认为它的作用是返回参数的第一个字符的 ASCII,</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">mysql> select ord(1);</span><br><span class="line">+--------+</span><br><span class="line">| ord(1) |</span><br><span class="line">+--------+</span><br><span class="line">| 49 |</span><br><span class="line">+--------+</span><br><span class="line">1 row <span class="keyword">in</span> <span class="built_in">set</span> (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql> select ord(2);</span><br><span class="line">+--------+</span><br><span class="line">| ord(2) |</span><br><span class="line">+--------+</span><br><span class="line">| 50 |</span><br><span class="line">+--------+</span><br><span class="line">1 row <span class="keyword">in</span> <span class="built_in">set</span> (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql> select ord(<span class="string">'abc'</span>);</span><br><span class="line">+------------+</span><br><span class="line">| ord(<span class="string">'abc'</span>) |</span><br><span class="line">+------------+</span><br><span class="line">| 97 |</span><br><span class="line">+------------+</span><br><span class="line">1 row <span class="keyword">in</span> <span class="built_in">set</span> (0.00 sec)</span><br></pre></td></tr></table></figure>
<p>那么这个函数为什么能正常显示 <code>is_new</code> 呢,因为 <code>is_new</code> 是 BIT 类型。</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql> select ord(b<span class="string">'1'</span>);</span><br><span class="line">+-----------+</span><br><span class="line">| ord(b<span class="string">'1'</span>) |</span><br><span class="line">+-----------+</span><br><span class="line">| 1 |</span><br><span class="line">+-----------+</span><br><span class="line">1 row <span class="keyword">in</span> <span class="built_in">set</span> (0.01 sec)</span><br></pre></td></tr></table></figure>
<p>就是说,<code>BIN</code> 是把 <code>is_new</code> 按二进制形式显示,<code>ORD</code> 是显示的 <code>is_new</code> 的 ASCII,或者转成了字符串?</p>
<p><code>BIT</code> 对应 Java 的布尔类型,<code>BIT</code> 默认只有一个比特位,那么 0 就是 false, 其他是 true,下面的设置方式在 mysql 中都是允许的</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `test_table`</span><br><span class="line"><span class="keyword">SET</span> `is_new`<span class="operator">=</span><span class="number">1</span>;</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `test_table`</span><br><span class="line"><span class="keyword">SET</span> `is_new`<span class="operator">=</span>b<span class="string">'1'</span>;</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `test_table`</span><br><span class="line"><span class="keyword">SET</span> `is_new`<span class="operator">=</span> <span class="literal">FALSE</span>;</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `test_table`</span><br><span class="line"><span class="keyword">SET</span> `is_new`<span class="operator">=</span> <span class="literal">TRUE</span>;</span><br></pre></td></tr></table></figure>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2019/05/15/Tips-Mysql-%E6%98%BE%E7%A4%BA-BIT/" data-id="cleghn5zl004mbbs6bsa4e8f7" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2019/05/15/Tips-Mysql-%E6%98%BE%E7%A4%BA-BIT/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/MySql/" rel="tag">MySql</a></li></ul>
</footer>
</div>
</article>
<article id="post-MySql错误排除" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/04/08/MySql%E9%94%99%E8%AF%AF%E6%8E%92%E9%99%A4/" class="article-date">
<time datetime="2019-04-08T06:09:01.000Z" itemprop="datePublished">2019-04-08</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Other/">Other</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/04/08/MySql%E9%94%99%E8%AF%AF%E6%8E%92%E9%99%A4/">MySql错误排除</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="最大文件打开数量的问题"><a href="#最大文件打开数量的问题" class="headerlink" title="最大文件打开数量的问题"></a>最大文件打开数量的问题</h2><p>使用 <code>ulimit -a</code> 可以查看系统对单个进程的限制</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">➜ ~ <span class="built_in">ulimit</span> -a</span><br><span class="line">-t: cpu time (seconds) unlimited</span><br><span class="line">-f: file size (blocks) unlimited</span><br><span class="line">-d: data seg size (kbytes) unlimited</span><br><span class="line">-s: stack size (kbytes) 8192</span><br><span class="line">-c: core file size (blocks) 0</span><br><span class="line">-v: address space (kbytes) unlimited</span><br><span class="line">-l: locked-in-memory size (kbytes) unlimited</span><br><span class="line">-u: processes 1418</span><br><span class="line">-n: file descriptors 7168</span><br></pre></td></tr></table></figure>
<p><code>ulimit -n</code> 是打开的最大文件数量限制,在 Mac 上可能是 256,如果是用了分表,默认情况下一个表对应一个文件,如果表的数量超过 256,打开超过256个文件的时候会报错。</p>
<p>解决方法:</p>
<p>1)<br>mysql 的 <code>my.cnf</code> 文件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">innodb_file_per_table = OFF </span><br></pre></td></tr></table></figure>
<p>关闭每个 table 建立一个文件,如果还是不行</p>
<p>2)<br>修改最大文件打开数</p>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2019/04/08/MySql%E9%94%99%E8%AF%AF%E6%8E%92%E9%99%A4/" data-id="cleghn5zk004ibbs60r0pcy5k" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2019/04/08/MySql%E9%94%99%E8%AF%AF%E6%8E%92%E9%99%A4/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/MySql/" rel="tag">MySql</a></li></ul>
</footer>
</div>
</article>
<article id="post-Redis命令" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/03/20/Redis%E5%91%BD%E4%BB%A4/" class="article-date">
<time datetime="2019-03-20T07:36:57.000Z" itemprop="datePublished">2019-03-20</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Other/">Other</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/03/20/Redis%E5%91%BD%E4%BB%A4/">Redis命令</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>连接:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -h {host} -p {port}</span><br></pre></td></tr></table></figure>
<p>设置一个:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379> <span class="built_in">set</span> aaa bbb</span><br><span class="line">OK</span><br></pre></td></tr></table></figure>
<p>获取值,成功的话返回值,失败时 nil</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379> get aaa</span><br><span class="line"><span class="string">"bbb"</span></span><br><span class="line">127.0.0.1:6379> get ddd</span><br><span class="line">(nil)</span><br></pre></td></tr></table></figure>
<p>值是否存在,若 key 存在,返回 1 ,否则返回 0:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379> exists aaa</span><br><span class="line">(<span class="built_in">integer</span>) 1</span><br></pre></td></tr></table></figure>
<p>获取keys:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379> keys aaa</span><br><span class="line">1) <span class="string">"aaa"</span></span><br><span class="line">127.0.0.1:6379> keys ddd</span><br><span class="line">(empty list or <span class="built_in">set</span>)</span><br><span class="line">127.0.0.1:6379></span><br></pre></td></tr></table></figure>
<p>获取过期时间,当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379> ttl aaa</span><br><span class="line">(<span class="built_in">integer</span>) -1</span><br><span class="line">127.0.0.1:6379> ttl ddd</span><br><span class="line">(<span class="built_in">integer</span>) -2</span><br></pre></td></tr></table></figure>
<p>设置过期时间:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">redis> EXPIRE cache_page 30 <span class="comment"># 设置过期时间为 30 秒</span></span><br><span class="line">(<span class="built_in">integer</span>) 1</span><br></pre></td></tr></table></figure>
<p>列出所有数据库:</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">CONFIG GET databases</span><br><span class="line">1) <span class="string">"databases"</span></span><br><span class="line">2) <span class="string">"16"</span></span><br></pre></td></tr></table></figure>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379[1]> INFO keyspace</span><br><span class="line"><span class="comment"># Keyspace</span></span><br><span class="line">db0:keys=10,expires=10,avg_ttl=140298</span><br><span class="line">db1:keys=3774,expires=3770,avg_ttl=73246701</span><br></pre></td></tr></table></figure>
<p>选择数据库</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select 1</span><br></pre></td></tr></table></figure>
</div>
<footer class="article-footer">
<a data-url="http://sw926.github.io/2019/03/20/Redis%E5%91%BD%E4%BB%A4/" data-id="cleghn5zj004fbbs6bg7z899t" class="article-share-link">Share</a>
<a href="http://sw926.github.io/2019/03/20/Redis%E5%91%BD%E4%BB%A4/#disqus_thread" class="article-comment-link">Comments</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Redis/" rel="tag">Redis</a></li></ul>
</footer>
</div>
</article>
<nav id="page-nav">
<span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><span class="space">…</span><a class="page-number" href="/page/6/">6</a><a class="extend next" rel="next" href="/page/2/">Next &raquo;</a>
</nav>
</section>
<aside id="sidebar">
<div class="widget-wrap">
<h3 class="widget-title">Categories</h3>
<div class="widget">
<ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Android/">Android</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Git/">Git</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Java/">Java</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Kotlin/">Kotlin</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Node-js/">Node.js</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Other/">Other</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Python/">Python</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Ruby/">Ruby</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Tags</h3>
<div class="widget">
<ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Android/" rel="tag">Android</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Android-Studio/" rel="tag">Android Studio</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ConstraintLayout/" rel="tag">ConstraintLayout</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Dagger2/" rel="tag">Dagger2</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Databinding/" rel="tag">Databinding</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Flutter/" rel="tag">Flutter</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Git/" rel="tag">Git</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Gradle/" rel="tag">Gradle</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Gson/" rel="tag">Gson</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Java/" rel="tag">Java</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Java-Thread/" rel="tag">Java Thread</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Java-Time/" rel="tag">Java Time</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Jenkins/" rel="tag">Jenkins</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Karabiner-Elements/" rel="tag">Karabiner Elements</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Kotlin/" rel="tag">Kotlin</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/MySql/" rel="tag">MySql</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Nginx/" rel="tag">Nginx</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Ngrok/" rel="tag">Ngrok</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Other/" rel="tag">Other</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Python/" rel="tag">Python</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/React/" rel="tag">React</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Redis/" rel="tag">Redis</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Room/" rel="tag">Room</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Ruby/" rel="tag">Ruby</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring-Boot/" rel="tag">Spring Boot</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/bash/" rel="tag">bash</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/" rel="tag">git</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/jvm/" rel="tag">jvm</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/sdkman/" rel="tag">sdkman</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/sh/" rel="tag">sh</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ss/" rel="tag">ss</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/webpack/" rel="tag">webpack</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Tag Cloud</h3>
<div class="widget tagcloud">
<a href="/tags/Android/" style="font-size: 20px;">Android</a> <a href="/tags/Android-Studio/" style="font-size: 18px;">Android Studio</a> <a href="/tags/ConstraintLayout/" style="font-size: 10px;">ConstraintLayout</a> <a href="/tags/Dagger2/" style="font-size: 14px;">Dagger2</a> <a href="/tags/Databinding/" style="font-size: 10px;">Databinding</a> <a href="/tags/Flutter/" style="font-size: 10px;">Flutter</a> <a href="/tags/Git/" style="font-size: 12px;">Git</a> <a href="/tags/Gradle/" style="font-size: 16px;">Gradle</a> <a href="/tags/Gson/" style="font-size: 10px;">Gson</a> <a href="/tags/Java/" style="font-size: 12px;">Java</a> <a href="/tags/Java-Thread/" style="font-size: 10px;">Java Thread</a> <a href="/tags/Java-Time/" style="font-size: 10px;">Java Time</a> <a href="/tags/Jenkins/" style="font-size: 10px;">Jenkins</a> <a href="/tags/Karabiner-Elements/" style="font-size: 10px;">Karabiner Elements</a> <a href="/tags/Kotlin/" style="font-size: 12px;">Kotlin</a> <a href="/tags/MySql/" style="font-size: 12px;">MySql</a> <a href="/tags/Nginx/" style="font-size: 12px;">Nginx</a> <a href="/tags/Ngrok/" style="font-size: 10px;">Ngrok</a> <a href="/tags/Other/" style="font-size: 10px;">Other</a> <a href="/tags/Python/" style="font-size: 12px;">Python</a> <a href="/tags/React/" style="font-size: 10px;">React</a> <a href="/tags/Redis/" style="font-size: 10px;">Redis</a> <a href="/tags/Room/" style="font-size: 10px;">Room</a> <a href="/tags/Ruby/" style="font-size: 10px;">Ruby</a> <a href="/tags/Spring-Boot/" style="font-size: 16px;">Spring Boot</a> <a href="/tags/bash/" style="font-size: 10px;">bash</a> <a href="/tags/git/" style="font-size: 10px;">git</a> <a href="/tags/jvm/" style="font-size: 10px;">jvm</a> <a href="/tags/sdkman/" style="font-size: 10px;">sdkman</a> <a href="/tags/sh/" style="font-size: 10px;">sh</a> <a href="/tags/ss/" style="font-size: 10px;">ss</a> <a href="/tags/webpack/" style="font-size: 10px;">webpack</a>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Archives</h3>
<div class="widget">
<ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/05/">May 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/04/">April 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/11/">November 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/07/">July 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/06/">June 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/05/">May 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/04/">April 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/03/">March 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/02/">February 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/01/">January 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/12/">December 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/06/">June 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/05/">May 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/02/">February 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/11/">November 2016</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/09/">September 2016</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/06/">June 2016</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/05/">May 2016</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/04/">April 2016</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/01/">January 2016</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/11/">November 2015</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/09/">September 2015</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/08/">August 2015</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/07/">July 2015</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/05/">May 2015</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/04/">April 2015</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Recent Posts</h3>
<div class="widget">
<ul>
<li>
<a href="/2020/05/14/ADB-%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/">ADB 命令整理</a>
</li>
<li>
<a href="/2020/04/27/Kotlin-%E8%A1%A5%E5%9D%91/">Kotlin 补坑</a>
</li>
<li>
<a href="/2020/04/22/Kotlin%E7%9A%84%E9%9D%9E%E7%A9%BA%E6%96%AD%E8%A8%80%E8%B0%83%E7%94%A8/">Kotlin的非空断言调用</a>
</li>
<li>
<a href="/2019/11/02/Java-Time/">Java Time</a>
</li>
<li>
<a href="/2019/07/03/Tips-Java-Thread/">Tips:Java Thread</a>
</li>
</ul>
</div>
</div>
</aside>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info" class="inner">
© 2023 sunwei<br>
Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
</div>
</div>
</footer>
</div>
<nav id="mobile-nav">
<a href="/" class="mobile-nav-link">Home</a>
<a href="/archives" class="mobile-nav-link">Archives</a>
</nav>
<script>
var disqus_shortname = 'sw926';
(function(){
var dsq = document.createElement('script');
dsq.type = 'text/javascript';
dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script src="/js/script.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-62569931-6"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-62569931-6');
</script>
</div>
</body>
</html>