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' 字符 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;
棧的讀取速度比堆快?;绢愋鸵坏┍宦暶鳎琷ava將在棧上直接存儲(chǔ)它,所以基本類型的變量表示的是數(shù)據(jù)本身。

假如調(diào)用基本類型的包裝類來(lái)創(chuàng)建對(duì)象,那么將會(huì)在堆中創(chuàng)建。
Employee a=new Emploee(1.4);

  1. 等號(hào)右側(cè)的new Double()。這個(gè)new是在內(nèi)存的堆中為對(duì)象開(kāi)辟控件,保存對(duì)象的數(shù)據(jù)和方法。
  2. 等號(hào)左側(cè) Double a。a指代的是Double的一個(gè)對(duì)象,稱為對(duì)象引用,這個(gè)對(duì)象引用是在棧中創(chuàng)建的。實(shí)際上a不是對(duì)象本身,它用來(lái)指向一個(gè)地址。
  3. 賦值=。這個(gè)就是把對(duì)象的地址賦給a。

此時(shí)輸出a就是一個(gè)內(nèi)存地址。有興趣的同學(xué)自己試一試。

這個(gè)地方說(shuō)明一個(gè)問(wèn)題,假如你自定義的對(duì)象重寫(xiě)了.toString方法,此處就會(huì)顯示你的自定義的重寫(xiě)方法的輸出值。
在java的基本類型包裝類中就重寫(xiě)了這個(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)有被重寫(xiě),Employer的toString()方法被重寫(xiě)了。來(lái)看輸出結(jié)果:

e=Wrapper$Employee@1b6d3586
f=Employer's year=5

前者仍然是內(nèi)存地址,后者是我們重寫(xiě)的方法。

print方法在調(diào)用事,假如類中的toString()方法沒(méi)有被重寫(xiě),則會(huì)電泳String.valueof()方法(后邊有講),假如重寫(xiě)了就會(huì)調(diào)用toString方法。
所有的包裝類(Integer,Boolean等)都已經(jīng)重寫(xiě)了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)存地址了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,706評(píng)論 18 399
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,803評(píng)論 11 349
  • 第一章:Java程序設(shè)計(jì)概述 Java和C++最大的不同在于Java采用的指針模型可以消除重寫(xiě)內(nèi)存和損壞數(shù)據(jù)的可能...
    loneyzhou閱讀 1,368評(píng)論 1 7
  • 老鼠 提心吊膽出沒(méi), 哆哆嗦嗦啃食。 都怪人們討厭, 活著真費(fèi)力氣。
    笑蒼天_6696閱讀 243評(píng)論 0 0
  • 早晨起床想吃煎餅果子,洗漱完出門騎個(gè)摩拜穿過(guò)南鑼鼓巷徑直騎向方磚廠胡同拐個(gè)彎,遠(yuǎn)遠(yuǎn)的就看到了小付煎餅的旗子。嘿,沒(méi)...
    皮皮絡(luò)閱讀 153評(píng)論 0 0

友情鏈接更多精彩內(nèi)容