www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 公眾號精選 > 架構(gòu)師社區(qū)
[導讀]Java是很多人一直在用的編程語言,但是有些Java概念是非常難以理解的,哪怕是一些多年的老手,對某些Java概念也存在一些混淆和困惑。 所以,這篇文章會介紹四個Java中最難理解的四個概念,去幫助開發(fā)者更清晰的理解這些概念。

Java 是很多人一直在用的編程語言,但是有些 Java 概念是非常難以理解的,哪怕是一些多年的老手,對某些 Java 概念也存在一些混淆和困惑。

所以,在這篇文章里,會介紹四個 Java 中最難理解的四個概念,去幫助開發(fā)者更清晰的理解這些概念:

  1. 匿名內(nèi)部類的用法
  2. 多線程
  3. 如何實現(xiàn)同步
  4. 序列化

匿名內(nèi)部類

匿名內(nèi)部類又叫匿名類,它有點像局部類(Local Class)或者內(nèi)部類(Inner Class),只是匿名內(nèi)部類沒有名字,我們可以同時聲明并實例化一個匿名內(nèi)部類。

一個匿名內(nèi)部類僅適用在想使用一個局部類并且只會使用這個局部類一次的場景。

匿名內(nèi)部類是沒有需要明確聲明的構(gòu)造函數(shù)的,但是會有一個隱藏的自動聲明的構(gòu)造函數(shù)。

創(chuàng)建匿名內(nèi)部類有兩種辦法:

  1. 通過繼承一個類(具體或者抽象都可以)去創(chuàng)建出匿名內(nèi)部類
  2. 通過實現(xiàn)一個接口創(chuàng)建出匿名內(nèi)部類

咱們看看下面的例子:

interface Programmer { void develop();}
public class TestAnonymousClass { public static Programmer programmer = new Programmer() { @Override public void develop() { System.out.println("我是在類中實現(xiàn)了接口的匿名內(nèi)部類"); } };
public static void main(String[] args) { Programmer anotherProgrammer = new Programmer() { @Override public void develop() { System.out.println("我是在方法中實現(xiàn)了接口的匿名內(nèi)部類"); } };
TestAnonymousClass.programmer.develop(); anotherProgrammer.develop(); }}

從上面的例子可以看出,匿名類既可以在類中也可以在方法中被創(chuàng)建。

之前我們也提及匿名類既可以繼承一個具體類或者抽象類,也可以實現(xiàn)一個接口。所以在上面的代碼里,我創(chuàng)建了一個叫做 Programmer 的接口,并在 TestAnonymousClass 這個類中和 main() 方法中分別實現(xiàn)了接口。

Programmer除了接口以外既可以是一個抽象類也可以是一個具體類。

抽象類,像下面的代碼一樣:

public?abstract?class?Programmer?{ public abstract void develop();}

具體類代碼如下:

public?class?Programmer?{????public?void?develop()?{????????System.out.println("我是一個具體類");????}}

OK,繼續(xù)深入,那么如果 Programmer 這個類沒有無參構(gòu)造函數(shù)怎么辦?我們可以在匿名類中訪問類變量嗎?我們?nèi)绻^承一個類,需要在匿名類中實現(xiàn)所有方法嗎?

public?class?Programmer?{ protected int age;
public Programmer(int age) { this.age = age; }
public void showAge() { System.out.println("年齡:" + age); }
public void develop() { System.out.println("開發(fā)中……除了異性,他人勿擾"); }
public static void main(String[] args) { Programmer programmer = new Programmer(38) { @Override public void showAge() { System.out.println("在匿名類中的showAge方法:" + age); } }; programmer.showAge(); }}
  1. 構(gòu)造匿名類時,我們可以使用任何構(gòu)造函數(shù)。上面的代碼可以看到我們使用了帶參數(shù)的構(gòu)造函數(shù)。
  2. 匿名類可以繼承具體類或者抽象類,也能實現(xiàn)接口。所以訪問修飾符規(guī)則同普通類是一樣的。子類可以訪問父類中的 protected 限制的屬性,但是無法訪問 private 限制的屬性。
  3. 如果匿名類繼承了具體類,比如上面代碼中的 Programmer 類,那么就不必重寫所有方法。但是如果匿名類繼承了一個抽象類或者實現(xiàn)了一個接口,那么這個匿名類就必須實現(xiàn)所有沒有實現(xiàn)的抽象方法。
  4. 在一個匿名內(nèi)部類中你不能使用靜態(tài)初始化,也沒辦法添加靜態(tài)變量。
  5. 匿名內(nèi)部類中可以有被 final 修飾的靜態(tài)常量。

匿名類的典型使用場景

  1. 臨時使用:我們有時候需要添加一些類的臨時實現(xiàn)去修復(fù)一些問題或者添加一些功能。為了避免在項目里添加java文件,尤其是僅使用一次這個類的時候,我們就會使用匿名類。
  2. UI Event Listeners:在java的圖形界面編程中,匿名類最常使用的場景就是去創(chuàng)建一個事件監(jiān)聽器。比如:
button.setOnClickListener(new?View.OnClickListener()?{ public void onClick(View v) { }});

上面的代碼中,我們通過匿名類實現(xiàn)了 setOnClickListener 接口,當用戶點擊按鈕的時候,就會觸發(fā)我們實現(xiàn)的 onClick 方法。

多線程

Java 中的多線程就是利用多個線程共同完成一個大任務(wù)的運行過程,使用多線程可以最大程度的利用CPU。

使用多線程的使用線程而不是進程來做任務(wù)處理,是因為線程比進程更加輕量,線程是一個輕量級的進程,是程序執(zhí)行的最小單元,并且線程和線程之間是共享主內(nèi)存的,而進程不是。

線程生命周期

什么?聽說這四個概念,很多Java老手都說不清!

正如上圖所示,線程生命周期一共有六種狀態(tài)。我們現(xiàn)在依次對這些狀態(tài)進行介紹。

  1. New:當我們構(gòu)造出一個線程實例的時候, 這個線程就擁有了 New 狀態(tài)。這個狀態(tài)是線程的第一個狀態(tài)。此時,線程并沒有準備運行。
  2. Runnable:當調(diào)用了線程類的 start() 方法, 那么這個線程就會從 New 狀態(tài)轉(zhuǎn)換到 Runnable 狀態(tài)。這就意味著這個線程要準備運行了。但是,如果線程真的要運行起來,就需要線程調(diào)度器來調(diào)度執(zhí)行這個線程。但是線程調(diào)度器可能忙于在執(zhí)行其他的線程,從而不能及時去調(diào)度執(zhí)行這個線程。線程調(diào)度器是基于 FIFO 策略去從線程池中挑出一個線程來執(zhí)行的。
  3. Blocked:線程可能會因為不同的情況自動的轉(zhuǎn)為 Blocked 狀態(tài)。比如,等候 I/O 操作,等候網(wǎng)絡(luò)連接等等。除此之外,任意的優(yōu)先級比當前正在運行的線程高的線程都可能會使得正在運行的線程轉(zhuǎn)為 Blocked 狀態(tài)。
  4. Waiting:在同步塊中調(diào)用被同步對象的 wait 方法,當前線程就會進入 Waiting 狀態(tài)。如果在另一個線程中的同一個對象被同步的同步塊中調(diào)用 notify()/notifyAll(),就可能使得在 Waiting 的線程轉(zhuǎn)入 Runnable 狀態(tài)。
  5. Timed_Waiting:同 Waiting 狀態(tài),只是會有個時間限制,當超時了,線程會自動進入 Runnable 狀態(tài)。
  6. Terminated:線程在線程的 run() 方法執(zhí)行完畢后或者異常退出run()方法后,就會進入 Terminated 狀態(tài)。

為什么要使用多線程

大白話講就是通過多線程同時做多件事情讓 Java 應(yīng)用程序跑的更快,使用線程來實行并行和并發(fā)。如今的 CPU 都是多核并且頻率很高,如果單獨一個線程,并沒有充分利用多核 CPU 的優(yōu)勢。

重要的優(yōu)勢

  • 可以更好地利用 CPU
  • 可以更好地提升和響應(yīng)性相關(guān)的用戶體驗
  • 可以減少響應(yīng)時間
  • 可以同時服務(wù)多個客戶端

創(chuàng)建線程有兩種方式

  1. 通過繼承Thread類創(chuàng)建線程

這個繼承類會重寫 Thread 類的 run() 方法。一個線程的真正運行是從 run() 方法內(nèi)部開始的,通過 start() 方法會去調(diào)用這個線程的 run() 方法。

public?class?MultithreadDemo?extends?Thread?{ @Override????public?void?run()?{ try { System.out.println("線程 " + Thread.currentThread().getName() + " 現(xiàn)在正在運行"); } catch (Exception e) { e.printStackTrace(); } }
????public?static?void?main(String[]?args)?{ for (int i = 0; i < 10; i++) { MultithreadDemo multithreadDemo = new MultithreadDemo(); multithreadDemo.start(); } }}
  1. 通過實現(xiàn)Runnable接口創(chuàng)建線程

我們創(chuàng)建一個實現(xiàn)了 java.lang.Runnable 接口的新類,并實現(xiàn)其 run() 方法。然后我們會實例化一個 Thread 對象,并調(diào)用這個對象的 start() 方法。

public?class?MultithreadDemo?implements?Runnable?{
@Override public void run() { try { System.out.println("線程 " + Thread.currentThread().getName() + " 現(xiàn)在正在運行"); } catch (Exception e) { e.printStackTrace(); } }
public static void main(String[] args) { for (int i = 0; i < 10; i++) { Thread thread = new Thread(new MultithreadDemo()); thread.start(); } }}

兩種創(chuàng)建方式對比

  • 如果一個類繼承了 Thread 類,那么這個類就沒辦法繼承別的任何類了。因為 Java 是單繼承,不允許同時繼承多個類。多繼承只能采用接口的方式,一個類可以實現(xiàn)多個接口。所以,使用實現(xiàn) Runnable 接口在實踐中比繼承 Thread 類更好一些。
  • 第一種創(chuàng)建方式,可以重寫 yield()、interrupt() 等一些可能不太常用的方法。但是如果我們使用第二種方式去創(chuàng)建線程,則 yield() 等方法就無法重寫了。

同步

同步只有在多線程條件下才有意義,一次只能有一個線程執(zhí)行同步塊。

在 Java 中,同步這個概念非常重要,因為 Java 本身就是一門多線程語言,在多線程環(huán)境中,做合適的同步是極度重要的。

為什么要使用同步

在多線程環(huán)境中執(zhí)行代碼,如果一個對象可以被多個線程訪問,為了避免對象狀態(tài)或者程序執(zhí)行出現(xiàn)錯誤,對這個對象使用同步是非常必要的。

在深入講解同步概念之前,我們先來看看同步相關(guān)的問題。

class?Production?{
//沒有做方法同步 void printProduction(int n) { for (int i = 1; i <= 5; i++) { System.out.print(n * i+" "); try { Thread.sleep(400); } catch (Exception e) { System.out.println(e); } }
}}
class MyThread1 extends Thread {
Production p;
MyThread1(Production p) { this.p = p; }
public void run() { p.printProduction(5); }
}
class MyThread2 extends Thread {
Production p;
MyThread2(Production p) { this.p = p; }
public void run() { p.printProduction(100); }}
public class SynchronizationTest { public static void main(String args[]) { Production obj = new Production(); //多線程共享同一個對象 MyThread1 t1 = new MyThread1(obj); MyThread2 t2 = new MyThread2(obj); t1.start(); t2.start(); }}

運行上面的代碼后,由于我們沒有加同步,可以看到運行結(jié)果非?;靵y。

Output:100 5 10 200 15 300 20 400 25 500

接下來,我們給 printProduction 方法加上同步:

class?Production?{
//做了方法同步 synchronized void printProduction(int n) { for (int i = 1; i <= 5; i++) { System.out.print(n * i+" "); try { Thread.sleep(400); } catch (Exception e) { System.out.println(e); } }
}}

當我們對 printProduction() 加上了同步(synchronized)后, 已有一個線程執(zhí)行的情況下,是不會有任何一個線程可以再次執(zhí)行這個方法。這次加了同步后的輸出結(jié)果是有次序的。

Output:5 10 15 20 25 100 200 300 400 500

類似于對方法做同步,你也可以去同步 Java 類和對象。

注意:其實有時候我們可以不必去同步整個方法。出于性能原因,我們其實可以僅同步方法中我們需要同步的部分代碼。被同步的這部分代碼就是方法中的同步塊。

序列化

Java 的序列化就是將一個 Java 對象轉(zhuǎn)化為一個字節(jié)流的一種機制。從字節(jié)流再轉(zhuǎn)回 Java 對象叫做反序列化,是序列化的反向操作。

序列化和反序列化是和平臺無關(guān)的,也就是說你可以在 Linux 系統(tǒng)序列化,然后在 Windows 操作系統(tǒng)做反序列化。

如果要序列化對象,需要使用 ObjectOutputStream 類的 writeObject() 方法。如果要做反序列化,則要使用 ObjectOutputStream 類的 readObject() 方法。

如下圖所示,對象被轉(zhuǎn)化為字節(jié)流后,被儲存在了不同的介質(zhì)中。這個流程就是序列化。在圖的右邊,也可以看到從不同的介質(zhì)中,比如內(nèi)存,獲得字節(jié)流并轉(zhuǎn)化為對象,這叫做反序列化。

什么?聽說這四個概念,很多Java老手都說不清!

為什么使用序列化

如果我們創(chuàng)建了一個 Java 對象,這個對象的狀態(tài)在程序執(zhí)行完畢或者退出后就消失了,不會得到保存。

所以,為了能解決這類問題,Java 提供了序列化機制。這樣,我們就能把對象的狀態(tài)做臨時儲存或者進行持久化,以供后續(xù)當我們需要這個對象時,可以通過反序列化把對象還原回來。

下面給出一些代碼看看我們是怎么來做序列化的。

import?java.io.Serializable;
public class Player implements Serializable {
private static final long serialVersionUID = 1L;
private String serializeValueName; private transient String nonSerializeValuePos;
public String getSerializeValueName() { return serializeValueName; }
public void setSerializeValueName(String serializeValueName) { this.serializeValueName = serializeValueName; }
public String getNonSerializeValueSalary() { return nonSerializeValuePos; }
public void setNonSerializeValuePos(String nonSerializeValuePos) { this.nonSerializeValuePos = nonSerializeValuePos; }
@Override public String toString() { return "Player [serializeValueName=" + serializeValueName + "]"; }}
import?java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;
public class SerializingObject { public static void main(String[] args) {
Player playerOutput = null; FileOutputStream fos = null; ObjectOutputStream oos = null;
playerOutput = new Player(); playerOutput.setSerializeValueName("niubi"); playerOutput.setNonSerializeValuePos("x:1000,y:1000");
try { fos = new FileOutputStream("Player.ser"); oos = new ObjectOutputStream(fos); oos.writeObject(playerOutput);
System.out.println("序列化數(shù)據(jù)被存放至Player.ser文件");
oos.close(); fos.close();
} catch (IOException e) {
e.printStackTrace(); } }}

Output:序列化數(shù)據(jù)被存放至Player.ser文件

import?java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;
public class DeSerializingObject {
public static void main(String[] args) {
Player playerInput = null; FileInputStream fis = null; ObjectInputStream ois = null;
try { fis = new FileInputStream("Player.ser"); ois = new ObjectInputStream(fis); playerInput = (Player) ois.readObject();
System.out.println("從Player.ser文件中恢復(fù)");
ois.close(); fis.close();
} catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }
System.out.println("player名字為 : " + playerInput.getSerializeValueName()); System.out.println("player位置為 : " + playerInput.getNonSerializeValuePos()); }}

Output:

從Player.ser文件中恢復(fù)player名字為 : niubiplayer位置為 : null

關(guān)鍵特性

  1. 如果父類實現(xiàn)了 Serializable 接口那么子類就不必再實現(xiàn) Serializable 接口了。但是反過來不行。
  2. 序列化只支持非 static 的成員變量
  3. static 修飾的變量和常量以及被 transient 修飾的變量是不會被序列化的。所以,如果我們不想要序列化某些非 static 的成員變量,直接用 transient 修飾它們就好了。
  4. 當反序列化對象的時候,是不會調(diào)用對象的構(gòu)造函數(shù)的。
  5. 如果一個對象被一個要序列化的對象引用了,這個對象也會被序列化,并且這個對象也必須要實現(xiàn) Serializable 接口。

總結(jié)

首先,我們介紹了匿名類的定義,使用場景和使用方式。

其次,我們討論了多線程和其生命周期以及多線程的使用場景。

再次,我們了解了同步,知道同步后,僅同時允許一個線程執(zhí)行被同步的方法或者代碼塊。當一個線程在執(zhí)行被同步的代碼時,別的線程只能在隊列中等待直到執(zhí)行同步代碼的線程釋放資源。

最后,我們知道了序列化就是把對象狀態(tài)儲存起來以供后續(xù)使用。

特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:

什么?聽說這四個概念,很多Java老手都說不清!

什么?聽說這四個概念,很多Java老手都說不清!

什么?聽說這四個概念,很多Java老手都說不清!

長按訂閱更多精彩▼

什么?聽說這四個概念,很多Java老手都說不清!

如有收獲,點個在看,誠摯感謝

免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉