-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
439 lines (293 loc) · 182 KB
/
atom.xml
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>羽觞的博客</title>
<link href="/atom.xml" rel="self"/>
<link href="http://yoursite.com/"/>
<updated>2019-05-03T16:51:49.001Z</updated>
<id>http://yoursite.com/</id>
<author>
<name>羽觞</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>java编程思想(十): 内部类</title>
<link href="http://yoursite.com/2019/05/03/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3-%E5%8D%81-%E5%86%85%E9%83%A8%E7%B1%BB/"/>
<id>http://yoursite.com/2019/05/03/java编程思想-十-内部类/</id>
<published>2019-05-03T15:50:48.000Z</published>
<updated>2019-05-03T16:51:49.001Z</updated>
<content type="html"><![CDATA[<p>将一个类的定义放在另一个类的内部,这就是内部类。</p><p>内部类拥有外部类对象的引用。</p><p>在一个类中可以有多个内部类,以不同的方式实现同一个接口,或者继承同一个类。</p><p>有了内部类,一个类可以有任意多种方式实现任意多个接口,可以有任意多种方式继承任意多个类。</p><h2 id="成员内部类"><a href="#成员内部类" class="headerlink" title="成员内部类"></a>成员内部类</h2>]]></content>
<summary type="html">
<p>将一个类的定义放在另一个类的内部,这就是内部类。</p>
<p>内部类拥有外部类对象的引用。</p>
<p>在一个类中可以有多个内部类,以不同的方式实现同一个接口,或者继承同一个类。</p>
<p>有了内部类,一个类可以有任意多种方式实现任意多个接口,可以有任意多种方式继承
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想(七): 复用类</title>
<link href="http://yoursite.com/2019/05/03/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3-%E4%B8%83-%E5%A4%8D%E7%94%A8%E7%B1%BB/"/>
<id>http://yoursite.com/2019/05/03/java编程思想-七-复用类/</id>
<published>2019-05-03T08:38:47.000Z</published>
<updated>2019-05-03T13:22:54.902Z</updated>
<content type="html"><![CDATA[<h2 id="1-final-关键字"><a href="#1-final-关键字" class="headerlink" title="1. final 关键字"></a>1. final 关键字</h2><p>final关键字主要的含义就是“无法改变”。final可以用于数据、方法和类。</p><h3 id="1-数据"><a href="#1-数据" class="headerlink" title="1. 数据"></a>1. 数据</h3><p>final作用于数据上表示数据本身不可以改变。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">final</span> <span class="keyword">int</span> a = <span class="number">10</span>;</span><br><span class="line">a = <span class="number">11</span>; <span class="comment">// 错误 </span></span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> C = <span class="number">2</span>; <span class="comment">// 编译期常量</span></span><br><span class="line"><span class="keyword">final</span> List<String> list = <span class="keyword">new</span> ArrayList<String>();</span><br><span class="line">list.add(<span class="string">"a"</span>); <span class="comment">// 正确</span></span><br><span class="line">list.add(<span class="string">"b"</span>); <span class="comment">// 正确</span></span><br><span class="line">list = <span class="keyword">new</span> ArrayList<String>(); <span class="comment">// 错误,list不能指向其他对象</span></span><br></pre></td></tr></table></figure></p><p>如上,final作用于引用表示引用值本身不能变,即不能指向其他对象。</p><h4 id="final修饰参数"><a href="#final修饰参数" class="headerlink" title="final修饰参数"></a>final修饰参数</h4><p>在方法体的匿名内部类中,参数需要用final修饰。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">adder</span></span>{<span class="function"><span class="keyword">void</span> <span class="title">addXYZ</span><span class="params">()</span></span>;}</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">outer</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> adder <span class="title">getAdder</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> x)</span></span>{</span><br><span class="line"> <span class="keyword">final</span> <span class="keyword">int</span> y = <span class="number">10</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> adder(){</span><br><span class="line"> <span class="keyword">int</span> z = <span class="number">10</span>;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">addXYZ</span><span class="params">()</span></span>{<span class="keyword">return</span> x + y + z;}</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><a id="more"></a><p>因为方法体中的变量是分配在栈上的,生命周期只在方法体内,而内部类对象分配在堆上。如果内部类如果保存外部类的引用,会导致错误。所以为了解决这个问题,java内部会拷贝外部变量。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">adder</span></span>{<span class="function"><span class="keyword">void</span> <span class="title">addXYZ</span><span class="params">()</span></span>;}</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">outer</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> adder <span class="title">getAdder</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> x)</span></span>{</span><br><span class="line"> <span class="keyword">final</span> <span class="keyword">int</span> y = <span class="number">10</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> adder(){</span><br><span class="line"> <span class="keyword">int</span> copyx = x; <span class="comment">// java隐式拷贝</span></span><br><span class="line"> <span class="keyword">int</span> copyy = y; <span class="comment">// java隐式拷贝</span></span><br><span class="line"> <span class="keyword">int</span> z = <span class="number">10</span>;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">addXYZ</span><span class="params">()</span></span>{<span class="keyword">return</span> copyx + copyy + z;}</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>为了让内外含义保持一致,方法体内的局部变量<code>x,y</code>需要用final修饰。</p><blockquote><p>引申:为什么java不能实现和其他语言一样的函数闭包呢?</p></blockquote><h3 id="2-方法"><a href="#2-方法" class="headerlink" title="2. 方法"></a>2. 方法</h3><p>final作用于方法有两个方面。</p><ol><li>不能在继承类中重写覆盖</li><li>内联调用</li></ol><p>内联调用是为了减少函数调用的开销(压栈、跳转、出栈等),在调用的地方直接用函数代码代替。不过当方法很大时,程序代码会膨胀,性能没有提高。</p><p>现在很多虚拟机会检测这种情况,进行优化。所以final主要是为了禁止继承类覆盖。</p><h3 id="3-类"><a href="#3-类" class="headerlink" title="3. 类"></a>3. 类</h3><p>final 类不能被继承。</p><h2 id="2-初始化和类的加载"><a href="#2-初始化和类的加载" class="headerlink" title="2. 初始化和类的加载"></a>2. 初始化和类的加载</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>{</span><br><span class="line"> {</span><br><span class="line"> System.out.println(<span class="string">"Animal: 非静态初始化"</span>);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> System.out.println(<span class="string">"Animal: 静态初始化"</span>);</span><br><span class="line"> }</span><br><span class="line"> Animal() {</span><br><span class="line"> System.out.println(<span class="string">"Animal: Constructor"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">extends</span> <span class="title">Animal</span> </span>{</span><br><span class="line"> {</span><br><span class="line"> System.out.println(<span class="string">"Dog: 非静态初始化"</span>);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> System.out.println(<span class="string">"Dog: 静态初始化"</span>);</span><br><span class="line"> }</span><br><span class="line"> Dog() {</span><br><span class="line"> System.out.println(<span class="string">"Dog: Constructor"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DogConstructor</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> <span class="keyword">new</span> Dog();</span><br><span class="line"> }</span><br><span class="line">}<span class="comment">/* output:</span></span><br><span class="line"><span class="comment">Animal: 静态初始化</span></span><br><span class="line"><span class="comment">Dog: 静态初始化</span></span><br><span class="line"><span class="comment">Animal: 非静态初始化</span></span><br><span class="line"><span class="comment">Animal: Constructor</span></span><br><span class="line"><span class="comment">Dog: 非静态初始化</span></span><br><span class="line"><span class="comment">Dog: Constructor</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><p>如上例所示,步骤如下:</p><ol><li>new Dog()触发加载Dog类时,发现继承了基类Animal,于是继续加载基类Animal</li><li>基类静态初始化,进而子类Dog静态初始化</li><li>在堆上分配内存,清空为0(默认初始化)</li><li>基类执行定义初始化和构造器</li><li>子类执行定义初始化和构造器</li></ol>]]></content>
<summary type="html">
<h2 id="1-final-关键字"><a href="#1-final-关键字" class="headerlink" title="1. final 关键字"></a>1. final 关键字</h2><p>final关键字主要的含义就是“无法改变”。final可以用于数据、方法和类。</p>
<h3 id="1-数据"><a href="#1-数据" class="headerlink" title="1. 数据"></a>1. 数据</h3><p>final作用于数据上表示数据本身不可以改变。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">final</span> <span class="keyword">int</span> a = <span class="number">10</span>;</span><br><span class="line">a = <span class="number">11</span>; <span class="comment">// 错误 </span></span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> C = <span class="number">2</span>; <span class="comment">// 编译期常量</span></span><br><span class="line"><span class="keyword">final</span> List&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;String&gt;();</span><br><span class="line">list.add(<span class="string">"a"</span>); <span class="comment">// 正确</span></span><br><span class="line">list.add(<span class="string">"b"</span>); <span class="comment">// 正确</span></span><br><span class="line">list = <span class="keyword">new</span> ArrayList&lt;String&gt;(); <span class="comment">// 错误,list不能指向其他对象</span></span><br></pre></td></tr></table></figure></p>
<p>如上,final作用于引用表示引用值本身不能变,即不能指向其他对象。</p>
<h4 id="final修饰参数"><a href="#final修饰参数" class="headerlink" title="final修饰参数"></a>final修饰参数</h4><p>在方法体的匿名内部类中,参数需要用final修饰。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">adder</span></span>&#123;<span class="function"><span class="keyword">void</span> <span class="title">addXYZ</span><span class="params">()</span></span>;&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">outer</span></span>&#123;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> adder <span class="title">getAdder</span><span class="params">(<span class="keyword">final</span> <span class="keyword">int</span> x)</span></span>&#123;</span><br><span class="line"> <span class="keyword">final</span> <span class="keyword">int</span> y = <span class="number">10</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> adder()&#123;</span><br><span class="line"> <span class="keyword">int</span> z = <span class="number">10</span>;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">addXYZ</span><span class="params">()</span></span>&#123;<span class="keyword">return</span> x + y + z;&#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想(六): 访问权限控制</title>
<link href="http://yoursite.com/2019/05/03/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3-%E5%85%AD-%E8%AE%BF%E9%97%AE%E6%9D%83%E9%99%90%E6%8E%A7%E5%88%B6/"/>
<id>http://yoursite.com/2019/05/03/java编程思想-六-访问权限控制/</id>
<published>2019-05-03T02:54:59.000Z</published>
<updated>2019-05-03T08:58:10.781Z</updated>
<content type="html"><![CDATA[<h1 id="访问权限控制"><a href="#访问权限控制" class="headerlink" title="访问权限控制"></a>访问权限控制</h1><p>访问权限控制主要是为了解决类库开发的问题,类库的代码往往需要重构,但是类库的使用者却需要代码保持不变,为此,对于类库中的代码,使用者的访问应该是受限制的,他应该只能访问部分需要公开的代码,比如所谓的API。</p><p>因此程序代码需要约定代码的访问权限。在java中,访问权限从大到小为:public, protected, 包访问权限(没有关键词), private. 其中包是库的基本单元。</p><h2 id="包-库单元"><a href="#包-库单元" class="headerlink" title="包:库单元"></a>包:库单元</h2><p>包是通过名字空间组织的一组类。</p><p>通过包可以很方便的把实现某一功能的类组织起来,在类文件(.java)中通过 <code>package package_name</code> 指定类所在的包,通过<code>import</code> 来导入。比如<code>import java.util.ArrayList</code> 导入<code>java.util</code>包下的<code>ArrayList</code>类。</p><a id="more"></a><h3 id="代码组织"><a href="#代码组织" class="headerlink" title="代码组织"></a>代码组织</h3><p>编译一个.java文件时,生成一个同名的.class文件,其中.java文件必须保证只有一个public的类和任意数量的非public类。</p><ol><li><p>通过package指定所在的包</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// access/mypackage/MyClass.java</span></span><br><span class="line"><span class="keyword">package</span> access.mypackage;</span><br><span class="line">Class MyClass{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>通过import导入</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// access/ImportedMyClass.java</span></span><br><span class="line"><span class="keyword">import</span> access.mypackage.MyClass;</span><br><span class="line">Class ImportedMyClass{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> MyClass m = <span class="keyword">new</span> MyClass();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h3 id="包命名与包查找"><a href="#包命名与包查找" class="headerlink" title="包命名与包查找"></a>包命名与包查找</h3><p>上文通过package指定了包,并通过import导入包中的类,那么import是如何找到这个类呢?</p><p>首先,需要给包一个独一无二的名字,最好的办法是通过域名, 比如<code>package com.ajm</code>。而包文件所处的路径应当与域名相同,这样才能通过包的名字查找。<code>package com.ajm</code>对应的代码目录结构是<code>{src}/com/ajm/</code> 其中<code>src</code>是包所在的系统路径。</p><p>import只是在.java文件中指明要包含的包,但是java是如何查找并导入的呢?实际上,在<code>javac</code>、<code>java</code>命令中,我们需要用<code>-CLASSPATH</code>指定包的路径。</p><p>java解释器的运行过程如下:首先找出环境变量<code>CLASSPATH</code>(通过操作系统设置), <code>CLASSPATH</code>包含了一个或多个目录,是查找.class文件的根目录;然后将.换成反斜杠,比如<code>import access.mypackage.MyClass</code>换成<code>access/mypackage/</code>, 在<code>CLASSPATH</code>中查找这个子目录,然后找出MyClass.class文件。</p><h2 id="访问权限修饰词"><a href="#访问权限修饰词" class="headerlink" title="访问权限修饰词"></a>访问权限修饰词</h2><h3 id="public"><a href="#public" class="headerlink" title="public"></a>public</h3><p>所有人都可以访问,用于提供给类库使用者的接口。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// access/dessert/Cookie.java</span></span><br><span class="line"><span class="keyword">package</span> access.dessert;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Cookie</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Cookie</span><span class="params">()</span></span>{</span><br><span class="line"> System.out.println(<span class="string">"Cookie Constructor"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">bite</span><span class="params">()</span></span>{ System.out.println(<span class="string">"bite"</span>); } <span class="comment">// 不加修饰词,默认包访问权限</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// access/Dinner.java</span></span><br><span class="line"><span class="keyword">package</span> access;</span><br><span class="line"><span class="keyword">import</span> access.dessert.*;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dinner</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> Cookie cookie = <span class="keyword">new</span> Cookie();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">/* output:</span></span><br><span class="line"><span class="comment">Cookie Constructor</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><p>如上,Cookie在包<code>access.dessert</code>中,但是在这个包之外的<code>Dinner</code>却可以访问Cookie的public构造器。</p><h3 id="包访问权限"><a href="#包访问权限" class="headerlink" title="包访问权限"></a>包访问权限</h3><p>包访问权限是默认的访问权限,不需要关键词修饰,同一个包内的各个类可以互相访问<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// access/Dinner1.java</span></span><br><span class="line"><span class="keyword">package</span> access;</span><br><span class="line"><span class="keyword">import</span> access.dessert.*;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dinner1</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> Cookie cookie = <span class="keyword">new</span> Cookie(); <span class="comment">// 可以访问</span></span><br><span class="line"> cookie.bite(); <span class="comment">// 不能访问</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// access/dessert/Dinner2.java</span></span><br><span class="line"><span class="keyword">package</span> access.dessert;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Dinner2</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> Cookie cookie = <span class="keyword">new</span> Cookie(); <span class="comment">// 可以访问</span></span><br><span class="line"> cookie.bite(); <span class="comment">// 可以访问</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h3 id="protected"><a href="#protected" class="headerlink" title="protected"></a>protected</h3><p>包可以访问,包以外的继承类可以访问。有些方法或域想要让包外的派生类可以使用,但是如果用public修饰,所有人都可以使用,为了解决这个问题,引入protected.</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//: access/ChocolateChip.java</span></span><br><span class="line"><span class="comment">// Can't use package-access member from another package.</span></span><br><span class="line"><span class="keyword">import</span> access.dessert.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ChocolateChip</span> <span class="keyword">extends</span> <span class="title">Cookie</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">ChocolateChip</span><span class="params">()</span> </span>{</span><br><span class="line"> System.out.println(<span class="string">"ChocolateChip constructor"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">chomp</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="comment">//! bite(); // Can't access bite</span></span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> ChocolateChip x = <span class="keyword">new</span> ChocolateChip();</span><br><span class="line"> x.chomp();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>例如ChocolateChip类继承自Cookie,想要使用bite()方法,但是由于在包<code>access.dessert</code>之外,无法访问。为了解决这个问题,可以将bite()方法改为protected,如下:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// access/dessert/Cookie.java</span></span><br><span class="line"><span class="keyword">package</span> access.dessert;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Cookie</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Cookie</span><span class="params">()</span></span>{</span><br><span class="line"> System.out.println(<span class="string">"Cookie Constructor"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">bite</span><span class="params">()</span></span>{ System.out.println(<span class="string">"bite"</span>); } <span class="comment">// 包内类和派生类可以访问</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h3 id="private"><a href="#private" class="headerlink" title="private"></a>private</h3><p>只有类内部可以访问</p><h3 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h3><p>class 只能是public 或 包访问权限的,因为protected, private作用在class上没有意义。因此,在一个.java文件中,希望暴露给所有人使用的类,用public; 只是用于包内的辅助类,默认包权限。</p><h2 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h2><p>访问控制的一个很好的例子是单例设计模式。有时候我们想要某个类只能生成一个对象实例。在实际应用中,有时候系统只需要拥有一个全局对象,比如服务器程序中,服务器的配置信息存放在一个文件中,可以通过一个<code>单例对象</code>读取这个文件信息,其他对象可以通过这个单例对象获取这些信息。</p><p>为了实现这个目的,显然,该类的构造器只能是私有的,否则就可以通过<code>new</code>创建对象了。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// singleton(饿汉模式:类加载时生成对象)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span></span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Singleton INSTANCE = <span class="keyword">new</span> Singleton();</span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span></span>{}</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">return</span> INSTANCE;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// singleton(懒汉模式)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span></span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Singleton INSTANCE = <span class="keyword">null</span>;</span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span></span>{}</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(INSTANCE == <span class="keyword">null</span>){</span><br><span class="line"> INSTANCE = <span class="keyword">new</span> Singleton();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> INSTANCE;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>但是,以上的单例实现不是线程安全的,getInstance方法如果被两个线程同时访问,都因为<code>INSTANCE == null</code>而创建实例,就会产生两个实例。</p>]]></content>
<summary type="html">
<h1 id="访问权限控制"><a href="#访问权限控制" class="headerlink" title="访问权限控制"></a>访问权限控制</h1><p>访问权限控制主要是为了解决类库开发的问题,类库的代码往往需要重构,但是类库的使用者却需要代码保持不变,为此,对于类库中的代码,使用者的访问应该是受限制的,他应该只能访问部分需要公开的代码,比如所谓的API。</p>
<p>因此程序代码需要约定代码的访问权限。在java中,访问权限从大到小为:public, protected, 包访问权限(没有关键词), private. 其中包是库的基本单元。</p>
<h2 id="包-库单元"><a href="#包-库单元" class="headerlink" title="包:库单元"></a>包:库单元</h2><p>包是通过名字空间组织的一组类。</p>
<p>通过包可以很方便的把实现某一功能的类组织起来,在类文件(.java)中通过 <code>package package_name</code> 指定类所在的包,通过<code>import</code> 来导入。比如<code>import java.util.ArrayList</code> 导入<code>java.util</code>包下的<code>ArrayList</code>类。</p>
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想(九): 接口</title>
<link href="http://yoursite.com/2019/04/11/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3-%E4%B9%9D-%E6%8E%A5%E5%8F%A3/"/>
<id>http://yoursite.com/2019/04/11/java编程思想-九-接口/</id>
<published>2019-04-11T14:14:43.000Z</published>
<updated>2019-05-03T15:39:03.725Z</updated>
<content type="html"><![CDATA[<h1 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h1><p><strong>接口和内部类</strong>提供了很好的接口与实现分离的方法。</p><h2 id="完全解耦"><a href="#完全解耦" class="headerlink" title="完全解耦"></a>完全解耦</h2><p>在多态中,一个方法操作的是类,那么你可以使用这个类及其子类,代码会有很好的复用性。但是对于不在这个继承结构中的某个类,就没有办法了。</p><p>而接口却可以放宽这种限制。</p><h2 id="多重继承"><a href="#多重继承" class="headerlink" title="多重继承"></a>多重继承</h2><p>多重继承实际上就是组合多个类的接口。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// B为抽象类或基类,C1,...为接口</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span> <span class="keyword">extends</span> <span class="title">B</span> <span class="keyword">implements</span> <span class="title">C1</span>, <span class="title">C2</span>, <span class="title">C3</span> ...</span></span><br></pre></td></tr></table></figure></p><p>则如上A可以向上转型为B, C1, C2 …, 因此可以很方便的复用代码</p><h2 id="适配接口"><a href="#适配接口" class="headerlink" title="适配接口"></a>适配接口</h2><p>接口最大的用处就是一个接口可以有很多不同的实现。于是如果一个方法以一个接口类型为参数,则使用者可以通过改变接口的实现方式和传入的对象,来产生不同的行为。</p><p>比如Java中的Scanner类,它的构造器接收的是一个Readable接口。如果创建了一个新的类,想让Scanner作用于它,只需实现Readable接口。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//: interfaces/RandomWords.java</span></span><br><span class="line"><span class="comment">// Implementing an interface to conform to a method.</span></span><br><span class="line"><span class="keyword">import</span> java.nio.*;</span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RandomWords</span> <span class="keyword">implements</span> <span class="title">Readable</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Random rand = <span class="keyword">new</span> Random(<span class="number">47</span>);</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">char</span>[] capitals =</span><br><span class="line"> <span class="string">"ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span>.toCharArray();</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">char</span>[] lowers =</span><br><span class="line"> <span class="string">"abcdefghijklmnopqrstuvwxyz"</span>.toCharArray();</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">char</span>[] vowels =</span><br><span class="line"> <span class="string">"aeiou"</span>.toCharArray();</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> count;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">RandomWords</span><span class="params">(<span class="keyword">int</span> count)</span> </span>{ <span class="keyword">this</span>.count = count; }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">read</span><span class="params">(CharBuffer cb)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(count-- == <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">return</span> -<span class="number">1</span>; <span class="comment">// Indicates end of input</span></span><br><span class="line"> cb.append(capitals[rand.nextInt(capitals.length)]);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="number">4</span>; i++) {</span><br><span class="line"> cb.append(vowels[rand.nextInt(vowels.length)]);</span><br><span class="line"> cb.append(lowers[rand.nextInt(lowers.length)]);</span><br><span class="line"> }</span><br><span class="line"> cb.append(<span class="string">" "</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">10</span>; <span class="comment">// Number of characters appended</span></span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> Scanner s = <span class="keyword">new</span> Scanner(<span class="keyword">new</span> RandomWords(<span class="number">10</span>));</span><br><span class="line"> <span class="keyword">while</span>(s.hasNext())</span><br><span class="line"> System.out.println(s.next());</span><br><span class="line"> }</span><br><span class="line">} <span class="comment">/* Output:</span></span><br><span class="line"><span class="comment">Yazeruyac</span></span><br><span class="line"><span class="comment">Fowenucor</span></span><br><span class="line"><span class="comment">Goeazimom</span></span><br><span class="line"><span class="comment">Raeuuacio</span></span><br><span class="line"><span class="comment">Nuoadesiw</span></span><br><span class="line"><span class="comment">Hageaikux</span></span><br><span class="line"><span class="comment">Ruqicibui</span></span><br><span class="line"><span class="comment">Numasetih</span></span><br><span class="line"><span class="comment">Kuuuuozog</span></span><br><span class="line"><span class="comment">Waqizeyoy</span></span><br><span class="line"><span class="comment">*/</span><span class="comment">//:~</span></span><br></pre></td></tr></table></figure></p><p>如果某个类没有实现Readable接口,那应该怎么办呢?只需extends,并实现Readable接口即可。其实就是一个适配器,适配Readable接口。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//: interfaces/RandomDoubles.java</span></span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RandomDoubles</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Random rand = <span class="keyword">new</span> Random(<span class="number">47</span>);</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">next</span><span class="params">()</span> </span>{ <span class="keyword">return</span> rand.nextDouble(); }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> RandomDoubles rd = <span class="keyword">new</span> RandomDoubles();</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="number">7</span>; i ++)</span><br><span class="line"> System.out.print(rd.next() + <span class="string">" "</span>);</span><br><span class="line"> }</span><br><span class="line">} <span class="comment">/* Output:</span></span><br><span class="line"><span class="comment">0.7271157860730044 0.5309454508634242 0.16020656493302599 0.18847866977771732 0.5166020801268457 0.2678662084200585 0.2613610344283964</span></span><br><span class="line"><span class="comment">*/</span><span class="comment">//:~</span></span><br></pre></td></tr></table></figure><p>为RandomDouble 适配Readable接口<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//: interfaces/AdaptedRandomDoubles.java</span></span><br><span class="line"><span class="comment">// Creating an adapter with inheritance.</span></span><br><span class="line"><span class="keyword">import</span> java.nio.*;</span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AdaptedRandomDoubles</span> <span class="keyword">extends</span> <span class="title">RandomDoubles</span></span></span><br><span class="line"><span class="class"><span class="keyword">implements</span> <span class="title">Readable</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> count;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">AdaptedRandomDoubles</span><span class="params">(<span class="keyword">int</span> count)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.count = count;</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">read</span><span class="params">(CharBuffer cb)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(count-- == <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line"> String result = Double.toString(next()) + <span class="string">" "</span>;</span><br><span class="line"> cb.append(result);</span><br><span class="line"> <span class="keyword">return</span> result.length();</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> Scanner s = <span class="keyword">new</span> Scanner(<span class="keyword">new</span> AdaptedRandomDoubles(<span class="number">7</span>));</span><br><span class="line"> <span class="keyword">while</span>(s.hasNextDouble())</span><br><span class="line"> System.out.print(s.nextDouble() + <span class="string">" "</span>);</span><br><span class="line"> }</span><br><span class="line">} <span class="comment">/* Output:</span></span><br><span class="line"><span class="comment">0.7271157860730044 0.5309454508634242 0.16020656493302599 0.18847866977771732 0.5166020801268457 0.2678662084200585 0.2613610344283964</span></span><br><span class="line"><span class="comment">*/</span><span class="comment">//:~</span></span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<h1 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h1><p><strong>接口和内部类</strong>提供了很好的接口与实现分离的方法。</p>
<h2 id="完全解耦"><a href="#完
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想(十八): Java I/O系统</title>
<link href="http://yoursite.com/2019/04/11/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3-%E5%8D%81%E5%85%AB-Java-I-O%E7%B3%BB%E7%BB%9F/"/>
<id>http://yoursite.com/2019/04/11/java编程思想-十八-Java-I-O系统/</id>
<published>2019-04-11T13:00:25.000Z</published>
<updated>2019-05-03T08:43:47.449Z</updated>
<summary type="html">
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想(八): 多态</title>
<link href="http://yoursite.com/2019/04/11/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3-%E5%85%AB-%E5%A4%9A%E6%80%81/"/>
<id>http://yoursite.com/2019/04/11/java编程思想-八-多态/</id>
<published>2019-04-11T10:13:30.000Z</published>
<updated>2019-05-03T08:57:52.602Z</updated>
<content type="html"><![CDATA[<h1 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h1><p><strong>多态的主要优点是消除类型之间的耦合关系</strong>,可以将类型之间的公共部分放到基类,则所有导出类可以看成是基类,<strong>编程只需面向基类,只需一份代码</strong>;<strong>而且增加新的导出类,代码无需更改</strong>。</p><a id="more"></a><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Shape</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span></span>{System.out.println(<span class="string">"draw Shape"</span>);}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Triangle</span> <span class="keyword">extends</span> <span class="title">Shape</span></span>{</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span></span>{System.out.println(<span class="string">"draw Triangle"</span>);}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Circle</span> <span class="keyword">extends</span> <span class="title">Shape</span></span>{</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span></span>{System.out.println(<span class="string">"draw Circle"</span>);}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DrawShape</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">drawShape</span><span class="params">(Shape shape)</span></span>{</span><br><span class="line"> shape.draw();</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> Circle circle = <span class="keyword">new</span> Circle();</span><br><span class="line"> drawShape(circle);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>如上,对于drawShape(Shape shape)方法,如果没有多态的话,需要写drawShape(Circle circle), drawShape(Triangle triangle) 等方法,且每增加一个导出类,都需要增加一个对应方法。<br>但是通过多态,可以将这些公共的部分提取出来,直接面向基类Shape编程。而且对于新的导出类,drawShape的代码不需要改变。</p><h2 id="动态绑定"><a href="#动态绑定" class="headerlink" title="动态绑定"></a>动态绑定</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">drawShape</span><span class="params">(Shape shape)</span></span>{</span><br><span class="line"> shape.draw();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>上面的代码中,编译器是不知道shape引用是指向Circle对象还是Triangle对象的。所以编译器不知道要调用哪个方法。</p><p>解决这个问题的方法是<strong>动态绑定</strong>。因为要知道调用哪个方法,必须要区分Circle,Triangle等对象,所以需要在对象中存储某种<strong>类型信息</strong>。动态绑定的机制就是在运行时根据<strong>对象的类型</strong>绑定相应的方法。</p><p>java中除了static、final的方法之外,其他方法默认都是后期绑定的,所以要关闭动态绑定,只需将某个声明为final。</p><h2 id="构造器"><a href="#构造器" class="headerlink" title="构造器"></a>构造器</h2><p>因为导出类由基类派生,所以要构造导出类,首先需要构造基类。<br>导出类的构造器调用之前,需要先调用基类的构造器,如果导出类没有通过super()显式调用,则会调用基类默认构造器,如果不存在,则会报错。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Meal</span></span>{</span><br><span class="line"><span class="comment">// Meal(){System.out.println("Meal()");}</span></span><br><span class="line"> Meal(String str){ System.out.println(<span class="string">"Meal(String str)"</span>);}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Sandwich</span> <span class="keyword">extends</span> <span class="title">Meal</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Sandwich</span><span class="params">()</span></span>{</span><br><span class="line"><span class="comment">// super("haha");</span></span><br><span class="line"> System.out.println(<span class="string">"Sanwich()"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> Sandwich sandwich = <span class="keyword">new</span> Sandwich();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 代码运行报错,因为Sandwich中没有显式调用Meal的构造器,而且Meal中由于有了Meal(String str)构造器,编译器无法自动合成默认构造器。</span></span><br></pre></td></tr></table></figure><p>可以加入<code>super("haha")</code>显式调用基类的构造器。</p><h3 id="构造器调用顺序"><a href="#构造器调用顺序" class="headerlink" title="构造器调用顺序"></a>构造器调用顺序</h3><p>要构造出导出类对象,首先得构造出基类对象。</p><ol><li>将分配给对象的存储空间初始化为二进制0</li><li>先调用基类构造器</li><li>按声明顺序调用成员初始化方法</li><li>调用导出类构造器实体<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Meal</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> Bread bread = <span class="keyword">new</span> Bread();</span><br><span class="line"> Meal() { System.out.println(<span class="string">"Meal()"</span>); }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Bread</span> </span>{</span><br><span class="line"> Bread() { System.out.println(<span class="string">"Bread()"</span>); }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cheese</span> </span>{</span><br><span class="line"> Cheese() { System.out.println(<span class="string">"Cheese()"</span>); }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Lettuce</span> </span>{</span><br><span class="line"> Lettuce() { System.out.println(<span class="string">"Lettuce()"</span>); }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Lunch</span> <span class="keyword">extends</span> <span class="title">Meal</span> </span>{</span><br><span class="line"> Lunch() { System.out.println(<span class="string">"Lunch()"</span>); }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">PortableLunch</span> <span class="keyword">extends</span> <span class="title">Lunch</span> </span>{</span><br><span class="line"> PortableLunch() { System.out.println(<span class="string">"PortableLunch()"</span>);}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Sandwich</span> <span class="keyword">extends</span> <span class="title">PortableLunch</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> Bread b = <span class="keyword">new</span> Bread();</span><br><span class="line"> <span class="keyword">private</span> Cheese c = <span class="keyword">new</span> Cheese();</span><br><span class="line"> <span class="keyword">private</span> Lettuce l = <span class="keyword">new</span> Lettuce();</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Sandwich</span><span class="params">()</span> </span>{ System.out.println(<span class="string">"Sandwich()"</span>); }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> <span class="keyword">new</span> Sandwich();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/*output: </span></span><br><span class="line"><span class="comment">Bread()</span></span><br><span class="line"><span class="comment">Meal()</span></span><br><span class="line"><span class="comment">Lunch()</span></span><br><span class="line"><span class="comment">PortableLunch()</span></span><br><span class="line"><span class="comment">Bread()</span></span><br><span class="line"><span class="comment">Cheese()</span></span><br><span class="line"><span class="comment">Lettuce()</span></span><br><span class="line"><span class="comment">Sandwich()</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure></li></ol><h3 id="构造器内调用多态方法"><a href="#构造器内调用多态方法" class="headerlink" title="构造器内调用多态方法"></a>构造器内调用多态方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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"><span class="keyword">import</span> <span class="keyword">static</span> net.mindview.util.Print.*;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Glyph</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span> </span>{ print(<span class="string">"Glyph.draw()"</span>); }</span><br><span class="line"> Glyph() {</span><br><span class="line"> print(<span class="string">"Glyph() before draw()"</span>);</span><br><span class="line"> draw();</span><br><span class="line"> print(<span class="string">"Glyph() after draw()"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RoundGlyph</span> <span class="keyword">extends</span> <span class="title">Glyph</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> radius = <span class="number">1</span>;</span><br><span class="line"> RoundGlyph(<span class="keyword">int</span> r) {</span><br><span class="line"> radius = r;</span><br><span class="line"> print(<span class="string">"RoundGlyph.RoundGlyph(), radius = "</span> + radius);</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span> </span>{</span><br><span class="line"> print(<span class="string">"RoundGlyph.draw(), radius = "</span> + radius);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">PolyConstructors</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> <span class="keyword">new</span> RoundGlyph(<span class="number">5</span>);</span><br><span class="line"> }</span><br><span class="line">} <span class="comment">/* Output:</span></span><br><span class="line"><span class="comment">Glyph() before draw()</span></span><br><span class="line"><span class="comment">RoundGlyph.draw(), radius = 0</span></span><br><span class="line"><span class="comment">Glyph() after draw()</span></span><br><span class="line"><span class="comment">RoundGlyph.RoundGlyph(), radius = 5</span></span><br><span class="line"><span class="comment">*/</span><span class="comment">//:~</span></span><br></pre></td></tr></table></figure><p>上面的代码中先调用了基类构造器Glyph()时,draw()由于动态绑定,会调用RoundGlyph中的draw方法,而此时radius尚未初始化,只是在一开始存储空间初始化为0。</p><p>所以在构造器中,最好不要调用非final的方法。</p><h2 id="向下转型"><a href="#向下转型" class="headerlink" title="向下转型"></a>向下转型</h2><p>向上转型时安全的,因为导出类有基类的所有接口。但是向下转型却未必正确。所以在Java语言中,所有转型都会得到检查,由于类型信息存在运行时的对象中,可以进行<strong>RTTI(运行时类型识别)</strong>,检查向下转型是否正确,错误则抛出ClassCastException。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Useful</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">f</span><span class="params">()</span> </span>{}</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">g</span><span class="params">()</span> </span>{}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MoreUseful</span> <span class="keyword">extends</span> <span class="title">Useful</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">f</span><span class="params">()</span> </span>{}</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">g</span><span class="params">()</span> </span>{}</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">u</span><span class="params">()</span> </span>{}</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">v</span><span class="params">()</span> </span>{}</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">w</span><span class="params">()</span> </span>{}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RTTI</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> Useful[] x = {</span><br><span class="line"> <span class="keyword">new</span> Useful(),</span><br><span class="line"> <span class="keyword">new</span> MoreUseful()</span><br><span class="line"> };</span><br><span class="line"> x[<span class="number">0</span>].f();</span><br><span class="line"> x[<span class="number">1</span>].g();</span><br><span class="line"> <span class="comment">// Compile time: method not found in Useful:</span></span><br><span class="line"> <span class="comment">//! x[1].u();</span></span><br><span class="line"> ((MoreUseful)x[<span class="number">1</span>]).u(); <span class="comment">// Downcast/RTTI</span></span><br><span class="line"> ((MoreUseful)x[<span class="number">0</span>]).u(); <span class="comment">// Exception thrown</span></span><br><span class="line"> }</span><br><span class="line">} <span class="comment">///:~</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// ouput: java.lang.ClassCastException: class Useful cannot be cast to class MoreUseful</span></span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<h1 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h1><p><strong>多态的主要优点是消除类型之间的耦合关系</strong>,可以将类型之间的公共部分放到基类,则所有导出类可以看成是基类,<strong>编程只需面向基类,只需一份代码</strong>;<strong>而且增加新的导出类,代码无需更改</strong>。</p>
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想笔记(五): 初始化与清理</title>
<link href="http://yoursite.com/2019/03/23/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E7%AC%94%E8%AE%B0-%E4%BA%94-%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%8E%E6%B8%85%E7%90%86/"/>
<id>http://yoursite.com/2019/03/23/java编程思想笔记-五-初始化与清理/</id>
<published>2019-03-23T11:44:47.000Z</published>
<updated>2019-05-03T08:57:36.234Z</updated>
<content type="html"><![CDATA[<h1 id="成员初始化"><a href="#成员初始化" class="headerlink" title="成员初始化"></a>成员初始化</h1><h2 id="默认、指定初始化"><a href="#默认、指定初始化" class="headerlink" title="默认、指定初始化"></a>默认、指定初始化</h2><p>类的成员如果没有指定会默认初始化,基本类型初始化为默认值,引用初始化为<code>null</code>。也可以通过定义显示初始化。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">InitialValues</span> </span>{</span><br><span class="line"> <span class="keyword">boolean</span> bool = <span class="keyword">true</span>;</span><br><span class="line"> <span class="keyword">boolean</span> bool1; <span class="comment">// 默认为 false</span></span><br><span class="line"> <span class="keyword">char</span> ch = <span class="string">'x'</span>;</span><br><span class="line"> <span class="keyword">char</span> ch1; <span class="comment">// 默认初始化为 空</span></span><br><span class="line"> <span class="keyword">byte</span> b = <span class="number">47</span>;</span><br><span class="line"> <span class="keyword">short</span> s = <span class="number">0xff</span>;</span><br><span class="line"> <span class="keyword">int</span> i = <span class="number">999</span>;</span><br><span class="line"> <span class="keyword">long</span> lng = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">float</span> f = <span class="number">3.14f</span>;</span><br><span class="line"> <span class="keyword">double</span> d = <span class="number">3.14159</span>;</span><br><span class="line"> String a; <span class="comment">// 默认初始化为null</span></span><br><span class="line">} <span class="comment">///:~</span></span><br></pre></td></tr></table></figure></p><a id="more"></a><h2 id="初始化块"><a href="#初始化块" class="headerlink" title="初始化块"></a>初始化块</h2><p>可以通过{}初始化块初始化。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Initial</span></span>{</span><br><span class="line"> <span class="keyword">int</span> a = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">double</span> b;</span><br><span class="line"> Initial(){}</span><br><span class="line"> {</span><br><span class="line"> System.out.println(<span class="string">"执行初始化块"</span>);</span><br><span class="line"> a = <span class="number">2</span>;</span><br><span class="line"> b = <span class="number">3.5</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> Initial v = <span class="keyword">new</span> Initial();</span><br><span class="line"> System.out.println(<span class="string">"a: "</span> + a);</span><br><span class="line"> }</span><br><span class="line">}<span class="comment">/* output:</span></span><br><span class="line"><span class="comment">执行初始化块</span></span><br><span class="line"><span class="comment">a: 2</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure></p><h2 id="静态数据初始化"><a href="#静态数据初始化" class="headerlink" title="静态数据初始化"></a>静态数据初始化</h2><p>静态数据的初始化与非静态数据类似,static初始化块需要用static修饰。下面是一个例子:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">InitialValues3</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> a = <span class="number">3</span>;</span><br><span class="line"> <span class="keyword">double</span> b;</span><br><span class="line"> InitialValues3(){</span><br><span class="line"> System.out.println(<span class="string">"InitialValues3() 构造器"</span>);</span><br><span class="line"> }</span><br><span class="line"> {</span><br><span class="line"> System.out.println(<span class="string">"执行非静态初始化块"</span>);</span><br><span class="line"> a = <span class="number">1</span>;</span><br><span class="line"> b = <span class="number">3.5</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> System.out.println(<span class="string">"执行静态初始化块"</span>);</span><br><span class="line"> c = <span class="number">100</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">static</span> <span class="keyword">int</span> c = <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> System.out.println(<span class="string">"c: "</span> + InitialValues3.c);</span><br><span class="line"> InitialValues3 v1 = <span class="keyword">new</span> InitialValues3();</span><br><span class="line"> System.out.println(<span class="string">"a: "</span> + v1.a);</span><br><span class="line"> InitialValues3 v2 = <span class="keyword">new</span> InitialValues3();</span><br><span class="line"> System.out.println(<span class="string">"a: "</span> + v2.a);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}<span class="comment">/*output: </span></span><br><span class="line"><span class="comment">执行静态初始化块</span></span><br><span class="line"><span class="comment">c: 100</span></span><br><span class="line"><span class="comment">执行非静态初始化块</span></span><br><span class="line"><span class="comment">InitialValues3() 构造器</span></span><br><span class="line"><span class="comment">a: 1</span></span><br><span class="line"><span class="comment">执行非静态初始化块</span></span><br><span class="line"><span class="comment">InitialValues3() 构造器</span></span><br><span class="line"><span class="comment">a: 1</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure></p><p>在通过InitialValues3.c 访问静态变量c时,会先初始化c,此时并没有创建InitialValues3的对象实例。静态变量初始化一次后,不需要再调用。</p><h1 id="构造器初始化"><a href="#构造器初始化" class="headerlink" title="构造器初始化"></a>构造器初始化</h1><p>构造器初始化在成员初始化之后。</p><h1 id="对象创建过程"><a href="#对象创建过程" class="headerlink" title="对象创建过程"></a>对象创建过程</h1><p>综上,假设有一个Dog类,对象创建的过程如下:</p><ol><li>构造器实际上是静态方法,当首次创建Dog对象,或者Dog类的静态方法、域首次访问时,java解释器会查找类路径,定位Dog.class文件。</li><li>加载Dog.class文件(创建Class对象), 将Dog类的静态域初始化(静态存储区中),所以静态初始化只在类加载时初始化一次。</li><li>用new Dog()创建对象时,根据类内域的声明首先在堆上分配足够的存储空间。</li><li>将存储区域清零。</li><li>按顺序执行各种定义处的初始化。</li><li>执行构造器</li></ol>]]></content>
<summary type="html">
<h1 id="成员初始化"><a href="#成员初始化" class="headerlink" title="成员初始化"></a>成员初始化</h1><h2 id="默认、指定初始化"><a href="#默认、指定初始化" class="headerlink" title="默认、指定初始化"></a>默认、指定初始化</h2><p>类的成员如果没有指定会默认初始化,基本类型初始化为默认值,引用初始化为<code>null</code>。也可以通过定义显示初始化。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">InitialValues</span> </span>&#123;</span><br><span class="line"> <span class="keyword">boolean</span> bool = <span class="keyword">true</span>;</span><br><span class="line"> <span class="keyword">boolean</span> bool1; <span class="comment">// 默认为 false</span></span><br><span class="line"> <span class="keyword">char</span> ch = <span class="string">'x'</span>;</span><br><span class="line"> <span class="keyword">char</span> ch1; <span class="comment">// 默认初始化为 空</span></span><br><span class="line"> <span class="keyword">byte</span> b = <span class="number">47</span>;</span><br><span class="line"> <span class="keyword">short</span> s = <span class="number">0xff</span>;</span><br><span class="line"> <span class="keyword">int</span> i = <span class="number">999</span>;</span><br><span class="line"> <span class="keyword">long</span> lng = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">float</span> f = <span class="number">3.14f</span>;</span><br><span class="line"> <span class="keyword">double</span> d = <span class="number">3.14159</span>;</span><br><span class="line"> String a; <span class="comment">// 默认初始化为null</span></span><br><span class="line">&#125; <span class="comment">///:~</span></span><br></pre></td></tr></table></figure></p>
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想笔记(二)、(三):对象和操作符</title>
<link href="http://yoursite.com/2019/03/07/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E7%AC%94%E8%AE%B0-%E4%BA%8C-%EF%BC%9A%E4%B8%80%E5%88%87%E9%83%BD%E6%98%AF%E5%AF%B9%E8%B1%A1/"/>
<id>http://yoursite.com/2019/03/07/java编程思想笔记-二-:一切都是对象/</id>
<published>2019-03-07T13:10:29.000Z</published>
<updated>2019-05-03T08:57:30.496Z</updated>
<content type="html"><![CDATA[<h1 id="一切都是对象"><a href="#一切都是对象" class="headerlink" title="一切都是对象"></a>一切都是对象</h1><h2 id="通过引用操作对象"><a href="#通过引用操作对象" class="headerlink" title="通过引用操作对象"></a>通过引用操作对象</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">"abc"</span>;</span><br></pre></td></tr></table></figure><p>对象”abc”在堆中,s是对其的一个引用。</p><h2 id="new创造对象"><a href="#new创造对象" class="headerlink" title="new创造对象"></a>new创造对象</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ArrayList<Integer> list = <span class="keyword">new</span> ArrayList<Integer>();</span><br></pre></td></tr></table></figure><a id="more"></a><h2 id="基本数据类型-primitive-type"><a href="#基本数据类型-primitive-type" class="headerlink" title="基本数据类型(primitive type)"></a>基本数据类型(primitive type)</h2><p>由于基本数据类型经常用到,如果将其变为类,通过new 在堆上分配的话,开销太大,所以java将基本数据类型在栈上分配。且与c/c++不同,这些类型的大小固定。<br><img src="../images/java2_1.png" alt=""></p><h2 id="不需要销毁对象"><a href="#不需要销毁对象" class="headerlink" title="不需要销毁对象"></a>不需要销毁对象</h2><h3 id="对象作用域"><a href="#对象作用域" class="headerlink" title="对象作用域"></a>对象作用域</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> String s = <span class="string">"abc"</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在上面的语句中,引用s的作用域在{}之间,而对象”abc”在堆上分配,在{}之外仍然存在,知道被垃圾回收器回收之前,一直存在。</p><p>所以与c++不同,java中new 出的对象不需要自己手动释放,垃圾回收器(garbage collector)会通过引用计数等方法自动判断某个对象不再被使用,释放内存。</p><h2 id="类成员变量默认值"><a href="#类成员变量默认值" class="headerlink" title="类成员变量默认值"></a>类成员变量默认值</h2><p>类内的基本类型成员变量,会默认初始化。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">A</span></span>{</span><br><span class="line"> <span class="keyword">int</span> x;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">f</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">int</span> y;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>上段代码中,x会被默认初始化为0,而y的值和c/c++中相同,可能是任意值,但是java会在编译期报错,c/c++会警告。<br><img src="../images/java2_2.png" alt=""></p><h1 id="操作符"><a href="#操作符" class="headerlink" title="操作符"></a>操作符</h1><h2 id="equals"><a href="#equals" class="headerlink" title="== equals"></a>== equals</h2><p>对于对象来说, == 是判断两个对象的引用是否相同。<br>如:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>{</span><br><span class="line"> Integer n1 = <span class="keyword">new</span> Integer(<span class="number">1</span>);</span><br><span class="line"> Integer n2 = <span class="keyword">new</span> Integer(<span class="number">2</span>);</span><br><span class="line"> System.out.println(n1 == n2);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>上段代码输出为<code>false</code>,为了实现自己的对象比较,需要用equals方法,默认的equals是比较引用,需要进行覆盖。</p><h2 id="java没有sizeof"><a href="#java没有sizeof" class="headerlink" title="java没有sizeof"></a>java没有sizeof</h2><p>c/c++中的sizeof主要是为了方便移植,因为同一个类型在不同的机器上占用的字节大小不同。但是java的基本数据类型是固定大小的。</p>]]></content>
<summary type="html">
<h1 id="一切都是对象"><a href="#一切都是对象" class="headerlink" title="一切都是对象"></a>一切都是对象</h1><h2 id="通过引用操作对象"><a href="#通过引用操作对象" class="headerlink" title="通过引用操作对象"></a>通过引用操作对象</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String s = <span class="string">"abc"</span>;</span><br></pre></td></tr></table></figure>
<p>对象”abc”在堆中,s是对其的一个引用。</p>
<h2 id="new创造对象"><a href="#new创造对象" class="headerlink" title="new创造对象"></a>new创造对象</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ArrayList&lt;Integer&gt; list = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br></pre></td></tr></table></figure>
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>java编程思想笔记(一):对象导论</title>
<link href="http://yoursite.com/2019/03/07/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E7%AC%94%E8%AE%B0(%E4%B8%80)%EF%BC%9A%E5%AF%B9%E8%B1%A1%E5%AF%BC%E8%AE%BA/"/>
<id>http://yoursite.com/2019/03/07/java编程思想笔记(一):对象导论/</id>
<published>2019-03-07T10:10:47.000Z</published>
<updated>2019-05-03T08:49:36.170Z</updated>
<content type="html"><![CDATA[<h1 id="面向对象"><a href="#面向对象" class="headerlink" title="面向对象"></a>面向对象</h1><p>早期的程序语言与计算机底层结构有着紧密的联系,所以寻求一个真实问题的解决方法需要映射到计算机底层的操作指令。而面向对象的语言,解决一个问题对应的解空间是<strong>对象</strong>。</p><p>面向对象程序设计方式的5个特性:</p><ul><li>万物皆为对象</li><li>程序是对象的集合,对象之间通过发送消息来告诉彼此所要做的,发送消息其实就是调用对象的一个方法</li><li>对象有自己的存储空间,由其他对象组成</li><li>每个对象都有相应的类型,即每个对象都是一个类型(class)的实例(instance)</li><li>某一特定类型的对象可以接收相同的消息</li></ul><p>对象:状态(数据) + 行为(方法) + 标识<br>类:具有相同属性和行为的对象集合<br><a id="more"></a></p><h2 id="对象提供接口,可以隐藏具体实现"><a href="#对象提供接口,可以隐藏具体实现" class="headerlink" title="对象提供接口,可以隐藏具体实现"></a>对象提供接口,可以隐藏具体实现</h2><p><img src="../images/java1.png" alt=""></p><h2 id="对象可以由其他对象组合(has-a"><a href="#对象可以由其他对象组合(has-a" class="headerlink" title="对象可以由其他对象组合(has-a)"></a>对象可以由其他对象组合(has-a)</h2><p><img src="../images/java2.png" alt=""></p><h2 id="子类可以继承父类,并且可以新增方法或覆盖方法(is-a"><a href="#子类可以继承父类,并且可以新增方法或覆盖方法(is-a" class="headerlink" title="子类可以继承父类,并且可以新增方法或覆盖方法(is-a)"></a>子类可以继承父类,并且可以新增方法或覆盖方法(is-a)</h2><p><img src="../images/java3.png" alt=""></p><h2 id="多态和向上转型"><a href="#多态和向上转型" class="headerlink" title="多态和向上转型"></a>多态和向上转型</h2><p>由于继承的特性,可以把派生类的对象看成是泛化的基类对象,在运行时根据对象的不同类型选择不同的代码执行,这就是多态性。</p><p>对于非面向对象编程的编译器,产生的函数调用会引起<strong>前期绑定</strong>,就是一个函数名会绑定到一个代码的绝对地址。而对于面向对象,会有<strong>动态绑定</strong>,编译器确保调用方法存在,被调用的代码在运行时确定。</p><p>在java中,会有一段代码通过对象中保存的信息计算实际代码的地址。<br><img src="../images/java4.png" alt=""><br><img src="../images/java5.png" alt=""></p><h2 id="单根继承结构"><a href="#单根继承结构" class="headerlink" title="单根继承结构"></a>单根继承结构</h2><p>java 中所有类都继承自单一的基类<a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html" target="_blank" rel="noopener">Object</a>,这样可以方便参数传递,垃圾回收和异常处理(有确定的类型信息)等</p><h2 id="参数化类型"><a href="#参数化类型" class="headerlink" title="参数化类型"></a>参数化类型</h2><p>在Java SE5之前,容器存储的对象都是Object类型,于是将对象放入容器需要向上转型,而取出时需要向下转型,但是向下转型不一定是安全的,可能会产生运行时异常,比如如下代码:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Dog d = <span class="keyword">new</span> Dog();</span><br><span class="line">Animal a = d;</span><br><span class="line">Pig p = a;</span><br></pre></td></tr></table></figure></p><p>于是,为了解决这个问题,有了<strong>参数化类型机制</strong>。如以下代码:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ArrayList<Integer> L = <span class="keyword">new</span> ArrayList<Integer>();</span><br></pre></td></tr></table></figure></p><h2 id="对象生命周期"><a href="#对象生命周期" class="headerlink" title="对象生命周期"></a>对象生命周期</h2><p>java中,对象都在堆上创建,当对象不再使用时,通过垃圾回收器自动释放内存。</p>]]></content>
<summary type="html">
<h1 id="面向对象"><a href="#面向对象" class="headerlink" title="面向对象"></a>面向对象</h1><p>早期的程序语言与计算机底层结构有着紧密的联系,所以寻求一个真实问题的解决方法需要映射到计算机底层的操作指令。而面向对象的语言,解决一个问题对应的解空间是<strong>对象</strong>。</p>
<p>面向对象程序设计方式的5个特性:</p>
<ul>
<li>万物皆为对象</li>
<li>程序是对象的集合,对象之间通过发送消息来告诉彼此所要做的,发送消息其实就是调用对象的一个方法</li>
<li>对象有自己的存储空间,由其他对象组成</li>
<li>每个对象都有相应的类型,即每个对象都是一个类型(class)的实例(instance)</li>
<li>某一特定类型的对象可以接收相同的消息</li>
</ul>
<p>对象:状态(数据) + 行为(方法) + 标识<br>类:具有相同属性和行为的对象集合<br>
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java编程思想" scheme="http://yoursite.com/tags/java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3/"/>
</entry>
<entry>
<title>vscode java 配置</title>
<link href="http://yoursite.com/2018/12/28/vscode-java-%E9%85%8D%E7%BD%AE/"/>
<id>http://yoursite.com/2018/12/28/vscode-java-配置/</id>
<published>2018-12-28T12:07:37.000Z</published>
<updated>2018-12-30T18:01:09.245Z</updated>
<content type="html"><![CDATA[<blockquote><p><a href="https://code.visualstudio.com/docs/languages/java" target="_blank" rel="noopener">java in vscode</a></p></blockquote><h2 id="插件安装"><a href="#插件安装" class="headerlink" title="插件安装"></a>插件安装</h2><p>安装 <strong>Java Extension Pack</strong> 插件,会自动安装以下四个插件:</p><ul><li>Language Support for Java(TM) by Red Hat</li><li>Debugger for Java</li><li>Java Test Runner</li><li>Maven for Java<br>在vscode中可以通过以上插件配置java编程环境。但是如果不用maven、gradle等项目构建工具,后两个插件是无法使用的,而且对于简单的仅有.java文件的项目结构,就我找遍各种资料,也没有找到导入jar包的方法,自动识别文件内容有时也会出错。<h2 id="配置jdk路径"><a href="#配置jdk路径" class="headerlink" title="配置jdk路径"></a>配置jdk路径</h2>打开settings.json,在用户设置中添加 <code>"java.home": "D:\\Program Files\\Java\\jdk-11.0.1"</code>,<a id="more"></a><h2 id="run-and-debug"><a href="#run-and-debug" class="headerlink" title="run and debug"></a>run and debug</h2></li></ul><ol><li>找不到依赖文件<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><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><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">NBody</span></span>{</span><br><span class="line"> <span class="comment">/** return the radius of the universe in file */</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">double</span> <span class="title">readRadius</span><span class="params">(String filename)</span></span>{</span><br><span class="line"> <span class="keyword">double</span> radius=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">try</span>{</span><br><span class="line"> In in = <span class="keyword">new</span> In(filename);</span><br><span class="line"> in.readInt();</span><br><span class="line"> radius = in.readDouble();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span>(Exception e){</span><br><span class="line"> System.out.println(e);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// System.out.println("Read file " + filename + " successful!");</span></span><br><span class="line"> <span class="keyword">return</span> radius; </span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/** return an array of planets from file */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Planet[] readPlanets(String filename){</span><br><span class="line"> Planet[] planets = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">try</span>{</span><br><span class="line"> In in = <span class="keyword">new</span> In(filename);</span><br><span class="line"> <span class="keyword">int</span> N = in.readInt();</span><br><span class="line"> in.readDouble();</span><br><span class="line"> <span class="comment">/** construct planets array */</span></span><br><span class="line"> planets = <span class="keyword">new</span> Planet[N];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<N;i++){</span><br><span class="line"></span><br><span class="line"> <span class="keyword">double</span> xP = in.readDouble();</span><br><span class="line"> <span class="keyword">double</span> yP = in.readDouble();</span><br><span class="line"> <span class="keyword">double</span> xV = in.readDouble();</span><br><span class="line"> <span class="keyword">double</span> yV = in.readDouble();</span><br><span class="line"> <span class="keyword">double</span> m = in.readDouble();</span><br><span class="line"> String img = in.readString();</span><br><span class="line"> planets[i] = <span class="keyword">new</span> Planet(xP, yP, xV, yV, m, img);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(<span class="string">"Read file "</span> + filename + <span class="string">" successful!"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span>(Exception e){System.out.println(e);}</span><br><span class="line"> System.out.println();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> planets;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> <span class="keyword">double</span> T = Double.parseDouble(args[<span class="number">0</span>]);</span><br><span class="line"> <span class="keyword">double</span> dt = Double.parseDouble(args[<span class="number">1</span>]);</span><br><span class="line"> String filename = args[<span class="number">2</span>];</span><br><span class="line"> <span class="keyword">double</span> radius = readRadius(filename);</span><br><span class="line"> Planet[] planets = readPlanets(filename);</span><br><span class="line"> StdAudio.play(<span class="string">"./audio/2001.mid"</span>);</span><br><span class="line"></span><br><span class="line"> StdDraw.setScale(-radius,radius);</span><br><span class="line"> StdDraw.enableDoubleBuffering();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">double</span> time = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(time < T){</span><br><span class="line"> <span class="keyword">double</span>[] xForces = <span class="keyword">new</span> <span class="keyword">double</span>[planets.length];</span><br><span class="line"> <span class="keyword">double</span>[] yForces = <span class="keyword">new</span> <span class="keyword">double</span>[planets.length];</span><br><span class="line"> <span class="comment">/** save the forces to xForces and yFroces arrays */</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<planets.length;i++){</span><br><span class="line"> xForces[i] = planets[i].calcNetForceExertedByX(planets);</span><br><span class="line"> yForces[i] = planets[i].calcNetForceExertedByY(planets);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/** update all planets */</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<planets.length;i++){</span><br><span class="line"> planets[i].update(dt, xForces[i], yForces[i]);</span><br><span class="line"> }</span><br><span class="line"> StdDraw.clear();</span><br><span class="line"> <span class="comment">/** draw image background */</span></span><br><span class="line"> StdDraw.picture(<span class="number">0</span>, <span class="number">0</span>, <span class="string">"./images/starfield.jpg"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/** draw all the planets */</span></span><br><span class="line"> <span class="keyword">for</span>(Planet p : planets){</span><br><span class="line"> p.draw();</span><br><span class="line"> }</span><br><span class="line"> StdDraw.show();</span><br><span class="line"> StdDraw.pause(<span class="number">10</span>);</span><br><span class="line"> time += dt;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> StdOut.printf(<span class="string">"%d\n"</span>, planets.length);</span><br><span class="line"> StdOut.printf(<span class="string">"%.2e\n"</span>, radius);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < planets.length; i++) {</span><br><span class="line"> StdOut.printf(<span class="string">"%11.4e %11.4e %11.4e %11.4e %11.4e %12s\n"</span>,</span><br><span class="line"> planets[i].xxPos, planets[i].yyPos, planets[i].xxVel,</span><br><span class="line"> planets[i].yyVel, planets[i].mass, planets[i].imgFileName); </span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><p>上面的java程序依赖<code>In, Planet, StdAudio,StdDraw,StdOut</code> 而进行Run/Debug时会报错,找不到<code>In,StdAudio</code>等,但是把对应java文件双击打开后,运行正常。</p><ol start="2"><li>需要命令行参数,则配置launch.json中的”args”<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"configurations"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">"type"</span>: <span class="string">"java"</span>,</span><br><span class="line"> <span class="attr">"name"</span>: <span class="string">"CodeLens (Launch) - NBody"</span>,</span><br><span class="line"> <span class="attr">"request"</span>: <span class="string">"launch"</span>,</span><br><span class="line"> <span class="attr">"mainClass"</span>: <span class="string">"NBody"</span>,</span><br><span class="line"> <span class="attr">"args"</span>: <span class="string">"157788000.0 25000.0 data/planets.txt"</span></span><br><span class="line"> }</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h2 id="library-path"><a href="#library-path" class="headerlink" title="library path"></a>library path</h2><p>不用maven什么的话,现在没有办法加载库,通过calssPath也不行。</p>]]></content>
<summary type="html">
<blockquote>
<p><a href="https://code.visualstudio.com/docs/languages/java" target="_blank" rel="noopener">java in vscode</a></p>
</blockquote>
<h2 id="插件安装"><a href="#插件安装" class="headerlink" title="插件安装"></a>插件安装</h2><p>安装 <strong>Java Extension Pack</strong> 插件,会自动安装以下四个插件:</p>
<ul>
<li>Language Support for Java(TM) by Red Hat</li>
<li>Debugger for Java</li>
<li>Java Test Runner</li>
<li>Maven for Java<br>在vscode中可以通过以上插件配置java编程环境。但是如果不用maven、gradle等项目构建工具,后两个插件是无法使用的,而且对于简单的仅有.java文件的项目结构,就我找遍各种资料,也没有找到导入jar包的方法,自动识别文件内容有时也会出错。<h2 id="配置jdk路径"><a href="#配置jdk路径" class="headerlink" title="配置jdk路径"></a>配置jdk路径</h2>打开settings.json,在用户设置中添加 <code>&quot;java.home&quot;: &quot;D:\\Program Files\\Java\\jdk-11.0.1&quot;</code>,
</summary>
<category term="vscode" scheme="http://yoursite.com/categories/vscode/"/>
<category term="java" scheme="http://yoursite.com/tags/java/"/>
<category term="vscode" scheme="http://yoursite.com/tags/vscode/"/>
</entry>
<entry>
<title>JDK and JRE, java.lang.UnsupportedClassVersionError</title>
<link href="http://yoursite.com/2018/12/21/JDK-and-JRE/"/>
<id>http://yoursite.com/2018/12/21/JDK-and-JRE/</id>
<published>2018-12-21T02:37:20.000Z</published>
<updated>2018-12-22T19:12:14.588Z</updated>
<content type="html"><![CDATA[<p>今天我下载了jdk 11.0.1,一番配置后,运行简单的程序时时出现了<code>java.lang.UnsupportedClassVersionError</code>的错误,错误信息如下:</p><h3 id="错误信息"><a href="#错误信息" class="headerlink" title="错误信息"></a>错误信息</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">ajm@DESKTOP-R8SS06A MINGW64 /d/学习/cs61b</span><br><span class="line">$ java HelloWorld</span><br><span class="line">Error: A JNI error has occurred, please check your installation and try again</span><br><span class="line">Exception in thread "main" java.lang.UnsupportedClassVersionError: HelloWorld has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0</span><br><span class="line"> at java.lang.ClassLoader.defineClass1(Native Method)</span><br><span class="line"> at java.lang.ClassLoader.defineClass(Unknown Source)</span><br><span class="line"> at java.security.SecureClassLoader.defineClass(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader.defineClass(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader.access$100(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader$1.run(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader$1.run(Unknown Source)</span><br><span class="line"> at java.security.AccessController.doPrivileged(Native Method)</span><br><span class="line"> at java.net.URLClassLoader.findClass(Unknown Source)</span><br><span class="line"> at java.lang.ClassLoader.loadClass(Unknown Source)</span><br><span class="line"> at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)</span><br><span class="line"> at java.lang.ClassLoader.loadClass(Unknown Source)</span><br><span class="line"> at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)</span><br></pre></td></tr></table></figure><a id="more"></a><h3 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h3><p>由错误信息可以知道,是由于高版本的JDK(Java Development Kit),编译产生的.class文件在低版本的JRE(Java Runtime Environment) 无法运行而报错。JDK是用于java程序开发的工具包,包含javac编译器、jar打包工具等。JRE是能够让计算机运行java程序的软件包,比如java HelloWorld,执行HelloWorld程序。</p><h4 id="查看JDK-JRE版本"><a href="#查看JDK-JRE版本" class="headerlink" title="查看JDK,JRE版本"></a>查看JDK,JRE版本</h4><figure class="highlight bash"><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">ajm@DESKTOP-R8SS06A MINGW64 /d/学习/cs61b</span><br><span class="line">$ java -version</span><br><span class="line">java version <span class="string">"1.8.0_171"</span></span><br><span class="line">Java(TM) SE Runtime Environment (build 1.8.0_171-b11)</span><br><span class="line">Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)</span><br><span class="line"></span><br><span class="line">ajm@DESKTOP-R8SS06A MINGW64 /d/学习/cs61b</span><br><span class="line">$ javac -version</span><br><span class="line">javac 11.0.1</span><br></pre></td></tr></table></figure><p>发现JRE是老的版本,于是我直接删除了这个老的版本。但是发现运行时出了问题:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ajm@DESKTOP-R8SS06A MINGW64 /d/学习/cs61b</span><br><span class="line">$ java -version</span><br><span class="line">bash: /c/Program Files (x86)/Common Files/Oracle/Java/javapath/java: No such file or directory</span><br></pre></td></tr></table></figure></p><p>这是因为环境变量中的路径问题,直接在PATH中删除老版本java的路径,就能正确找到java 11.0.1这个版本。</p>]]></content>
<summary type="html">
<p>今天我下载了jdk 11.0.1,一番配置后,运行简单的程序时时出现了<code>java.lang.UnsupportedClassVersionError</code>的错误,错误信息如下:</p>
<h3 id="错误信息"><a href="#错误信息" class="headerlink" title="错误信息"></a>错误信息</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">ajm@DESKTOP-R8SS06A MINGW64 /d/学习/cs61b</span><br><span class="line">$ java HelloWorld</span><br><span class="line">Error: A JNI error has occurred, please check your installation and try again</span><br><span class="line">Exception in thread &quot;main&quot; java.lang.UnsupportedClassVersionError: HelloWorld has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0</span><br><span class="line"> at java.lang.ClassLoader.defineClass1(Native Method)</span><br><span class="line"> at java.lang.ClassLoader.defineClass(Unknown Source)</span><br><span class="line"> at java.security.SecureClassLoader.defineClass(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader.defineClass(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader.access$100(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader$1.run(Unknown Source)</span><br><span class="line"> at java.net.URLClassLoader$1.run(Unknown Source)</span><br><span class="line"> at java.security.AccessController.doPrivileged(Native Method)</span><br><span class="line"> at java.net.URLClassLoader.findClass(Unknown Source)</span><br><span class="line"> at java.lang.ClassLoader.loadClass(Unknown Source)</span><br><span class="line"> at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)</span><br><span class="line"> at java.lang.ClassLoader.loadClass(Unknown Source)</span><br><span class="line"> at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)</span><br></pre></td></tr></table></figure>
</summary>
<category term="java" scheme="http://yoursite.com/categories/java/"/>
<category term="java" scheme="http://yoursite.com/tags/java/"/>
<category term="error" scheme="http://yoursite.com/tags/error/"/>
</entry>
<entry>
<title>error C2589: (: ::右边的非法标记</title>
<link href="http://yoursite.com/2018/11/25/error-C2589-%E5%8F%B3%E8%BE%B9%E7%9A%84%E9%9D%9E%E6%B3%95%E6%A0%87%E8%AE%B0/"/>
<id>http://yoursite.com/2018/11/25/error-C2589-右边的非法标记/</id>
<published>2018-11-25T06:04:36.000Z</published>
<updated>2018-12-22T18:26:08.018Z</updated>
<content type="html"><![CDATA[<blockquote><p>原文:<a href="https://blog.csdn.net/zhuangshn/article/details/5537499" target="_blank" rel="noopener">https://blog.csdn.net/zhuangshn/article/details/5537499</a> </p></blockquote><h2 id="error-C2589-“-”-“-”右边的非法标记"><a href="#error-C2589-“-”-“-”右边的非法标记" class="headerlink" title="error C2589: “(”: “::”右边的非法标记"></a>error C2589: “(”: “::”右边的非法标记</h2><ol><li><p>错误输出<br> error C2589: “(”: “::”右边的非法标记</p><p> error C2059: 语法错误 : “::”</p></li><li><p>错误代码举例</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">num_choices = std::max(1, std::min(26, num_choices));</span><br></pre></td></tr></table></figure></li><li><p>函数模板max </p><p>注:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。</p></li><li><p>错误原因</p><p>函数模板max与Visual C++中的全局的宏max冲突。 </p></li><li><p>解决办法</p><p> 第一种办法:设置项目属性,在预定义处理器中添加定义<code>NOMINMAX</code>来禁止使用Vsual C++的min/max宏定义。</p><p> 项目属性 ——> C/C++ ——> 预处理器 ——> 预处理器定义 (此处添加预定义编译开关 NOMINMAX)</p><p> 第二种办法: 加上括号,与Vsual C++的min/max宏定义区分开</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">num_choices = (std::max)(1, std::min(26, num_choices));</span><br></pre></td></tr></table></figure></li></ol>]]></content>
<summary type="html">
<blockquote>
<p>原文:<a href="https://blog.csdn.net/zhuangshn/article/details/5537499" target="_blank" rel="noopener">https://blog.csdn.net/zh
</summary>
<category term="error" scheme="http://yoursite.com/categories/error/"/>
<category term="error" scheme="http://yoursite.com/tags/error/"/>
<category term="C++" scheme="http://yoursite.com/tags/C/"/>
</entry>
<entry>
<title>cmake find_path(),windows带空格的路径</title>
<link href="http://yoursite.com/2018/11/25/cmake-find-path-windows%E5%B8%A6%E7%A9%BA%E6%A0%BC%E7%9A%84%E8%B7%AF%E5%BE%84/"/>
<id>http://yoursite.com/2018/11/25/cmake-find-path-windows带空格的路径/</id>
<published>2018-11-25T02:54:21.000Z</published>
<updated>2018-12-05T19:35:16.277Z</updated>
<content type="html"><![CDATA[<p>cmake中的windows 路径如果有空格,比如<code>D:/Program Files/libigl</code>, 需要改成<code>D:/Program\ Files/libigl</code><br><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">find_path(LIBIGL_INCLUDE_DIR igl/readOBJ.h</span><br><span class="line"> HINTS</span><br><span class="line"> ENV LIBIGL</span><br><span class="line"> ENV LIBIGLROOT</span><br><span class="line"> ENV LIBIGL_ROOT</span><br><span class="line"> ENV LIBIGL_DIR</span><br><span class="line"> PATHS</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/../..</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/..</span><br><span class="line"> ${CMAKE_SOURCE_DIR}</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/libigl</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/../libigl</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/../../libigl</span><br><span class="line"> D:/Program\ Files/libigl</span><br><span class="line"> /usr</span><br><span class="line"> /usr/local</span><br><span class="line"> /usr/local/igl/libigl</span><br><span class="line"> PATH_SUFFIXES include</span><br><span class="line">)</span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>cmake中的windows 路径如果有空格,比如<code>D:/Program Files/libigl</code>, 需要改成<code>D:/Program\ Files/libigl</code><br><figure class="highlight plai
</summary>
<category term="error" scheme="http://yoursite.com/categories/error/"/>
<category term="cmake" scheme="http://yoursite.com/tags/cmake/"/>
</entry>
<entry>
<title>hadoop集群搭建</title>
<link href="http://yoursite.com/2018/09/26/hadoop%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA/"/>
<id>http://yoursite.com/2018/09/26/hadoop集群搭建/</id>
<published>2018-09-26T04:09:45.000Z</published>
<updated>2018-12-17T08:19:31.173Z</updated>
<content type="html"><![CDATA[<h1 id="hadoop-集群搭建"><a href="#hadoop-集群搭建" class="headerlink" title="hadoop 集群搭建"></a>hadoop 集群搭建</h1><p>实验室当前hadoop集群节点如下:</p><table><thead><tr><th>主机名</th><th>用户名</th><th>IP</th><th>集群中的角色</th></tr></thead><tbody><tr><td>master</td><td>hadoop</td><td>10.13.61.122</td><td>NameNode、JobTracker</td></tr><tr><td>slave1</td><td>hadoop</td><td>10.13.61.125</td><td>DataNode、TaskTracker</td></tr><tr><td>slave2</td><td>hadoop</td><td>10.13.61.132</td><td>DataNode、TaskTracker</td></tr><tr><td>slave3</td><td>hadoop</td><td>10.13.61.146</td><td>DataNode、TaskTracker</td></tr><tr><td>slave4</td><td>hadoop</td><td>10.13.61.144</td><td>DataNode、TaskTracker</td></tr><tr><td>slave5</td><td>hadoop</td><td>10.13.61.143</td><td>DataNode、TaskTracker</td></tr><tr><td>slave6</td><td>hadoop</td><td>10.13.61.147</td><td>DataNode、TaskTracker</td></tr><tr><td>ajm-zju</td><td>hadoop</td><td>10.13.61.129</td><td>DataNode、TaskTracker</td></tr></tbody></table><p>各个节点的用户名均设置为 <strong>hadoop</strong>,密码均为 <strong>123456</strong>。其中slave3,slave4目前一般不使用。</p><p>hadoop集群安装主要有以下几个步骤:</p><ol><li>环境配置(host设置,ssh免密登录,Java安装等)</li><li>hadoop安装及修改配置文件</li><li>运行及测试</li></ol><a id="more"></a><h2 id="一、环境配置"><a href="#一、环境配置" class="headerlink" title="一、环境配置"></a>一、环境配置</h2><h3 id="1-用户、主机名、hosts文件"><a href="#1-用户、主机名、hosts文件" class="headerlink" title="1. 用户、主机名、hosts文件"></a>1. 用户、主机名、hosts文件</h3><p>由于目前已经搭建好的hadoop集群的用户名均为hadoop,所以需要在Ubuntu系统上新建一个hadoop用户,步骤如下:</p><h4 id="创建hadoop操作用户"><a href="#创建hadoop操作用户" class="headerlink" title="创建hadoop操作用户"></a>创建hadoop操作用户</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo useradd -m hadoop -s /bin/bash</span><br></pre></td></tr></table></figure><h4 id="给hadoop用户添加密码"><a href="#给hadoop用户添加密码" class="headerlink" title="给hadoop用户添加密码"></a>给hadoop用户添加密码</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo passwd hadoop</span><br></pre></td></tr></table></figure><p>输入密码后回车,密码在输入时是不可见的。</p><h4 id="给hadoop用户分配sudo权限"><a href="#给hadoop用户分配sudo权限" class="headerlink" title="给hadoop用户分配sudo权限"></a>给hadoop用户分配sudo权限</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo adduser hadoop sudo</span><br></pre></td></tr></table></figure><p>注销或重启系统,以hadoop用户登录</p><h4 id="切换用户"><a href="#切换用户" class="headerlink" title="切换用户"></a>切换用户</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su <用户名>,例如 su hadoop; su ajm</span><br></pre></td></tr></table></figure><p>输入要切换的用户密码,即可切换。</p><h4 id="安装vim、gedit"><a href="#安装vim、gedit" class="headerlink" title="安装vim、gedit"></a>安装vim、gedit</h4><p>vim是命令行编辑工具,gedit是图形界面编辑器,不习惯vim的话建议使用gedit<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install vim</span><br><span class="line">sudo apt-get install gedit</span><br></pre></td></tr></table></figure></p><h4 id="修改主机名"><a href="#修改主机名" class="headerlink" title="修改主机名"></a>修改主机名</h4><p><strong>不想修改主机名可以跳过此步,不会有影响</strong></p><p>在终端中输入hostname可以查看当前主机名,如下图:<br><img src="/images/1.jpg" alt=""><br>实际上在终端中有 <strong>hadoop@ajm-zju</strong>,其中hadoop是用户名,ajm-zju是主机名<br>比如要把新的主机加入集群,为了名称统一,可以将主机名改为 <strong>slave7</strong>,只需:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo hostname slave7 #暂时生效,重启后会失效</span><br><span class="line">sudo gedit /etc/hostname</span><br></pre></td></tr></table></figure></p><p>在文件中修改为slave7即可</p><h4 id="查看本机ip地址"><a href="#查看本机ip地址" class="headerlink" title="查看本机ip地址"></a>查看本机ip地址</h4><p>终端中输入以下命令:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ifconfig</span><br></pre></td></tr></table></figure></p><p><img src="/images/ip.jpg" alt=""><br>图中的 <strong>inet地址: 10.13.61.129</strong> 即为本机ip地址。</p><h4 id="配置hosts"><a href="#配置hosts" class="headerlink" title="配置hosts"></a>配置hosts</h4><p>/etc/hosts文件里维护了主机名和ip地址的映射关系,这样可以直接通过主机名通信,不用每次输入复杂的ip地址。通过cat命令可以直接在命令行中查看文件内容:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo cat /etc/hosts</span><br></pre></td></tr></table></figure></p><p>在我的主机上,结果如下:<br><img src="/images/hosts.jpg" alt=""><br>可以hosts文件中保存了hadoop集群中其他主机的 <strong>ip地址<->主机名</-></strong> 映射关系,这样在hadoop进行通信时,可以直接通过主机名访问。所以如果集群加入新的主机,需要在新主机上修改hosts文件如上图,并加上本机地址映射<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo gedit /etc/hosts</span><br></pre></td></tr></table></figure></p><p>终端中输入以上命令进行修改</p><h4 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h4><p>如果配置成功,通过 <strong>ping</strong> 测试时,可以直接通过主机名而不需要ip地址<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ping master</span><br><span class="line">ping slave1</span><br><span class="line">ping 其他主机</span><br></pre></td></tr></table></figure></p><p>成功时结果如下:<br><img src="/images/ping.jpg" alt=""><br>注:ping指令会一直执行,可以通过 <code>ctrl+C</code> 停止</p><h3 id="2-配置SSH免密登录"><a href="#2-配置SSH免密登录" class="headerlink" title="2. 配置SSH免密登录"></a>2. 配置SSH免密登录</h3><p>由于hadoop集群中master主机需要调度各个slave,而这需要配置ssh远程登录服务。</p><h4 id="安装ssh"><a href="#安装ssh" class="headerlink" title="安装ssh"></a>安装ssh</h4><p>ubuntu 默认安装了ssh 客户端,没有安装服务端。运行:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps -e|grep ssh</span><br></pre></td></tr></table></figure></p><p>结果应该与下文类似:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hadoop@ajm-zju:/home/ajm$ ps -e|grep ssh</span><br><span class="line"> 1444 ? 00:00:00 sshd</span><br></pre></td></tr></table></figure></p><p>如果没有 <code>sshd</code> ,则说明没有安装ssh服务端,可以输入以下命令安装:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install openssh-server</span><br></pre></td></tr></table></figure></p><h4 id="ssh登录其他主机"><a href="#ssh登录其他主机" class="headerlink" title="ssh登录其他主机"></a>ssh登录其他主机</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh master</span><br></pre></td></tr></table></figure><p>出现身份警告时,输入yes并回车,需要输入密码时,请输入master主机的密码。<br>之后就登录了master主机,可以通过命令行操作maseter主机。<br><img src="/images/ssh.jpg" alt=""><br>注:退出登录使用<code>exit</code> 命令。</p><h4 id="生成RSA公私钥对"><a href="#生成RSA公私钥对" class="headerlink" title="生成RSA公私钥对"></a>生成RSA公私钥对</h4><p>但是每次ssh登录都需要输入密码太麻烦,所以可以通过公私钥的方式免密登录,配置方法是 <strong>A主机将公钥加入到B主机的authorized_keys中</strong>, 则A可以免密登录B。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa # 一路回车</span><br><span class="line">cd ~/.ssh # 公私钥对保存在此目录</span><br><span class="line">ls # 查看目录中的文件列表</span><br></pre></td></tr></table></figure></p><p>终端中输入以上命令后,可以看到有 id_rsa(私钥),id_rsa.pub(公钥)。<br>则将id_rsa.pub追加到master主机的authorized_keys中,则当前主机可以免密登录master主机。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-copy-id -i ~/.ssh/id_rsa.pub master</span><br></pre></td></tr></table></figure></p><p>如需要输入密码则输入master主机的密码</p><h4 id="ssh免密登录测试"><a href="#ssh免密登录测试" class="headerlink" title="ssh免密登录测试"></a>ssh免密登录测试</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh master</span><br></pre></td></tr></table></figure><p>如果直接登录成功,则配置正确。<br>登录master后,由于master主机已经生成了公私钥对,可以将master的公钥发给当前主机,实现master对当前主机的ssh免密登录。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-copy-id -i ~/.ssh/id_rsa.pub <hostname></span><br></pre></td></tr></table></figure></p><p>如果出现错误,则需要在master主机中修改/etc/hosts,添加新主机的 ip<->hostname 映射。</-></p><h3 id="3-java安装"><a href="#3-java安装" class="headerlink" title="3. java安装"></a>3. java安装</h3><p>下载 <code>jdk-8u101.linux-x64.tar.gz</code>,运行以下命令解压到/usr目录下:<br><figure class="highlight plain"><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">sudo mkdir /usr/java</span><br><span class="line">sudo tar -zxvf jdk-8u101.linux-x64.tar.gz -C /usr/java</span><br><span class="line">cd /usr/java/jdk1.8.0_101/bin</span><br><span class="line">./java -version #查看java版本</span><br></pre></td></tr></table></figure></p><p><img src="/images/java.jpg" alt=""><br>出现上图结果则正确安装</p><h4 id="配置环境变量"><a href="#配置环境变量" class="headerlink" title="配置环境变量"></a>配置环境变量</h4><p>在前面是通过<code>./java</code> 执行java可执行程序,但是为了执行这个程序,必须每次都切换到<code>/usr/java/jdk1.8.0_101/bin</code>目录下,为了能在任何目录下都能执行java的相关程序,需要配置环境变量。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo gedit /etc/profile</span><br></pre></td></tr></table></figure></p><p>在/etc/profile文件末尾添加如下<br><figure class="highlight plain"><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">export JAVA_HOME=/usr/java/jdk1.8.0_101</span><br><span class="line">export JRE_HOME=/usr/java/jdk1.8.0_101/jre</span><br><span class="line">export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib</span><br><span class="line">export PATH=$PATH:$JAVA_HOME/bin</span><br></pre></td></tr></table></figure></p><p>保存后退出。通过<code>source</code>命令使得上面的修改生效。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure></p><p>输入以下命令测试是否成功配置环境变量<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -version</span><br></pre></td></tr></table></figure></p><p><img src="/images/java1.jpg" alt=""><br>出现以上结果则成功配置。</p><h2 id="二、Hadoop安装"><a href="#二、Hadoop安装" class="headerlink" title="二、Hadoop安装"></a>二、Hadoop安装</h2><h3 id="1-安装及环境变量配置"><a href="#1-安装及环境变量配置" class="headerlink" title="1. 安装及环境变量配置"></a>1. 安装及环境变量配置</h3><h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><p>将hadoop-2.6.0.tar.gz解压到目录/opt<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo tar -zxvf hadoop-2.6.0.tar.gz -C /opt # 解压到/opt</span><br><span class="line">cd /opt # 切到含有hadoop-2.6.0的目录下</span><br><span class="line">sudo chown -R hadoop:hadoop ./hadoop-2.6.0 # 修改文件权限</span><br></pre></td></tr></table></figure></p><h4 id="配置环境变量-1"><a href="#配置环境变量-1" class="headerlink" title="配置环境变量"></a>配置环境变量</h4><p>与java配置环境变量相同,在/etc/profile中追加:<br><figure class="highlight plain"><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">export HADOOP_HOME=/opt/hadoop-2.6.0</span><br><span class="line">export HADOOP_LIB_NATIVE=$HADOOP_HOME/lib/native</span><br><span class="line">export PATH=$PATH:$HADOOP_HOME/bin</span><br><span class="line">export PATH=$PATH:$HADOOP_HOME/sbin</span><br><span class="line">export PATH=$PATH:$HADOOP_HOME/lib</span><br></pre></td></tr></table></figure></p><p>保存后退出。通过<code>source</code>命令使得上面的修改生效。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure></p><p>输入以下命令测试是否成功配置环境变量<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hadoop version</span><br></pre></td></tr></table></figure></p><p><img src="/images/hadoop_v.jpg" alt=""><br>出现以上结果则成功配置。</p><h3 id="2-配置参数"><a href="#2-配置参数" class="headerlink" title="2. 配置参数"></a>2. 配置参数</h3><p>需要对所有的集群节点配置参数,其中大部分文件都是相同的,可以配置一个之后直接复制覆盖相关文件,而比如不同主机java安装路径不同的话,需要复制之后修改hadoop-env.sh和yarn-env.sh的相关参数。<br>hadoop需要配置一些参数才能成功运行,这些配置文件都在<code>/opt/hadoop-2.6.0/etc/hadoop/</code> 目录下。</p><h4 id="hadoop-env-sh-and-yarn-env-sh"><a href="#hadoop-env-sh-and-yarn-env-sh" class="headerlink" title="hadoop-env.sh and yarn-env.sh"></a>hadoop-env.sh and yarn-env.sh</h4><p>在<code>hadoop-env.sh</code>和<code>yarn-env.sh</code>中需要指定java安装目录。在文件末尾追加以下内容即可:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">export JAVA_HOME=/usr/java/jdk1.8.0_101</span><br></pre></td></tr></table></figure></p><h4 id="slaves"><a href="#slaves" class="headerlink" title="slaves"></a>slaves</h4><p>slaves文件需要添加所有的slave节点主机名如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">slave1</span><br><span class="line">slave2</span><br><span class="line">slave3</span><br><span class="line">slave4</span><br><span class="line">slave5</span><br><span class="line">slave6</span><br><span class="line">ajm-zju</span><br><span class="line"><Your hostname></span><br></pre></td></tr></table></figure></p><h4 id="core-site-xml"><a href="#core-site-xml" class="headerlink" title="core-site.xml"></a>core-site.xml</h4><p>添加以下内容:<br><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"><configuration></span><br><span class="line"> <property></span><br><span class="line"> <name>fs.defaultFS</name></span><br><span class="line"> <value>hdfs://master:8020</value></span><br><span class="line"> <description></description></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>io.file.buffer.size</name></span><br><span class="line"> <value>131072</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>hadoop.tmp.dir</name></span><br><span class="line"> <value>/opt/hadoop-2.6.0/tmp</value></span><br><span class="line"> <description>A base for other temporary directories.</description></span><br><span class="line"> </property></span><br><span class="line"></configuration></span><br></pre></td></tr></table></figure></p><h4 id="hdfs-site-xml"><a href="#hdfs-site-xml" class="headerlink" title="hdfs-site.xml"></a>hdfs-site.xml</h4><p>这个文件配置hdfs文件系统相关参数,添加以下内容:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><configuration></span><br><span class="line"></span><br><span class="line"> <property></span><br><span class="line"> <name>dfs.replication</name></span><br><span class="line"> <value>3</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>dfs.namenode.name.dir</name></span><br><span class="line"> <value>file:/opt/hadoop-2.6.0/dfs/name</value></span><br><span class="line"> <description>namenode上存储hdfs name空间元数据</description></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>dfs.datanode.data.dir</name></span><br><span class="line"> <value>file:/opt/hadoop-2.6.0/dfs/data</value></span><br><span class="line"> <description>datanode上数据块的物理存储位置</description></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>dfs.namenode.secondary.http-address</name></span><br><span class="line"> <value>master:50090</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>dfs.webhdfs.enabled</name></span><br><span class="line"> <value>true</value> </span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>dfs.permissions</name></span><br><span class="line"> <value>false</value> </span><br><span class="line"> </property></span><br><span class="line"></configuration></span><br></pre></td></tr></table></figure></p><h4 id="mapred-site-xml"><a href="#mapred-site-xml" class="headerlink" title="mapred-site.xml"></a>mapred-site.xml</h4><p>这个文件配置mapreduce任务相关参数。首先需要重命名mapred-site.xml.template文件:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mv ./mapred-site.xml.template mapred-site.xml</span><br></pre></td></tr></table></figure></p><p>然后将以下内容添加到 mapred-site.xml:<br><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"><configuration></span><br><span class="line"> <property></span><br><span class="line"> <name>mapreduce.framework.name</name></span><br><span class="line"> <value>yarn</value></span><br><span class="line"> </property></span><br><span class="line"></span><br><span class="line"> <property></span><br><span class="line"> <name>mapreduce.jobhistory.address</name></span><br><span class="line"> <value>master:10020</value></span><br><span class="line"> </property></span><br><span class="line"> </span><br><span class="line"> <property></span><br><span class="line"> <name>mapreduce.jobhistory.webapp.address</name></span><br><span class="line"> <value>master:19888</value></span><br><span class="line"> </property></span><br><span class="line"></span><br><span class="line"> <property></span><br><span class="line"> <name>mapreduce.jobhistory.itermediate-done-dir</name> </span><br><span class="line"> <value>${hadoop.tmp.dir}/mr-history/tmp</value></span><br><span class="line"> </property></span><br><span class="line"> </span><br><span class="line"> <property></span><br><span class="line"> <name>mapreduce.jobhistory.done-dir</name></span><br><span class="line"> <value>${hadoop.tmp.dir}/mr-history/done</value></span><br><span class="line"> </property></span><br><span class="line"> </span><br><span class="line"> <property></span><br><span class="line"> <name>mapreduce.jobtracker.staging.root.dir</name></span><br><span class="line"> <value>/user</value></span><br><span class="line"> </property></span><br><span class="line"></configuration></span><br></pre></td></tr></table></figure></p><h4 id="yarn-site-xml"><a href="#yarn-site-xml" class="headerlink" title="yarn-site.xml"></a>yarn-site.xml</h4><p>这个文件配置yarn资源管理调度的相关参数,添加以下内容:<br><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line"><configuration></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.nodemanager.aux-services</name></span><br><span class="line"> <value>mapreduce_shuffle</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name></span><br><span class="line"> <value>org.apache.hadoop.mapred.ShuffleHandler</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.resourcemanager.address</name></span><br><span class="line"> <value>master:8032</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.resourcemanager.scheduler.address</name></span><br><span class="line"> <value>master:8030</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.resourcemanager.resource-tracker.address</name></span><br><span class="line"> <value>master:8035</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.resourcemanager.admin.address</name></span><br><span class="line"> <value>master:8033</value></span><br><span class="line"> </property> </span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.resourcemanager.webapp.address</name></span><br><span class="line"> <value>master:8088</value></span><br><span class="line"> </property></span><br><span class="line"></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.app.mapreduce.am.staging-dir</name></span><br><span class="line"> <value>/user</value></span><br><span class="line"> </property></span><br><span class="line"></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.nodemanager.resource.memory-mb</name></span><br><span class="line"> <value>20480</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.scheduler.minimum-allocation-mb</name></span><br><span class="line"> <value>2048</value></span><br><span class="line"> </property></span><br><span class="line"> <property></span><br><span class="line"> <name>yarn.nodemanager.vmem-pmem-ratio</name></span><br><span class="line"> <value>2.1</value></span><br><span class="line"> </property></span><br><span class="line"></span><br><span class="line"></configuration></span><br></pre></td></tr></table></figure></p><h2 id="三、-运行及测试"><a href="#三、-运行及测试" class="headerlink" title="三、 运行及测试"></a>三、 运行及测试</h2><p>ssh登录master主机后,进行以下操作。</p><h3 id="格式化分布式文件系统-已有hadoop系统请跳过这一步"><a href="#格式化分布式文件系统-已有hadoop系统请跳过这一步" class="headerlink" title="格式化分布式文件系统(已有hadoop系统请跳过这一步)"></a>格式化分布式文件系统(已有hadoop系统请跳过这一步)</h3><font color="#FF0000" size="4">只有在第一次搭建hadoop系统时需要进行格式化操作,请不要在已有的hadoop系统上格式化,这会删除所有的数据!!!!</font><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hdfs namenode -format</span><br></pre></td></tr></table></figure><h3 id="运行文件系统管理器hdfs"><a href="#运行文件系统管理器hdfs" class="headerlink" title="运行文件系统管理器hdfs"></a>运行文件系统管理器hdfs</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">start-dfs.sh</span><br></pre></td></tr></table></figure><h3 id="运行任务调度管理器yarn"><a href="#运行任务调度管理器yarn" class="headerlink" title="运行任务调度管理器yarn"></a>运行任务调度管理器yarn</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">start-yarn.sh</span><br></pre></td></tr></table></figure><h3 id="查看相关进程"><a href="#查看相关进程" class="headerlink" title="查看相关进程"></a>查看相关进程</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jps</span><br></pre></td></tr></table></figure><p>在master中可以看到:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[hadoop@master ~]$ jps</span><br><span class="line">5859 SecondaryNameNode</span><br><span class="line">6003 ResourceManager</span><br><span class="line">6293 Jps</span><br><span class="line">24991 JobHistoryServer</span><br><span class="line">5695 NameNode</span><br></pre></td></tr></table></figure></p><p>在各个slave中可以看到:<br><figure class="highlight plain"><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">hadoop@ajm-zju:/$ jps</span><br><span class="line">28976 DataNode</span><br><span class="line">31952 NodeManager</span><br><span class="line">32158 Jps</span><br></pre></td></tr></table></figure></p><h3 id="Web查看信息"><a href="#Web查看信息" class="headerlink" title="Web查看信息"></a>Web查看信息</h3><p>在web上可以看到集群启动的信息:</p><ul><li>查看hdfs: <a href="master:50070" target="_blank" rel="noopener">master:50070</a></li><li>查看resourcemanager: <a href="master:8088" target="_blank" rel="noopener">master:8088</a></li></ul><p>如果web页面访问不了,可能是master主机的防火墙未关闭, ssh登录master主机,运行以下命令:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo systemctl status firewalld.service # 查看防火墙状态</span><br></pre></td></tr></table></figure></p><p><img src="/images/wall.jpg" alt=""><br>若图中的Active:显示为active,则需要关闭防火墙。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo systemctl stop firewalld.service # 关闭防火墙</span><br></pre></td></tr></table></figure></p><p>关闭后重新访问页面即可。</p><h3 id="关闭hadoop"><a href="#关闭hadoop" class="headerlink" title="关闭hadoop"></a>关闭hadoop</h3><p>执行相反的操作<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">stop-yarn.sh</span><br><span class="line">stop-dfs.sh</span><br></pre></td></tr></table></figure></p><blockquote><p>本文引用了以下内容</p><ul><li><a href="https://www.jianshu.com/p/4e0dc91ad86e" target="_blank" rel="noopener">Hadoop真分布式集群最速搭建攻略</a></li></ul></blockquote>]]></content>
<summary type="html">
<h1 id="hadoop-集群搭建"><a href="#hadoop-集群搭建" class="headerlink" title="hadoop 集群搭建"></a>hadoop 集群搭建</h1><p>实验室当前hadoop集群节点如下:</p>
<table>
<thead>
<tr>
<th>主机名</th>
<th>用户名</th>
<th>IP</th>
<th>集群中的角色</th>
</tr>
</thead>
<tbody>
<tr>
<td>master</td>
<td>hadoop</td>
<td>10.13.61.122</td>
<td>NameNode、JobTracker</td>
</tr>
<tr>
<td>slave1</td>
<td>hadoop</td>
<td>10.13.61.125</td>
<td>DataNode、TaskTracker</td>
</tr>
<tr>
<td>slave2</td>
<td>hadoop</td>
<td>10.13.61.132</td>
<td>DataNode、TaskTracker</td>
</tr>
<tr>
<td>slave3</td>
<td>hadoop</td>
<td>10.13.61.146</td>
<td>DataNode、TaskTracker</td>
</tr>
<tr>
<td>slave4</td>
<td>hadoop</td>
<td>10.13.61.144</td>
<td>DataNode、TaskTracker</td>
</tr>
<tr>
<td>slave5</td>
<td>hadoop</td>
<td>10.13.61.143</td>
<td>DataNode、TaskTracker</td>
</tr>
<tr>
<td>slave6</td>
<td>hadoop</td>
<td>10.13.61.147</td>
<td>DataNode、TaskTracker</td>
</tr>
<tr>
<td>ajm-zju</td>
<td>hadoop</td>
<td>10.13.61.129</td>
<td>DataNode、TaskTracker</td>
</tr>
</tbody>
</table>
<p>各个节点的用户名均设置为 <strong>hadoop</strong>,密码均为 <strong>123456</strong>。其中slave3,slave4目前一般不使用。</p>
<p>hadoop集群安装主要有以下几个步骤:</p>
<ol>
<li>环境配置(host设置,ssh免密登录,Java安装等)</li>
<li>hadoop安装及修改配置文件</li>
<li>运行及测试</li>
</ol>
</summary>
<category term="大数据" scheme="http://yoursite.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="hadoop" scheme="http://yoursite.com/tags/hadoop/"/>
</entry>
</feed>