Java 陣列、Java 日期時間、Java 正規表示式、Java 方法

Bonnie*~*發表於2020-01-07

Java 陣列

陣列對於每一門程式語言來說都是重要的資料結構之一,當然不同語言對陣列的實現及處理也不盡相同。

Java 語言中提供的陣列是用來儲存固定大小的同型別元素。

你可以宣告一個陣列變數,如 numbers[100] 來代替直接宣告 100 個獨立變數 number0,number1,....,number99。

本教程將為大家介紹 Java 陣列的宣告、建立和初始化,並給出其對應的程式碼。


宣告陣列變數

首先必須宣告陣列變數,才能在程式中使用陣列。下面是宣告陣列變數的語法:

dataType[] arrayRefVar; // 首選的方法   或

dataType arrayRefVar[]; // 效果相同,但不是首選方法

注意: 建議使用 dataType[] arrayRefVar 的宣告風格宣告陣列變數。 dataType arrayRefVar[] 風格是來自 C/C++ 語言 ,在Java中採用是為了讓 C/C++ 程式設計師能夠快速理解java語言。

例項

下面是這兩種語法的程式碼示例:

double[] myList; // 首選的方法   或

double myList[]; // 效果相同,但不是首選方法

建立陣列

Java語言使用new操作符來建立陣列,語法如下:

arrayRefVar = new dataType[arraySize];

上面的語法語句做了兩件事:

  • 一、使用 dataType[arraySize] 建立了一個陣列。
  • 二、把新建立的陣列的引用賦值給變數 arrayRefVar。

陣列變數的宣告,和建立陣列可以用一條語句完成,如下所示:

dataType[] arrayRefVar = new dataType[arraySize];

 另外,你還可以使用如下的方式建立陣列。

dataType[] arrayRefVar = {value0, value1, ..., valuek};

 陣列的元素是通過索引訪問的。陣列索引從 0 開始,所以索引值從 0 到 arrayRefVar.length-1。

例項

下面的語句首先宣告瞭一個陣列變數 myList,接著建立了一個包含 10 個 double 型別元素的陣列,並且把它的引用賦值給 myList 變數。

public class TestArray {
   public static void main(String[] args) {
      // 陣列大小
      int size = 10;
      // 定義陣列
      double[] myList = new double[size];
      myList[0] = 5.6;
      myList[1] = 4.5;
      myList[2] = 3.3;
      myList[3] = 13.2;
      myList[4] = 4.0;
      myList[5] = 34.33;
      myList[6] = 34.0;
      myList[7] = 45.45;
      myList[8] = 99.993;
      myList[9] = 11123;
      // 計算所有元素的總和
      double total = 0;
      for (int i = 0; i < size; i++) {
         total += myList[i];
      }
      System.out.println("總和為: " + total);
   }
}

以上例項輸出結果為:

總和為: 11367.373

下面的圖片描繪了陣列 myList。這裡 myList 陣列裡有 10 個 double 元素,它的下標從 0 到 9。

java陣列結構說明

 

處理陣列

陣列的元素型別和陣列的大小都是確定的,所以當處理陣列元素時候,我們通常使用基本迴圈或者 For-Each 迴圈。

示例

該例項完整地展示瞭如何建立、初始化和操縱陣列:

public class TestArray {
   public static void main(String[] args) {
      double[] myList = {1.9, 2.9, 3.4, 3.5};
 
      // 列印所有陣列元素
      for (int i = 0; i < myList.length; i++) {
         System.out.println(myList[i] + " ");
      }
      // 計算所有元素的總和
      double total = 0;
      for (int i = 0; i < myList.length; i++) {
         total += myList[i];
      }
      System.out.println("Total is " + total);
      // 查詢最大元素
      double max = myList[0];
      for (int i = 1; i < myList.length; i++) {
         if (myList[i] > max) max = myList[i];
      }
      System.out.println("Max is " + max);
   }
}

以上例項編譯執行結果如下:

1.9
2.9
3.4
3.5
Total is 11.7
Max is 3.5

For-Each 迴圈

JDK 1.5 引進了一種新的迴圈型別,被稱為 For-Each 迴圈或者加強型迴圈,它能在不使用下標的情況下遍歷陣列。

語法格式如下:

for(type element: array)
{
    System.out.println(element);
}

例項

該例項用來顯示陣列 myList 中的所有元素:

public class TestArray {
   public static void main(String[] args) {
      double[] myList = {1.9, 2.9, 3.4, 3.5};
 
      // 列印所有陣列元素
      for (double element: myList) {
         System.out.println(element);
      }
   }
}

以上例項編譯執行結果如下:

1.9
2.9
3.4
3.5

陣列作為函式的引數

陣列可以作為引數傳遞給方法。

例如,下面的例子就是一個列印 int 陣列中元素的方法:

public static void printArray(int[] array) {
  for (int i = 0; i < array.length; i++) {
    System.out.print(array[i] + " ");
  }
}

下面例子呼叫 printArray 方法列印出 3,1,2,6,4 和 2:

printArray(new int[]{3, 1, 2, 6, 4, 2});

陣列作為函式的返回值

public static int[] reverse(int[] list) {
  int[] result = new int[list.length];
 
  for (int i = 0, j = result.length - 1; i < list.length; i++, j--) {
    result[j] = list[i];
  }
  return result;
}

以上例項中 result 陣列作為函式的返回值。

多維陣列

多維陣列可以看成是陣列的陣列,比如二維陣列就是一個特殊的一維陣列,其每一個元素都是一個一維陣列,例如:

String str[][] = new String[3][4];

多維陣列的動態初始化(以二維陣列為例)

1. 直接為每一維分配空間,格式如下:

type[][] typeName = new type[typeLength1][typeLength2];

type 可以為基本資料型別和複合資料型別,arraylength1 和 arraylength2 必須為正整數,arraylength1 為行數,arraylength2 為列數。

例如:

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

解析:

二維陣列 a 可以看成一個兩行三列的陣列。

2. 從最高維開始,分別為每一維分配空間,例如:

String s[][] = new String[2][];
s[0] = new String[2];
s[1] = new String[3];
s[0][0] = new String("Good");
s[0][1] = new String("Luck");
s[1][0] = new String("to");
s[1][1] = new String("you");
s[1][2] = new String("!");

解析:

s[0]=new String[2] 和 s[1]=new String[3] 是為最高維分配引用空間,也就是為最高維限制其能儲存資料的最長的長度,然後再為其每個陣列元素單獨分配空間 s0=new String("Good") 等操作。

多維陣列的引用(以二維陣列為例)

對二維陣列中的每個元素,引用方式為 arrayName[index1][index2],例如:

num[1][0];

Arrays 類

java.util.Arrays 類能方便地運算元組,它提供的所有方法都是靜態的。

具有以下功能:

  • 給陣列賦值:通過 fill 方法。
  • 對陣列排序:通過 sort 方法,按升序。
  • 比較陣列:通過 equals 方法比較陣列中元素值是否相等。
  • 查詢陣列元素:通過 binarySearch 方法能對排序好的陣列進行二分查詢法操作。

具體說明請檢視下錶:

序號方法和說明
1public static int binarySearch(Object[] a, Object key)
用二分查詢演算法在給定陣列中搜尋給定值的物件(Byte,Int,double等)。陣列在呼叫前必須排序好的。如果查詢值包含在陣列中,則返回搜尋鍵的索引;否則返回 (-(插入點) - 1)。
2public static boolean equals(long[] a, long[] a2)
如果兩個指定的 long 型陣列彼此相等,則返回 true。如果兩個陣列包含相同數量的元素,並且兩個陣列中的所有相應元素對都是相等的,則認為這兩個陣列是相等的。換句話說,如果兩個陣列以相同順序包含相同的元素,則兩個陣列是相等的。同樣的方法適用於所有的其他基本資料型別(Byte,short,Int等)。
3public static void fill(int[] a, int val)
將指定的 int 值分配給指定 int 型陣列指定範圍中的每個元素。同樣的方法適用於所有的其他基本資料型別(Byte,short,Int等)。
4public static void sort(Object[] a)
對指定物件陣列根據其元素的自然順序進行升序排列。同樣的方法適用於所有的其他基本資料型別(Byte,short,Int等)。

Java 日期時間

java.util 包提供了 Date 類來封裝當前的日期和時間。 Date 類提供兩個建構函式來例項化 Date 物件。

第一個建構函式使用當前日期和時間來初始化物件。

Date( )

第二個建構函式接收一個引數,該引數是從1970年1月1日起的毫秒數

Date(long millisec)

Date物件建立以後,可以呼叫下面的方法。

序號方法和描述
1boolean after(Date date)
若當呼叫此方法的Date物件在指定日期之後返回true,否則返回false。
2boolean before(Date date)
若當呼叫此方法的Date物件在指定日期之前返回true,否則返回false。
3Object clone( )
返回此物件的副本。
4int compareTo(Date date)
比較當呼叫此方法的Date物件和指定日期。兩者相等時候返回0。呼叫物件在指定日期之前則返回負數。呼叫物件在指定日期之後則返回正數。
5int compareTo(Object obj)
若obj是Date型別則操作等同於compareTo(Date) 。否則它丟擲ClassCastException。
6boolean equals(Object date)
當呼叫此方法的Date物件和指定日期相等時候返回true,否則返回false。
7long getTime( )
返回自 1970 年 1 月 1 日 00:00:00 GMT 以來此 Date 物件表示的毫秒數。
8int hashCode( )
 返回此物件的雜湊碼值。
9void setTime(long time)
 
用自1970年1月1日00:00:00 GMT以後time毫秒數設定時間和日期。
10String toString( )
把此 Date 物件轉換為以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一週中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。

獲取當前日期時間

Java中獲取當前日期和時間很簡單,使用 Date 物件的 toString() 方法來列印當前日期和時間,如下所示:

例項:

import java.util.Date;
  
public class DateDemo {
   public static void main(String args[]) {
       // 初始化 Date 物件
       Date date = new Date();
        
       // 使用 toString() 函式顯示日期時間
       System.out.println(date.toString());
   }
}

以上例項編譯執行結果如下:

Mon May 04 09:51:52 CDT 2013

日期比較

Java使用以下三種方法來比較兩個日期:

  • 使用 getTime() 方法獲取兩個日期(自1970年1月1日經歷的毫秒數值),然後比較這兩個值。
  • 使用方法 before(),after() 和 equals()。例如,一個月的12號比18號早,則 new Date(99, 2, 12).before(new Date (99, 2, 18)) 返回true。
  • 使用 compareTo() 方法,它是由 Comparable 介面定義的,Date 類實現了這個介面。

使用 SimpleDateFormat 格式化日期

SimpleDateFormat 是一個以語言環境敏感的方式來格式化和分析日期的類。SimpleDateFormat 允許你選擇任何使用者自定義日期時間格式來執行。例如:

import  java.util.*;
import java.text.*;
 
public class DateDemo {
   public static void main(String args[]) {
 
      Date dNow = new Date( );
      SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
 
      System.out.println("當前時間為: " + ft.format(dNow));
   }
}
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");

這一行程式碼確立了轉換的格式,其中 yyyy 是完整的公元年,MM 是月份,dd 是日期,HH:mm:ss 是時、分、秒。

注意:有的格式大寫,有的格式小寫,例如 MM 是月份,mm 是分;HH 是 24 小時制,而 hh 是 12 小時制。

以上例項編譯執行結果如下:

當前時間為: 2018-09-06 10:16:34

日期和時間的格式化編碼

時間模式字串用來指定時間格式。在此模式中,所有的 ASCII 字母被保留為模式字母,定義如下:

字母描述示例
G紀元標記AD
y四位年份2001
M月份July or 07
d一個月的日期10
h A.M./P.M. (1~12)格式小時12
H一天中的小時 (0~23)22
m分鐘數30
s秒數55
S毫秒數234
E星期幾Tuesday
D一年中的日子360
F一個月中第幾周的周幾2 (second Wed. in July)
w一年中第幾周40
W一個月中第幾周1
aA.M./P.M. 標記PM
k一天中的小時(1~24)24
K A.M./P.M. (0~11)格式小時10
z時區Eastern Standard Time
'文字定界符Delimiter
"單引號`

使用printf格式化日期

printf 方法可以很輕鬆地格式化時間和日期。使用兩個字母格式,它以 %t 開頭並且以下面表格中的一個字母結尾。

轉  換  符

說    明

示    例

c

包括全部日期和時間資訊

星期六 十月 27 14:21:20 CST 2007

F

"年-月-日"格式

2007-10-27

D

"月/日/年"格式

10/27/07

r

"HH:MM:SS PM"格式(12時制)

02:25:51 下午

T

"HH:MM:SS"格式(24時制)

14:28:16

R

"HH:MM"格式(24時制)

14:28

 例項:

import java.util.Date;
 
public class DateDemo {
 
  public static void main(String args[]) {
     // 初始化 Date 物件
     Date date = new Date();
 
     //c的使用  
    System.out.printf("全部日期和時間資訊:%tc%n",date);          
    //f的使用  
    System.out.printf("年-月-日格式:%tF%n",date);  
    //d的使用  
    System.out.printf("月/日/年格式:%tD%n",date);  
    //r的使用  
    System.out.printf("HH:MM:SS PM格式(12時制):%tr%n",date);  
    //t的使用  
    System.out.printf("HH:MM:SS格式(24時制):%tT%n",date);  
    //R的使用  
    System.out.printf("HH:MM格式(24時制):%tR",date);  
  }
}

以上例項編譯執行結果如下:

全部日期和時間資訊:星期一 九月 10 10:43:36 CST 2012  
年-月-日格式:2012-09-10  
月/日/年格式:09/10/12  
HH:MM:SS PM格式(12時制):10:43:36 上午  
HH:MM:SS格式(24時制):10:43:36  
HH:MM格式(24時制):10:43  

如果你需要重複提供日期,那麼利用這種方式來格式化它的每一部分就有點複雜了。因此,可以利用一個格式化字串指出要被格式化的引數的索引。

索引必須緊跟在%後面,而且必須以$結束。例如:

import java.util.Date;
  
public class DateDemo {
 
   public static void main(String args[]) {
       // 初始化 Date 物件
       Date date = new Date();
        
       // 使用toString()顯示日期和時間
       System.out.printf("%1$s %2$tB %2$td, %2$tY", 
                         "Due date:", date);
   }
}

以上例項編譯執行結果如下:

Due date: February 09, 2014

 或者,你可以使用 < 標誌。它表明先前被格式化的引數要被再次使用。例如:

import java.util.Date;
  
public class DateDemo {
 
   public static void main(String args[]) {
       // 初始化 Date 物件
       Date date = new Date();
        
       // 顯示格式化時間
       System.out.printf("%s %tB %<te, %<tY", 
                         "Due date:", date);
   }
}

以上例項編譯執行結果如下:

Due date: February 09, 2014

 定義日期格式的轉換符可以使日期通過指定的轉換符生成新字串。這些日期轉換符如下所示:

import java.util.*;
  
public class DateDemo {
   public static void main(String args[]) {
       Date date=new Date();                                      
        //b的使用,月份簡稱  
        String str=String.format(Locale.US,"英文月份簡稱:%tb",date);       
        System.out.println(str);                                                                              
        System.out.printf("本地月份簡稱:%tb%n",date);  
        //B的使用,月份全稱  
        str=String.format(Locale.US,"英文月份全稱:%tB",date);  
        System.out.println(str);  
        System.out.printf("本地月份全稱:%tB%n",date);  
        //a的使用,星期簡稱  
        str=String.format(Locale.US,"英文星期的簡稱:%ta",date);  
        System.out.println(str);  
        //A的使用,星期全稱  
        System.out.printf("本地星期的簡稱:%tA%n",date);  
        //C的使用,年前兩位  
        System.out.printf("年的前兩位數字(不足兩位前面補0):%tC%n",date);  
        //y的使用,年後兩位  
        System.out.printf("年的後兩位數字(不足兩位前面補0):%ty%n",date);  
        //j的使用,一年的天數  
        System.out.printf("一年中的天數(即年的第幾天):%tj%n",date);  
        //m的使用,月份  
        System.out.printf("兩位數字的月份(不足兩位前面補0):%tm%n",date);  
        //d的使用,日(二位,不夠補零)  
        System.out.printf("兩位數字的日(不足兩位前面補0):%td%n",date);  
        //e的使用,日(一位不補零)  
        System.out.printf("月份的日(前面不補0):%te",date);  
   }
}

輸出結果為:

英文月份簡稱:May
本地月份簡稱:五月
英文月份全稱:May
本地月份全稱:五月
英文星期的簡稱:Thu
本地星期的簡稱:星期四
年的前兩位數字(不足兩位前面補0):20
年的後兩位數字(不足兩位前面補0):17
一年中的天數(即年的第幾天):124
兩位數字的月份(不足兩位前面補0):05
兩位數字的日(不足兩位前面補0):04
月份的日(前面不補0):4

解析字串為時間

SimpleDateFormat 類有一些附加的方法,特別是parse(),它試圖按照給定的SimpleDateFormat 物件的格式化儲存來解析字串。例如:

import java.util.*;
import java.text.*;
  
public class DateDemo {
 
   public static void main(String args[]) {
      SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd"); 
 
      String input = args.length == 0 ? "1818-11-11" : args[0]; 
 
      System.out.print(input + " Parses as "); 
 
      Date t; 
 
      try { 
          t = ft.parse(input); 
          System.out.println(t); 
      } catch (ParseException e) { 
          System.out.println("Unparseable using " + ft); 
      }
   }
}

以上例項編譯執行結果如下:

$ java DateDemo
1818-11-11 Parses as Wed Nov 11 00:00:00 GMT 1818
$ java DateDemo 2007-12-01
2007-12-01 Parses as Sat Dec 01 00:00:00 GMT 2007

Java 休眠(sleep)

sleep()使當前執行緒進入停滯狀態(阻塞當前執行緒),讓出CPU的使用、目的是不讓當前執行緒獨自霸佔該程式所獲的CPU資源,以留一定時間給其他執行緒執行的機會。

你可以讓程式休眠一毫秒的時間或者到您的計算機的壽命長的任意段時間。例如,下面的程式會休眠3秒:

 

import java.util.*;
  
public class SleepDemo {
   public static void main(String args[]) {
      try { 
         System.out.println(new Date( ) + "\n"); 
         Thread.sleep(1000*3);   // 休眠3秒
         System.out.println(new Date( ) + "\n"); 
      } catch (Exception e) { 
          System.out.println("Got an exception!"); 
      }
   }
}

以上例項編譯執行結果如下:

Thu Sep 17 10:20:30 CST 2015

Thu Sep 17 10:20:33 CST 2015

測量時間

下面的一個例子表明如何測量時間間隔(以毫秒為單位):

import java.util.*;
  
public class DiffDemo {
 
   public static void main(String args[]) {
      try {
         long start = System.currentTimeMillis( );
         System.out.println(new Date( ) + "\n");
         Thread.sleep(5*60*10);
         System.out.println(new Date( ) + "\n");
         long end = System.currentTimeMillis( );
         long diff = end - start;
         System.out.println("Difference is : " + diff);
      } catch (Exception e) {
         System.out.println("Got an exception!");
      }
   }
}

以上例項編譯執行結果如下:

Fri Jan 08 09:48:47 CST 2016

Fri Jan 08 09:48:50 CST 2016

Difference is : 3019

Calendar類

我們現在已經能夠格式化並建立一個日期物件了,但是我們如何才能設定和獲取日期資料的特定部分呢,比如說小時,日,或者分鐘? 我們又如何在日期的這些部分加上或者減去值呢? 答案是使用Calendar 類。

Calendar類的功能要比Date類強大很多,而且在實現方式上也比Date類要複雜一些。

Calendar類是一個抽象類,在實際使用時實現特定的子類的物件,建立物件的過程對程式設計師來說是透明的,只需要使用getInstance方法建立即可。

建立一個代表系統當前日期的Calendar物件

Calendar c = Calendar.getInstance();//預設是當前日期

建立一個指定日期的Calendar物件

使用Calendar類代表特定的時間,需要首先建立一個Calendar的物件,然後再設定該物件中的年月日引數來完成。

//建立一個代表2009年6月12日的Calendar物件
Calendar c1 = Calendar.getInstance();
c1.set(2009, 6 - 1, 12);

Calendar類物件欄位型別

Calendar類中用以下這些常量表示不同的意義,jdk內的很多類其實都是採用的這種思想

常量描述
Calendar.YEAR年份
Calendar.MONTH月份
Calendar.DATE日期
Calendar.DAY_OF_MONTH日期,和上面的欄位意義完全相同
Calendar.HOUR12小時制的小時
Calendar.HOUR_OF_DAY24小時制的小時
Calendar.MINUTE分鐘
Calendar.SECOND
Calendar.DAY_OF_WEEK星期幾

Calendar類物件資訊的設定

Set設定

如:

Calendar c1 = Calendar.getInstance();

 呼叫:

public final void set(int year,int month,int date)
c1.set(2009, 6, 12);//把Calendar物件c1的年月日分別設這為:2009、6、12

利用欄位型別設定

如果只設定某個欄位,例如日期的值,則可以使用如下set方法:

public void set(int field,int value)

把 c1物件代表的日期設定為10號,其它所有的數值會被重新計算

c1.set(Calendar.DATE,10);

把c1物件代表的年份設定為2008年,其他的所有數值會被重新計算

c1.set(Calendar.YEAR,2008);

其他欄位屬性set的意義以此類推

Add設定

Calendar c1 = Calendar.getInstance();

把c1物件的日期加上10,也就是c1也就表示為10天后的日期,其它所有的數值會被重新計算

c1.add(Calendar.DATE, 10);

 把c1物件的日期減去10,也就是c1也就表示為10天前的日期,其它所有的數值會被重新計算

c1.add(Calendar.DATE, -10);

其他欄位屬性的add的意義以此類推

Calendar類物件資訊的獲得

Calendar c1 = Calendar.getInstance();
// 獲得年份
int year = c1.get(Calendar.YEAR);
// 獲得月份
int month = c1.get(Calendar.MONTH) + 1;
// 獲得日期
int date = c1.get(Calendar.DATE);
// 獲得小時
int hour = c1.get(Calendar.HOUR_OF_DAY);
// 獲得分鐘
int minute = c1.get(Calendar.MINUTE);
// 獲得秒
int second = c1.get(Calendar.SECOND);
// 獲得星期幾(注意(這個與Date類是不同的):1代表星期日、2代表星期1、3代表星期二,以此類推)
int day = c1.get(Calendar.DAY_OF_WEEK);

GregorianCalendar類

Calendar類實現了公曆日曆,GregorianCalendar是Calendar類的一個具體實現。

Calendar 的getInstance()方法返回一個預設用當前的語言環境和時區初始化的GregorianCalendar物件。GregorianCalendar定義了兩個欄位:AD和BC。這是代表公曆定義的兩個時代。

下面列出GregorianCalendar物件的幾個構造方法:

序號建構函式和說明
1GregorianCalendar() 
在具有預設語言環境的預設時區內使用當前時間構造一個預設的 GregorianCalendar。
2GregorianCalendar(int year, int month, int date) 
在具有預設語言環境的預設時區內構造一個帶有給定日期設定的 GregorianCalendar
3GregorianCalendar(int year, int month, int date, int hour, int minute) 
為具有預設語言環境的預設時區構造一個具有給定日期和時間設定的 GregorianCalendar。
4GregorianCalendar(int year, int month, int date, int hour, int minute, int second) 
  為具有預設語言環境的預設時區構造一個具有給定日期和時間設定的 GregorianCalendar。
5GregorianCalendar(Locale aLocale) 
在具有給定語言環境的預設時區內構造一個基於當前時間的 GregorianCalendar。
6GregorianCalendar(TimeZone zone) 
在具有預設語言環境的給定時區內構造一個基於當前時間的 GregorianCalendar。
7GregorianCalendar(TimeZone zone, Locale aLocale) 
 在具有給定語言環境的給定時區內構造一個基於當前時間的 GregorianCalendar。

 這裡是GregorianCalendar 類提供的一些有用的方法列表:

序號方法和說明
1void add(int field, int amount) 
根據日曆規則,將指定的(有符號的)時間量新增到給定的日曆欄位中。
2protected void computeFields() 
轉換UTC毫秒值為時間域值
3protected void computeTime() 
覆蓋Calendar ,轉換時間域值為UTC毫秒值
4boolean equals(Object obj) 
比較此 GregorianCalendar 與指定的 Object。
5int get(int field) 
獲取指定欄位的時間值
6int getActualMaximum(int field) 
返回當前日期,給定欄位的最大值
7int getActualMinimum(int field) 
返回當前日期,給定欄位的最小值
8int getGreatestMinimum(int field) 
 返回此 GregorianCalendar 例項給定日曆欄位的最高的最小值。
9Date getGregorianChange() 
獲得格里高利曆的更改日期。
10int getLeastMaximum(int field) 
返回此 GregorianCalendar 例項給定日曆欄位的最低的最大值
11int getMaximum(int field) 
返回此 GregorianCalendar 例項的給定日曆欄位的最大值。
12Date getTime()
獲取日曆當前時間。
13long getTimeInMillis() 
獲取用長整型表示的日曆的當前時間
14TimeZone getTimeZone() 
獲取時區。
15int getMinimum(int field) 
返回給定欄位的最小值。
16int hashCode() 
重寫hashCode.
17boolean isLeapYear(int year)
確定給定的年份是否為閏年。
18void roll(int field, boolean up) 
在給定的時間欄位上新增或減去(上/下)單個時間單元,不更改更大的欄位。
19void set(int field, int value) 
用給定的值設定時間欄位。
20void set(int year, int month, int date) 
設定年、月、日的值。
21void set(int year, int month, int date, int hour, int minute) 
設定年、月、日、小時、分鐘的值。
22void set(int year, int month, int date, int hour, int minute, int second) 
設定年、月、日、小時、分鐘、秒的值。
23void setGregorianChange(Date date) 
設定 GregorianCalendar 的更改日期。
24void setTime(Date date) 
用給定的日期設定Calendar的當前時間。
25void setTimeInMillis(long millis) 
用給定的long型毫秒數設定Calendar的當前時間。
26void setTimeZone(TimeZone value) 
用給定時區值設定當前時區。
27String toString() 
返回代表日曆的字串。

 例項:

 

import java.util.*;
  
public class GregorianCalendarDemo {
 
   public static void main(String args[]) {
      String months[] = {
      "Jan", "Feb", "Mar", "Apr",
      "May", "Jun", "Jul", "Aug",
      "Sep", "Oct", "Nov", "Dec"};
      
      int year;
      // 初始化 Gregorian 日曆
      // 使用當前時間和日期
      // 預設為本地時間和時區
      GregorianCalendar gcalendar = new GregorianCalendar();
      // 顯示當前時間和日期的資訊
      System.out.print("Date: ");
      System.out.print(months[gcalendar.get(Calendar.MONTH)]);
      System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
      System.out.println(year = gcalendar.get(Calendar.YEAR));
      System.out.print("Time: ");
      System.out.print(gcalendar.get(Calendar.HOUR) + ":");
      System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
      System.out.println(gcalendar.get(Calendar.SECOND));
      
      // 測試當前年份是否為閏年
      if(gcalendar.isLeapYear(year)) {
         System.out.println("當前年份是閏年");
      }
      else {
         System.out.println("當前年份不是閏年");
      }
   }
}

以上例項編譯執行結果如下:

Date: Apr 22 2009
Time: 11:25:27
當前年份不是閏年

 關於 Calender 類的完整列表,你可以參考標準的 Java文件

Java 正規表示式

正規表示式定義了字串的模式。

正規表示式可以用來搜尋、編輯或處理文字。

正規表示式並不僅限於某一種語言,但是在每種語言中有細微的差別。

正規表示式例項

一個字串其實就是一個簡單的正規表示式,例如 Hello World 正規表示式匹配 "Hello World" 字串。

.(點號)也是一個正規表示式,它匹配任何一個字元如:"a" 或 "1"。

下表列出了一些正規表示式的例項及描述:

正規表示式描述

this is text

匹配字串 "this is text"

this\s+is\s+text

注意字串中的 \s+

匹配單詞 "this" 後面的 \s+ 可以匹配多個空格,之後匹配 is 字串,再之後 \s+ 匹配多個空格然後再跟上 text 字串。

可以匹配這個例項:this is text

^\d+(\.\d+)?

^ 定義了以什麼開始

\d+ 匹配一個或多個數字

? 設定括號內的選項是可選的

\. 匹配 "."

可以匹配的例項:"5", "1.5" 和 "2.21"。

Java 正規表示式和 Perl 的是最為相似的。

java.util.regex 包主要包括以下三個類:

  • Pattern 類:

    pattern 物件是一個正規表示式的編譯表示。Pattern 類沒有公共構造方法。要建立一個 Pattern 物件,你必須首先呼叫其公共靜態編譯方法,它返回一個 Pattern 物件。該方法接受一個正規表示式作為它的第一個引數。

  • Matcher 類:

    Matcher 物件是對輸入字串進行解釋和匹配操作的引擎。與Pattern 類一樣,Matcher 也沒有公共構造方法。你需要呼叫 Pattern 物件的 matcher 方法來獲得一個 Matcher 物件。

  • PatternSyntaxException:

    PatternSyntaxException 是一個非強制異常類,它表示一個正規表示式模式中的語法錯誤。

以下例項中使用了正規表示式 .*runoob.* 用於查詢字串中是否包了 runoob 子串:

import java.util.regex.*;
 
class RegexExample1{
   public static void main(String args[]){
      String content = "I am noob " +
        "from runoob.com.";
 
      String pattern = ".*runoob.*";
 
      boolean isMatch = Pattern.matches(pattern, content);
      System.out.println("字串中是否包含了 'runoob' 子字串? " + isMatch);
   }
}

 例項輸出結果為:

字串中是否包含了 'runoob' 子字串? true

捕獲組

捕獲組是把多個字元當一個單獨單元進行處理的方法,它通過對括號內的字元分組來建立。

例如,正規表示式 (dog) 建立了單一分組,組裡包含"d","o",和"g"。

捕獲組是通過從左至右計算其開括號來編號。例如,在表示式((A)(B(C))),有四個這樣的組:

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

可以通過呼叫 matcher 物件的 groupCount 方法來檢視錶達式有多少個分組。groupCount 方法返回一個 int 值,表示matcher物件當前有多個捕獲組。

還有一個特殊的組(group(0)),它總是代表整個表示式。該組不包括在 groupCount 的返回值中。

例項

下面的例子說明如何從一個給定的字串中找到數字串:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    public static void main( String args[] ){
 
      // 按指定模式在字串查詢
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(\\D*)(\\d+)(.*)";
 
      // 建立 Pattern 物件
      Pattern r = Pattern.compile(pattern);
 
      // 現在建立 matcher 物件
      Matcher m = r.matcher(line);
      if (m.find( )) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
         System.out.println("Found value: " + m.group(3) ); 
      } else {
         System.out.println("NO MATCH");
      }
   }
}

以上例項編譯執行結果如下:

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
Found value: ! OK?

正規表示式語法

在其他語言中,\\ 表示:我想要在正規表示式中插入一個普通的(字面上的)反斜槓,請不要給它任何特殊的意義。

在 Java 中,\\ 表示:我要插入一個正規表示式的反斜線,所以其後的字元具有特殊的意義。

所以,在其他的語言中(如Perl),一個反斜槓 \ 就足以具有轉義的作用,而在 Java 中正規表示式中則需要有兩個反斜槓才能被解析為其他語言中的轉義作用。也可以簡單的理解在 Java 的正規表示式中,兩個 \\ 代表其他語言中的一個 \,這也就是為什麼表示一位數字的正規表示式是\\d,而表示一個普通的反斜槓是 \\\\。

字元

說明

\

將下一字元標記為特殊字元、文字、反向引用或八進位制轉義符。例如,"n"匹配字元"n"。"\n"匹配換行符。序列"\\\\"匹配"\\","\\("匹配"("。

^

匹配輸入字串開始的位置。如果設定了 RegExp 物件的 Multiline 屬性,^ 還會與"\n"或"\r"之後的位置匹配。

$

匹配輸入字串結尾的位置。如果設定了 RegExp 物件的 Multiline 屬性,$ 還會與"\n"或"\r"之前的位置匹配。

*

零次或多次匹配前面的字元或子表示式。例如,zo* 匹配"z"和"zoo"。* 等效於 {0,}。

+

一次或多次匹配前面的字元或子表示式。例如,"zo+"與"zo"和"zoo"匹配,但與"z"不匹配。+ 等效於 {1,}。

?

零次或一次匹配前面的字元或子表示式。例如,"do(es)?"匹配"do"或"does"中的"do"。? 等效於 {0,1}。

{n}

是非負整數。正好匹配 n 次。例如,"o{2}"與"Bob"中的"o"不匹配,但與"food"中的兩個"o"匹配。

{n,}

是非負整數。至少匹配 次。例如,"o{2,}"不匹配"Bob"中的"o",而匹配"foooood"中的所有 o。"o{1,}"等效於"o+"。"o{0,}"等效於"o*"。

{n,m}

m 和 n 是非負整數,其中 n <= m。匹配至少 n 次,至多 m 次。例如,"o{1,3}"匹配"fooooood"中的頭三個 o。'o{0,1}' 等效於 'o?'。注意:您不能將空格插入逗號和數字之間。

?

當此字元緊隨任何其他限定符(*、+、?、{n}、{n,}、{n,m})之後時,匹配模式是"非貪心的"。"非貪心的"模式匹配搜尋到的、儘可能短的字串,而預設的"貪心的"模式匹配搜尋到的、儘可能長的字串。例如,在字串"oooo"中,"o+?"只匹配單個"o",而"o+"匹配所有"o"。

.

匹配除"\r\n"之外的任何單個字元。若要匹配包括"\r\n"在內的任意字元,請使用諸如"[\s\S]"之類的模式。

(pattern)

匹配 pattern 並捕獲該匹配的子表示式。可以使用 $0…$9 屬性從結果"匹配"集合中檢索捕獲的匹配。若要匹配括號字元 ( ),請使用"\("或者"\)"。

(?:pattern)

匹配 pattern 但不捕獲該匹配的子表示式,即它是一個非捕獲匹配,不儲存供以後使用的匹配。這對於用"or"字元 (|) 組合模式部件的情況很有用。例如,'industr(?:y|ies) 是比 'industry|industries' 更經濟的表示式。

(?=pattern)

執行正向預測先行搜尋的子表示式,該表示式匹配處於匹配 pattern 的字串的起始點的字串。它是一個非捕獲匹配,即不能捕獲供以後使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配"Windows 2000"中的"Windows",但不匹配"Windows 3.1"中的"Windows"。預測先行不佔用字元,即發生匹配後,下一匹配的搜尋緊隨上一匹配之後,而不是在組成預測先行的字元後。

(?!pattern)

執行反向預測先行搜尋的子表示式,該表示式匹配不處於匹配 pattern 的字串的起始點的搜尋字串。它是一個非捕獲匹配,即不能捕獲供以後使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配"Windows 3.1"中的 "Windows",但不匹配"Windows 2000"中的"Windows"。預測先行不佔用字元,即發生匹配後,下一匹配的搜尋緊隨上一匹配之後,而不是在組成預測先行的字元後。

x|y

匹配 x 或 y。例如,'z|food' 匹配"z"或"food"。'(z|f)ood' 匹配"zood"或"food"。

[xyz]

字符集。匹配包含的任一字元。例如,"[abc]"匹配"plain"中的"a"。

[^xyz]

反向字符集。匹配未包含的任何字元。例如,"[^abc]"匹配"plain"中"p","l","i","n"。

[a-z]

字元範圍。匹配指定範圍內的任何字元。例如,"[a-z]"匹配"a"到"z"範圍內的任何小寫字母。

[^a-z]

反向範圍字元。匹配不在指定的範圍內的任何字元。例如,"[^a-z]"匹配任何不在"a"到"z"範圍內的任何字元。

\b

匹配一個字邊界,即字與空格間的位置。例如,"er\b"匹配"never"中的"er",但不匹配"verb"中的"er"。

\B

非字邊界匹配。"er\B"匹配"verb"中的"er",但不匹配"never"中的"er"。

\cx

匹配 x 指示的控制字元。例如,\cM 匹配 Control-M 或回車符。x 的值必須在 A-Z 或 a-z 之間。如果不是這樣,則假定 c 就是"c"字元本身。

\d

數字字元匹配。等效於 [0-9]。

\D

非數字字元匹配。等效於 [^0-9]。

\f

換頁符匹配。等效於 \x0c 和 \cL。

\n

換行符匹配。等效於 \x0a 和 \cJ。

\r

匹配一個回車符。等效於 \x0d 和 \cM。

\s

匹配任何空白字元,包括空格、製表符、換頁符等。與 [ \f\n\r\t\v] 等效。

\S

匹配任何非空白字元。與 [^ \f\n\r\t\v] 等效。

\t

製表符匹配。與 \x09 和 \cI 等效。

\v

垂直製表符匹配。與 \x0b 和 \cK 等效。

\w

匹配任何字類字元,包括下劃線。與"[A-Za-z0-9_]"等效。

\W

與任何非單詞字元匹配。與"[^A-Za-z0-9_]"等效。

\xn

匹配 n,此處的 n 是一個十六進位制轉義碼。十六進位制轉義碼必須正好是兩位數長。例如,"\x41"匹配"A"。"\x041"與"\x04"&"1"等效。允許在正規表示式中使用 ASCII 程式碼。

\num

匹配 num,此處的 num 是一個正整數。到捕獲匹配的反向引用。例如,"(.)\1"匹配兩個連續的相同字元。

\n

標識一個八進位制轉義碼或反向引用。如果 \n 前面至少有 n 個捕獲子表示式,那麼 n 是反向引用。否則,如果 n 是八進位制數 (0-7),那麼 n是八進位制轉義碼。

\nm

標識一個八進位制轉義碼或反向引用。如果 \nm 前面至少有 nm 個捕獲子表示式,那麼 nm 是反向引用。如果 \nm 前面至少有 n 個捕獲,則 n 是反向引用,後面跟有字元 m。如果兩種前面的情況都不存在,則 \nm 匹配八進位制值 nm,其中 和 m 是八進位制數字 (0-7)。

\nml

當 n 是八進位制數 (0-3),m 和 l 是八進位制數 (0-7) 時,匹配八進位制轉義碼 nml

\un

匹配 n,其中 n 是以四位十六進位制數表示的 Unicode 字元。例如,\u00A9 匹配版權符號 (©)。

根據 Java Language Specification 的要求,Java 原始碼的字串中的反斜線被解釋為 Unicode 轉義或其他字元轉義。因此必須在字串字面值中使用兩個反斜線,表示正規表示式受到保護,不被 Java 位元組碼編譯器解釋。例如,當解釋為正規表示式時,字串字面值 "\b" 與單個退格字元匹配,而 "\\b" 與單詞邊界匹配。字串字面值 "\(hello\)" 是非法的,將導致編譯時錯誤;要與字串 (hello) 匹配,必須使用字串字面值 "\\(hello\\)"。


Matcher 類的方法

索引方法

索引方法提供了有用的索引值,精確表明輸入字串中在哪能找到匹配:

序號方法及說明
1public int start() 
返回以前匹配的初始索引。
2public int start(int group)
 返回在以前的匹配操作期間,由給定組所捕獲的子序列的初始索引
3public int end()
返回最後匹配字元之後的偏移量。
4public int end(int group)
返回在以前的匹配操作期間,由給定組所捕獲子序列的最後字元之後的偏移量。

研究方法

研究方法用來檢查輸入字串並返回一個布林值,表示是否找到該模式:

序號方法及說明
1public boolean lookingAt() 
 嘗試將從區域開頭開始的輸入序列與該模式匹配。
2public boolean find() 
嘗試查詢與該模式匹配的輸入序列的下一個子序列。
3public boolean find(int start
重置此匹配器,然後嘗試查詢匹配該模式、從指定索引開始的輸入序列的下一個子序列。
4public boolean matches() 
嘗試將整個區域與模式匹配。

替換方法

替換方法是替換輸入字串裡文字的方法:

序號方法及說明
1public Matcher appendReplacement(StringBuffer sb, String replacement)
實現非終端新增和替換步驟。
2public StringBuffer appendTail(StringBuffer sb)
實現終端新增和替換步驟。
3public String replaceAll(String replacement) 
 替換模式與給定替換字串相匹配的輸入序列的每個子序列。
4public String replaceFirst(String replacement)
 替換模式與給定替換字串匹配的輸入序列的第一個子序列。
5public static String quoteReplacement(String s)
返回指定字串的字面替換字串。這個方法返回一個字串,就像傳遞給Matcher類的appendReplacement 方法一個字面字串一樣工作。

start 和 end 方法

下面是一個對單詞 "cat" 出現在輸入字串中出現次數進行計數的例子:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static final String REGEX = "\\bcat\\b";
    private static final String INPUT =
                                    "cat cat cat cattie cat";
 
    public static void main( String args[] ){
       Pattern p = Pattern.compile(REGEX);
       Matcher m = p.matcher(INPUT); // 獲取 matcher 物件
       int count = 0;
 
       while(m.find()) {
         count++;
         System.out.println("Match number "+count);
         System.out.println("start(): "+m.start());
         System.out.println("end(): "+m.end());
      }
   }
}

以上例項編譯執行結果如下:

Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22

可以看到這個例子是使用單詞邊界,以確保字母 "c" "a" "t" 並非僅是一個較長的詞的子串。它也提供了一些關於輸入字串中匹配發生位置的有用資訊。

Start 方法返回在以前的匹配操作期間,由給定組所捕獲的子序列的初始索引,end 方法最後一個匹配字元的索引加 1。

matches 和 lookingAt 方法

matches 和 lookingAt 方法都用來嘗試匹配一個輸入序列模式。它們的不同是 matches 要求整個序列都匹配,而lookingAt 不要求。

lookingAt 方法雖然不需要整句都匹配,但是需要從第一個字元開始匹配。

這兩個方法經常在輸入字串的開始使用。

我們通過下面這個例子,來解釋這個功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static final String REGEX = "foo";
    private static final String INPUT = "fooooooooooooooooo";
    private static final String INPUT2 = "ooooofoooooooooooo";
    private static Pattern pattern;
    private static Matcher matcher;
    private static Matcher matcher2;
 
    public static void main( String args[] ){
       pattern = Pattern.compile(REGEX);
       matcher = pattern.matcher(INPUT);
       matcher2 = pattern.matcher(INPUT2);
 
       System.out.println("Current REGEX is: "+REGEX);
       System.out.println("Current INPUT is: "+INPUT);
       System.out.println("Current INPUT2 is: "+INPUT2);
 
 
       System.out.println("lookingAt(): "+matcher.lookingAt());
       System.out.println("matches(): "+matcher.matches());
       System.out.println("lookingAt(): "+matcher2.lookingAt());
   }
}

以上例項編譯執行結果如下:

Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
Current INPUT2 is: ooooofoooooooooooo
lookingAt(): true
matches(): false
lookingAt(): false

replaceFirst 和 replaceAll 方法

replaceFirst 和 replaceAll 方法用來替換匹配正規表示式的文字。不同的是,replaceFirst 替換首次匹配,replaceAll 替換所有匹配。

下面的例子來解釋這個功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static String REGEX = "dog";
    private static String INPUT = "The dog says meow. " +
                                    "All dogs say meow.";
    private static String REPLACE = "cat";
 
    public static void main(String[] args) {
       Pattern p = Pattern.compile(REGEX);
       // get a matcher object
       Matcher m = p.matcher(INPUT); 
       INPUT = m.replaceAll(REPLACE);
       System.out.println(INPUT);
   }
}

以上例項編譯執行結果如下:

The cat says meow. All cats say meow.

appendReplacement 和 appendTail 方法

Matcher 類也提供了appendReplacement 和 appendTail 方法用於文字替換:

看下面的例子來解釋這個功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
   private static String REGEX = "a*b";
   private static String INPUT = "aabfooaabfooabfoobkkk";
   private static String REPLACE = "-";
   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      // 獲取 matcher 物件
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()){
         m.appendReplacement(sb,REPLACE);
      }
      m.appendTail(sb);
      System.out.println(sb.toString());
   }
}

以上例項編譯執行結果如下:

-foo-foo-foo-kkk

PatternSyntaxException 類的方法

PatternSyntaxException 是一個非強制異常類,它指示一個正規表示式模式中的語法錯誤。

PatternSyntaxException 類提供了下面的方法來幫助我們檢視發生了什麼錯誤。

序號方法及說明
1public String getDescription()
獲取錯誤的描述。
2public int getIndex() 
 獲取錯誤的索引。
3public String getPattern() 
獲取錯誤的正規表示式模式。
4public String getMessage() 
返回多行字串,包含語法錯誤及其索引的描述、錯誤的正規表示式模式和模式中錯誤索引的視覺化指示。

Java 方法

在前面幾個章節中我們經常使用到 System.out.println(),那麼它是什麼呢?

  • println() 是一個方法。
  • System 是系統類。
  • out 是標準輸出物件。

這句話的用法是呼叫系統類 System 中的標準輸出物件 out 中的方法 println()。

那麼什麼是方法呢?

Java方法是語句的集合,它們在一起執行一個功能。

  • 方法是解決一類問題的步驟的有序組合
  • 方法包含於類或物件中
  • 方法在程式中被建立,在其他地方被引用

方法的優點

  • 1. 使程式變得更簡短而清晰。
  • 2. 有利於程式維護。
  • 3. 可以提高程式開發的效率。
  • 4. 提高了程式碼的重用性。

方法的命名規則

  • 1.方法的名字的第一個單詞應以小寫字母作為開頭,後面的單詞則用大寫字母開頭寫,不使用連線符。例如:addPerson。
  • 2.下劃線可能出現在 JUnit 測試方法名稱中用以分隔名稱的邏輯元件。一個典型的模式是:test<MethodUnderTest>_<state>,例如 testPop_emptyStack。

方法的定義

一般情況下,定義一個方法包含以下語法:

修飾符 返回值型別 方法名(引數型別 引數名){
    ...
    方法體
    ...
    return 返回值;
}

方法包含一個方法頭和一個方法體。下面是一個方法的所有部分:

  • 修飾符:修飾符,這是可選的,告訴編譯器如何呼叫該方法。定義了該方法的訪問型別。
  • 返回值型別 :方法可能會返回值。returnValueType 是方法返回值的資料型別。有些方法執行所需的操作,但沒有返回值。在這種情況下,returnValueType 是關鍵字void
  • 方法名:是方法的實際名稱。方法名和參數列共同構成方法簽名。
  • 引數型別:引數像是一個佔位符。當方法被呼叫時,傳遞值給引數。這個值被稱為實參或變數。引數列表是指方法的引數型別、順序和引數的個數。引數是可選的,方法可以不包含任何引數。
  • 方法體:方法體包含具體的語句,定義該方法的功能。

               

如:

public static int age(int birthday){...}

引數可以有多個:

static float interest(float principal, int year){...}

注意: 在一些其它語言中方法指過程和函式。一個返回非void型別返回值的方法稱為函式;一個返回void型別返回值的方法叫做過程。

例項

下面的方法包含 2 個引數 num1 和 num2,它返回這兩個引數的最大值。

/** 返回兩個整型變數資料的較大值 */
public static int max(int num1, int num2) {
   int result;
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

方法呼叫

Java 支援兩種呼叫方法的方式,根據方法是否返回值來選擇。

當程式呼叫一個方法時,程式的控制權交給了被呼叫的方法。當被呼叫方法的返回語句執行或者到達方法體閉括號時候交還控制權給程式。

當方法返回一個值的時候,方法呼叫通常被當做一個值。例如:

int larger = max(30, 40);

 如果方法返回值是void,方法呼叫一定是一條語句。例如,方法println返回void。下面的呼叫是個語句:

System.out.println("歡迎訪問菜鳥教程!");

 下面的例子演示瞭如何定義一個方法,以及如何呼叫它:

public class TestMax {
   /** 主方法 */
   public static void main(String[] args) {
      int i = 5;
      int j = 2;
      int k = max(i, j);
      System.out.println( i + " 和 " + j + " 比較,最大值是:" + k);
   }
 
   /** 返回兩個整數變數較大的值 */
   public static int max(int num1, int num2) {
      int result;
      if (num1 > num2)
         result = num1;
      else
         result = num2;
 
      return result; 
   }
}

以上例項編譯執行結果如下:

5 和 2 比較,最大值是:5

這個程式包含 main 方法和 max 方法。main 方法是被 JVM 呼叫的,除此之外,main 方法和其它方法沒什麼區別。

main 方法的頭部是不變的,如例子所示,帶修飾符 public 和 static,返回 void 型別值,方法名字是 main,此外帶個一個 String[] 型別引數。String[] 表明引數是字串陣列。

void 關鍵字

本節說明如何宣告和呼叫一個 void 方法。

下面的例子宣告瞭一個名為 printGrade 的方法,並且呼叫它來列印給定的分數

例項:

public class TestVoidMethod {
  public static void main(String[] args) {
    printGrade(78.5);
  }
 
  public static void printGrade(double score) {
    if (score >= 90.0) {
       System.out.println('A');
    }
    else if (score >= 80.0) {
       System.out.println('B');
    }
    else if (score >= 70.0) {
       System.out.println('C');
    }
    else if (score >= 60.0) {
       System.out.println('D');
    }
    else {
       System.out.println('F');
    }
  }
}

以上例項編譯執行結果如下:

C

這裡printGrade方法是一個void型別方法,它不返回值。

一個void方法的呼叫一定是一個語句。 所以,它被在main方法第三行以語句形式呼叫。就像任何以分號結束的語句一樣。

通過值傳遞引數

呼叫一個方法時候需要提供引數,你必須按照引數列表指定的順序提供。

例如,下面的方法連續n次列印一個訊息:

public static void nPrintln(String message, int n) {
  for (int i = 0; i < n; i++) {
    System.out.println(message);
  }
}

下面的例子演示按值傳遞的效果。

該程式建立一個方法,該方法用於交換兩個變數。

public class TestPassByValue {
  public static void main(String[] args) {
    int num1 = 1;
    int num2 = 2;
 
    System.out.println("交換前 num1 的值為:" +
                        num1 + " ,num2 的值為:" + num2);
 
    // 呼叫swap方法
    swap(num1, num2);
    System.out.println("交換後 num1 的值為:" +
                       num1 + " ,num2 的值為:" + num2);
  }
  /** 交換兩個變數的方法 */
  public static void swap(int n1, int n2) {
    System.out.println("\t進入 swap 方法");
    System.out.println("\t\t交換前 n1 的值為:" + n1
                         + ",n2 的值:" + n2);
    // 交換 n1 與 n2的值
    int temp = n1;
    n1 = n2;
    n2 = temp;
 
    System.out.println("\t\t交換後 n1 的值為 " + n1
                         + ",n2 的值:" + n2);
  }
}

以上例項編譯執行結果如下:

交換前 num1 的值為:1 ,num2 的值為:2
    進入 swap 方法
        交換前 n1 的值為:1,n2 的值:2
        交換後 n1 的值為 2,n2 的值:1
交換後 num1 的值為:1 ,num2 的值為:2

傳遞兩個引數呼叫swap方法。有趣的是,方法被呼叫後,實參的值並沒有改變。

方法的過載

上面使用的max方法僅僅適用於int型資料。但如果你想得到兩個浮點型別資料的最大值呢?

解決方法是建立另一個有相同名字但引數不同的方法,如下面程式碼所示:

public static double max(double num1, double num2) {
  if (num1 > num2)
    return num1;
  else
    return num2;
}

如果你呼叫max方法時傳遞的是int型引數,則 int型引數的max方法就會被呼叫;

如果傳遞的是double型引數,則double型別的max方法體會被呼叫,這叫做方法過載;

就是說一個類的兩個方法擁有相同的名字,但是有不同的引數列表。

Java編譯器根據方法簽名判斷哪個方法應該被呼叫。

方法過載可以讓程式更清晰易讀。執行密切相關任務的方法應該使用相同的名字。

過載的方法必須擁有不同的引數列表。你不能僅僅依據修飾符或者返回型別的不同來過載方法。

變數作用域

變數的範圍是程式中該變數可以被引用的部分。

方法內定義的變數被稱為區域性變數。

區域性變數的作用範圍從宣告開始,直到包含它的塊結束。

區域性變數必須宣告才可以使用。

方法的引數範圍涵蓋整個方法。引數實際上是一個區域性變數。

for迴圈的初始化部分宣告的變數,其作用範圍在整個迴圈。

但迴圈體內宣告的變數其適用範圍是從它宣告到迴圈體結束。它包含如下所示的變數宣告:

你可以在一個方法裡,不同的非巢狀塊中多次宣告一個具有相同的名稱區域性變數,但你不能在巢狀塊內兩次宣告區域性變數。

命令列引數的使用

有時候你希望執行一個程式時候再傳遞給它訊息。這要靠傳遞命令列引數給main()函式實現。

命令列引數是在執行程式時候緊跟在程式名字後面的資訊。

例項:

下面的程式列印所有的命令列引數:

public class CommandLine {
   public static void main(String args[]){ 
      for(int i=0; i<args.length; i++){
         System.out.println("args[" + i + "]: " + args[i]);
      }
   }
}

如下所示,執行這個程式:

$ javac CommandLine.java 
$ java CommandLine this is a command line 200 -100
args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100

構造方法

當一個物件被建立時候,構造方法用來初始化該物件。構造方法和它所在類的名字相同,但構造方法沒有返回值。

通常會使用構造方法給一個類的例項變數賦初值,或者執行其它必要的步驟來建立一個完整的物件。

不管你是否自定義構造方法,所有的類都有構造方法,因為Java自動提供了一個預設構造方法,預設構造方法的訪問修改符和類的訪問修改符相同(類為 public,建構函式也為 public;類改為 protected,建構函式也改為 protected)。

一旦你定義了自己的構造方法,預設構造方法就會失效。

下面是一個使用構造方法的例子:

// 一個簡單的建構函式
class MyClass {
  int x;
 
  // 以下是建構函式
  MyClass() {
    x = 10;
  }
}

你可以像下面這樣呼叫構造方法來初始化一個物件:

public class ConsDemo {
   public static void main(String args[]) {
      MyClass t1 = new MyClass();
      MyClass t2 = new MyClass();
      System.out.println(t1.x + " " + t2.x);
   }
}

大多時候需要一個有引數的構造方法。

大多時候需要一個有引數的構造方法。

// 一個簡單的建構函式
class MyClass {
  int x;
 
  // 以下是建構函式
  MyClass(int i ) {
    x = i;
  }
}

你可以像下面這樣呼叫構造方法來初始化一個物件:

public class ConsDemo {
  public static void main(String args[]) {
    MyClass t1 = new MyClass( 10 );
    MyClass t2 = new MyClass( 20 );
    System.out.println(t1.x + " " + t2.x);
  }
}

執行結果如下:

10 20

可變引數

JDK 1.5 開始,Java支援傳遞同型別的可變引數給一個方法。

方法的可變引數的宣告如下所示:

typeName... parameterName

在方法宣告中,在指定引數型別後加一個省略號(...) 。

一個方法中只能指定一個可變引數,它必須是方法的最後一個引數。任何普通的引數必須在它之前宣告。

例項:

public class VarargsDemo {
    public static void main(String args[]) {
        // 呼叫可變引數的方法
        printMax(34, 3, 3, 2, 56.5);
        printMax(new double[]{1, 2, 3});
    }
 
    public static void printMax( double... numbers) {
        if (numbers.length == 0) {
            System.out.println("No argument passed");
            return;
        }
 
        double result = numbers[0];
 
        for (int i = 1; i <  numbers.length; i++){
            if (numbers[i] >  result) {
                result = numbers[i];
            }
        }
        System.out.println("The max value is " + result);
    }
}

以上例項編譯執行結果如下:

The max value is 56.5
The max value is 3.0

finalize() 方法

Java 允許定義這樣的方法,它在物件被垃圾收集器析構(回收)之前呼叫,這個方法叫做 finalize( ),它用來清除回收物件。

例如,你可以使用 finalize() 來確保一個物件開啟的檔案被關閉了。

在 finalize() 方法裡,你必須指定在物件銷燬時候要執行的操作。

finalize() 一般格式是:

protected void finalize()
{
   // 在這裡終結程式碼
}

關鍵字 protected 是一個限定符,它確保 finalize() 方法不會被該類以外的程式碼呼叫。

當然,Java 的記憶體回收可以由 JVM 來自動完成。如果你手動使用,則可以使用上面的方法。

例項:

public class FinalizationDemo {  
  public static void main(String[] args) {  
    Cake c1 = new Cake(1);  
    Cake c2 = new Cake(2);  
    Cake c3 = new Cake(3);  
      
    c2 = c3 = null;  
    System.gc(); //呼叫Java垃圾收集器
  }  
}  
 
class Cake extends Object {  
  private int id;  
  public Cake(int id) {  
    this.id = id;  
    System.out.println("Cake Object " + id + "is created");  
  }  
    
  protected void finalize() throws java.lang.Throwable {  
    super.finalize();  
    System.out.println("Cake Object " + id + "is disposed");  
  }  
}

執行以上程式碼,輸出結果如下:

$ javac FinalizationDemo.java 
$ java FinalizationDemo
Cake Object 1is created
Cake Object 2is created
Cake Object 3is created
Cake Object 3is disposed
Cake Object 2is disposed

 

相關文章