Java中char[]輸出不是內(nèi)存地址的原因詳解
前言
Java中共有八種基本數(shù)據(jù)類型:byte,int,short,long,float,double,char,boolean。
計(jì)算機(jī)中的基礎(chǔ)數(shù)據(jù)單位是bit, 1byte=8bit。
| 數(shù)據(jù)類型 | 存儲(chǔ)大小 | 舉例 | 注釋 | 包裝類 |
|---|---|---|---|---|
| byte | 1byte | 3 | 字節(jié) | Byte |
| int | 4byte | 4 | 整數(shù) | Integer |
| short | 2bytes | 5 | 短整數(shù) | Short |
| long | 8bytes | 6 | 長(zhǎng)整數(shù) | Long |
| float | 4bytes | 1.3 | 單精度浮點(diǎn)型 | Float |
| double | 8bytes | 1.2 | 雙精度浮點(diǎn)型 | Double |
| char | 2bytes | ‘a(chǎn)' | 字符 | Char |
| boolean | 1bit | true | 布爾值 | Boolean |
這8種基本數(shù)據(jù)類型很簡(jiǎn)單,在示例中應(yīng)用來(lái)看一下:
public class Test {
public static void main(String[] args){
System.out.println("8種基本數(shù)據(jù)類型");
int a=5;
System.out.println(a);
char b='z';
System.out.println(b);
boolean d=false;
System.out.println(d);
byte e=3;
System.out.println(e);
short f=4;
System.out.println(f);
long g=32000000;
System.out.println(g);
float h=5;
System.out.println(h);
double i=6;
System.out.println(i);
}
}
一段簡(jiǎn)單的輸出代碼,看看打印結(jié)果:
8種基本數(shù)據(jù)類型 5 z false 3 4 32000000 5.0 6.0
可以看到輸出結(jié)果是沒(méi)有問(wèn)題的。
基本數(shù)據(jù)類型和對(duì)象引用
基本數(shù)據(jù)類型會(huì)一直在棧中創(chuàng)建,當(dāng)聲明基本類型時(shí),不需要new。
int a=1;
棧的讀取速度比堆快。基本類型一旦被聲明,java將在棧上直接存儲(chǔ)它,所以基本類型的變量表示的是數(shù)據(jù)本身。
假如調(diào)用基本類型的包裝類來(lái)創(chuàng)建對(duì)象,那么將會(huì)在堆中創(chuàng)建。
Employee a=new Emploee(1.4);
等號(hào)右側(cè)的new Double() 。這個(gè)new是在內(nèi)存的堆中為對(duì)象開辟控件,保存對(duì)象的數(shù)據(jù)和方法。
等號(hào)左側(cè) Double a。a指代的是Double的一個(gè)對(duì)象,稱為對(duì)象引用,這個(gè)對(duì)象引用是在棧中創(chuàng)建的。實(shí)際上a不是對(duì)象本身,它用來(lái)指向一個(gè)地址。
賦值=。這個(gè)就是把對(duì)象的地址賦給a。
此時(shí)輸出a就是一個(gè)內(nèi)存地址。有興趣的同學(xué)自己試一試。
這個(gè)地方說(shuō)明一個(gè)問(wèn)題,假如你自定義的對(duì)象重寫了.toString方法,此處就會(huì)顯示你的自定義的重寫方法的輸出值。
在java的基本類型包裝類中就重寫了這個(gè)方法,所以調(diào)用print方法時(shí)會(huì)自動(dòng)調(diào)用它的toString()方法。
public class Wrapper {
static class Employee{
static int age;
Employee(int a){
age=a;
}
}
static class Employer{
static int year;
Employer (int y){
year=y;
}
@Override
public String toString() {
return "Employer's year="+year;
}
}
public static void main(String[] args){
Employee e=new Employee(4);
System.out.println("e="+e);
Employer f=new Employer(5);
System.out.println("f="+f);
}
}
在上邊的例子中Employee的toString()方法沒(méi)有被重寫,Employer的toString()方法被重寫了。
來(lái)看輸出結(jié)果:
e=Wrapper$Employee@1b6d3586 f=Employer's year=5
前者仍然是內(nèi)存地址,后者是我們重寫的方法。
print方法在調(diào)用事,假如類中的toString()方法沒(méi)有被重寫,則會(huì)電泳String.valueof()方法(后邊有講),假如重寫了就會(huì)調(diào)用toString方法。
所有的包裝類(Integer,Boolean等)都已經(jīng)重寫了toString方法,所以不會(huì)輸出內(nèi)存地址,而是輸出正確的值。
下面的是Double類中的方法:
private final double value;
public String toString() {
return toString(value);
}
整形數(shù)據(jù)類型取值范圍
byte占據(jù)8位,則其取值范圍應(yīng)該是2的8次方,也就是-128~127,超過(guò)這個(gè)區(qū)間就會(huì)報(bào)錯(cuò),例如:
byte a=128;
在編譯器中會(huì)報(bào)錯(cuò),提示不能將int轉(zhuǎn)換為byte,因?yàn)?28已經(jīng)超出byte的范圍了。
同樣可以推得其他值的取值范圍。
基本類型的數(shù)組輸出值
public class TestOne {
public static void main(String[] args) {
int a=127;
System.out.println(a);
int[] b=new int[]{1,2,3};
System.out.println(b);
int[] c=new int[100];
System.out.println(c);
int[] d={1,2,3};
System.out.println(d);
boolean e=false;
System.out.println(e);
boolean[] f={false,false,true};
System.out.println(f);
char g='a';
System.out.println(g);
char[] h={'a','b','c'};
System.out.println(h);
char[] i=new char[]{'a','b','c'};
System.out.println(i);
float j=1.2f;
System.out.println(j);
float[] k={1.2f,1.3f,1.4f};
System.out.println(k);
}
}
看一下打印的結(jié)果:
127 [I@15db9742 [I@6d06d69c [I@7852e922 false [Z@4e25154f a abc abc 1.2 [F@70dea4e
可以看到,在結(jié)果中,所有的基本類型都可以打印出來(lái),數(shù)組類型只能打印出char數(shù)組,其他的都是內(nèi)存地址。
來(lái)看一下源碼,在print函數(shù)中
public void print(char c) {
write(String.valueOf(c));
}
這個(gè)char被轉(zhuǎn)換為了String類型,然后進(jìn)行wirte方法:
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
這里會(huì)立即發(fā)送緩沖流輸出。
對(duì)于所有的基礎(chǔ)類型都會(huì)打印出具體的值,這個(gè)沒(méi)有問(wèn)題,但是對(duì)于數(shù)組為什么只有char的數(shù)組類型打印出了正確的結(jié)果而沒(méi)有輸出內(nèi)存地址?
帶著這個(gè)問(wèn)題我們來(lái)了解一下:
對(duì)于int型數(shù)組,java調(diào)用的是下面的方法:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
此處數(shù)組被認(rèn)為是Object類型,調(diào)用的是
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
此處的三目表達(dá)式用來(lái)判空,然后看一下obj.toString()方法:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
相信看到此處應(yīng)該可以看出來(lái)為什么輸出會(huì)是[I@1b6d3586了,I代表的類的名稱。
那么對(duì)于char數(shù)組類型的調(diào)用呢,次數(shù)室友玄機(jī)的:
public void println(char x[]) {
synchronized (this) {
print(x);
newLine();
}
}
此處調(diào)用的是println(char x[])這個(gè)函數(shù),那么這個(gè)char x[]是個(gè)什么鬼呢?
其實(shí)就是java中的數(shù)組初始化,相當(dāng)于char[] x 。
然后看看print(x)函數(shù):
public void print(char s[]) {
write(s);
}
最后是write()函數(shù):
private void write(char buf[]) {
try {
synchronized (this) {
ensureOpen();
textOut.write(buf);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush) {
for (int i = 0; i < buf.length; i++)
if (buf[i] == '\n')
out.flush();
}
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
到了這大家知道為什么會(huì)有區(qū)別了么,因?yàn)槠渌愋偷臄?shù)組都被認(rèn)為是Object類型了,所以會(huì)輸出內(nèi)存地址。而char[]調(diào)用的方法是輸出char這個(gè)數(shù)組中的每一個(gè)值,所以不是內(nèi)存地址了。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
java接口中的代理設(shè)計(jì)模式代碼時(shí)實(shí)踐
這篇文章主要介紹了java接口中的代理設(shè)計(jì)模式代碼時(shí)實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
java web監(jiān)聽器統(tǒng)計(jì)在線用戶及人數(shù)
本文主要介紹了java web監(jiān)聽器統(tǒng)計(jì)在線用戶及人數(shù)的方法解析。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04
Druid基本配置及內(nèi)置監(jiān)控使用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Druid基本配置及內(nèi)置監(jiān)控使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
SpringBoot詳解MySQL如何實(shí)現(xiàn)讀寫分離
當(dāng)響應(yīng)的瓶頸在數(shù)據(jù)庫(kù)的時(shí)候,就要考慮數(shù)據(jù)庫(kù)的讀寫分離,當(dāng)然還可以分庫(kù)分表,那是單表數(shù)據(jù)量特別大,當(dāng)單表數(shù)據(jù)量不是特別大,但是請(qǐng)求量比較大的時(shí)候,就要考慮讀寫分離了.具體的話,還是要看自己的業(yè)務(wù)...如果還是很慢,那就要分庫(kù)分表了...我們這篇就簡(jiǎn)單講一下讀寫分離2022-09-09
Java調(diào)用IK分詞器進(jìn)行分詞方式,封裝工具類
這篇文章主要介紹了Java調(diào)用IK分詞器進(jìn)行分詞方式,封裝工具類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

