日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

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

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

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

簡(jiǎn)介

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

Number的范圍

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

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

考慮到我們最常用的int操作,雖然int的范圍夠大,但是如果我們?cè)谧鲆恍﹊nt操作的時(shí)候還是可能超出int的范圍。

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

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

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

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

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

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

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

舉個(gè)例子:

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; }

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

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

Math的addExact和multiplyExact方法已經(jīng)提供了Overflow的判斷,我們看下addExact的實(shí)現(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來存儲(chǔ)數(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)換成了兩個(gè)long相加,從而保證不溢出范圍。

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

第四種方式:使用BigInteger

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

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

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

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

比如下面的例子:

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

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

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

再看下面的一個(gè)例子:

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)只有最后一個(gè)才是我們要的結(jié)果。

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

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

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

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

我們?cè)谑褂米兞孔鳛槌龜?shù)的時(shí)候,一定要注意先判斷是否為0.

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

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

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

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

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

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

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

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

所以這時(shí)候我們需要和0xFFFFFFFFL進(jìn)行mask操作,將高32位重置為0.

NAN和INFINITY

在整型運(yùn)算中,除數(shù)是不能為0的,否則直接運(yùn)行異常。但是在浮點(diǎn)數(shù)運(yùn)算中,引入了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); }

運(yùn)行結(jié)果是true。

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

運(yùn)行結(jié)果是false。

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

那么我們?cè)趺幢容^NaN呢?

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

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

接下來我們看一個(gè)在代碼中經(jīng)常會(huì)用到的一個(gè)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')); }

運(yùn)行輸出:

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)的計(jì)數(shù)器

考慮下面的代碼:

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

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

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

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

0.6轉(zhuǎn)成為二進(jì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)生了一個(gè)循環(huán)。

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

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

BigDecimal的構(gòu)建

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

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

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

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

這是因?yàn)槎M(jìn)制無法完美的展示所有的小數(shù)。

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

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

類型轉(zhuǎn)換問題

在java中各種類型的Number可以互相進(jìn)行轉(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)向小范圍的類型時(shí),我們要考慮是否超出轉(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的范圍。

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

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

結(jié)果是多少呢?

答案不是0,而是-57。

為什么呢?

因?yàn)檫@里我們做了兩次轉(zhuǎn)換,第一次從1111111111轉(zhuǎn)換到float,float雖然有32位,但是只有23位是存放真正的數(shù)值的,1位是符號(hào)位,剩下的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操作詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美日韩一二三四| 欧美亚洲激情| 亚洲精品乱码| av在线资源| 日韩在线精品| 91精品国产福利在线观看麻豆| 日韩在线视频精品| 久久久成人网| 亚洲一区激情| 综合在线一区| 欧美日韩精品一区二区三区视频 | 成人自拍av| 四虎4545www国产精品 | 成人在线视频中文字幕| 成人小电影网站| 在线日韩视频| 午夜日韩在线| 日本aⅴ精品一区二区三区| 欧美一级二区| 麻豆精品av| 日韩毛片视频| 日韩亚洲精品在线| 日韩av在线播放中文字幕| 婷婷精品在线| 国际精品欧美精品| 韩国精品主播一区二区在线观看 | 麻豆精品视频在线| 日韩国产激情| 久久亚洲一区| 国产日韩欧美一区二区三区在线观看 | 久久精品在线| 亚洲欧美高清| 国产精品久久久久久久久免费高清| 日本一区二区免费高清| 久久免费国产| 免费国产亚洲视频| 国产日产高清欧美一区二区三区| 精品久久在线| 日韩视频不卡| 国产精品一区二区精品视频观看| 国产一区三区在线播放| 欧美日韩国产综合网| 蜜臀久久99精品久久久久久9| 欧美日韩亚洲一区| 久久国产中文字幕| 日韩av资源网| 亚洲成人av观看| 日本在线视频一区二区| 日韩电影在线视频| 日韩1区2区日韩1区2区| 波多野结衣久久精品| 亚洲深深色噜噜狠狠爱网站 | 国产高清一区二区| 日本成人在线一区| 六月丁香综合在线视频| 欧美+日本+国产+在线a∨观看| 婷婷综合成人| 九九色在线视频| 日韩av字幕| 91精品亚洲| 国产精品天堂蜜av在线播放| 欧美精品一区二区久久| 国产精品v亚洲精品v日韩精品| 欧美亚洲在线日韩| 国产精品1luya在线播放| 欧美日韩国产欧| 久久精品国产999大香线蕉| 日韩中文字幕区一区有砖一区 | 亚洲精品黄色| 久久亚洲专区| 久久免费精品| 日韩毛片一区| 亚洲精品99| 国产一区二区三区免费在线| 日本一区二区中文字幕| 国产综合婷婷| 日韩av片子| 日韩av一级片| 亚洲高清av| 成人亚洲一区二区| 欧美视频一区| 亚洲一二av| 成人av二区| 麻豆视频在线看| 国产精品一区二区三区四区在线观看 | 久久国产麻豆精品| 99成人在线| 久久精品成人| 给我免费播放日韩视频| 欧美日韩一区二区三区四区在线观看 | 高清av一区二区三区| 国产九九精品| 丝瓜av网站精品一区二区| 日韩在线综合| 色综合五月天| 国产精品黄色| 亚洲精品黄色| 男人操女人的视频在线观看欧美| 一区二区三区视频免费观看| 精品免费av| 国产午夜一区| 日本在线成人| 亚洲九九精品| 蜜臀精品一区二区三区在线观看 | 国产婷婷精品| 99国产精品免费视频观看| 成年男女免费视频网站不卡| 少妇精品久久久| 天堂av在线一区| 日韩午夜av| 国产精品91一区二区三区| 欧美日韩水蜜桃| 亚洲爱爱视频| 久久国产主播| 136国产福利精品导航网址| 啪啪国产精品| 久久久久亚洲| 91精品国产成人观看| 久久久久午夜电影| 亚洲特级毛片| 99久久99久久精品国产片果冰| 亚洲成人av观看| 日韩高清中文字幕一区二区| av在线最新| 久久久久午夜电影| 国产一区二区中文| 欧美一级精品| 亚洲黄色影院| 巨乳诱惑日韩免费av| 在线精品国产亚洲| 亚洲欧美日本国产| 久久精品99久久久| 国产高清亚洲| 国产一区二区三区四区大秀| 国产精品国产一区| 高清一区二区| 日韩天堂在线| 青青久久av| 欧美精品一区二区三区精品| 欧美在线亚洲| 亚洲一区二区三区无吗| 日韩激情一二三区| 国产精品一区二区免费福利视频| 国产精品a级| 国产成人调教视频在线观看| 欧美激情国产在线| 亚洲成人日韩| 日本不卡视频在线| 精品资源在线| 99tv成人| 中文字幕成人| 麻豆精品一区二区综合av| 久久男人av| 欧美日韩尤物久久| 亚洲一区二区免费在线观看| 欧美一区二区三区久久| 福利一区二区免费视频| 欧美肉体xxxx裸体137大胆| 日韩一级网站| 国产欧美日韩一区二区三区四区 | 青青国产91久久久久久| 精品视频国内| 999精品一区| 亚洲精品看片| 国产精品久久久久久久免费软件| 日本黄色精品| 视频一区二区三区入口| 美女视频一区在线观看| 99久久久久| 91国内精品| 精品免费av在线| 亚洲精选91| 亚洲一级少妇| 日韩精品社区| 午夜av成人| 日韩成人在线看| 日韩精品网站| 日韩精品久久理论片| 超碰成人av| 久久午夜精品| 精品日本视频| 中文字幕一区日韩精品| 久久精品网址| 爽爽淫人综合网网站| 精品免费av| 亚洲一区二区日韩| 在线看片福利| 日韩精品免费视频一区二区三区| 日韩伦理在线一区| 日韩高清一区| 国内亚洲精品| 国产精品2区| 中国女人久久久| 黄色网一区二区| 久久香蕉精品| 国产一区调教| 97成人在线| 99riav1国产精品视频| 欧美激情aⅴ一区二区三区| 国产精品日韩久久久|