《Java8學習筆記》讀書筆記(五)

第4章 認識對象

學習目標
? 區(qū)分基本類型與對象類型
? 了解對象與引用的關(guān)系
? 從打包器認識對象
? 以對象觀點看待數(shù)組
? 認識字符串的特性

4.1 類與對象

第3章講的都是基本類型,這一章開始講對象類型。在Java中一切皆對象(Object),要產(chǎn)生對象必須先寫類(Class),類是對象的模版,對象是類的實例(Instance)

4.1.1 定義類

一個類就是一個模版,它包括了所有的屬性和方法,就象設(shè)計師手上的設(shè)計圖紙一樣,如果我們需要設(shè)計一個大黃鴨,那么我們首先會繪制一個大黃鴨的設(shè)計圖,上面定義了大黃鴨的大小、顏色等,我們會根據(jù)設(shè)計圖制作出實際的大黃鴨,每個大黃鴨都是同一個款式,但會擁有自己的大小,顏色。


圖4.1 大黃鴨設(shè)計、制作
如果我們要設(shè)計的就是一個關(guān)于大黃鴨的設(shè)計的軟件,那如何使用Java來編寫呢?首先就要在程序中定義類,這相當于圖4.1中大黃鴨的設(shè)計圖:

class BigDuke{
    String color;
    int size;
}

類定義時使用class關(guān)鍵字,名稱使用BigDuck,相當于為大黃鴨的設(shè)計圖取名叫BigDuck,大黃鴨的顏色用字符串表示,也就是color變量,可存儲”深黃”,”淺黃”,”大黃”等。
大黃鴨的尺寸會是’大’,’中’,’小’,所以使用了char類型。如果要在程序中,利用BigDuck在程序內(nèi)建立實例,就要使用new關(guān)鍵字。例如:

new BigDuck();

在對象術(shù)語中,這叫做實例化一個對象。如果要有個標簽,和這個對象綁定,可以這樣聲明:

BigDuck bd;

是不是很象前面我們聲明基本變量的形式?不過Java專門為這種指向?qū)ο蟮摹白兞俊比×藗€術(shù)語,叫“引用”(Reference Name)。如果要將bd綁到新建的對象上,可以使用“=”賦值,在Java術(shù)語中,叫“將bd引用至實例化對象”。如:

BigDuck bd=new BigDuck();

圖4.2 class、new、=等語法對應(yīng)
提示:對象(Object)與實例(Instance)在Java中幾乎是等義的名詞,本書中就視為相同意義。
在BigDuck類中,定義了color與size兩個變量,以Java的術(shù)語來說,叫作定義兩個屬性(Field)成員,或叫定義兩個成員變量,這表示每個新建的BigDuck實例中都能擁有各自不同的color值與size值。(默然說話:其實簡單說,就是類是一個模版,它定義的類別應(yīng)該具有的屬性,但沒有值,而實例對象則會具備相同的屬性,且每個屬性可以有不同的值。比如人類可以定義膚色與身高,然后每個人類的實例可以擁有不同的膚色值與身高值。

class BigDuck{
    String color;
    char size;
}
/**
 * 說明類和對象關(guān)系的代碼示例
 * 文件:ObjectTest.java
 * @author mouyo
 */
public class ObjectTest {
    public static void main(String[] args) {
        //實例化大黃鴨對象
        BigDuck foodDuck=new BigDuck();
        BigDuck lakeDuck=new BigDuck();
        
        //為每個大黃鴨對象的屬性賦值
        foodDuck.color="淺黃";
        foodDuck.size='小';
        lakeDuck.color="深黃";
        lakeDuck.size='大';
        
        //顯示每個大黃鴨對象的各自屬性值
        System.out.println("黃鴨飯:"+foodDuck.color+","+foodDuck.size);
        System.out.println("湖中大黃鴨:"+lakeDuck.color+","+lakeDuck.size);
    }
}

在這個ObjectTest.java中,定義了兩個類,一個是公開(public)的ObjectTest類,Java規(guī)定,公開(public)的類名必須與文件一致。另一個是非公開的BigDuck。
提示:只要有類定義,編譯程序就會產(chǎn)生一個.class文件。上例中會產(chǎn)生ObjectTest.class和BigDuck.class兩個文件
程序中實例化了兩個BigDuck對象,并分別聲明了foodDuck與lakeDuck兩個引用變量,接著指定了foodDuck綁定的對象所擁有的color和size分別賦值為”淺黃”和’小’,而lakeDuck綁定的對象所擁有的color和size分別賦值為”深黃”和’大’。最后分別顯示foodDuck與lakeDuck各自擁有的屬性值:

run:
黃鴨飯:淺黃,小
湖中大黃鴨:深黃,大
成功構(gòu)建 (總時間: 0 秒)

執(zhí)行結(jié)果如上,可以看出來,每個對象都擁有自己的數(shù)據(jù),它們是相互獨立,互不影響的。(默然說話:這也就在提醒我們,當我們進行屬性賦值的時候,除了要關(guān)心屬性的值之外,還要關(guān)心被賦值的屬性是哪個對象,如果搞錯了對象,那值也就是不對的了。
觀察為每個大黃鴨對象的屬性賦值的那段代碼,你會發(fā)現(xiàn)它們雖然是給不同的對象賦值,但代碼的書寫基本是一樣的。只要是一樣的代碼,我們就可以進行模版化,讓這些代碼只寫一遍。這里我們可以使用構(gòu)造方法。構(gòu)造方法是與類名同名的方法,它沒有返回值。

public class BigDuck2 {
   String color;
   char size;
   BigDuck2(String color,char size){//構(gòu)造方法
       this.color=color;//將參數(shù)color指定給color屬性
       this.size=size;
   }
   
    public static void main(String[] args) {
        BigDuck2 foodDuck=new BigDuck2("淺黃",'小');//使用指定構(gòu)造方法建立對象
        BigDuck2 lakeDuck=new BigDuck2("深黃",'大');
        
        //顯示每個大黃鴨對象的各自屬性值
        System.out.println("黃鴨飯:"+foodDuck.color+","+foodDuck.size);
        System.out.println("湖中大黃鴨:"+lakeDuck.color+","+lakeDuck.size);
    }
}

在這個例子中,定義新建對象時,必須傳入兩個參數(shù)給String類型的color與char類型size參數(shù),而構(gòu)造方法中,由于color參數(shù)與color屬性名相同,你不可以直接寫color=color,而要寫成this.color=color。
在實際使用new創(chuàng)建對象時,就可以直接傳入字符串與字符,分別代表BigDuck實例的color與size值,執(zhí)行結(jié)果與上個例子相同。

4.1.2 使用標準類

第一章已經(jīng)講過,Java Se提供了標準API,這些API就是由許多類組成,你可以直接取用這些標準類,省去自己打造基礎(chǔ)的需求。下面舉兩個基本的標準類:java.util.Scannerjava.math.BigDecimal。
1.使用java.util.Scanner
目前為止的程序例子都很無聊,變量值都是寫死的,沒有辦法接受用戶的輸入。如果要在命令行模式下取得用戶輸入,我們就可以使用java.util.Scanner。

package cn.com.speakermore.ch04;

import java.util.Random;
import java.util.Scanner;//導入標準API中的Scanner類

/**
 * 猜數(shù)
 * @author mouyo
 */
public class Guess {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);//創(chuàng)建Scanner對象
        int number=new Random().nextInt(10);
        int guess;
        
        do{
            System.out.print("猜數(shù)(0~9)");
            guess=input.nextInt();//獲得用戶輸入的整型數(shù)
        }while(guess!=number);
        System.out.println("恭喜!猜對了!");
    }
}

由于我們不想每次都輸入java.util.Scanner,所以一開始就使用import告訴編譯器:“我需要使用java.util.Scanner,請幫我導入?!痹趯嵗╪ew)Scanner對象時,必須傳入System.in對象,它是一個java.io.InputStream流對象(默然說話:關(guān)于這些內(nèi)容,第10章會詳細介紹,你現(xiàn)在就當做烏龜?shù)钠ü伞?guī)定——來照著寫就可以了)。
接下來就可以很簡單的通過Scanner的對象(名字叫input)來獲得鍵盤的輸入了。大家完全不用管它是怎么獲得鍵盤輸入的,反正就是能獲得。(默然說話:這就是面向?qū)ο罄锩娴囊粋€概念:封裝。舉個生活中的例子:你只要懂得打開水龍頭,就可以得到水,而完全不用去關(guān)心水怎么是從水龍頭里流出來的。忽略細節(jié),可以讓我們更專心的做自己想要去完成的事情,而不用啥都操心,這就是封裝。后面的相關(guān)章節(jié)還會詳細闡述。
ScannernextInt()方法會查看鍵盤輸入的是不是數(shù)字,如果是數(shù)字就會接收。Scanner對每個基本類型,都會有個對應(yīng)的nextXxx()方法,如nextByte()、nextShort()、nextLong()、nextFloat()、nextDouble()、nextBoolean()等,如果要取字符串,則使用next(),如果是取一行字符串,則使用nextLine()(以換行分隔)。

提示:包是java管理類的一種方式,后面相關(guān)內(nèi)容會介紹。包名以java開頭的類,都是標準API提供的類。

2.使用java.math.BigDecimal
第2章介紹基本類型的時候有個問題:1.0-0.8的結(jié)果是多少?答案肯定不是0.2,而是0.19999999999999996。為什么?java的bug?肯定不是,因為你用其他的語言來算這個算式也會得到同樣的結(jié)果。
簡單來說,java遵守IEEE754浮點數(shù)運算規(guī)范,使用分數(shù)與指數(shù)來表示浮點數(shù)。例如0.5是使用1/2來表示,0.75是使用1/2+1/4來表示,而0.1會使用1/16+1/32+1/256+…無限循環(huán)下去,無法精確表示。因而造成運算上的誤差。
再來舉個例子,你覺得下面的程序片段會顯示什么結(jié)果?

        double a=0.1;
        double b=0.1;
        double c=0.1;
        
        if((a+b+c)==0.3){
            System.out.println("等于0.3");
        }else{
            System.out.println("不等于0.3");
        }

由于浮點數(shù)誤差的關(guān)系,結(jié)果是顯示“不等于0.3”。類似的例子還有很多,結(jié)論就是,如果要求精確度,那就要小心地使用浮點數(shù),而且別用==直接比較浮點數(shù)運算結(jié)果。
那么要怎么辦能得到更好的精確度?可以使用java.math.BigDecimal類。

import java.math.BigDecimal;
/**
 *DecimalDemo.java
 * @author mouyo
 */

public class DecimalDemo {
    public static void main(String[] args) {
        BigDecimal a=new BigDecimal("1.0");
        BigDecimal b=new BigDecimal("0.8");
        BigDecimal result=a.subtract(b);
        System.out.println(result);
        System.out.println(1.0-0.8);
    }
}

創(chuàng)建BigDecimal的方法之一是使用字符串,BigDecimal在創(chuàng)建時會分析字符串,以默認精度進行接下來的運算。BigDecimal提供有plus()、substract()、multiply()、divide()等方法,可以進行加、減、乘、除等運算,這些方法都會返回代表運算結(jié)果的BigDecimal。
上面的例子可以看到0.2的結(jié)果,再來看利用BigDecimal比較相等的例子。

import java.math.BigDecimal;

/**
 *DecimalDemo2.java
 * @author mouyo
 */
public class DecimalDemo2 {
    public static void main(String[] args) {
        BigDecimal a=new BigDecimal("0.1");
        BigDecimal b=new BigDecimal("0.1");
        BigDecimal c=new BigDecimal("0.1");
        BigDecimal result=new BigDecimal("0.3");
        
        if(a.add(b).add(c).equals(result)){
            System.out.println("等于0.3");
        }else{
            System.out.println("不等于0.3");
        }
    }
}

由于BigDecimaladd()方法都會返回代表運算結(jié)果的BigDecimal,所以就直接利用返回再次add()。最后再調(diào)用equals()方法比較相等。最后的結(jié)果是等于0.3。

4.1.3 對象指定與相等性

在上一例中,比較兩個BigDecimal是否相等,是使用equals()方法而非使用==運算符,為什么?前面說過,在Java中有兩大類型系統(tǒng),基本類型和引用類型,基本類型把值直接放到變量中,而引用類型是把對象的內(nèi)存地址放入變量中。
當使用=(默然說話:記??!這個不是等號,是賦值號,用來把一個值放到某個變量中!)給基本變量賦值時,就是把值直接放入了變量中,而引用類型變量賦值時,放入的是一個對象的所在位置的地址。正因為如此,當使用==進行比較時,基本變量就是比較了值是否相等(默然說話:因為基本變量就保存了一個值呀!)而引用類型變量比較的卻是內(nèi)存位置是否相等(因為引用類型變量保存的是地址呀!)。
這是基本類型變量的代碼與示例圖,記住,基本類型保存的是值!

        int a=10;
        int b=10;
        int c=a;
        System.out.println(a==b);
        System.out.println(a==c);

圖4.3 基本變量的賦值與比較相等的結(jié)果


圖4.4 基本變量的賦值與比較相等的原理
這是引用類型變量的代碼與示例圖,記住,引用類型保存的是地址!
BigDecimal a=new BigDecimal("0.1");
BigDecimal b=new BigDecimal("0.1");
BigDecimal c=a;
System.out.println(a==b);
System.out.println(a==c);

圖4.5 引用類型變量的賦值與比較相等

圖4.6 引用類型變量的比較相等結(jié)果
使用==比較的就是變量里所保存的值是否相等,由于引用類型保存的值是對象的內(nèi)存地址,所以比較兩個引用型變量相等,就是比較兩個引用變量所引用的對象是不是同一個(默然說話:內(nèi)存地址相同,就是同一個變量,因為不可能在同一個內(nèi)存地址中放兩個不同的對象。),如果我們想要的結(jié)果是兩個對象的內(nèi)容是不是一樣,我們需要使用equals()方法。(默然說話:上面的程序中可以看到兩個對象都裝著“0.1”這個數(shù),所以如果我們是要兩個對象裝的內(nèi)容是不是一樣,是不能使用==來比較的,因為它比較的是地址
提示:其實從內(nèi)存的實際運作來看,=與==對于基本類型變量與引用類型變量的作用并沒有不同,只是因為它們所保存的值的意義不一樣,才造成了這一區(qū)別。

4.2 基本類型包裝類

基本類型long、int、double、float、boolean等,在J2SE5.0之前必須手動使用Long、Integer、Double、Float、Boolean等打包為對象,才能當作對象來操作。5.0之后開始自動打包了。

4.2.1 包裝基本類型

Java的基本類型在于效率,但更多的時候,會使用類建立實例,因為對象本身可以提供更多信息,更多方便的操作??梢允褂肔ong、Integer、Double、Float、Boolean、Byte等類來包裝(Wrap)基本類型。
Long、Integer、Double等類就是所謂的包裝類(Wrapper),正如此名稱所示,這些類主要目的就是提供對象實例作為“殼”,將基本類型包裝在對象中,就像是將基本類型當作對象操作。

/**
 *  IntegerDemo.java
 * @author mouyo
 */
public class IntegerDemo {
    public static void main(String[] args) {
        //基本類型
        int data1=10;
        int data2=10;
        //包裝類型
        Integer wrapper1=new Integer(data1);
        Integer wrapper2=new Integer(data2);
        //基本類型除法,只能得到整數(shù)部分,小數(shù)被舍棄
        System.out.println(data1/3);
        //使用包裝類的方法把整數(shù)轉(zhuǎn)為小數(shù),得到了有小數(shù)的結(jié)果
        System.out.println(wrapper1.doubleValue()/3);
        //使用包裝類提供的方法進行比較,得到更多的信息
        System.out.println(wrapper2.compareTo(wrapper2));
    }
}

包裝類都放在java.lang包中,這個包是java編譯器默認會導入的包,所以不需要import語句來顯示導入。包裝一個基本類型就是new出包裝類,然后將基本類型傳給包裝類就可以了。
基本數(shù)據(jù)類型如果都是整型,那最后的計算結(jié)果也會是整形。
如果我們期望得到小數(shù)的結(jié)果,那么可以使用包裝類的轉(zhuǎn)換方法來得到一個小數(shù),然后計算機在運算時會自動類型轉(zhuǎn)換為小數(shù)后再做計算,最后的結(jié)果就也是小數(shù)(默然說話:其實我們平時寫程序時,是直接把整型數(shù)寫成小數(shù)。比如10/3.0,這樣的結(jié)果就會是小數(shù)了。)。
Integer提供compareTo()方法,可與另一個Integer對象比較,如果相同就返回0,如果小于傳入的對象就返回-1。否則就是1。而==和!=只能得到很少的信息。

4.2.2 自動裝箱、拆箱

除了使用new來包裝之外,從J2SE5.0之后提供了自動裝箱功能??梢赃@樣包裝基本類型:

Integer wrapper=10;

編譯程序會自動判斷是否能進行自動裝箱,在上例如你的wrapper會被賦值為一個Integer對象。其他基本類型也是一樣的。改寫下上面的代碼:

Integer data1=10;
Integer data2=20;
System.out.println(data1.doubleValue() / 3);
System.out.println(data1.compareTo(data2));

程序看上去簡潔很多,data1和data2在運行時會自動裝箱Integer對象。自動裝箱還可以這樣用:

int i=0;
Integer wrapper=i;

也可以使用更一般化的Number來自動裝箱:

Number num=3.11f;

3.11f會先被自動裝箱為Float,然后引用給num。
Java SE 5.0開始,還可以進行自動拆箱,也就是把包裝類自動取值賦給基本類型變量。如:

Integer wrapper=10;//自動裝箱
int a=wrapper;//自動拆箱

在運算時,也可以進行自動裝箱與拆箱,如:

Integer a=10;
System.out.println(i+10);
System.out.println(i++);

4.2.3 自動裝箱、拆箱的內(nèi)幕

所謂自動裝箱與拆箱其實只是編譯器幫我們做了本來是我們需要自己做的事情。編譯器在編譯時會根據(jù)我們所寫的代碼來決定是否進行裝箱或拆箱。例如下面的代碼:

Integer number=100;

在Oracle的JDK中 ,編譯程序會自動將代碼展開為:

Integer localInteger=Integer.valueOf(100);

但自動裝拆箱其實是有問題的,例如:

Integer a=null;
int j=i;

這段代碼在編譯的時候是不會報錯的,因為null是一個特殊對象,它可以指定給任何聲明的對象,表示沒有引用到任何的內(nèi)存地址,但是一旦執(zhí)行編譯出的代碼,就會報錯,因為編譯后的代碼是這樣的:

Object localObject=null;
int i=localObject.intValue();

這里由于localObject對象被賦值為空,而代表沒有任何的內(nèi)存位置,所以也就不可能執(zhí)行第二句調(diào)用intValue()方法,此時計算機就會報錯NullPointerException(空指針異常,有的教科書或老師又把它叫做空點異常)。表示你想調(diào)用一段根本不在內(nèi)存里存在的代碼。
除了有這方面的bug之外,還有一些稀奇古怪的現(xiàn)象。比如下面的代碼:

/**
 *  Boxing.java
 * @author mouyo
 */
public class Boxing {
    public static void main(String[] args) {
        Integer i1=100;
        Integer i2=100;
        if(i1==i2){
            System.out.println("相等");
        }else{
            System.out.println("不相等");
        }
    }
}

這個代碼沒問題,結(jié)果是相等。


圖4.7 結(jié)果相等
可是,我們只要改一下,象下面這樣:

package cn.com.speakermore.ch04;

/**
 *  Boxing.java
 * @author mouyo
 */
public class Boxing {
    public static void main(String[] args) {
        Integer i1=200;
        Integer i2=200;
        if(i1==i2){
            System.out.println("相等");
        }else{
            System.out.println("不相等");
        }
    }
}

能看出來改了哪里么?對,只是把100換成了200,運行之后的結(jié)果卻變成了不相等。


圖4.8 200之后的結(jié)果是不相等。
為何是這樣的結(jié)果,這是因為在Integer的自動裝箱過程中,它使用了valueOf()方法,而valueOf()方法會建立一個緩存,緩存那些小于128的整數(shù)。這樣,當我們的值小于128時,值相同,對象就是相同的,但是一旦大于等于128,由于沒有緩存,雖然值是相同的,但對象就會不一樣。用==比較時,自然就得到了不相等的結(jié)果。
所以,結(jié)論還是前面已經(jīng)討論過的,別使用==或!=來比較兩個對象的值是否相同(因為引用型數(shù)據(jù)類型都是比較的地址),而要使用equals()方法。

4.3 數(shù)組對象

數(shù)組在Java中就是對象,所以前面介紹過的對象基本性質(zhì),在操作數(shù)組時也都要注意,如引用名的聲明、=指定的作用、==與!=的比較等。

4.3.1 數(shù)組基礎(chǔ)

數(shù)組基本上是用來收集數(shù)據(jù),具有下標(index)的數(shù)據(jù)結(jié)構(gòu),在Java中要聲明數(shù)組并初始值,可以如下:

int[] score={88,87,99,67,77,81,86,55,46,78};

這段代碼創(chuàng)建一個數(shù)組,因為使用int[]聲明,所以會在內(nèi)存中分配長度為10的int連續(xù)空間,每個空間依次存儲了大括號中的整數(shù),每個整數(shù)都用一個下標來標識,下標從0開始,所以10個長度的數(shù)組,下標最大就只到9。如果你使用了10或以上的數(shù)字作下標,就會拋出ArrayIndexOutOfBoundException(數(shù)組下標越界異常)。
數(shù)組使用下標來獲得每一個數(shù)據(jù),重點就是可以很方便的和循環(huán)結(jié)合,用很少的代碼對大量數(shù)據(jù)進行批量處理:

/**
 * Score.java
 * @author mouyo
 */
public class Score {
    public static void main(String[] args) {
        int[] score={88,87,99,67,77,81,86,55,46,78};
        for (int i = 0; i < score.length; i++) {
            System.out.println("學生分數(shù):"+score[i]);
        }
    }
}

在聲明的數(shù)組名稱旁加上[]并指定下標,就可以取得對應(yīng)值,上例從i為0-9,逐一取出值并顯示出來。


圖4.9 10個學生分數(shù)的顯示
在Java中數(shù)組是對象,而不是單純的數(shù)據(jù)集合,數(shù)組的length屬性可以取得數(shù)組長度。也就是數(shù)組的元素個數(shù)。
其實上面這個程序可以使用更簡單的方式來編寫,因為是順序取到數(shù)組中每一個值,所以我們可以使用增強式for循環(huán),這是從JDK5開始出現(xiàn)的更方便的for循環(huán),我基本是強烈推薦,在需要遍歷一個數(shù)組的時候都使用增強式for循環(huán)。

for (int score:scores ) {
   System.out.println("學生分數(shù):"+score);
}

這個程序片段會取得scores數(shù)組第一個元素,指定給score變量后執(zhí)行循環(huán)體,接著取得scores中第二個元素,指定給score變量后執(zhí)行循環(huán)體。依此類推,直到scores數(shù)組中所有元素都訪問完為止。將這段for循環(huán)片段取代Score類中的for循環(huán),執(zhí)行結(jié)果相同。實際上,增強式for循環(huán)也是Java提供的方便功能。
如果要給數(shù)組的某個元素賦值,也是要通過下標。例如:

scores[3]=86;
System.out.println(scores[3]);

上面這個程序片段將數(shù)組中第4個元素(因為下標從0開始,下標3就是第4個元素)指定86,所以會顯示86,所以會顯示86的結(jié)果。
一維數(shù)組使用一個下標存取數(shù)組元素,你也可以聲明二維數(shù)組,二維數(shù)組使用兩個下標存取數(shù)組元素。例如,聲明數(shù)組來儲存XY坐標位置要放的值。

/**
 * XY.java
 * @author mouyo
 */
public class XY {
    public static void main(String[] args) {
        int[][] cords={
            {1,2,3},
            {4,5,6}
        };//聲明二維數(shù)組并賦值初始值
        for(int x=0;x<cords.length;x++){//獲得有幾行
            for(int y=0;y<cords[x].length;y++){//獲得每行有幾個元素
                System.out.print(cords[x][y]+"  ");
            }
            System.out.println("");
        }
    }
}

要聲明二維數(shù)組,就是在類型關(guān)鍵詞旁加上[][]。初學者暫時將二維數(shù)組看作是一個表格會比較容易理解,由于有兩個維度,所以首先得通過cords.length得到有幾行,然后再使用cords[x].length獲得每行有幾個元素,之后再一個一個進行輸出。
二維數(shù)組有兩個下標,所以也要使用二重嵌套循環(huán)來完成取值遍歷的代碼,同樣由于這里對下標并沒有特別需要,所以也可以使用增強for循環(huán)來完成

       for(int[] row:cords){//獲得有幾行
            for(int value:row){//獲得每行幾個元素
                System.out.print(value+"  ");
            }
            System.out.println("");
        }

最后執(zhí)行結(jié)果相同。


圖4.10 二維數(shù)組執(zhí)行結(jié)果
提示:如果是三維數(shù)組,就是在類型關(guān)鍵字后使用三個[],如果是四維就是四個[]。依此類推。不過基本上是用不到如此復(fù)雜的維度,現(xiàn)代編程通常一維就足夠了,二維都基本上不用的。

4.3.2 操作數(shù)組對象

前面都是知道元素值來建立數(shù)組的例子,如果事先不知道元素值,只知道元素個數(shù),那可以使用new關(guān)鍵字指定長度的方式創(chuàng)建數(shù)組。例如:

int[] scores=new int[5];
數(shù)據(jù)類型 初始值
byte 0
short 0
int 0
long 0L
float 0.0F
double 0.0
char \u0000(即’’)
boolean false
null

在Java中只要看到new,就一定是創(chuàng)建對象(默然說話:計算機的實際操作是劃分一塊內(nèi)存空間供對象使用),這個語法其實已經(jīng)說明數(shù)組就是一個對象。使用new創(chuàng)建數(shù)組之后,數(shù)組中每個元素都會被初始化,如表4.1所示:
表4.1 數(shù)組元素初始值

數(shù)據(jù)類型 初始值
byte 0
short 0
int 0
long 0L
float 0.0F
double 0.0
char \u0000(即’’)
boolean false
null

如果默認值不符合你的需求,可以使用java.util.Arrays的fill()方法來設(shè)定新建數(shù)組的元素值。例如,每個學生的成績默認60分:

import java.util.Arrays;

/**
 * Score2.java
 * @author mouyong
 */
public class Score2 {
    public static void main(String[] args) {
        int[] scores=new int[10];
        System.out.println("默認初始值");
        for(int score:scores){
            System.out.print(score+"  ");
        }
        System.out.println("\n初始填充后");
        Arrays.fill(scores, 60);
         for(int score:scores){
            System.out.print(score+"  ");
        }
    }
}

執(zhí)行結(jié)果如下:


圖4.11學生分數(shù)數(shù)組的初始化值
數(shù)組既然是對象,再加上我們講過,對象是根據(jù)類而建立的實例,那么代表數(shù)組的類定義在哪里呢?答案是由JVM動態(tài)產(chǎn)生。你可以將int[]看作是類名稱,這樣,根據(jù)int[]聲明的變量就是一個引用變量,那么下面這段代碼會是什么結(jié)果?

         int[] scores1={88,66,48,99,12,45,55,76};
         int[] scores2=scores1;
         
         scores2[0]=99;
         System.out.println(scores1[0]);

因為數(shù)組是對象,而scores1與scores2是引用名稱,所以將scores1賦值給scores2的意思就是將scores1引用的對象內(nèi)存地址賦值給scores2,所以兩個變量指向了同一塊內(nèi)存,那么,當你通過scores2[0]對這個數(shù)組的第1個元素進行修改之后,scores1也能看到變化(默然說話:記住,因為它們的指向是同一個地址,再想想前面給大家的引用變量聲明的動畫)。
所以最后的輸出scores1[0]的值也是99。
再來看前面提過的二維數(shù)組:

int[][] cords=new int[2][3];

這個語法其實是建立了一個int[][]類型的對象,里面有2個int[]類型的對象。這2個一維的數(shù)組對象的長度都是3。初始值為0。


圖4.12二維數(shù)組的對象引用示意
對,從上圖中我們可以得到一個結(jié)論,其實Java的二維數(shù)組根本不是一個表格,所以Java完全可以建立一個不規(guī)則的數(shù)組。例如:

/**
 * IrregularArray.java
 * @author mouyo
 */
public class IrregularArray {
    public static void main(String[] args) {
        int[][] arr=new int[2][];//聲明arr對象為二維數(shù)組
        arr[0]=new int[]{1,2,3,4,5};//arr[0]是一個長度為5的一維數(shù)組
        arr[1]=new int[]{1,2,3};//arr[1]是一個長度為3的一維數(shù)組
        //從輸出可以看出來,第一個輸出了5個數(shù),第二個輸出了3個數(shù),并非一個表格
        for(int[] row:arr){
            for(int value:row){
                System.out.print(value+"  ");
            }
            System.out.println();
        }
        
    }
}

這個例子我們可以看到,在new一個二維數(shù)組時可以只寫最高維,而不用寫最后一個維度的數(shù)量。然后再給每個數(shù)組下標實例化不同的低維度數(shù)組。而具體的數(shù)值就放在最低維度指向的空間里。(默然說話:我驚訝的發(fā)現(xiàn),當寫了二維聲明之后,不能再使用直接初始化的語法了,也就是說,不能寫成arr[0]={1,2,3,4,5},必須寫成arr[0]=new int[]{1,2,3,4,5},可能是因為一開始聲明時沒有給出低維度的長度,所以必須重新對低維度劃分空間罷)。
當然,其實這個初始化的代碼也可以寫為:

        int[][] arr={
            {1,2,3,4,5},
            {1,2,3}
        };

以上都是基本類型創(chuàng)建的數(shù)組,那么引用類型創(chuàng)建的數(shù)組會是什么樣的情況呢?首先看看如何用new關(guān)鍵字建立Integer數(shù)組:

Integer[] scores=new Integer[3];

看上去不過就是把int換成了類Integer而已。那想想這個數(shù)組創(chuàng)建了幾個Integer對象呢?錯誤!不是3個,而是一個Integer對象都沒有創(chuàng)建?;仡^看表4.1,對象類型的默認值是null。這里只創(chuàng)建出一個Integer[]對象,它可以容納3個Integer對象,但是因為對象型的默認初始化值為null,所以現(xiàn)在這三個對象都還沒有產(chǎn)生。我們必須在給它們的每個下標都賦值時,才會有Integer對象產(chǎn)生。

/**
 * IntegerArray.java
 * @author mouyong
 */
public class IntegerArray {
    public static void main(String[] args) {
        Integer[] scores=new Integer[3];
        System.out.println("僅實例化了數(shù)組之后,數(shù)組中的初始化值:");
        for(Integer score:scores){
            System.out.println(score);
        }
        scores[0]=new Integer(98);
        scores[1]=new Integer(99);
        scores[2]=new Integer(87);
        
        System.out.println("實例化每個元素之后,數(shù)組中的元素值:");
         for(Integer score:scores){
            System.out.println(score);
        }
        
    }
}

代碼的執(zhí)行結(jié)果如下:


4.13對象類型的數(shù)組初始化
所以每次講對象類型數(shù)組,我總是說,對象類型數(shù)組需要new兩次,一次是new出對象數(shù)組,另一次是new出一系列放在數(shù)組中的對象。
上面的代碼之所以這樣寫,主要是為了突出對象的特點,其實JDK5.0之后有了自動裝箱和拆箱,所以數(shù)組元素賦值可以寫成這樣:

        scores[0]=98;
        scores[1]=99;
        scores[2]=87;

對象類型其實也可以使用大括號進行初始化,只是寫得要長些:

Integer[] scores={new Integer(98),new Integer(99),new Integer(87)};

同樣,上面的寫法也是為了強調(diào)對象型需要先new,JDK5.0之后有了自動裝箱和拆箱,所以也可以寫成這樣:

Integer[] scores={99,98,87};

4.3.3 數(shù)組復(fù)制

在知道了數(shù)組其實是一種對象,你就要知道,下面的代碼不是復(fù)制:

int[] scores1={88,66,48,99,12,45,55,76};
int[] scores2=scores1;

復(fù)制應(yīng)該是出現(xiàn)兩個內(nèi)容相同的對象,但這只是讓兩個變量指向了同一個對象,也就是對象只有一個,并沒有兩個。所以真正的復(fù)制應(yīng)該是這樣的。

int[] scores1={88,66,48,99,12,45,55,76};
int[] scores2=new int[scores1.length];
for(int i=0;i<scores1.length;i++){
    scores2[i]=scores1[i];
}

這是自己使用循環(huán)來完成每一個值的復(fù)制,其實可以使用System.arraycopy()方法來直接完成這個過程,比我們用循環(huán)來得快:

int[] scores1={88,66,48,99,12,45,55,76};
int[] scores2=new int[scores1.length];
System.arraycopy(scores1,0,scores2,0,scores1.length);

System.arraycopy()有五個參數(shù),分別是源數(shù)組,源數(shù)組開始下標,目標數(shù)組,目標數(shù)組開始下標,復(fù)制長度。如果使用JDK6以上,還有個更方便的Arrays.copyOf()方法,你不用另行建立數(shù)組,Arrays.copyOf()會幫你創(chuàng)建:

import java.util.Arrays;

/**
 * CopyArray.java
 * @author mouyong
 */
public class CopyArray {
    public static void main(String[] args) {
        int[] scores1={88,81,75,68,79,95,93};
        int[] scores2=Arrays.copyOf(scores1, scores1.length);
        System.out.println("scores2數(shù)組的元素:");
        for(int score:scores2){
            System.out.print(score+"  ");
        }
        System.out.println("");
        scores2[0]=99;
        System.out.println("修改了scores2第1個元素之后,scores1的元素仍然不變");
        for(int score:scores1){
            System.out.print(score+"  ");
        }
    }
}

執(zhí)行結(jié)果如下所示:


圖4.14Arrays.copyOf()進行數(shù)組復(fù)制無需自行創(chuàng)建數(shù)組
Java中,數(shù)組一旦創(chuàng)建,長度就是固定的,如果長度不夠,就只能創(chuàng)建新的數(shù)組,將原來的內(nèi)容復(fù)制到新數(shù)組中。如:

int[] scores1={88,81,75,68,79,95,93};
int[] scores2=Arrays.copyOf(scores1, scores1.length*2);
System.out.println("scores2數(shù)組的元素:");
for(int score:scores2){
    System.out.print(score+"  ");
}

Arrays.copyOf()的第二個參數(shù)就是指定新數(shù)組的長度。上面程序讓新創(chuàng)建的數(shù)組長度是原來數(shù)組長度的2倍,輸出時會看到增加部分元素的值均為默認值0。
無論是System.arraycopy()還是Arrays.copyOf(),用在類類型聲明的數(shù)值時,都是執(zhí)行淺層復(fù)制(默然說話:也就是說,如果你的數(shù)組元素是對象,那么復(fù)制一個新的數(shù)組時,新數(shù)組還在引用原數(shù)組的對象,并不會把原數(shù)組的對象進行復(fù)制!)。如果真的要連同對象一同復(fù)制,你得自行操作,因為基本上只有自己才知道,每個對象復(fù)制時,有哪些屬性必須復(fù)制。

4.4 字符串對象

在Java中,字符串本質(zhì)是打包字符數(shù)組的對象。它同樣也有屬性和方法。不過在Java中基于效率的考慮,給予字符串某些特別且必須注意的性質(zhì)。

4.4.1 字符串基礎(chǔ)

由字符組成的文字符號稱為字符串。例如,“Hello”字符串就是由’H’、’e’、’l’、’l’、’o’、五個字符組成,在某些程序語言中,字符串是以字符數(shù)組的方式存在,然而在Java中,字符串是java.lang.String實例,用來打包字符數(shù)組。所有用””包括的一串字符都是字符串。

        String name="sophie";//創(chuàng)建String對象
        System.out.println(name);//輸出sophie
        System.out.println(name.length());//顯示長度為6
        System.out.println(name.charAt(0));//顯示第1個字符s
        System.out.println(name.toUpperCase());//顯示全大寫SOPHIE

因為字符串在Java中是對象,所以它有很多的方法,上面的示例給大家看到了幾個很常用的字符串方法,length()可以獲得字符串長度;charAt()可以獲得指定下標的字符,toUpperCase()可以把所有小寫字母轉(zhuǎn)成大寫字母。
如果已有一個char[]數(shù)組,也可以使用new來創(chuàng)建String對象。如:

        char[] ch={'H','e','l','l','o'};
        String str=new String(ch);

也可以使用toCharArray()方法,將字符串以char[]的形式返回。

char[] ch2=str.toCharArray()

Java中可以使用+運算來連接字符串。前面我們一直在用。
為了認識數(shù)組與字符串,可以看看程序入口main()方法的String[] args參數(shù),在啟動JVM并指定執(zhí)行類時,可以一并指定命令行參數(shù)。

/**
 * Avarage.java
 * @author mouyong
 */
public class Avarage {
    public static void main(String[] args) {
        long sum=0;
        for(String arg:args){
            sum+=Long.parseLong(arg);//把字符串轉(zhuǎn)化為長整型
        }
        System.out.println("平均:"+(float)sum/args.length);
    }
}

在NetBeans中如果要提供命令行參數(shù),可以這樣進行操作。

  • (1)在項目上右擊,在彈出的快捷菜單中選擇“屬性”,打開“項目屬性”對話框,在左邊的“類別”列表中選擇“運行”。


圖4.15配置命令行參數(shù)

  • (2)單擊右側(cè)上方“配置”列表框旁邊的“新建…”按鈕,打開“創(chuàng)建新的配置”對話框,在“類別”文本框中填入配置的名稱,我填的是“命令行參數(shù)”。


圖4.16創(chuàng)建新的配置

  • (3)單擊“主類”文本框右側(cè)的“瀏覽…”按鈕,從中選擇你寫的示例。
  • (4)在“參數(shù)”文本框中手工輸入?yún)?shù)1 2 3 4,注意,每個數(shù)字之間要用空格分開,不然JVM會認為你只輸入了一個參數(shù)。
    這樣設(shè)定之后,點擊工具欄上的“運行”按鈕,就會按你所設(shè)置的配置調(diào)用程序了。

4.4.2 字符串特性

各程序語言會有細微、重要且不容忽視的特性。在Java的字符串來說,就有一些必須注意的特性:
? 字符串常量和字符串池。
? “不可變”(Immutable)的字符串。
*1.字符串常量與字符串池
來看下面的片段:

String name1=new String("Hello");
String name2=new String("Hello");
System.out.println(name1==name2);

希望現(xiàn)在的你會很自信的回答:結(jié)果是false。是的,結(jié)果的確是false。因為name1和name2引用了不同的對象,盡管它們的內(nèi)容一樣,但內(nèi)存地址不同,所以==的比較結(jié)果就是false。


圖4.17片段執(zhí)行結(jié)果

再看下面的片段:

String name1="Hello";
String name2="Hello";
System.out.println(name1==name2);

這個代碼和上面似乎沒啥區(qū)別嘛,只不過沒有顯式new而已。但是如果你運行一下,你就會驚訝的發(fā)現(xiàn):結(jié)果是true!!!


圖4.18片段執(zhí)行結(jié)果
難道這里使用了不同的規(guī)則?答案是:沒有,和前面的顯式new的規(guī)則是一致的!所以正確的推論是:name1和name2都指向了同一個對象!
在Java中為了效率的考慮,以””包括的字符串,只要內(nèi)容相同(序列、大小寫相同),無論在程序中出現(xiàn)幾次,JVM都只會建立一個String對象,并在字符串池中維護。在上面這個程序片段的第一行,JVM會建立一個String實例放在字符串池中,并把地址賦值給name1,而第二行則是讓name2直接引用了字符串池中的同一個String對象。
用””寫下的字符串稱為字符串常量(String Literal),既然你用”Hello”寫死了字符串內(nèi)容,基于節(jié)省內(nèi)存的考慮,自然就不用為這些字符串常量分別建立String實例。
前面一直強調(diào),如果想比較對象的內(nèi)容是否相同,不要使用==,要使用equals()。這個同樣適用String。
2.不可變動字符串
在Java中,字符串對象一旦建立,就無法更改對象中任何內(nèi)容,對象沒有提供任何方法可以更改字符串內(nèi)容。那么+連字符串是怎么做到的呢?

String name1=”Java”;
String name2=name1+”World”;
System.out.println(name2);

上面這個程序片段會顯示JavaWorld,由于無法更改字符串對象內(nèi)容,所以絕不是在name1引用的字符串對象之后附加World。而創(chuàng)建了java.lang.StringBuilder對象,使用其append()方法來進行+左右兩邊字符串附加,最后再轉(zhuǎn)換為toString()返回。
簡單地說,使用+連接字符串會產(chǎn)生新的String對象,這并不是告訴你,不要使用+連接字符串,畢竟這種做法非常方便。但是不要將+用在重復(fù)性的連接場合,比如循環(huán)或遞歸時。這會因為頻繁產(chǎn)生新對象,造成效能上的負擔。
比如,如果我們想輸出一個從1加到100的算式(注意,不是1到100相加的結(jié)果,而是顯示描述1加到100的這個算式:1+2+3+4+5……+100),你會怎么寫?

也許是這樣寫?
for(int i=1;i<100;i++){
    System.out.print(i+"+");
}

System.out.println(100);

這樣寫代碼很簡潔,但是一個一個循環(huán)輸出效能是很低的。有沒有更好的辦法?

String str="";
for(int i=1;i<100;i++){
    str+=i+"+";
}
System.out.println(str+100);

只有一個輸出語句,效能大大提高!但是使用了連接字符串,會造成頻繁產(chǎn)生新對象的問題。象上面這樣的情況下,強烈建議使用StringBuilder!

/**
 * OneTo100.java
 * @author mouyong
 */
public class OneTo100 {
    public static void main(String[] args) {
        StringBuilder builder=new StringBuilder();
        for(int i=1;i<100;i++){
            builder.append(i).append("+");
        }
        System.out.println(builder.append(100).toString());
    }
}

StringBuilder每次append()調(diào)用之后,都會返回原StringBuilder對象,所以我們可以連接調(diào)用append()方法。這個程序只產(chǎn)生一個StringBuilder對象,只進行一次輸出,無論是從計算效能還是內(nèi)存使用效能上來說,都是非常棒的!

提示:java.lang.StringBuilder是JDK5之后新增的類,在該版本之前,我們有java.lang.StringBuffer,StringBuilder和StringBuffer其實是一樣的。但是StringBuilder的效率更高,因為他不考慮多線程情況下的同步問題。所以如果你的程序會涉及到多線程的情況,可以直接改用StringBuffer

4.4.3 字符串編碼

你我都是中國人(默然說話:對的!下面要談?wù)摰膯栴}與中文有關(guān),如果你就不使用中國字,那可以略過),在Java中你必然要處理中文,所以你要了解Java如何處理中文。
要知道,java源代碼文檔在NetBeans中是UTF-8編碼。在windows簡體中文版下默認是GB2312。在Eclipse中情況又會不同,Eclipse會自動讓java源代碼文件的編碼是所在操作系統(tǒng)的默認編碼。所以,如果你的Eclipse在Windows簡體中文下就是GB2312,如果是在Mac下,就會是UTF-8。
如果你使用的是GB2312編碼,在編譯器編譯你的代碼時,會自動把所有的中文都轉(zhuǎn)為Unicode編碼。比如”哈啰”就會變成”\u54C8\u56C9”。這個”\uxxxx”就是Unicode的編碼形式。
那么編譯器是如何知道要將中國字轉(zhuǎn)成哪種Unicode編碼呢?當你使用javac指令沒有指定-encodding參數(shù)時,會使用操作系統(tǒng)默認編碼,如果你的源代碼文件采用了不同的編碼形式,則必須指定-encoding參數(shù)。
提示:在Windows下不要使用純文本編輯器轉(zhuǎn)存UTF-8文件來編寫源代碼,因為記事本會在文檔頭加BOM,這樣會造成Java編譯器無法編譯。建議使用NotePad++。
IDE也是允許你自定義編碼的,如果是NetBeans,可以在項目上右擊,在彈出的快捷菜單中選擇“屬性”,打開“項目屬性”對話框,在左邊“類別”列表中選擇“源”。然后在右側(cè)最下方的“編碼”選擇框中選擇代碼的編碼。

4.5 查詢Java API文件

書上提到的各種Java類是如何知道應(yīng)該調(diào)用什么方法呢?是通過查詢Java API文檔知道的。
http://docs.oracle.com/javase/8/docs/api/
這個鏈接就是Java API文檔,里面包括了所有Java類的方法屬性及使用介紹、特點介紹。
不過在平時如果知道一個Java類,想知道怎么用,我更習慣用下面這個鏈接。
http://www.baidu.com/
以前喜歡用谷歌,現(xiàn)在用不了,只好將就著用了。

4.6 重點復(fù)習

要產(chǎn)生對象必須先定義類,類是對象的模板,對象是類的實例。定義類使用class關(guān)鍵字,實例化對象使用new關(guān)鍵字。
想在建立對象時,一并進行某個初始流程,可以定義構(gòu)造函數(shù),構(gòu)造函數(shù)是與類名同名的方法,它不能寫返回值。參數(shù)根據(jù)需要指定,也可以沒有參數(shù)。
Java遵守IEEE 754浮點運算規(guī)范,使用分數(shù)與指數(shù)來表示浮點數(shù)。如果要求精確度,那就要小心使用浮點數(shù)。不要使用==直接比較浮點數(shù)運算結(jié)果。
要讓基本類型象對象一樣的操作,可以使用Long、Integer、Double、Float等類來打包基本類型。JDK5之后提供了自動裝箱和拆箱,媽媽再也不擔心我不會裝箱和拆箱了。
數(shù)組在Java中就是對象,下標從0開始,下標超出范圍會拋異常。
無論是System.arraycopy()還是Arrays.copyOf(),用在類的數(shù)組時,都是執(zhí)行淺層復(fù)制。
字符串也是對象。
字符串對象一旦建立,無法更改對象內(nèi)容。不要將+用在重復(fù)性的連接場合。
使用javac指令沒有指定-encoding參數(shù)時,會使用操作系統(tǒng)默認編碼。

4.7 課后練習

4.7.1 選擇題

  1. 如果有以下的程序代碼:
int x=100;
int y=100;
Integer wx=x;
Integer wy=y;
System.out.println(x==y);
System.out.println(wx==wy);

在JDK 5以上的環(huán)境編譯與執(zhí)行,則顯示結(jié)果是()
A.true、true
B.true、false
C.false、true
D.編譯失敗

  1. 如果有以下的程序代碼:
int x=200;
int y=200;
Integer wx=x;
Integer wy=y;
System.out.println(x==y);
System.out.println(wx==wy);
在JDK 5以上的環(huán)境編譯與執(zhí)行,則顯示結(jié)果是()
A.true、true 
B.true、false 
C.false、true    
D.編譯失敗
  1. 如果有以下的程序代碼:
int x=300;
int y=300;
Integer wx=x;
Integer wy=y;
System.out.println(wx.equals(x));
System.out.println(wy.equals(y));

在JDK 5以上的環(huán)境編譯與執(zhí)行,則顯示結(jié)果是()
A.true、true
B.true、false
C.false、true
D.編譯失敗

  1. 如果有以下的程序代碼:
int[] arr1={1,2,3};
int[] arr2=arr1;
arr2[1]=20;
System.out.println(arr1[1]);

在JDK 5以上的環(huán)境編譯與執(zhí)行,則顯示結(jié)果是()
A.執(zhí)行時顯示2
B.執(zhí)行時顯示20
C.執(zhí)行時出現(xiàn)ArrayIndexOfBuondException
D.編譯失敗

  1. 如果有以下的程序代碼:
int[] arr1={1,2,3};
int[] arr2=new int[arr1.length]
arr2=arr1;
for(int value:arr2){
    System.out.print(value);
}

在JDK 5以上的環(huán)境編譯與執(zhí)行,則顯示結(jié)果是()
A.執(zhí)行時顯示123
B.執(zhí)行時顯示12300
C.執(zhí)行時出現(xiàn)ArrayIndexOfBuondException
D.編譯失敗

  1. 如果有以下的程序代碼:
String[] strs=new String[5]

以下描述正確的是()
A.產(chǎn)生5個String對象
B.產(chǎn)生1個String對象
C.產(chǎn)生0個String對象
D.編譯失敗

  1. 如果有以下的程序代碼:
    String[] strs={“java”, “java”, “java”, “java”, “java”}
    以下描述正確的是()
    A.產(chǎn)生5個String對象 B.產(chǎn)生1個String對象
    C.產(chǎn)生0個String對象 D.編譯失敗

  2. 如果有以下的程序代碼:

String[][] strs=new String[2][5]

以下描述正確的是()
A.產(chǎn)生10個String對象
B.產(chǎn)生2個String對象
C.產(chǎn)生0個String對象
D.編譯失敗

  1. 如果有以下的程序代碼:
String[][] strs={
{“java”, “java”, “java”},
{“java”, “java”, “java”, “java”}
};
System.out.println(strs.length);
System.out.println(strs[0].length);
System.out.println(strs[1].length);

以下描述正確的是()
A.顯示2、3、4
B.顯示2、0、1
C.顯示1、2、3
D.編譯失敗

  1. 如果有以下的程序代碼:
String[][] strs={
{“java”, “java”, “java”},
{“java”, “java”, “java”, “java”}
};
for(row:strs){
for(value:row){
    …
}
}

空白處應(yīng)該分別填上()
A.String、String
B.String、String[]
C.String[]、String
D.String[]、String[]

4.7.2 操作題

1.Fibonacci為13 歐洲數(shù)學家,在他的著作中提過,若一只兔子每月生一只小兔子,一個月后小兔子也開始生產(chǎn)。起初只有一只小兔子,一個月后有兩只兔子,兩個月后有三只兔子,三個月后有五只 …,也就是每個月兔子總數(shù)會是1、1、2、3、5、8、13、21、34、89,這就是費氏數(shù)列,可用公式定義如下:
fn=fn-1+fn-2 if n>1
fn=n if n=0,1
編寫程序,可以讓用戶輸入想計算的費氏數(shù)列的個數(shù),由程序全部顯示出來。
2.請編寫一個簡單的洗 程序,可以在文本模式下顯示洗牌結(jié)果。
3.下面是一個數(shù)組,請使用程序使其中元素排序為由小到大:
int[] number={70,80,31,37,10,1,48,60,33,80};
4.下面是一個排序后的數(shù)組,請編寫程序可讓用戶在數(shù)組中尋找指定數(shù)字,找到就顯示索引值,找不到就顯示-1:
int number={1,10,31,33,37,48,60,70,80};

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

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,674評論 0 4
  • 醫(yī)院是最無情的地方也是最有情的地方。在我還沒有踏上學醫(yī)之旅的時候,我一直很害怕到醫(yī)院去,因為自己小時候就...
    小爬姑娘閱讀 314評論 0 0
  • iOS逆向入門實踐 — 逆向微信,偽裝定位(一) iOS 逆向開發(fā)小試-釘釘篇 粉絲福利,Pokemon Go 鎖...
    愛我你就抱抱我閱讀 192評論 0 0
  • 公司今年事情特別多,無論是外面來的,還是內(nèi)部的,各種風波漩渦,處在這中心,深深地感覺人生無常。 就在上個星期二,我...
    黑土錢閱讀 131評論 0 2

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