異常、多線程、集合類、泛型

来源:https://www.cnblogs.com/wanggang9968/archive/2020/05/13/12885153.html
-Advertisement-
Play Games

"TOC" 異常 基本概念 異常 是在運行時期發生的不正常情況。 異常類 在java中用類的形式對不正常情況進行了描述和封裝對象,描述不正常的情況的類。 異常就是java通過面向對象的思想將問題封裝成了對象.用異常類對其進行描述. 異常體系 不同的問題用不同的類進行具體的描述。 比如角標越界。空指針 ...


目錄

異常

基本概念

  • 異常

是在運行時期發生的不正常情況。

  • 異常類

在java中用類的形式對不正常情況進行了描述和封裝對象,描述不正常的情況的類。

異常就是java通過面向對象的思想將問題封裝成了對象.用異常類對其進行描述.

  • 異常體系

不同的問題用不同的類進行具體的描述。 比如角標越界。空指針等等。問題很多,意味著描述的類也很多,將其共性進行向上抽取

不正常情況就分為了兩大類。

  1. Throwable: 無論是error,還是異常,問題,問題發生就應該可以拋出,讓調用者知道並處理。
  2. throws throw ,凡是可以被這兩個關鍵字所操作的類和對象都具備可拋性.

一般不可處理的. Error是由jvm拋出的嚴重性的問題
可以處理的.Exception

  • 自定義異常:自定義的問題描述

異常的分類

  1. 編譯時被檢測異常:
  • 只要是Exception和其子類都是(除了特殊子類RuntimeException體系)
  • 這種問題一旦出現,希望在編譯時就進行檢測,讓這種問題有對應的處理方式。
  • 這樣的問題都可以針對性的處理。
  1. 編譯時不檢測異常(運行時異常)
  • 就是Exception中的RuntimeException和其子類。
  • 這種問題的發生,無法讓功能繼續,運算無法進行,更多是因為調用者的原因導致的而或者引發了內部狀態的改變導致的。
  • 那麼這種問題一般不處理,直接編譯通過,在運行時,讓調用者調用時的程式強制停止,讓調用者對代碼進行修正。

所以自定義異常時,要麼繼承Exception。要麼繼承RuntimeException。

throws 和throw的區別:

  1. throws使用在函數上.
    throw使用在函數內.
  2. throws拋出的是異常類,可以拋出多個,用逗號隔開。
    throw拋出的是異常對象。

異常處理的捕捉形式

這是可以對異常進行針對性處理的方式。

//具體格式是:
try
{
 //需要被檢測異常的代碼。
}
catch(異常類 變數)//該變數用於接收發生的異常對象
{
 //處理異常的代碼。
}
finally
{
 //一定會被執行的代碼。
}

異常的註意事項

  1. 子類在覆蓋父類方法時,父類的方法如果拋出了異常, 那麼子類的方法只能拋出父類的異常或者該異常的子類。
  2. 如果父類拋出多個異常,那麼子類只能拋出父類異常的子集。

簡單說:子類覆蓋父類只能拋出父類的異常或者子類或者子集。
註意:如果父類的方法沒有拋出異常,那麼子類覆蓋時絕對不能拋,就只能try .

對類文件進行分類管理;給類提供多層命名(名稱)空間; 寫在程式文件的第一行;

  • 類名的全稱是:
    包名.類名

包也是一種封裝形式;

//package
//protected必須是成為其子類,才能繼承
//import導入指定包中的類用的
  • 導包的原則:用到哪個導哪個;
  • jar包:Java的壓縮包;

多線程

  • 進程和線程
  • 進程:正在進行中的程式;
  • 線程:就是進程中一個負責程式執行的控制單元(執行路徑) 一個進程中可以多執行路徑,稱之為多線程;
  • 一個進程中至少有一個線程;
  • 開啟多個線程是為了同時運行多個代碼;
  • 每一個線程都有運行的內容,這個內容稱為這個線程執行的任務;
  • 多線程好處:解決了多部分同時運行的問題;
  • 多線程弊端:線程太多回到的效率降低;

其實應用的執行都是CPU進行著高速的轉換,這個切換是隨機的;

  • 如:JVM啟動時就啟動了多個線程,至少有兩個線程分析的出來;
  1. 執行main函數的線程; 該線程的代碼都在主函數中;
  2. 負責垃圾回收的線程; 垃圾回收器中;
    finalize清除垃圾,重新分配資源
    System.gc()啟動垃圾回收器
//主線程運行示例:
class  Demo  extends   Thread
{
	private String name;
	Demo (String name)
	{
		this.name=name;
	}
	public void run()
	{
		for(int x=0;x<10;x++)
		{
			for(int y=-99999;y<999999999;y++){}
			System.out.println(name+“....x”+x);
		}
	}
}
class Threaddemo
{
	Demo d1=new Demo(“旺財”);
	Demo d2=new Demo(“xiaoqiang”);
	d1.start();
	d2.start();  //開啟線程,運行run方法
}

如何創建一個線程呢?

* 創建線程方式一:繼承Thread類。

步驟:

  1. 定義一個類繼承Thread類。
  2. 覆蓋Thread類中的run方法。
  3. 直接創建Thread的子類對象創建線程。
  4. 調用start方法開啟線程並調用線程的任務run方法執行。

可以通過Thread的getName獲取線程的名稱 Thread-編號(從0開始)

  • 主線程的名字就是main
  • 創建線程的目的是為了開啟一條執行路徑,去運行指定的代碼和其他代碼實現同時運行。
  • 而運行的指定代碼就是這個執行路徑的任務。
  • jvm創建的主線程的任務都定義在了主函數中。
  • 而自定義的線程它的任務在哪兒呢?
  1. Thread類用於描述線程,線程是需要任務的。所以Thread類也對任務的描述。

  2. 這個任務就通過Thread類中的run方法來體現。也就是說,run方法就是封裝自定義線程運行任務的函數。

  3. run方法中定義就是線程要運行的任務代碼。

  4. 開啟線程是為了運行指定代碼,所以只有繼承Thread類,並覆寫run方法。

  5. 將運行的代碼定義在run方法中即可。

  • 通過Thread的getName()方法來獲取該線程的名字
    currentThread()正在運行的線程名字
  • 調用start和run的區別
被創建           
start()  運行          
sleep(time)     
wait()  凍結
Sleep(time)時間到  
notify()
Run()方法結束,線程的任務結束
Stop()
消亡
  • 線程的狀態:
  • CPU的執行資格:等待執行;
  • CPU的執行權:正在執行
  • 臨時阻塞狀態:具備執行資格,沒有執行權,只有正在運行的有執行權;
  • 只有一個有執行權;
  • 創建線程的第二種方式:實現Runnable介面
  1. 定義類實現Runnable介面。
  2. 覆蓋介面中的run方法,將線程的任務代碼封裝到run方法中。
  3. 通過Thread類創建線程對象,並將Runnable介面的子類對象作為Thread類的構造函數的參數進行傳遞。
  • 為什麼?
  • 因為線程的任務都封裝在Runnable介面子類對象的run方法中。 所以要線上程對象創建時就必須明確要運行的任務。
  1. 調用線程對象的start方法開啟線程。
  • 實現Runnable介面的好處:
  1. 將線程的任務從線程的子類中分離出來,進行了單獨的封裝。 按照面向對象的思想將任務的封裝成對象。
  2. 避免了java單繼承的局限性。

所以,創建線程的第二種方式較為常用。

  • 線程安全問題解決思路

將多條操作共用數據的線程代碼封裝起來,當有線程執行代碼時,其他不能參與運算;

同步代碼塊 :synchronized(對象)
{
	需要被同步的代碼;
}
  • 同步的好處:

解決了線程的安全問題;

  • 同步的弊端:

相對降低了效率,因為同步外的線程都會判斷同步鎖

  • 線程間通信(多個線程在處理同一資源,但是任務卻不同):
  1. 這些方法存在於同步中;
  2. 使用這些方法時必須要標識所屬的同步的鎖;
  • 等待、喚醒機制:
    • 涉及的方法:
1. wait() //讓線程處於凍結狀態,被wait的線程會被存儲線程池
2. notify() //喚醒線程池中任意一個線程
3. notifyAll() //喚醒線程池中所有線程

這些方法都必須定義在同步中,因為這些方法是用於操作線程狀態的方法

  • 必須要明確到底操作的是哪個鎖上的線程
  • 為什麼這些方法定義在object類中?

因為這些方法是監視器的方法,監視器本身就是一個鎖

  • Wait和sleep的方法:
  1. wait可以指定時間也可以不指定
    Sleep必須指定時間
  2. 在同步中,對CPU的執行權和鎖的處理不同
    Wait:釋放執行權,釋放鎖
    Sleep:釋放執行權,不釋放鎖
  • 停止線程
  1. stop方法(已過時)
  2. Run方法結束
  • Interrupt()將線程從凍結狀態恢復到運行狀態,讓線程具備CPU的執行資格
  • 守護線程setDaemon(true)將該線程標記為守護線程,當所有線程被守護時,CPU退出

集合類

  • 集合類的由來

對象用於封裝特有數據,對象多了需要存儲.
如果對象的個數不確定,就使用集合容器進行存儲。

  • 集合特點
  1. 用於存儲對象的容器。
  2. 集合的長度是可變的。
  3. 集合中不可以存儲基本數據類型值。

集合容器因為內部的數據結構不同,有多種具體容器。

Collection介面

  • 不斷的向上抽取,就形成了集合框架,框架的頂層Collection介面:
    • Collection
  1. 添加
boolean add(Object obj):
boolean addAll(Collection coll):
  1. 刪除
boolean remove(object obj):
boolean removeAll(Collection coll);
void clear();
  1. 判斷
boolean contains(object obj):
boolean containsAll(Colllection coll);
boolean isEmpty():判斷集合中是否有元素。
  1. 獲取
int size():
Iterator iterator():
  • 取出元素的方式:迭代器。 該對象必須依賴於具體容器,因為每一個容器的數據結構都不同。
  • 所以該迭代器對象是在容器中進行內部實現的。
  • 對於使用容器者而言,具體的實現不重要,只要通過容器獲取到該實現的迭代器的對象即可,
  • 也就是iterator方法。
  • Iterator介面就是對所有的Collection容器進行元素取出的公共介面。
  • 好比就是抓娃娃游戲機中的夾子!
  1. 其他
boolean retainAll(Collection coll)	//取交集。
Object[] toArray()	//將集合轉成數組。
  • Collection方法
  • List:有序(存入和取出的順序一致),元素都有索引(角標),元素可以重覆。
  • Set:元素不能重覆,無序。
  • List特有的常見方法:有一個共性特點就是都可以操作角標。
  1. 添加
void add(index,element)
void add(index,collection)
  1. 刪除
Object remove(index):
  1. 修改
Object set(index,element)
  1. 獲取
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subList(from,to);
//list集合是可以完成對元素的增刪改查.

List:

  • Vector:內部是數組數據結構,是同步的。增刪,查詢都很慢!
  • ArrayList:內部是數組數據結構,是不同步的。替代了Vector。查詢的速度快。
  • LinkedList:內部是鏈表數據結構,是不同步的。增刪元素的速度很快。
LinkedList:
addFirst();
addLast():
//jdk1.6
offerFirst();
offetLast();

getFirst();.//獲取但不移除,如果鏈表為空,拋出NoSuchElementException.
getLast();
//jdk1.6
peekFirst();//獲取但不移除,如果鏈表為空,返回null.
peekLast():

removeFirst();//獲取並移除,如果鏈表為空,拋出NoSuchElementException.
removeLast();
//jdk1.6
pollFirst();//獲取並移除,如果鏈表為空,返回null.
pollLast();
  • Set:元素不可以重覆,是無序。

Set介面中的方法和Collection一致。

  • HashSet: 內部數據結構是哈希表 ,是不同步的。
  • 如何保證該集合的元素唯一性呢?
  1. 是通過對象的hashCode和equals方法來完成對象唯一性的。
  2. 如果對象的hashCode值不同,那麼不用判斷equals方法,就直接存儲到哈希表中。
  3. 如果對象的hashCode值相同,那麼要再次判斷對象的equals方法是否為true。
  4. 如果為true,視為相同元素,不存。如果為false,那麼視為不同元素,就進行存儲。

記住:如果元素要存儲到HashSet集合中,必須覆蓋hashCode方法和equals方法。

  • TreeSet:可以對Set集合中的元素進行排序。是不同步的。

  • 判斷元素唯一性的方式

就是根據比較方法的返回結果是否是0,是0,就是相同元素,不存。

  1. TreeSet對元素進行排序的方式一:

讓元素自身具備比較功能,就需要實現Comparable介面。覆蓋compareTo方法。

  • 如果不要按照對象中具備的自然順序進行排序。如果對象中不具備自然順序。怎麼辦?
  1. 可以使用TreeSet集合第二種排序方式二:

讓集合自身具備比較功能,定義一個類實現Comparator介面,覆蓋compare方法。將該類對象作為參數傳遞給TreeSet集合的構造函數。

if(this.hashCode()== obj.hashCode() && this.equals(obj))
  • 哈希表確定元素是否相同
  1. 判斷的是兩個元素的哈希值是否相同。 如果相同,在判斷兩個對象的內容是否相同。
  2. 判斷哈希值相同,其實判斷的是對象的hashCode的方法。判斷內容相同,用的是equals方法。

註意:如果哈希值不同,是不需要判斷equals。

集合的一些技巧

  • 需要唯一嗎?
    需要:Set
  • 需要制定順序:
    需要: TreeSet
    不需要:HashSet
  • 但是想要一個和存儲一致的順序(有序):
    LinkedHashSet
    不需要:List
  • 需要頻繁增刪嗎?
    需要:LinkedList
    不需要:ArrayList
  • 如何記錄每一個容器的結構和所屬體系呢?
    • List
      |--ArrayList
      |--LinkedList
    • Set
      |--HashSet
      |--TreeSet
  • 尾碼名就是該集合所屬的體系。
    首碼名就是該集合的數據結構。
  • 看到array:就要想到數組,就要想到查詢快,有角標.
  • 看到link:就要想到鏈表,就要想到增刪快,就要想要 add get remove+frist last的方法
  • 看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆蓋hashcode方法和equals方法。
  • 看到tree:就要想到二叉樹,就要想要排序,就要想到兩個介面Comparable,Comparator 。
  • 通常這些常用的集合容器都是不同步的。

Map

  • Map:一次添加一對元素。Collection 一次添加一個元素。
  • Map也稱為雙列集合,Collection集合稱為單列集合。
  • 其實map集合中存儲的就是鍵值對。
  • map集合中必須保證鍵的唯一性。
  • 常用方法
  1. 添加
value put(key,value)
//返回前一個和key關聯的值,如果沒有返回null.
  1. 刪除
void  clear()
//清空map集合。
value remove(key)
//根據指定的key翻出這個鍵值對。
  1. 判斷
boolean containsKey(key)
boolean containsValue(value)
boolean isEmpty()
  1. 獲取
value get(key)
//通過鍵獲取值,如果沒有該鍵返回null。
//當然可以通過返回null,來判斷是否包含指定鍵。
int size()
//獲取鍵值對的個數。
  • Map介面常用的子類
  1. Hashtable :內部結構是哈希表,是同步的。不允許null作為鍵,null作為值。
  2. Properties:用來存儲鍵值對型的配置文件的信息,可以和IO技術相結合。
  3. HashMap : 內部結構是哈希表,不是同步的。允許null作為鍵,null作為值。
  4. TreeMap : 內部結構是二叉樹,不是同步的。可以對Map集合中的鍵進行排序。

泛型

jdk1.5出現的安全機制。
泛型技術是給編譯器使用的技術,用於編譯時期。確保了類型的安全。
運行時,會將泛型去掉,生成的class文件中是不帶泛型的,這個稱為泛型的擦除。
為什麼擦除呢?
因為為了相容運行的類載入器。

  • 好處
  1. 將運行時期的問題ClassCastException轉到了編譯時期。
  2. 避免了強制轉換的麻煩。
  • <>
  • 當操作的引用數據類型不確定的時候。就使用<>。將要操作的引用數據類型傳入即可.
  • 其實<>就是一個用於接收具體引用數據類型的參數範圍。
  • 在程式中,只要用到了帶有<>的類或者介面,就要明確傳入的具體引用數據類型 。
  • 泛型的補償

在運行時,通過獲取元素的類型進行轉換動作。不用使用者再強制轉換了。

  • 泛型的通配符:

? 未知類型

  • 泛型的限定:
  • extends E: 接收E類型或者E的子類型對象。上限
    一般存儲對象的時候用。比如 添加元素 addAll.
  • super E: 接收E類型或者E的父類型對象。 下限。
    一般取出對象的時候用。比如比較器。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我是風箏,公眾號「古時的風箏」,一個不只有技術的技術公眾號,一個在程式圈混跡多年,主業 Java,另外 Python、React 也玩兒的 6 的斜杠開發者。 Spring Cloud 系列文章已經完成,可以到 "我的github" 上查看系列完整內容。也可以在公眾號內回覆「pdf」獲取我精心製作的 ...
  • 預設情況下 拖拽a標簽效果如下: 現在我們禁止這個行為:在標簽行內寫入 ondragstart="return false" ...
  • 工廠模式就是好 工廠模式很普遍,想必好多人一開始接觸的就是這個模式了 工廠方法模式一種創建對象的模式,它被廣泛應用在jdk中以及Spring、Mybatis、Hibernate和Struts框架中; 工廠方法模式基於"輸入",應用在超類和多個子類之間的情況,這種模式將創建對象的責任轉移到工廠類; 首 ...
  • [TOC] 哈嘍,大家好!距離上一篇文章近1個半月了,不是我拖呀~,剛好這個月遇到了工作調整,再加上要照顧10個月的孩子,實屬不易,所以就這麼長時間沒來更新了。這不,我每天碼一點點,'滴水成河',努力完成了這篇文章。 1. 封裝和解構 1.1 封裝 說明: 等號(=)右邊有多個數值僅通過逗號分割,就 ...
  • 我們在爬取網站的時候,都會遵守 robots 協議,在爬取數據的過程中,儘量不對伺服器造成壓力。但並不是所有人都這樣,網路上仍然會有大量的惡意爬蟲。對於網路維護者來說,爬蟲的肆意橫行不僅給伺服器造成極大的壓力,還意味著自己的網站資料泄露,甚至是自己刻意隱藏在網站的隱私的內容也會泄露,這也就是反爬蟲技 ...
  • 1、@Resource註解和@Autowired的區別 @Autowired註解:是按類型裝配依賴對象,預設情況下它要求依賴對象必須存在,如果允許null值,可以設置它required屬性為false。 @Resource註解:和@Autowired一樣,也可以標註在欄位或屬性的setter方法上, ...
  • spring boot集成hasor下的dataway,幹掉後臺,自動配置介面,實現0代碼搭建介面 ...
  • 一、完善球賽程式,測試球賽程式。 將代碼末尾稍作改動即可,若代碼正確,則運行,否則輸出Error。 from random import random #列印程式介紹信息 def printIntro(): print("19信計2班23號鄧若言") print("這個程式模擬兩個選手A和B的乒乓球 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...