-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrss.xml
More file actions
826 lines (826 loc) · 126 KB
/
Copy pathrss.xml
File metadata and controls
826 lines (826 loc) · 126 KB
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
<?xml version="1.0" encoding="utf-8"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>袁式无语</title><link>https://umaYnit.github.io/</link><description>嗯,大概就这样吧</description><generator>Hugo 0.102.3 https://gohugo.io/</generator><language>zh-CN</language><managingEditor>umasensei@gmail.com (uma)</managingEditor><webMaster>umasensei@gmail.com (uma)</webMaster><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><lastBuildDate>Thu, 08 Sep 2022 15:24:52 +0800</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://umaYnit.github.io/rss.xml"/><item><title>从百度云盘玩一玩前端操作</title><link>https://umaYnit.github.io/posts/%E4%BB%8E%E7%99%BE%E5%BA%A6%E4%BA%91%E7%9B%98%E7%8E%A9%E4%B8%80%E7%8E%A9%E5%89%8D%E7%AB%AF%E6%93%8D%E4%BD%9C/</link><guid isPermaLink="true">https://umaYnit.github.io/posts/%E4%BB%8E%E7%99%BE%E5%BA%A6%E4%BA%91%E7%9B%98%E7%8E%A9%E4%B8%80%E7%8E%A9%E5%89%8D%E7%AB%AF%E6%93%8D%E4%BD%9C/</guid><pubDate>Thu, 08 Sep 2022 00:20:49 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><p>起因是这样的,好早之前下载了一个学习视频,最近突然心血来潮想学习一下,等学到了第36个视频的时候,才发现视频没全部下载下来,本地只有49个。</p>
<p>于是去百度网盘上溜了一圈,找到了原资源,总共有116个视频。原本只需要简单的全选后下载即可,但是恰好b站最近又给我推了一抹多的什么硬盘损坏的视频,搞得我很紧张,想只下载缺失的部分。</p>
<p>然而事情可不会这么顺利,百度网盘的网页页面是真的难用,它在我点了十几个选择勾勾之后,突然一下子全清掉了,人都麻了。</p>
<p><img src="https://umaYnit.github.io/img/baidu_01.gif" alt="成年人的崩溃就在一瞬间"></p>
<p>成年人的崩溃就在一瞬间。</p>
<p>于是我就上头了,想要直接在这个页面,用代码自己去帮我点击选择要下载的视频。虽然我不会前端,但是说干就干。</p>
<p>首先查看这个框到底是个啥。本想着是个checkbox啥的,那就简单了。没想打开F12调试工具一看,居然是个span,而且选中和不选中,居然没有变化,怪了。</p>
<p><img src="https://umaYnit.github.io/img/baidu_02.png" alt="百度网盘的选中框居然是span"></p>
<p>终于,在试了好几次之后,才看到,变化的居然是更上级的dd,这个dd又是什么鬼东西。麻了,要不算了吧。但是一想到在朋友面前刚装的b,不能不做呀,但是又毫无头绪。</p>
<p><img src="https://umaYnit.github.io/img/baidu_03.png" alt="百度网盘选中框居然是dd"></p>
<p>只好再在F12里找找东西了。随便翻翻,发现在span上有好几个点击事件,右边还有一个Remove按钮,于是我就全都点了一下Remove。欸,页面上的选中框,点不动了,我好像又行了。但是为啥下面的点击事件都是一行,重复绑定了么?</p>
<p><img src="https://umaYnit.github.io/img/baidu_04.png" alt="无意间找到了选中框的点击事件"></p>
<p>点进js source,点击的格式化,哦,来了来了,是源代码,打个断点试试。断点后,点击选中框,还是没有变化....破东西,不玩了。算了算了,,都到这步了(都浪费这么多时间了),再看看吧。</p>
<p>回到Elements的点击事件标签看,哦,哪路或多。原来不是重复绑定,不是同一个点击事件呀,是js压缩到一行了,好吧,那就每个都下个断点。</p>
<p><img src="https://umaYnit.github.io/img/baidu_05.png" alt="原来不是重复绑定的点击事件呀"></p>
<p>终于,在一番操作后,点击span,进入到断点了,我彷佛看到了胜利的曙光,有个可爱的天使在向我招手(来自半夜1点的发言)。</p>
<p><img src="https://umaYnit.github.io/img/baidu_06.png" alt="终于找到了选中框的点击事件"></p>
<p>找到了点击后调用的js了,然而我又陷入了迷茫,接下来该怎么办。突然又失去了头绪。</p>
<p>然后突然想起来,好像,可以直接触发元素的点击事件?赶紧试试。</p>
<p>给回到Elements页面,右键span,选择<code>add attribute</code>,然后输入<code>id=&quot;aaaa&quot;</code>,给span加上id。接下来切换到Console页面,熟练的在console里写上,<code>document.getElementById(&quot;aaaa&quot;)</code>,回车,哦,有了。</p>
<p><img src="https://umaYnit.github.io/img/baidu_07.png" alt="在js里选中了span"></p>
<p>接下来就是赶紧查一查,怎么触发点击。直接打开搜索,输入“js 触发click”,进入第一个页面。有了,而且好像很简单的样子,赶紧复制下来试试。</p>
<p><img src="https://umaYnit.github.io/img/baidu_08.png" alt="搜索出来的js触发click方法"></p>
<p>回到Console页面,输入<code>document.getElementById(&quot;aaaa&quot;).click()</code>,回车确认,触发了断点,看来成功了,那么剩下的就都好说了。接下来,只需要选中所有的span,然后过滤出自己需要的,最后,触发他们的click事件就行了。</p>
<p>接下来的选中元素呀,啥的,过程就省略了,直接贴上代码。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="c1">// 查看过滤的情况
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">let</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl"><span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="s2">&#34;dd.g-clearfix&#34;</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">item</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">&#34;a&#34;</span><span class="p">).</span><span class="nx">innerHTML</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="o">&gt;</span> <span class="mi">49</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">arr</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">&#34;a&#34;</span><span class="p">).</span><span class="nx">innerHTML</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 选中过滤后的文件
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="s2">&#34;dd.g-clearfix&#34;</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">item</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">&#34;a&#34;</span><span class="p">).</span><span class="nx">innerHTML</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="o">&gt;</span> <span class="mi">49</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">item</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">&#34;span&#34;</span><span class="p">).</span><span class="nx">click</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><img src="https://umaYnit.github.io/img/baidu_09.png" alt="终于完成了目标,用js选中了想要的文件"></p>
<p>到这里,这个突发奇想的目标,就算达成了。虽然总共花了半个多小时,手动选可能最多就1,2分钟的时间,但是,我得到了快乐哈哈哈。</p></description><category domain="https://umaYnit.github.io/posts/">posts</category><category domain="https://umaYnit.github.io/tags/js/">Js</category><category domain="https://umaYnit.github.io/tags/web/">Web</category></item><item><title>随想03</title><link>https://umaYnit.github.io/slice/%E9%9A%8F%E6%83%B303/</link><guid isPermaLink="true">https://umaYnit.github.io/slice/%E9%9A%8F%E6%83%B303/</guid><pubDate>Sun, 10 Jan 2021 18:21:19 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><blockquote>
<p>语言这个东西,在翻译机器日渐进步的今天,感觉好像不用自己去掌握也没什么太大的问题,但实际上还有很太多因为语言而割裂开的事物。</p>
</blockquote>
<p>昨天我给朋友讲,我感觉我比起身边的人,总能搜到他们搜不到的问题的答案,或者能够很快找到问题相关的资料。我仔细想了一下,大概有如下这些信息:</p>
<ul>
<li>
<p>1、简单的,常见的问题,无论是生活中的,还是技能向初级阶段的,总结来说,就是专业性不是那么强的,比较大众化的,能够直接在百度搜索,并且要带入自己是小白的视角,用相关的语气去搜,即尽量白话的形式,注意描述的要贴切。或者只输入出现的关键词,注意用空格隔开。</p>
<p>比如XXX入门,比如电脑出现了一些能够描述出现象的问题(出现莫名其妙的文件夹呀),再比如生活中的一些自己不太知道的方面突然想到的一些问题。</p>
<p>总的来说,可能需要一些练习(比如关键字的寻找,现象的描述,和该问题是否大众化的判断),然后就能很轻易的知道,怎么去查找。</p>
</li>
<li>
<p>2、有语言及相关语言使用者偏向的,最好使用该语种去搜索,这时百度是多半不行的,要用谷歌。</p>
<p>这一个点,就是我这两天体会特别深刻的。前段时间,从一些公众号看到了书的安利,《30天自制操作系统》,这本书很久远了,是日本人写的,我最近想用Rust尝试去做这个(原书是作者自制汇编+C)。还没动手的时候,觉得好像还挺简单的,因为还知道一些<a href="https://os.phil-opp.com/">Rust写操作系统的资料</a>,结果一开始就遇到了问题了:大部分的OS教程都跳过了引导程序的部分,直接使用了现有的完善的东西,而这样就和“30天”那个匹配不上。于是就尝试着从完整的那个部分,删除所有的东西,然后将“30天”的代码放进去,然后编译不过,提示 <code>invalid instruction mnemonic 'xxx'</code>(无效的指令助记符,即汇编)。直接先是一波谷歌,明白了,有很多种不同类型的汇编,而这里使用从原本完整部分的代码里,得到了关键信息<code>.intel_syntax noprefix</code>。我这里就凭借着自己的经验,直接拿该信息凭借空格再加上无效的指令后,去谷歌搜索(例如<code>.intel_syntax noprefix db</code>)。经过一番努力后,终于把所有的错误都改正过来后,结果还是不行。这时我陷入了盲目的查找中(因为自己没有学过任何相关的东西),说来也是运气好,在翻了很多页之后,看到了一个有点特别的记录(有我要找的信息的对照),点进去一看,好家伙,是一个人尝试在Linux上玩“30天”(原书只提供了win的环境)。直接复制他的第一天的代码,终于成功了,很是激动。然而,到第二天的代码的时候,又出现问题了,他编写了ld脚本,并使用了额外的工具,但是一方面我是win环境,另一方面不太想用额外的工具。于是又开始盲目的搜索,这次就不行了,一方面,这个问题不能很简单的描述,另一方面比较小众。在我尝试了很多关键词都不行之后,在想求助老师的帮助的时候,突然间一个激灵,我切换到日语输入法使用了日语去搜索,关键词为 “30天自制操作系统 Rust”,一下子就出现了很多想要的信息。这个就是我题记里的感想,一是现代浏览器能自动的翻译到你能看得懂的语言,但目前搜索引擎没办法做这件事。二是我发现日文这边也有很多庞大的社区,在其中看到了很多特别有意思的东西,但是语言上的隔阂,让本来的&quot;互联&quot;的互联网变得像似一个一个孤岛一样。</p>
</li>
</ul></description><category domain="https://umaYnit.github.io/slice/">slice</category><category domain="https://umaYnit.github.io/tags/%E6%90%9C%E7%B4%A2/">搜索</category><category domain="https://umaYnit.github.io/tags/%E9%9A%8F%E6%83%B3/">随想</category></item><item><title>随想02</title><link>https://umaYnit.github.io/slice/%E9%9A%8F%E6%83%B302/</link><guid isPermaLink="true">https://umaYnit.github.io/slice/%E9%9A%8F%E6%83%B302/</guid><pubDate>Wed, 06 Jan 2021 17:52:16 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><blockquote>
<p>知识的诅咒(The Curse of Knowledge),即:我们一旦知道了某事,就无法想象这件事在未知者眼中的样子。当我们把自己知道的知识解释给别人的时候,因为信息的不对等,我们很难把自己知道的完完全全给对方解释清楚。总是,我们的知识“诅咒”了我们。</p>
</blockquote>
<p>以前学日语的时候,总觉得先生讲的太怪了,我以后要是有机会给别人讲,我肯定要XXX这样讲这样做。后来等到自己学的差不多了,有了能够以助教的身份给入门的人讲内容的机会的时候,突然之间发现,自己忘记了以前到底想要怎么做,即上面的XXX现在在我的脑海里真的就是XXX。</p></description><category domain="https://umaYnit.github.io/slice/">slice</category><category domain="https://umaYnit.github.io/tags/%E7%9F%A5%E8%AF%86%E8%AF%85%E5%92%92/">知识诅咒</category><category domain="https://umaYnit.github.io/tags/%E9%9A%8F%E6%83%B3/">随想</category></item><item><title>随想01</title><link>https://umaYnit.github.io/slice/%E9%9A%8F%E6%83%B3/</link><guid isPermaLink="true">https://umaYnit.github.io/slice/%E9%9A%8F%E6%83%B3/</guid><pubDate>Mon, 04 Jan 2021 13:37:07 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><p>如何注意到那些特别细小的性能问题呢?这里的细小可能是对于我这种不懂的人来说的。印象最深的例子是很早之前看到(可能是这篇)的一个讲关于Disruptor里,有一个class里,在声明变量的时候,写了几个无用的变量(jdk8之后有新的注解<code>@Contended</code>),而这几个变量对性能影响非常大(实际上就是cpu缓存的问题(缓存行对齐))。</p>
<p>黑盒、封装、缓存,这些技术将底层的事物抽象起来,让底层离我们非常远,可以非常简单的,从高层次入手,但是总会有一个阶段,你发现遇到瓶颈了,而这个瓶颈,不是自己这个层面的,是需要更往下走,去了解底下的事物,即<strong>抽象泄露</strong>。</p>
<p>为什么会有这样的现象呢,是因为抽象并不能囊括所有的情况,所以那些偏向底层的人,非常不信任高层级的抽象。比如Rust的那些高级表达,真的没有开销吗?又比如关于缓存,一般情况下,是希望缓存对于外部来说是透明的,即不需要知道缓存的存在,但是类似上面的情况,在复杂的,性能敏感的时候,是不是又非得去关注这个点呢。</p>
<p>附一些相关文章:</p>
<ul>
<li><a href="https://www.cnblogs.com/cyfonly/p/5800758.html">伪共享(false sharing),并发编程无声的性能杀手</a></li>
<li><a href="https://www.jianshu.com/p/648e9565969e?utm_campaign=hugo">聊聊CPU缓存、伪共享与缓存行填充</a></li>
</ul></description><category domain="https://umaYnit.github.io/slice/">slice</category><category domain="https://umaYnit.github.io/tags/%E6%80%A7%E8%83%BD/">性能</category><category domain="https://umaYnit.github.io/tags/%E9%9A%8F%E6%83%B3/">随想</category></item><item><title>Rust中Vec扩容时容量大小</title><link>https://umaYnit.github.io/posts/rust%E4%B8%ADvec%E6%89%A9%E5%AE%B9%E6%97%B6%E5%AE%B9%E9%87%8F%E5%A4%A7%E5%B0%8F/</link><guid isPermaLink="true">https://umaYnit.github.io/posts/rust%E4%B8%ADvec%E6%89%A9%E5%AE%B9%E6%97%B6%E5%AE%B9%E9%87%8F%E5%A4%A7%E5%B0%8F/</guid><pubDate>Sun, 20 Dec 2020 20:52:01 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><blockquote>
<p>有没有小伙伴拯救我,带我一起学习呀。</p>
</blockquote>
<p>又是一个人的无聊的周末,打开极客时间,于是开始刷,养了很久的Rust视频课,第19节讲集合,在阅读doc文档时,有一部分提到了<a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#capacity-and-reallocation">Vec扩容的问题</a>。如下所示:</p>
<p><img src="https://umaYnit.github.io/img/vec_cap.png" alt="https://doc.rust-lang.org/std/vec/struct.Vec.html#capacity-and-reallocation"></p>
<p>视频中讲的是:</p>
<blockquote>
<p>容量是成倍增加,比如指定了一个容量为10的vec,那么扩容时会以10的倍数来自动增长,第一次扩容时就变成了20。</p>
</blockquote>
<p>初一听好像确实没什么问题,和文档中说的一样。但是突然想到了,声明时指定容量的是方法<code>with_capacity(usize)</code>,这时就是上面说的情况,但是使用<code>new()</code>方法声明时并没有指定容量,那容量应该是多少呢?说到就打开ide,写出如下代码开始测试:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">vec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="mi">20</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">vec</span><span class="p">.</span><span class="n">capacity</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>截取部分打印结果,如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:5<span class="o">]</span> vec.capacity<span class="o">()</span> <span class="o">=</span> <span class="m">4</span>
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:5<span class="o">]</span> vec.capacity<span class="o">()</span> <span class="o">=</span> <span class="m">8</span>
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:5<span class="o">]</span> vec.capacity<span class="o">()</span> <span class="o">=</span> <span class="m">16</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:5<span class="o">]</span> vec.capacity<span class="o">()</span> <span class="o">=</span> <span class="m">32</span>
</span></span><span class="line"><span class="cl">...
</span></span></code></pre></td></tr></table>
</div>
</div><p>可以看到,初始是4,后面以4为倍数开始增长。就很疑惑,这个4是哪里来的呢,emmm,去看看源码吧(大家一般可以先看源码,我比较菜,就忘记了)。</p>
<p>首先查看<code>vec.capacity()</code>这个方法到底是在干什么。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">//==========vec.rs
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">capacity</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">usize</span> <span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">.</span><span class="n">capacity</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">//==========raw_vec.rs
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">capacity</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">usize</span> <span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">usize</span>::<span class="n">MAX</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">cap</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>可以看到,其实就是返回了结构体里的<code>cap</code>字段,并没有更多的操作。然后查看<code>new()</code>方法,看看有啥操作没:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">//==========vec.rs
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">new</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nb">Vec</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">buf</span>: <span class="nc">RawVec</span>::<span class="n">NEW</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="mi">0</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">//==========raw_vec.rs
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">NEW</span>: <span class="nc">Self</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">Self</span>::<span class="n">new</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">new</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="bp">Self</span>::<span class="n">new_in</span><span class="p">(</span><span class="n">Global</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">new_in</span><span class="p">(</span><span class="n">alloc</span>: <span class="nc">A</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// `cap: 0` means &#34;unallocated&#34;. zero-sized types are ignored.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">ptr</span>: <span class="nc">Unique</span>::<span class="n">dangling</span><span class="p">(),</span><span class="w"> </span><span class="n">cap</span>: <span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">alloc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>发现还是没有任何操作,就是简单的设置了一下,在<code>new()</code>方法里,<code>cap</code>初始化就是0,没有出现任何和4这个数字有关系的代码。那相关代码只能在是<code>push()</code>里了:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">//==========vec.rs
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">push</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">value</span>: <span class="nc">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">len</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">.</span><span class="n">capacity</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="c1">//省略下面的操作代码
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>这里的<code>reserve()</code>方法好像就是在做扩容,继续点进去查看,一路关键点下去:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">//==========vec.rs
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">reserve</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">buf</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">len</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="c1">//==========raw_vec.rs
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">reserve</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">handle_reserve</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">try_reserve</span><span class="p">(</span><span class="n">len</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">try_reserve</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span><span class="w"> </span><span class="n">TryReserveError</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">needs_to_grow</span><span class="p">(</span><span class="n">len</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">grow_amortized</span><span class="p">(</span><span class="n">len</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nb">Ok</span><span class="p">(())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>最终,目光停留在了<code>self.grow_amortized(len, additional)</code>这句代码上,内心感觉这里应该就是关键了:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">grow_amortized</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">additional</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span><span class="w"> </span><span class="n">TryReserveError</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="c1">//省略部分无关代码
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">required_cap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">len</span><span class="p">.</span><span class="n">checked_add</span><span class="p">(</span><span class="n">additional</span><span class="p">).</span><span class="n">ok_or</span><span class="p">(</span><span class="n">CapacityOverflow</span><span class="p">)</span><span class="o">?</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">cap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">cap</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="n">required_cap</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// Tiny Vecs are dumb. Skip to:
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="c1">// - 8 if the element size is 1, because any heap allocators is likely
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="c1">// to round up a request of less than 8 bytes to at least 8 bytes.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="c1">// - 4 if elements are moderate-sized (&lt;= 1 KiB).
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="c1">// - 1 otherwise, to avoid wasting too much space for very short Vecs.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="c1">// Note that `min_non_zero_cap` is computed statically.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">elem_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">min_non_zero_cap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">elem_size</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="mi">8</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">elem_size</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="mi">1024</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="mi">4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="mi">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">cap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmp</span>::<span class="n">max</span><span class="p">(</span><span class="n">min_non_zero_cap</span><span class="p">,</span><span class="w"> </span><span class="n">cap</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="c1">//省略部分无关代码
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>可以看到,这里有这么大一段判断的代码,成倍增长是来自于<code>cmp::max(self.cap * 2, required_cap)</code>,而初始大小则是下面那段<code>if else</code>,这个总共分了三种情况:</p>
<ul>
<li>首先如果元素的大小是<strong>1</strong>,则初始<code>cap</code>给了<strong>8</strong>,</li>
<li>否则如果元素的大小 小于等于<strong>1024</strong>(即1Kb),则初始cap是<strong>4</strong>,</li>
<li>最后,即元素大小大于<strong>1024</strong>的情况,初始cap给了<strong>1</strong></li>
</ul>
<p>所以上面最初的测试代码,因为数字42的默认类型是<code>i32</code>,而<code>i32</code>类型的大小是4,满足第二种情况,所以打印的初始值是4。</p>
<p>最后,测试一下第1,3种情况:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">mem</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">elem_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">elem_size</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">vec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">vec</span><span class="p">.</span><span class="n">capacity</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">elem_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="p">[</span><span class="kt">bool</span><span class="p">;</span><span class="w"> </span><span class="mi">1025</span><span class="p">]</span><span class="o">&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">elem_size</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">vec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">push</span><span class="p">([</span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="mi">1025</span><span class="p">]);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">vec</span><span class="p">.</span><span class="n">capacity</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>运行结果如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:5<span class="o">]</span> <span class="nv">elem_size</span> <span class="o">=</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:8<span class="o">]</span> vec.capacity<span class="o">()</span> <span class="o">=</span> <span class="m">8</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:11<span class="o">]</span> <span class="nv">elem_size</span> <span class="o">=</span> <span class="m">1025</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>src<span class="se">\m</span>ain.rs:14<span class="o">]</span> vec.capacity<span class="o">()</span> <span class="o">=</span> <span class="m">4</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>完美契合。</p>
<blockquote>
<p>嗯,这就样水了一篇博客,主要还是害怕自己如果不写下这些简单的,就难以去写那些复杂的,有意义的文章,终归还是要偿还上学时不写作文的债呀。</p>
</blockquote></description><category domain="https://umaYnit.github.io/posts/">posts</category><category domain="https://umaYnit.github.io/tags/rust/">Rust</category><category domain="https://umaYnit.github.io/tags/vec/">Vec</category></item><item><title>RPG游戏相关突发感想</title><link>https://umaYnit.github.io/life/rpg%E6%B8%B8%E6%88%8F%E7%9B%B8%E5%85%B3%E7%AA%81%E5%8F%91%E6%84%9F%E6%83%B3/</link><guid isPermaLink="true">https://umaYnit.github.io/life/rpg%E6%B8%B8%E6%88%8F%E7%9B%B8%E5%85%B3%E7%AA%81%E5%8F%91%E6%84%9F%E6%83%B3/</guid><pubDate>Wed, 16 Dec 2020 12:02:49 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><p>今天在打车的路上的时候,突然有了一点关于RPG、GAL这样的剧情类的游戏的相关感想。</p>
<p>我没有玩过巫师3,但是昨天看了一个相关的视频,是主角在走到某个墙转角时,会有一个喜欢男主的女的突然出来壁咚他,然后视频的内容就是假如在触发剧情前,先用燃烧瓶丢墙壁会怎样。一般来说,这个取决于游戏是否有制作相关的判定,在这个游戏里,就出现了变化,行动变成了尾随,而判定条件是主角是否拿着武器,就是说其实和墙壁是否着火没有太大关系。</p>
<p>无论是最近非常火的2077,还是之前的巫师3,都有很多类似的会对剧情产生影响的选择,有些是显式的,比如对话时的选项,有些是隐式的,比如剧情触发前置条件。</p>
<p>早在高中时代,因为很喜欢key社的动漫,clannad、air、kanon,于是去收集相关信息,才知道这些动漫都是由游戏改编的,而这种类型的游戏,就叫galgame。当时记得花了好大的功夫才终于弄好了,可以在手机上游玩。</p>
<p>gal的中文好像是美少女游戏,游戏内容大概就是你作为其中的主角,然后有一个背景,和一些相关的角色,主体就是对话和选择。我还听过另一些称呼:视觉小说。(当然起初两者是不相同的,视觉小说更偏向于线性的没有选择的)。</p>
<p>我本身是一个“选择困难症”患者,在日常生活中经常难以做出选择,导致懒得做选择,上面花了好大劲弄的游戏,自然是没坚持过第五次出现的选项。然后我突然想到,现世人生其实不就是一个更复杂,或者说非常复杂的rpg游戏嘛,你做出的每一个动作都会对接下来的剧情(人生)产生影响。但是因为是一直持续着的,而且无法重复的。</p>
<p>然后还想到,现在的游戏虽然感觉挺多变的,不同的行为有不同的剧情不同的结局,但实际上这些都是提前设计好的,不同对话选项的不同反应,是固定好了的,不同数据值的不同影响,也是设计好了的,不同剧情的前置条件,就像是填表一样。即是能够在代码里看到,预测的,所以当前的开放世界游戏有时候玩起来无论如何都和现实有差距。那如果想做一个更接近的游戏,是不是应该重新去思考,怎么样才能更有现实感,譬如选项虽然是固定的,但是npc的反应是实时计算生成的(额,我写出来时才想到,既然相关联的事物是随机的,那选项肯定是设计不了的),这样,应该就和现实体验差不多吧,降低了选择的感觉。</p></description><category domain="https://umaYnit.github.io/life/">life</category><category domain="https://umaYnit.github.io/tags/whim/">Whim</category></item><item><title>吃药时的莫名想法</title><link>https://umaYnit.github.io/life/%E5%90%83%E8%8D%AF%E6%97%B6%E7%9A%84%E8%8E%AB%E5%90%8D%E6%83%B3%E6%B3%95/</link><guid isPermaLink="true">https://umaYnit.github.io/life/%E5%90%83%E8%8D%AF%E6%97%B6%E7%9A%84%E8%8E%AB%E5%90%8D%E6%83%B3%E6%B3%95/</guid><pubDate>Wed, 16 Dec 2020 12:02:49 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><p>天气太热起了疹子,去诊所开了药,红红绿绿的有一大把。</p>
<p>就着水,很 轻松的 一口就咽下去了,一点药的味道都没有留下。</p>
<p>回想起了小的时候,无论怎样尝试,都没办法“一口”。</p>
<p>最终褐色药片和糖衣化掉的白色药片的味道充斥着记忆。</p></description><category domain="https://umaYnit.github.io/life/">life</category><category domain="https://umaYnit.github.io/tags/whim/">Whim</category></item><item><title>Rust中panic的思考</title><link>https://umaYnit.github.io/posts/rust%E4%B8%ADpanic%E7%9A%84%E6%80%9D%E8%80%83/</link><guid isPermaLink="true">https://umaYnit.github.io/posts/rust%E4%B8%ADpanic%E7%9A%84%E6%80%9D%E8%80%83/</guid><pubDate>Tue, 15 Dec 2020 20:16:49 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><p>今天在Rust相关的群里看到一个问题</p>
<blockquote>
<p>A:怎么处理web服务中接口panic的?</p>
</blockquote>
<p>我心想,Rust的强制错误处理在对比其他常用编程语言来说非常完善了,为啥会有panic呢?刚好就有人问出了我心中的这个问题。有如下对话:</p>
<blockquote>
<p>B:你的接口还会 panic ?
A:一般来说不会panic ,以防万一。比如,你之前开发的时候有bug ,上线了没查到,结果你接口panic了。这是很有可能的。举个例子,例如这种代码,开发期间正常编译,上线了绝对panic。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">];</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">v</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">6</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>B:所有根据索引操作的代码 和写 .unwrap() 没有区别呀。你会写 unwrap() 吗?</p>
<p>A:假设你就写了unwrap,但是没发现,要预防线上panic呀。你可以保证你自己不写panic ,人多了的情况下,很难保证所有人绝对不写panic</p>
<p>B:这样说好像不对, 真的代码质量这么差的话, 从提交代码的流程上就一定得有代码审核的过程。那要不然你还得防止 代码是不是有木马, 代码里有死循环, 代码里有任何东西都有可能</p>
<p>A:这是从管理上解决,问题是我们怎么从代码层面预防panic ,例如用了actix web的情况下</p>
</blockquote>
<p>到这里我先去看了一下<code>Vec</code>的<code>remove</code>操作源码:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">remove</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">index</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">T</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="cp">#[cold]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="cp">#[inline(never)]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">assert_failed</span><span class="p">(</span><span class="n">index</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">panic!</span><span class="p">(</span><span class="s">&#34;removal index (is {}) should be &lt; len (is {})&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">index</span><span class="p">,</span><span class="w"> </span><span class="n">len</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">len</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">index</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">assert_failed</span><span class="p">(</span><span class="n">index</span><span class="p">,</span><span class="w"> </span><span class="n">len</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="c1">//后面操作部分省略
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>可以看到是因为一来就有一个<code>assert_failed</code>函数,对长度<code>len</code>进行了校验,如果失败,则直接<code>panic</code>。</p>
<p>这里我首先想到的是Rust提供了捕获<code>panic</code>的方法<code>catch_unwind</code>,打开doc文档查看,发现好像是及其不推荐使用该方法的,而且还有可能捕获不到。</p>
<p>因为讨论的是web接口,于是我先去<code>actix-web</code>的库查找相关的issue,还真有一个: <a href="https://github.com/actix/actix-web/issues/1501">Panic within a handler should return an HTTP 500</a>。该issue是在讨论发生<code>panic</code>时web框架应返回错误码500而不是直接就没有任何反应的断开连接。</p>
<p>在这个issue里,发起者提到了几种他认为的error级别的情况(例如数据库连接断开、数据库格式变化、上游服务器/API变化),他认为这些不应该一级一级向上传播,而是直接<code>panic</code>掉(比如调用<code>pool.get().await.unwrap()</code>从连接池获得连接时,如果得到了连接,那就ok,但是如果没有,这时无论如何做什么都会遭受灾难性的失败,因此需要<code>panic</code>,并且也提到了采用<code>catch_unwind</code>方法来捕获。</p>
<p>而库的现作者觉得,终止连接就是对<code>panic</code>最恰当的相应,用户在写编写业务代码的时候应该在所有情况下进行处理或冒泡(向上传递),并且<code>catch_unwind</code>也不等同于其他语言中的try-catch。</p>
<p>到这里,我其实是很认同库作者的发言的,我也觉得所有的错误都应该被处理掉,而不是当场产生<code>panic</code>,再去捕获它,或者说不应该使用<code>panic</code>做错误处理的流程。</p>
<p>所以就有了新的疑问,<strong>为啥 Rust 标准库里的 Vec 集合的 remove 方法会产生 panic ,还没有其他的方法也是类似的, 在日常开发中怎样能够避免出现会 panic 的代码?</strong></p>
<p>于是去rust的github仓库查询相关issue,刚好就又有一个相关的:<a href="https://github.com/rust-lang/rust/pull/77480">Add <code>try_remove</code> to <code>Vec</code></a>。这是一个pr,正如标题上所说,发起者添加了一个不会产生<code>panic</code>的<code>try_remove</code>方法,该方法的返回值是<code>Option&lt;T&gt;</code>。照理说好像就没问题了,但是这个pr目前是关闭状态,继续往下看为什么。下面就有人回了,如果你要加这个,那就还应该增加<code>try_</code>的类似的方法,例如<code>try_swap_remove</code>,<code>try_insert</code>,<code>try_split_at</code>,不然就会很奇怪。</p>
<p>然后下面就开始讨论是否有必要做这些事情,比如因为索引前提很简单,所以用户应该自己检查,又比如应该避免多次检查等,这里因为个人能力有限,所以建议大家去看原文。</p>
<p>虽然最后没能得到肯定的答案,我有如下一些想法:</p>
<ul>
<li>标准库要怎样设计能够既清晰明了,又能在不使用unsafe的情况下(不手动做unsafe的事),满足所有的需求,比如索引越界检查,虽然有讲到llvm能够优化部分检查操作,但这样是不是就又是一种隐式的经验问题了:我需要知道这样写,代码才性能好,因为这样才能让编译器给我优化。</li>
<li>在工程中,能不能通过某些手段,去避免所有的会panic的代码。比如和panic相关的部分,交给最厉害的做,然后剩下的在提交代码做必须强制处理异常的检查。</li>
</ul></description><category domain="https://umaYnit.github.io/posts/">posts</category><category domain="https://umaYnit.github.io/tags/rust/">Rust</category><category domain="https://umaYnit.github.io/tags/web/">Web</category></item><item><title>从Java的隐藏开销思考关于Rust零开销抽象的部分</title><link>https://umaYnit.github.io/posts/%E4%BB%8Ejava%E7%9A%84%E9%9A%90%E8%97%8F%E5%BC%80%E9%94%80%E6%80%9D%E8%80%83%E5%85%B3%E4%BA%8Erust%E9%9B%B6%E5%BC%80%E9%94%80%E6%8A%BD%E8%B1%A1%E7%9A%84%E9%83%A8%E5%88%86/</link><guid isPermaLink="true">https://umaYnit.github.io/posts/%E4%BB%8Ejava%E7%9A%84%E9%9A%90%E8%97%8F%E5%BC%80%E9%94%80%E6%80%9D%E8%80%83%E5%85%B3%E4%BA%8Erust%E9%9B%B6%E5%BC%80%E9%94%80%E6%8A%BD%E8%B1%A1%E7%9A%84%E9%83%A8%E5%88%86/</guid><pubDate>Mon, 19 Oct 2020 16:28:02 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><p>今天在翻某群历史消息的时候,看到有一篇关于Android的性能优化文章归档的博客,其中有一篇,叫<a href="https://academy.realm.io/cn/posts/360andev-jake-wharton-java-hidden-costs-android/">探索Java隐藏的开销</a>。就从字节码和本地代码层面,以及各大App中的情况来探究了语言开销的问题。虽然文章更多的是以安卓的习惯和角度去探寻问题,但很多语言相关及分析思路上,是相通的。写到这里时,我突然又想到了kotlin,kotlin也是java字节码平台上的一种语言,那么它的实现也依赖于并受限于字节码和jvm提供的功能,是不是也会有相同的问题(见第二小点内容,嵌套类的实现)。</p>
<p>第一个小点,讲的是一个Java类中,隐藏(自动创建)的方法。如下代码所示,下面这段代码有多少个方法?</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Example</span><span class="o">{</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>脑子里回想起学习Java基础的“每个类在没有显示声明构造方法时,都会隐式的有一个空参构造方法”。再想想其他的,好像没有了,遂回答:“一个”。</p>
<p>继续看文章,文章中编译到了<code>dex</code>文件,使用<code>dexdump</code>查看信息,打印出函数列表(<code>method_ids_size </code>)为<strong>2</strong>,有点出乎意料,猜想是否与继承有关(java的类都继承自Object)。使用<code>javap</code>查看字节码信息,如下所示:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">$</span> <span class="n">javap</span> <span class="o">-</span><span class="n">c</span> <span class="n">Example</span><span class="o">.</span><span class="na">class</span>
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Example</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">Example</span><span class="o">();</span>
</span></span><span class="line"><span class="cl"> <span class="n">Code</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">0</span><span class="o">:</span> <span class="n">aload_0</span>
</span></span><span class="line"><span class="cl"> <span class="n">1</span><span class="o">:</span> <span class="n">invokespecial</span> <span class="err">#</span><span class="n">1</span> <span class="c1">//java/lang/Object.&#34;&lt;init&gt;&#34;:()V
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">4</span><span class="o">:</span> <span class="k">return</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>在索引 1 处,是我们的对象构造函数,它被父类的构造函数调用。这是因为,即使我们不声明它,<code>Example</code> 也是继承于 <code>Object</code> 的。每一个构造函数都会调用它的父类的构造函数。它是自动插入的。这意味着我们的 class 流中有两个方法。
所有这些关于我的初始问题的答案都是对的。区别就是术语不同。这是真实的情况。我们没有定义任何方法。但是只有人类关心它。作为人类,我们读写这些源文件。我们是唯一关心它们内部构造的人。另外两个方法更重要,方法的个数实际上是编译进 class 文件里面了。无论是否声明,这些方法都在 class 的内部。</p>
</blockquote>
<p>上面这段是原文章的回答,目前我还不是很能理解第二个函数关于父类构造函数。我对题目的理解是该<code>Example</code>类包含定义的方法,而父类构造方法是调用的部分,不知道为啥这里也被包含了进去。和同事讨论后,他的理解是,父类的方法是放在了子类的里面。所以回到了Java这里,继承到底是怎么实现的问题。之前也和他有凭感觉的猜想过,得出的结论是类似于大圆包含小圆,子类包含了父类。今天回想起来,感觉好像不是很对,于是手动尝试上面的实验。测试如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Example</span> <span class="kd">extends</span> <span class="n">B</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="n">C</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">C</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这里编写了3个类,Example、B和C,其中Example继承了B,B继承了C,除了因为需要打jar包的缘故,给Example类写了一个main方法外,都是没有写其他方法的。使用文章中提到的工具<a href="https://github.com/JakeWharton/diffuse"><code>dex-method-list</code></a>,打印出详细信息,如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">$</span> <span class="n">java</span> <span class="o">-</span><span class="n">jar</span> <span class="n">diffuse</span><span class="o">.</span><span class="na">jar</span> <span class="n">members</span> <span class="o">--</span><span class="n">jar</span> <span class="n">test</span><span class="o">.</span><span class="na">jar</span>
</span></span><span class="line"><span class="cl"><span class="n">B</span> <span class="o">&lt;</span><span class="n">init</span><span class="o">&gt;()</span>
</span></span><span class="line"><span class="cl"><span class="n">C</span> <span class="o">&lt;</span><span class="n">init</span><span class="o">&gt;()</span>
</span></span><span class="line"><span class="cl"><span class="n">Example</span> <span class="o">&lt;</span><span class="n">init</span><span class="o">&gt;()</span>
</span></span><span class="line"><span class="cl"><span class="n">Example</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[])</span>
</span></span><span class="line"><span class="cl"><span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Object</span> <span class="o">&lt;</span><span class="n">init</span><span class="o">&gt;()</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>可以看到,总共有5个方法,分别是Example类、B类和C类的构造方法,main 方法和一个Object的构造方法。到这里,可以得出,之前和同事猜想的结论是错误的,属于瞎猜。然后这里主要的疑问点,其实是<code>dexdump</code>工具这里的<code>method_ids_size</code>计数,到底是指哪一部分的问题。所以又写了如下来进行测试:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Example</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">String</span> <span class="n">_s</span> <span class="o">=</span> <span class="n">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">42</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="n">$</span> <span class="n">javac</span> <span class="n">Example</span><span class="o">.</span><span class="na">java</span>
</span></span><span class="line"><span class="cl"><span class="n">$</span> <span class="n">dx</span> <span class="o">--</span><span class="n">dex</span> <span class="o">--</span><span class="n">output</span><span class="o">=</span><span class="n">example</span><span class="o">.</span><span class="na">dex</span> <span class="n">Example</span><span class="o">.</span><span class="na">class</span>
</span></span><span class="line"><span class="cl"><span class="n">$</span> <span class="n">dexdump</span> <span class="o">-</span><span class="n">f</span> <span class="n">example</span><span class="o">.</span><span class="na">dex</span>
</span></span><span class="line"><span class="cl"><span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="n">method_ids_size</span> <span class="o">:</span> <span class="n">4</span>
</span></span><span class="line"><span class="cl"><span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="n">$</span> <span class="n">java</span> <span class="o">-</span><span class="n">jar</span> <span class="n">diffuse</span><span class="o">.</span><span class="na">jar</span> <span class="n">members</span> <span class="o">--</span><span class="n">jar</span> <span class="n">test</span><span class="o">.</span><span class="na">jar</span>
</span></span><span class="line"><span class="cl"><span class="n">Example</span> <span class="o">&lt;</span><span class="n">init</span><span class="o">&gt;()</span>
</span></span><span class="line"><span class="cl"><span class="n">Example</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[])</span>
</span></span><span class="line"><span class="cl"><span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Object</span> <span class="o">&lt;</span><span class="n">init</span><span class="o">&gt;()</span>
</span></span><span class="line"><span class="cl"><span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">String</span> <span class="nf">valueOf</span><span class="o">(</span><span class="kt">int</span><span class="o">)</span> <span class="err">→</span> <span class="n">String</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>所以<code>dexdump</code>方法统计的应该是所有包含的方法的数量,类似于方法表一样。另一方面,子类初始化时,不会实例化父类。说到初始化,这里简单回顾一下:</p>
<p>首先Java的类通过new关键字和构造方法来实例化,这里构造方法其实应该翻译为构造器(<code>constructor </code>)比较好,因为它实际上和Java里的方法并不一样。</p>
<p>1、在概念层面,方法属于Java的类成员,而构造器不属于。构造器和方法是平等的概念,而不是包含(Filed:成员变量、Method:普通方法、Type:内部定义的其他类型,如内部接口、内部类等),</p>
<p>2、在虚拟机层面构造器使用<code>invokespecial</code>指令执行,而方法使用<code>invokevirtual</code>指令执行。</p>
<blockquote>
<p>Constructors, static initializers, and instance initializers are not members and therefore are not inherited. ---- <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2">8.2 Class Memebers章节</a>
构造方法,静态初始化器,对象初始化器,都不是类的成员,因此它们也不可以被子类继承。</p>
<p>a constructor declaration looks just like a method declaration that has no result... ---- <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8">8.8 Constructor Declarations 章节</a>
一个 constructor 的定义就像是一个没有返回值的 method 的定义。</p>
</blockquote>
<p>说到这里,有一些相关的题目:“Java的构造方法到底有还是没有返回值?”、“Java中的构造方法是方法吗?”。现在这些问题大家心里就有自己的见解了吧。</p>
<p>然后</p>
<p>上面说的Java关于new一个对象的侧重点是由这篇文章衍生的部分,是围绕文章相关来的,所以其中还有更多的细节,例如对象的访问定位问题、类加载过程等,大家可以自己去更深入的了解学习。相信下面这类题目,已经完全没有难度了:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Father</span><span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">5</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="nf">Father</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;Father&#39;s i is &#34;</span> <span class="o">+</span> <span class="k">this</span><span class="o">.</span><span class="na">i</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">test</span><span class="o">();</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">test</span><span class="o">(){</span>
</span></span><span class="line"><span class="cl"> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">i</span> <span class="o">-</span> <span class="n">1</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Son</span> <span class="kd">extends</span> <span class="n">Father</span><span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">55</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="nf">Son</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;Son&#39;s i is &#34;</span> <span class="o">+</span> <span class="k">this</span><span class="o">.</span><span class="na">i</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nd">@Override</span>
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">test</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">i</span> <span class="o">+</span> <span class="n">1</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">new</span> <span class="n">Son</span><span class="o">();</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在上面查找资料的过程中,还有另一个有意思的问题。在查看字节码时,发现在构造方法中有一个字节码指令<code>aload_0</code>,不知道是做什么的,于是就查了一下百度,看到这样一条信息:</p>
<blockquote>
<p>总结起来:在非静态方法中, aload_0 表示对this的操作,在static 方法中,aload_0表示对方法的第一参数的操作。</p>
</blockquote>
<p>尝试编写如下代码,并编译到字节码查看:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Example</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">f1</span><span class="o">(</span><span class="n">Integer</span> <span class="n">a</span><span class="o">,</span> <span class="n">Integer</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">Integer</span> <span class="n">_c</span> <span class="o">=</span> <span class="n">a</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">Integer</span> <span class="n">_d</span> <span class="o">=</span> <span class="n">b</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">f2</span><span class="o">(</span><span class="kt">int</span> <span class="n">a</span><span class="o">,</span> <span class="n">Integer</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_c</span> <span class="o">=</span> <span class="n">a</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">Integer</span> <span class="n">_d</span> <span class="o">=</span> <span class="n">b</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">f3</span><span class="o">(</span><span class="kt">int</span> <span class="n">a</span><span class="o">,</span> <span class="n">Integer</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">Example</span> <span class="n">_e</span> <span class="o">=</span> <span class="k">this</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">_c</span> <span class="o">=</span> <span class="n">a</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">Integer</span> <span class="n">_d</span> <span class="o">=</span> <span class="n">b</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="n">$</span> <span class="n">javap</span> <span class="o">-</span><span class="n">c</span> <span class="n">Example</span><span class="o">.</span><span class="na">java</span>
</span></span><span class="line"><span class="cl"><span class="n">Compiled</span> <span class="n">from</span> <span class="s">&#34;Example.java&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Example</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">Example</span><span class="o">();</span>
</span></span><span class="line"><span class="cl"> <span class="n">Code</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">0</span><span class="o">:</span> <span class="n">aload_0</span>
</span></span><span class="line"><span class="cl"> <span class="n">1</span><span class="o">:</span> <span class="n">invokespecial</span> <span class="err">#</span><span class="n">1</span> <span class="c1">// Method java/lang/Object.&#34;&lt;init&gt;&#34;:()V
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="n">4</span><span class="o">:</span> <span class="k">return</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">f1</span><span class="o">(</span><span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Integer</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Integer</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">Code</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">0</span><span class="o">:</span> <span class="n">aload_0</span>
</span></span><span class="line"><span class="cl"> <span class="n">1</span><span class="o">:</span> <span class="n">astore_2</span>
</span></span><span class="line"><span class="cl"> <span class="n">2</span><span class="o">:</span> <span class="n">aload_1</span>
</span></span><span class="line"><span class="cl"> <span class="n">3</span><span class="o">:</span> <span class="n">astore_3</span>
</span></span><span class="line"><span class="cl"> <span class="n">4</span><span class="o">:</span> <span class="k">return</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">f2</span><span class="o">(</span><span class="kt">int</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Integer</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">Code</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">0</span><span class="o">:</span> <span class="n">iload_0</span>
</span></span><span class="line"><span class="cl"> <span class="n">1</span><span class="o">:</span> <span class="n">istore_2</span>
</span></span><span class="line"><span class="cl"> <span class="n">2</span><span class="o">:</span> <span class="n">aload_1</span>
</span></span><span class="line"><span class="cl"> <span class="n">3</span><span class="o">:</span> <span class="n">astore_3</span>
</span></span><span class="line"><span class="cl"> <span class="n">4</span><span class="o">:</span> <span class="k">return</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">f3</span><span class="o">(</span><span class="kt">int</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Integer</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">Code</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">0</span><span class="o">:</span> <span class="n">aload_0</span>
</span></span><span class="line"><span class="cl"> <span class="n">1</span><span class="o">:</span> <span class="n">astore_3</span>
</span></span><span class="line"><span class="cl"> <span class="n">2</span><span class="o">:</span> <span class="n">iload_1</span>
</span></span><span class="line"><span class="cl"> <span class="n">3</span><span class="o">:</span> <span class="n">istore</span> <span class="n">4</span>
</span></span><span class="line"><span class="cl"> <span class="n">5</span><span class="o">:</span> <span class="n">aload_2</span>
</span></span><span class="line"><span class="cl"> <span class="n">6</span><span class="o">:</span> <span class="n">astore</span> <span class="n">5</span>
</span></span><span class="line"><span class="cl"> <span class="n">8</span><span class="o">:</span> <span class="k">return</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这里总共写了3个方法,前两个是静态方法,第三个是非静态方法。参数上面,分别使用了基本类型和引用类型进行对照。</p>
<p>现在来看字节码的情况,首先方法<code>f1</code>中,果然出现了<code>aload_0</code>代表第一个参数,但是在方法<code>f2</code>中,就不是<code>aload_0</code>了,而是<code>iload_0</code>,所以<code>aload_0</code>应该是加载第一个引用类型的变量。然后继续看非静态方法<code>f3</code>,可以看到,虽然在Java代码中它的第一个参数是基本类型,但是第一行指令任然是<code>aload_0</code>,而第一个参数<code>int</code>类型使用的指令却是<code>iload_1</code>,不是从0开始,而是从1开始了。所以结论就很明显了,*load_*是加载指令,其中load前面的代表变量的类型,而load后面的代表参数位置,但是非静态方法比较特殊。这个时候,要是以前的我呀,多半会去死记硬背了:”非静态方法的第一个参数是从1开始“。</p>
<p>但是,恰好最近学了Rust,又恰好,其中有一部分概念比较相似,所以我们可以用更加理解的方式,去学习。看如下代码:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">A</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">impl</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">f1</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">f2</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">A</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// a.f1(); //error: this is an associated function, not a method
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">f2</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">A</span>::<span class="n">f1</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">A</span>::<span class="n">f2</span><span class="p">(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>把<code>struct A</code>当作Java中的类,<code>main</code>方法中,<code>let a = A();</code>就相当于Java中<code>new</code>一个实例对象出来。</p>
<p>回到文章,第二部分讲的是关于java嵌套类的隐藏开销,如下代码:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="c1">// Outer.java
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Outer</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kd">class</span> <span class="nc">Example</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl"> <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></description><category domain="https://umaYnit.github.io/posts/">posts</category><category domain="https://umaYnit.github.io/tags/rust/">Rust</category><category domain="https://umaYnit.github.io/tags/java/">Java</category></item><item><title>Hello World</title><link>https://umaYnit.github.io/posts/hello-world/</link><guid isPermaLink="true">https://umaYnit.github.io/posts/hello-world/</guid><pubDate>Sun, 22 Mar 2020 17:22:55 +0800</pubDate><author>umasensei@gmail.com (uma)</author><copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright><description><p>又开始尝试写博客了。以前也尝试过很多次,从wordpress到hexo再到现在使用的hugo,折腾这个还是花了不少时间,然而每次都只写了一个Hello World,说到底还是没有写博客、日志之类的习惯。</p>
<p>这次又尝试搭建博客,自己还是想有一个地方,可以记录技术、心得、或是生活。</p>
<p>本次起意是在周三的时候,想解决docker多阶段构建时,产生的none镜像的问题(见此处)。当时按自己的思路写了一个shell脚本,后来过了一会儿的时候,发现了shell命令的新用法,遂简化了一部分,再后来无意间发现了更方便地写法,就有一个递进的优化过程,因为自己学习了新知识,新思路。于是想将思考过程记录下来,就产生了写博客的想法,不过最终还是只是像平常一样,将结果记录在了onenote上。</p>
<p>周六的时候,发现了一个非常棒的编程练习网站,虽然以前也经常看到有讲,在leetcode之类的网站上面刷题什么的,也有去尝试过,但是那些网站更多的是算法相关的,比较难的题目,写起来没有太多感觉。而这个网站,更多的是针对语言特性练习,界面也非常的简洁大方,能做什么,怎样做也是一目了然,引导机制十分完善。我选的练习是kotlin(恋恋不忘),题目也是一些比如全字母句之类的。自己靠着蛮力判断完情况后,发现有一个社区解答,看完之后,哇,居然还能这么用?不愧是kotlin,真的牛皮,想记录感悟,于是就产生了确实需要写博客这个想法。</p>
<p>说起来,关于本次搭建博客,有一个感悟的地方,关于可选择性。</p>
<p>想到要搭建博客,于是搜索引擎走起,一眼过去,各种各样的,很多。什么动态博客呀、静态博客呀,wordpress、hexo、hugo、jekyll等,光博客框架就很多。随便打开一个框架后,发现,什么主题呀、模块呀、配置呀。我的天,可研究配置的地方更是多得不得了,眼花缭乱,让我这个选择困难加拖延症无从下手。在浪费了n个小时的时间,逛了很多网站,看了很多主题,模板,插件后,终于回想起来,我好像离最初的目标越来越远了。最后</p>
<p>自己目前的困难点只在于写作,写作这件事本身和markdown语法。</p></description><category domain="https://umaYnit.github.io/posts/">posts</category></item></channel></rss>