Java中泛型詳解,非常詳細

来源:https://www.cnblogs.com/qian-fen/archive/2023/05/31/17445243.html
-Advertisement-
Play Games

在前面的幾篇文章中,詳細地給大家介紹了Java里的集合。但在介紹集合時,我們涉及到了泛型的概念卻並沒有詳細學習,所以今天我們要花點時間給大家專門講解什麼是泛型、泛型的作用、用法、特點等內容 ...


前言

在前面的幾篇文章中,詳細地給大家介紹了Java里的集合。但在介紹集合時,我們涉及到了泛型的概念卻並沒有詳細學習,所以今天我們要花點時間給大家專門講解什麼是泛型、泛型的作用、用法、特點等內容。

有些粉絲朋友,在之前就一直很好奇,比如List< String >中的 < String > 部分到底是什麼?有啥用?為什麼要加這個< >?這一部分有沒有什麼特別的用法?總之,你的疑問可能會有很多,別急,今天就帶你一點點認識Java里的泛型!


全文大約【6000】 字,不說廢話,只講可以讓你學到技術、明白原理的純乾貨!本文帶有豐富的案例及配圖視頻,讓你更好地理解和運用文中的技術概念,並可以給你帶來具有足夠啟迪的思考...

一. 泛型簡介

作為Java中常用且重要的一個概念,泛型幫我們實現了代碼重用,也保證了類型安全。但關於它的詳細內容,目前很多同學還不清楚,所以接下來就帶各位來學習這個重要的知識點。

1. 背景

為了能夠讓大家更好地理解泛型的作用,在我們開始學習泛型之前,先給大家提個開發需求:

我們現在有一個需求,要求你編寫一個對數組進行排序的方法,該方法能夠對浮點型數組、整型數組、字元串數組或者是其他任何類型的數組進行排序,你該如何實現?

有的小伙伴會說,這很簡單啊,我可以利用方法重載,針對每種類型的數組分別編寫一個排序方法,需要為幾種類型的數組排序,我就定義幾個排序方法。如果你是這麼實現的,只能哈哈哈了,這種做法明顯不好,代碼可重用性太差

又有的小伙伴說了,可以定義一個方法,裡面設置一個Object[]類型的參數,這樣無論是哪種類型都可以處理了。這樣定義方法,比上面那個同學的想法要稍好一點,但此時我們需要在Object類型和整型、String類型或其他類型之間進行強制類型轉換。所以這樣做就無法保證集合中元素的類型安全,稍一不慎就可能會導致 ClassCastException類型轉換異常

so,這也不行,那也不行,到底該怎麼辦?這不,為瞭解決這些問題,所以Java中就產生了泛型這個技術。

2. 概念

泛型(generics) 這個技術是在JDK 5中引入的新特性,它的本質其實是類型參數化, 利用泛型可以實現一套代碼對多種數據類型的動態處理,保證了更好的代碼重用性。並且泛型還提供了編譯時對類型安全進行檢測的機制,該機制允許我們在編譯時就能夠檢測出非法的類型, 提高了代碼的安全性

這種特性,使得泛型成了一種 “代碼模板” ,讓我們利用一套代碼就能實現對各種類型的套用。也就是說,我們只需要編寫一次代碼,就可以實現萬能匹配,這也是”泛型“這個概念的含義,你可以將其理解為”廣泛的類型“、”非特定的類型“。咱們上面的那個需求,利用泛型就能輕鬆實現,還不需要進行類型的強制轉換,並且也保證了數據的類型安全。

3. 作用

所以根據上面泛型的概念,我們可以提取出泛型的核心作用:

  • 泛型可以在編譯時對類型進行安全檢測,使得所有的強制轉換都是自動隱式實現的,保證了類型的安全性;
  • 泛型作為”代碼模板“,實現了 一套代碼對各種類型的套用, 提高了代碼的可重用性。

4. 使用場景

基於泛型的這些特性和作用,我們可以把泛型用在很多地方,在這裡給大家做了一個總結,通常情況下,泛型可以用在如下場景中:

  • 泛型集合:在各種集合中使用泛型,保證集合中元素的類型安全;
  • 泛型方法:在各種方法中使用泛型,保證方法中參數的類型安全;
  • 泛型類:在類的定義時使用泛型,為某些變數和方法定義通用的類型;
  • 泛型介面:在介面定義時使用泛型,為某些常量和方法定義通用的類型;
  • 泛型加反射:泛型也可以結合反射技術,實現在運行時獲取傳入的實際參數等功能。

但是我們要註意,無論我們在哪個地方使用泛型,泛型都不能是基本類型, 關於這一點,我會在講解泛型擦除時再細說。

總之,泛型的應用場景有很多,以上只是給大家總結的幾個重點使用場景,接下來就這幾個場景分別給大家進行講解。

5. 配套視頻

與本節內容配套的視頻鏈接如下:戳我直達

二. 泛型集合

1. 簡介

泛型最常見的一個用途,就是在集合中對數據元素的類型進行限定。集合作為一個容器,主要是用來容納保存數據元素的,但集合的設計者並不知道我們會用集合來保存什麼類型的對象,所以他們就把集合設計成能保存任何類型的對象。這就要求集合具有很好的通用性,內部可以裝載各種類型的數據元素。集合之所以可以實現這一功能,主要是集合的源碼中已經結合泛型做了相關的設計,我們來看看Collection的源碼,如下圖所示:

image.png

而Collection的子類List中也增加了對泛型的支持,如下圖所示:

image.png

上面的源碼中,集合中的< E >就是泛型,至於泛型的名字為什麼叫做”E“,後面再跟大家細說。但不管如何,從這些源碼中我們就可以看出,Java的集合本身就支持泛型了。我們先不管集合底層是如何設計的,咱們先從基本用法開始學起。

2. 語法

在集合中使用泛型其實比較簡單,我們以List集合為例,其基本語法如下:

//可以省略後面ArrayList里的String,編譯器可以自動根據前面<>里的類型,推斷出後面<>里使用的泛型類型
List<String> list = new ArrayList<>();

上面的語法,其含義是說我們定義了一個ArrayList集合,但該集合不能隨便添加數據元素,只能添加String類型的元素。也就是說,在上面的語法中,我們通過泛型,限定了ArrayList集合的元素類型。當我們定義List集合時,如果已經限定了泛型類型,但後面添加元素時你非得違背這個類型,Java就會在編譯階段報錯,如下圖所示:

image.png

我們在定義集合時,可以省略後面ArrayList里的String,編譯器可以自動根據前面< >里的類型,推斷出後面< >里使用的泛型類型。另外Set和Map集合的用法,與List集合類似,我們可以通過下麵這個案例來體會一下集合泛型的魅力。

3. 代碼案例

在本案例中,我們可以給List、Set、Map等集合設置泛型,從而限定集合中數據元素的類型。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Demo01 {
	public static void main(String[] args) {
		//定義集合泛型
		//此時的集合只能接受String類型元素,後面ArrayList<>中的<>,裡面的String可寫可不寫
		List<String> list = new ArrayList<>();
		//如果類型不一致,在編譯階段就會檢測出有錯誤,保證了數據的安全性
		//list.add(100);
		list.add("Hello");
		String strValue = list.get(0);
		System.out.println("list value="+strValue);
		
		Set<Integer> set=new HashSet<>();
		//set.add("hello");
		set.add(200);
		Iterator<Integer> iterator = set.iterator();
		while(iterator.hasNext()) {
			Integer nextValue = iterator.next();
			System.out.println("set value="+nextValue);
		}
		
		//限定Map集合的key是String類型,value是Long類型
		Map<String,Long> map=new HashMap<>();
		//map.put("number", "10000");
		map.put("number", 10000L);
		Long value = map.get("number");
		System.out.println("map value="+value);
	}
}

在這個案例中,我們在集合中通過泛型限定了集合元素的數據類型。如果元素的類型與要求的不一致,在編譯階段就會檢測出有錯誤,不需要進入到運行階段才能發現類型不一致。而且我們 在獲取集合中的元素時,也不需要進行強制類型轉換,程式會自動進行隱式轉換, 這就保證了數據的安全性,也提高了代碼的執行效率。

另外我們所使用的泛型參數,也被稱為類型變數,是用於指定泛型類型名稱的標識符。我們可以根據需要,在集合、類、介面、方法等地方定義一個或多個泛型參數,這些泛型化的類型參數也被稱為參數化的類或參數化的類型。

4. 配套視頻

與本節內容配套的視頻鏈接如下:戳我直達

三. 泛型介面

我們除了可以在集合中使用泛型,還可以在定義介面時使用泛型,這也是泛型的常用形式之一。

1. 語法

在定義介面時使用泛型的基本語法格式如下:

//在介面名稱後面緊跟泛型<>
public interface InterfaceName<T> {
    // 介面的方法定義
}

//可以同時定義多個泛型,多個泛型用","逗號分割
public interface InterfaceName2<M,N> {
    // 介面的方法定義
}

大家註意,這裡泛型的名稱T/M/N,其實是我們隨意寫的,我們並不一定非要使用T,也可以使用M、N、E等任意名稱。而之所以使用T,只是採用了Type類型這個單詞的首字母而已。雖然如此,但我們在實際開發時,為了儘量做到見名知意,請大家還是要儘量採用有意義的名稱,通常會使用如下幾個常用字母:

  • E - Element(表示集合元素,常在集合中使用);
  • T - Type(表示Java類,常用在類和介面中);
  • K - Key(表示鍵);
  • V - Value(表示值);
  • N - Number(表示數值類型);
  • - 表示不確定的Java類型。

另外,這裡的T只是一種類型參數,你可以把它理解成是一個”錶面的占位符“。在真正賦值時,它可以用任何實際的類型來替代,如Integer、String、自定義類型等。並且我們在定義介面時,可以根據實際需要,同時定義多個泛型,多個泛型之間用","逗號分割。而在實際使用時,我們需要在該介面名的後面加上一對尖括弧,用來傳入實際的類型。

2. 代碼案例

2.1 定義泛型介面

接下來我們再通過一個案例來學習一下介面泛型如何使用,這裡我們定義一個泛型介面ICompute,內部定義了一個用於計算的方法,如下所示:


public interface ICompute<M,N> {

	//定義一個加法計算的方法
	M add(M m,N n);
}

2.2 實現泛型介面

接下來我們把這個介面進行實現,代碼如下:

public class Demo02 {
	public static void main(String[] args) {
		//這裡壹哥直接利用匿名內部類的寫法進行實現,大家也可以編寫一個類實現ICompute介面
		//我這裡傳入了兩個Integer類型的具體參數,分別取代M和N
		ICompute<Integer, Integer> iCompute = new ICompute<Integer, Integer>() {
			@Override
			public Integer add(Integer m, Integer n) {
				return m+n;
			}
		};
		
		//調用上面實現的方法
		Integer result = iCompute.add(100, 200);
		System.out.println("result="+result);
	}
}

這裡直接利用匿名內部類的寫法進行實現,大家也可以編寫一個類實現ICompute介面。我這裡傳入了兩個Integer類型的具體參數,分別取代M和N,當然我們也可以根據需要,在實現時傳入Float/Double等其他類型。

3. 配套視頻

與本節內容配套的視頻鏈接如下:戳我直達

四. 泛型類

其實Java的類和介面在很多地方都很類似,所以我們在定義介面時可以使用泛型,也可以在定義類時使用泛型,泛型類常用於類中的屬性類型不確定的情況下,這也是泛型的常用形式之一。

1. 語法

其實泛型類的聲明和普通類的聲明類似,只是在類名後面多添加了一個關於泛型的聲明。並且泛型類的類型參數部分,可以包含一個或多個類型參數,多個參數間用逗號隔開。一般我們在定義泛型類時,需要在類名後添加類型參數,語法格式與泛型介面一致,如下所示:

public class ClassName<T> {
    // 類的成員變數和方法定義
}

泛型類的要求和泛型介面完全一樣,這裡就不再贅述了。

2. 代碼案例

2.1 定義泛型類

接下來定義一個泛型類Pair,它包含兩個類型相同的成員變數:

public class Pair<T> {

	//我們可以直接把泛型當成一個java的“類型”來用,Java類怎麼用,泛型就可以怎麼用
	//直接利用泛型來定義成員變數
	private T first;
    private T second;

    //構造方法中使用泛型
    public Pair(T first, T second) {
        this.first = first;
        this.second = second;
    }

    //方法中使用泛型
    public T getFirst() {
        return first;
    }

    public T getSecond() {
        return second;
    }
}

在上述代碼中,我們定義了一個泛型類Pair,它有兩個類型相同的成員變數first和second,以及一個構造函數和兩個訪問成員變數的方法。在定義Pair類時,我們使用了類型參數T來代表類型,而在實例化該泛型類時,需要指明泛型類中的類型參數,並賦予泛型類屬性相應類型的值,比如指定T是String/Integer/Student/Person等任意類型。

2.2 使用泛型類

接下來是使用Pair類的具體代碼:


public class Demo03 {
	public static void main(String[] args) {
		//調用泛型類
		Pair<String> pair = new Pair<>("Hello", "World");
		// 輸出 "Hello"
		System.out.println("first="+pair.getFirst()); 
		// 輸出 "World"
		System.out.println("last="+pair.getSecond()); 
	}
}

在上述代碼中,我們使用了Pair類,並將類型參數指定為String類型。然後我們創建了一個Pair對象,並通過getFirstgetSecond方法訪問了成員變數。

3. 配套視頻

與本節內容配套的視頻鏈接如下:戳我直達

五. 繼承泛型類和實現泛型介面

在Java中,泛型不僅可以用於類、方法的定義,還可以用於類和介面的繼承與實現。接下來就給大家詳細介紹一下,該如何繼承泛型類和實現泛型介面。

1. 簡介

大家要註意,一個被定義為泛型的類和介面,也可以被子類繼承和實現。例如下麵的示例代碼,就給大家演示瞭如何繼承一個泛型類。

public class FatherClass<T1>{}

public class SonClass<T1,T2,T3> extents FatherClass<T1>{}

但是如果我們想要SonClass類在繼承FatherClass類時,能夠保留父類的泛型類型,則需要在繼承時就指定。否則直接使用extends FatherClass語句進行繼承操作時,T1、T2 和 T3都會自動變為Object類型,所以一般情況下都是將父類的泛型類型保留。

接下來會分別給大家介紹一下如何繼承泛型類和實現泛型介面。

2. 繼承泛型類

2.1 定義泛型父類

在Java中,我們可以通過繼承一個泛型類來實現泛型的重用。子類可以繼承父類中定義的泛型類型,並根據自己的需要,增加、修改泛型類型的參數,從而實現泛型類的個性化定製。下麵是一個泛型類的示例:

public class GenericClass<T1> {

	private T1 data;

	public GenericClass(T1 data) {
		this.data = data;
	}

	public T1 getData() {
		return data;
	}
}

2.2 泛型子類繼承父類

我們可以通過繼承GenericClass類,來創建一個新的泛型類SonGenericClass,並增加新的泛型類型:

public class SonGenericClass<T1,T2> extends GenericClass<T1>{

	private T2 otherData;
    
    public SonGenericClass(T1 data, T2 otherData) {
        super(data);
        this.otherData = otherData;
    }
    
    public T2 getOtherData() {
        return otherData;
    }
}

在上面的示例中,SonGenericClass類繼承了GenericClass類,並增加了一個新的泛型類型T2。在構造方法中,調用父類的構造方法,並傳入T1類型的數據,然後再將T2類型的數據賦值給類的成員變數otherData。通過這種方式,我們可以創建一個具有更多泛型參數的類,並且保留了原始泛型類的特性。我們來看看最終的測試結果:

public class Demo08 {

	public static void main(String[] args) {
		SonGenericClass<Integer,String> son=new SonGenericClass<>(100, "hello");
        //子類從父類中繼承來的泛型
		Integer data = son.getData();
		String otherData = son.getOtherData();
		System.out.println("t1---data="+data+",t2---data="+otherData);
	}
}

這樣,子類通過繼承父類,也自動獲得了父類中的泛型。

3. 實現泛型介面

3.1 定義泛型介面

類似於繼承泛型類,我們也可以通過實現泛型介面,來定義具有多個泛型參數的介面。實現泛型介面的過程與實現普通介面的過程相同,我們只需要在介面名後面添加 < T > 這樣的泛型參數聲明即可。下麵是一個泛型介面的示例:

public interface GenericInterface<T1> {
	
	public void doSomething(T1 data);
}

3.2 兩種實現方式

我們在實現泛型介面時,可以採用兩種實現方式:

  1. 指定具體類型:就是在實現介面時,明確指定泛型參數的具體類型;
  2. 保留泛型參數:在實現介面時,不明確指定泛型參數的具體類型,而是保留泛型參數。

如果是通過指定具體類型的方式進行實現,一般形式如下:

public class StringPair implements Pair<String> {
    .....
}

在這種方式中,我們定義了一個Pair介面,然後讓子類StringPair進行實現,但在實現時就明確指定了具體的泛型參數為String。這樣,我們在使用StringPair對象時,就明確知道了類內部的數據類型。

如果是通過保留泛型參數的方式進行實現,一般形式如下:

public class NumberPair<T extends 父類型> implements Pair<T> {
    ......
}

在這種方式中,我們定義了一個泛型介面Pair< T >,然後定義一個實現字類NumberPair,可以在實現時保留泛型參數。

3.3 實現泛型介面

接下來,我們再編寫一個SubGenericInterface類,並通過保留泛型參數的方式,來實現GenericInterface介面,並增加一個新的泛型類型T2,代碼如下:

public class SubGenericClass<T1,T2> implements GenericInterface<T1>{

	private T2 otherData;
	
	@Override
	public void doSomething(T1 data) {
		System.out.println("t1="+data);
	}
    
    public SubGenericClass(T2 otherData) {
        this.otherData = otherData;
    }
    
    public T2 getOtherData() {
        return otherData;
    }

}

這樣泛型子類就實現了泛型父類,併在子類中增加了一個新的泛型,最終的結果如下所示:

public class Demo09 {

	public static void main(String[] args) {
		SubGenericClass<Integer,String> sub=new SubGenericClass<>("hello");
		sub.doSomething(100);
		String otherData = sub.getOtherData();
		System.out.println("t2---data="+otherData);
	}
}

其實,實現泛型介面和繼承泛型類都很簡單,我們只需要在類定義中使用相同的泛型類型參數,然後實現介面的方法或覆蓋超類的方法即可。

以上就是關於泛型的概念、作用、泛型介面、泛型類等相關的內容,其實泛型的內容還有很多,比如泛型方法、泛型擦除和泛型中的通配符等。但受限於篇幅,會在下一篇文章中繼續給大家講解這些內容,敬請繼續關註哦。


五. 結語

至此,在本文中就把泛型的概念、作用、泛型介面和泛型類給大家介紹完了,本文重點內容如下:

  • 泛型是一種類型參數,可以編寫模板代碼來適應任意類型;
  • 泛型在使用時不必對類型進行強制轉換,它可以通過編譯器在編譯階段對類型進行檢查;
  • 使用泛型時可以把泛型參數< T >替換成想要的class類型,例如 ArrayList< String> ArrayList< Number >等;
  • 編譯器可以根據前面的泛型,在後面自動推斷出類型,例如List< String > list = new ArrayList<>();
  • 如果我們在使用時不指定泛型參數類型時,編譯器會給出警告,且只能將 < T >視為Object類型;
  • 我們可以在介面和類中定義泛型類型,實現此介面的類必須傳入正確的泛型類型;
  • 我們可以同時定義多個泛型,例如 Map<K, V>
  • 可以繼承泛型類和實現泛型介面。


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

-Advertisement-
Play Games
更多相關文章
  • # 1. Netty總體結構 ## 1.1 Netty簡介 ​ Netty是一款用於創建高性能網路應用程式的高級框架。它的基於 Java NIO 的非同步的和事件驅動的實現,保證了高負載下應用程式性能的最大化和可伸縮性。 ​ 其次,Netty 也包含了一組**設計模式**,將應用程式邏輯從網路層解耦, ...
  • 1. 多線程程式在一個核的CPU運行 ![image.png](https://cdn.nlark.com/yuque/0/2023/png/35902537/1685453577663-714d9c16-e8a3-4828-bb86-86dfa10c8e52.png#averageHue=%23f ...
  • ![](https://img2023.cnblogs.com/other/1218593/202305/1218593-20230531145646615-374710580.png) ## **1.簡介** Grep Console是一款方便開發者對idea控制台輸出日誌進行個性化管理的插件。 ...
  • # 基於 Web 實現 m3u8 視頻播放的簡單應用示例 ## 實現思路 將視頻(MP4 等)轉換為 M3U8 視頻的服務,可以按照以下步驟進行操作: 1. 將視頻(MP4 等)轉換為 M3U8:在服務中,使用適當的工具(如 FFmpeg)將接收到的視頻(MP4 等)轉換為 M3U8 格式。這將生成 ...
  • 裝飾器在 Python 中扮演了重要的角色,這是一種精巧的語言特性,讓我們能夠修改或增強函數和類的行為,無需修改它們的源代碼。這篇文章將深入探討裝飾器的所有相關主題,包括裝飾器的基礎知識、實現與使用、工作原理,以及通過實際例子學習裝飾器的獨特用法。 ...
  • ## 併發與並行😣 ### 併發與並行的概念和區別 並行:同一個時間段內多個任務同時在不同的CPU核心上執行。強調同一時刻多個任務之間的”**同時執行**“。 併發:同一個時間段內多個任務都在進展。強調多個任務間的”**交替執行**“。 ![](https://img2023.cnblogs.co ...
  • 摘要:在讀多寫少的環境中,有沒有一種比ReadWriteLock更快的鎖呢?有,那就是JDK1.8中新增的StampedLock! 本文分享自華為雲社區《【高併發】高併發場景下一種比讀寫鎖更快的鎖》,作者: 冰 河。 什麼是StampedLock? ReadWriteLock鎖允許多個線程同時讀取共 ...
  • ###BIO:同步阻塞 主線程發起io請求後,需要等待當前io操作完成,才能繼續執行。 ###NIO:同步非阻塞 引入selector、channel、等概念,當主線程發起io請求後,輪詢的查看系統是否準備好執行io操作,沒有準備好則主線程不會阻塞會繼續執行,準備好主線程會阻塞等待io操作完成。 # ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...