Chương này giải thích các cú pháp cơ bản của ngôn ngữ lập trình Java. Tôi sẽ giả định rằng bạn đã viết một số chương trình Java đơn giản. Mặt khác, đọc " Giới thiệu về lập trình Java cho lập trình viên lần đầu ".
Để thành thạo một ngôn ngữ lập trình, bạn cần nắm vững hai điều:
- Các cú pháp của ngôn ngữ lập trình: Không quá khó để tìm hiểu một nhóm nhỏ các từ khóa và cú pháp. Ví dụ, JDK 1.8 có 48 từ khóa; C11 có 44 và C ++ 11 có 73.
- Các thư viện Giao diện chương trình ứng dụng (API) được liên kết với ngôn ngữ: Bạn không muốn tự mình viết mọi thứ. Thay vào đó, bạn có thể sử dụng lại mã có sẵn trong thư viện. Việc nghiên cứu các library (thư viện có sẵn) có thể khó khăn vì nó thực sự rất lớn, nhưng việc chúng ta làm quen và tìm hiểu nó là điều cần thiết để phát triển các ứng dụng.
Bài viết sẽ hướng dẫn bạn các kiến thức cơ bản sau:
1. Cú pháp cơ bản: biến, kiểu dữ liệu, lệnh in ra màn hình
2. Cấu trúc điều kiện: if, else if, switch
3. Cấu trúc vòng lặp: for, while, do while
4. Mảng và Chuỗi
5. Phương thức
Sau đây chúng ta sẽ lần lượt đi qua từng phần một :)
9. String và char operations
9.1 char Arithmetic Operations
Nhớ lại rằng bạn đã từng biết tới bảng mã ASCII khi học C. Java cũng tương tự:
- Trong Java, mỗi cái
char
được biểu thị bằng số Unicode 16 bit. Ví dụ, char
'0'
được biểu thị bằng mã số 48
( 30H
), char
'1'
bởi 49
( 31H
), char
'A'
bởi 65
( 41H
). char
'a'
bởi 97
( 61H
). Hãy lưu ý rằng char
'0'
KHÔNG int 0
, char
'1'
KHÔNG int 1
.
char
s có thể tham gia vào các hoạt động số học. A char
được coi là cơ sở của nó int
(trong phạm vi [0, 65535]
) trong các phép toán số học. Nói cách khác, char
và int
có thể thay thế cho nhau. char '0' ⇔ int 48
, char '1' ⇔ int 49
, char 'A' ⇔ int 65
,char 'a' ⇔ int 97
. Ví dụ như,
char c1 = '0';
char c2 = 'A';
char c3;
System.out.println((int)c1);
System.out.println((int)c2);
c3 = 97;
System.out.println(c3);
System.out.println((char)97);
- Trong các phép toán số học,
char
(và byte
, và short
) trước tiên được chuyển đổi thành int
. Trong Java, phép tính số học chỉ được thực hiện tại int
, long
, float
, hoặc double
; KHÔNG trong byte
, short
và char
.
- Do đó,
char ⊕ char ⇒ int ⊕ int ⇒ int
nơi ⊕
biểu thị một hoạt động số học nhị phân (ví dụ như +
, -
, *
, /
và %
). Bạn có thể cần phải đưa kết quả rõ ràng int
trở lạichar
. Ví dụ như,
char c1 = '0';
char c2 = 'A';
char c3;
//c3 = c1 + c2;
c3 = (char)(c1 + c2);
System.out.println(c3);
System.out.println(c1 + c2);
System.out.println((char)(c1 + c2));
- Tương tự ,
char ⊕ int ⇒ int ⊕ int ⇒ int
. Bạn có thể cần phải rõ ràng bỏ kết quả int
trở lại char
. Ví dụ như
char c1 = '0';
char c2 = 'A';
char c3;
//c3 = c1 + 5;
c3 = (char)(c1 + 5);
System.out.println(c3);
System.out.println(c1 + 5);
for (int codeNum = 'a'; codeNum <= 'z'; ++codeNum) {
System.out.println((char)codeNum + ": " + codeNum);
}
- Tuy nhiên, đối với các toán tử kết hợp (ví dụ như
+=
, -=
, *=
, /=
, %=
), việc đánh giá được thực hiện theo int
, nhưng kết quả được đúc trở lại LHS tự động. Ví dụ như,
char c4 = '0';
c4 += 5;
System.out.println(c4);
- Đối với tăng (
++
) và giảm ( --
) của char
(và byte
, và short
), không có khuyến mãi nào int
. Ví dụ như,
for (char c = '0'; c <= '9'; ++c) {
System.out.println(c);
}
9.2 Converting char to int
Bạn có thể chuyển đổi char
'0'
để '9'
để int
0
đến 9
bằng cách trừ char
với các cơ sở '0'
, ví dụ '8' - '0' ⇒ 8
.
Đó là, giả sử c
là một char
giữa '0'
và '9'
, (c - '0')
là tương ứng int
0
với 9
.
Chương trình sau minh họa cách chuyển đổi một ký tự thập lục phân ( 0-9
, A-F
hoặc a-f
) thành số thập phân tương đương ( 0-15
), bằng cách trừ đi cơ sở thích hợp char
.
char hexChar = 'a';
int dec;
if (hexChar >= '0' && hexChar <= '9') {
dec = hexChar - '0';
} else if (hexChar >= 'A' && hexChar <= 'F') {
dec = hexChar - 'A' + 10;
} else if (hexChar >= 'a' && hexChar <= 'f') {
dec = hexChar - 'a' + 10;
} else {
dec = -1;
System.out.println("Invalid hex char");
}
System.out.println(hexChar + ": " + dec);
9.3 String Operations
Nhất thường được sử dụng String
phương pháp này như sau, giả sử rằng str
, str1
, str2
là String
các biến:
str.length()
: trả về độ dài của str
.
str.charAt(int index)
: trả lại char
tại index
vị trí của str
. Hãy lưu ý rằng index
bắt đầu tại 0
, và lên đến str.length()-1
.
str1.equals(str2)
: để so sánh nội dung của str1
và str2
. Lưu ý rằng bạn không thể sử dụng "str1 == str2"
để so sánh hai String
s. Điều này là do " ==
" chỉ áp dụng cho các loại nguyên thủy, nhưng String
không phải là loại nguyên thủy.
Ví dụ như,
String str = "Java is cool!";
System.out.println(str.length());
System.out.println(str.charAt(2));
System.out.println(str.charAt(5));
String anotherStr = "Java is COOL!";
System.out.println(str.equals(anotherStr));
System.out.println(str.equalsIgnoreCase(anotherStr));
System.out.println(anotherStr.equals(str));
System.out.println(anotherStr.equalsIgnoreCase(str));
Để kiểm tra tất cả các phương thức có sẵn cho String
, hãy mở Tài liệu JDK ⇒ Chọn "Tài liệu API" Nhấp vào "FRAMES" (menu trên cùng) Từ "Mô-đun" (ngăn trên cùng bên trái), chọn " java.base
" Từ " java.base
Gói" (trên cùng bên trái khung), chọn " java.lang
" Từ "Lớp" (khung dưới cùng bên trái), chọn " String
" chọn "TÓM TẮT" "PHƯƠNG PHÁP" (khung bên phải) (@ https://docs.oracle.com/javase/10/docs /api/java/lang/String.html cho JDK 10).
Ví dụ như,
String str = "Java is cool!";
System.out.println(str.length());
System.out.println(str.charAt(2));
System.out.println(str.substring(0, 3));
System.out.println(str.indexOf('a'));
System.out.println(str.lastIndexOf('a'));
System.out.println(str.endsWith("cool!"));
System.out.println(str.toUpperCase());
System.out.println(str.toLowerCase());
9.4 Converting String to Primitive
Chuỗi thành int / byte / short / long
Bạn có thể sử dụng các phương thức dựng sẵn JDK để chuyển đổi một hàm chứa số nguyên hợp lệ (ví dụ: " ") thành một (ví dụ :). Thời gian chạy kích hoạt a nếu chuỗi đầu vào không chứa một số nguyên hợp lệ (ví dụ: " ").
Ví dụ, Integer.parseInt(anIntStr)
String
1234
int
1234
NumberFormatException
abc
String inStr = "5566";
int number = Integer.parseInt(inStr);
//number = Integer.parseInt("abc");
Similarly, you could use methods Byte.parseByte(aByteStr)
, Short.parseShort(aShortStr)
, Long.parseLong(aLongStr)
to convert a String
containing a valid byte
, short
or long
literal to the primitive type.
String to double/float
Bạn cũng có thể dùng
Double.parseDouble(aDoubleStr)
hoặc Float.parseFloat(aFloatStr)
để đổi một String
sang double
or float
, e.g.
String inStr = "55.66";
float aFloat = Float.parseFloat(inStr);
double aDouble = Double.parseDouble("1.2345");
aDouble = Double.parseDouble("1.2e-3");
//aDouble = Double.parseDouble("abc");
String to char
Bạn cũng có thể dung aStr.charAt(index)
để extract một ký tự từ chuỗi String
, trong đó index
băt đầu 0
cho tới aStr.length()-1
, e.g.,
String msg = "Hello, world";
char msgChar;
for (int idx = 0; idx < msg.length(); ++idx) {
msgChar = msg.charAt(idx);
.......
}
String to boolean
Bạn cũng có thể dùng Boolean.parseBoolean(aBooleanStr)
để chuyển đổi giá trị String "true
" or "false
" sang boolean
true
or false
, e.g.,
String boolStr = "true";
boolean done = Boolean.parseBoolean(boolStr);
boolean valid = Boolean.parseBoolean("false");
9.5 Converting Primitive to String
Để chuyển đổi một nguyên thủy thành a String
, bạn có thể:
- Sử dụng
+
toán tử '' để ghép nối nguyên thủy với một khoảng trống String ""
.
- Sử dụng các phương thức tích hợp JDK , áp dụng cho tất cả các nguyên hàm.
String.valueOf(aPrimitve)
- Sử dụng các
toString()
phương thức của lớp wrapper tương ứng, chẳng hạn như , , , vvInteger.toString(anInt)
Double.toString(aDouble)
Character.toString(aChar)
Boolean.toString(aBoolean)
Ví dụ như,
String str1 = 123 + "";
String str2 = 12.34 + "";
String str3 = 'c' + "";
String str4 = true + "";
String str5 = String.valueOf(12345);
String str6 = String.valueof(true);
String str7 = String.valueOf(55.66);
String str8 = Integer.toString(1234);
String str9 = Double.toString(1.23);
String str10 = Character.toString('z');
9.6 Formatting String - String.format()
Hãy nhớ lại rằng bạn có thể sử dụng printf()
để tạo một chuỗi được định dạng và gửi nó đến bảng điều khiển hiển thị, ví dụ:
System.out.printf("Hi, %d, %.1f%n", 11, 22.22);
Có một hàm tương tự được gọi là String.format()
trả về chuỗi được định dạng, thay vì gửi đến bàn điều khiển, ví dụ:
String str = String.format("%.1f", 1.234);
String.format()
có dạng tương tự như printf()
.
9.7 Code Example: Reverse String
Chương trình sau sẽ nhắc người dùng một chuỗi và in chuỗi đầu vào theo thứ tự ngược lại. Ví dụ như,
Enter a String: abcdefg
The reverse is: gfedcba
import java.util.Scanner;
public class ReverseString {
public static void main(String[] args) {
String inStr;
int inStrLen;
Scanner in = new Scanner(System.in);
System.out.print("Enter a String: ");
inStr = in.next();
inStrLen = inStr.length();
System.out.print("The reverse is: ");
for (int inCharIdx = inStrLen - 1; inCharIdx >= 0; --inCharIdx) {
System.out.print(inStr.charAt(inCharIdx));
}
System.out.println();
in.close();
}
}
9.8 Exercises on String and char operations
LINK
10. Arrays
Giả sử rằng bạn muốn tìm trung bình của các nhãn hiệu cho một lớp là 30 sinh viên, bạn chắc chắn không muốn để tạo ra 30 biến: mark1
, mark2
, ..., mark30
. Thay vào đó, Bạn có thể sử dụng một biến duy nhất, được gọi là một mảng , với 30 phần tử (hoặc các mục).
Mảng là một tập hợp các phần tử cùng loại , được xác định bởi một cặp dấu ngoặc vuông [ ]
. Để sử dụng một mảng, bạn cần:
- Khai báo mảng với tên và kiểu . Sử dụng tên số nhiều cho mảng, ví dụ
marks
, rows
, numbers
. Tất cả các yếu tố của mảng thuộc về cùng một loại.
- Phân bổ mảng bằng
new
toán tử hoặc thông qua khởi tạo , ví dụ:
int[] marks;
int marks[];
marks = new int[5];
int[] factors = new int[20];
int[] numbers = {11, 22, 33, 44, 55, 66};
Khi một mảng được xây dựng thông qua new
toán tử, tất cả các phần tử được khởi tạo thành giá trị mặc định của chúng, ví dụ: 0
for int
, 0.0
for double
, false
for boolean
và null
cho các đối tượng. [Không giống như C / C ++, không khởi tạo nội dung mảng.]
Khi một mảng được khai báo nhưng không được phân bổ, nó có một giá trị đặc biệt được gọi null
.
10.1 Array Index - Chỉ Số Mảng
Bạn có thể tham khảo một phần tử của một mảng thông qua một chỉ mục (hoặc chỉ mục ) được đặt trong dấu ngoặc vuông [ ]
. Chỉ số mảng của Java bắt đầu bằng zero ( 0
). Ví dụ, giả sử rằng marks
là một int
mảng của 5 yếu tố, sau đó 5 yếu tố là: marks[0]
, marks[1]
, marks[2]
, marks[3]
, và marks[4]
.
int[] marks = new int[5];
marks[0] = 95;
marks[1] = 85;
marks[2] = 77;
marks[3] = 69;
marks[4] = 66;
System.out.println(marks[0]);
System.out.println(marks[3] + marks[4]);
10.2 Array's length
Để tạo một mảng, bạn cần biết trước chiều dài (hoặc kích thước ) của mảng và phân bổ tương ứng. Khi một mảng được tạo, độ dài của nó được cố định và không thể thay đổi trong thời gian chạy. Đôi khi, thật khó để xác định độ dài của một mảng (ví dụ: có bao nhiêu sinh viên?). Tuy nhiên, bạn cần ước tính độ dài và phân bổ giới hạn trên. Giả sử bạn đặt độ dài thành 30 (đối với một lớp sinh viên) và có 31 sinh viên, bạn cần phân bổ một mảng mới (có độ dài 31), sao chép mảng cũ sang mảng mới và xóa mảng cũ. Nói cách khác, độ dài của một mảng không thể được điều chỉnh động trong thời gian chạy. Đây có lẽ là nhược điểm chính của việc sử dụng một mảng. (Có các cấu trúc khác có thể được điều chỉnh động.)
Trong Java, độ dài của mảng được giữ trong một biến liên quan được gọi length
và có thể được truy xuất bằng cách sử dụng " arrayName.length
", ví dụ:
int[] factors = new int[5];
int numFactors = factors.length;
The index of an array is between
0
and
arrayName.length - 1
.
Chỉ số của một mảng là giữa 0
và arrayName.length - 1
.
Không giống như các ngôn ngữ như C / C ++, Java thực hiện kiểm tra ràng buộc chỉ mục mảng trong thời gian chạy . Nói cách khác, đối với mỗi tham chiếu đến một phần tử mảng, chỉ mục được kiểm tra đối với mảng length
. Nếu chỉ mục nằm ngoài phạm vi [0, arrayName.length-1]
, Java Runtime sẽ báo hiệu một ngoại lệ được gọi ArrayIndexOutOfBoundException
. Điều quan trọng cần lưu ý là việc kiểm tra mảng liên kết chỉ số tiêu thụ năng lượng tính toán, chắc chắn sẽ làm chậm quá trình xử lý. Tuy nhiên, những lợi ích đạt được về mặt kỹ thuật phần mềm tốt vượt trội về tốc độ.
10.3 Array and Loop
Mảng làm việc chặt chẽ với các vòng lặp. Bạn có thể xử lý tất cả các phần tử của một mảng thông qua một vòng lặp, ví dụ,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class MeanSDArray {
public static void main(String[] args) {
int[] marks = {74, 43, 58, 60, 90, 64, 70};
int sum = 0;
int sumSq = 0;
double mean, stdDev;
for (int i = 0; i < marks.length; ++i) {
sum += marks[i];
sumSq += marks[i] * marks[i];
}
mean = (double)sum / marks.length;
stdDev = Math.sqrt((double)sumSq / marks.length - mean * mean);
System.out.printf("Mean is: %.2f%n", mean);
System.out.printf("Standard deviation is: %.2f%n", stdDev);
}
}
|
10.4 Enhanced for-loop (or "for-each" Loop) (JDK 5)
JDK 5 introduces a new loop syntax known as enhanced for-loop (or for-each loop) to facilitate processing of arrays and collections. It takes the following syntax:
Syntax | Example |
for (type item : anArray) {
body ;
}
| int[] numbers = {8, 2, 6, 4, 3};
int sum = 0, sumSq = 0;
for (int number : numbers) {
sum += number;
sumSq += number * number;
}
System.out.println("The sum is: " + sum);
System.out.println("The square sum is: " + sumSq);
|
Vòng lặp này sẽ được đọc là "cho mỗi phần tử trong mảng ...". Vòng lặp thực thi một lần cho mỗi phần tử trong mảng, với giá trị của phần tử được sao chép vào biến khai báo. Vòng lặp for-every thuận tiện để chuyển đổi tất cả các phần tử của một mảng. Nó đòi hỏi ít dòng mã hơn, loại bỏ bộ đếm vòng lặp và chỉ mục mảng và dễ đọc hơn. Tuy nhiên, đối với mảng các kiểu nguyên thủy (ví dụ: mảng int
s), nó chỉ có thể đọc các phần tử và không thể sửa đổi nội dung của mảng. Điều này là do giá trị của mỗi phần tử được sao chép vào biến của vòng lặp, thay vì làm việc trên bản sao gốc của nó.
Trong nhiều tình huống, bạn chỉ muốn chuyển qua mảng và đọc từng phần tử. Đối với những trường hợp này, vòng lặp for nâng cao được ưa thích và khuyên dùng hơn các cấu trúc vòng lặp khác.
10.5 Code Example: Read and Print Array
Chương trình sau sẽ nhắc người dùng về độ dài và tất cả các thành phần của một mảng và in mảng đó dưới dạng [a0, a1, ..., an]
. Ví dụ như,
Enter the number of items: 5
Enter the value of all items (separated by space): 7 9 1 6 2
The values are: [7, 9, 1, 6, 2]
import java.util.Scanner;
public class ReadPrintArray {
public static void main(String[] args) {
int numItems;
int[] items;
Scanner in = new Scanner(System.in);
System.out.print("Enter the number of items: ");
numItems = in.nextInt();
items = new int[numItems];
if (items.length > 0) {
System.out.print("Enter the value of all items (separated by space): ");
for (int i = 0; i < items.length; ++i) {
items[i] = in.nextInt();
}
}
System.out.print("The values are: [");
for (int i = 0; i < items.length; ++i) {
if (i == 0) {
System.out.print(items[0]);
} else {
System.out.print(", " + items[i]);
}
}
System.out.println("]");
in.close();
}
}
Arrays.toString() (JDK 5)
JDK 5 provides an built-in methods called Arrays.toString(anArray)
, which returns a String
in the form [a0, a1, ..., an]
. You need to import java.util.Arrays
. For examples,
import java.util.Arrays;
public class TestArrayToString {
public static void main(String[] args) {
int[] a1 = {6 ,1, 3, 4, 5};
int[] a2 = {};
double[] a3 = new double[1];
System.out.println(Arrays.toString(a1));
System.out.println(Arrays.toString(a2));
System.out.println(Arrays.toString(a3));
a3[0] = 2.2;
System.out.println(Arrays.toString(a3));
}
}
10.6 Code Example: Horizontal and Vertical Histograms
Chương trình sau đây sẽ nhắc người dùng về số lượng sinh viên và cấp độ của từng sinh viên. Sau đó, nó in biểu đồ, ở dạng ngang và dọc, như sau:
Enter the grade for student 1: 98
Enter the grade for student 2: 100
Enter the grade for student 3: 9
Enter the grade for student 4: 3
Enter the grade for student 5: 56
Enter the grade for student 6: 58
Enter the grade for student 7: 59
Enter the grade for student 8: 87
0- 9: **
10- 19:
20- 29:
30- 39:
40- 49:
50- 59: ***
60- 69:
70- 79:
80- 89: *
90-100: **
*
* * *
* * * *
0-9 10-19 20-29 30-39 40-49 50-59 60-69 70-79 80-89 90-100
import java.util.Scanner;
import java.util.Arrays;
public class GradesHistograms {
public static void main(String[] args) {
int numStudents;
int[] grades;
int[] bins = new int[10];
Scanner in = new Scanner(System.in);
System.out.print("Enter the number of students: ");
numStudents = in.nextInt();
grades = new int[numStudents];
for (int i = 0; i < grades.length; ++i) {
System.out.print("Enter the grade for student " + (i + 1) + ": ");
grades[i] = in.nextInt();
}
System.out.println(Arrays.toString(grades));
for (int grade : grades) {
if (grade == 100) {
++bins[9];
} else {
++bins[grade/10];
}
}
System.out.println(Arrays.toString(bins));
for (int binIdx = 0; binIdx < bins.length; ++binIdx) {
if (binIdx != 9) {
System.out.printf("%2d-%3d: ", binIdx*10, binIdx*10+9);
} else {
System.out.printf("%2d-%3d: ", 90, 100);
}
for (int itemNo = 0; itemNo < bins[binIdx]; ++itemNo) {
System.out.print("*");
}
System.out.println();
}
int binMax = bins[0];
for (int binIdx = 1; binIdx < bins.length; ++binIdx) {
if (binMax < bins[binIdx]) binMax = bins[binIdx];
}
for (int level = binMax; level > 0; --level) {
for (int binIdx = 0; binIdx < bins.length; ++binIdx) {
if (bins[binIdx] >= level) {
System.out.print(" * ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
for (int binIdx = 0; binIdx < bins.length; ++binIdx) {
System.out.printf("%3d-%-3d", binIdx*10, (binIdx != 9) ? binIdx * 10 + 9 : 100);
}
System.out.println();
in.close();
}
}
Ghi chú:
- Chúng tôi sử dụng hai mảng trong bài tập này, một mảng để lưu trữ các lớp của học sinh (có độ dài
numStudents
) và mảng còn lại để lưu trữ số lượng biểu đồ (độ dài 10
).
- Chúng tôi sử dụng một
10
-element int
mảng gọi là bins
, để giữ đếm histogram cho lớp của [0, 9]
, [10, 19]
, ..., [90, 100]
. Hãy lưu ý rằng có 101
các lớp giữa [0, 100]
và thùng cuối cùng có 11
các lớp (thay vì 10 cho phần còn lại). Các bins
chỉ số của là grade/10
, ngoại trừ grade
của 100
.
10.7 Multi-Dimensional Array
Trong Java, bạn có thể khai báo một mảng các mảng. Ví dụ như:
int grid[][] = new int[12][8];
grid[0][0] = 8;
grid[1][1] = 5;
System.out.println(grid.length);
System.out.println(grid[0].length);
System.out.println(grid[11].length);
Trong ví dụ trên, grid
là một mảng gồm 12 phần tử. Mỗi phần tử ( grid[0]
đến grid[11]
) là một int
mảng 8 phần tử . Nói cách khác, grid
là "mảng 12 phần tử" của "mảng int 8 phần tử". Do đó, grid.length
cho 12
và grid[0].length
cho 8
.
public class Array2DTest {
public static void main(String[] args) {
int[][] grid = new int[12][8];
int numRows = grid.length;
int numCols = grid[0].length;
for (int row = 0; row < numRows; ++row) {
for (int col = 0; col < numCols; ++col) {
grid[row][col] = row*numCols + col + 1;
}
}
for (int row = 0; row < numRows; ++row) {
for (int col = 0; col < numCols; ++col) {
System.out.printf("%3d", grid[row][col]);
}
System.out.println();
}
}
}
Nói chính xác, Java không hỗ trợ mảng đa chiều trực tiếp. Đó là, nó không hỗ trợ cú pháp grid[3, 2]
như một số ngôn ngữ. Hơn nữa, có thể các mảng trong một mảng có độ dài khác nhau.
Hãy lưu ý rằng cách đúng để xem "mảng mảng" như được hiển thị, thay vì coi nó như một bảng 2D, ngay cả khi tất cả các mảng có cùng độ dài.
Ví dụ,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| public class Array2DWithDifferentLength {
public static void main(String[] args) {
int[][] grid = {
{1, 2},
{3, 4, 5},
{6, 7, 8, 9}
};
for (int y = 0; y < grid.length; ++y) {
for (int x = 0; x < grid[y].length; ++x) {
System.out.printf("%2d", grid[y][x]);
}
System.out.println();
}
int[][] grid1 = new int[3][];
grid1[0] = new int[2];
grid1[1] = new int[3];
grid1[2] = new int[4];
for (int y = 0; y < grid1.length; ++y) {
for (int x = 0; x < grid1[y].length; ++x) {
System.out.printf("%2d", grid1[y][x]);
}
System.out.println();
}
}
}
|
11. Methods (Functions)
11.1 Why Methods?
Đôi khi, một phần mã nhất định phải được sử dụng nhiều lần. Thay vì viết lại mã nhiều lần, tốt hơn là đặt chúng vào "chương trình con" và "gọi" "chương trình con" này nhiều lần - để dễ bảo trì và hiểu. Chương trình con được gọi là phương thức (trong Java) hoặc hàm (trong C / C ++).
Lợi ích của việc sử dụng các phương pháp là:
- Phân chia và chinh phục : Xây dựng chương trình từ các phần hoặc thành phần đơn giản, nhỏ. Mô đun hóa chương trình thành các nhiệm vụ độc lập.
- Tránh lặp lại mã : Rất dễ sao chép và dán, nhưng khó duy trì và đồng bộ hóa tất cả các bản sao.
- Tái sử dụng phần mềm : Bạn có thể sử dụng lại các phương thức trong các chương trình khác, bằng cách đóng gói chúng vào mã thư viện (hoặc API).
11.2 Using Methods
Hai bên tham gia vào việc sử dụng một phương thức: một người gọi , người gọi (hoặc gọi ) phương thức và phương thức được gọi.
Quá trình là:
- Người gọi gọi một phương thức và truyền đối số cho phương thức.
- Phương pháp:
- nhận được các đối số được thông qua bởi người gọi,
- thực hiện các hoạt động được lập trình được xác định trong phần thân của phương thức và
- trả về một kết quả cho người gọi
- Người gọi nhận được kết quả và tiếp tục các hoạt động của nó.
Ví dụ: Giả sử rằng chúng ta cần đánh giá diện tích của một vòng tròn nhiều lần, tốt hơn là viết một phương thức được gọi getArea()
và sử dụng lại nó khi cần.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| public class EgMethodGetArea {
public static void main(String[] args) {
double r = 1.1, area, area2;
area = getArea(r);
System.out.println("area is " + area);
area2 = getArea(2.2);
System.out.println("area 2 is " + area2);
System.out.println("area 3 is " + getArea(3.3));
}
public static double getArea(double radius) {
return radius * radius * Math.PI;
}
}
|
The expected outputs are:
area is 3.8013271108436504
area 2 is 15.205308443374602
area 3 is 34.21194399759284
Trong ví dụ trên, một phương thức có thể sử dụng lại được gọi getArea()
được xác định, nhận một đối số double
từ người gọi, thực hiện phép tính và trả về double
kết quả cho người gọi. Trong main()
, chúng ta gọi getArea()
các phương thức ba lần, mỗi lần với một tham số khác nhau.
Lưu ý rằng có một sự chuyển điều khiển từ người gọi sang phương thức được gọi và từ phương thức trở lại người gọi, như được minh họa.
Method Definition Syntax
Cú pháp cho định nghĩa phương thức như sau:
public static returnValueType methodName(arg-1-type arg-1, arg-2-type arg-2,... ) {
body ;
}
public static double getArea(double radius) {
return radius * radius * Math.PI;
}
public static int max(int number1, int number2) {
if (number1 > number2) {
return number1;
} else {
return number2;
}
}
Lưu ý rằng bạn cần chỉ định loại đối số và giá trị trả về trong định nghĩa phương thức.
Calling Methods
Để gọi một phương thức, chỉ cần sử dụng . Ví dụ, để gọi các phương thức trên:methodName(arguments)
double area1 = getArea(1.1);
double r2 = 2.2;
double area2 = getArea(r2);
double r3 = 3.3;
System.out.println("Area is: " + area(r3));
int result1 = max(5, 8);
int i1 = 7, i2 = 9;
int result2 = max(i1, i2);
System.out.println("Max is: " + max(15, 16));
Lưu ý rằng bạn cần chỉ định loại trong định nghĩa phương thức, nhưng không phải trong khi gọi.
Method Naming Convention
Tên của một phương thức sẽ là một động từ hoặc cụm động từ (hành động), bao gồm một hoặc nhiều từ. Từ đầu tiên là chữ thường, trong khi phần còn lại được viết hoa ban đầu (gọi là trường hợp lạc đà ). Ví dụ, getArea()
, setRadius()
, moveDown()
, isPrime()
,, vv
Another Example:
public class EgMinMaxMethod {
public static void main(String[] args) {
int a = 6, b = 9, max, min;
max = max(a, b);
min = min(a, b);
System.out.println(max + "," + min);
System.out.println(max(5, 8));
System.out.println(min(5, 8));
}
public static int max(int number1, int number2) {
if (number1 > number2) {
return number1;
} else {
return number2;
}
}
public static int min(int number1, int number2) {
return (number1 < number2) ? number1 : number2;
}
}
11.3 The "return" statement
Bên trong thân phương thức, bạn có thể sử dụng một return
câu lệnh để trả về một giá trị (của returnValueType
khai báo trong chữ ký của phương thức) để trả về một giá trị cho người gọi. Cú pháp là:
return aReturnValue;
return;
11.4 The "void" Return-Type
Giả sử rằng bạn cần một phương thức để thực hiện một số hành động nhất định (ví dụ: in) mà không cần trả lại giá trị cho người gọi, bạn có thể khai báo loại giá trị trả về của nó là void
. Trong phần thân của phương thức, bạn có thể sử dụng return;
câu lệnh "" mà không có giá trị trả về để trả lại quyền điều khiển cho người gọi. Trong trường hợp này, return
tuyên bố là tùy chọn. Nếu không có return
câu lệnh nào , toàn bộ cơ thể sẽ được thực thi và điều khiển trả về cho người gọi ở cuối cơ thể.
Lưu ý rằng đó main()
là một phương thức có loại giá trị trả về là void
. main()
được gọi bởi thời gian chạy Java, thực hiện các hành động được xác định trong phần thân và không trả lại gì cho thời gian chạy Java.
11.5 Actual Parameters vs. Formal Parameters
Hãy nhớ lại rằng một phương thức nhận các đối số từ người gọi của nó, thực hiện các hành động được xác định trong phần thân của phương thức và trả về một giá trị (hoặc không có gì) cho người gọi.
Trong ví dụ trên, biến được (double radius)
khai báo trong chữ ký của getArea(double radius)
được gọi là tham số chính thức . Phạm vi của nó là trong cơ thể của phương thức. Khi phương pháp này được gọi bởi một người gọi, người gọi phải cung cấp cái gọi là tham số thực tế s hoặc tranh cãi , có giá trị sau đó được sử dụng cho việc tính toán thực tế. Ví dụ: khi phương thức được gọi thông qua " area1=getArea(radius1)
", radius1
là tham số thực tế, với giá trị là 1.1
.
11.6 Code Example: Magic Number
The following program contains a boolean
method called isMagic(int number)
, which returns true
if the given number
contains the digit 8
, e.g., 18, 108, and 1288. The signature of the method is:
public static boolean isMagic(int number);
It also provides the main()
method to test the isMagic()
. For example,
Enter a positive integer: 1288
1288 is a magic number
Enter a positive integer: 1234567
1234567 is not a magic number
import java.util.Scanner;
public class MagicNumber {
public static void main(String[] args) {
int number;
Scanner in = new Scanner(System.in);
System.out.print("Enter a positive integer: ");
number = in.nextInt();
if (isMagic(number)) {
System.out.println(number + " is a magic number");
} else {
System.out.println(number + " is not a magic number");
}
in.close();
}
public static boolean isMagic(int number) {
boolean isMagic = false;
while (number > 0) {
int digit = number % 10;
if (digit == 8) {
isMagic = true;
break;
}
number /= 10;
}
return isMagic;
}
}
Take note of the proper documentation comment for the method.
11.7 Code Example: int Array Methods
The following program contains
various method for int
array with signatures as follows:
public static void print(int[] array);
public static int min(int[] array);
public static int sum(int[] array);
public static double average(int[] array);
It also contains the main() method to test all the methods. For example,
Enter the number of items: 5
Enter the value of all items (separated by space): 8 1 3 9 4
The values are: [8, 1, 3, 9, 4]
The min is: 1
The sum is: 25
The average (rounded to 2 decimal places) is: 5.00
import java.util.Scanner;
public class IntArrayMethodsTest {
public static void main(String[] args) {
int numItems;
int[] items;
Scanner in = new Scanner(System.in);
System.out.print("Enter the number of items: ");
numItems = in.nextInt();
items = new int[numItems];
if (items.length > 0) {
System.out.print("Enter the value of all items (separated by space): ");
for (int i = 0; i < items.length; ++i) {
items[i] = in.nextInt();
}
}
System.out.print("The values are: ");
print(items);
System.out.println("The min is: " + min(items));
System.out.println("The sum is: " + sum(items));
System.out.printf("The average (rounded to 2 decimal places) is: %.2f%n", average(items));
in.close();
}
public static void print(int[] array) {
System.out.print("[");
for (int i = 0; i < array.length; ++i) {
System.out.print((i == 0) ? array[i] : ", " + array[i]);
}
System.out.println("]");
}
public static int min(int[] array) {
int min = array[0];
for (int i = 1; i < array.length; ++i) {
if (array[i] < min) min = array[i];
}
return min;
}
public static int sum(int[] array) {
int sum = 0;
for (int item: array) sum += item;
return sum;
}
public static double average(int[] array) {
return (double)(sum(array)) / array.length;
}
}
11.8 Pass-by-Value for Primitive-Type Parameters
Trong Java, khi một đối số của kiểu nguyên thủy được truyền vào một phương thức, một bản sao được tạo và chuyển vào phương thức. Phương thức được gọi hoạt động trên bản sao nhân bản và không thể sửa đổi bản sao gốc. Điều này được gọi là pass-by-value .
Ví dụ,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| public class PassByValueTest {
public static void main(String[] args) {
int number = 8, result;
System.out.println("In caller, before calling the method, number is: " + number);
result = increment(number);
System.out.println("In caller, after calling the method, number is: " + number);
System.out.println("The result is " + result);
}
public static int increment(int number) {
System.out.println("Inside method, before operation, number is " + number);
++number;
System.out.println("Inside method, after operation, number is " + number);
return number;
}
}
|
Ghi chú:
- Mặc dù có một biến được gọi
number
trong cả phương thức main()
và increment()
phương thức, có hai bản sao riêng biệt - một bản có sẵn main()
và một bản khác có sẵn increment()
- xảy ra có cùng tên. Bạn có thể thay đổi tên của một trong hai, mà không ảnh hưởng đến chương trình.
11.9 Pass-by-Reference for Arrays and Objects
Như đã đề cập, đối với các tham số kiểu nguyên thủy, một bản sao được sao chép được tạo và truyền vào phương thức. Do đó, phương thức không thể sửa đổi các giá trị trong trình gọi. Nó được gọi là pass-by-value.
Đối với mảng (và đối tượng - sẽ được mô tả trong chương sau), tham chiếu mảng được truyền vào phương thức và phương thức có thể sửa đổi nội dung của các phần tử của mảng. Nó được gọi là tham chiếu qua. Ví dụ,
import java.util.Arrays;
public class PassByReferenceTest {
public static void main(String[] args) {
int[] testArray = {9, 5, 6, 1, 4};
System.out.println("In caller, before calling the method, array is: "
+ Arrays.toString(testArray));
increment(testArray);
System.out.println("In caller, after calling the method, array is: "
+ Arrays.toString(testArray));
}
public static void increment(int[] array) {
System.out.println("Inside method, before operation, array is "
+ Arrays.toString(array));
for (int i = 0; i < array.length; ++i) ++array[i];
System.out.println("Inside method, after operation, array is "
+ Arrays.toString(array));
}
}
11.10 Varargs - Method with Variable Number of Formal Arguments (JDK 5)
Trước JDK 5, một phương thức phải được khai báo với một số đối số chính thức cố định . Giống như C printf()
, có số lượng đối số thay đổi , không thể được thực hiện. Mặc dù bạn có thể sử dụng một mảng để truyền một số lượng đối số khác nhau, nhưng nó không gọn gàng và đòi hỏi một số nỗ lực lập trình.
JDK 5 giới thiệu các đối số biến (hoặc varargs) và cú pháp mới " Type...
". Ví dụ,
public PrintWriter printf(String format, Object... args)
public PrintWriter printf(Local l, String format, Object... args)
Varargs chỉ có thể được sử dụng cho đối số cuối cùng. Ba dấu chấm ( ...
) chỉ ra rằng đối số cuối cùng có thể được truyền dưới dạng một mảng hoặc dưới dạng một chuỗi các đối số được phân tách bằng dấu phẩy. Trình biên dịch tự động gói các varargs thành một mảng. Sau đó, bạn có thể truy xuất và xử lý từng đối số này bên trong phần thân của phương thức dưới dạng một mảng. Có thể truyền varargs dưới dạng một mảng, vì Java duy trì độ dài của mảng trong một biến liên quan length
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| public class VarargsTest {
public static void doSomething(String... strs) {
System.out.print("Arguments are: ");
for (String str : strs) {
System.out.print(str + ", ");
}
System.out.println();
}
public static void doSomething(String s1, String s2) {
System.out.println("Overloaded version with 2 args: " + s1 + ", " + s2);
}
public static void main(String... args) {
doSomething("Hello", "world", "again", "and", "again");
doSomething("Hello", "world");
String[] strs = {"apple", "orange"};
doSomething(strs);
}
}
|
11.11 Implicit Type-Casting for Method's Parameters
Một phương thức lấy double
tham số có thể chấp nhận bất kỳ kiểu nguyên thủy số nào, chẳng hạn như int
hoặc float
. Điều này là do đúc kiểu ngầm được thực hiện. Tuy nhiên, một phương thức lấy int
tham số không thể chấp nhận double
giá trị. Điều này là do việc tạo kiểu ngầm định luôn là một chuyển đổi mở rộng nhằm tránh mất độ chính xác. Một kiểu đúc rõ ràng là cần thiết để thu hẹp chuyển đổi. Đọc " Đúc kiểu " trên các quy tắc chuyển đổi.
11.12 Method Overloading
Trong Java, một phương thức (của một tên phương thức cụ thể) có thể có nhiều hơn một phiên bản, mỗi phiên bản hoạt động trên một bộ tham số khác nhau - được gọi là nạp chồng phương thức . Các phiên bản sẽ được phân biệt bởi số lượng, loại hoặc thứ tự của các tham số.
Example 1
public class AverageMethodOverloading {
public static void main(String[] args) {
System.out.println(average(8, 6));
System.out.println(average(8, 6, 9));
System.out.println(average(8.1, 6.1));
System.out.println(average(8, 6.1));
//average(1, 2, 3, 4)
}
public static int average(int n1, int n2) {
System.out.println("version 1");
return (n1 + n2)/2;
}
public static int average(int n1, int n2, int n3) {
System.out.println("version 2");
return (n1 + n2 + n3)/3;
}
public static double average(double n1, double n2) {
System.out.println("version 3");
return (n1 + n2)/2.0;
}
}
The expected outputs are:
version 1
7
version 2
7
version 3
7.1
version 3
7.05
Example 2: Arrays
Giả sử bạn cần một phương pháp để tính tổng các yếu tố cho int[]
, short[]
, float[]
và double[]
, bạn cần phải viết tất cả các phiên bản quá tải - không có phím tắt.
public class SumArrayMethodOverloading {
public static void main(String[] args) {
int[] a1 = {9, 1, 2, 6, 5};
System.out.println(sum(a1));
double[] a2 = {1.1, 2.2, 3.3};
System.out.println(sum(a2));
float[] a3 = {1.1f, 2.2f, 3.3f};
//System.out.println(sum(a3));
}
public static int sum(int[] array) {
System.out.println("version 1");
int sum = 0;
for (int item : array) sum += item;
return sum;
}
public static double sum(double[] array) {
System.out.println("version 2");
double sum = 0.0;
for (double item : array) sum += item;
return sum;
}
}
11.13 "boolean" Methods
Đọc hiểu và phân tích đoạn code sau
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class BooleanMethodTest {
public static boolean isOdd(int number) {
if (number % 2 == 1) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
System.out.println(isOdd(5));
System.out.println(isOdd(6));
System.out.println(isOdd(-5));
}
}
|
إرسال تعليق