float类型转integer_Java基础(一)之数据类型——全面,浅显易懂
前言
把 Java 個人所學的基礎知識做了一個梳理整合。內容盡量做到全面,淺顯易懂吧,這樣既方便自己以后查閱復習,也分享出來給剛剛入門的程序員們,希望可以給大家一些參考,讓大家對Java有一個基本的認識,更好的學習Java。
Java的數據類型主要分為兩大:
- 內置數據類型
- 引用數據類型
基本數據類型(內置數據類型)
內置數據類型總共有八種:
- byte/8
- char/16
- short/16
- int/32
- float/32
- long/64
- double/64
- boolean/~
這應該沒什么好說的,基本類型就是這八種。不同的數據類型儲存不同類型的變量。
基本類型都有對應的包裝類型,基本類型與其對應的包裝類型之間的賦值使用自動裝箱與拆箱完成。
裝箱與拆箱
在 Java 5 之前如果要生成一個數值為10的Integer對象,必須這樣進行:
Integer i = new Integer(10);
在 Java 5 之后就提供了自動裝箱的特性,上面的代碼就變成了這樣:
int i = 10;
這個過程中會自動根據數值創建對應的 Integer對象,這就是裝箱。
那什么是拆箱呢?顧名思義,跟裝箱對應,就是自動將包裝器類型轉換為基本數據類型:
Integer x = 10; // 裝箱 int y = x; // 拆箱簡單一點說,裝箱就是自動將基本數據類型轉換為包裝器類型;拆箱就是自動將包裝器類型轉換為基本數據類型。
裝箱過程是通過調用包裝器的valueOf方法實現的,那么new Integer() 與 Integer.valueOf() 之間有什么區別呢?
- new Integer(123) 每次都會新建一個對象;
- Integer.valueOf(123) 會使用緩存池中的對象,多次調用會取得同一個對象的引用。
從上面代碼打印出來的情況,我們可以很明顯的看到兩者的區別。valueOf() 方法的實現比較簡單,就是先判斷值是否在緩存池中,如果在的話就直接返回緩存池的內容。
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 緩存池的大小默認為 -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() {}}編譯器會在自動裝箱過程調用 valueOf() 方法,因此多個 Integer 實例使用自動裝箱來創建并且值相同,那么就會引用相同的對象。
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基本類型對應的緩沖池如下:
- 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
在使用這些基本類型對應的包裝類型時,就可以直接使用緩沖池中的對象。
數據轉換
Java的變量類型為布爾型boolean;字符型char;整型byte、short、int、long;浮點型float、double。
其中四種整型變量和兩種浮點型變量分別對應于不同的精度和范圍。
簡單數據類型之間的轉換又可以分為:
- 低級到高級的自動類型轉換
- 高級到低級的強制類型轉換
- 包裝類過渡類型能夠轉換
類型由低級到高級分別為(byte,short,char)-->int-->long-->float-->double
byte b; int i=b; long l=b; float f=b; double d=b;上面的語句在 Java 里面可以直接通過,但是將double型變量賦值給float變量,不加強轉的話會報錯。
引用數據類型(String)
String 被聲明為 final,因此它不可被繼承。
在 Java 8 中,String 內部使用 char 數組存儲數據。
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[]; }value 數組被聲明為 final,這意味著 value 數組初始化之后就不能再引用其它數組。并且 String 內部沒有改變 value 數組的方法,因此可以保證 String 不可變。
public static void main(String[] args) {//定義字符串變量//String:引用類型,但是一個不可變的字符序列,當被聲明那一刻起,就已經決定它的不能給改變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 值經常被使用,例如 String 用做 HashMap 的 key。不可變的特性可以使得 hash 值也不可變,因此只需要進行一次計算。所以 String 的處理速度要快過其它的鍵對象。這就是HashMap中的鍵往往都使用字符串。
2. String Pool 的需要
如果一個 String 對象已經被創建過了,那么就會從 String Pool 中取得引用。只有 String 是不可變的,才可能使用 String Pool。如果 String 是可變的,那么變量改變了它的值,那么其它指向這個值的變量的值也會一起改變。
3. 安全性
String 經常作為參數,String 不可變性可以保證參數不可變。例如在作為網絡連接參數的情況下如果 String 是可變的,那么在網絡連接過程中,String 被改變,改變 String 對象的那一方以為現在連接的是其它主機,而實際情況卻不一定是。否則黑客們可以鉆到空子,改變字符串指向的對象的值,造成安全漏洞。
4. 線程安全
String 不可變性天生具備線程安全,可以在多個線程中安全地使用。String 自己便是線程安全的。
5.本地安全性
類加載器要用到字符串,不可變性提供了安全性,以便正確的類被加載。譬如你想加載java.sql.Connection類,而這個值被改成了myhacked.Connection,那么會對你的數據庫造成不可知的破壞。
String, StringBuffer 跟 StringBuilder
1. 可變性
- String 不可變
- StringBuffer 和 StringBuilder 可變
2. 線程安全
- String 不可變,因此是線程安全的
- StringBuilder 不是線程安全的
- StringBuffer 是線程安全的,內部使用 synchronized 進行同步
三者使用情況:
- 如果字符串不會更改,請使用String類,因為String對象是不可變的。
- 如果字符串可以更改(例如:字符串構造中的大量邏輯和操作)并且只能從單個線程訪問,則使用 StringBuilder 就足夠了。
- 如果字符串可以更改,并且將從多個線程訪問,使用 StringBuffer 因為 StringBuffer 是同步的,因此具有線程安全性。
在大部分情況下 StringBuffer > String,StringBuilder > StringBuffer。
字符串常量池
我們帶著以下三個問題,去理解字符串常量池:
- 字符串常量池的設計意圖是什么?
- 字符串常量池在哪里?
- 如何操作字符串常量池?
字符串常量池的設計思想
- 字符串的分配,和其他的對象分配一樣,耗費高昂的時間與空間代價,作為最基礎的數據類型,大量頻繁的創建字符串,極大程度地影響程序的性能
- JVM為了提高性能和減少內存開銷,在實例化字符串常量的時候進行了一些優化
創建字符串常量時,首先堅持字符串常量池是否存在該字符串
存在該字符串,返回引用實例,不存在,實例化該字符串并放入池中
- 實現的基礎
運行時實例創建的全局字符串常量池中有一個表,總是為池中每個唯一的字符串對象維 護一個引用,這就意味著它們一直引用著字符串常量池中的對象,所以,在常量池中的這些字符串不會被垃圾收集器回收
即:“享元模式”,顧名思義 - - - > 共享元素模式。
一個系統中如果有多處用到了相同的一個元素,那么我們應該只存儲一份此元素,而讓所有地方都引用這一個元素。
看下列代碼:
String a = "aaa" ; String b = "aaa" ; System.out.println(a == b ); //true字符串常量池在哪里
在分析字符串常量池的位置時,首先了解一下堆、棧、方法區:
- 堆
JVM只有一個堆區(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身
對象的由垃圾回收器負責回收,因此大小和生命周期不需要確定
- 棧
每個棧中的數據(原始類型和對象引用)都是私有的
棧分為3個部分:基本類型變量區、執行環境上下文、操作指令區(存放操作指令)
數據大小和生命周期是可以確定的,當沒有引用指向數據時,這個數據就會自動消失
- 方法區
方法區中包含的都是在整個程序中永遠唯一的元素,如class,static變量
答案就是:在Java 7之前,String Pool被放在運行時常量池中,它屬于永久代。而在Java 7,String Pool被移到堆中。這是因為永久代的空間有限,在大量使用字符串的場景下會導致OutOfMemoryError錯誤。
問題:String str = new String("abc") 創建多少個對象?
1.在常量池中查找是否有"abc"對象
- 有則返回對應的引用實例
- 沒有則創建對應的實例對象
2.在堆中 new 一個 String("abc") 對象
3.將對象地址賦值給str,創建一個引用
答案:如果常量池中沒有"abc"字面量則創建兩個對象,否則創建一個對象,以及創建一個引用。
操作字符串常量池的方式
下面代碼中,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}當一個字符串調用intern()方法時,如果String Pool中已經存在一個字符串和該字符串值相等(使用equals()方法進行確定),那么就會返回String Pool中字符串的引用;否則,就會在String Pool中添加一個新的字符串,并返回這個新字符串的引用。
如果是采用"bbb"的形式創建字符串,會自動地將字符串放入
public static void main(String[] args) {String s5="bbb";String s6="bbb";System.out.println(s5==s6); // true}總結
以上是生活随笔為你收集整理的float类型转integer_Java基础(一)之数据类型——全面,浅显易懂的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 子类重写父类虚函数_C/C++编程笔记:
- 下一篇: java 返回空数组_避免在Java中检