成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么源碼中都使用16進制進行狀態管理?

開發 前端
在計算機中,一個字節有八位,最大值為 1111 1111。對應的10進制數是255,對應的16進制是 FF。所以半個字節用16進制是可以通過一個字母就能表示,而轉換成10進制就是一個無規律的數字。

[[402867]]

前言

在Android源碼中,對于“多狀態”的管理總是通過16進制數字來表示,類似這種格式:

  1. //ViewGroup.java 
  2.  
  3. protected int mGroupFlags; 
  4.  
  5. static final int FLAG_CLIP_CHILDREN = 0x1; 
  6. private static final int FLAG_CLIP_TO_PADDING = 0x2; 
  7. static final int FLAG_INVALIDATE_REQUIRED  = 0x4; 
  8. private static final int FLAG_RUN_ANIMATION = 0x8; 
  9. static final int FLAG_ANIMATION_DONE = 0x10; 
  10. private static final int FLAG_PADDING_NOT_NULL = 0x20; 

那么,你有沒有想過為什么遇到多狀態的管理,就選擇用16進制?

簡單的狀態表示

來舉個實際的例子,我們作為一個人,身上肯定會有很多標簽,比如帥氣、可愛、博學、機智、懶惰、小氣。

針對這些標簽,我們就可以設定不同的人設:

  1. //定義實體類 
  2.  data class Person(var tag : String) 
  3.  
  4. //修改標簽 
  5.  val person1 = Person("帥氣"
  6.  
  7.  //判斷標簽 
  8.   fun isCute():Boolean{ 
  9.    return person1.tag == "可愛" 
  10.   } 

當一個人只有一個標簽的時候是很簡單的,直接賦值或者取值判斷即可。但是,如果一個人有多個標簽呢?

也很簡單,使用集合存儲即可:

  1. val person2 = Person(mutableListOf()) 
  2. person2.tags.add("帥氣"
  3. person2.tags.add("可愛"
  4.  
  5. person2.tags.remove("可愛"
  6.  
  7. person2.tags.contains("可愛")  

但是用到集合之后,這個計算就變得比較復雜了,由于remove和contains方法都是通過遍歷集合的方式實現的,從時間復雜度角度看的話,當刪除某個標簽或者判斷某個標簽是否存在的時間復雜度都是O(n)。

有沒有什么辦法讓多個標簽也像剛才的單個標簽那么簡單地使用操作呢?

二進制運算

當然有啦,不然這篇文章也不會有了,在這之前,我們先復習下二進制的幾種運算。

  • 1、按位與(&)

當兩個對應位的值都為1,則結果為1,否則為0。

舉例:0x1 & 0x4

  1. 0001 & 
  2. 0100 
  3.      = 
  4. 0000 
  • 2、按位或(|)

當兩個對應位的值都只要有一位是1,則結果為1。

舉例:0x1 | 0x4

  1. 0001 | 
  2. 0100 
  3.      = 
  4. 0101 
  • 3、取反( ~ )

將一個數按位取反。

舉例:~ 0x1

  1. 0001 ~ 
  2.      = 
  3. 1110      

好了,有了這三種運算,我們的狀態管理就足夠了。

引入16進制

接下來,就來完成一個完整的狀態管理例子。

  1. //設定所有狀態對應的16進制值 
  2.  
  3. //可愛,對應二進制0001 
  4. val TAG_CUTE = Ox1   
  5. //帥氣,對應二進制0010  
  6. val TAG_HANDSOME = Ox2 
  7. //博學,對應二進制0100 
  8. val TAG_LEARNED = Ox4 
  9.  
  10. var personTag = 0 

狀態增加

如果一個二進制數字想留下另一個二進制數字的痕跡,我們可以通過或運算,這樣只要第二個數字某位上有1,那么最終的結果在同樣的位數肯定也是1。

所以,我們可以通過這個方法來完成狀態增加的功能:

  1. //增加可愛狀態 
  2. personTag |= TAG_CUTE 
  3.  
  4. 0000 | 
  5. 0001  
  6. 0001 

這樣操作之后,personTag的第四位上的數字就為1了,也就帶有TAG_CUTE這個標記了。

狀態移除

按照上述的邏輯,狀態的移除其實就是需要把對應的位數從1改為0。

假設personTag現在的值變成了二進制數0111。

如果要刪除TAG_CUTE屬性,就需要把第四位的1改為0。那么我們可以做的操作就是先對TAG_CUTE取反,也就是把0001,變成了1110。然后再和personTag進行與運算,這樣第四位肯定就會變為0,而其他位上面的值不變。

  1. //personTag為二進制數0111 
  2. personTag &= ~TAG_CUTE 
  3.  
  4. 0001 ~ 
  5. 1110 & 
  6. 0111 
  7. 0110 

完成對TAG_CUTE狀態的移除。

狀態判斷

同理,對是否有某個狀態的判斷,其實就是判斷在某個位上是否值為1。所以我們只需要對狀態進行 與運算,如果結果為0,就代表沒有這個狀態,否則就代表有這個狀態。

  1. //personTag為二進制數0111 
  2. (personTag & TAG_CUTE) != 0 
  3.  
  4. 0111 & 
  5. 0001 
  6. 0001 

結果不為0,所以代表personTag 包含了 TAG_CUTE 這個狀態。

注意的點

細心的朋友可能會發現,剛才我們用到的16進制值,跳過了Ox3這個值,這是為什么呢?

其實不難發現,所謂的通過16進制管理狀態,其實是通過二進制來管理狀態,歸根結底是通過二進制中的1所在的位數來進行管理。

所以我們對狀態賦值,需要選取單獨占有一位的二進制值,比如0001 ,0010,0100,1000,10000等等。

如果用了其他值會發生什么呢?舉個例子,增加Ox3的TAG。

  1. //懶惰,對應二進制0011 
  2. val TAG_LAZY = Ox3 
  3.  
  4.  
  5. //增加可愛狀態 
  6. personTag |= TAG_CUTE 
  7. //增加帥氣狀態 
  8. personTag |= TAG_HANDSOME 

在我們增加了可愛和帥氣狀態之后,personTag的二進制值為 0011。

這時候再對它進行判斷,是否含有懶惰狀態:

  1. //是否含有懶惰狀態 
  2. (personTag & TAG_LAZY) != 0 
  3.  
  4. 0011 & 
  5. 0011  
  6. 0011 

結果不為0,難道我們增加了懶惰狀態嗎?很明顯沒有,我不懶但是卻說我懶,這是誣陷!

所以你明白狀態取值的范圍了嗎?

為什么是16進制?

到此,通過16進制管理狀態的功能已經實現了,很明顯這種方式管理狀態要簡便許多,其根本原理就是通過二進制的計算來完成對狀態的管理。

有人又要問了,既然本質是通過二進制來完成管理,那么用10進制來表示也可以啊,比如上述的例子:

  1. //設定所有狀態對應的10進制值 
  2.  
  3. //可愛,對應二進制0001 
  4. val TAG_CUTE = 1   
  5. //帥氣,對應二進制0010  
  6. val TAG_HANDSOME = 2 
  7. //博學,對應二進制0100 
  8. val TAG_LEARNED = 4 
  9.  
  10. var personTag = 0 

這跟16進制不是一樣么?

從根本來說,確實是一樣的,但是16進制有16進制的好處,這就涉及到16進制為什么被設計出來的原因了。

在計算機中,一個字節有八位,最大值為 1111 1111。對應的10進制數是255,對應的16進制是 FF。所以半個字節用16進制是可以通過一個字母就能表示,而轉換成10進制就是一個無規律的數字。為了方便,代碼中一般使用16進制來表示 二進制,就是因為其可以和二進制進行一個更方便直觀的轉換。

總結

今天和大家介紹了下源碼中常用的通過16進制轉換2進制來管理狀態的方法。

 

簡單的、基礎的道理解決大問題,這也許就是大道從簡的含義?

 

責任編輯:武曉燕 來源: 碼上積木
相關推薦

2024-10-24 19:25:48

2024-01-12 07:46:07

MQTT協議物聯網應用.NET

2012-03-06 09:20:02

ibmdw

2022-09-08 08:02:26

MySQL隔離

2010-06-12 11:11:55

UML應用

2011-04-01 16:23:14

Cacti監控Nginx

2017-04-05 16:40:45

2021-02-11 13:30:56

Nodejs源碼c++

2023-10-10 09:19:59

日志Java

2012-09-26 10:02:44

框架開發項目

2020-04-07 13:40:13

GraphQLAPI編程語言

2021-04-26 20:44:59

Nacos方法String.inte

2014-08-13 14:48:01

LinuxShell腳本

2024-02-22 08:17:31

十六進制數字計算

2014-11-21 10:50:26

JavaString

2011-03-08 12:59:38

proftpd

2010-06-17 15:53:41

WAP協議

2017-07-03 13:33:42

AndroidItemDecorat

2020-07-03 07:59:01

Linux服務systemd

2020-07-30 12:16:33

阿里巴巴Apache對象
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩av看片| 久久久久亚洲 | 亚洲毛片在线观看 | 日韩在线免费视频 | 久久狠狠 | 精品久| 亚洲资源在线 | 中文字幕 在线观看 | 麻豆视频国产在线观看 | 国产综合久久久 | 亚洲图片视频一区 | 毛片久久久| 99热.com| 日韩在线视频一区 | 国产在线中文字幕 | jvid精品资源在线观看 | 美女天天干 | 日本精品在线播放 | 国产欧美一区二区三区在线看 | 国产精品无码永久免费888 | 亚洲一区二区三区四区五区午夜 | 国产高清性xxxxxxxx | 亚洲精品免费在线 | 久久男人 | 久久久一二三 | 国产传媒视频在线观看 | 欧美日韩三区 | 亚洲精品在 | 国产精品夜色一区二区三区 | 国产精品免费看 | 在线观看免费av网 | 日日碰狠狠躁久久躁96avv | www.成人.com| 国产最新精品视频 | 亚洲视频精品 | 国产欧美日韩综合精品一区二区 | 精品av天堂毛片久久久借种 | 一区二区三区不卡视频 | 91欧美精品成人综合在线观看 | 嫩草视频在线免费观看 | 久久神马 |