1. 程式人生 > 實用技巧 >java基本型別

java基本型別

參考:

https://www.cnblogs.com/doit8791/archive/2012/05/25/2517448.html

https://www.cnblogs.com/zhuyeshen/p/11642211.html

https://blog.csdn.net/weixin_42570248/article/details/89786882

https://www.runoob.com/java/java-basic-datatypes.html

https://blog.csdn.net/qq_20264581/article/details/83755789

Java 基本資料型別

變數就是申請記憶體來儲存值。也就是說,當建立變數的時候,需要在記憶體中申請空間。

記憶體管理系統根據變數的型別為變數分配儲存空間,分配的空間只能用來儲存該型別資料。

因此,通過定義不同型別的變數,可以在記憶體中儲存整數、小數或者字元。

Java 的兩大資料型別:

  • 內建資料型別
  • 引用資料型別

內建資料型別

Java語言提供了八種基本型別。六種數字型別(四個整數型,兩個浮點型),一種字元型別,還有一種布林型。

byte:

  • byte 資料型別是8位、有符號的,以二進位制補碼錶示的整數;
  • 最小值是-128(-2^7);
  • 最大值是127(2^7-1);
  • 預設值是0;
  • byte 型別用在大型陣列中節約空間,主要代替整數,因為 byte 變數佔用的空間只有 int 型別的四分之一;
  • 例子:byte a = 100,byte b = -50。

short:

  • short 資料型別是 16 位、有符號的以二進位制補碼錶示的整數
  • 最小值是-32768(-2^15);
  • 最大值是32767(2^15 - 1);
  • Short 資料型別也可以像 byte 那樣節省空間。一個short變數是int型變數所佔空間的二分之一;
  • 預設值是0;
  • 例子:short s = 1000,short r = -20000。

int:

  • int 資料型別是32位、有符號的以二進位制補碼錶示的整數;
  • 最小值是-2,147,483,648(-2^31);
  • 最大值是2,147,483,647(2^31 - 1);
  • 一般地整型變數預設為 int 型別;
  • 預設值是0;
  • 例子:int a = 100000, int b = -200000。

long:

  • long 資料型別是 64 位、有符號的以二進位制補碼錶示的整數;
  • 最小值是-9,223,372,036,854,775,808(-2^63);
  • 最大值是9,223,372,036,854,775,807(2^63 -1);
  • 這種型別主要使用在需要比較大整數的系統上;
  • 預設值是0L;
  • 例子: long a = 100000L,Long b = -200000L。
    "L"理論上不分大小寫,但是若寫成"l"容易與數字"1"混淆,不容易分辯。所以最好大寫。

float:

  • float 資料型別是單精度、32位、符合IEEE 754標準的浮點數;
  • float 在儲存大型浮點陣列的時候可節省記憶體空間;
  • 預設值是0.0f;
  • 浮點數不能用來表示精確的值,如貨幣;
  • 例子:float f1 = 234.5f。

double:

  • double 資料型別是雙精度、64 位、符合IEEE 754標準的浮點數;
  • 浮點數的預設型別為double型別;
  • double型別同樣不能表示精確的值,如貨幣;
  • 預設值是0.0d;
  • 例子:double d1 = 123.4。

boolean:

  • boolean資料型別表示一位的資訊;
  • 只有兩個取值:true 和 false;
  • 這種型別只作為一種標誌來記錄 true/false 情況;
  • 預設值是false;
  • 例子:boolean one = true。

char:

  • char型別是一個單一的 16 位 Unicode 字元;
  • 最小值是\u0000(即為0);
  • 最大值是\uffff(即為65,535);
  • char 資料型別可以儲存任何字元;
  • 例子:char letter = 'A';。

例項

對於數值型別的基本型別的取值範圍,我們無需強制去記憶,因為它們的值都已經以常量的形式定義在對應的包裝類中了。請看下面的例子:

例項

public class PrimitiveTypeTest { public static void main(String[] args) { // byte System.out.println("基本型別:byte 二進位制位數:" + Byte.SIZE); System.out.println("包裝類:java.lang.Byte"); System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE); System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE); System.out.println(); // short System.out.println("基本型別:short 二進位制位數:" + Short.SIZE); System.out.println("包裝類:java.lang.Short"); System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE); System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE); System.out.println(); // int System.out.println("基本型別:int 二進位制位數:" + Integer.SIZE); System.out.println("包裝類:java.lang.Integer"); System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE); System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE); System.out.println(); // long System.out.println("基本型別:long 二進位制位數:" + Long.SIZE); System.out.println("包裝類:java.lang.Long"); System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE); System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE); System.out.println(); // float System.out.println("基本型別:float 二進位制位數:" + Float.SIZE); System.out.println("包裝類:java.lang.Float"); System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE); System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE); System.out.println(); // double System.out.println("基本型別:double 二進位制位數:" + Double.SIZE); System.out.println("包裝類:java.lang.Double"); System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE); System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE); System.out.println(); // char System.out.println("基本型別:char 二進位制位數:" + Character.SIZE); System.out.println("包裝類:java.lang.Character"); // 以數值形式而不是字元形式將Character.MIN_VALUE輸出到控制檯 System.out.println("最小值:Character.MIN_VALUE=" + (int) Character.MIN_VALUE); // 以數值形式而不是字元形式將Character.MAX_VALUE輸出到控制檯 System.out.println("最大值:Character.MAX_VALUE=" + (int) Character.MAX_VALUE); }}
執行例項 »

編譯以上程式碼輸出結果如下所示:

基本型別:byte 二進位制位數:8
包裝類:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127

基本型別:short 二進位制位數:16
包裝類:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767

基本型別:int 二進位制位數:32
包裝類:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647

基本型別:long 二進位制位數:64
包裝類:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807

基本型別:float 二進位制位數:32
包裝類:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38

基本型別:double 二進位制位數:64
包裝類:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308

基本型別:char 二進位制位數:16
包裝類:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535

Float和Double的最小值和最大值都是以科學記數法的形式輸出的,結尾的"E+數字"表示E之前的數字要乘以10的多少次方。比如3.14E3就是3.14 × 103=3140,3.14E-3 就是 3.14 x 10-3=0.00314。

實際上,JAVA中還存在另外一種基本型別 void,它也有對應的包裝類 java.lang.Void,不過我們無法直接對它們進行操作。

型別預設值

下表列出了 Java 各個型別的預設值:

資料型別預設值
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char 'u0000'
String (or any object) null
boolean false

例項

public class Test { static boolean bool; static byte by; static char ch; static double d; static float f; static int i; static long l; static short sh; static String str; public static void main(String[] args) { System.out.println("Bool :" + bool); System.out.println("Byte :" + by); System.out.println("Character:" + ch); System.out.println("Double :" + d); System.out.println("Float :" + f); System.out.println("Integer :" + i); System.out.println("Long :" + l); System.out.println("Short :" + sh); System.out.println("String :" + str); } }

例項輸出結果為:

Bool     :false
Byte     :0
Character:
Double   :0.0
Float    :0.0
Integer  :0
Long     :0
Short    :0
String   :null

引用型別

  • 在Java中,引用型別的變數非常類似於C/C++的指標。引用型別指向一個物件,指向物件的變數是引用變數。這些變數在宣告時被指定為一個特定的型別,比如 Employee、Puppy 等。變數一旦聲明後,型別就不能被改變了。
  • 物件、陣列都是引用資料型別。
  • 所有引用型別的預設值都是null。
  • 一個引用變數可以用來引用任何與之相容的型別。
  • 例子:Site site = new Site("Runoob")。

Java 常量

常量在程式執行時是不能被修改的。

在 Java 中使用 final 關鍵字來修飾常量,宣告方式和變數類似:

final double PI = 3.1415927;

雖然常量名也可以用小寫,但為了便於識別,通常使用大寫字母表示常量。

字面量可以賦給任何內建型別的變數。例如:

byte a = 68;
char a = 'A'

byte、int、long、和short都可以用十進位制、16進位制以及8進位制的方式來表示。

當使用字面量的時候,字首0表示 8 進位制,而字首0x代表 16 進位制, 例如:

int decimal = 100;
int octal = 0144;
int hexa =  0x64;

和其他語言一樣,Java的字串常量也是包含在兩個引號之間的字元序列。下面是字串型字面量的例子:

"Hello World"
"two\nlines"
"\"This is in quotes\""

字串常量和字元常量都可以包含任何Unicode字元。例如:

char a = '\u0001';
String a = "\u0001";

Java語言支援一些特殊的轉義字元序列。

符號字元含義
\n 換行 (0x0a)
\r 回車 (0x0d)
\f 換頁符(0x0c)
\b 退格 (0x08)
\0 空字元 (0x0)
\s 空格 (0x20)
\t 製表符
\" 雙引號
\' 單引號
\\ 反斜槓
\ddd 八進位制字元 (ddd)
\uxxxx 16進位制Unicode字元 (xxxx)

自動型別轉換

整型、實型(常量)、字元型資料可以混合運算。運算中,不同型別的資料先轉化為同一型別,然後進行運算。

轉換從低階到高階。

  ------------------------------------>  

byte,short,char—> int —> long—> float —> double

資料型別轉換必須滿足如下規則:

  • 1. 不能對boolean型別進行型別轉換。

  • 2. 不能把物件型別轉換成不相關類的物件。

  • 3. 在把容量大的型別轉換為容量小的型別時必須使用強制型別轉換。

  • 4. 轉換過程中可能導致溢位或損失精度,例如:

    int i =128;   
    byte b = (byte)i;

    因為 byte 型別是 8 位,最大值為127,所以當 int 強制轉換為 byte 型別時,值 128 時候就會導致溢位。

  • 5. 浮點數到整數的轉換是通過捨棄小數得到,而不是四捨五入,例如:

    (int)23.7 == 23;
    (int)-45.89f == -45

自動型別轉換

必須滿足轉換前的資料型別的位數要低於轉換後的資料型別,例如: short資料型別的位數為16位,就可以自動轉換位數為32的int型別,同樣float資料型別的位數為32,可以自動轉換為64位的double型別。

例項

public class ZiDongLeiZhuan{ public static void main(String[] args){ char c1='a';//定義一個char型別 int i1 = c1;//char自動型別轉換為int System.out.println("char自動型別轉換為int後的值等於"+i1); char c2 = 'A';//定義一個char型別 int i2 = c2+1;//char 型別和 int 型別計算 System.out.println("char型別和int計算後的值等於"+i2); } }

執行結果為:

char自動型別轉換為int後的值等於97
char型別和int計算後的值等於66

解析:c1 的值為字元a,查 ASCII 碼錶可知對應的 int 型別值為 97, A 對應值為 65,所以i2=65+1=66。

強制型別轉換

  • 1. 條件是轉換的資料型別必須是相容的。

  • 2. 格式:(type)value type是要強制型別轉換後的資料型別 例項:

    例項

    public class QiangZhiZhuanHuan{ public static void main(String[] args){ int i1 = 123; byte b = (byte)i1;//強制型別轉換為byte System.out.println("int強制型別轉換為byte後的值等於"+b); } }

    執行結果:

    int強制型別轉換為byte後的值等於123

隱含強制型別轉換

  • 1. 整數的預設型別是 int。

  • 2. 浮點型不存在這種情況,因為在定義 float 型別時必須在數字後面跟上 F 或者 f。

這一節講解了 Java 的基本資料型別。

Java基本資料型別總結

基本型別,或者叫做內建型別,是JAVA中不同於類的特殊型別。它們是我們程式設計中使用最頻繁的型別。java是一種強型別語言,第一次申明變數必須說明資料型別,第一次變數賦值稱為變數的初始化。

1. Java的簡單型別及其封裝器類

Java基本型別共有八種,基本型別可以分為三類,字元型別char,布林型別boolean以及數值型別byte、short、int、long、float、double。數值型別又可以分為整數型別byte、short、int、long和浮點數型別float、double。JAVA中的數值型別不存在無符號的,它們的取值範圍是固定的,不會隨著機器硬體環境或者作業系統的改變而改變。實際上,JAVA中還存在另外一種基本型別void,它也有對應的包裝類 java.lang.Void,不過我們無法直接對它們進行操作。8 中型別表示範圍如下:

byte:8位,最大儲存資料量是255,存放的資料範圍是-128~127之間。

short:16位,最大資料儲存量是65536,資料範圍是-32768~32767之間。

int:32位,最大資料儲存容量是2的32次方減1,資料範圍是負的2的31次方到正的2的31次方減1。

long:64位,最大資料儲存容量是2的64次方減1,資料範圍為負的2的63次方到正的2的63次方減1。

float:32位,資料範圍在3.4e-45~1.4e38,直接賦值時必須在數字後加上f或F。

double:64位,資料範圍在4.9e-324~1.8e308,賦值時可以加d或D也可以不加。

boolean:只有true和false兩個取值。

char:16位,儲存Unicode碼,用單引號賦值。

Java決定了每種簡單型別的大小。這些大小並不隨著機器結構的變化而變化。這種大小的不可更改正是Java程式具有很強移植能力的原因之一。下表列出了Java中定義的簡單型別、佔用二進位制位數及對應的封裝器類。

簡單型別

boolean

byte

char

short

Int

long

float

double

void

二進位制位數

1

8

16

16

32

64

32

64

--

封裝器類

Boolean

Byte

Character

Short

Integer

Long

Float

Double

Void

對於數值型別的基本型別的取值範圍,我們無需強制去記憶,因為它們的值都已經以常量的形式定義在對應的包裝類中了。如:

基本型別byte 二進位制位數:Byte.SIZE最小值:Byte.MIN_VALUE最大值:Byte.MAX_VALUE

基本型別short二進位制位數:Short.SIZE最小值:Short.MIN_VALUE最大值:Short.MAX_VALUE

基本型別char二進位制位數:Character.SIZE最小值:Character.MIN_VALUE最大值:Character.MAX_VALUE

基本型別double 二進位制位數:Double.SIZE最小值:Double.MIN_VALUE最大值:Double.MAX_VALUE

注意:float、double兩種型別的最小值與Float.MIN_VALUE、 Double.MIN_VALUE的值並不相同,實際上Float.MIN_VALUE和Double.MIN_VALUE分別指的是 float和double型別所能表示的最小正數。也就是說存在這樣一種情況,0到±Float.MIN_VALUE之間的值float型別無法表示,0 到±Double.MIN_VALUE之間的值double型別無法表示。這並沒有什麼好奇怪的,因為這些範圍內的數值超出了它們的精度範圍。

Float和Double的最小值和最大值都是以科學記數法的形式輸出的,結尾的"E+數字"表示E之前的數字要乘以10的多少倍。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314。

Java基本型別儲存在棧中,因此它們的存取速度要快於儲存在堆中的對應包裝類的例項物件。從Java5.0(1.5)開始,JAVA虛擬機器(Java Virtual Machine)可以完成基本型別和它們對應包裝類之間的自動轉換。因此我們在賦值、引數傳遞以及數學運算的時候像使用基本型別一樣使用它們的包裝類,但這並不意味著你可以通過基本型別呼叫它們的包裝類才具有的方法。另外,所有基本型別(包括void)的包裝類都使用了final修飾,因此我們無法繼承它們擴充套件新的類,也無法重寫它們的任何方法。

基本型別的優勢:資料儲存相對簡單,運算效率比較高

包裝類的優勢:有的容易,比如集合的元素必須是物件型別,滿足了java一切皆是物件的思想

2.Java中的常量

十六進位制整型常量:以十六進位制表示時,需以0x或0X開頭,如0xff,0X9A。

八進位制整型常量:八進位制必須以0開頭,如0123,034。

長整型:長整型必須以L作結尾,如9L,342L。

浮點數常量:由於小數常量的預設型別是double型,所以float型別的後面一定要加f(F)。同樣帶小數的變數預設為double型別。

如:float f;

f=1.3f;//必須宣告f。

字元常量:字元型常量需用兩個單引號括起來(注意字串常量是用兩個雙引號括起來)。Java中的字元佔兩個位元組。一些常用的轉義字元:

①\r表示接受鍵盤輸入,相當於按下了回車鍵;

②\n表示換行;

③\t表示製表符,相當於Table鍵;

④\b表示退格鍵,相當於Back Space鍵;

⑤\'表示單引號;

⑥\''表示雙引號;

⑦\\表示一個斜槓\。

3. 資料型別之間的轉換

1).簡單型別資料間的轉換,有兩種方式:自動轉換和強制轉換,通常發生在表示式中或方法的引數傳遞時。

自動轉換

具體地講,當一個較"小"資料與一個較"大"的資料一起運算時,系統將自動將"小"資料轉換成"大"資料,再進行運算。而在方法呼叫時,實際引數較"小",而被呼叫的方法的形式引數資料又較"大"時(若有匹配的,當然會直接呼叫匹配的方法),系統也將自動將"小"資料轉換成"大"資料,再進行方法的呼叫,自然,對於多個同名的過載方法,會轉換成最"接近"的"大"資料並進行呼叫。這些型別由"小"到"大"分別為 (byte,short,char)--int--long--float—double。這裡我們所說的"大"與"小",並不是指佔用位元組的多少,而是指表示值的範圍的大小。

①下面的語句可以在Java中直接通過:

byte b;int i=b; long l=b; float f=b; double d=b;

②如果低階型別為char型,向高階型別(整型)轉換時,會轉換為對應ASCII碼值,例如

char c='c'; int i=c;

System.out.println("output:"+i);輸出:output:99;

③對於byte,short,char三種類型而言,他們是平級的,因此不能相互自動轉換,可以使用下述的強制型別轉換。

short i=99 ; char c=(char)i; System.out.println("output:"+c);輸出:output:c;

強制轉換

將"大"資料轉換為"小"資料時,你可以使用強制型別轉換。即你必須採用下面這種語句格式: int n=(int)3.14159/2;可以想象,這種轉換肯定可能會導致溢位或精度的下降。

2)表示式的資料型別自動提升, 關於型別的自動提升,注意下面的規則。

①所有的byte,short,char型的值將被提升為int型;

②如果有一個運算元是long型,計算結果是long型;

③如果有一個運算元是float型,計算結果是float型;

④如果有一個運算元是double型,計算結果是double型;

例, byte b; b=3; b=(byte)(b*3);//必須宣告byte。

3)包裝類過渡型別轉換

一般情況下,我們首先宣告一個變數,然後生成一個對應的包裝類,就可以利用包裝類的各種方法進行型別轉換了。例如:

①當希望把float型轉換為double型時:

float f1=100.00f;

Float F1=new Float(f1);

double d1=F1.doubleValue();//F1.doubleValue()為Float類的返回double值型的方法

②當希望把double型轉換為int型時:

double d1=100.00;

Double D1=new Double(d1);

int i1=D1.intValue();

簡單型別的變數轉換為相應的包裝類,可以利用包裝類的建構函式。即:Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)

而在各個包裝類中,總有形為××Value()的方法,來得到其對應的簡單型別資料。利用這種方法,也可以實現不同數值型變數間的轉換,例如,對於一個雙精度實型類,intValue()可以得到其對應的整型變數,而doubleValue()可以得到其對應的雙精度實型變數。

4)字串與其它型別間的轉換

其它型別向字串的轉換

①呼叫類的串轉換方法:X.toString();

②自動轉換:X+"";

③使用String的方法:String.volueOf(X);

字串作為值,向其它型別的轉換

①先轉換成相應的封裝器例項,再呼叫對應的方法轉換成其它型別

例如,字元中"32.1"轉換double型的值的格式為:new Float("32.1").doubleValue()。也可以用:Double.valueOf("32.1").doubleValue()

②靜態parseXXX方法

String s = "1";

byte b = Byte.parseByte( s );

short t = Short.parseShort( s );

int i = Integer.parseInt( s );

long l = Long.parseLong( s );

Float f = Float.parseFloat( s );

Double d = Double.parseDouble( s );

③Character的getNumericValue(char ch)方法

5)Date類與其它資料型別的相互轉換

整型和Date類之間並不存在直接的對應關係,只是你可以使用int型為分別表示年、月、日、時、分、秒,這樣就在兩者之間建立了一個對應關係,在作這種轉換時,你可以使用Date類建構函式的三種形式:

①Date(int year, int month, int date):以int型表示年、月、日

②Date(int year, int month, int date, int hrs, int min):以int型表示年、月、日、時、分

③Date(int year, int month, int date, int hrs, int min, int sec):以int型表示年、月、日、時、分、秒

在長整型和Date類之間有一個很有趣的對應關係,就是將一個時間表示為距離格林尼治標準時間1970年1月1日0時0分0秒的毫秒數。對於這種對應關係,Date類也有其相應的建構函式:Date(long date)。

獲取Date類中的年、月、日、時、分、秒以及星期你可以使用Date類的getYear()、getMonth()、getDate()、getHours()、getMinutes()、getSeconds()、getDay()方法,你也可以將其理解為將Date類轉換成int。

而Date類的getTime()方法可以得到我們前面所說的一個時間對應的長整型數,與包裝類一樣,Date類也有一個toString()方法可以將其轉換為String類。

有時我們希望得到Date的特定格式,例如20020324,我們可以使用以下方法,首先在檔案開始引入,

import java.text.SimpleDateFormat;

import java.util.*;

java.util.Date date = new java.util.Date();

//如果希望得到YYYYMMDD的格式

SimpleDateFormat sy1=new SimpleDateFormat("yyyyMMDD");

String dateFormat=sy1.format(date);

//如果希望分開得到年,月,日

SimpleDateFormat sy=new SimpleDateFormat("yyyy");

SimpleDateFormat sm=new SimpleDateFormat("MM");

SimpleDateFormat sd=new SimpleDateFormat("dd");

String syear=sy.format(date);

String smon=sm.format(date);

String sday=sd.format(date);

總結:只有boolean不參與資料型別的轉換

(1).自動型別的轉換:a.常數在表數範圍內是能夠自動型別轉換的

b.資料範圍小的能夠自動資料型別大的轉換(注意特例)

int到float,long到float,long到double 是不會自動轉換的,不然將會丟失精度

c.引用型別能夠自動轉換為父類的

d.基本型別和它們包裝型別是能夠互相轉換的

(2).強制型別轉換:用圓括號括起來目標型別,置於變數前

4.Java引用型別

Java有 5種引用型別(物件型別):類 介面 陣列 列舉 標註

引用型別:底層結構和基本型別差別較大

JVM的記憶體空間:(1). Heap 堆空間:分配物件 new Student()

(2). Stack 棧空間:臨時變數 Student stu

(3).Code 程式碼區 :類的定義,靜態資源 Student.class

eg:Student stu = new Student(); //new 在記憶體的堆空間建立物件

stu.study(); //把物件的地址賦給stu引用變數

上例實現步驟:a.JVM載入Student.class 到Code區

b.new Student()在堆空間分配空間並建立一個Student例項

c.將此例項的地址賦值給引用stu, 棧空間

MySQL——VARCHAR和CHAR型別

前述

VARCHAR和CHAR是兩種最主要的字串型別。不幸的是,很難精確地解釋這些值是怎麼儲存在磁碟和記憶體中的,因為這跟儲存引擎的具體實現有關。下面的描述假設使用的儲存引擎是InnoDB和/或者MyISAM。如果使用的不是這兩種儲存引擎,請參考所使用的儲存引擎的文件。

先看看VARCHAR和CHAR值通常在磁碟上怎麼儲存。請注意,儲存引擎儲存CHAR或者VARCHAR值的方式在記憶體中和在磁碟上可能不一樣,所以MySQL伺服器從儲存引擎讀出的值可能需要轉換為另一種儲存格式。

VARCHAR型別

VARCHAR型別用於儲存可變長字串,是最常見的字串資料型別。它比定長型別更節省空間,因為它僅使用必要的空間(例如,越短的字串使用越少的空間)。有一種情況例外,如果MySQL表使用ROW_FORMAT=FIXED建立的話,每一行都會使用定長儲存,這會很浪費空間。

VARCHAR需要使用1或2個額外位元組記錄字串的長度:如果列的最大長度小於或等於255位元組,則只使用1個位元組表示,否則使用2個位元組。假設採用latin1字符集,一個VARCHAR(10)的列需要11個位元組的儲存空間。VARCHAR(1000)的列則需要1002個位元組,因為需要2個位元組儲存長度資訊。

VARCHAR節省了儲存空間,所以對效能也有幫助。但是,由於行是變長的,在UPDATE時可能使行變得比原來更長,這就導致需要做額外的工作。如果一個行佔用的空間增長,並且在頁內沒有更多的空間可以儲存,在這種情況下,不同的儲存引擎的處理方式是不一樣的。例如,MyISAM會將行拆成不同的片段儲存,InnoDB則需要分裂頁來使行可以放進頁內。其他一些儲存引擎也許從不在原資料位置更新資料。

VARCHAR適用情況

下面這些情況下適用VARCHAR是合適的:

  • 字串列的最大長度比平均長度大很多
  • 列的更新很少,所以碎片不是問題
  • 使用了像UTF-8這樣複雜的字符集,每個字元都使用不同的位元組數進行儲存

CHAR型別

CHAR型別是定長的:MySQL總是根據定義的字串長度分配足夠的空間。當儲存CHAR值時,MySQL會刪除所有的末尾空格。CHAR值會根據需要採用空格進行填充以方便比較。

CHAR適合儲存很短的字串,或者所有值都接近同一個長度。例如,CHAR非常適合儲存密碼的MD5值,因為這是一個定長的值。對於經常變更的資料,CHAR也比VARCHAR更好,因為定長的CHAR型別不容易產生碎片。對於非常短的列,CHAR比VARCHAR在儲存空間上也更有效率。例如用CHAR(1)來儲存只有Y和N的值,如果採用單位元組字符集只需要一個位元組,但是VARCHAR(1)卻需要兩個位元組,因為還有一個記錄長度的額外位元組。

測試

下面通過例子來具體說明CHAR與VARCHAR行為上的不同,首先,我們建立一張只有一個CHAR(10)欄位的表,並且往裡面插入一些值:

  1. CREATE TABLE char_test
  2. (
  3. char_col CHAR(10)
  4. );
  5. INSERT INTO char_test
  6. VALUES
  7. ('string1').
  8. (' string2').
  9. ('string3 ');

當我們檢索這些值的時候,會發現string3末尾的空格被截斷了。

  1. SELECT CONCAT("'", char_col, "'")
  2. FROM char_test;
執行結果

如果用VARCHAR(10)欄位儲存相同的值,可以得到如下結果:

  1. CREATE TABLE varchar_test
  2. (
  3. varchar_col VARCHAR(10)
  4. );
  5. INSERT INTO varchar_test
  6. VALUES
  7. ('string1').
  8. (' string2').
  9. ('string3 ');
  10. SELECT CONCAT("'", varchar_col, "'")
  11. FROM varchar_test;
執行結果

VARCHAR(5)與VARCHAR(200)的區別

我們倘若用VARCHAR(5)和VARCHAR(200)來儲存'hello',我們知道這兩者的空間開銷是一樣的。那麼我們可以讓VARCHAR的長度始終保持很大嗎?使用更短的列有什麼優勢嗎?

事實證明有很大的優勢。更長的列會消耗更多的記憶體,因為MySQL通常會分配固定大小的記憶體塊來儲存內部值。尤其是使用記憶體臨時表進行排序或操作時會特別糟糕。在利用磁碟臨時表進行排序時也同樣糟糕。

所以最好的策略是隻分配真正需要的空間。

總結

當我們為字串型別的欄位選取型別的時候,判斷該選取VARCHAR還是CHAR,我們可以從以下幾個方面來考慮:

  • 該欄位資料集的平均長度與最大長度是否相差很小,若相差很小優先考慮CHAR型別,反之,考慮VARCHAR型別。
  • 若欄位儲存的是MD5後的雜湊值,或一些定長的值,優先選取CHAR型別。
  • 若欄位經常需要更新,則優先考慮CHAR型別,由於CHAR型別為定長,因此不容易產生碎片。
  • 對於欄位值儲存很小的資訊,如性別等,優先選取CHAR型別,因為VARCHAR型別會佔用額外的位元組儲存字串長度資訊。

總之一句話,當我們能夠選取CHAR型別的時候,或者說空間消耗相對並不是影響因素的重點時,儘量選取CHAR型別,因為在其他方面,CHAR型別都有著或多或少的優勢。而當空間消耗成為了很大的影響因素以後,我們則考慮使用VARCHAR型別。

varchar與char有什麼區別?——[面試系列]

區別一,定長和變長
char 表示定長,長度固定,varchar表示變長,即長度可變。char如果插入的長度小於定義長度時,則用空格填充;varchar小於定義長度時,還是按實際長度儲存,插入多長就存多長。

因為其長度固定,char的存取速度還是要比varchar要快得多,方便程式的儲存與查詢;但是char也為此付出的是空間的代價,因為其長度固定,所以會佔據多餘的空間,可謂是以空間換取時間效率。varchar則剛好相反,以時間換空間。

區別之二,儲存的容量不同
對 char 來說,最多能存放的字元個數 255,和編碼無關。
而 varchar 呢,最多能存放 65532 個字元。varchar的最大有效長度由最大行大小和使用的字符集確定。整體最大長度是 65,532位元組。

一篇文章看懂mysql中varchar能存多少漢字、數字,以及varchar(100)和varchar(10)的區別

看完這篇文章,你能搞清楚以下問題:

1、varchar(100)和varchar(10)的區別在哪裡?

2、varchar能存多少漢字、數字?

3、varchar的最大長度是多少呢?

4、字元、位元組、位,之間的關係?

5、mysql欄位型別儲存需要多少位元組?

接下來請仔細看,整理不易啊。

1、varchar(100)和varchar(10)的區別在哪裡?

一般初學會認為,二者佔用的空間是一樣的。比如說我儲存5個char,二者都是實際佔用了5個char了【不準確的想法:varchar在實際儲存的時候會多一個byte用來存放長度】。
但是深入一下,設計資料庫的時候,二者一樣嗎?
答案是否定的【至少varchar型別需要在資料之前利用一個或者兩個位元組來儲存資料的長度】並且二者在記憶體中的操作方式也是不同的,下面的例子中有體現(例子連結:看下面的例子。)
如現在使用者需要儲存一個地址資訊。根據評估,只要使用100個字元就可以了。但是有些資料庫管理員會認為,反正Varchar資料型別是根據實際的需要來分配長度的。還不如給其大一點的呢。為此他們可能會為這個欄位一次性分配200個字元的儲存空間。這VARCHAR(100)與VARCHAR(200)真的相同嗎?

結果是否定的。雖然他們用來儲存90個字元的資料,其儲存空間相同。但是對於記憶體的消耗是不同的。對於VARCHAR資料型別來說,硬碟上的儲存空間雖然都是根據實際字元長度來分配儲存空間的,但是對於記憶體來說,則不是。其時使用固定大小的記憶體塊來儲存值。簡單的說,就是使用字元型別中定義的長度,即200個字元空間。顯然,這對於排序或者臨時表(這些內容都需要通過記憶體來實現)作業會產生比較大的不利影響。解釋可以參見這裡。如果不想看解釋,我這裡大概說下:假設VARCHAR(100)與VARCHAR(200)型別,實際存90個字元,它不會對儲存端產生影響(就是實際佔用硬碟是一樣的)。但是,它確實會對查詢產生影響,因為當MySql建立臨時表(SORT,ORDER等)時,VARCHAR會轉換為CHAR,轉換後的CHAR的長度就是varchar的長度,在記憶體中的空間就變大了,在排序、統計時候需要掃描的就越多,時間就越久。

所以如果某些欄位會涉及到檔案排序或者基於磁碟的臨時表時,分配VARCHAR資料型別時仍然不能夠太過於慷慨。還是要評估實際需要的長度,然後選擇一個最長的欄位來設定字元長度。如果為了考慮冗餘,可以留10%左右的字元長度。千萬不能認為其為根據實際長度來分配儲存空間,而隨意的分配長度,或者說乾脆使用最大的字元長度。
----------------------------------char------------------------------------------
1、從碎片角度進行考慮,使用CHAR字元型時,由於儲存空間都是一次性分配的。為此某個欄位的內容,其都是儲存在一起的。單從這個角度來講,其不存在碎片的困擾。而可變長度的字元資料型別,其儲存的長度是可變的。當其更改前後資料長度不一致時,就不可避免的會出現碎片的問題。故使用可變長度的字元型資料時,資料庫管理員要時不時的對碎片進行整理。如執行資料庫匯出匯入作業,來消除碎片。
2、考慮其長度的是否相近,如果某個欄位其長度雖然比較長,但是其長度總是近似的,如一般在90個到100個字元之間,甚至是相同的長度。此時比較適合採用CHAR字元型別。比較典型的應用就是MD5雜湊值。當利用MD5雜湊值來儲存使用者密碼時,就非常使用採用CHAR字元型別。因為其長度是相同的。另外,像用來儲存使用者的身份證號碼等等,一般也建議使用CHAR型別的資料。
另外請大家考慮一個問題,CHAR(1)與VARCHAR(1)兩這個定義,會有什麼區別呢?雖然這兩個都只能夠用來儲存單個的字元,但是VARCHAR要比CHAR多佔用一個儲存位置。這主要是因為使用VARCHAR資料型別時,會多用1個位元組用來儲存長度資訊。這個管理上的開銷char字元型別是沒有的。

---------------------------------總結---------------------------------------------

二者在磁碟上儲存佔的空間是一樣的。區別有二。第一、一個變長一個固定長度。第二、在記憶體中的操作方式,varchar也是按照最長的方式在記憶體中進行操作的。比如說要進行排序的時候,varcahr(100)是按照100這個長度來進行的。

2、varchar能存多少漢字、數字?

具體還是要看版本的,一個字元佔用3個位元組 ,一個漢字(包括數字)佔用3個位元組=一個字元

4.0版本以下,varchar(100),指的是100位元組,如果存放UTF8漢字時,只能存33個(每個漢字3位元組)

5.0版本以上,varchar(100),指的是100字元,無論存放的是數字、字母還是UTF8漢字(每個漢字3位元組),都可以存放100個。

UTF8編碼中一個漢字(包括數字)佔用3個位元組

GBK編碼中一個漢字(包括數字)佔用2個位元組

3、varchar的最大長度是多少呢?

mysql的vachar欄位的型別雖然最大長度是65535,但是並不是能存這麼多資料,最大可以到65533,其中需要1到2個位元組來儲存資料長度(如果列宣告的長度超過255,則使用兩個位元組來儲存長度,否則1個)位元組,當不允許非空欄位的時候(因為要用一個位元組來儲存不可為空的標識),當允許非空欄位的時候只能到65532(省下了儲存非空的那個位元組)。

行中可以用的位元組數如下計算:(參考文件:https://www.jianshu.com/p/ee1e4b14c5e7)

欄位非空時候:varchar(65535) -2 bytes (儲存長度,按2個算) - 1byte (latin1型別) - 1 (null byte)=65531位元組可以用

減1的原因是實際行儲存從第二個位元組開始';

欄位可以空時候:varchar(65535) -2 bytes (儲存長度,按2個算) - 1byte (latin1型別) =65532位元組可以用

根據這個最大位元組數,以及編碼方式,可以計算能儲存的漢字數。

4、字元、位元組、位,之間的關係?

1、位:
資料儲存的最小單位。每個二進位制數字0或者1就是1個位;
2、位元組:
8個位構成一個位元組;

即:1 byte (位元組)= 8 bit(位);

1 KB = 1024 B(位元組);
1 MB = 1024 KB; (2^10 B)
1 GB = 1024 MB; (2^20 B)
1 TB = 1024 GB; (2^30 B)

3、字元:

a、A、中、+、*、の......均表示一個字元;
一般 utf-8 編碼下,一個漢字 字元 佔用 3 個 位元組;數字屬於漢字,和漢字佔用一樣位元組。
一般 gbk 編碼下,一個漢字 字元 佔用 2 個 位元組;

5、mysql欄位型別儲存需要多少位元組?

數字型別

列型別 需要的儲存量
TINYINT 1 位元組
SMALLINT 2 個位元組
MEDIUMINT 3 個位元組
INT 4 個位元組
INTEGER 4 個位元組
BIGINT 8 個位元組
FLOAT(X) 4 如果 X < = 24 或 8 如果 25 < = X < = 53
FLOAT 4 個位元組
DOUBLE 8 個位元組
DOUBLE PRECISION 8 個位元組
REAL 8 個位元組
DECIMAL(M,D) M位元組(D+2 , 如果M < D)
NUMERIC(M,D) M位元組(D+2 , 如果M < D)

日期和時間型別

列型別 需要的儲存量
DATE 3 個位元組
DATETIME 8 個位元組
TIMESTAMP 4 個位元組
TIME 3 個位元組
YEAR 1 位元組

串型別

列型別 需要的儲存量
CHAR(M) M位元組,1 <= M <= 255
VARCHAR(M) L+1 位元組, 在此L <= M1 <= M <= 255
TINYBLOB,TINYTEXT L+1 位元組, 在此L< 2 ^ 8
BLOB,TEXT L+2 位元組, 在此L< 2 ^ 16
MEDIUMBLOB,MEDIUMTEXT L+3 位元組, 在此L< 2 ^ 24
LONGBLOB,LONGTEXT L+4 位元組, 在此L< 2 ^ 32
ENUM('value1','value2',...) 1 或 2 個位元組, 取決於列舉值的數目(最大值65535)
SET('value1','value2',...) 1,2,3,4或8個位元組, 取決於集合成員的數量(最多64個成員)

text與blob的區別在於:text不能儲存圖片。blob是二進位制流,text是非二進位制。

mysql 的二進位制資料型別 BINARY, VARBINARY, BLOB 都沒有字符集的概念。