-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
259 lines (131 loc) · 159 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>wsblog</title>
<link href="http://example.com/atom.xml" rel="self"/>
<link href="http://example.com/"/>
<updated>2022-08-30T13:26:45.491Z</updated>
<id>http://example.com/</id>
<author>
<name>wsyzs</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>Java学习之多线程</title>
<link href="http://example.com/2022/08/30/Java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
<id>http://example.com/2022/08/30/Java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E5%A4%9A%E7%BA%BF%E7%A8%8B/</id>
<published>2022-08-30T10:35:56.000Z</published>
<updated>2022-08-30T13:26:45.491Z</updated>
<content type="html"><![CDATA[<h3 id="什么是进程?"><a href="#什么是进程?" class="headerlink" title="什么是进程?"></a>什么是进程?</h3><p>在多任务操作系统之中,一个后台正在运行的应用就是一个进程。</p><p>通俗定义而言,就是一个应用程序就是一个进程。</p><h3 id="进程与线程的关系?"><a href="#进程与线程的关系?" class="headerlink" title="进程与线程的关系?"></a>进程与线程的关系?</h3><p>一个进程需要完成多个任务,这时候利用线程进行任务操作,可以极大提高CPU的利用率。</p><p>一个进程至少有一个线程,一个线程只能属于一个进程。</p><h3 id="线程的生命周期。"><a href="#线程的生命周期。" class="headerlink" title="线程的生命周期。"></a>线程的生命周期。</h3><p>线程按照其创建、运行以及结束几个阶段,划分为六个生命周期。分别为:</p><p>新建状态:jvm为创建的线程对象分配推空间和相关资源,当线程被创建完成时即为新建状态;</p><p>可运行状态:该状态实际包含两种状态,分别是就绪状态和运行状态。当创建的线程对象执行start方法时,则会进入就绪状态;当进入就绪状态的线程争抢到cpu资源时,会执行run方法,进入运行状态。</p><p>阻塞状态:正在运行的线程对象由于缺乏相应的资源,无法继续执行后续任务,此时会让出cpu进入阻塞状态,当获取到需要的资源时,会重新进入就绪状态争抢cpu资源。线程阻塞原因较为常见的有:</p><p>当前正在运行的线程,需要访问同步锁资源,当同步锁资源被其他线程占有,只能等待其他线程释放资源才能执行后续任务;<br>当前线程发出I/O请求。<br>等待状态:正在运行的线程通过调用无时间参数限制的方法后,进入等待状态,只有被重新唤醒才能进入就绪状态。比如线程调用wait()、join()等方法,从而进入等待状态,只有其他线程通过notify或者notifyAll方法唤醒后才能进入就绪状态(join方法只能等待插入的线程执行完毕之后才能进入就绪状态)。</p><p>定时等待状态:与定时状态的区别在于,其含有时间参数,在指定的时间参数结束后或者其他线程唤醒后,线程自动进入就绪状态。</p><p>终止状态:线程的run方法或者call方法执行完毕之后或者捕捉到程序异常或者错误时,线程进入终止状态,即线程死亡。 </p><h3 id="单线程程序与多线程程序。"><a href="#单线程程序与多线程程序。" class="headerlink" title="单线程程序与多线程程序。"></a>单线程程序与多线程程序。</h3><p>单线程程序:一般只含有主程序,即一个程序按照顺序运行。较为脆弱和效率过低。</p><p>多线程程序:将一个程序划分不同任务给线程,每一个线程都能独立完成任务,以此提高cpu的利用效率。</p><p>前台和后台:每一个运行的线程都默认为前台,前台线程运行结束以后,后台程序自动结束。前台线程也可以转化为后台线程。</p><p>线程的优先级:线程抢占cpu资源的方式一般有两种。一为通过时间片原则抢占cpu资源,即划分执行时间,每一个线程在执行时间结束后释放cpu资源;二为通过抢占式的方法,各线程竞争cpu资源,该方式也为jvm默认的线程调度方式。在抢占式方法中,可以通过设置线程的优先级提高线程的抢占率,但并不是优先级高的一定能够抢占到cpu资源。</p><h3 id="创建线程对象的方法。"><a href="#创建线程对象的方法。" class="headerlink" title="创建线程对象的方法。"></a>创建线程对象的方法。</h3><p>Thread。通过继承Thread类,重写run方法,定义一个子类。通过该子类创建实例对象,即创建了线程对象。<br>Runnable。Runnable是一个接口,构造该接口的实现类,重写run方法,实例化对象,再将runnable子类实例化的对象作为参数传入Thread类的构造方法之中。<br>Callable。该类也为接口类,通过构造该类的实现类,重写call实现线程创建。调用时,实例化子类对象,通过Future类封装子类对象,再将封装后的FutureTask对象作为参数传入Thread的构造方法之中。<br>通过线程池创建以上三种线程对象。实际上,线程类型同以上三种,只是线程池提供了对线程对象的管理,使线程更加安全、高效的运行。<br>各种方法之间的区别。<br>Thread:该继承方法是线程实现的基础,但由于java中只支持单继承,若一个类已经有父类,需要在使用线程时,便无法通过此种方式创建线程;</p><p>Runnable:该类为接口类,java中支持多实现,解决了已有父类无法创建线程的问题。</p><p>Callable:该类为接口类,在runnable接口的基础上,实现了对线程执行结果的获取,即线程执行结束之后可以返回一个执行结果。</p><h3 id="线程同步。"><a href="#线程同步。" class="headerlink" title="线程同步。"></a>线程同步。</h3><p>线程安全:当多个线程对同一个资源进行请求时,由于线程的延迟,会导致被请求资源出现错误,如数据不一致、数据出现不应有的改变等。<br>实现线程安全的方法:<br>同步代码块:由于线程安全问题是由多个线程共享同一资源而导致的,要解决线程安全问题,必须保证任意时刻,共享资源的代码块只能被一个线程访问。<br>实现方式:使用synchronized关键字修饰共享资源的代码块。实质上为将共享资源的代码块上同步锁,当有线程在访问时,锁定程序代码块,只有访问的线程执行结束后,才能重新释放代码块。<br>基本格式为:synchronized(lock){…;//资源代码块}<br>Lock为锁对象,可以是任意类型。但是不同线程共享的锁对象必须保持一致,如此才能使锁的标志位对所有线程而言都是一样的。<br>同步方法:在方法的修饰符后面使用synchronized关键字,可以将方法进行锁定,一次只能允许一个线程访问该方法。此时,该方法的锁对象是方法所在的对象本身;若为静态方法,锁对象为方法所在的类的class对象。<br>优点:解决了多个线程同时访问共享数据时的线程安全问题。</p><p>缺点:线程在执行同步代码时每次都会判断锁的状态,非常消耗资源,效率较低。</p><h3 id="同步锁。"><a href="#同步锁。" class="headerlink" title="同步锁。"></a>同步锁。</h3><p>背景:同步代码块和同步方法的使用是一种封闭的锁机制,使用简单,也能较好的解决线程安全问题,但是该方法无法中断等待锁的进程不在等待,也无法通过轮询的方式得到锁,需要一直等待才能得到锁。</p><p>Lock锁:jdk5开始时引入,功能与synchronized相似,但是可以让线程持续获取同步锁失败后返回,不再继续等待,同时使用也更加灵活。</p><p>Lock是一个接口类,其有多个实现类,其中最为常用的有ReentrantLock类,常用的方法有:</p><p>Lock():在线程获取锁时如果锁已被其他线程获取,则进行等待,是最初级的获取锁的方法。Lock不会自动释放锁,哪怕程序异常也不会自动释放,只能手动释放锁。</p><p>tryLock() :用来尝试获取锁,如果当前锁没有被其他线程占用,则获取成功,返回 true,否则返回 false,代表获取锁失败。相比于 lock(),这样的方法显然功能更强大,我们可以根据是否能获取到锁来决定后续程序的行为。</p><p>Unlock():释放锁。一般使用try-catch模块对程序异常进行捕获,并且在finally中使用该方法释放锁,确保锁一定会在程序执行完后被释放。</p><p>lockInterruptibly():这个方法的作用就是去获取锁,如果这个锁当前是可以获得的,那么这个方法会立刻返回,但是如果这个锁当前是不能获得的(被其他线程持有),那么当前线程便会开始等待,除非它等到了这把锁或者是在等待的过程中被中断了,否则这个线程便会一直在这里执行这行代码。一句话总结就是,除非当前线程在获取锁期间被中断,否则便会一直尝试获取直到获取到为止。</p><p>顾名思义,lockInterruptibly() 是可以响应中断的。</p><h3 id="线程通信。"><a href="#线程通信。" class="headerlink" title="线程通信。"></a>线程通信。</h3><p>背景:</p><p>若一个线程执行run方法时,对于不同的方法需要获取不同的锁,并且要在执行的方法之中获取下一步的锁才能继续执行,此时若有多个线程同时执行run方法,分别获得不同方法的锁,此时,在每个线程执行完当前方法后,想要继续执行后续方法,获取锁时都是锁定状态,只能不断等待下去,便造成了线程之间的死锁问题。</p><p>线程通信:</p><p>解决死锁问题,可以通过线程之间通信,释放彼此需要的锁来进行。线程通信即通过信号量机制实现。</p><p>信号量机制。<br>意义:实现线程通信,解决线程堵塞问题。</p><p>实际应用:实现资源能被有限个线程使用。</p><p>特点:</p><p>信号量机制不同于互斥锁,其可以指定某一个资源能够被访问的线程最大数量,当有一个线程访问该资源时,信号量减一,当线程完成资源访问释放时,信号量加一,故信号量也可看作一个计数器。</p><p>Java中的信号量对象:Semaphore。其构造时可以传入一个整型参数,表示对应资源可接受线程的最大访问数量。</p><p> CountDownLatch:实现线程等待,即需要指定个数的线程到达某一个点时才进行下一步操作。</p><h3 id="线程池。"><a href="#线程池。" class="headerlink" title="线程池。"></a>线程池。</h3><p>优点:</p><p>1.降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;</p><p>2.提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行;</p><p>3.方便线程并发数的管控,线程若是无限制的创建,不仅会额外消耗大量系统资源,更是占用过多资源而阻塞系统或oom等状况,从而降低系统的稳定性。线程池能有效管控线程,统一分配、调优,提供资源使用率;</p><p>4.更强大的功能,线程池提供了定时、定期以及可控线程数等功能的线程池,使用方便简单。</p><p>常用线程池:</p><p>Executor(通用线程池):<br>时间:jdk5被引入,在java.util.concurrent包中,其为接口类,常用的子接口有ExecutorService,通过该接口可以很好的进行线程管理。</p><p>Executor实现线程管理池的主要步骤:<br>(1)创建线程实现类对象。</p><p>(2)使用Executor线程执行器类创建线程池。</p><p>(3)使用ExecutorService执行器服务类的submit()方法将线程实现类对象提交到线程池管理。</p><p>(4)线程任务执行完后,使用shutdown()方法关闭线程池。</p><p>CompletableFuture(函数式异步编程辅助类):<br>背景:jdk8时引入,实现了Future接口和CompletionStage接口</p><p>(jdk8时引入的线程任务完成接口),对Future接口进行了强大的扩展,同时简化了异步编程的复杂性,其实际上是为了解决callable实现接口时,使用FutureTask进行封装的不足。<br>实际代码演示:</p><h4 id="1-创建线程"><a href="#1-创建线程" class="headerlink" title="1 创建线程"></a>1 创建线程</h4><figure class="highlight plaintext"><figcaption><span>java.util.concurrent.Callable;</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">import java.util.concurrent.ExecutionException;</span><br><span class="line">import java.util.concurrent.FutureTask;</span><br><span class="line"> </span><br><span class="line">class Threads extends Thread{</span><br><span class="line"></span><br><span class="line">@Override</span><br><span class="line">public void run() {</span><br><span class="line">// TODO Auto-generated method stub</span><br><span class="line">System.out.println(Thread.currentThread().getName()+"为通过继承Thread所创建的线程!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">class Runnables implements Runnable{</span><br><span class="line"> </span><br><span class="line">@Override</span><br><span class="line">public void run() {</span><br><span class="line">// TODO Auto-generated method stub</span><br><span class="line">System.out.println(Thread.currentThread().getName()+"为通过实现Runnable所创建的线程!");</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">class Callables implements Callable<Integer>{</span><br><span class="line"> </span><br><span class="line">@Override</span><br><span class="line">public Integer call() throws Exception {</span><br><span class="line">// TODO Auto-generated method stub</span><br><span class="line">System.out.println(Thread.currentThread().getName()+"为通过实现Callables所创建的线程!");</span><br><span class="line">return 0;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">public class CreateThreads {</span><br><span class="line"></span><br><span class="line">public static void main(String[] args){</span><br><span class="line"></span><br><span class="line">Threads threads = new Threads();</span><br><span class="line">threads.setName("线程一");</span><br><span class="line">threads.start();</span><br><span class="line"></span><br><span class="line">Runnables runnables = new Runnables();</span><br><span class="line">Thread temp = new Thread(runnables);</span><br><span class="line">temp.setName("线程二");</span><br><span class="line">temp.start();</span><br><span class="line"></span><br><span class="line">Callables callables = new Callables();</span><br><span class="line">FutureTask<Integer> future = new FutureTask<Integer>(callables);</span><br><span class="line">Thread temps=new Thread(future);</span><br><span class="line">temps.setName("线程三");</span><br><span class="line">temps.start();</span><br><span class="line">try {</span><br><span class="line">int ans=future.get();</span><br><span class="line">System.out.println("Callable返回的结果为:"+ans);</span><br><span class="line">} catch (InterruptedException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">e.printStackTrace();</span><br><span class="line">} catch (ExecutionException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">e.printStackTrace();</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>运行结果:<br><img src="https://img-blog.csdnimg.cn/1850f0a278a64ddfb833e1c052e1506f.png" alt="enter description here"></p><h3 id="2-同步代码块"><a href="#2-同步代码块" class="headerlink" title="2 同步代码块"></a>2 同步代码块</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><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></pre></td><td class="code"><pre><span class="line"> * 该代码为同步静态资源和方法,需要注意,同步块中的锁对象需要为静态变量</span><br><span class="line"> * 保证线程访问资源都共用同一个锁对象。</span><br><span class="line"> * 若共享成员变量,则创建线程时,使用同一个实体类对象作为参数。</span><br><span class="line"> * */</span><br><span class="line">class ThreadTest extends Thread{</span><br><span class="line"></span><br><span class="line">public static int sum=20;</span><br><span class="line">public static int ans=20;</span><br><span class="line">private static Object ob = new Object();</span><br><span class="line">@Override</span><br><span class="line">public void run() {</span><br><span class="line">// TODO Auto-generated method stub</span><br><span class="line"></span><br><span class="line">while(sum>0) {</span><br><span class="line"></span><br><span class="line">synchronized (ob) {</span><br><span class="line"></span><br><span class="line">if(sum>0) {</span><br><span class="line">try {</span><br><span class="line">sleep(1000);</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">// TODO: handle exception</span><br><span class="line">}</span><br><span class="line">System.out.println(currentThread().getName()+"消耗资源"+sum--);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">while(ans>0) {</span><br><span class="line">try {</span><br><span class="line">sleep(1000);</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">// TODO: handle exception</span><br><span class="line">}</span><br><span class="line">this.Spend();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">public static synchronized void Spend() {</span><br><span class="line"></span><br><span class="line">if(ans>0) {</span><br><span class="line">System.out.println(currentThread().getName()+"通过同步方法消耗资源"+ans--);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public class SynchronizedBlock {</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">ThreadTest test1 = new ThreadTest();</span><br><span class="line">test1.setName("线程一");</span><br><span class="line"></span><br><span class="line">ThreadTest test2 = new ThreadTest();</span><br><span class="line">test2.setName("线程二");</span><br><span class="line"></span><br><span class="line">ThreadTest test3 = new ThreadTest();</span><br><span class="line">test3.setName("线程三");</span><br><span class="line"></span><br><span class="line">//ThreadTest test4 = new ThreadTest();</span><br><span class="line">//test4.setName("线程四");</span><br><span class="line">//</span><br><span class="line">//ThreadTest test5 = new ThreadTest();</span><br><span class="line">//test5.setName("线程五");</span><br><span class="line"></span><br><span class="line">test1.start();</span><br><span class="line">test2.start();</span><br><span class="line">test3.start();</span><br><span class="line">//test4.start();</span><br><span class="line">//test5.start();</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>运行结果:<br><img src="https://img-blog.csdnimg.cn/03099a6dddd14564a875cfdbdcc45d69.png" alt="enter description here"></p><h3 id="3-lock锁"><a href="#3-lock锁" class="headerlink" title="3 lock锁"></a>3 lock锁</h3><figure class="highlight plaintext"><figcaption><span>java.util.concurrent.locks.Lock;</span></figcaption><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">import java.util.concurrent.locks.ReentrantLock;</span><br><span class="line"> </span><br><span class="line">class Runnablel implements Runnable{</span><br><span class="line"> </span><br><span class="line">private int socre = 20;</span><br><span class="line">private Lock lock = new ReentrantLock();</span><br><span class="line">@Override</span><br><span class="line">public void run() {</span><br><span class="line">// TODO Auto-generated method stub</span><br><span class="line">while(this.socre>0) {</span><br><span class="line"></span><br><span class="line">lock.lock();</span><br><span class="line">try {</span><br><span class="line"></span><br><span class="line">if(this.socre>0) {</span><br><span class="line">Thread.sleep(1000);</span><br><span class="line">System.out.println(Thread.currentThread().getName()+"正在消耗资源"+this.socre--);</span><br><span class="line">}</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">// TODO: handle exception</span><br><span class="line">}</span><br><span class="line">finally {</span><br><span class="line"></span><br><span class="line">lock.unlock();</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">public class RunnableLock {</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">Runnablel runnables = new Runnablel();</span><br><span class="line">Thread test1 = new Thread(runnables,"线程1");</span><br><span class="line">Thread test2 = new Thread(runnables,"线程2");</span><br><span class="line">Thread test3 = new Thread(runnables,"线程3");</span><br><span class="line">test1.start();</span><br><span class="line">test2.start();</span><br><span class="line">test3.start();</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>运行结果:<br><img src="https://img-blog.csdnimg.cn/7cafc5d169d54501a50250f68327698f.png" alt="enter description here"></p><h3 id="4-线程通信"><a href="#4-线程通信" class="headerlink" title="4 线程通信"></a>4 线程通信</h3><figure class="highlight plaintext"><figcaption><span>java.util.concurrent.Semaphore;</span></figcaption><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></pre></td><td class="code"><pre><span class="line"> </span><br><span class="line">class Runnablec implements Runnable {</span><br><span class="line"></span><br><span class="line">private int resource = 20;</span><br><span class="line"></span><br><span class="line">//创建信号量</span><br><span class="line">private Semaphore A = new Semaphore(1);</span><br><span class="line">private Semaphore B = new Semaphore(1);</span><br><span class="line">@Override</span><br><span class="line">public void run() {</span><br><span class="line">// TODO Auto-generated method stub</span><br><span class="line">while(resource>0) {</span><br><span class="line">try {</span><br><span class="line">A.acquire();</span><br><span class="line">if(resource>0) {</span><br><span class="line">Thread.sleep(1000);</span><br><span class="line">this.display();</span><br><span class="line">B.acquire();</span><br><span class="line">this.showInfo();</span><br><span class="line">}</span><br><span class="line">} catch (InterruptedException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">e.printStackTrace();</span><br><span class="line">}</span><br><span class="line">finally {</span><br><span class="line"></span><br><span class="line">B.release();</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">public void showInfo() {</span><br><span class="line"></span><br><span class="line">System.out.println(Thread.currentThread().getName()+"获取了信号量B释放了信号量A");</span><br><span class="line">this.A.release();</span><br><span class="line">}</span><br><span class="line">public void display() {</span><br><span class="line"></span><br><span class="line">System.out.println(Thread.currentThread().getName()+"获取了信号量A消耗资源"+this.resource--);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">public class ThreadCommunication {</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">Runnablec rc = new Runnablec();</span><br><span class="line">Thread t1 = new Thread(rc,"线程1");</span><br><span class="line">Thread t2 = new Thread(rc,"线程2");</span><br><span class="line">Thread t3 = new Thread(rc,"线程3");</span><br><span class="line">t1.start();</span><br><span class="line">t2.start();</span><br><span class="line">t3.start();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>部分运行结果:<br><img src="https://img-blog.csdnimg.cn/3579f2730a7c41ab807ee174ecd92165.png" alt="enter description here"></p><h3 id="5-线程池使用"><a href="#5-线程池使用" class="headerlink" title="5 线程池使用"></a>5 线程池使用</h3><p>参考博客:<a href="https://blog.csdn.net/u013541140/article/details/95225769">Java 多线程:彻底搞懂线程池</a><br>补充说明:<br>创建和使用线程时,容易引发oom问题,故需要对线程进行控制,尤其对于线程池而言,直接使用Executors创建线程容易引发以上问题;<br>针对不同的并发场景,使用不同的线程池进行线程管理可极大节约资源。</p>]]></content>
<summary type="html"><h3 id="什么是进程?"><a href="#什么是进程?" class="headerlink" title="什么是进程?"></a>什么是进程?</h3><p>在多任务操作系统之中,一个后台正在运行的应用就是一个进程。</p>
<p>通俗定义而言,就是一个应用程序就是</summary>
</entry>
<entry>
<title>java学习之网络编程</title>
<link href="http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/"/>
<id>http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/</id>
<published>2022-08-30T10:35:28.000Z</published>
<updated>2022-08-30T13:25:13.416Z</updated>
<content type="html"><![CDATA[<p>相关知识点:</p><p>Transient:Java中的关键字,只能修饰变量,不能修饰类和方法。</p><p>作用:使被修饰的变量无法被序列化。</p><p>拓展:一个静态变量,无论是否被transient修饰都无法被序列化。若静态变量反序列化得到相应的值,可能是由于jvm中存在与静态变量相同名的静态变量,值是jvm中与静态变量相同名的静态变量的值。</p><p>若一个类实现了serializable,则其中的非静态变量和非transient修饰的变量都会被自动序列化;若类实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。</p><p>String[] args:在main方法中,args用来存放传入的参数,dos中编程时,可在字节码文件之后设置传入的参数。</p><p>InetAddress类使用介绍:</p><p>相关方法演示如下:</p><figure class="highlight plaintext"><figcaption><span>java.io.IOException;</span></figcaption><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">import java.net.InetAddress;</span><br><span class="line">import java.net.UnknownHostException;</span><br><span class="line"> </span><br><span class="line">public class InetAddressTest {</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) throws IOException {</span><br><span class="line"></span><br><span class="line">//以百度为例,生成Inetaddress对象</span><br><span class="line">//通过百度名:www.baidu.com获取对象</span><br><span class="line"></span><br><span class="line">InetAddress hosts=InetAddress.getByName("www.baidu.com");</span><br><span class="line"></span><br><span class="line">//打印hosts内容</span><br><span class="line">System.out.println("百度的地址为:"+hosts);</span><br><span class="line"></span><br><span class="line">//获取百度的主机名</span><br><span class="line">System.out.println("百度的主机名为:"+hosts.getHostName());</span><br><span class="line"></span><br><span class="line">//获取百度的原始ip地址</span><br><span class="line">System.out.println("百度的ip地址为:"+hosts.getHostAddress());</span><br><span class="line"></span><br><span class="line">//判断在3000ms内,百度是否允许访问</span><br><span class="line">System.out.println("3000ms内,百度是否允许访问:"+hosts.isReachable(3000));</span><br><span class="line"></span><br><span class="line">//InetAddress 的localhost()方法,都为获取本地的主机地址</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>运行结果:<br><img src="https://img-blog.csdnimg.cn/6cb1c6a91be44feeac6a9d0fba3858e5.png" alt="enter description here"><br>UDP相关知识点:</p><p>UDP:用户数据报协议,一种面向无连接,且只进行数据包发送,不进行确认的协议。</p><p>Java中进行UDP数据交互基本思路:</p><p>设置本主机发送数据包的端口和ip。类似于建立一个站点,用于接收和发送数据包。实际上,数据包的接收端主机地址是封装在数据包之中,本地主机设置的端口只需将数据包发送或者接收即可;<br>获取需要发送的数据包用户IP。相当于获取用户的地址信息,从而获知该将数据包发往何处。<br>接收端接收发送的数据包,并对数据包进行解析。接收端在设定的端口号接收数据包,接收之后可解析数据包。<br>理解:UDP数据包交互类似于收取快递一般,首先建立快递站,再将需要收取和发送的快递放到快递站,由此在交给指定用户。</p><p>相应方法:</p><p>UDP编程主要依赖于以下类:</p><p>DatagramSocket类:<br>作用:在本地主机设置端口,用于收发数据包,若无参数时,随机分配端口;可传入参数指定端口号。</p><p>相关方法:</p><p>Void Send(DatagramPacket val):用于发送数据包;</p><p>Void receive(DatagramPacket val):用于监听是否有数据包发送到本主机,若有则用val存储接收到的数据包。在其监听之时,会一直堵塞进程,直到有相应数据包传入(即不会执行该语句之后的代码块,直到有数据包传入)。可设置等待时间,超出该时间则结束程序。</p><p>DatagramPacket类。<br>作用:用来构造数据包对象,其中包含要发送的数据包和要接收的数据包。</p><p>若是发送数据包,需要包含发送的字节数组信息,以及要将多大的数据包进行发送,同时还要拥有接收方的ip地址和端口号。</p><p>若是接收数据包,需要包含用多大的字节数组接收数据包,同时要接收多大的数据包。</p><p>若是解析信息,需要注意传回数据包中数据的长度。(缓冲区的长度不一定等于传回信息的长度,故需要以传回的信息长度为读取的大小。)</p><p>InetAddress类。<br>作用:获取需要的主机地址。</p><p>UDP简易信息交互实例:</p><p>Server端代码:</p><figure class="highlight plaintext"><figcaption><span>java.io.IOException;</span></figcaption><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><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br></pre></td><td class="code"><pre><span class="line">import java.net.DatagramPacket;</span><br><span class="line">import java.net.DatagramSocket;</span><br><span class="line">import java.net.InetAddress;</span><br><span class="line">import java.net.SocketException;</span><br><span class="line">import java.util.Scanner;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">public class UDPServer {</span><br><span class="line"></span><br><span class="line">public static final int FIL_MAX=1024;</span><br><span class="line">public static final int PORT=8080;</span><br><span class="line">public static final int TIMES=8000;</span><br><span class="line">public DatagramSocket server;</span><br><span class="line">public DatagramPacket packet;</span><br><span class="line">public InetAddress address;</span><br><span class="line">public InetAddress reciveaddress; </span><br><span class="line">public int moPort;</span><br><span class="line">public int reviceport;</span><br><span class="line">public boolean marks;</span><br><span class="line">public Scanner in;</span><br><span class="line"></span><br><span class="line">//初始化信息方法</span><br><span class="line">public void init() {</span><br><span class="line">try {</span><br><span class="line"></span><br><span class="line">//创建标准I/O流</span><br><span class="line">in=new Scanner(System.in);</span><br><span class="line">//创建服务器端口</span><br><span class="line">server=new DatagramSocket(PORT);</span><br><span class="line">//设置服务器拥塞时间</span><br><span class="line">//server.setSoTimeout(TIMES);</span><br><span class="line">//设置默认的inetaddress对象</span><br><span class="line">address=InetAddress.getLocalHost();</span><br><span class="line">//设置默认端口</span><br><span class="line">moPort=9000;</span><br><span class="line">//设置接收端口默认值</span><br><span class="line">reviceport=-1;</span><br><span class="line">//设置信息接收数据包</span><br><span class="line">packet=new DatagramPacket(new byte[FIL_MAX],FIL_MAX);</span><br><span class="line">marks=true;</span><br><span class="line">System.out.println("初始化信息成功!");</span><br><span class="line">} catch (Exception e) {</span><br><span class="line"></span><br><span class="line">System.out.println("初始化信息失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//服务器运行方法</span><br><span class="line">public void ServerRun() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line">while(marks) {</span><br><span class="line"></span><br><span class="line">System.out.println("server等待接收信息....");</span><br><span class="line">//接收信息</span><br><span class="line"></span><br><span class="line">server.receive(packet);</span><br><span class="line">if(packet.getPort()!=0)</span><br><span class="line">{</span><br><span class="line">acceptMessage();</span><br><span class="line">askInfo();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">System.out.println("程序运行结束!");</span><br><span class="line">} catch (Exception e) {</span><br><span class="line"></span><br><span class="line">System.out.println("运行程序失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">//服务器接收方法</span><br><span class="line">public void acceptMessage() {</span><br><span class="line"></span><br><span class="line">//获取发送端主机地址信息</span><br><span class="line">reciveaddress=packet.getAddress();</span><br><span class="line">//获取发送端端口</span><br><span class="line">reviceport=packet.getPort();</span><br><span class="line">//获取发送的信息</span><br><span class="line">String message=new String(packet.getData(),0,packet.getLength());</span><br><span class="line">//获取发送端主机名</span><br><span class="line">String addressname=reciveaddress.getHostName();</span><br><span class="line">//输出信息</span><br><span class="line">System.out.println("接收到来自用户"+addressname+"的信息:"+message);</span><br><span class="line">}</span><br><span class="line">//服务器发送信息方法</span><br><span class="line">public void sendMessage() {</span><br><span class="line"></span><br><span class="line">System.out.println("请选择要发送的对象:1默认对象 2上一次接收用户的对象");</span><br><span class="line">int user=in.nextInt();</span><br><span class="line">InetAddress sendaddress=address;</span><br><span class="line">int ports=moPort;</span><br><span class="line">if(user==2) {</span><br><span class="line"></span><br><span class="line">if(reviceport==-1) {</span><br><span class="line">System.out.println("尚未接收到信息!");</span><br><span class="line">}</span><br><span class="line">else {</span><br><span class="line"></span><br><span class="line">sendaddress=address;</span><br><span class="line">ports=reviceport;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">System.out.println("请输入要发送的信息:");</span><br><span class="line">in.nextLine();</span><br><span class="line">String message=in.nextLine();</span><br><span class="line">byte[] info=message.getBytes();</span><br><span class="line">DatagramPacket packets=new DatagramPacket(info,info.length,sendaddress,ports);</span><br><span class="line">try {</span><br><span class="line">server.send(packets);</span><br><span class="line">System.out.println("信息发送成功!");</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">// TODO: handle exception</span><br><span class="line">System.out.println("信息发送失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void askInfo() {</span><br><span class="line"></span><br><span class="line">System.out.println("是否发送信息(over退出程序):Y/N");</span><br><span class="line">String choic=in.next();</span><br><span class="line">if(choic.equals("Y")) {</span><br><span class="line">sendMessage();</span><br><span class="line">}</span><br><span class="line">else if(choic.equals("over")) {</span><br><span class="line">server.close();</span><br><span class="line">marks=false;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">//创建测试对象</span><br><span class="line">UDPServer test=new UDPServer();</span><br><span class="line">test.init();</span><br><span class="line">test.ServerRun();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p> Client端代码:</p><figure class="highlight plaintext"><figcaption><span>java.net.DatagramPacket;</span></figcaption><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><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br></pre></td><td class="code"><pre><span class="line">import java.net.DatagramSocket;</span><br><span class="line">import java.net.InetAddress;</span><br><span class="line">import java.util.Scanner;</span><br><span class="line"> </span><br><span class="line">public class UDPClient {</span><br><span class="line"> </span><br><span class="line">public static final int FIL_MAX=1024;</span><br><span class="line">public static final int PORT=9000;</span><br><span class="line">public static final int TIMES=3000;</span><br><span class="line">public DatagramSocket client;</span><br><span class="line">public DatagramPacket packet;</span><br><span class="line">public InetAddress address;</span><br><span class="line">public InetAddress reciveaddress; </span><br><span class="line">public int moPort;</span><br><span class="line">public int reviceport;</span><br><span class="line">public Scanner in;</span><br><span class="line">public boolean marks;</span><br><span class="line">//初始化信息方法</span><br><span class="line">public void init() {</span><br><span class="line">try {</span><br><span class="line"></span><br><span class="line">//创建标准I/O流</span><br><span class="line">in=new Scanner(System.in);</span><br><span class="line">//创建服务器端口</span><br><span class="line">client=new DatagramSocket(PORT);</span><br><span class="line">//设置服务器拥塞时间</span><br><span class="line">//client.setSoTimeout(TIMES);</span><br><span class="line">//设置默认的inetaddress对象</span><br><span class="line">address=InetAddress.getLocalHost();</span><br><span class="line">//设置默认端口</span><br><span class="line">moPort=8080;</span><br><span class="line">//设置接收端口默认值</span><br><span class="line">reviceport=-1;</span><br><span class="line">//设置信息接收数据包</span><br><span class="line">packet=new DatagramPacket(new byte[FIL_MAX],FIL_MAX);</span><br><span class="line">marks=true;</span><br><span class="line">System.out.println("初始化信息成功!");</span><br><span class="line">} catch (Exception e) {</span><br><span class="line"></span><br><span class="line">System.out.println("初始化信息失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//服务器运行方法</span><br><span class="line">public void ClientRun() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line">while(marks) {</span><br><span class="line"></span><br><span class="line">System.out.println("client等待接收信息....");</span><br><span class="line">//接收信息</span><br><span class="line"></span><br><span class="line">client.receive(packet);</span><br><span class="line">if(packet.getPort()!=0) {</span><br><span class="line">acceptMessage();</span><br><span class="line">askInfo();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">System.out.println("程序运行结束!");</span><br><span class="line"></span><br><span class="line">} catch (Exception e) {</span><br><span class="line"></span><br><span class="line">System.out.println("运行程序失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">//服务器接收方法</span><br><span class="line">public void acceptMessage() {</span><br><span class="line"></span><br><span class="line">//获取发送端主机地址信息</span><br><span class="line">reciveaddress=packet.getAddress();</span><br><span class="line">//获取发送端端口</span><br><span class="line">reviceport=packet.getPort();</span><br><span class="line">//获取发送的信息</span><br><span class="line">String message=new String(packet.getData(),0,packet.getLength());</span><br><span class="line">//获取发送端主机名</span><br><span class="line">String addressname=reciveaddress.getHostName();</span><br><span class="line">//输出信息</span><br><span class="line">System.out.println("接收到来自用户"+addressname+"的信息:"+message);</span><br><span class="line">}</span><br><span class="line">//服务器发送信息方法</span><br><span class="line">public void sendMessage() {</span><br><span class="line"></span><br><span class="line">System.out.println("请选择要发送的对象:1默认对象 2上一次接收用户的对象");</span><br><span class="line">int user=in.nextInt();</span><br><span class="line">InetAddress sendaddress=address;</span><br><span class="line">int ports=moPort;</span><br><span class="line">if(user==2) {</span><br><span class="line"></span><br><span class="line">if(reviceport==-1) {</span><br><span class="line">System.out.println("尚未接收到信息!");</span><br><span class="line">}</span><br><span class="line">else {</span><br><span class="line"></span><br><span class="line">sendaddress=address;</span><br><span class="line">ports=reviceport;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">System.out.println("请输入要发送的信息:");</span><br><span class="line">in.nextLine();</span><br><span class="line">String message=in.nextLine();</span><br><span class="line">byte[] info=message.getBytes();</span><br><span class="line">DatagramPacket packets=new DatagramPacket(info,info.length,sendaddress,ports);</span><br><span class="line">try {</span><br><span class="line">client.send(packets);</span><br><span class="line">System.out.println("信息发送成功!");</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">// TODO: handle exception</span><br><span class="line">System.out.println("信息发送失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">//问讯信息控制</span><br><span class="line">public void askInfo() {</span><br><span class="line"></span><br><span class="line">System.out.println("是否发送信息(over退出程序):Y/N");</span><br><span class="line">String choic=in.next();</span><br><span class="line">if(choic.equals("Y")) {</span><br><span class="line">sendMessage();</span><br><span class="line">}</span><br><span class="line">else if(choic.equals("over")) {</span><br><span class="line">client.close();</span><br><span class="line">marks=false;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">//创建测试对象</span><br><span class="line">UDPClient test=new UDPClient();</span><br><span class="line">test.init();</span><br><span class="line">test.askInfo();</span><br><span class="line">test.ClientRun();</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>TCP交互</p><p>特点:tcp协议即传输控制协议,是一种面向连接的,可靠的具有安全性的通信协议。</p><p>Tcp协议分为服务器和客户端两部分,每次通信都需要服务器端先启动。</p><p>实现基本流程:</p><p>服务器端:</p><p>设置监听端口:设置一个监听端口,用于接收请求连接通信的客户端数据对象,彼此之间建立联系;</p><p>创建输入流:用来与客户端的输出流进行连接,实现数据读取;</p><p>创建输出流:用来与客户端的输入流进行连接,实现数据传输。</p><p>客户端:</p><p>设置socket对象,其中封装了本地的主机地址,欲要进行通信的服务器主机地址以及接收的端口号和数据等。</p><p>与服务器端相同,创建输入输出流。</p><p>主要的类:</p><p>ServerSocket类:用来创建服务器端的监听窗口。</p><p>Socket类:用来设置客户端和服务器的数据对象。</p><p>DataInputStream类:用来连接服务器和客户端的输入输出流。</p><p>DataOutputStream类:用来连接服务其和客户端的输出输入流。</p><p>注意实现:</p><p>ServerSocket类的Accept方法,用于监听是否有客户端连接,若一直未收到连接请求,将会始终处于阻塞状态,datainputstream中的read方法也会处于阻塞状态。因此若想实现服务器和客户端循环通信,需要将服务器的监听方法写在循环体外。</p><p>TCP实例代码:</p><p>服务器端:</p><figure class="highlight plaintext"><figcaption><span>java.io.DataInputStream;</span></figcaption><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><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line">import java.io.DataOutputStream;</span><br><span class="line">import java.io.IOException;</span><br><span class="line">import java.net.ServerSocket;</span><br><span class="line">import java.net.Socket;</span><br><span class="line">import java.util.Scanner;</span><br><span class="line"> </span><br><span class="line">public class SocketServer {</span><br><span class="line"></span><br><span class="line">private ServerSocket server;</span><br><span class="line">private final int PORT=8080;</span><br><span class="line">private Socket client;</span><br><span class="line">private DataOutputStream out;</span><br><span class="line">private DataInputStream in;</span><br><span class="line">private Scanner input;</span><br><span class="line">private void init() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line">//创建服务器监听端口</span><br><span class="line">server=new ServerSocket(PORT);</span><br><span class="line"></span><br><span class="line">//创建I/O输入输出流</span><br><span class="line">input=new Scanner(System.in);</span><br><span class="line">System.out.println("初始化信息成功!");</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">// TODO: handle exception</span><br><span class="line">System.out.println("初始化信息失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void sendMessage() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line"></span><br><span class="line">//连接客户端的输入流</span><br><span class="line">out=new DataOutputStream(client.getOutputStream());</span><br><span class="line">input.nextLine();</span><br><span class="line">String message=input.nextLine();</span><br><span class="line">out.writeUTF(message);</span><br><span class="line">System.out.println("发送成功!");</span><br><span class="line"></span><br><span class="line">} catch (IOException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println("发送信息失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void acceptMessage() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line">//连接客户端的输出流</span><br><span class="line">in=new DataInputStream(client.getInputStream());</span><br><span class="line">String message=in.readUTF();</span><br><span class="line">System.out.println("接收到来自"+client.getInetAddress().getHostName()+"的信息:"+message);</span><br><span class="line">System.out.println("请输入回信内容:");</span><br><span class="line">sendMessage();</span><br><span class="line">} catch (Exception e) {</span><br><span class="line"></span><br><span class="line">System.out.println("读取信息失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void ServerRun() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line"> System.out.println("Server等待接收信息...");</span><br><span class="line"> client=server.accept();</span><br><span class="line"> while(true) {</span><br><span class="line"> </span><br><span class="line"> acceptMessage();</span><br><span class="line"> System.out.println("是否退出程序?(y/n)");</span><br><span class="line"> String index=input.next();</span><br><span class="line"> if(index.equals("y")) {</span><br><span class="line"> </span><br><span class="line"> stopServer();</span><br><span class="line"> System.out.println("程序已关闭!");</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> System.out.println("Server等待接收信息...");</span><br><span class="line"> }</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">System.out.println("程序运行失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void stopServer() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line">in.close();</span><br><span class="line">out.close();</span><br><span class="line">server.close();</span><br><span class="line">input.close();</span><br><span class="line"></span><br><span class="line">} catch (IOException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println("程序关闭失败!");</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">SocketServer test=new SocketServer();</span><br><span class="line">test.init();</span><br><span class="line">test.ServerRun();</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>客户端代码:</p><figure class="highlight plaintext"><figcaption><span>java.io.DataInputStream;</span></figcaption><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><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line">import java.io.DataOutputStream;</span><br><span class="line">import java.io.IOException;</span><br><span class="line">import java.net.InetAddress;</span><br><span class="line">import java.net.Socket;</span><br><span class="line">import java.net.UnknownHostException;</span><br><span class="line">import java.util.Scanner;</span><br><span class="line"> </span><br><span class="line">public class SocketClient {</span><br><span class="line"></span><br><span class="line">private final int PORT=9000;</span><br><span class="line">private final int MOPORT=8080;</span><br><span class="line">private InetAddress address;</span><br><span class="line">private Socket client;</span><br><span class="line">private DataInputStream in;</span><br><span class="line">private DataOutputStream out;</span><br><span class="line">private Scanner input;</span><br><span class="line">private boolean marks=false;</span><br><span class="line">public void init() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line">address=InetAddress.getLocalHost();</span><br><span class="line">client=new Socket(address, MOPORT);</span><br><span class="line">in=new DataInputStream(client.getInputStream());</span><br><span class="line">out=new DataOutputStream(client.getOutputStream());</span><br><span class="line">input=new Scanner(System.in);</span><br><span class="line">System.out.println("信息初始化成功!");</span><br><span class="line">} catch (UnknownHostException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println("信息初始化失败!");</span><br><span class="line">System.out.println(e.getMessage());</span><br><span class="line">} catch (IOException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println("信息初始化失败!");</span><br><span class="line">System.out.println(e.getMessage());</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void sendMessage() {</span><br><span class="line">try {</span><br><span class="line">System.out.println("请输入要发送的内容:");</span><br><span class="line">input.nextLine();</span><br><span class="line">String message=input.nextLine();</span><br><span class="line">out.writeUTF(message);</span><br><span class="line">System.out.println("信息已发送!");</span><br><span class="line">} catch (IOException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println("信息写入失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void acceptMessage() {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line">String mesage=in.readUTF();</span><br><span class="line">System.out.println("收到来自"+client.getInetAddress().getHostName()+"的信息:"+mesage);</span><br><span class="line">sendMessage();</span><br><span class="line">} catch (Exception e) {</span><br><span class="line">System.out.println("获取信息失败!");</span><br><span class="line">System.out.println(e.getMessage());</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void stopClient() {</span><br><span class="line">try {</span><br><span class="line">in.close();</span><br><span class="line">out.close();</span><br><span class="line">input.close();</span><br><span class="line">} catch (IOException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println("程序关闭失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public void ClientRun() throws InterruptedException {</span><br><span class="line"></span><br><span class="line">while(true) {</span><br><span class="line">System.out.println("client....");</span><br><span class="line">System.out.println("是否查看信息?y/n (over退出程序)");</span><br><span class="line">String indexs=input.next();</span><br><span class="line">if(indexs.equals("y")) {</span><br><span class="line">if(marks) {</span><br><span class="line"></span><br><span class="line">acceptMessage();</span><br><span class="line">}</span><br><span class="line">else {</span><br><span class="line">System.out.println("未接收到信息,请发送信息!");</span><br><span class="line">marks=true;</span><br><span class="line">sendMessage();</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">else if(indexs.equals("over")) {</span><br><span class="line"></span><br><span class="line">stopClient();</span><br><span class="line">System.out.println("退出程序成功!");</span><br><span class="line">break;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">SocketClient test=new SocketClient();</span><br><span class="line">test.init();</span><br><span class="line">try {</span><br><span class="line">test.ClientRun();</span><br><span class="line">} catch (InterruptedException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println(e.getMessage());</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>URL学习</p><p>URL:资源定位符,即网络地址。</p><p>URL结构:protocol://host:port/path?query#fragment</p><p>protocol(协议)可以是 HTTP、HTTPS、FTP 和 File,host为主机名,port 为端口号,path为文件路径及文件名。</p><p>实例解析如下:<br>URL:<a href="http://www.baidu.com/index.html?language=cn#j2se">http://www.baidu.com/index.html?language=cn#j2se</a><br>URL 解析:</p><p>协议为(protocol):http</p><p>主机为(host:port):<a href="http://www.baidu.com/">www.baidu.com</a></p><p>端口号为(port): 80 ,以上URL实例并未指定端口,因为 HTTP 协议默认的端口号为 80。</p><p>文件路径为(path):/index.html</p><p>请求参数(query):language=cn</p><p>定位位置(fragment):j2se,定位到网页中 id 属性为 j2se 的 HTML 元素位置 。</p><p>URL有四种构造方法:</p><p>1.public URL(String protocol, String host, int port, String file) throws MalformedURLException.</p><p>通过给定的协议名称、主机号、端口号以及文件名称创建url对象。</p><p>2.public URL(String protocol, String host, String file) throws MalformedURLException。</p><p>此处未指明端口号,采用默认端口号:80</p><p>3.public URL(String url) throws MalformedURLException</p><p>通过给定的URL字符串创建URL.</p><p>4.public URL(URL context, String url) throws MalformedURLException</p><p>使用基地址和相对URL创建</p><p>注意:</p><p>若要获取URL对象的链接对象,可使用openConnection方法。</p><p>若协议为http,该方法返回 HttpURLConnection 对象</p><p>若协议为JAR 文件,该方法将返回 JarURLConnection 对象</p><p>…</p><p>针对不同的协议返回不同的URLConnect对象。</p><p>在得到的网页信息输出若有乱码,可通过如下方式解决:</p><p>BufferedReader input=new BufferedReader(new InputStreamReader(in,”utf-8”));</p><p>其中in是URLConnect返回的输入流对象(inputStream)。</p><p>其基本方法演示实例如下:</p><figure class="highlight plaintext"><figcaption><span>java.io.BufferedReader;</span></figcaption><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></pre></td><td class="code"><pre><span class="line">import java.io.IOException;</span><br><span class="line">import java.io.InputStream;</span><br><span class="line">import java.io.InputStreamReader;</span><br><span class="line">import java.net.URL;</span><br><span class="line">import java.net.URLConnection;</span><br><span class="line"> </span><br><span class="line">public class URLTest{</span><br><span class="line"></span><br><span class="line">public static void AnalyseWeb(URL webl) {</span><br><span class="line"></span><br><span class="line">System.out.println("未指明路径和文件名,输出URL信息如下:");</span><br><span class="line">System.out.println("解析对象:"+webl.toString());</span><br><span class="line">System.out.println("验证信息:"+webl.getAuthority());</span><br><span class="line">System.out.println("URL协议:"+webl.getProtocol());</span><br><span class="line">System.out.println("URL主机名:"+webl.getHost());</span><br><span class="line">System.out.println("URL端口号:"+webl.getPort());</span><br><span class="line">System.out.println("URL默认端口号:"+webl.getDefaultPort());</span><br><span class="line">System.out.println("URL文件名部分:"+webl.getFile());</span><br><span class="line">System.out.println("URL路径部分:"+webl.getPath());</span><br><span class="line">System.out.println("URL查询部分:"+webl.getQuery());</span><br><span class="line">System.out.println("获取引用:"+webl.getRef());</span><br><span class="line">System.out.println("连接url指定的网址对象...");</span><br><span class="line">ConnectWeb(webl);</span><br><span class="line">}</span><br><span class="line">public static void ConnectWeb(URL webc) {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line"></span><br><span class="line">URLConnection result=webc.openConnection();</span><br><span class="line">System.out.println("输出"+webc.toString()+"的URLConnect对象基本信息:");</span><br><span class="line">System.out.println("检索链接内容:"+result.getContent());</span><br><span class="line">System.out.println("返回头部 content-encoding 字段值:"+result.getContentEncoding());</span><br><span class="line">System.out.println("返回头部 content-length字段值:"+result.getContentLength());</span><br><span class="line">System.out.println("返回头部 content-type 字段值:"+result.getContentType());</span><br><span class="line">System.out.println("返回头部 last-modified 字段值:"+result.getLastModified());</span><br><span class="line">System.out.println("返回头部 expires 字段值:"+result.getExpiration());</span><br><span class="line">System.out.println("返回对象的 ifModifiedSince 字段值:"+result.getIfModifiedSince());</span><br><span class="line">System.out.println("返回 URLConnection 对象连接的URL:"+result.getURL());</span><br><span class="line">System.out.println("URLConnect对象的相关操作....");</span><br><span class="line">OperateURL(result);</span><br><span class="line"></span><br><span class="line">} catch (IOException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">System.out.println("获取URLConnections对象失败!");</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public static void OperateURL(URLConnection webo) {</span><br><span class="line"></span><br><span class="line">System.out.println("使用"+webo.getURL()+"的URLconnect对象进行资源读入与读出");</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line"></span><br><span class="line">//获取webo的输入流</span><br><span class="line">InputStream in=webo.getInputStream();</span><br><span class="line">BufferedReader input=new BufferedReader(new InputStreamReader(in,"utf-8"));</span><br><span class="line">char[] message=new char[512];</span><br><span class="line">int len=0;</span><br><span class="line">System.out.println("*******************输出读取到的信息如下*********************");</span><br><span class="line">while((len=input.read(message))!=-1) {</span><br><span class="line"></span><br><span class="line">System.out.println(String.valueOf(message));</span><br><span class="line">}</span><br><span class="line">} catch (IOException e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line">e.printStackTrace();</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">public static void main(String[] args) {</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line"></span><br><span class="line">//创建URL对象</span><br><span class="line">URL test=new URL("https://www.baidu.com");</span><br><span class="line">AnalyseWeb(test);</span><br><span class="line"></span><br><span class="line">} catch (Exception e) {</span><br><span class="line">// TODO Auto-generated catch block</span><br><span class="line"></span><br><span class="line">System.out.println(e.getMessage());</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>以上代码仅供参考,健壮性和正确性未充分验证。</p><p>部分资料可参考:<a href="https://blog.csdn.net/qq_45754762/article/details/111406474">java-网络编程之TCP、UDP简单交互</a></p>]]></content>
<summary type="html"><p>相关知识点:</p>
<p>Transient:Java中的关键字,只能修饰变量,不能修饰类和方法。</p>
<p>作用:使被修饰的变量无法被序列化。</p>
<p>拓展:一个静态变量,无论是否被transient修饰都无法被序列化。若静态变量反序列化得到相应的值,可能是由</summary>
</entry>
<entry>
<title>Java学习之集合框架</title>
<link href="http://example.com/2022/08/30/Java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/"/>
<id>http://example.com/2022/08/30/Java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/</id>
<published>2022-08-30T10:34:40.000Z</published>
<updated>2022-08-30T13:31:43.083Z</updated>
<content type="html"><![CDATA[<p>集合框架定义:集合框架是一个用来代表和操纵集合的统一架构。</p><p>集合框架结构图如下:<br><img src="https://img-blog.csdnimg.cn/902c9e318d494c1c86b0e215de1666bf.png" alt="enter description here"><br>图中最顶层包括(从左向右):迭代器、集合以及图。</p><p>集合框架一般包含:接口、实现、算法。</p><p>接口用于定义框架的结构和抽象数据类型,多接口可以实现以不同的方式操作集合对象。</p><p>实现:一个接口有多个实现类,本质上为可复用的数据结构。不同的实现类根据不同的场景而使用。</p><p>算法:是实现集合接口的对象里的方法执行的一些有用的计算。例如搜索和排序等方法,用于提高框架的性能,方法为多态,可进行复用。</p><p>Map不是集合,但是也包含在集合之中。<br><img src="https://img-blog.csdnimg.cn/c9e3cd8bf8c04da4a39eeedfc00cbe44.png" alt="enter description here"><br>集合框架中的接口描述:</p><p>Collection接口:Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。Collection 接口存储一组不唯一,无序的对象。</p><p>List 接口:有序的Collection接口。List 接口存储一组不唯一,有序(插入顺序)的对象。</p><p>Set接口:Set 接口存储一组唯一,无序的对象。</p><p>SortedSet:继承于Set保存有序的集合。</p><p>Map接口:存储一组键值对象,提供key(键)到value(值)的映射。</p><p>Map.Entry:描述在一个Map中的一个元素(键/值对)。是一个 Map 的内部接口。</p><p>SortedMap:继承于 Map,使 Key 保持在升序排列。</p><p>Enumeration:这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。</p><p>注意:</p><p>由于collection是一个接口,无法直接用于创建对象。</p><p>Collection下面有诸多子类继承或实现了其接口,故在创建对象时可以调用子类或实现类的构造方法。(类似于上转型)</p><p>List是collection的一个子类,其本身也为接口类型,无法用于创建对象。</p><p>List的实现类有:</p><p>(1)ArrayList(),该类是线程不安全类,其本身类是一个动态数组,取值操作很快,但是扩容时效率会下降。其并非可以无限增容,最大容量应为Integer的最大值。其中的排序算法sort源于Array中的TimSort二分归并排序方法。</p><p>(2)LinkedList(),该类也是线程不安全类,利用内部类Node为数据单元的双向链表。其具有读效率低,写效率高,操作效率高等特性,适合用于频繁add,remove等操作的List,同时可以节省一定的内存,在clear的情况下推荐使用GC回收,并且没有最大长度限制。</p><p>其最大的优势是删除时只需要做节点的移动,十分方便。</p><p>stack。最后一种为栈。<br>总结:</p><p>Java集合框架为程序员提供了预先包装的数据结构和算法来操纵他们。</p><p>集合是一个对象,可容纳其他对象的引用。集合接口声明对每一种类型的集合可以执行的操作。</p><p>集合框架的类和接口均在java.util包中。</p><p>任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换。</p>]]></content>
<summary type="html"><p>集合框架定义:集合框架是一个用来代表和操纵集合的统一架构。</p>
<p>集合框架结构图如下:<br><img src="https://img-blog.csdnimg.cn/902c9e318d494c1c86b0e215de1666bf.png" alt="enter</summary>
</entry>
<entry>
<title>java学习之数据结构</title>
<link href="http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
<id>http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/</id>
<published>2022-08-30T10:34:16.000Z</published>
<updated>2022-08-30T13:37:26.369Z</updated>
<content type="html"><![CDATA[<p><br>Java数据结构类型</p><p>Java数据结构包括Enumeration、BitSet、Vector、Stack、Dictionary、</p><p>Hashtable、Properties以及java2中引入的Collection共八种类型,</p><p>八种类型中包含了接口和类。</p><p>该八种类型分别对映:</p><p>枚举、位集合、向量、栈、字典、哈希表、属性以及框架-集合框架。</p><p>枚举(Enumeration)</p><p>其本质上为一个接口,其中定义了一些方法,通过这些方法可以枚举一个对象集合中的所有元素。已逐渐被迭代器所取代,在传统的一些方法中还保留该类型。</p><p>其主要方法有:</p><p>boolean hasMoreElements( ) : 测试此枚举是否包含更多的元素。</p><p>Object nextElement( ) : 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。</p><p>演示如下:</p><p><img src="https://img-blog.csdnimg.cn/07d6ee8a682747d99c6df1789208d7b1.png" alt="enter description here"></p><p>输出为:<br><img src="https://img-blog.csdnimg.cn/d1c5c1a9dbfd498490308ec332ad7c21.png" alt="enter description here"></p><p>注意事项:</p><p>Enumeration为接口类,其包括三个方法,nextElem返回值为泛型,其余两个方法中,有一个默认方法。</p><p>Enumeration中的默认方法为asIterator,其返回值为Iterator,特别注意的是,返回的元素是未遍历的元素集合,若元素在调用该方法时已经遍历结束,那么Iterator迭代器之中的元素集合为空。</p><p>位集合(BitSet)</p><p>位集合实现了一组可以单独设置和清除的位或标志。</p><p>位集合实现了Cloneable接口的方法。</p><p>其构造方式有两种,一种为不含参数的默认方法,另一种为含有整数值参数的构造方法,该整数值是为集合分配的初始大小,并且所有位初始化为0。</p><p>在第二种方式中,初始化的集合大小,其为64的整数倍,若设置的大小不是64的整数倍,则大小为大于设置大小的64的整数倍。</p><p>void and(BitSet set):位集合的与运算。</p><p>将两个bitset类型的位集合每一位进行与运算,只保留两个集合中都存在的数值。若集合中有某个参数与set位集合中不同,则清除。</p><p>void andNot(BitSet set):将存在与该集合中的数值都消除,只保留不相交的部分。</p><p>在bitset位集合中,空值则表示位false,若有数值存在,则真值为true,其余方法还有:</p><p>boolean equals(Object bitSet):将此对象与指定的对象进行比较。</p><p>void flip(int index):将指定索引处的位设置为其当前值的补码。</p><p>void flip(int startIndex, int endIndex):将指定的 fromIndex(包括)到指定的 toIndex(不包括)范围内的每个位设置为其当前值的补码。</p><p>boolean get(int index):返回指定索引处的位值。</p><p>boolean intersects(BitSet bitSet):如果指定的 BitSet 中有设置为 true 的位,并且在此 BitSet 中也将其设置为 true,则返回 true。</p><p>void or(BitSet bitSet):对此位 set 和位 set 参数执行逻辑或操作。</p><p>void xor(BitSet bitSet):对此位 set 和位 set 参数执行逻辑异或操作。</p><p>代码演示如下:</p><p><img src="https://img-blog.csdnimg.cn/fb0c09956b0a499390ea604b73949cc9.png" alt="enter description here"></p><p>输出为:</p><p><img src="https://img-blog.csdnimg.cn/35c075ca97164cbd91707548bcdb8bdd.png" alt="enter description here"></p><p>向量(vector)</p><p>Vector为一个类,其使用与数组极为相似,可通过下标进行索引。</p><p>其优势为创建对象时不需要设置大小,可根据需要,大小动态变化。</p><p>Vector具有同步访问的特点,包含许多传统的方法。</p><p>其一般用于事先不知道数组的大小,或者只需要一个可以改变大小的数组的情景即可。</p><p>Vector类有四种构造方法,分别为:</p><p>无参构造(Vector()):默认的大小为10;<br>含有一个参数(Vector(int size)):创建指定大小的向量;<br>含有两个参数(Vector(int size,int incr)):创建指定大小的向量,同时设置一个增量值,使向量每次以incr的大小增加空间。<br>包含集合的构造(Vector(Collection c)):创建一个包含集合c元素的向量。<br>Vector常用的方法有:</p><p>Void add(object c):将元素c添加到向量中。</p><p>Void add(int index,object element):在指定位置,添加元素。</p><p>Boolean addAll(collection c):将集合c中的所有元素,按照迭代器返回的顺序,添加到此向量的末尾。</p><p>void addElement(Object obj) :将指定的组件添加到此向量的末尾,将其大小增加 1。</p><p>int capacity() :返回此向量的当前容量。</p><p>void clear() :从此向量中移除所有元素。</p><p>Object clone() :返回向量的一个副本。</p><p>boolean contains(Object elem) :如果此向量包含指定的元素,则返回 true。</p><p>boolean containsAll(Collection c) :如果此向量包含指定 Collection 中的所有元素,则返回 true。</p><p>void copyInto(Object[] anArray) :将此向量的组件复制到指定的数组中。</p><p>Object elementAt(int index) :返回指定索引处的组件。</p><p>Enumeration elements() :返回此向量的组件的枚举。</p><p>void ensureCapacity(int minCapacity) :增加此向量的容量(如有必要),以确保其至少能够保存最小容量参数指定的组件数。</p><p>boolean equals(Object o) :比较指定对象与此向量的相等性。</p><p>int indexOf(Object elem) :返回此向量中第一次出现的指定元素的索引,如果此向量不包含该元素,则返回 -1。</p><p>int indexOf(Object elem, int index) :返回此向量中第一次出现的指定元素的索引,从 index 处正向搜索,如果未找到该元素,则返回 -1。</p><p>void insertElementAt(Object obj, int index) :将指定对象作为此向量中的组件插入到指定的 index 处。</p><p>Object lastElement() :返回此向量的最后一个组件。</p><p>int lastIndexOf(Object elem) :返回此向量中最后一次出现的指定元素的索引;如果此向量不包含该元素,则返回 -1。</p><p>Object remove(int index) : 移除此向量中指定位置的元素。</p><p>boolean remove(Object o) :移除此向量中指定元素的第一个匹配项,如果向量不包含该元素,则元素保持不变。</p><p>boolean removeAll(Collection c) :从此向量中移除包含在指定 Collection 中的所有元素。</p><p>部分方法演示如下:</p><p><img src="https://img-blog.csdnimg.cn/d7bba033952349c5a4fb7b12cc9472c5.png" alt="enter description here"></p><p>输出结果为:</p><p><img src="https://img-blog.csdnimg.cn/7ea9b39f196d4594a1571fac19cb2f96.png" alt="enter description here"></p><p>栈(stack)</p><p>栈实现了栈内元素先进后出,后进先出的顺序。</p><p>栈类似于对象垂直放置的数组。</p><p>Stack继承了vector类,是vector类的一个子类,故stack具有vector类的所有方法,</p><p>同时,stack类还定义了自己的一些方法。</p><p>Stack只有一个默认的无参构造方法,其实质是系统的储存器为所创建的对象分配一个堆栈。</p><p>其自定义的主要方法如下:</p><p>boolean empty() :测试堆栈是否为空。</p><p>Object peek( ):查看堆栈顶部的对象,但不从堆栈中移除它。</p><p>Object pop( ):移除堆栈顶部的对象,并作为此函数的值返回该对象。</p><p>Object push(Object element):把项压入堆栈顶部。</p><p>int search(Object element):返回对象在堆栈中的位置,以 1 为基数。</p><p>实际演示如下:</p><p><img src="https://img-blog.csdnimg.cn/b84a95be9d1442a38fb9eda0ce8c3d53.png" alt="enter description here"></p><p>输出结果如下:</p><p><img src="https://img-blog.csdnimg.cn/6ceae9fcdf3d43d3a51de641c16944b9.png" alt="enter description here"></p><p>字典类(dictionary)</p><p>字典类是一个抽象类,它定义了一个键映射到值的数据结构。</p><p>字典类实际已经不符合需求而被Map所取代。</p><p>字典类中定义的抽象方法如下:</p><p>Enumeration elements( ):返回此 dictionary 中值的枚举。</p><p>Object get(Object key):返回此 dictionary 中该键所映射到的值。</p><p>boolean isEmpty( ):测试此 dictionary 是否不存在从键到值的映射。</p><p>Enumeration keys( ):返回此 dictionary 中的键的枚举。</p><p>Object put(Object key, Object value):将指定 key 映射到此 dictionary 中指定 value。</p><p>Object remove(Object key):从此 dictionary 中移除 key (及其相应的 value)。</p><p>int size( ):返回此 dictionary 中条目(不同键)的数量。</p><p>注意:</p><p>Hashtable<K,V>类继承了dictionary类,并且实现了Map<K,V>, Cloneable, java.io.Serializable三个接口。</p><p>实际演示如下:</p><p><img src="https://img-blog.csdnimg.cn/0d6caf5f57b840eaaea2ef2442c2e686.png" alt="enter description here"></p><p>输出为:</p><p><img src="https://img-blog.csdnimg.cn/b0baf0bf2be04d659a2f4296ca6c6e8a.png" alt="enter description here"></p><p>哈希表(Hashtable)</p><p>Hashtable是原始java.util的一部分,其是dictionary类的具体实现。</p><p>Java2中实现了Map接口,现在被加入到集合框架之中,和hashmap类很相似,但是他支持同步。(哈希表的键是经过哈希函数变换后得到的散列码)</p><p>其构造方式有四种,分别为:</p><p>1.无参构造:Hashtable()</p><p>2.初始化哈希表的大小:Hashtable(int size);</p><p>3.初始化哈希表的大小,并且使用fillRation填充指定比例,填充比例介于0.0-1.0之间:Hashtable(int size,float fillRation);</p><p>4.使用map集合中的元素作为初始元素构造哈希表:Hashtable(Map M)。</p><p>其方法的部分演示如下:</p><p><img src="https://img-blog.csdnimg.cn/fc318384ca754134a8bc0f1ea9dd6ac1.png" alt="enter description here"></p><p>输出结果为:</p><p><img src="https://img-blog.csdnimg.cn/aaf3ded8794c43a2913518eb1b59bccd.png" alt="enter description here"></p><p>其余方法有:</p><p>Enumeration elements( ):返回此哈希表中的值的枚举。</p><p>boolean isEmpty( ):测试此哈希表是否没有键映射到值。</p><p>Enumeration keys( ):返回此哈希表中的键的枚举。</p><p>void rehash( ):增加此哈希表的容量并在内部对其进行重组,以便更有效地容纳和访问其元素。</p><p>String toString( ):返回此 Hashtable 对象的字符串表示形式,其形式为 ASCII 字符 “, “ (逗号加空格)分隔开的、括在括号中的一组条目。</p><p>Object clone( ):创建此哈希表的浅表副本。</p><p>属性(Properties)</p><p>Properties 继承于 Hashtable.Properties 类表示了一个持久的属性集.属性列表中每个键及其对应值都是一个字符串。</p><p>Properties默认拥有一个实例变量:Properties defaults;该对象为默认持有一个属性列表。</p><p>其有两种构造方法:</p><p>无参构造:Properties();<br>设置默认值的构造方法:Properties(Properties propDefault)。<br>两种构造方法属性列表都为空。</p><p>Properties继承于hashtable,故拥有所有hashtable所定义的方法。除此之外</p><p>其余一些方法有:</p><p>String getProperty(String key):用指定的键在此属性列表中搜索属性。</p><p>String getProperty(String key, String defaultProperty):用指定的键在属性列表中搜索属性。</p><p>void list(PrintStream streamOut):将属性列表输出到指定的输出流。</p><p>void list(PrintWriter streamOut):将属性列表输出到指定的输出流。</p><p>PrintWriter,与PrintStream相似,实现了PrintStream中的所有 print 方法。PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter类。</p><p>void load(InputStream streamIn) throws IOException:从输入流中读取属性列表(键和元素对)。</p><p>Enumeration propertyNames( ):按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)</p><p>Object setProperty(String key, String value):调用 Hashtable 的方法 put。</p><p>void store(OutputStream streamOut, String description):以适合使用 load(InputStream)方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。</p><p>实际代码演示如下:<br><img src="https://img-blog.csdnimg.cn/1e80cabe56754253918e4879b80311e0.png" alt="enter description here"></p><p>输出结果为:</p><p><img src="https://img-blog.csdnimg.cn/a7ffeb32ab3d45b3a7cfee58f255b97c.png" alt="enter description here"></p><p></p>]]></content>
<summary type="html"><p><br>Java数据结构类型</p>
<p>Java数据结构包括Enumeration、BitSet、Vector、Stack、Dictionary、</p>
<p>Hashtable、Properties以及java2中引入的Collection共八种类型,</p>
<</summary>
</entry>
<entry>
<title>java学习之LinkedList</title>
<link href="http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8BLinkedList/"/>
<id>http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8BLinkedList/</id>
<published>2022-08-30T10:33:00.000Z</published>
<updated>2022-08-30T13:17:57.684Z</updated>
<content type="html"><![CDATA[<p>LinkedList:一种线性表,但不按照线性顺序存储数据(实际上为链表)。</p><p>链表分为单向链表和双向链表,实际应当还有循环链表。</p><p>单向链表:将一个区域分成两部分,分别为节点区域和数据域。</p><p>如下图所示:<br><img src="https://img-blog.csdnimg.cn/5b6b22852fe846478f2536a813978fcb.png" alt="enter description here"><br>双向链表:设置两个节点指针,使其指向前驱和后继节点,前驱表示指向它的节点,后继表示它指向的节点。<br><img src="https://img-blog.csdnimg.cn/e579d35774de4ae3b7cacf5c5bbf9a4d.png" alt="enter description here"><br>Linkedlist和arraylist使用方式类似,但二者执行不同操作时效率不同。</p><p>Arraylist查找和修改的效率要高,增加和删除的效率较低,linkedlist正好与之相反。</p><p>以下情况使用 ArrayList :</p><p>频繁访问列表中的某一个元素。</p><p>只需要在列表末尾进行添加和删除元素操作。</p><p>以下情况使用 LinkedList :</p><p>你需要通过循环迭代来访问列表中的某些元素。</p><p>需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。</p><p>LinkedList 继承了 AbstractSequentialList 类。</p><p>LinkedList 实现了 Queue 接口,可作为队列使用。</p><p>LinkedList 实现了 List 接口,可进行列表的相关操作。</p><p>LinkedList 实现了 Deque 接口,可作为队列使用。</p><p>LinkedList 实现了 Cloneable 接口,可实现克隆。</p><p>LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。</p><p>Linkedlist有两个构造方法,分别为无参构造和以集合为参数进行构造。</p><p>简单代码演示如下:<br><img src="https://img-blog.csdnimg.cn/fdca03b8904e49289f7ad6797315e52d.png" alt="enter description here"><br>输出结果为:<br><img src="https://img-blog.csdnimg.cn/aa833520c5994e299632309a05c9f263.png" alt="enter description here"><br>Linkedlist其他常用方法如下:<br><img src="https://img-blog.csdnimg.cn/5521f676b24a452da2f852446bc82048.png" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/32b5178bd9b64580813a158ea620a924.png" alt="enter description here"><br>更多相关方法可参考:<a href="https://www.runoob.com/manual/jdk11api/java.base/java/util/LinkedList.html">LinkedList</a></p>]]></content>
<summary type="html"><p>LinkedList:一种线性表,但不按照线性顺序存储数据(实际上为链表)。</p>
<p>链表分为单向链表和双向链表,实际应当还有循环链表。</p>
<p>单向链表:将一个区域分成两部分,分别为节点区域和数据域。</p>
<p>如下图所示:<br><img src="ht</summary>
</entry>
<entry>
<title>Java学习之HashSet</title>
<link href="http://example.com/2022/08/30/Java%E5%AD%A6%E4%B9%A0%E4%B9%8BHashSet/"/>
<id>http://example.com/2022/08/30/Java%E5%AD%A6%E4%B9%A0%E4%B9%8BHashSet/</id>
<published>2022-08-30T10:32:31.000Z</published>
<updated>2022-08-30T13:20:10.984Z</updated>
<content type="html"><![CDATA[<p>Hashset基于HashMap而实现。</p><p>特点:</p><p>不允许有重复的值出现;<br>存储数据是无序的;<br>可以保存null值;<br>线程是不安全的。<br>线程安全与不安全的区别:</p><p>若线程不安全,则多个线程对同一共享数据进行修改时,数据的最终结果是不确定的,只能由最后一次修改的线程所确定;</p><p>若线程安全,则可以保证数据的一致性,但由于线程安全,需要增加事务回滚和判定操作,所以速度较慢。</p><p>Hashset实现了set接口。</p><p>Hashset一般方法代码演示如下:<br><img src="https://img-blog.csdnimg.cn/aec189699d0840d0b0e8eb070de32929.png" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/cb837e7c06514d2c9c113204144e6390.png" alt="enter description here"><br>输出结果为:<br><img src="https://img-blog.csdnimg.cn/7c7f4b305c664a7298f343b877ff84ee.png" alt="enter description here"><br>注意事项:</p><p>Hashset是继承于HashMap,故其类似于套壳集合。</p><p>Hashet没有可以获取值的方法,若想获取某个值,只能先判定欲获取的值在不在集合中。</p><p>Hashset只能用迭代器或foreach进行遍历,foreach遍历时,需要保证替换元素与集合的类型相同。<br>详细内容:<a href="https://www.cnblogs.com/LiaHon/p/11257805.html">Java集合 HashSet的原理及常用方法 - 工匠初心 - 博客园</a></p>]]></content>
<summary type="html"><p>Hashset基于HashMap而实现。</p>
<p>特点:</p>
<p>不允许有重复的值出现;<br>存储数据是无序的;<br>可以保存null值;<br>线程是不安全的。<br>线程安全与不安全的区别:</p>
<p>若线程不安全,则多个线程对同一共享数据进行修改时</summary>
</entry>
<entry>
<title>java学习之HashMap</title>
<link href="http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8BHashMap/"/>
<id>http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8BHashMap/</id>
<published>2022-08-30T10:32:07.000Z</published>
<updated>2022-08-30T13:32:57.902Z</updated>
<content type="html"><![CDATA[<p>HashMap</p><p>定义:散列表,存储的内容是一个键值对的映射。是Map接口的实现类。</p><p>原理:根据键的hashcode值存储数据,具有很快的访问速度,最多允许一条记录的键值为null,不支持线程同步,其记录数据是无序的,即不记录插入顺序。</p><p>相关内容引入:</p><p>HashCode:根据一个规则(哈希函数),为即将存入的数据分配一个地址,若该地址不存在如何数据,直接使用该地址,否则调用equals方法比较二者是否相同,若相同,则不存入该地址,不相同则散列其他地址。(hashmap的具体实现中,会使用一个table来保存已经存入的hashcode数值,若表中没有则直接存入数据,若table中存在hashcode,则调用equals进行比较。)</p><p>需要注意:若equals得到的结果为true,则表明比较的两个元素hashcode相等,若得到的结果为false,比较的两个元素hashcode不一定不相等。</p><p>特点:</p><p>HashMap中的键值类型可以相同也可以不同,但是声明都只能是语言的包装类。<br>相关方法的代码演示如下:<br><img src="https://img-blog.csdnimg.cn/bd270edc18854f19889943f4f8e35433.png" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/a8ee725bd5fb48f68366e642286f8566.png" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/406686659db44d8093cfff31febbf0de.png" alt="enter description here"><br>输出结果为:<br><img src="https://img-blog.csdnimg.cn/ee63a1284e2e4948b78b6a4428c12430.png" alt="enter description here"><br>相关参考:<a href="https://blog.csdn.net/woshimaxiao1/article/details/83661464">Java集合之一—HashMap_woshimaxiao1的博客-CSDN博客_hashmap</a></p>]]></content>
<summary type="html"><p>HashMap</p>
<p>定义:散列表,存储的内容是一个键值对的映射。是Map接口的实现类。</p>
<p>原理:根据键的hashcode值存储数据,具有很快的访问速度,最多允许一条记录的键值为null,不支持线程同步,其记录数据是无序的,即不记录插入顺序。</p>
<</summary>
</entry>
<entry>
<title>java学习之iteraor、泛型、object、序列化</title>
<link href="http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8Biteraor%E3%80%81%E6%B3%9B%E5%9E%8B%E3%80%81object%E3%80%81%E5%BA%8F%E5%88%97%E5%8C%96/"/>
<id>http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8Biteraor%E3%80%81%E6%B3%9B%E5%9E%8B%E3%80%81object%E3%80%81%E5%BA%8F%E5%88%97%E5%8C%96/</id>
<published>2022-08-30T10:31:35.000Z</published>
<updated>2022-08-30T13:14:27.527Z</updated>
<content type="html"><![CDATA[<p>Object类</p><p>定义:Object是所有类的父类,java中的所有类都继承于Object类,即java中的所有类都可以使用Object类的方法和非私有属性。</p><p>特点:</p><p>继承有显式继承和隐式继承,其中隐式继承指一个类未指明父类的情况下,默认继承Object类。</p><p>Java泛型</p><p>定义:java泛型是jdk5中新引入的特性。泛型提供了编译时类型检测安全机制,该机制允许编程的代码编译时可以检测非法数据类型。</p><p>特点:</p><p>泛型类似于占位符作用。在不确定参数类型的清况下,可以使用泛型声明数据,在调用具体数据时,在为数据进行数据类型声明;<br>泛型使用时只能使用引用数据类型,不支持原始类型的声明。<br>使用情景:若一个方法可以接受多种数据类型参数,此时可以使用泛型声明数据类型,在使用时引入相应引用数据类型即可。</p><p>泛型的使用方法:</p><p>所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前。</p><p>每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。</p><p>类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。</p><p>Java中的泛型标记:</p><p>E - Element (在集合中使用,因为集合中存放的是元素)</p><p>T - Type(Java 类)</p><p>K - Key(键)</p><p>V - Value(值)</p><p>N - Number(数值类型)</p><p>? - 表示不确定的 java 类型</p><p>有界的类型参数:</p><p>定义:限制泛型的范围,即约束泛型声明的变量或返回值只能在那几个数据类型中被使用。</p><p>使用方法:要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。</p><p>泛型类:</p><p>泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。</p><p>和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。</p><p>类通配符</p><p>类型通配符一般是使用 ? 代替具体的类型参数。例如 List<?> 在逻辑上是 List<String>,List<Integer> 等所有 List<具体类型实参> 的父类。<br>类型通配符上限通过形如List来定义,如此定义就是通配符泛型值接受Number及其下层子类类型。<br>类型通配符下限通过形如 List<? super Number> 来定义,表示类型只能接受 Number 及其上层父类类型,如 Object 类型的实例。</p><p>序列化</p><p>定义:</p><p>Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。</p><p>原理:</p><p>将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。</p><p>整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。</p><p>类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。</p><p>ObjectOutputStream 类包含很多写方法来写各种数据类型</p><p>注意:</p><p>public final void writeObject(Object x) throws IOException:序列化一个对象,并将它发送到输出流。</p><p>public final Object readObject() throws IOException, ClassNotFoundException:该方法从流中取出下一个对象,并将对象反序列化。它的返回值为Object,因此,你需要将它转换成合适的数据类型。</p><p>一个类的对象序列化成功必须具备以下条件:</p><p>该类必须实现 java.io.Serializable 接口。</p><p>该类的所有属性必须是可序列化的。</p><p>一个Java标准类能否被序列化,只需要检查该类是否实现java.io.Serializable接口。</p><p>迭代器相关方法和应用代码演示如下:<br><img src="https://img-blog.csdnimg.cn/ff30171cdef040e7a48b6d20e0bfb844.png" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/b85ede964529424da3f6e901c6acec8c.png" alt="enter description here"><br>运行结果如下:<br><img src="https://img-blog.csdnimg.cn/33de02702d254fed98a9241c040405bb.png" alt="enter description here"><br>泛型代码演示如下:<br><img src="https://img-blog.csdnimg.cn/0b07d50addba420f963ad5b9ceda677d.png" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/bc5f59683cd841568dca8f5a35a8f573.png" alt="enter description here"><br>运行结果为:<br><img src="https://img-blog.csdnimg.cn/9429d38e4e8b437eb7160f91f6f895e3.png" alt="enter description here"><br>序列化代码演示如下:<br><img src="https://img-blog.csdnimg.cn/7d7a9f65ddbc4fdd8c9d4783f924e909.png" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/898a2becdaf349a2bb43474e3aee6f0f.png" alt="enter description here"></p><p>输出结果为:<br><img src="https://img-blog.csdnimg.cn/af2bfb986b184156b54938965d4ccab9.png" alt="enter description here"><br>总结:</p><p>序列化中的最高数据流为ObjectOutputStream和ObjectInputStream两个方法,其中两个方法包含了众多的输出和输入流对象方法。</p><p>在使用序列化时,需要将文件后缀命名为.ser,同时被序列化的对象必须是Serialzeable的实现类。</p><p>反序列化对象时,需要指明对象的类型,进行类型转换。</p>]]></content>
<summary type="html"><p>Object类</p>
<p>定义:Object是所有类的父类,java中的所有类都继承于Object类,即java中的所有类都可以使用Object类的方法和非私有属性。</p>
<p>特点:</p>
<p>继承有显式继承和隐式继承,其中隐式继承指一个类未指明父类的情况下,</summary>
</entry>
<entry>
<title>java学习之面向对象</title>
<link href="http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/"/>
<id>http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</id>
<published>2022-08-30T10:30:22.000Z</published>
<updated>2022-08-30T13:22:17.450Z</updated>
<content type="html"><![CDATA[<h5 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h5><p>继承是指提取不同类的相同属性和方法,使之组成新的类,令拥有此方法和属性的类继承于新形成的类,即父类。(继承关系如下图所示)<br><img src="https://img-blog.csdnimg.cn/2f23db4df0ef436eb4e0a0fe70a440c8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>由此可知,继承具有单一性,一个子类只能继承一个父类,一个父类可以有多个子类。</p><p>继承的关键字有extends和implements。<br>子类可以重写父类的方法,增加新的属性,但是父类中用private声明的属性和方法不能被子类继承,同时,final修饰的类不能被继承,final类中的属性和方法不一定为final类型。<br>子类中可以使用super访问父类的方法和属性,使用this定位自身。<br>继承具有多重性,如图所示:<br><img src="https://img-blog.csdnimg.cn/42f07eea77554aeb97c0aff37eada835.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>Java中继承的多重性区别于c++中。</p><p>Java中implements可以有多个继承类(实际该implements为实现类,用于实现接口中的抽象方法),其用“,”分隔。如public class C implements A,B{}</p><p>继承的优点:实现代码复用,降低代码冗余。<br>缺点:类与类之间紧密联系,提高了代码的耦合。</p><p>关于构造器:子类不继承父类的构造器。<br>继承归属于java.lang包,故不需要声明使用。Object默认为所有不指明继承关系类的父类,即祖先类。<br><img src="https://img-blog.csdnimg.cn/d78a47aaca074776856c037f875764b4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>Java语言建立需要继承的类时,若为同一个类文件中,则需要将被继承的类定义在公共类之外。<br>继承时,子类的无参构造函数会自动调用父类的无参构造函数。</p><h6 id="向上转型与向下转型"><a href="#向上转型与向下转型" class="headerlink" title="向上转型与向下转型"></a>向上转型与向下转型</h6><p>向上转型:子类转向父类,即利用子类构造对象,却当作父类来使用。<br>如:Animal dog=new dog();</p><p>由小范围转向大范围,同时一定要注意转型是安全的。</p><p>向下转型:将父类转换为对应的子类(类似与强制类型转换)。要求父类原来就是子类转换而来,所以向下转型是一个还原的动作。</p><p>如:Dog dogs=(Dog)dog;若类型不同,程序会报错。</p><p>向上转型成功后,对象无法调用子类特有的方法和属性,只能向下转型以后才能调用。</p><p>例子:USB接口,就是通过判断插入的为什么类型的子类,从而将接口下转型为对应子类。</p><p>判断是否为某一类子类可使用instanceof方法,boolean-class</p><h6 id="重写与重载"><a href="#重写与重载" class="headerlink" title="重写与重载"></a>重写与重载</h6><p> 重写:子类对父类允许访问的方法,保持方法名和参数类型、数量不变,对核心代码进行重写(外壳不变,核心重写);</p><p>重写注意:若父类中抛出异常,则子类中若存在异常,只能为父类中异常的子类或者父类中的异常,不能检测出父类异常的父类。</p><p>如:父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,抛出 IOException 异常或者 IOException 的子类异常。</p><p>注意事项:<br>方法重写后,返回类型可以与原来的方法不同,但是必须是父类返回值的派生类。<br>方法重写其访问权限不能低于被重写的方法的访问权限。<br>父类的成员方法只能被子类所重写,final修饰的方法不能别重写,static修饰的方法也不能被重写,但是可以被重新声明<br>构造方法不能被重写。</p><p>重载:在同一个类中,方法名相同,参数不同,返回值类型可以不同也可以相同。</p><p>重载的方法都必须有一个独一无二的参数列表</p><p>被重载的方法必须改变参数列表,返回值类型可以修改,访问权限也可以修改,可以抛出新的异常或者更高权限的异常,同一个类或者子类中可以重载方法,无法以返回值类型判断方法的重载。</p><p>方法的重载是一个类多态的体现,方法的重写是父类与子类之间一种多态的体现。 </p><p>多态<br>解释:同一种行为有多个不同的表现形式或形态的能力。</p><p>多态就是同一个接口,使用不同的实例执行不同的操作。</p><p>优点:灵活,降低类型耦合,可替换,可扩充,接口性。</p><p>虚函数:</p><p>在java中,上转型对象在调用经子类重写后的方法时,验证时使用父类的方法验证,但JVM调用时使用子类的该方法。</p><p>虚函数的存在就是为了多态。</p><p>总结:多态有多种形式,但是其本质通俗而言就是定义未实现的方法,通过需要在后续继承类中或者实现方法中将其根据不同需要实现。最易理解的例子就是USB插口,其本质就是多态的运用。</p><p>抽象类<br>定义:对象都是用类进行描述,但是并非所有的类都是用来描述对象的,如果类中没有包含足够的信息来描述具体的实例对象,这样的类就称之为抽象类。</p><p>抽象类与普通类的区别在于,其不能实例化对象,除此以外,和普通类没有其他区别。</p><p>由抽象类的特性可知,抽象类只能通过继承实现。一个类只能继承一个父类,但是一个类可以继承多个接口。</p><p>抽象类不一定含有抽象方法,含有抽象方法的一定是抽象类。</p><p>任何子类都必须重写父类中的抽象方法,或者声明自身为抽象类。</p><p>抽象类和抽象方法通过abstract定义。</p><p>如以下例子:<br><img src="https://img-blog.csdnimg.cn/e978eae5f3c846008985815dabf6d303.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>输出为:<br><img src="https://img-blog.csdnimg.cn/3fbe89f758be42898cb21712b1f15c86.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_14,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"></p><p>封装<br>定义:对类的方法和属性进行隐藏,即对外部用户隐藏类的某些属性值或者成员方法的实现细节。</p><p>通俗理解,通过设定方法和属性的访问权限,增加相应的操作方法,使程序调用该类时,通过其设定的内部方法对属性值进行操作等。</p><p>优点:在修改时,可以修改对应类的内部结构和方法,不需要修改调用此方法的程序。</p><p>运用恰当可以降低耦合。</p><p>接口<br>定义:抽象方法的集合,是一个抽象类型。</p><p>接口无法实例化对象,并且接口不包含成员变量,变量需要使用static和final来修饰。即变量类型只能为public static final修饰。</p><p>接口使用类来实现,实现接口的类必须实现接口中的所有抽象方法,若未能实现所有方法,则只能定义为抽象类。</p><p>Java中可以使用接口来声明一个接口类型的变量,它们可以成为一个空指针,或者绑定在此接口的一个实现类上。</p><p>接口中的方法必须都为抽象方法,接口支持多继承,接口中没有构造方法。</p><p>接口中的方法不声明访问权限会默认为public abstract,同时接口中的方法修饰也只能如此。变量则只能为public static final。</p><p>接口中的方法无法在接口内实现,只能在实现接口的类中实现。<br>Jdk1.8版本以后的变化:</p><p>接口中允许包含静态方法和方法体。</p><p>接口中可以包含实现方法,该方法称为默认方法,使用default来修饰。</p><p>Jdk1.9版本后变化:</p><p>允许将方法定义为 private,使得某些复用的代码不会把方法暴露出去。</p><p>接口声明格式:</p><p>[可见度] interface 接口名称 [extends 其他的接口名] {</p><p> // 声明变量//声明抽象方法</p><p> }</p><p>注意:</p><p>接口中的方法和变量都是隐式抽象,不需要完整声明。</p><p>在java9之前,接口中的方法只能为public权限,java9之后可以使用private修饰。</p><p>接口必须定义在自己的文件之中</p><p><img src="https://img-blog.csdnimg.cn/aab70768f13c494f94dce26939c3bb2a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/78a8dfc4027f4ce7bbf45f0ccbcdcabb.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>调用静态成员方法时,需要使用类名.方法名直接调用</p><p>创建接口变量时,可以创建空指针,但是在使用的时候,需要指明其实现类,不能使用空指针调用方法。</p><p>接口的继承:</p><p>接口的继承与类的继承类似,一个接口可以继承另一个接口,使用关键字extends定义</p><p>同时接口可以实现多继承,即一个接口可以继承多个接口。</p><p>标记接口:</p><p>没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:<br>1.建立一个公共的父接口:</p><p>正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。</p><p>2.向一个类添加数据类型:</p><p>这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。<br>枚举<br>Java中的枚举本质上也为一个类,但是其是特殊类。一般用于表示常量。可在内部和外部中定义枚举类。</p><p>其格式为:</p><p>enum [类名]{[值],[值],…[值];}</p><p>中间使用“,”号分隔。</p><p>简单使用为类名.值的方式。</p><p>若使用变量接受枚举值,那么需要使用枚举类名进行定义。<br>如:<br><img src="https://img-blog.csdnimg.cn/d12ade6ffdfb44a9b1c30cd909a4dd8a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>枚举值的声明定义都是public static final类型。</p><p>枚举的值也可以通过foreach进行迭代。</p><p>枚举中有三个方法values(), ordinal() 和 valueOf() 方法,都位于 java.lang.Enum 类中</p><p>其主要作用有:</p><p>values() 返回枚举类中所有的值。</p><p>ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。</p><p>valueOf()方法返回指定字符串值的枚举常量。<br>枚举类的成员:</p><p>枚举跟普通类一样可以用自己的变量、方法和构造函数,构造函数只能使用 private 访问修饰符,所以外部无法调用。</p><p>枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。</p><p>需要注意:</p><p>枚举类型的构造方法,在初始化每个枚举值的时候才能自动调用,外部不可调用。</p><p>如下:<br><img src="https://img-blog.csdnimg.cn/4b8415e8e11848cfa26f980a87fb699f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_20,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br><img src="https://img-blog.csdnimg.cn/b89853d0096243658b370f355c02e601.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_19,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>输出如下:<br><img src="https://img-blog.csdnimg.cn/28b35a47542a4bf398e216413cd2ce55.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWF4oCm6YeM,size_13,color_FFFFFF,t_70,g_se,x_16" alt="enter description here"><br>包<br>包的作用:</p><p>1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。</p><p>2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。</p><p>3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。</p><p>包的创建:</p><p>创建包的时候,你需要为这个包取一个合适的名字。之后,如果其他的一个源文件包含了这个包提供的类、接口、枚举或者注释类型的时候,都必须将这个包的声明放在这个源文件的开头。</p><p>包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。</p><p>如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。</p><p>在 java 源文件中 import 语句应位于 package 语句之后,所有类的定义之前,可以没有,也可以有多条,其语法格式为:</p><p>import package1[.package2…].(classname|*);</p><p>总结</p><p>包的出现,解决了类的命名空间冲突和权限保护问题。</p><p>包的声明要放在类的声明之前,类的声明放在源码之前。</p><p>包的结构中class和java可以不放在一起,避免分享包结构中造成源码泄露。</p><p>包的寻找是从CLASS PATH路径下的目录结合寻找的。</p><p>不同包类名相同时,引用需要使用包名定义。</p><p>(实际上,在使用某一个包中的类时,系统会自动补全定义)。</p>]]></content>
<summary type="html"><h5 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h5><p>继承是指提取不同类的相同属性和方法,使之组成新的类,令拥有此方法和属性的类继承于新形成的类,即父类。(继承关系如下图所示)<br><img </summary>
</entry>
<entry>
<title>java学习之数据类型</title>
<link href="http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/"/>
<id>http://example.com/2022/08/30/java%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/</id>
<published>2022-08-30T07:57:17.000Z</published>
<updated>2022-08-30T13:40:01.680Z</updated>
<content type="html"><![CDATA[<h1 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h1><h3 id="byte"><a href="#byte" class="headerlink" title="byte"></a>byte</h3><p>byte 数据类型是8位、有符号的,以二进制补码表示的整数;<br>最小值是 -128(-2^7); 最大值是 127(2^7-1);<br>默认值是 0;<br>byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的1/4;<br>对应封装类: java.lang.Byte。</p><h3 id="short"><a href="#short" class="headerlink" title="short"></a>short</h3><p>short 数据类型是 16 位、有符号的以二进制补码表示的整数;<br>最小值是 -32768(-2^15);<br>最大值是 32767(2^15 - 1);<br>Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;<br>默认值是 0;<br>对应封装类: java.lang.Short。</p><h3 id="int"><a href="#int" class="headerlink" title="int"></a>int</h3><p>int 数据类型是32位、有符号的以二进制补码表示的整数;<br>最小值是 -2,147,483,648(-2^31);<br>最大值是 2,147,483,647(2^31 - 1);<br>一般地整型变量默认为 int 类型;<br>默认值是 0 ;<br>对应封装类: java.lang.Integer。</p><h3 id="long"><a href="#long" class="headerlink" title="long"></a>long</h3><p>long 数据类型是 64 位、有符号的以二进制补码表示的整数;<br>最小值是 -9,223,372,036,854,775,808(-2^63);<br>最大值是 9,223,372,036,854,775,807(2^63 -1);<br>这种类型主要使用在需要比较大整数的系统上;<br>默认值是 0L;<br>对应封装类: java.lang.Long。</p><h3 id="float"><a href="#float" class="headerlink" title="float"></a>float</h3><p>float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;<br>float 在储存大型浮点数组的时候可节省内存空间;<br>默认值是 0.0f;<br>浮点数不能用来表示精确的值;<br>举例:货币表示不能用float或者double<br>原因:float和double都是浮点数, 都有取值范围, 都有精度范围. 浮点数与通常使用的小数不同, 使用中, 往往难以确定。<br>解决:使用BigDecimal类型存储金额;<br>对应封装类: java.lang.Float。</p><h3 id="double"><a href="#double" class="headerlink" title="double"></a>double</h3><p>double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数;<br>浮点数的默认类型为 double 类型;<br>double类型同样不能表示精确的值;<br>默认值是 0.0d;<br>对应封装类: java.lang.Double。</p><h3 id="char"><a href="#char" class="headerlink" title="char"></a>char</h3><p>char 类型是一个单一的 16 位 Unicode 字符;<br>最小值是 \u0000(十进制等效值为 0);<br>最大值是 \uffff(即为 65535);<br>char 数据类型可以储存任何字符;<br>对应封装类: java.lang.Character。</p><h3 id="boolean"><a href="#boolean" class="headerlink" title="boolean"></a>boolean</h3><p>boolean数据类型表示一位的信息;<br>只有两个取值:true 和 false;<br>这种类型只作为一种标志来记录 true/false 情况;<br>默认值是 false;<br>对应封装类: java.lang.Boolean。</p><h3 id="void"><a href="#void" class="headerlink" title="void"></a>void</h3><p>特殊数据类型,无法直接使用。<br>对应封装类: java.lang.Void。</p><h1 id="引用数据类型"><a href="#引用数据类型" class="headerlink" title="引用数据类型"></a>引用数据类型</h1><p>前言:所有引用数据类型的默认值都为null,引用类型指向一个对象,在被声明以后,类型无法更改。</p><h3 id="Class"><a href="#Class" class="headerlink" title="Class"></a>Class</h3><p>存储区域:堆区。<br>主要类型:自定义对象类型,String类型,StringBuffer类型以及StringBuilder类型等;<br>自定义对象类型:使用自定义类构造对象。<br>String类型:字符串对象,其为不可变对象,底层实际为final修饰的char数组。实际上可通过对value的反射改变该地址中存储的数据。<br>String类型不可变原因:<br>1.String使用广泛,频率高,设计为不可变类型,可避免jvm重复检查String类型增删改查之后的安全性,提高效率;<br>2.字符串的值被保存在常量池之中,常量池的存在是为了优化以及提高效率,若多个String对象指向同一个值,若其中一个String对象改变值而常量池若也随即改变,容易引发许多逻辑错误;<br>3.hashcode缓存需要。String类型对象在被创建之后hashcode就被缓存,不需要重新计算;<br>4.多线程安全。多线程之中,可变对象的值容易被多个线程共享,若其中一个改变,易造成不可预估的后果。<br>StringBuffer类型:StringBuffer类型是可变对象类型,其是线程安全的,在多线程情况下,推荐使用。<br>StringBuilder类型:StringBuilder类型是可变对象类型,其是线程不安全的,不过其效率最高,速度最快。</p><h3 id="Interface"><a href="#Interface" class="headerlink" title="Interface"></a>Interface</h3><p>接口:用于定义方法或行为的类型。无法被实例化,但是可以被实现。</p><h3 id="Array"><a href="#Array" class="headerlink" title="Array"></a>Array</h3><p>数组:数组本身便是引用数据类型,其值存储在常量池中,对象指向其连续的一段地址首端。</p><h1 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h1><h3 id="局部变量"><a href="#局部变量" class="headerlink" title="局部变量"></a>局部变量</h3><p>定义:类的方法中的变量。<br>作用域:当前方法之中。<br>局部变量声明在方法、构造方法或者语句块中;<br>局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;<br>访问修饰符不能用于局部变量;<br>局部变量只在声明它的方法、构造方法或者语句块中可见;<br>局部变量是在栈上分配的。<br>局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。</p><h3 id="类变量"><a href="#类变量" class="headerlink" title="类变量"></a>类变量</h3><p>定义:独立于类的方法之外,使用是static修饰,也叫静态变量。<br>作用域:当前类之中。<br>类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。<br>无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。<br>静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。<br>静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。<br>静态变量在第一次被访问时创建,在程序结束时销毁。<br>与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。<br>默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。<br>静态变量可以通过:ClassName.VariableName的方式访问。<br>类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。</p><h3 id="实例变量"><a href="#实例变量" class="headerlink" title="实例变量"></a>实例变量</h3><p>定义:独立于类的方法之外,没有static修饰,也叫成员变量。<br>作用域:当前类之中。<br>实例变量声明在一个类中,但在方法、构造方法和语句块之外;<br>当一个对象被实例化之后,每个实例变量的值就跟着确定;<br>实例变量在对象创建的时候创建,在对象被销毁的时候销毁;<br>实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;<br>实例变量可以声明在使用前或者使用后;<br>访问修饰符可以修饰实例变量;<br>实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;<br>实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;<br>实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObjectReference.VariableName。</p><h3 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h3><p>定义:被关键字final修饰的变量。<br>特点:只允许一次赋值。</p><h1 id="基础语法"><a href="#基础语法" class="headerlink" title="基础语法"></a>基础语法</h1><h3 id="修饰符"><a href="#修饰符" class="headerlink" title="修饰符"></a>修饰符</h3><p>1.访问控制修饰符<br>Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。<br>default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。<br>private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)<br>public : 对所有类可见。使用对象:类、接口、变量、方法<br>protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。<br>2.非访问控制修饰符<br>Java 提供了许多非访问修饰符:<br>static 修饰符,用来修饰类方法和类变量。<br>final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。<br>abstract 修饰符,用来创建抽象类和抽象方法。<br>synchronized 和 volatile 修饰符,主要用于线程的编程。<br>ransient 修饰符,序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。</p><h3 id="位运算符"><a href="#位运算符" class="headerlink" title="位运算符"></a>位运算符</h3><p>ava定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。<br>位运算符作用在所有的位上,并且按位运算。<br>& 如果相对应位都是1,则结果为1,否则为0;<br>| 如果相对应位都是 0,则结果为 0,否则为 1 ;<br>^ 如果相对应位值相同,则结果为0,否则为1 ;<br>〜 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。<br><< 按位左移运算符。左操作数按位左移右操作数指定的位数。<br>.>> 按位右移运算符。左操作数按位右移右操作数指定的位数。<br>.>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。</p><h3 id="循环结构"><a href="#循环结构" class="headerlink" title="循环结构"></a>循环结构</h3><p>Java中有三种主要的循环结构:<br>while 循环<br>do…while 循环<br>for 循环<br>break 关键字:<br>break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。<br>break 跳出最里层的循环,并且继续执行该循环下面的语句。<br>continue 关键字:<br>continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。<br>在 for 循环中,continue 语句使程序立即跳转到更新语句。<br>在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。</p><h3 id="条件语句"><a href="#条件语句" class="headerlink" title="条件语句"></a>条件语句</h3><p>一个 if 语句包含一个布尔表达式和一条或多条语句。<br>常见形式有:<br>if<br>if-else<br>if-else if-else<br>if-else 嵌套</p><h3 id=""><a href="#" class="headerlink" title=""></a></h3>]]></content>
<summary type="html"><h1 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h1><h3 id="byte"><a href="#byte" class="headerlink" title="b</summary>
</entry>
<entry>
<title>Hello World</title>
<link href="http://example.com/2022/08/29/hello-world/"/>
<id>http://example.com/2022/08/29/hello-world/</id>
<published>2022-08-29T02:35:18.806Z</published>
<updated>2022-08-30T13:44:50.046Z</updated>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
<summary type="html"><p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for</summary>
</entry>
</feed>