成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

java安全編碼指南之:Number操作詳解

瀏覽:2日期:2022-08-24 18:03:19

簡介

java中可以被稱為Number的有byte,short,int,long,float,double和char,我們在使用這些Nubmer的過程中,需要注意些什么內(nèi)容呢?一起來看看吧。

Number的范圍

每種Number類型都有它的范圍,我們看下java中Number類型的范圍:

java安全編碼指南之:Number操作詳解

考慮到我們最常用的int操作,雖然int的范圍夠大,但是如果我們在做一些int操作的時候還是可能超出int的范圍。

超出了int范圍會發(fā)送什么事情呢?看下面的例子:

public void testIntegerOverflow(){ System.out.println(Integer.MAX_VALUE+1000); }

運行結(jié)果:-2147482649。

很明顯Integer.MAX_VALUE+1000將會超出Integer的最大值范圍,但是我們沒有得到異常提醒,反而得到了一個錯誤的結(jié)果。

正確的操作是如果我們遇到了Overflow的問題,需要拋出異常:ArithmeticException。

怎么防止這種IntegerOverflow的問題呢?一般來講,我們有下面幾種方式。

第一種方式:在做Integer操作之前,進行預(yù)判斷是否超出范圍:

舉個例子:

static final int safeAdd(int left, int right) { if (right > 0 ? left > Integer.MAX_VALUE - right : left < Integer.MIN_VALUE - right) { throw new ArithmeticException('Integer overflow'); } return left + right; }

上面的例子中,我們需要進行兩個整數(shù)相加操作,在相加之前,我們需要進行范圍的判斷,從而保證計算的安全性。

第二種方式:使用Math的addExact和multiplyExact方法:

Math的addExact和multiplyExact方法已經(jīng)提供了Overflow的判斷,我們看下addExact的實現(xiàn):

public static int addExact(int x, int y) { int r = x + y; // HD 2-12 Overflow iff both arguments have the opposite sign of the result if (((x ^ r) & (y ^ r)) < 0) { throw new ArithmeticException('integer overflow'); } return r; }

看下怎么使用:

public int addUseMath(int a, int b){ return Math.addExact(a,b); }

第三種方式:向上轉(zhuǎn)型

既然超出了Integer的范圍,那么我們可以用范圍更大的long來存儲數(shù)據(jù)。

public static long intRangeCheck(long value) { if ((value < Integer.MIN_VALUE) || (value > Integer.MAX_VALUE)) { throw new ArithmeticException('Integer overflow'); } return value; } public int addUseUpcasting(int a, int b){ return (int)intRangeCheck((long)a+(long)b); }

上面的例子中,我們將a+b轉(zhuǎn)換成了兩個long相加,從而保證不溢出范圍。

然后進行一次范圍比較,從而判斷相加之后的結(jié)果是否仍然在整數(shù)范圍內(nèi)。

第四種方式:使用BigInteger

我們可以使用BigInteger.valueOf(a)將int轉(zhuǎn)換成為BigInteger,再進行后續(xù)操作:

public int useBigInteger(int a, int b){ return BigInteger.valueOf(a).add(BigInteger.valueOf(b)).intValue(); }

區(qū)分位運算和算數(shù)運算

我們通常會對Integer進行位運算或者算數(shù)運算。雖然可以進行兩種運算,但是最好不要將兩種運算同時進行,這樣會造成混淆。

比如下面的例子:

x += (x << 1) + 1;

上面的例子是想做什么呢?其實它是想將3x+1的值賦給x。

但是這樣寫出來讓人很難理解,所以我們需要避免這樣實現(xiàn)。

再看下面的一個例子:

public void testBitwiseOperation(){ int i = -10; System.out.println(i>>>2); System.out.println(i>>2); System.out.println(i/4); }

本來我們想做的是將i除以4,結(jié)果發(fā)現(xiàn)只有最后一個才是我們要的結(jié)果。

我們來解釋一下,第一個i>>>2是邏輯右移,將會把最左邊的填充成0,所以得出的結(jié)果是一個正值1073741821。

第二個i>>2是算數(shù)右移,最左邊的還是會填充成1,但是會向下取整,所以得出結(jié)果是-3.

直接使用i/4,我們是向上取整,所以得出結(jié)果是-2.

注意不要使用0作為除數(shù)

我們在使用變量作為除數(shù)的時候,一定要注意先判斷是否為0.

兼容C++的無符號整數(shù)類型

在java中只有16位的char表示的是無符號整數(shù),而int實際上表示的是帶符號的整數(shù)。

而在C或者C++中是可以直接表示無符號的整數(shù)的,那么,如果我們有一個32位的無符號整數(shù),該怎么用java來處理呢?

public int readIntWrong(DataInputStream is) throws IOException { return is.readInt(); }

看上面的例子,我們從Stream中讀取一個int值,如果是一個32位的無符號整數(shù),那么讀出來int就變成了有符號的負(fù)整數(shù),這和我們的期望是相符的。

考慮一下,long是64位的,我們是不是可以使用long來表示32位的無符號整數(shù)呢?

public long readIntRight(DataInputStream is) throws IOException{ return is.readInt() & 0xFFFFFFFFL; // Mask with 32 one-bits }

看上面的例子,我們返回的是long,如果將32位的int轉(zhuǎn)換成為64位的long,會自動根據(jù)符號位進行補全。

所以這時候我們需要和0xFFFFFFFFL進行mask操作,將高32位重置為0.

NAN和INFINITY

在整型運算中,除數(shù)是不能為0的,否則直接運行異常。但是在浮點數(shù)運算中,引入了NAN和INFINITY的概念,我們來看一下Double和Float中的定義。

public static final double POSITIVE_INFINITY = 1.0 / 0.0;public static final double NEGATIVE_INFINITY = -1.0 / 0.0;public static final double NaN = 0.0d / 0.0;

public static final float POSITIVE_INFINITY = 1.0f / 0.0f;public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;public static final float NaN = 0.0f / 0.0f;

1除以0就是INFINITY,而0除以0就是NaN。

接下來,我們看一下NAN和INFINITY的比較:

public void compareInfinity(){ System.out.println(Double.POSITIVE_INFINITY == Double.POSITIVE_INFINITY); }

運行結(jié)果是true。

public void compareNaN(){ System.out.println(Double.NaN == Double.NaN); }

運行結(jié)果是false。

可以看到NaN和NaN相比是false。

那么我們怎么比較NaN呢?

別急,Double提供了一個isNaN方法,我們可以這樣使用:

System.out.println(Double.isNaN(Double.NaN));

接下來我們看一個在代碼中經(jīng)常會用到的一個Double解析:

public void incorrectParse(String userInput){ double val = 0; try { val = Double.valueOf(userInput); } catch (NumberFormatException e) { } //do something for val }

這段代碼有沒有問題?咋看下好像沒有問題,但是,如果我們的userInput是NaN,Infinity,或者-Infinity,Double.valueOf是可以解析得到結(jié)果的。

public void testNaN(){ System.out.println(Double.valueOf('NaN')); System.out.println(Double.valueOf('Infinity')); System.out.println(Double.valueOf('-Infinity')); }

運行輸出:

NaN

Infinity

-Infinity

所以,我們還需要額外去判斷NaN和Infinity:

public void correctParse(String userInput){ double val = 0; try { val = Double.valueOf(userInput); } catch (NumberFormatException e) { } if (Double.isInfinite(val)){ // Handle infinity error } if (Double.isNaN(val)) { // Handle NaN error } //do something for val }

不要使用float或者double作為循環(huán)的計數(shù)器

考慮下面的代碼:

for (float x = 0.1f; x <= 1.0f; x += 0.1f) { System.out.println(x);}

上面的代碼有什么問題呢?

我們都知道java中浮點數(shù)是不準(zhǔn)確的,但是不一定有人知道為什么不準(zhǔn)確。

這里給大家解釋一下,計算機中所有與的數(shù)都是以二進制存儲的,我們以0.6為例。

0.6轉(zhuǎn)成為二進制格式是乘2取整,0.6x2=1.2,取整剩余0.2,繼續(xù)上面的步驟0.2x2=0.4,0.4x2=0.8,0.8x2=1.6,取整剩余0.6,產(chǎn)生了一個循環(huán)。

所以0.6的二進制格式是.1001 1001 1001 1001 1001 1001 1001 … 無限循環(huán)下去。

所以,有些小數(shù)是無法用二進制精確的表示的,最終導(dǎo)致使用float或者double作為計數(shù)器是不準(zhǔn)的。

BigDecimal的構(gòu)建

為了解決float或者Double計算中精度缺失的問題,我們通常會使用BigDecimal。

那么在使用BigDecimal的時候,請注意一定不要從float構(gòu)建BigDecimal,否則可能出現(xiàn)意想不到的問題。

public void getFromFloat(){ System.out.println(new BigDecimal(0.1)); }

上面的代碼,我們得到的結(jié)果是:0.1000000000000000055511151231257827021181583404541015625。

這是因為二進制無法完美的展示所有的小數(shù)。

所以,我們需要從String來構(gòu)建BigDecimal:

public void getFromString(){ System.out.println(new BigDecimal('0.1')); }

類型轉(zhuǎn)換問題

在java中各種類型的Number可以互相進行轉(zhuǎn)換:

比如:

short to byte or char

char to byte or short

int to byte, short, or char

long to byte, short, char, or int

float to byte, short, char, int, or long

double to byte, short, char, int, long, or float

或者反向:

byte to short, int, long, float, or double

short to int, long, float, or double

char to int, long, float, or double

int to long, float, or double

long to float or double

float to double

從大范圍的類型轉(zhuǎn)向小范圍的類型時,我們要考慮是否超出轉(zhuǎn)換類型范圍的情況:

public void intToByte(int i){ if ((i < Byte.MIN_VALUE) || (i > Byte.MAX_VALUE)) { throw new ArithmeticException('Value is out of range'); } byte b = (byte) i; }

比如上面的例子中,我們將int轉(zhuǎn)換成為byte,那么在轉(zhuǎn)換之前,需要先判斷int是否超出了byte的范圍。

同時我們還需要考慮到精度的切換,看下面的例子:

public void intToFloat(){ System.out.println(subtraction(1111111111,1111111111)); } public int subtraction(int i , float j){ return i - (int)j; }

結(jié)果是多少呢?

答案不是0,而是-57。

為什么呢?

因為這里我們做了兩次轉(zhuǎn)換,第一次從1111111111轉(zhuǎn)換到float,float雖然有32位,但是只有23位是存放真正的數(shù)值的,1位是符號位,剩下的8位是指數(shù)位。

所以從1111111111轉(zhuǎn)換到float發(fā)送了精度丟失。

我們可以把subtraction方法修改一下,首先判斷float的范圍,如果超出了23bit的表示范圍,則說明發(fā)送了精度丟失,我們需要拋出異常:

public int subtraction(int i , float j){ System.out.println(j); if ((j > 0x007fffff) || (j < -0x800000)) { throw new ArithmeticException('Insufficient precision'); } return i - (int)j; }

當(dāng)然還有一種辦法,我們可以用精度更高的double來做轉(zhuǎn)換,double有52位來存放真正的數(shù)據(jù),所以足夠了。

public int subtractionWithDouble(int i , double j){ System.out.println(j); return i - (int)j; }

本文的代碼:

learn-java-base-9-to-20/tree/master/security

以上這篇java安全編碼指南之:Number操作詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Java
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
欧美日韩视频一区二区三区| 亚洲在线视频| 日韩亚洲视频| 中文av一区特黄| av亚洲精华国产精华| 在线播放视频一区| 久久超碰97中文字幕| 久久国产一区| 精品少妇一区二区三区视频免付费 | 国产精品乱码人人做人人爱| 国产欧美精品国产国产专区 | 久久这里有精品15一区二区三区| 亚洲综合视频在线观看| 亚洲午夜一区| **性色生活片久久毛片| 精品动漫av| 亚洲黄色性网站| 亚洲综合二区| 亚洲精品大片www| 9色精品在线| 亚洲国产中文字幕| 久久一区二区精品| 久久国产精品99精品国产| 在线不卡欧美精品一区二区三区| 国产成人精品影院| 久久久久一区二区三区四区| 欧美激情综合| 综合久久久久久久| 亚洲制服av| 美女爽到高潮91| 91精品一区二区三区久久久久久| 国产99久久久精品| 久久精品男人的天堂| 欧美激情日韩| 亚洲一区二区在线观看视频 | 一本色道久久综合亚洲精品高清| 亚洲综合免费观看高清完整版在线 | 91天堂素人约啪| 国产精品理伦片| 亚洲日本久久| 亚洲一区二区av在线| 久久久久网站| 国产在线播精品第三| 久久久一区二区三区| 欧美日韩在线三区| 国产伦精一区二区三区| 精品国产一区二区三区av性色| 欧美+日本+国产+在线a∨观看| 国产精品久久久久久亚洲毛片| 91久久亚洲| 五月天一区二区| 欧美人与性动xxxx| 99这里只有精品| 国产精品久久久久精k8| 国产精品一级| 日韩1区2区日韩1区2区| 日韩视频一区二区| 韩日精品在线| 奇米精品一区二区三区四区| 日韩一区二区免费在线电影| 欧美日韩亚洲三区| 性久久久久久久久| 91精品国产色综合久久不卡蜜臀| 91视频你懂的| 一区二区在线免费| 国产亚洲精品久久飘花| 国产精品一二一区| 国产精品麻豆一区二区| 日本精品裸体写真集在线观看| 成人综合婷婷国产精品久久免费| 久久精品人人做人人爽97| 亚洲激情影院| 美女一区二区视频| 精品人在线二区三区| 99在线精品免费视频九九视| 激情五月激情综合网| 国产欧美一区二区精品性色| 久久久久久一区| 91丨九色丨黑人外教| 亚洲国产乱码最新视频 | 五月天婷婷综合| 日韩欧美中文一区| 亚洲国产成人不卡| 紧缚捆绑精品一区二区| 久久久99免费| 一本色道久久综合亚洲精品不卡 | 亚洲日本va午夜在线影院| 91福利在线免费观看| 99久久99久久综合| 亚洲国产乱码最新视频 | 久久久久久久久久久黄色| 免费日韩av| 成人免费的视频| 亚洲影视在线观看| 日韩精品一区国产麻豆| 亚洲精选在线| 成人一区二区三区中文字幕| 亚洲综合色视频| 精品第一国产综合精品aⅴ| 亚洲欧美久久久久一区二区三区| 福利一区福利二区| 亚洲国产精品视频| 精品国产伦一区二区三区免费 | 欧美精品成人| 美国毛片一区二区三区| 中文字幕一区三区| 91精品国产综合久久久久久漫画 | 中文字幕永久在线不卡| 91精品国产综合久久福利| 亚洲黄色天堂| 成人免费高清在线| 青青草成人在线观看| 亚洲天堂福利av| 亚洲精品在线一区二区| 欧美中文字幕一区二区三区亚洲 | 久久综合五月| 日韩一区二区免费看| 91尤物视频在线观看| 九九精品视频在线看| 一区二区三区av电影| 26uuu色噜噜精品一区二区| 久久综合九色综合欧美狠狠| 伊人精品在线| 91亚洲永久精品| 久久99久久99精品免视看婷婷| 亚洲精品免费电影| 国产欧美一区二区在线观看| 91精品国产一区二区三区蜜臀| 久久国产免费| 韩日视频一区| 成人高清免费观看| 韩日欧美一区二区三区| 日韩制服丝袜av| 亚洲激情六月丁香| 中文无字幕一区二区三区| 日韩精品一区二区三区在线播放| 欧美专区在线观看一区| 国产伦精品一区二区三区四区免费 | 久久精品一区二区三区不卡牛牛| 欧美伦理视频网站| 久久亚洲国产精品一区二区| 在线精品福利| 欧美日韩国产综合网| 99精品视频一区二区| 国产成人自拍在线| 国产在线播精品第三| 日韩avvvv在线播放| 亚洲综合无码一区二区| 亚洲欧美色一区| 国产精品黄色在线观看| 欧美国产成人精品| 国产亚洲一本大道中文在线| 日韩精品一区二区三区四区| 717成人午夜免费福利电影| 欧美三级一区二区| 欧美性大战久久久久久久 | 国产精品美女一区二区三区 | 国产成人精品在线看| 国产九九视频一区二区三区| 另类调教123区 | 亚洲九九精品| 亚洲国产精品一区二区第一页 | 欧美日韩在线综合| 欧美三级三级三级爽爽爽| 一本一道久久a久久精品| 男人天堂欧美日韩| 国产乱码精品| 先锋影音一区二区三区| 久久精品亚洲一区二区| 久久久久久久久久码影片| 六月婷婷久久| 91高清在线观看| 在线看日本不卡| 精品视频1区2区| 91精品国产综合久久久久久久久久| 91精品国产91热久久久做人人 | 国产精品水嫩水嫩| 亚洲欧美综合色| 亚洲欧洲色图综合| 狂野欧美性猛交xxxx巴西| 亚洲色图丝袜美腿| 日本成人在线看| 午夜在线视频一区二区区别| 狠狠色综合播放一区二区| 美女视频黄a大片欧美| 奇米在线7777在线精品| 麻豆精品蜜桃视频网站| 国产麻豆精品95视频| 成人一区二区三区视频在线观看| 成人永久看片免费视频天堂| 91啪亚洲精品| 亚洲欧洲在线一区| 久久精品123| 在线一区二区三区做爰视频网站| 欧美日韩中文精品| 欧美大片顶级少妇| 国产精品美女www爽爽爽| 亚洲精品久久久蜜桃| 日韩在线a电影| 国产精品系列在线观看|