You are on page 1of 5

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ạimain để 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.

You might also like