float类型转integer_Java基础(一)之数据类型——全面,浅显易懂
前言
把 Java 個人所學(xué)的基礎(chǔ)知識做了一個梳理整合。內(nèi)容盡量做到全面,淺顯易懂吧,這樣既方便自己以后查閱復(fù)習(xí),也分享出來給剛剛?cè)腴T的程序員們,希望可以給大家一些參考,讓大家對Java有一個基本的認(rèn)識,更好的學(xué)習(xí)Java。
Java的數(shù)據(jù)類型主要分為兩大:
- 內(nèi)置數(shù)據(jù)類型
- 引用數(shù)據(jù)類型
基本數(shù)據(jù)類型(內(nèi)置數(shù)據(jù)類型)
內(nèi)置數(shù)據(jù)類型總共有八種:
- byte/8
- char/16
- short/16
- int/32
- float/32
- long/64
- double/64
- boolean/~
這應(yīng)該沒什么好說的,基本類型就是這八種。不同的數(shù)據(jù)類型儲存不同類型的變量。
基本類型都有對應(yīng)的包裝類型,基本類型與其對應(yīng)的包裝類型之間的賦值使用自動裝箱與拆箱完成。
裝箱與拆箱
在 Java 5 之前如果要生成一個數(shù)值為10的Integer對象,必須這樣進(jìn)行:
Integer i = new Integer(10);
在 Java 5 之后就提供了自動裝箱的特性,上面的代碼就變成了這樣:
int i = 10;
這個過程中會自動根據(jù)數(shù)值創(chuàng)建對應(yīng)的 Integer對象,這就是裝箱。
那什么是拆箱呢?顧名思義,跟裝箱對應(yīng),就是自動將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型:
Integer x = 10; // 裝箱 int y = x; // 拆箱簡單一點說,裝箱就是自動將基本數(shù)據(jù)類型轉(zhuǎn)換為包裝器類型;拆箱就是自動將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型。
裝箱過程是通過調(diào)用包裝器的valueOf方法實現(xiàn)的,那么new Integer() 與 Integer.valueOf() 之間有什么區(qū)別呢?
- new Integer(123) 每次都會新建一個對象;
- Integer.valueOf(123) 會使用緩存池中的對象,多次調(diào)用會取得同一個對象的引用。
從上面代碼打印出來的情況,我們可以很明顯的看到兩者的區(qū)別。valueOf() 方法的實現(xiàn)比較簡單,就是先判斷值是否在緩存池中,如果在的話就直接返回緩存池的內(nèi)容。
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}在 Java 8 中,Integer 緩存池的大小默認(rèn)為 -128~127。
/*** Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.** The cache is initialized on first usage. The size of the cache* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.* During VM initialization, java.lang.Integer.IntegerCache.high property* may be set and saved in the private system properties in the* sun.misc.VM class.*/private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}編譯器會在自動裝箱過程調(diào)用 valueOf() 方法,因此多個 Integer 實例使用自動裝箱來創(chuàng)建并且值相同,那么就會引用相同的對象。
Integer m = 101;Integer n = 101;System.out.println(m == n); // trueInteger x = 127;Integer y = 127;System.out.println(x == y); // trueInteger a = 128;Integer b = 128;System.out.println(a == b); // false基本類型對應(yīng)的緩沖池如下:
- boolean values true and false
- all byte values
- short values between -128 and 127
- int values between -128 and 127
- char in the range u0000 to u007F
在使用這些基本類型對應(yīng)的包裝類型時,就可以直接使用緩沖池中的對象。
數(shù)據(jù)轉(zhuǎn)換
Java的變量類型為布爾型boolean;字符型char;整型byte、short、int、long;浮點型float、double。
其中四種整型變量和兩種浮點型變量分別對應(yīng)于不同的精度和范圍。
簡單數(shù)據(jù)類型之間的轉(zhuǎn)換又可以分為:
- 低級到高級的自動類型轉(zhuǎn)換
- 高級到低級的強(qiáng)制類型轉(zhuǎn)換
- 包裝類過渡類型能夠轉(zhuǎn)換
類型由低級到高級分別為(byte,short,char)-->int-->long-->float-->double
byte b; int i=b; long l=b; float f=b; double d=b;上面的語句在 Java 里面可以直接通過,但是將double型變量賦值給float變量,不加強(qiáng)轉(zhuǎn)的話會報錯。
引用數(shù)據(jù)類型(String)
String 被聲明為 final,因此它不可被繼承。
在 Java 8 中,String 內(nèi)部使用 char 數(shù)組存儲數(shù)據(jù)。
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[]; }value 數(shù)組被聲明為 final,這意味著 value 數(shù)組初始化之后就不能再引用其它數(shù)組。并且 String 內(nèi)部沒有改變 value 數(shù)組的方法,因此可以保證 String 不可變。
public static void main(String[] args) {//定義字符串變量//String:引用類型,但是一個不可變的字符序列,當(dāng)被聲明那一刻起,就已經(jīng)決定它的不能給改變String str = "abc" ;//String str = new String("abc") ;appendStr(str) ;System.out.println(str); /// abc}public static void appendStr(String str){str += "def" ;}String 不可變有幾大好處:
1. 可以緩存 hash 值
因為 String 的 hash 值經(jīng)常被使用,例如 String 用做 HashMap 的 key。不可變的特性可以使得 hash 值也不可變,因此只需要進(jìn)行一次計算。所以 String 的處理速度要快過其它的鍵對象。這就是HashMap中的鍵往往都使用字符串。
2. String Pool 的需要
如果一個 String 對象已經(jīng)被創(chuàng)建過了,那么就會從 String Pool 中取得引用。只有 String 是不可變的,才可能使用 String Pool。如果 String 是可變的,那么變量改變了它的值,那么其它指向這個值的變量的值也會一起改變。
3. 安全性
String 經(jīng)常作為參數(shù),String 不可變性可以保證參數(shù)不可變。例如在作為網(wǎng)絡(luò)連接參數(shù)的情況下如果 String 是可變的,那么在網(wǎng)絡(luò)連接過程中,String 被改變,改變 String 對象的那一方以為現(xiàn)在連接的是其它主機(jī),而實際情況卻不一定是。否則黑客們可以鉆到空子,改變字符串指向的對象的值,造成安全漏洞。
4. 線程安全
String 不可變性天生具備線程安全,可以在多個線程中安全地使用。String 自己便是線程安全的。
5.本地安全性
類加載器要用到字符串,不可變性提供了安全性,以便正確的類被加載。譬如你想加載java.sql.Connection類,而這個值被改成了myhacked.Connection,那么會對你的數(shù)據(jù)庫造成不可知的破壞。
String, StringBuffer 跟 StringBuilder
1. 可變性
- String 不可變
- StringBuffer 和 StringBuilder 可變
2. 線程安全
- String 不可變,因此是線程安全的
- StringBuilder 不是線程安全的
- StringBuffer 是線程安全的,內(nèi)部使用 synchronized 進(jìn)行同步
三者使用情況:
- 如果字符串不會更改,請使用String類,因為String對象是不可變的。
- 如果字符串可以更改(例如:字符串構(gòu)造中的大量邏輯和操作)并且只能從單個線程訪問,則使用 StringBuilder 就足夠了。
- 如果字符串可以更改,并且將從多個線程訪問,使用 StringBuffer 因為 StringBuffer 是同步的,因此具有線程安全性。
在大部分情況下 StringBuffer > String,StringBuilder > StringBuffer。
字符串常量池
我們帶著以下三個問題,去理解字符串常量池:
- 字符串常量池的設(shè)計意圖是什么?
- 字符串常量池在哪里?
- 如何操作字符串常量池?
字符串常量池的設(shè)計思想
- 字符串的分配,和其他的對象分配一樣,耗費高昂的時間與空間代價,作為最基礎(chǔ)的數(shù)據(jù)類型,大量頻繁的創(chuàng)建字符串,極大程度地影響程序的性能
- JVM為了提高性能和減少內(nèi)存開銷,在實例化字符串常量的時候進(jìn)行了一些優(yōu)化
創(chuàng)建字符串常量時,首先堅持字符串常量池是否存在該字符串
存在該字符串,返回引用實例,不存在,實例化該字符串并放入池中
- 實現(xiàn)的基礎(chǔ)
運行時實例創(chuàng)建的全局字符串常量池中有一個表,總是為池中每個唯一的字符串對象維 護(hù)一個引用,這就意味著它們一直引用著字符串常量池中的對象,所以,在常量池中的這些字符串不會被垃圾收集器回收
即:“享元模式”,顧名思義 - - - > 共享元素模式。
一個系統(tǒng)中如果有多處用到了相同的一個元素,那么我們應(yīng)該只存儲一份此元素,而讓所有地方都引用這一個元素。
看下列代碼:
String a = "aaa" ; String b = "aaa" ; System.out.println(a == b ); //true字符串常量池在哪里
在分析字符串常量池的位置時,首先了解一下堆、棧、方法區(qū):
- 堆
JVM只有一個堆區(qū)(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身
對象的由垃圾回收器負(fù)責(zé)回收,因此大小和生命周期不需要確定
- 棧
每個棧中的數(shù)據(jù)(原始類型和對象引用)都是私有的
棧分為3個部分:基本類型變量區(qū)、執(zhí)行環(huán)境上下文、操作指令區(qū)(存放操作指令)
數(shù)據(jù)大小和生命周期是可以確定的,當(dāng)沒有引用指向數(shù)據(jù)時,這個數(shù)據(jù)就會自動消失
- 方法區(qū)
方法區(qū)中包含的都是在整個程序中永遠(yuǎn)唯一的元素,如class,static變量
答案就是:在Java 7之前,String Pool被放在運行時常量池中,它屬于永久代。而在Java 7,String Pool被移到堆中。這是因為永久代的空間有限,在大量使用字符串的場景下會導(dǎo)致OutOfMemoryError錯誤。
問題:String str = new String("abc") 創(chuàng)建多少個對象?
1.在常量池中查找是否有"abc"對象
- 有則返回對應(yīng)的引用實例
- 沒有則創(chuàng)建對應(yīng)的實例對象
2.在堆中 new 一個 String("abc") 對象
3.將對象地址賦值給str,創(chuàng)建一個引用
答案:如果常量池中沒有"abc"字面量則創(chuàng)建兩個對象,否則創(chuàng)建一個對象,以及創(chuàng)建一個引用。
操作字符串常量池的方式
下面代碼中,s1和s2采用new String()的方式新建了兩個不同字符串,而s3和s4是通過s1.intern()方法取得一個字符串引用。intern()首先把s1引用的字符串放到String Pool中,然后返回這個字符串引用。因此s3和s4引用的是同一個字符串。
public static void main(String[] args) {String s1 = new String("aaa");String s2 = new String("aaa");System.out.println(s1 == s2);// falseString s3=s1.intern();String s4=s1.intern();System.out.println(s3==s4); // true}當(dāng)一個字符串調(diào)用intern()方法時,如果String Pool中已經(jīng)存在一個字符串和該字符串值相等(使用equals()方法進(jìn)行確定),那么就會返回String Pool中字符串的引用;否則,就會在String Pool中添加一個新的字符串,并返回這個新字符串的引用。
如果是采用"bbb"的形式創(chuàng)建字符串,會自動地將字符串放入
public static void main(String[] args) {String s5="bbb";String s6="bbb";System.out.println(s5==s6); // true}總結(jié)
以上是生活随笔為你收集整理的float类型转integer_Java基础(一)之数据类型——全面,浅显易懂的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 子类重写父类虚函数_C/C++编程笔记:
- 下一篇: python docx 设置表格字体和格