Chương 3: Phương thức rỗng

Trở về Mục lục cuốn sách

3.1  Dấu phẩy động

Ở chương trước ta đã gặp trục trặc khi tính toán những số không nguyên. Ta đã sửa một cách tạm bợ bằng việc tính số phần trăm thay vì số thập phân, nhưng một giải pháp tổng quát hơn sẽ là dùng số có dấu phẩy động, để biểu diễn được cả số nguyên lẫn số có phần thập phân. Trong Java, kiểu dấu phẩy động có tên double, là chữ gọi tắt của “double-precision” (độ chuẩn xác kép).

Bạn có thể tạo nên các biến phẩy động rồi gán giá trị cho chúng theo cú pháp giống như ta đã làm với những kiểu dữ liệu khác. Chẳng hạn:

    double pi;
    pi = 3.14159;

Việc khai báo một biến đồng thời gán giá trị cho nó cũng hợp lệ:

    int x = 1; 
    String empty = ""; 
    double pi = 3.14159;

Cú pháp này rất thông dụng; việc kết hợp giữa khai báo và gán đôi khi còn được gọi là phép khởi tạo.

Mặc dù các số phẩy động rất hữu ích nhưng chúng cũng là nguồn gây nên rắc rối, vì dường như có phần trùng nhau giữa các số nguyên và số phẩy động. Chẳng hạn, nếu bạn có giá trị 1, thì đó là số nguyên, số phẩy động, hay cả hai?

Java phân biệt giá trị số nguyên 1 với giá trị phẩy động 1.0, dù rằng chúng có vẻ cùng là một số. Chúng thuộc về hai kiểu dữ liệu khác nhau, và nói chặt chẽ thì bạn không được phép gán giá trị kiểu này cho một biến kiểu khác. Chẳng hạn, câu lệnh sau là hợp lệ:

    int x = 1.1;

vì biến ở vế trái là int còn giá trị ở vế phải là double. Nhưng rất dễ quên mất quy tắc này, đặc biệt là vì có những nơi mà Java sẽ tự động chuyển từ một kiểu này sang kiểu khác. Chẳng hạn:

    double y = 1;

về lý thì không hợp lệ, nhưng Java vẫn cho phép điều này nhờ cách tự động chuyển đổi từ int sang double. Sự dễ dãi này khá tiện lợi, song có thể gặp vấn đề, chẳng hạn:

    double y = 1 / 3;

Bạn có thể trông đợi rằng biến y nhận giá trị 0.333333, vốn là một giá trị phẩy động hoàn toàn hợp lệ, song thực ra nó nhận được 0.0. Lý do là biểu thức vế phải là tỉ số giữa hai số nguyên, vì vậy Java thực hiện phép chia nguyên, và cho giá trị số nguyên bằng 0. Chuyển thành dạng số phẩy động, kết quả là 0.0.

Một cách giải quyết vấn đề này (khi bạn đã hình dung ra) là làm cho vế phải trở thành một biểu thức chứa số phẩy động:

    double y = 1.0 / 3.0;

Bằng cách này đã đặt y bằng 0.333333, như dự kiến.

Các toán tử mà ta đã gặp đến giờ—cộng, trừ, nhân, và chia—cũng làm việc được với các giá trị dấu phẩy động, mặc dù bạn có thể thấy thú vị khi biết được rằng cơ chế bên trong thì khác hẳn. Thực ra, đa số các bộ vi xử lý đều có phần mềm chuyên dụng để thực hiện các phép tính có dấu phẩy động.

3.2  Chuyển đổi từ double sang int

Như tôi đã nói, Java quy đổi các số int thành double một cách tự động nếu thấy cần thiết, vì trong quá trình chuyển đổi không bị mất thông tin. Ngược lại, chuyển từ double sang int lại cần phải làm tròn số. Java không tự động làm việc này, để đảm bảo rằng bạn, người lập trình, cũng biết được rằng phần thập phân của số sẽ bị mất đi.

Cách đơn giản nhất để chuyển một giá trị số phẩy động sang số nguyên là thực hiện việc định kiểu (typecast). Sở dĩ gọi là định kiểu vì bằng cách đó ta có thể lấy một giá trị thuộc kiểu này rồi “ấn định” nó thành kiểu khác (như việc định hình bằng khuôn đúc kim loại).

Cú pháp của định kiểu là đặt tên kiểu giữa cặp ngoặc tròn rồi dùng nó như một toán tử. Chẳng hạn,

    double pi = 3.14159; 
    int x = (int) pi;

Toán tử (int) có tác dụng chuyển bất kì thứ gì đi sau nó thành một số nguyên, bởi vậy x nhận giá trị bằng 3.

Định kiểu có quyền ưu tiên cao hơn so với các toán tử số học, bởi vậy ở ví dụ sau, trước hết giá trị của  pi được chuyển thành số nguyên, và kết quả sẽ là 60.0, chứ không phải 62.

    double pi = 3.14159; 
    double x = (int) pi * 20.0;

Việc chuyển thành số nguyên sẽ luôn làm tròn xuống, ngay cả khi phần thập phân là 0.99999999. Cách hoạt động này (quyền ưu tiên và việc làm tròn) có thể khiến cho việc định kiểu dễ gây nên lỗi.

3.3 Các phương thức Math

Khi làm toán, có lẽ bạn đã thấy các hàm như sin và log, đồng thời cũng biết cách tính các biểu thức như sin(π/2) và log(1/x). Đầu tiên, bạn lượng giá biểu thức trong cặp ngoặc tròn, vốn được gọi là đối số của hàm. Tiếp theo bạn lượng giá bản thân hàm đó, bằng cách tra bảng hoặc tính toán.

Công đoạn này có thể được áp dụng lặp lại để lượng giá những biểu thức phức tạp hơn như log(1/sin(π/2)). Đầu tiên, bạn lượng giá đối số của hàm đứng trong cùng, rồi lượng giá bản thân hàm đó, và cứ như vậy.

Java cung cấp cho ta các hàm để thực hiện những phép toán thông dụng nhất. Những hàm này được gọi là phương thức. Các phương thức toán học được kích hoạt bằng cách dùng cú pháp tương tự như câu lệnh print mà ta đã gặp:

    double root = Math.sqrt(17.0); 
    double angle = 1.5; 
    double height = Math.sin(angle);

Ví dụ đầu tiên đặt root bằng căn bậc hai của 17. Ví dụ thứ hai đi tìm sin của giá trị angle, vốn là 1.5. Java giả thiết rằng những giá trị bạn dùng với sin và các hàm lượng giác khác (costan) đều tính theo radian. Để chuyển từ độ sang radian, bạn có thể chia cho 360 đồng thời nhân với 2π. Thật tiện là Java có cung cấp Math.PI:

    double degrees = 90; 
    double angle = degrees * 2 * Math.PI / 360.0;

Lưu ý rằng chữ PI đều viết in toàn bộ. Java không nhận ra Pipi, hay pie.

Một phương thức hữu dụng khác có trong lớp Math là round, để làm tròn một giá trị số phẩy động về số nguyên gần đó nhất rồi trả lại một int.

int x = Math.round(Math.PI * 20.0);

Trong trường hợp này phép nhân xảy ra đầu tiên, trước khi phương thức được kích hoạt. Kết quả là 63 (được làm tròn lên từ 62.8319).

3.4  Kết hợp

Cũng như với các hàm toán học, những phương thức trong Java có thể được kết hợp lại,  nghĩa là bạn có thể dùng một biểu thức làm thành phần trong biểu thức khác. Chẳng hạn, bạn có thể dùng bất kì biểu thức nào làm đối số cho một phương thức:

    double x = Math.cos(angle + Math.PI/2);

Câu lệnh này lấy giá trị Math.PI, đem chia cho hai rồi cộng kết quả thu được vào giá trị của biến angle. Tiếp theo, tổng này được truyền làm tham số cho cos. (PI là tên của một biến, chứ không phải một phương thức; bởi vậy mà không có đối số nào, thậm chí không có cả đối số rỗng ()).

Bạn cũng có thể lấy kết quả của một phương thức để truyền làm đối số cho phương thức khác:

    double x = Math.exp(Math.log(10.0));

Trong Java, phương thức log luôn dùng cơ số bằng e, bởi vậy câu lệnh này tìm loga cơ số e của 10 rồi nâng e lên số mũ đó. Kết quả được gán cho x; hi vọng rằng bạn biết phép tính này để làm gì.

3.5  Bổ sung những phương thức mới

Đến bây giờ, chúng ta mới chỉ dùng những phương thức có sẵn trong Java, song thật ra có thể tạo ra những phương thức mới.  Ta đã thấy một lời định nghĩa cho phương thức main. Phương thức tên là main có ý nghĩa đặc biệt, song cú pháp của nó cũng giống như các phương thức khác:

    public static void TÊN( DANH SÁCH THAM SỐ ) { CÁC CÂU LỆNH }

Bạn có thể lấy tên bất kì để đặt cho phương thức mới, miễn là không phải main hay một từ khóa Java nào đó. Theo quy ước, các phương thức Java bắt đầu bằng chữ thường và dùng cách viết in từng chữ đầu của từ (còn gọi là “camel caps”), một tên gọi thú vị để chỉ những cái tên kiểu như jammingWordsTogetherLikeThis.

Danh sách các tham số thì quy định những thông tin (nếu có) mà bạn phải cung cấp khi dùng (hay kích hoạt) phương thức mới này.

Tham số của phương thức main là String[] args; điều này nghĩa là ai muốn kích hoạt main thì phải cung cấp một mảng các chuỗi (String) (ta sẽ bàn đến mảng ở Chương 12). Một số phương thức ta tập viết đầu tay thì không có tham số nào, vì vậy cú pháp sẽ có dạng như sau:

  public static void newLine() { 
    System.out.println(""); 
  }

Phương thức này có tên newLine, và cặp ngoặc tròn không chứa gì đồng nghĩa với việc phương thức này không nhận tham số. Nó chỉ có một câu lệnh, nhằm in một String rỗng, được biểu thị bởi "". Việc in một String mà không có chữ nào trong đó dường như là việc vô ích, nhưng vì println sẽ nhảy xuống dòng dưới sau khi in, nên câu lệnh này có tác dụng xuống dòng.

Trong main ta kích hoạt phương thức mới này cũng giống như cách ta kích hoạt các phương thức của Java:

  public static void main(String[] args) { 
    System.out.println("First line."); 
    newLine(); 
    System.out.println("Second line."); 
  }

Kết quả của chương trình này là

First line. 

Second line.

Lưu ý đến dòng trống giữa hai dòng chữ trên. Ta phải làm gì nếu muốn hai dòng này cách nhau xa hơn? Ta có thể liên tiếp kích hoạt phương thức mới này:

  public static void main(String[] args) {
    System.out.println("First line.");
    newLine();
    newLine();
    newLine(); 
    System.out.println("Second line."); 
  }

Hoặc ta cũng có thể viết một phương thức mới khác, có tên threeLine, để in ra ba dòng trống:

  public static void threeLine() { 
    newLine(); newLine(); newLine(); 
  } 
  public static void main(String[] args) { 
    System.out.println("First line."); 
    threeLine(); 
    System.out.println("Second line."); 
  }

Bạn có thể nhận thấy vài điều sau từ chương trình trên:

  • Có thể kích hoạt cùng một phương thức nhiều lần.
  • Trong một phương thức, bạn có thể kích hoạt một phương thức khác. Ở trường hợp này,  main kích hoạt threeLine còn threeLine thì kích hoạt newLine.
  • Trong threeLine tôi đã viết ba câu lệnh trên cùng một dòng; đây là điều hoàn toàn hợp lệ (hãy nhớ lại rằng các dấu trống và dấu xuống dòng thường không làm thay đổi ý nghĩa của chương trình). Mặc dù ta nên đặt mỗi câu lệnh trên một dòng riêng, song đôi khi tôi vẫn phá vỡ nguyên tắc này.

Có thể bạn sẽ tự hỏi tại sao lại phiền phức tạo ra những phương thức mới như vậy. Có một vài lí do, mà hai lí do trong số đó thể hiện qua ví dụ trên là:

  1. Việc tạo phương thức mới cho ta cơ hội đặt tên cho một nhóm các câu lệnh. Những phương thức có thể làm đơn giản chương trình qua việc ẩn giấu những thao tác tính toán phức tạp phía sau một câu lệnh đơn giản, và qua việc dùng những từ tiếng Anh thay cho mã lệnh bí hiểm. Theo bạn, cách viết nào rõ ràng hơn, newLine hay System.out.println("")?
  2. Việc tạo phương thức mới có thể rút ngắn chương trình bằng cách loại bỏ những đoạn mã lệnh lặp đi lặp lại. Chẳng hạn, để in chín dòng trống liên tiếp, bạn chỉ cần kích hoạt threeLine đúng ba lần.

Ở mục 7.6 ta sẽ quay trở lại câu hỏi này đồng thời kể thêm một số lợi ích khác của việc chia nhỏ chương trình thành các phương thức.

3.6  Lớp và phương thức

Chắp nối lại những đoạn mã từ mục trước, ta có lời định nghĩa lớp như sau:

class NewLine { 
  public static void newLine() { 
    System.out.println(""); 
  } 
  public static void threeLine() { 
    newLine(); newLine(); newLine(); 
  } 
  public static void main(String[] args) { 
    System.out.println("First line."); 
    threeLine(); 
    System.out.println("Second line."); 
  } 
}

Dòng thứ nhất cho biết rằng đó là lời định nghĩa một lớp mới có tên NewLineLớp là tập hợp các phương thức có liên quan đến nhau. Trong trường hợp này, lớp với tên gọi NewLine có chứa 3 phương thức tên là newLinethreeLine, và main.

Một lớp khác mà ta đã gặp là lớp Math. Nó gồm các phương thức có tên sqrtsin, v.v. Khi kích hoạt một phương thức toán học, ta phải nêu tên của lớp (Math) và tên của phương thức. Đó là lý do mà về cú pháp, có điểm khác biệt nhỏ giữa các phương thức Java và các phương thức mà ta viết:

Math.pow(2.0, 10.0); 
newLine();

Câu lệnh thứ nhất kích hoạt phương thức pow trong lớp Math (để đưa đối số thứ nhất lên lũy thừa cấp của đối số thứ hai). Câu lệnh tiếp theo kích hoạt phương thức newLine, mà Java giả sử rằng nó có ở trong lớp mà ta đang (tức là lớp NewLine).

Nếu bạn thử kích hoạt nhầm một phương thức từ lớp khác, trình biên dịch sẽ phát sinh một lỗi. Chẳng hạn, nếu bạn gõ vào:

pow(2.0, 10.0);

Trình biên dịch sẽ nói kiểu như, “Không thể tìm thấy phương thức có tên pow trong lớp NewLine.” Nếu bạn từng thấy lời thông báo này và có lẽ đã tự hỏi rằng tại sao nó phải tìm pow trong lời định nghĩa lớp của bạn, thì bây giờ bạn đã biết rồi đó.

3.7  Chương trình có nhiều phương thức

Khi bạn nhìn vào lời định nghĩa một lớp có chứa nhiều phương thức, tất sẽ có xu hướng muốn đọc từ trên xuống dưới, nhưng điều này dễ gây nhầm lần, bởi đó không phải là thứ tự thực hiện chương trình.

Việc thực hiện (thực thi) luôn bắt đầu từ câu lệnh thứ nhất của main, bất kể nó nằm đâu trong chương trình (ở ví dụ này thì tôi đã cố ý đặt ở cuối cùng). Những câu lệnh được thực hiện lần lượt, theo thứ tự, đến khi bạn gặp một lời gọi (kích hoạt) phương thức. Việc kích hoạt phương thức cũng giống như lối rẽ khỏi luồng thực thi chương trình. Thay vì đi tiếp đến câu lệnh liền kề, bạn chuyển đến dòng lệnh đầu tiên được kích hoạt, thực hiện tất cả những câu lệnh ở đó, rồi quay lại và tiếp tục tại điểm đã rẽ ngang.

Điều này nghe thật đơn giản, song bạn vẫn cần nhớ rằng một phương thức có thể kích hoạt phương thức khác. Bởi vậy, khi ta đang ở đoạn giữa của main, ta có thể buộc phải dời đi để thực hiện những câu lệnh trong threeLine. Như trong khi thực thi threeLine, có ba lần ta bị gián đoạn và phải dời đi và thực hiện newLine.

Về phần mình, newLine kích hoạt println, và tạo thêm một lối rẽ nữa. Thật may là Java rất khéo theo dõi vị trí đang thực thi, nên khi println hoàn thành, công việc lại được trả về đúng chỗ mà vừa rời khỏi newLine, và sau đó thì trở lại threeLine, rồi sau cùng trở lại main để chương trình có thể kết thúc.

Xét về khía cạnh kĩ thuật, chương trình chưa kết thúc sau main. Thay vì vậy, luồng thực thi tìm đến chỗ mà nó dời khỏi chương trình đã kích hoạt main, tức là trình thông dịch Java. Trình thông dịch này đảm nhiệm các việc như xóa cửa sổ và dọn dẹp nói chung, rồi sau đó chương trình mới kết thúc.

Vậy nghĩa lí của toàn bộ những thứ lằng nhằng này là gì? Khi đọc một chương trình, bạn đừng đọc từ trên xuống dưới, mà phải đọc theo luồng thực thi.

3.8  Tham số và đối số

Có những phương thức ta đã dùng yêu cầu phải có đối số, vốn là những giá trị mà bạn cần cung cấp để có thể kích hoạt được chúng. Chẳng hạn, để tìm sin của một số, bạn phải cung cấp số đó. Như vậy, sin đã nhận đối số là một double. Để in ra một chuỗi, bạn phải cung cấp chuỗi đó, vì vậy println nhận đối số là một String.

Lại có những phương thức nhận nhiều đối số; chẳng hạn, pow nhận hai double, đó là cơ số và số mũ.

Khi bạn dùng một phương thức, bạn phải cung cấp đối số. Khi bạn viết một phương thức, bạn cung cấp một danh sách các tham số (hay tham biến). Một tham số là một biến để chứa một đối số. Danh sách các tham biến chỉ định rằng cần phải có những đối số nào.

Chẳng hạn, printTwice chỉ định một tham số duy nhất, s, vốn có kiểu String. Tôi đặt tên nó là s để gợi nhớ rằng đó là một String, song tôi cũng có thể đặt bất kì tên biến hợp lệ nào cho nó.

  public static void printTwice(String s) { 
    System.out.println(s); 
    System.out.println(s); 
  }

Khi kích hoạt printTwice, ta phải cung cấp một đối số duy nhất có kiểu String.

    printTwice("Don't make me say this twice!");

Khi bạn kích hoạt một phương thức, đối số mà bạn cung cấp được dùng để gán cho các tham số. Trong trường hợp này, đối số "Don’t make me say this twice!" được gán cho tham số s. Quá trình này được gọi là truyền tham số vì giá trị được truyền từ bên ngoài phương thức vào bên trong.

Một đối số có thể là biểu thức bất kì, vì vậy nếu bạn có một biến String thì  có thể dùng chính biến này làm đối số:

    String argument = "Never say never."; 
    printTwice(argument);

Giá trị mà bạn cung cấp làm đối số sẽ phải có cùng kiểu với tham số. Chẳng hạn, nếu bạn thử dòng lệnh sau:

    printTwice(17);

Bạn sẽ nhận được thông báo lỗi kiểu như “cannot find symbol” (không tìm thấy kí hiệu); thông báo này không mấy hữu ích. Lí do là Java đang tìm một phương thức có tên printTwice mà có thể nhận đối số là số nguyên. Vì chẳng có phương thức nào như vậy nên nó không thể tìm thấy “kí hiệu” đó.

System.out.println chấp nhận được tham số thuộc kiểu dữ liệu bất kì. Nhưng phương thức này chỉ là một ngoại lệ; đại đa số các phương thức thì không dễ tính như vậy.

3.9  Biểu đồ ngăn xếp

Các tham số và những biến khác chỉ tồn tại trong phương thức riêng của chúng. Trong phạm vi của main, không có cái gì gọi là s. Nếu bạn thử dùng biến này, trình biên dịch sẽ phản đối. Tương tự, trong printTwice không có thứ gì gọi là argument cả.

Một cách theo dõi xem những biến nào được sử dụng ở đâu là dùng một biểu đồ ngăn xếp. Với ví dụ trên, biểu đồ ngăn xếp sẽ như sau:

Mỗi phương thức đều có một hộp màu xám gọi là khung., trong đó chứa các tham số và biến của phương thức. Tên của phương thức được ghi bên ngoài khung. Như thường lệ, giá trị của mỗi biến lại được viết trong một hộp cùng với tên biến ghi bên cạnh.

3.10  Phương thức có nhiều tham số

Có một lý do thường gây ra lỗi khi lập trình: đó chính là cú pháp để miêu tả và kích hoạt phương thức gồm nhiều tham số. Trước hết, hãy nhớ rằng bạn phải khai báo kiểu của từng tham số. Chẳng hạn

  public static void printTime(int hour, int minute) { 
    System.out.print(hour); 
    System.out.print(":"); 
    System.out.println(minute); 
  }

Rất dễ bị lôi cuốn theo cách viết int hour, minute, nhưng cách này chỉ đúng với việc khai báo biến, chứ không phải với danh sách tham số.

Một lý do khác gây nhầm lẫn là bạn không cần phải khai báo kiểu của đối số. Viết như dưới đây là sai!

    int hour = 11; 
    int minute = 59; 
    printTime(int hour, int minute); // SAI!

Trong trường hợp này, Java có thể tự biết kiểu của hour và minute khi nhìn vào đoạn khai báo của chúng. Ta không cần phải kèm thêm kiểu của biến khi truyền chúng làm đối số. Cú pháp đúng phải là  printTime(hour, minute).

3.11  Các phương thức trả lại kết quả

Một số phương thức ta đang dùng, như các phương thức của lớp Math, đều trả lại kết quả. Những phương thức khác, như  println và newLine, đều thực hiện một thao tác nhưng không trả lại kết quả nào. Điều này nảy sinh một số câu hỏi sau:

  • Điều gì sẽ xảy ra nếu nếu bạn kích hoạt một phương thức mà không làm gì với kết quả (nghĩa là bạn không gán nó vào một biến hay không dùng kết quả này làm bộ phận trong một biểu thức lớn hơn)?
  • Điều gì sẽ xảy ra nếu bạn dùng một phương thức print như một phần của biểu thức lớn hơn, chẳng hạn  System.out.println("boo!") + 7?
  • Ta có thể viết những phương thức để trả lại giá trị không, hay chỉ loanh quanh với những phương thức kiểu như newLine và printTwice?

Lời giải đáp đối với câu hỏi thứ ba là “Có, bạn có thể viết những phương thức để trả lại giá trị,” mà ta sẽ thấy cách làm sau một vài chương nữa. Tôi sẽ để cho bạn tự trả lời hai câu hỏi còn lại bằng cách thực hành trực tiếp. Thật ra, bất kì lúc nào bạn đặt ra câu hỏi về sự hợp lệ hay không hợp lệ của thao tác trong Java, thì một cách hay để tìm hiểu là đi hỏi trình biên dịch.

3.12  Thuật ngữ

khởi tạo:
Câu lệnh nhằm khai báo một biến đồng thời gán giá trị cho nó.
dấu phẩy động:
Một kiểu của biến (hoặc giá trị) có thể chứa cả số có phần thập phân lẫn số nguyên. Kiểu dấu phẩy động mà ta sẽ dùng là double.
lớp:
Một tập hợp được đặt tên, có chứa các phương thức. Đến giờ ta đã dùng lớp Math và lớp System, và cũng viết được các lớp có tên Hello và NewLine.
phương thức:
Một loạt những câu lệnh nhằm thực hiện một chức năng có ích. Phương thức được đặt tên. Nó có thể nhận hoặc không nhận  tham số, đồng thời có thể trả lại hoặc không trả một giá trị.
tham số:
Một đơn vị thông tin mà phương thức yêu cầu trước khi nó có thể được thực hiện. Tham số là các biến: chúng chứa những giá trị và có kiểu riêng.
đối số:
Giá trị mà bạn cung cấp khi bạn kích hoạt một phương thức. Giá trị này phải có cùng kiểu với tham số tương ứng.
khung:
Một cấu trúc (biểu diễn bởi khối chữ nhật màu xám trong biểu đồ ngăn xếp) có chứa các tham số và biến của một phương thức.
kích hoạt:
Làm cho phương thức được thực thi.

3.13  Bài tập

Bài tập 1

Hãy vẽ một khung ngăn xếp để biểu diễn trạng thái chương trình ở Mục 3.10 khi main kích hoạt printTime với các đối số 11 và 59.

Bài tập 2

Mục đích của bài tập này là luyện đọc mã lệnh để đảm bảo rằng bạn hiểu được luồng thực thi của chương trình gồm nhiều phương thức khác nhau.

  1. Kết quả của chương trình sau là gì? Hãy nói chính xác vị trí các dấu trống và các chỗ xuống dòng. GỢI Ý: Bắt đầu bằng việc diễn tả bằng lời xem ping và baffle làm những gì khi chúng được kích hoạt.
  2. Hãy vẽ một biểu đồ ngăn xếp biểu diễn trạng thái của chương trình khi ping được kích hoạt lần đầu.
  public static void zoop() { 
    baffle(); 
    System.out.print("You wugga "); 
    baffle(); 
  } 
  public static void main(String[] args) { 
    System.out.print("No, I "); 
    zoop(); 
    System.out.print("I "); 
    baffle(); 
  } 
  public static void baffle() { 
    System.out.print("wug"); 
    ping(); 
  } 
  public static void ping() { 
    System.out.println("."); 
  }

Bài tập 3

Mục đích của bài tập này là đảm bảo hiểu được cách viết và cách kích hoạt phương thức nhận tham số.

  1. Hãy viết dòng đầu tiên của một phương thức có tên zool nhận vào ba tham số: một int và hai String.
  2. Hãy viết một dòng lệnh  zool, truyền làm tham số các giá trị sau: 11, tên của con thú cưng lần đầu bạn nuôi, và tên của dãy phố mà bạn sống thời thơ ấu.

Bài tập 4

Mục đích của bài tập này là lấy đoạn mã từ một bài tập trước rồi bao gói nó vào trong một phương thức có nhận tham số. Bạn nên tìm một lời giải hoàn chỉnh cho Bài tập 2 để bắt đầu.

  1. Hãy viết một phương thức có tên printAmerican để nhận ngày, tháng, năm làm các tham số rồi in chúng ra dưới dạng quy định của Mỹ.
  2. Kiểm tra phương thức của bạn bằng cách kích hoạt nó từ main rồi truyền các đối số phù hợp. Kết quả phải trông giống như sau (chỉ trừ số ngày có thể khác đi):
    Saturday, July 16, 2011
  3. Một khi bạn đã gỡ lỗi xong cho printAmerican, hãy viết một phương thức khác có tên printEuropean để in ra ngày tháng theo quy chuẩn châu Âu.

3 phản hồi

Filed under Think Java

3 responses to “Chương 3: Phương thức rỗng

  1. Pingback: Think Java: Cách suy nghĩ như nhà khoa học máy tính | Blog của Chiến

  2. Cảm ơn Chiến nhé ! …. Tài Liệu hay lắm

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s