Java強(qiáng)制類型轉(zhuǎn)換的所有規(guī)則及說明
強(qiáng)制轉(zhuǎn)換
在Java中,我們也可以將==數(shù)據(jù)取值范圍大的轉(zhuǎn)換為數(shù)據(jù)取值范圍小到的==,這種轉(zhuǎn)換并不是自動的過程,而是需要我們手動的轉(zhuǎn)換,我們稱這種轉(zhuǎn)換為強(qiáng)制轉(zhuǎn)換。
例如下面代碼:
long a = 10; int b = a; // 報(bào)錯(cuò)
long類型內(nèi)存8個(gè)字節(jié),int類型內(nèi)存4個(gè)字節(jié)。
long取值范圍大于int;想要賦值成功,只有通過強(qiáng)制類型轉(zhuǎn)換,將 long類型強(qiáng)制轉(zhuǎn)換成int類型才能賦值。
強(qiáng)制轉(zhuǎn)換:將 取值范圍大的類型 強(qiáng)制轉(zhuǎn)換成 取值范圍小的類型;比較而言,自動轉(zhuǎn)換是Java自動執(zhí)行的,而強(qiáng)制轉(zhuǎn)換需要我們自己手動執(zhí)行。
強(qiáng)制轉(zhuǎn)換格式:
數(shù)據(jù)類型 變量名 = (數(shù)據(jù)類型)被轉(zhuǎn)數(shù)據(jù)值;
將 1.5 賦值到 int 類型,代碼修改為:
long a = 10; int b = (int)a;
同樣道理,當(dāng)一個(gè) short 類型與 int 類型相加,我們知道會類型提升,但是還想給結(jié)果賦值給 short 類型變量,就需要強(qiáng)制轉(zhuǎn)換。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo04 {
public static void main(String[] args) {
// short類型變量,內(nèi)存中存儲兩個(gè)字節(jié)
short s = 1;
int i = 1;
/*
出現(xiàn)編譯錯(cuò)誤
s和i做運(yùn)算的時(shí)候,i是int類型,s會被提升為int類型
s+i后的結(jié)果是int類型,將結(jié)果在賦值會short類型時(shí)發(fā)生錯(cuò)誤
*/
// s = s + i; // 編譯失敗
s = (short) (s + i); // 強(qiáng)制轉(zhuǎn)換,編譯成功
System.out.println(s);
}
}
1.轉(zhuǎn)換圖解
short 類型內(nèi)存占有2個(gè)字節(jié),在和 int類型運(yùn)算時(shí)會提升為 int 類型 ,自動補(bǔ)充2個(gè)字節(jié),計(jì)算后的結(jié)果還是 int 類型,但最終被強(qiáng)轉(zhuǎn)為了short類型,占用2個(gè)字節(jié)空間。

2.浮點(diǎn)數(shù)與整數(shù)的底層存儲
下面是8個(gè)基本數(shù)據(jù)類型的取值范圍大?。?/p>
| 數(shù)據(jù)類型 | 關(guān)鍵字 | 內(nèi)存占用 | 取值范圍 |
|---|---|---|---|
| 字節(jié)型 | byte | 1個(gè)字節(jié) | -128~127 |
| 短整型 | short | 2個(gè)字節(jié) | -32768~32767 |
| 整型 | int(默認(rèn)) | 4個(gè)字節(jié) | -2147483648~2147483647 |
| 長整型 | long | 8個(gè)字節(jié) | -2的63次方~2的63次方-1 |
| 單精度浮點(diǎn)數(shù) | float | 4個(gè)字節(jié) | 1.4013E-45~3.4028E+38 |
| 雙精度浮點(diǎn)數(shù) | double(默認(rèn)) | 8個(gè)字節(jié) | 4.9E-324~1.7977E+308 |
| 字符型 | char | 2個(gè)字節(jié) | 0-65535 |
| 布爾類型 | boolean | 1個(gè)字節(jié) | true,false |
我們可以發(fā)現(xiàn),int和float都是占用4個(gè)字節(jié)大小,但是float的取值范圍卻比int要大的多。同樣的情況在long與double這兩種類型上也存在;
這是為什么呢?
double與long表示范圍的差距是由于存儲結(jié)構(gòu)的不同導(dǎo)致的,換句話說我們保存1000這個(gè)數(shù),我們long要存儲+1000,其二進(jìn)制為001111101000,而double存儲的是+1E3。
拆開來看,存儲一個(gè)數(shù)double可以分成三部分:
- 尾數(shù)位(1)
- 基數(shù)位(10)
- 指數(shù)位(3)
也就是用科學(xué)計(jì)數(shù)法來存儲,這簡單的1000就能看出差距,long存儲1000需要符號位(+)和數(shù)字位(1000),需要5位。而double存儲,卻只需要3位。
同樣一個(gè)數(shù),double能夠用更少的內(nèi)存存儲,所以多余的內(nèi)存就能存儲更多的數(shù),因此double > long
通過如下代碼可以查看到每個(gè)類型的最大值:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
public static void main(String[] args) {
// 2147483647
System.out.println(Integer.MAX_VALUE);
// 3.4028235E38
System.out.println(Float.MAX_VALUE);
// 9223372036854775807
System.out.println(Long.MAX_VALUE);
// 1.7976931348623157E308
System.out.println(Double.MAX_VALUE);
}
}
3.整數(shù)之間的強(qiáng)制轉(zhuǎn)換
強(qiáng)制轉(zhuǎn)換指的是:取值范圍大的,轉(zhuǎn)換為取值范圍小的。強(qiáng)制轉(zhuǎn)換的時(shí)候尤其要注意轉(zhuǎn)換之后的類型是否能存儲之前的數(shù)據(jù)。
示例1:數(shù)值==沒有超出==轉(zhuǎn)換之后類型的取值范圍的情況
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo05_強(qiáng)制類型轉(zhuǎn)換_整數(shù)轉(zhuǎn)換_01 {
public static void main(String[] args) {
int a = 100;
byte b = (byte) a;
// byte也能存儲100,因此轉(zhuǎn)換的時(shí)候不會出現(xiàn)什么問題
System.out.println(b); // 100
}
}
示例2:數(shù)值==超出了==轉(zhuǎn)換之后類型的取值范圍的情況
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo06_強(qiáng)制類型轉(zhuǎn)換_整數(shù)轉(zhuǎn)換_02 {
public static void main(String[] args) {
// 八個(gè)字節(jié): 00000000 00000000 0000000 10000100 01000000 11000000 11000000 10000000 ---> 十進(jìn)制: 568022057088
long a = 568022057088L;
// 四個(gè)字節(jié): 01000000 11000000 11000000 10000000 ---> 十進(jìn)制: 1086374016
int b = (int) a;
System.out.println(b); // 1086374016
// 兩個(gè)字節(jié): 11000000 10000000 ---> 十進(jìn)制: -16256
short c = (short) b;
System.out.println(c); // -16256
// 一個(gè)字節(jié): 10000000 ---> 十進(jìn)制: -128
byte d = (byte) c;
System.out.println(d); // -128
}
}
4.浮點(diǎn)數(shù)的強(qiáng)制轉(zhuǎn)換
1) 浮點(diǎn)數(shù)轉(zhuǎn)浮點(diǎn)數(shù)
示例1:數(shù)值==沒有超出==轉(zhuǎn)換之后類型的取值范圍的情況
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo07_強(qiáng)制類型轉(zhuǎn)換_浮點(diǎn)數(shù)轉(zhuǎn)浮點(diǎn)數(shù)_01 {
public static void main(String[] args) {
double a = 180.8D;
float b = (float) a;
System.out.println(b); // 180.8
}
}
示例2:數(shù)值==超出了==轉(zhuǎn)換之后類型的取值范圍的情況
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo07_強(qiáng)制類型轉(zhuǎn)換_浮點(diǎn)數(shù)轉(zhuǎn)浮點(diǎn)數(shù)_02 {
public static void main(String[] args) {
double a = 3.8E38D;
float b = (float) a;
// float的最大取值范圍為: 1.4013E-45~3.4028E+38,無法存儲3.8E38,賦值失敗
System.out.println(b); // Infinity
}
}
超出最大容量:

2) 浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)
浮點(diǎn)數(shù)強(qiáng)制轉(zhuǎn)換為整數(shù)類型時(shí)也會出現(xiàn)一定的問題;
示例1:浮點(diǎn)數(shù)強(qiáng)制轉(zhuǎn)換為整數(shù),數(shù)值==沒有超出==轉(zhuǎn)換之后類型的取值范圍的情況
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo09_強(qiáng)制類型轉(zhuǎn)換_浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)_01 {
public static void main(String[] args) {
double a = 18.8D;
// 取值范圍: -2的63次方~2的63次方-1
long b = (long) a;
// 取值范圍: -2147483648~2147483647
int c = (int) a;
// 取值范圍: -32768~32767
short d = (short) a;
// 取值范圍: -128~127
byte e = (byte) a;
System.out.println(a); // 18.8
System.out.println(b); // 18
System.out.println(c); // 18
System.out.println(d); // 18
System.out.println(e); // 18
}
}
Tips:浮點(diǎn)數(shù)轉(zhuǎn)成整數(shù)后將會丟失精度,即小數(shù)點(diǎn)后面的通通丟失(注意,并不是四舍五入)
示例2:浮點(diǎn)數(shù)強(qiáng)制轉(zhuǎn)換為整數(shù)(long和int類型),數(shù)值==超出了==轉(zhuǎn)換之后類型的取值范圍的情況
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo10_強(qiáng)制類型轉(zhuǎn)換_浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)_02 {
public static void main(String[] args) {
double a = 5.2E63;
// 取值范圍: -2的63次方~2的63次方-1
long b = (long) a;
// 取值范圍: -2147483648~2147483647
int c = (int) a;
System.out.println(a); // 5.2E63
System.out.println(b); // 9223372036854775807(long的最大值)
System.out.println(c); // 2147483647(int的最大值)
}
}
Tips:當(dāng)強(qiáng)制超出該類型的范圍時(shí):如果是轉(zhuǎn)換為long或int類型,默認(rèn)為該類型的最大取值范圍值
執(zhí)行結(jié)果:

示例3:浮點(diǎn)數(shù)強(qiáng)制轉(zhuǎn)換為整數(shù)(short和byte類型),數(shù)值==超出了==轉(zhuǎn)換之后類型的取值范圍的情況
在Java中,將double或float轉(zhuǎn)換為short/byte時(shí),數(shù)值將首先轉(zhuǎn)換為int,然后轉(zhuǎn)換為short/byte,如果該數(shù)組超出了int的取值范圍,那么轉(zhuǎn)換為short或者byte時(shí)結(jié)果為-1,如果沒有超出int范圍,那么如果轉(zhuǎn)換為short將會截取2個(gè)字節(jié),轉(zhuǎn)換為byte將會截取1個(gè)字節(jié)。
示例代碼:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo11_強(qiáng)制類型轉(zhuǎn)換_浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)_03 {
public static void main(String[] args) {
/*
int的取值范圍(4個(gè)字節(jié)): -2147483648~2147483647
short取值范圍(2個(gè)字節(jié)): 取值范圍: -32768~32767
byte取值范圍(1個(gè)字節(jié)): -128~127
*/
// 超出了int范圍,直接為-1
System.out.println((short) 2147483648.8D); // -1
// 在int范圍內(nèi),截取兩個(gè)字節(jié)
// 01111111 11111111 11111111 11111100 ---> 2147483644
// 11111111 11111100 ---> -4
System.out.println((short) 2147483644.4D); // -4
// 在int范圍內(nèi),截取兩個(gè)字節(jié)
// 00000000 00001100 01101110 10110110 ---> 814774
// 01101110 10110110 ---> 28342
System.out.println((short) 814774.8D); // 28342
// 超出了int范圍,直接為-1
System.out.println((byte) 2147483648.8D); // -1
// 在int范圍內(nèi),截取1個(gè)字節(jié)
// 01111111 11111111 11111111 11111100 ---> 2147483644
// 11111100 ---> -4
System.out.println((byte) 2147483644.4D); // -4
// 在int范圍內(nèi),截取1個(gè)字節(jié)
// 00000000 00001100 01101110 10110110 ---> 814774
// 10110110 ---> -74
System.out.println((byte) 814774.8D); // -74
}
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
IDEA2022.1創(chuàng)建maven項(xiàng)目規(guī)避idea2022新建maven項(xiàng)目卡死無反應(yīng)問題
這篇文章主要介紹了IDEA2022.1創(chuàng)建maven項(xiàng)目規(guī)避idea2022新建maven項(xiàng)目卡死無反應(yīng)問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
深入分析Android系統(tǒng)中SparseArray的源碼
這篇文章主要介紹了深入分析Android系統(tǒng)中SparseArray的源碼,SparseArray為Java實(shí)現(xiàn),需要的朋友可以參考下2015-07-07
淺談spring中的default-lazy-init參數(shù)和lazy-init
下面小編就為大家?guī)硪黄獪\談spring中的default-lazy-init參數(shù)和lazy-init。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04
關(guān)于注解式的分布式Elasticsearch的封裝案例
這篇文章主要介紹了關(guān)于注解式的分布式Elasticsearch的封裝案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
mybatis-plus集成springboot實(shí)現(xiàn)XML映射器方式
本文詳細(xì)介紹了MyBatis-Plus中SQL映射配置的使用方法,包括動態(tài)SQL的支持和常見SQL操作的實(shí)現(xiàn),通過XML映射器,可以靈活地定義復(fù)雜的查詢語句,并處理動態(tài)條件和批量操作,文中還提供了具體的配置步驟和示例代碼,幫助開發(fā)者更好地理解和應(yīng)用這些功能2026-03-03
在非Spring管理對象中注入Spring Bean的解決方案
在SpringBoot開發(fā)中,我們習(xí)慣了通過@Autowired/@Resource等注解輕松注入依賴 Bean,但在WebSocket、定時(shí)任務(wù)等場景下,會遇到一個(gè)核心問題:非Spring創(chuàng)建的對象無法直接注入 Spring Bean,所以本文給大家介紹了在非Spring管理對象中注入Spring Bean的解決方案2026-02-02
java并發(fā)編程中實(shí)現(xiàn)可見性的四種可行方案解析
這篇文章主要介紹了java并發(fā)編程中實(shí)現(xiàn)可見性的四種可行方案解析,使用關(guān)鍵字volatile和使用鎖(如synchronized關(guān)鍵字或者java.util.concurrent包中的鎖)來確保對共享變量的修改在多線程環(huán)境中能夠正確地被其他線程所觀察到,需要的朋友可以參考下2023-08-08

