Java类型简介
1 java基本數據類型
1.1 基本數據類型
java的基礎數據類型有多少個,每個在內存的分配是多少呢?
| byte | 1 |
| short | 2 |
| char | 2 |
| int | 4 |
| long | 8 |
| reference | 4/8 |
| array | 4/8 |
引用類型分配的大小與平臺類型相關,如32位系統為4字節,64位為8字節
基本上在java所有的類型都是在這6個類型的基礎上衍化出來的,這是java世界的基石。
jvm會將內存劃分為棧與堆區,棧為線程獨有,堆為線程共享。如果在方法塊內定義了基本數據類型,那這些類型都會被分配在棧中,因為它們的大小是固定的,而且在方法結束的時候被立刻回收,很方便內存管理。
1.2 數組類型
數組類型可以看作基本數據的組合,數組類型會被分配在棧中嗎,可以作一個簡單的測試:
public class HelloWorld {public static void main(String[] args) {int[] a = new int[6];int[] b = new int[10];a=b;System.out.println(a);} }// 輸出 [I@15db9742這里a起碼分配了64字節,b分配了104字節,而將b賦值給a之后,將沒有運行出錯,說明數組不可能是分配在棧區,因為只有固定大小的變量才能分配在棧當中。數組可以看作引用類型的衍化類型。
數組在堆并不會只分配元素大小*數組size大小的字節,從常理看起碼還需要包含元素類型的描述以及size的記錄這兩個元數據的空間。
2 java復合類型
由上一節,提到java所有類型都有基本類型衍化生成,這里將以Object,Integer,String三種類型來展示衍化的工作。
2.1 Object
來看一下Object的源碼
public class Object {private static native void registerNatives();static {registerNatives();}public final native Class<?> getClass();public native int hashCode();public boolean equals(Object obj) {return (this == obj);}protected native Object clone() throws CloneNotSupportedException;public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}public final native void notify();public final native void notifyAll();public final native void wait(long timeout) throws InterruptedException;public final void wait(long timeout, int nanos) throws InterruptedException {if (timeout < 0) {throw new IllegalArgumentException("timeout value is negative");}if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}if (nanos > 0) {timeout++;}wait(timeout);}public final void wait() throws InterruptedException {wait(0);}protected void finalize() throws Throwable { } }Object類里面,沒有成員變量,只定義對應的幾個方法,以及類初始化時的一個方法塊。對于每個方法的具體作用,先按下不表。當Object 被new出一個實例時,可以簡單地看作在棧區生成一個引用,那在堆區內會為實例分配出多少字節呢?理論上,Object沒有成員變量,在堆應該是0字節,但是棧的引用又指向了堆了,表明堆肯定為此實例分配了內存。
答案是2個引用size的字節,即32位平臺下分配8個字節,64位平臺下分配16個字節,里面有兩個引用,一個指向當前Object的類對象,另一個對向klass對象。這兩個對象先按下不表,具體可以參見文章:new一個Object對象占用多少內存?。
2.2 Integer類型
先看源碼
import java.lang.annotation.Native;public final class Integer extends Number implements Comparable<Integer> {/*** A constant holding the minimum value an {@code int} can* have, -2<sup>31</sup>.*/@Native public static final int MIN_VALUE = 0x80000000;/*** A constant holding the maximum value an {@code int} can* have, 2<sup>31</sup>-1.*/@Native public static final int MAX_VALUE = 0x7fffffff;/*** Parses the string argument as a signed integer in the radix* specified by the second argument. The characters in the string* must all be digits of the specified radix (as determined by* whether {@link java.lang.Character#digit(char, int)} returns a* nonnegative value), except that the first character may be an* ASCII minus sign {@code '-'} ({@code '\u005Cu002D'}) to* indicate a negative value or an ASCII plus sign {@code '+'}* ({@code '\u005Cu002B'}) to indicate a positive value. The* resulting integer value is returned.** <p>An exception of type {@code NumberFormatException} is* thrown if any of the following situations occurs:* <ul>* <li>The first argument is {@code null} or is a string of* length zero.** <li>The radix is either smaller than* {@link java.lang.Character#MIN_RADIX} or* larger than {@link java.lang.Character#MAX_RADIX}.** <li>Any character of the string is not a digit of the specified* radix, except that the first character may be a minus sign* {@code '-'} ({@code '\u005Cu002D'}) or plus sign* {@code '+'} ({@code '\u005Cu002B'}) provided that the* string is longer than length 1.** <li>The value represented by the string is not a value of type* {@code int}.* </ul>** <p>Examples:* <blockquote><pre>* parseInt("0", 10) returns 0* parseInt("473", 10) returns 473* parseInt("+42", 10) returns 42* parseInt("-0", 10) returns 0* parseInt("-FF", 16) returns -255* parseInt("1100110", 2) returns 102* parseInt("2147483647", 10) returns 2147483647* parseInt("-2147483648", 10) returns -2147483648* parseInt("2147483648", 10) throws a NumberFormatException* parseInt("99", 8) throws a NumberFormatException* parseInt("Kona", 10) throws a NumberFormatException* parseInt("Kona", 27) returns 411787* </pre></blockquote>** @param s the {@code String} containing the integer* representation to be parsed* @param radix the radix to be used while parsing {@code s}.* @return the integer represented by the string argument in the* specified radix.* @exception NumberFormatException if the {@code String}* does not contain a parsable {@code int}.*/public static int parseInt(String s, int radix)throws NumberFormatException{/** WARNING: This method may be invoked early during VM initialization* before IntegerCache is initialized. Care must be taken to not use* the valueOf method.*/if (s == null) {throw new NumberFormatException("null");}if (radix < Character.MIN_RADIX) {throw new NumberFormatException("radix " + radix +" less than Character.MIN_RADIX");}if (radix > Character.MAX_RADIX) {throw new NumberFormatException("radix " + radix +" greater than Character.MAX_RADIX");}int result = 0;boolean negative = false;int i = 0, len = s.length();int limit = -Integer.MAX_VALUE;int multmin;int digit;if (len > 0) {char firstChar = s.charAt(0);if (firstChar < '0') { // Possible leading "+" or "-"if (firstChar == '-') {negative = true;limit = Integer.MIN_VALUE;} else if (firstChar != '+')throw NumberFormatException.forInputString(s);if (len == 1) // Cannot have lone "+" or "-"throw NumberFormatException.forInputString(s);i++;}multmin = limit / radix;while (i < len) {// Accumulating negatively avoids surprises near MAX_VALUEdigit = Character.digit(s.charAt(i++),radix);if (digit < 0) {throw NumberFormatException.forInputString(s);}if (result < multmin) {throw NumberFormatException.forInputString(s);}result *= radix;if (result < limit + digit) {throw NumberFormatException.forInputString(s);}result -= digit;}} else {throw NumberFormatException.forInputString(s);}return negative ? result : -result;}/*** 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() {}}/*** Returns an {@code Integer} instance representing the specified* {@code int} value. If a new {@code Integer} instance is not* required, this method should generally be used in preference to* the constructor {@link #Integer(int)}, as this method is likely* to yield significantly better space and time performance by* caching frequently requested values.** This method will always cache values in the range -128 to 127,* inclusive, and may cache other values outside of this range.** @param i an {@code int} value.* @return an {@code Integer} instance representing {@code i}.* @since 1.5*/public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}/*** The value of the {@code Integer}.** @serial*/private final int value;/*** Constructs a newly allocated {@code Integer} object that* represents the specified {@code int} value.** @param value the value to be represented by the* {@code Integer} object.*/public Integer(int value) {this.value = value;}}Integer是一個非常簡單的復合類型,只有一個不可變成員變量value,還有一個IntegerCache的內部靜態類,其緩存[-128, 127]范圍的Integer數組,使用valueOf生成的Integer實例的時候如果在此范圍內使用緩存實例,減少內存的浪費。因為Integer類無法修改value變量(聲明為final),并且本身也聲明為final,防止了子類修改value的可能,因此可以放心使用緩存來節省內存。
2.3 String類型
接下來來啃一個硬骨頭————String類。String經常被我們所使用,它自帶了兩種初始化方法,直接賦值字符串的分配在棧區,而使用new的將被分配在堆區,這里來看一下分配在堆區的類。
import java.util.Comparator;/*** The {@code String} class represents character strings. All* string literals in Java programs, such as {@code "abc"}, are* implemented as instances of this class.* <p>* Strings are constant; their values cannot be changed after they* are created. String buffers support mutable strings.* Because String objects are immutable they can be shared. For example:* <blockquote><pre>* String str = "abc";* </pre></blockquote><p>* is equivalent to:* <blockquote><pre>* char data[] = {'a', 'b', 'c'};* String str = new String(data);* </pre></blockquote><p>* Here are some more examples of how strings can be used:* <blockquote><pre>* System.out.println("abc");* String cde = "cde";* System.out.println("abc" + cde);* String c = "abc".substring(2,3);* String d = cde.substring(1, 2);* </pre></blockquote>* <p>* The class {@code String} includes methods for examining* individual characters of the sequence, for comparing strings, for* searching strings, for extracting substrings, and for creating a* copy of a string with all characters translated to uppercase or to* lowercase. Case mapping is based on the Unicode Standard version* specified by the {@link java.lang.Character Character} class.* <p>* The Java language provides special support for the string* concatenation operator ( + ), and for conversion of* other objects to strings. String concatenation is implemented* through the {@code StringBuilder}(or {@code StringBuffer})* class and its {@code append} method.* String conversions are implemented through the method* {@code toString}, defined by {@code Object} and* inherited by all classes in Java. For additional information on* string concatenation and conversion, see Gosling, Joy, and Steele,* <i>The Java Language Specification</i>.** <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor* or method in this class will cause a {@link NullPointerException} to be* thrown.** <p>A {@code String} represents a string in the UTF-16 format* in which <em>supplementary characters</em> are represented by <em>surrogate* pairs</em> (see the section <a href="Character.html#unicode">Unicode* Character Representations</a> in the {@code Character} class for* more information).* Index values refer to {@code char} code units, so a supplementary* character uses two positions in a {@code String}.* <p>The {@code String} class provides methods for dealing with* Unicode code points (i.e., characters), in addition to those for* dealing with Unicode code units (i.e., {@code char} values).** @author Lee Boynton* @author Arthur van Hoff* @author Martin Buchholz* @author Ulf Zibis* @see java.lang.Object#toString()* @see java.lang.StringBuffer* @see java.lang.StringBuilder* @see java.nio.charset.Charset* @since JDK1.0*/public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/*** The value is used for character storage.*/private final char value[];/*** Initializes a newly created {@code String} object so that it represents* an empty character sequence. Note that use of this constructor is* unnecessary since Strings are immutable.*/public String() {this.value = "".value;}/*** Initializes a newly created {@code String} object so that it represents* the same sequence of characters as the argument; in other words, the* newly created string is a copy of the argument string. Unless an* explicit copy of {@code original} is needed, use of this constructor is* unnecessary since Strings are immutable.** @param original A {@code String}*/public String(String original) {this.value = original.value;}/*** Returns the length of this string.* The length is equal to the number of <a href="Character.html#unicode">Unicode* code units</a> in the string.** @return the length of the sequence of characters represented by this* object.*/public int length() {return value.length;}/*** Returns {@code true} if, and only if, {@link #length()} is {@code 0}.** @return {@code true} if {@link #length()} is {@code 0}, otherwise* {@code false}* @since 1.6*/public boolean isEmpty() {return value.length == 0;}/*** Returns the {@code char} value at the* specified index. An index ranges from {@code 0} to* {@code length() - 1}. The first {@code char} value of the sequence* is at index {@code 0}, the next at index {@code 1},* and so on, as for array indexing.** <p>If the {@code char} value specified by the index is a* <a href="Character.html#unicode">surrogate</a>, the surrogate* value is returned.** @param index the index of the {@code char} value.* @return the {@code char} value at the specified index of this string.* The first {@code char} value is at index {@code 0}.* @throws IndexOutOfBoundsException if the {@code index}* argument is negative or not less than the length of this* string.*/public char charAt(int index) {if ((index < 0) || (index >= value.length)) {throw new StringIndexOutOfBoundsException(index);}return value[index];}public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String) anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;}/*** A Comparator that orders {@code String} objects as by* {@code compareToIgnoreCase}. This comparator is serializable.* <p>* Note that this Comparator does <em>not</em> take locale into account,* and will result in an unsatisfactory ordering for certain locales.* The java.text package provides <em>Collators</em> to allow* locale-sensitive ordering.** @see java.text.Collator#compare(String, String)* @since 1.2*/public static final Comparator<String> CASE_INSENSITIVE_ORDER= new CaseInsensitiveComparator();private static class CaseInsensitiveComparatorimplements Comparator<String>, java.io.Serializable {// use serialVersionUID from JDK 1.2.2 for interoperabilityprivate static final long serialVersionUID = 8575799808933029326L;public int compare(String s1, String s2) {int n1 = s1.length();int n2 = s2.length();int min = Math.min(n1, n2);for (int i = 0; i < min; i++) {char c1 = s1.charAt(i);char c2 = s2.charAt(i);if (c1 != c2) {c1 = Character.toUpperCase(c1);c2 = Character.toUpperCase(c2);if (c1 != c2) {c1 = Character.toLowerCase(c1);c2 = Character.toLowerCase(c2);if (c1 != c2) {// No overflow because of numeric promotionreturn c1 - c2;}}}}return n1 - n2;}/*** Replaces the de-serialized object.*/private Object readResolve() {return CASE_INSENSITIVE_ORDER;}}/*** Returns a canonical representation for the string object.* <p>* A pool of strings, initially empty, is maintained privately by the* class {@code String}.* <p>* When the intern method is invoked, if the pool already contains a* string equal to this {@code String} object as determined by* the {@link #equals(Object)} method, then the string from the pool is* returned. Otherwise, this {@code String} object is added to the* pool and a reference to this {@code String} object is returned.* <p>* It follows that for any two strings {@code s} and {@code t},* {@code s.intern() == t.intern()} is {@code true}* if and only if {@code s.equals(t)} is {@code true}.* <p>* All literal strings and string-valued constant expressions are* interned. String literals are defined in section 3.10.5 of the* <cite>The Java™ Language Specification</cite>.** @return a string that has the same contents as this string, but is* guaranteed to be from a pool of unique strings.*/public native String intern(); }String的內存分配實質就是char[] ,并且是不可變的char[],因為value變量聲明為final,并且沒有對外set方法,而且String還被聲明為final,這樣杜絕了初始化之后再被修改的可能性。這種不可變性的好處之后再表,這里先按下。
從String自帶的幾個方法里面,最為有意思的是intern()方法,先看一下源碼注釋。
簡單地來看,就是一個string的緩存池,跟Integer的IntegerCache是一個意思,不過由于String的可變性比Integer大很多,實現方式也由java實現改為native實現。(不知道怎么吐槽好,java無法直接調用底層,也非自舉,如果需要進一步了解native方法的實現,還得看c++的源碼,真是一言難盡)
轉載于:https://www.cnblogs.com/oreo/p/10781310.html
總結
- 上一篇: 信号与系统快速学习
- 下一篇: Vue 组件库 HeyUI@1.19.0