-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJVM_4_write_high_performance_code.html
697 lines (521 loc) · 74 KB
/
JVM_4_write_high_performance_code.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.0.0">
<meta name="baidu-site-verification" content="codeva-PBoQMHcqc8" />
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
<link rel="mask-icon" href="/images/logo.svg" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext">
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
<script id="hexo-configurations">
var NexT = window.NexT || {};
var CONFIG = {"hostname":"lfeng.tech","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
</script>
<meta name="description" content="4. 编写高效Java程序4.1 面向对象构造器参数太多怎么办?正常情况下,如果构造器参数过多,可能会考虑重写多个不同参数的构造函数,如下面的例子所示: 12345678910111213141516171819202122232425262728293031323334public class FoodNormal &#123; //required private final S">
<meta property="og:type" content="article">
<meta property="og:title" content="JVM性能优化系列-(4) 编写高效Java程序">
<meta property="og:url" content="https://lfeng.tech/JVM_4_write_high_performance_code.html">
<meta property="og:site_name" content="Vincent's Notes">
<meta property="og:description" content="4. 编写高效Java程序4.1 面向对象构造器参数太多怎么办?正常情况下,如果构造器参数过多,可能会考虑重写多个不同参数的构造函数,如下面的例子所示: 12345678910111213141516171819202122232425262728293031323334public class FoodNormal &#123; //required private final S">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://imgs.lfeng.tech/images/blog/20221211223336_46298.jpg">
<meta property="og:image" content="https://imgs.lfeng.tech/images/blog/20221211223337_9ab45.jpg">
<meta property="article:published_time" content="2020-02-21T23:43:49.000Z">
<meta property="article:modified_time" content="2022-12-11T14:33:37.162Z">
<meta property="article:author" content="Vincent">
<meta property="article:tag" content="Java">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://imgs.lfeng.tech/images/blog/20221211223336_46298.jpg">
<link rel="canonical" href="https://lfeng.tech/JVM_4_write_high_performance_code.html">
<script id="page-configurations">
// https://hexo.io/docs/variables.html
CONFIG.page = {
sidebar: "",
isHome : false,
isPost : true,
lang : 'zh-CN'
};
</script>
<title>JVM性能优化系列-(4) 编写高效Java程序 | Vincent's Notes</title>
<noscript>
<style>
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-header { opacity: initial; }
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="container use-motion">
<div class="headband"></div>
<header class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
</div>
<div class="site-meta">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<h1 class="site-title">Vincent's Notes</h1>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger">
</div>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="main-menu menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>
</li>
</ul>
</nav>
</div>
</header>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
<span>0%</span>
</div>
<main class="main">
<div class="main-inner">
<div class="content-wrap">
<div class="content post posts-expand">
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://lfeng.tech/JVM_4_write_high_performance_code.html">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Vincent">
<meta itemprop="description" content="Vincent's tech blog">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Vincent's Notes">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
JVM性能优化系列-(4) 编写高效Java程序
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-02-21 23:43:49" itemprop="dateCreated datePublished" datetime="2020-02-21T23:43:49Z">2020-02-21</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar-check"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2022-12-11 14:33:37" itemprop="dateModified" datetime="2022-12-11T14:33:37Z">2022-12-11</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
</span>
</span>
<span id="/JVM_4_write_high_performance_code.html" class="post-meta-item leancloud_visitors" data-flag-title="JVM性能优化系列-(4) 编写高效Java程序" title="阅读次数">
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数:</span>
<span class="leancloud-visitors-count"></span>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-comment"></i>
</span>
<span class="post-meta-item-text">Valine:</span>
<a title="valine" href="/JVM_4_write_high_performance_code.html#valine-comments" itemprop="discussionUrl">
<span class="post-comments-count valine-comment-count" data-xid="/JVM_4_write_high_performance_code.html" itemprop="commentCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p><img src="https://imgs.lfeng.tech/images/blog/20221211223336_46298.jpg" alt="JVM.jpg"></p>
<h2 id="4-编写高效Java程序"><a href="#4-编写高效Java程序" class="headerlink" title="4. 编写高效Java程序"></a>4. 编写高效Java程序</h2><h3 id="4-1-面向对象"><a href="#4-1-面向对象" class="headerlink" title="4.1 面向对象"></a>4.1 面向对象</h3><h4 id="构造器参数太多怎么办?"><a href="#构造器参数太多怎么办?" class="headerlink" title="构造器参数太多怎么办?"></a>构造器参数太多怎么办?</h4><p>正常情况下,如果构造器参数过多,可能会考虑重写多个不同参数的构造函数,如下面的例子所示:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">public class FoodNormal {</span><br><span class="line"></span><br><span class="line"> //required</span><br><span class="line"> private final String foodName;//名称</span><br><span class="line"> private final int reilang;//热量</span><br><span class="line"></span><br><span class="line"> //optional</span><br><span class="line"> private final int danbz;//蛋白质</span><br><span class="line"> private final int dianfen;//淀粉</span><br><span class="line"> private final int zf;//脂肪</span><br><span class="line"> </span><br><span class="line"> //全参数</span><br><span class="line"> public FoodNormal(String foodName, int reilang, int danbz, </span><br><span class="line"> int dianfen, int zf, int tang, int wss) {</span><br><span class="line"> super();</span><br><span class="line"> this.foodName = foodName;</span><br><span class="line"> this.reilang = reilang;</span><br><span class="line"> this.danbz = danbz;</span><br><span class="line"> this.dianfen = dianfen;</span><br><span class="line"> this.zf = zf;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> //2个参数</span><br><span class="line"> public FoodNormal(String foodName, int reilang) {</span><br><span class="line"> this(foodName,reilang,0,0,0,0,0);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> //3....6个参数</span><br><span class="line"> //</span><br><span class="line"> </span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> FoodNormal fn = new FoodNormal("food1",1200,200,0,0,300,100);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<span id="more"></span>
<p>但是问题很明显:1.可读性很差,特别是参数个数多,并且有多个相同类型的参数时;2.调换参数的顺序,编译器也不会报错。</p>
<p>针对这个两个问题,一种选择是 JavaBeans 模式,在这种模式中,调用一个<strong>无参数的构造函数</strong>来创建对象,然后调用 setter 方法来设置每个必需的参数和可选参数。这种方法缺陷很明显:排除了让类不可变的可能性,并且需要增加工作以确保线程安全。</p>
<p>推荐的方法是使用<strong>builder模式</strong>,该模式结合了可伸缩构造方法模式的安全性和JavaBean模式的可读性。</p>
<p>下面的例子中,创建了一个内部类Builder用于接受对应的参数,最后通过Builder类将参数返回。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">public class FoodBuilder {</span><br><span class="line"></span><br><span class="line"> //required</span><br><span class="line"> private final String foodName;</span><br><span class="line"> private final int reilang;</span><br><span class="line"></span><br><span class="line"> //optional</span><br><span class="line"> private int danbz;</span><br><span class="line"> private int dianfen;</span><br><span class="line"> private int zf;</span><br><span class="line"> </span><br><span class="line"> public static class Builder{</span><br><span class="line"> //required</span><br><span class="line"> private final String foodName;</span><br><span class="line"> private final int reilang;</span><br><span class="line"></span><br><span class="line"> //optional</span><br><span class="line"> private int danbz;</span><br><span class="line"> private int dianfen;</span><br><span class="line"> private int zf;</span><br><span class="line"> </span><br><span class="line"> public Builder(String foodName, int reilang) {</span><br><span class="line"> super();</span><br><span class="line"> this.foodName = foodName;</span><br><span class="line"> this.reilang = reilang;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public Builder danbz(int val) {</span><br><span class="line"> this.danbz = val;</span><br><span class="line"> return this;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public Builder dianfen(int val) {</span><br><span class="line"> this.dianfen = val;</span><br><span class="line"> return this;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public Builder zf(int val) {</span><br><span class="line"> this.zf = val;</span><br><span class="line"> return this;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public FoodBuilder build() {</span><br><span class="line"> return new FoodBuilder(this);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> private FoodBuilder(Builder builder) {</span><br><span class="line"> foodName = builder.foodName;</span><br><span class="line"> reilang = builder.reilang;</span><br><span class="line"> </span><br><span class="line"> danbz = builder.danbz;</span><br><span class="line"> dianfen = builder.danbz;</span><br><span class="line"> zf = builder.zf;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> FoodBuilder foodBuilder = new FoodBuilder.Builder("food2", 1000)</span><br><span class="line"> .danbz(100).dianfen(100).zf(100).build();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><strong>Builder模式更进一步</strong></p>
<p>标准的Builder模式,包含以下4个部分:</p>
<ol>
<li><strong>抽象建造者</strong>:一般来说是个接口,1)建造方法,建造部件的方法(不止一个);2)返回产品的方法</li>
<li><strong>具体建造者</strong>:继承抽象建造者,并且实现相应的建造方法。</li>
<li><strong>导演者</strong>:调用具体的建造者,创建产品对象。</li>
<li><strong>产品</strong>:需要建造的复杂对象。</li>
</ol>
<p>下面的例子中,man和woman是产品;personBuilder是抽象建造者;manBuilder和womanBuilder继承了personBuilder并实现了相应方法,是具体建造者;NvWa是导演者,调用建造者方法建造产品。</p>
<p><code>产品类</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line">public abstract class Person {</span><br><span class="line"></span><br><span class="line"> protected String head;</span><br><span class="line"> protected String body;</span><br><span class="line"> protected String foot;</span><br><span class="line"></span><br><span class="line"> public String getHead() {</span><br><span class="line"> return head;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setHead(String head) {</span><br><span class="line"> this.head = head;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public String getBody() {</span><br><span class="line"> return body;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setBody(String body) {</span><br><span class="line"> this.body = body;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public String getFoot() {</span><br><span class="line"> return foot;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setFoot(String foot) {</span><br><span class="line"> this.foot = foot;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 具体的产品</span><br><span class="line">public class Man extends Person {</span><br><span class="line"> public Man() {</span><br><span class="line"> System.out.println("create a man");</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public String toString() {</span><br><span class="line"> return "Man{}";</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public class Woman extends Person {</span><br><span class="line"></span><br><span class="line"> public Woman() {</span><br><span class="line"> System.out.println("create a Woman");</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public String toString() {</span><br><span class="line"> return "Woman{}";</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>抽象建造类</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">public abstract class PersonBuilder {</span><br><span class="line"> </span><br><span class="line"> //建造部件</span><br><span class="line"> public abstract void buildHead();</span><br><span class="line"> public abstract void buildBody();</span><br><span class="line"> public abstract void buildFoot();</span><br><span class="line"> </span><br><span class="line"> public abstract Person createPerson();</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>具体建造者</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">public class ManBuilder extends PersonBuilder {</span><br><span class="line"> </span><br><span class="line"> private Person person;</span><br><span class="line"> </span><br><span class="line"> public ManBuilder() {</span><br><span class="line"> this.person = new Man();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void buildHead() {</span><br><span class="line"> person.setHead("Brave Head");</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void buildBody() {</span><br><span class="line"> person.setBody("Strong body");</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void buildFoot() {</span><br><span class="line"> person.setFoot("powful foot");</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public Person createPerson() {</span><br><span class="line"> return person;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public class WomanBuilder extends PersonBuilder {</span><br><span class="line"> </span><br><span class="line"> private Person person;</span><br><span class="line"> </span><br><span class="line"> public WomanBuilder() {</span><br><span class="line"> this.person = new Woman();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void buildHead() {</span><br><span class="line"> person.setHead("Pretty Head");</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void buildBody() {</span><br><span class="line"> person.setBody("soft body");</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void buildFoot() {</span><br><span class="line"> person.setFoot("long white foot");</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public Person createPerson() {</span><br><span class="line"> return person;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>导演者</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">public class NvWa {</span><br><span class="line"> </span><br><span class="line"> public Person buildPerson(PersonBuilder pb) {</span><br><span class="line"> pb.buildHead();</span><br><span class="line"> pb.buildBody();</span><br><span class="line"> pb.buildFoot();</span><br><span class="line"> return pb.createPerson();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>下面是测试程序:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">public class Mingyun {</span><br><span class="line"></span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> System.out.println("create NvWa");</span><br><span class="line"> NvWa nvwa = new NvWa();</span><br><span class="line"> nvwa.buildPerson(new ManBuilder());</span><br><span class="line"> nvwa.buildPerson(new WomanBuilder());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="不需要实例化的类应该构造器私有"><a href="#不需要实例化的类应该构造器私有" class="headerlink" title="不需要实例化的类应该构造器私有"></a>不需要实例化的类应该构造器私有</h4><p>工程中的工具类,为了防止实例化,可以将构造器私有化。</p>
<h4 id="不要创建不必要的对象"><a href="#不要创建不必要的对象" class="headerlink" title="不要创建不必要的对象"></a>不要创建不必要的对象</h4><p><strong>1. 自动装箱和拆箱等隐式转换。</strong></p>
<blockquote>
<p>自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。</p>
</blockquote>
<p>自动装箱和拆箱在Java中很常见,比如我们有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么Java会自动将这个原始类型值转换成与之对应的对象。</p>
<p>自动装箱的弊端:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Integer sum = 0;</span><br><span class="line"> for(int i=1000; i<5000; i++){</span><br><span class="line"> sum+=i;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>上面的例子中,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。上面的循环中会创建将近4000个无用的Integer对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。</p>
<p><strong>2. 实例共用,声明为static</strong></p>
<p>多个共用的情况下,声明为static或者采用单例模式,以免生成多个对象影响程序性能。</p>
<h4 id="避免使用终结方法"><a href="#避免使用终结方法" class="headerlink" title="避免使用终结方法"></a>避免使用终结方法</h4><p>finalize方法,因为虚拟机不保证这个方法被执行,所以释放资源时,不能保证。</p>
<p><strong>为了合理的释放资源,推荐下面两种方法:</strong></p>
<ul>
<li>try resource</li>
</ul>
<p>Java 1.7中引入了try-with-resource语法糖来打开资源,而无需自己书写资源来关闭代码。例子如下:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">public class TryWithResource {</span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> try (Connection conn = new Connection()) {</span><br><span class="line"> conn.sendData();</span><br><span class="line"> }</span><br><span class="line"> catch (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>为了能够配合try-with-resource,资源必须实现<code>AutoClosable</code>接口。该接口的实现类需要重写<code>close</code>方法:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">public class Connection implements AutoCloseable {</span><br><span class="line"> public void sendData() {</span><br><span class="line"> System.out.println("正在发送数据");</span><br><span class="line"> }</span><br><span class="line"> @Override</span><br><span class="line"> public void close() throws Exception {</span><br><span class="line"> System.out.println("正在关闭连接");</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<ul>
<li>try finally</li>
</ul>
<p>在finally语句块中释放资源,保证资源永远能够被正常释放。</p>
<h4 id="使类和成员的可访问性最小化"><a href="#使类和成员的可访问性最小化" class="headerlink" title="使类和成员的可访问性最小化"></a>使类和成员的可访问性最小化</h4><p>可以有效的解除系统中各个模块的耦合度、实现每个模块的独立开发、使得系统更加的可维护,更加的健壮。</p>
<p><strong>如何最小化类和接口的可访问性?</strong></p>
<ol>
<li><p>能将类和接口做成包级私有就一定要做成包级私有的。</p>
</li>
<li><p>如果一个类或者接口,只被另外的一个类应用,那么最好将这个类或者接口做成其内部的私有类或者接口。</p>
</li>
</ol>
<p><strong>如何最小化一个了类中的成员的可访问性?</strong></p>
<ol>
<li><p>首先设计出该类需要暴露出来的api,然后将剩下的成员的设计成private类型。然后再其他类需要访问某些private类型的成员时,在删掉private,使其变成包级私有。如果你发现你需要经常这样做,那么就请你重新设计一下这个类的api。</p>
</li>
<li><p>对于protected类型的成员,作用域是整个系统,所以,能用包访问类型的成员的话就尽量不要使用保护行的成员。</p>
</li>
<li><p>不能为了测试而将包中的类或者成员变为public类型的,最多只能设置成包级私有类型。</p>
</li>
<li><p>实例域绝对不能是public类型的.</p>
</li>
</ol>
<h4 id="使可变性最小化"><a href="#使可变性最小化" class="headerlink" title="使可变性最小化"></a>使可变性最小化</h4><p>不可变类只是实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例的时候就提供,并在对象的整个生命周期(lifetime)内固定不变。</p>
<p>Java平台类库中包含许多不可变的类,其中有String、基本类型的包装类、BigInteger和BigDecimal。</p>
<p>存在不可变的类有许多理由:<strong>不可变的类比可变的类更加易于设计、实现和使用。不容易出错,且更加安全。</strong></p>
<p><strong>为了使类成为不可变,要遵循下面五条规则:</strong></p>
<p>1、<strong>不要提供任何会修改对象状态的方法</strong>(也称为mutator),即改变对象属性的方法。</p>
<p>2、<strong>保证类不会被扩展。</strong>这样可以防止粗心或者恶意的子类假装对象的状态已经改变,从而破坏该类的不可变行为。为了防止子类化,一般做法是使这个类成为final的。</p>
<p>3、使<strong>所有的域都是final的</strong>。通过系统的强制方式,这可以清楚地表明你的意图。而且,如果一个指向新创建实例的引用在缺乏同步机制的情况下,从一个线程被传递到另一个 线程,就必须确保正确的行为。</p>
<p>4、使<strong>所有的域都成为私有的</strong>。这样可以防止客户端获得访问被域引用的可变对象的权限,并防止客户端直接修改这些对象。虽然从技术上讲,允许不可变的类具有公有的final 域,只要这些域包含基本类型的值或者指向不可变对象的引用,但是不建议这样做,因为这样会使得在以后的版本中无法再改变内部的表示法。</p>
<p>5、确保对于任何可变组件的互斥访问。<strong>如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象的引用</strong>。并且,永远不要用客户端提供的对象引用初始化这样的域,也不要从任何访问方法(accessor)中返回该对象引用。在构造器、访问方法和readObject中请使用保护性拷贝(defensive copy)技术。</p>
<h4 id="优先使用复合"><a href="#优先使用复合" class="headerlink" title="优先使用复合"></a>优先使用复合</h4><ul>
<li>继承:会打破封装性</li>
<li>组合:在内部持有一个父类作为成员变量。</li>
</ul>
<p>使用继承扩展一个类很危险,父类的具体实现很容易影响子类的正确性。<strong>而复合优先于继承告诉我们,不用扩展现有的类,而是在新类中增加一个私有域,让它引用现有类的一个实例。</strong>这种设计称为复合(Composition)。</p>
<blockquote>
<p>只有当子类和超类之间确实存在父子关系时,才可以考虑使用继承。否则都应该用复合,包装类不仅比子类更加健壮,而且功能也更加强大。</p>
</blockquote>
<h4 id="接口优于抽象类"><a href="#接口优于抽象类" class="headerlink" title="接口优于抽象类"></a>接口优于抽象类</h4><p><strong>接口和抽象类</strong></p>
<ul>
<li>抽象类允许某些方法的实现,但是接口不允许(JDK 1.8开始已经可以了)</li>
<li>现有类必须成为抽象类的子类,但是只能单继承,接口可以多继承</li>
</ul>
<p><strong>接口优点</strong></p>
<ul>
<li>现有类可以很容易被更新,以实现新的接口。</li>
<li>接口允许我们构造非层次结构的类型框架,接口可以多继承。</li>
<li><strong>骨架实现类</strong>,下面对骨架类进行详细介绍</li>
</ul>
<p>假定有<code>Interface A</code>, 可以声明<code>abstarct class B implements A</code>,接着在真正的实现类C中 <code>class C extends B implements A</code>。B就是所谓的骨架类,骨架类中对A中的一些基础通用方法进行了实现,使得C可以直接使用骨架类中的实现,无需再次实现,或者调用骨架类中的实现进行进一步的定制与优化。C只需要实现B中未实现的方法或者添加新的方法。</p>
<p>骨架实现类的优点在于,<strong>它们提供抽象类的所有实现的帮助,而不会强加抽象类作为类型定义时的严格约束</strong>。对于具有骨架实现类的接口的大多数实现者来说,继承这个类是显而易见的选择,但它不是必需的。如果一个类不能继承骨架的实现,这个类可以直接实现接口。<strong>该类仍然受益于接口本身的任何默认方法</strong>。此外,骨架实现类仍然可以协助接口的实现。实现接口的类可以将接口方法的调用转发给继承骨架实现的私有内部类的包含实例。这种被称为模拟多重继承的技术,它提供了多重继承的许多好处,同时避免了缺陷。</p>
<p>JDK的实现中,使用了大量的骨架类,按照惯例,骨架实现类被称为AbstractInterface,其中Interface是它们实现的接口的名称。 例如,集合框架( Collections Framework)提供了一个框架实现以配合每个主要集合接口:AbstractCollection,AbstractSet,AbstractList和AbstractMap。</p>
<h3 id="4-2-方法"><a href="#4-2-方法" class="headerlink" title="4.2 方法"></a>4.2 方法</h3><h4 id="可变参数要谨慎使用"><a href="#可变参数要谨慎使用" class="headerlink" title="可变参数要谨慎使用"></a>可变参数要谨慎使用</h4><p>从Java 1.5开始就增加了可变参数(varargs)方法,又称作variable arity method。可变参数方法接受0个或多个指定类型的参数。<strong>它的机制是先创建一个数组,数组的大小为调用位置所传递的参数数量,然后将值传到数组中,最后将数组传递到方法。</strong></p>
<p>例如下面的例子,返回多个参数的和:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">// Simple use of varargs - Page 197</span><br><span class="line">static int sum(int... args) {</span><br><span class="line"> int sum = 0;</span><br><span class="line"> for (int arg : args)</span><br><span class="line"> sum += arg;</span><br><span class="line"> return sum;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>但是这种方法也接受0个参数,所以一般需要对参数进行检查。通常为了规避这种情况,就是<strong>声明该方法有两个参数,一个是指定类型的正常参数,另一个是这种类型的varargs参数</strong>。这个方法弥补了上面的不足(不需要再检查参数的数量了,因为至少要传递一个参数,否则不能通过编译):</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">static int min(int firstArg, int... remainingArgs) {</span><br><span class="line"> int min = firstArg;</span><br><span class="line"> for (int arg : remainingArgs)</span><br><span class="line"> if (arg < min)</span><br><span class="line"> min = arg;</span><br><span class="line"> return min;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<blockquote>
<p>需要注意的是,在重视性能的情况下,使用可变参数机制要特别小心。可变参数方法每次调用都会导致进行一次数组分配和初始化。</p>
</blockquote>
<h4 id="返回零长度的数组或集合,不要返回null"><a href="#返回零长度的数组或集合,不要返回null" class="headerlink" title="返回零长度的数组或集合,不要返回null"></a>返回零长度的数组或集合,不要返回null</h4><p>要求调用方单独处理null的情况。对于list的情况,可以直接返回jdk内置的Collections.emptyList()。</p>
<h4 id="优先使用标准的异常"><a href="#优先使用标准的异常" class="headerlink" title="优先使用标准的异常"></a>优先使用标准的异常</h4><ul>
<li>可读性。</li>
<li>追求代码的重用。</li>
<li>在类装载的性能上考虑,也提倡使用标准异常。</li>
</ul>
<p>常用异常:</p>
<p>illegalArgumentException — 调用者传递的参数不合适<br>illegalStateException — 接收状态异常<br>NullPointException — 空指针<br>UnSupportOperationException – 操作不支持</p>
<h3 id="4-3-通用程序设计"><a href="#4-3-通用程序设计" class="headerlink" title="4.3 通用程序设计"></a>4.3 通用程序设计</h3><h4 id="用枚举代替int常量"><a href="#用枚举代替int常量" class="headerlink" title="用枚举代替int常量"></a>用枚举代替int常量</h4><p>在枚举类型出现之前,一般都常常使用int常量或者String常量表示列举相关事物。如:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public static final int APPLE_FUJI = 0;</span><br><span class="line">public static final int APPLE_PIPPIN = 1;</span><br><span class="line">public static final int APPLE_GRANNY_SMITH = 2;</span><br><span class="line"></span><br><span class="line">public static final int ORANGE_NAVEL = 0;</span><br><span class="line">public static final int ORANGE_TEMPLE = 1;</span><br><span class="line">public static final int ORANGE_BLOOD = 2;</span><br></pre></td></tr></table></figure>
<p>针对int常量以下不足:</p>
<ol>
<li>在类型安全方面,如果你想使用的是ORANGE_NAVEL,但是传递的是APPLE_FUJI,编译器并不能检测出错误;</li>
<li>因为int常量是编译时常量,被编译到使用它们的客户端中。若与枚举常量关联的int发生了变化,客户端需重新编译,否则它们的行为就不确定;</li>
<li>没有便利方法将int常量翻译成可打印的字符串。这里的意思应该是比如你想调用的是ORANGE_NAVEL,debug的时候显示的是0,但你不能确定是APPLE_FUJI还是ORANGE_NAVEL</li>
</ol>
<p><strong>1. 默认枚举</strong></p>
<p>上面的例子可以使用下面的enum重写:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">public enum Apple {</span><br><span class="line"> APPLE_FUJI,</span><br><span class="line"> APPLE_PIPPIN,</span><br><span class="line"> APPLE_GRANNY_SMITH;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>在调用的时候,直接使用enum类型,在编译的时候可以直接指定类型,否则编译不通过;并且debug的时候,显示的是enum中的常量(APPLE_FUJI这样的),可以一眼看出是否用错;最后由于枚举导出的常量域(APPLE_FUJI等)与客户端之间是通过枚举来引用的,再增加或者重排序枚举类型中的常量后,并不需要重新编译客户端代码。</p>
<p><strong>2. 带行为的枚举</strong></p>
<p>首先必须明白,<strong>java里的枚举就是一个类,枚举中的每个对象,是这个枚举类的一个实例。</strong></p>
<p>因此我们可以编写下面的枚举类,并且提供相应的计算方法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">public enum DepotEnum {</span><br><span class="line"> UNPAY(0,"未支付"),PAID(1,"已支付"),TIMOUT(-1,"超时");</span><br><span class="line"> </span><br><span class="line"> private int status;</span><br><span class="line"> private String desc;</span><br><span class="line"> private String dbInfo;//其他属性</span><br><span class="line"> </span><br><span class="line"> private DepotEnum(int status, String desc) {</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.desc = desc;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public int getStatus() {</span><br><span class="line"> return status;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public String getDesc() {</span><br><span class="line"> return desc;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public String getDbInfo() {</span><br><span class="line"> return dbInfo;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public int calcStatus(int params) {</span><br><span class="line"> return status+params;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> for(DepotEnum e:DepotEnum.values()) {</span><br><span class="line"> System.out.println(e+":"+e.calcStatus(14));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>下面是比较复杂的枚举,这里在类里面定义了枚举BetterActive枚举类,进行计算加减乘除的操作,为了保证每增加一个枚举类后,都增加对应的计算方法,这里将计算方法oper定义为抽象方法,保证了在增加枚举变量时,一定增加对应的oper方法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">public class ActiveEnum {</span><br><span class="line"> </span><br><span class="line"> public enum BetterActive{</span><br><span class="line"> PLUS {</span><br><span class="line"> @Override</span><br><span class="line"> double oper(double x, double y) {</span><br><span class="line"> return x+y;</span><br><span class="line"> }</span><br><span class="line"> },MINUS {</span><br><span class="line"> @Override</span><br><span class="line"> double oper(double x, double y) {</span><br><span class="line"> return x-y;</span><br><span class="line"> }</span><br><span class="line"> },MUL {</span><br><span class="line"> @Override</span><br><span class="line"> double oper(double x, double y) {</span><br><span class="line"> return x*y;</span><br><span class="line"> }</span><br><span class="line"> },DIV {</span><br><span class="line"> @Override</span><br><span class="line"> double oper(double x, double y) {</span><br><span class="line"> return x/y;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> </span><br><span class="line"> abstract double oper(double x,double y); </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> System.out.println(BetterActive.PLUS.oper(0.1, 0.2));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><strong>3. 策略枚举</strong></p>
<p>主要是为了优化在多个枚举变量的情况下,尽量减少重复代码。下面以不同的日期,薪水的支付方式不同为例,进行说明,当增加了一个新的日期后,我们只需要在外层枚举类中进行修改,无需修改其他计算方法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">public enum BetterPayDay {</span><br><span class="line"> MONDAY(PayType.WORK), TUESDAY(PayType.WORK), WEDNESDAY(</span><br><span class="line"> PayType.WORK), THURSDAY(PayType.WORK), FRIDAY(PayType.WORK), </span><br><span class="line"> SATURDAY(PayType.REST), SUNDAY(PayType.REST),WUYI(PayType.REST);</span><br><span class="line"></span><br><span class="line"> private final PayType payType;//成员变量</span><br><span class="line"></span><br><span class="line"> BetterPayDay(PayType payType) {</span><br><span class="line"> this.payType = payType;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> double pay(double hoursOvertime) {</span><br><span class="line"> return payType.pay(hoursOvertime);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> //策略枚举</span><br><span class="line"> private enum PayType {</span><br><span class="line"> WORK {</span><br><span class="line"> double pay(double hoursOvertime) {</span><br><span class="line"> return hoursOvertime*HOURS_WORK;</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> REST {</span><br><span class="line"> double pay(double hoursOvertime) {</span><br><span class="line"> return hoursOvertime*HOURS_REST;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> </span><br><span class="line"> private static final int HOURS_WORK = 2;</span><br><span class="line"> private static final int HOURS_REST = 3;</span><br><span class="line"></span><br><span class="line"> abstract double pay(double hoursOvertime);//抽象计算加班费的方法</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> System.out.println(BetterPayDay.MONDAY.pay(7.5));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="将局部变量的作用域最小化"><a href="#将局部变量的作用域最小化" class="headerlink" title="将局部变量的作用域最小化"></a>将局部变量的作用域最小化</h4><ul>
<li>要使局部变量的作用域最小化,最有力的方法就是在第一次使用它的地方声明。</li>
<li><strong>几乎每个局部变量的声明都应该包含一个初始化表达式。</strong>如果没有足够信息来对一个变量进行有意义的初始化,就应该推迟这个声明,直到可以初始化为止。</li>
<li>尽量保证方法小而集中。</li>
<li>仅在某一代码块中使用的局部变量,那么就在该代码块中声明。</li>
</ul>
<h4 id="精确计算,避免使用float和double"><a href="#精确计算,避免使用float和double" class="headerlink" title="精确计算,避免使用float和double"></a>精确计算,避免使用float和double</h4><p>float和double类型不能用于精确计算,其主要目的是为了科学计算和工程计算,它们执行二进制浮点运算。</p>
<p>转成int或者long,推荐使用bigDecimal。</p>
<h4 id="当心字符串连接的性能"><a href="#当心字符串连接的性能" class="headerlink" title="当心字符串连接的性能"></a>当心字符串连接的性能</h4><p>String是不可变的,每一次拼接都会产生字符串的复制。</p>
<p>StringBuilder和StringBuffer</p>
<ul>
<li>都是可变的类。</li>
<li>StringBuffer线程安全,可以在多线程下使用;StrngBuilder非线程安全,速度比StringBuffer快。</li>
</ul>
<h4 id="控制方法的大小"><a href="#控制方法的大小" class="headerlink" title="控制方法的大小"></a>控制方法的大小</h4><p>这个好理解,主要是从解耦和可维护性角度考虑。</p>
<p>在Unix philosophy中也提到,编写代码时注意<code>Do One Thing and Do It Well</code>。</p>
<hr>
<p>本文由『后端精进之路』原创,首发于博客 <a target="_blank" rel="noopener" href="http://teckee.github.io/">http://teckee.github.io/</a> , 转载请注明出处</p>
<p>搜索『后端精进之路』关注公众号,立刻获取最新文章和<strong>价值2000元的BATJ精品面试课程</strong>。</p>
<p><img src="https://imgs.lfeng.tech/images/blog/20221211223337_9ab45.jpg" alt="后端精进之路.png"></p>
</div>
<div>
<ul class="post-copyright">
<li class="post-copyright-author">
<strong>本文作者: </strong>Vincent
</li>
<li class="post-copyright-link">
<strong>本文链接:</strong>
<a href="https://lfeng.tech/JVM_4_write_high_performance_code.html" title="JVM性能优化系列-(4) 编写高效Java程序">https://lfeng.tech/JVM_4_write_high_performance_code.html</a>
</li>
<li class="post-copyright-license">
<strong>版权声明: </strong>本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处!
</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-tags">
<a href="/tags/Java/" rel="tag"># Java</a>
</div>
<div class="post-nav">
<div class="post-nav-item">
<a href="/JVM_3_execute_system.html" rel="prev" title="JVM性能优化系列-(3) 虚拟机执行子系统">
<i class="fa fa-chevron-left"></i> JVM性能优化系列-(3) 虚拟机执行子系统
</a></div>
<div class="post-nav-item">
<a href="/JVM_5_early_compile_optimization.html" rel="next" title="JVM性能优化系列-(5) 早期编译优化">
JVM性能优化系列-(5) 早期编译优化 <i class="fa fa-chevron-right"></i>
</a></div>
</div>
</footer>
</article>
</div>
<div class="comments" id="valine-comments"></div>
<script>
window.addEventListener('tabs:register', () => {
let { activeClass } = CONFIG.comments;
if (CONFIG.comments.storage) {
activeClass = localStorage.getItem('comments_active') || activeClass;
}
if (activeClass) {
let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
if (activeTab) {
activeTab.click();
}
}
});
if (CONFIG.comments.storage) {
window.addEventListener('tabs:click', event => {
if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
let commentClass = event.target.classList[1];
localStorage.setItem('comments_active', commentClass);
});
}
</script>
</div>
<div class="toggle sidebar-toggle">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
<aside class="sidebar">
<div class="sidebar-inner">
<ul class="sidebar-nav motion-element">
<li class="sidebar-nav-toc">
文章目录
</li>
<li class="sidebar-nav-overview">
站点概览
</li>
</ul>
<!--noindex-->
<div class="post-toc-wrap sidebar-panel">
<div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E7%BC%96%E5%86%99%E9%AB%98%E6%95%88Java%E7%A8%8B%E5%BA%8F"><span class="nav-number">1.</span> <span class="nav-text">4. 编写高效Java程序</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4-1-%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1"><span class="nav-number">1.1.</span> <span class="nav-text">4.1 面向对象</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%99%A8%E5%8F%82%E6%95%B0%E5%A4%AA%E5%A4%9A%E6%80%8E%E4%B9%88%E5%8A%9E%EF%BC%9F"><span class="nav-number">1.1.1.</span> <span class="nav-text">构造器参数太多怎么办?</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%B8%8D%E9%9C%80%E8%A6%81%E5%AE%9E%E4%BE%8B%E5%8C%96%E7%9A%84%E7%B1%BB%E5%BA%94%E8%AF%A5%E6%9E%84%E9%80%A0%E5%99%A8%E7%A7%81%E6%9C%89"><span class="nav-number">1.1.2.</span> <span class="nav-text">不需要实例化的类应该构造器私有</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%B8%8D%E8%A6%81%E5%88%9B%E5%BB%BA%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E5%AF%B9%E8%B1%A1"><span class="nav-number">1.1.3.</span> <span class="nav-text">不要创建不必要的对象</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%81%BF%E5%85%8D%E4%BD%BF%E7%94%A8%E7%BB%88%E7%BB%93%E6%96%B9%E6%B3%95"><span class="nav-number">1.1.4.</span> <span class="nav-text">避免使用终结方法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%B1%BB%E5%92%8C%E6%88%90%E5%91%98%E7%9A%84%E5%8F%AF%E8%AE%BF%E9%97%AE%E6%80%A7%E6%9C%80%E5%B0%8F%E5%8C%96"><span class="nav-number">1.1.5.</span> <span class="nav-text">使类和成员的可访问性最小化</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E5%8F%AF%E5%8F%98%E6%80%A7%E6%9C%80%E5%B0%8F%E5%8C%96"><span class="nav-number">1.1.6.</span> <span class="nav-text">使可变性最小化</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BC%98%E5%85%88%E4%BD%BF%E7%94%A8%E5%A4%8D%E5%90%88"><span class="nav-number">1.1.7.</span> <span class="nav-text">优先使用复合</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%8E%A5%E5%8F%A3%E4%BC%98%E4%BA%8E%E6%8A%BD%E8%B1%A1%E7%B1%BB"><span class="nav-number">1.1.8.</span> <span class="nav-text">接口优于抽象类</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-%E6%96%B9%E6%B3%95"><span class="nav-number">1.2.</span> <span class="nav-text">4.2 方法</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E8%A6%81%E8%B0%A8%E6%85%8E%E4%BD%BF%E7%94%A8"><span class="nav-number">1.2.1.</span> <span class="nav-text">可变参数要谨慎使用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%BF%94%E5%9B%9E%E9%9B%B6%E9%95%BF%E5%BA%A6%E7%9A%84%E6%95%B0%E7%BB%84%E6%88%96%E9%9B%86%E5%90%88%EF%BC%8C%E4%B8%8D%E8%A6%81%E8%BF%94%E5%9B%9Enull"><span class="nav-number">1.2.2.</span> <span class="nav-text">返回零长度的数组或集合,不要返回null</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BC%98%E5%85%88%E4%BD%BF%E7%94%A8%E6%A0%87%E5%87%86%E7%9A%84%E5%BC%82%E5%B8%B8"><span class="nav-number">1.2.3.</span> <span class="nav-text">优先使用标准的异常</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-3-%E9%80%9A%E7%94%A8%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1"><span class="nav-number">1.3.</span> <span class="nav-text">4.3 通用程序设计</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%94%A8%E6%9E%9A%E4%B8%BE%E4%BB%A3%E6%9B%BFint%E5%B8%B8%E9%87%8F"><span class="nav-number">1.3.1.</span> <span class="nav-text">用枚举代替int常量</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B0%86%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%9C%80%E5%B0%8F%E5%8C%96"><span class="nav-number">1.3.2.</span> <span class="nav-text">将局部变量的作用域最小化</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%B2%BE%E7%A1%AE%E8%AE%A1%E7%AE%97%EF%BC%8C%E9%81%BF%E5%85%8D%E4%BD%BF%E7%94%A8float%E5%92%8Cdouble"><span class="nav-number">1.3.3.</span> <span class="nav-text">精确计算,避免使用float和double</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%BD%93%E5%BF%83%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BF%9E%E6%8E%A5%E7%9A%84%E6%80%A7%E8%83%BD"><span class="nav-number">1.3.4.</span> <span class="nav-text">当心字符串连接的性能</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%8E%A7%E5%88%B6%E6%96%B9%E6%B3%95%E7%9A%84%E5%A4%A7%E5%B0%8F"><span class="nav-number">1.3.5.</span> <span class="nav-text">控制方法的大小</span></a></li></ol></li></ol></li></ol></div>
</div>
<!--/noindex-->
<div class="site-overview-wrap sidebar-panel">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image" alt="Vincent"
src="/images/avatar.jpg">
<p class="site-author-name" itemprop="name">Vincent</p>
<div class="site-description" itemprop="description">Vincent's tech blog</div>
</div>
<div class="site-state-wrap motion-element">
<nav class="site-state">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">65</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-categories">
<a href="/categories/">
<span class="site-state-item-count">15</span>
<span class="site-state-item-name">分类</span></a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/">
<span class="site-state-item-count">23</span>
<span class="site-state-item-name">标签</span></a>
</div>
</nav>
</div>
<div class="links-of-author motion-element">
<span class="links-of-author-item">
<a href="https://github.com/teckee" title="GitHub → https://github.com/teckee" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
</span>
<span class="links-of-author-item">
<a href="mailto:h0ck@foxmail.com" title="E-Mail → mailto:h0ck@foxmail.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
</span>
</div>
</div>
</div>
</aside>
<div id="sidebar-dimmer"></div>
</div>
</main>
<footer class="footer">
<div class="footer-inner">
<div class="beian"><a href="https://beian.miit.gov.cn/" rel="noopener" target="_blank">沪ICP备19042895号-2 </a>
</div>
<div class="copyright">
©
<span itemprop="copyrightYear">2023</span>
<span class="with-love">
<i class="fa fa-heart"></i>
</span>
<span class="author" itemprop="copyrightHolder">Vincent</span>
</div>
<div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
</div>
<div class="busuanzi-count">
<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
<span class="post-meta-item-icon">
<i class="fa fa-user"></i>
</span>
<span class="site-uv" title="总访客量">
<span id="busuanzi_value_site_uv"></span>
</span>
</span>
<span class="post-meta-divider">|</span>
<span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="site-pv" title="总访问量">
<span id="busuanzi_value_site_pv"></span>
</span>
</span>
</div>
</div>
</footer>
</div>
<script src="/lib/anime.min.js"></script>
<script src="/lib/velocity/velocity.min.js"></script>
<script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script>
<script src="/js/motion.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/js/next-boot.js"></script>
<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
var GUEST = ['nick', 'mail', 'link'];
var guest = 'nick,mail,link';
guest = guest.split(',').filter(item => {
return GUEST.includes(item);
});
new Valine({
el : '#valine-comments',
verify : false,
notify : false,
appId : 'cgQ905Fj6xbazWtyi9b1hafr-gzGzoHsz',
appKey : '68EFTwnd9XYY352gRUJlJyMu',
placeholder: "Just go go",
avatar : 'mm',
meta : guest,
pageSize : '10' || 10,
visitor : true,
lang : '' || 'zh-cn',
path : location.pathname,
recordIP : false,
serverURLs : ''
});
}, window.Valine);
});
</script>
</body>
</html>