Java Bài 5: Toán Tử (Operator) – Yellow Code Books

Rate this item:

Rating: 4.8/5. From 34 votes.

Please wait…

Được chỉnh sửa ngày 03/11/2022.

Chào mừng các bạn đến với bài học Java số 5, bài học về các toán tử trong Java. Bài học này nằm trong chuỗi bài học lập trình ngôn ngữ Java của Yellow Code Books.

Nếu như ở bài trước các bạn đã làm quen với việc khai báo và sử dụng các biến và hằng trong Java. Thì đến bài hôm nay chúng ta cùng học cách vận dụng các biến và hằng này vào các logic tính toán trong chương trình, thông qua việc tìm hiểu về các toán tử.

Trước khi vào làm quen với các toán tử, mình muốn nói về khái niệm biểu thức cái đã.

Biểu Thức

Bạn nên biết là lập trình không khác gì làm toán cả, tất cả chúng ta, những Lập Trình Viên, chỉ đơn giản là đang vận dụng các phép toán mà chúng ta đã từng được học vào trong việc lập trình ra các ứng dụng mà thôi. Và để làm quen lại với kiến thức toán, chúng ta cùng quay về với khái niệm biểu thức. Trong toán học định nghĩa rằng biểu thức (expression) là sự kết hợp giữa các toán tử (operator) và các toán hạng (operand) theo đúng một trật tự nhất định. Trong đó mỗi toán hạng có thể là một hằng, một biến hoặc một biểu thức khác.

Mình xin minh họa một biểu thức như sau.

Hình minh họa một Biểu ThứcHình minh họa một Biểu ThứcHình minh họa một Biểu Thức

Qua đó * + là các toán tử. 2, y5 là các toán hạng. Rõ hơn nữa thì 25 là các hằng, còn ybiến.

Cũng giống như trong toán học, bạn có thể dùng cặp dấu ngoặc đơn () để gom nhóm các biểu thức lại, và khi đó thì biểu thức trong dấu ngoặc đơn sẽ được ưu tiên thực hiện trước.

Ví dụ minh họa cho một biểu thức có dấu ngoặc đơn như sau.

2

*

(

y

+

5

)

Ngoài các toán tử *+ trên đây, trong lập trình còn nhiều các toán tử đặc thù khác nữa. Mời các bạn cùng nhau làm quen tiếp nào.

Toán Tử Số Học

Chúng ta hãy làm quen với toán tử đầu tiên trong lập trình đó chính là toán tử số học (arithmetic operator). Toán tử này thì hoàn toàn giống với toán học, đó là các phép toán cộng, trừ, nhân, chia. Cụ thể về các phép toán trong toán tử số học được mình liệt kê ở bảng sau.

Toán TửÝ Nghĩa+Toán tử cộng. Tương tự phép toán cộng trong toán học. Tuy nhiên trong lập trình có thể dùng toán tử này để cộng chuỗi (sẽ được mình nói cụ thể ở bài học chuỗi sau).Toán tử trừ. Tương tự phép toán trừ trong toán học.*Toán tử nhân. Tương tự phép toán nhân trong toán học./Toán tử chia. Hơi khác với toán một chút là nếu hai phần tử trong phép toán đều là số nguyên thì kết quả của phép toán cũng là số nguyên, ví dụ 5/2 sẽ bằng 2. Còn hai phần tử là số thực thì kết quả sẽ là số thực, ví dụ 5.0/2.0 sẽ bằng 2.5.%Toán tử chia lấy phần dư. Ví dụ 5%2 sẽ bằng 1, đó chính là số dư của phép chia.

Bài Thực Hành Số 1

Bạn hãy thử code để biết kết quả in ra của phép gán (toán tử Gán sẽ được nói rõ ở mục tiếp theo) từ một biểu thức tới biến age với các toán tử số học như sau.

int age;
int thisYear = 2016;
int yearOfBirth = 1990;
age = thisYear - yearOfBirth;
System.out.println("I am " + age + " years old");

Kết quả như sau

I am 26 years old

Bài Thực Hành Số 2

Bạn thử đoán xem kết quả in ra của các các so1so2, và so3 như ví dụ bên dưới, và xem kết quả có đúng với bạn đoán không nhé.

int so1;
int so2;
float so3;

so1 = 15 / 6;
so2 = 15 % 6;
so3 = 15.0f / 6.0f;

System.out.println("Ket qua so1 la " + so1 + ", so2 la " + so2 + ", so3 la " + so3);

Và kết quả.

Ket qua so1 la 2, so2 la 3, so3 la 2.5

Toán Tử Gán

Giờ chúng ta cùng ra khỏi toán học để đến biểu thức có vẻ giống lập trình hơn xíu. Trong lập trình, ngoài các toán tử cộng, trừ, nhân chia như trong toán học ra, chúng ta còn có nhiều toán tử đặc thù khác, một trong số đó là toán tử gán (assignment operator).

Trong Java, toán tử gán được thực hiện thông qua ký hiệu “=”. Quen lắm phải không nào, vì bài trước bạn đã thực hành khai báo một biến như sau int count = 5; thì dấu “=” ở đây chính là một phép gán (chứ không phải so sánh bằng, việc so sánh sẽ được nói đến ở toán tử bên dưới). Phép gán được định nghĩa cụ thể thông qua cú pháp.

tên_biến = biểu_thức

Khi đó kết quả của một biểu_thức (có thể là một biểu thức gồm nhiều toán tử và toán hạng, cũng có thể chỉ là một con số như các ví dụ ở bài trước) sẽ được gán vào tên_biến. Hay hiểu cách khác, đó là tên_biến sẽ chứa đựng giá trị bằng với biểu_thức mang đến thông qua phép gán này.

Bài Thực Hành Số 3

Với bài thực hành này, bạn hãy thực hiện phép gán sau đây và cho biết kết quả in ra log sau khi gán giá trị cho biến thisYear là gì nhé.

final int THIS_YEAR = 2016;
int thisYear = 2000;
thisYear = THIS_YEAR;
 
System.out.println("This year is " + thisYear);

Kết quả như sau, bạn nên thử code và thực thi bằng IDE, hoặc tự đoán kết quả trước khi xem kết quả bên dưới.

This year is 2016

Gán Cho Nhiều Biến Cùng Lúc

Trong trường hợp bạn có một giá trị giống nhau được gán cho nhiều biến khác nhau, thay vì như ví dụ dưới đây bạn phải gán giá trị đó cho từng biến một.

int x = 10;
int y = 10;
int z = 10;

Thì bạn có thể thực hiện việc gán chỉ với một dòng như dưới đây. Đảm bảo đúng.

int x;
int y;
int z;
x = y = z = 10;

Hoặc bạn có thể viết ngắn gọn hơn, cách viết này gom các khai báo biến với cùng một kiểu dữ liệu vào cùng một dòng.

int x, y, z;
x = y = z = 10;

Nhưng lưu ý bạn không thể viết như vậy được: int x = int y = int z = 10;.

Đầy Đủ Các Toán Tử Gán

Thực sự thì toán tử gán không chỉ có mỗi toán tử “=”. Trong Java có rất nhiều các toán tử gán nữa được mình liệt kê ở bảng dưới đây.

Toán TửÝ Nghĩa=Đã được mình nói rõ ở trên kia rồi nhé.+=Cộng giá trị của tên_biến bên trái với biểu_thức bên phải và gán kết quả đó lại cho tên_biến.-=Ngược lại với toán tử trên, toán tử này trừ giá trị của tên_biến bên trái một giá trị biểu_thức bên phải, rồi gán kết quả đó lại cho tên_biến.*=Tương tự, nhân tên_biến với biểu_thức với và gán kết quả lại cho tên_biến./=Chia tên_biến cho biểu_thức và gán kết quả lại cho tên_biến.%=Chia lấy phần dư tên_biến cho biểu_thức và gán kết quả lại cho tên_biến.<<=Dịch trái tên_biến sang một giá trị biểu_thức và gán kết quả lại cho tên_biến (bạn hãy xem toán tử bitwise bên dưới để biết dịch trái nghĩa là gì nhé).>>=Ngược lại. Dịch phải tên_biến sang một giá trị biểu_thức và gán kết quả lại cho tên_biến (và bạn cũng xem toán tử bitwise bên dưới để biết dịch phải nghĩa là gì nhé).&=AND tên_biến với biểu_thức và gán kết quả lại cho tên_biến (cũng xem toán tử bitwise để rõ hơn về phép toán AND).|=OR tên_biến với biểu_thức và gán kết quả lại cho tên_biến (cũng xem toán tử bitwise để rõ hơn về phép toán OR).^=XOR tên_biến với biểu_thức và gán kết quả lại cho tên_biến (cũng xem toán tử bitwise để rõ hơn về phép toán XOR).

Để hiểu rõ hơn về các toán tử gán liệt kê trên đây mời bạn đến với bài thực hành sau.

Bài Thực Hành Số 4

Bạn thử đoán xem các so1, so2, so3, so4 sẽ có các giá trị như thế nào sau các phép gán sau nhé.

int so1, so2, so3, so4;
so1 = so2 = so3 = so4 = 10;

so1 += so2;
so2 -= 5;
so3 /= 2;
so4 %= 3;

System.out.println("Ket qua so1 la " + so1 + ", so2 la " + so2 + ", so3 la " + so3 + ", so4 la " + so4);

Và kết quả in ra là.

Ket qua so1 la 20, so2 la 5, so3 la 5, so4 la 1

Mình xin giải thích một chút cho các bạn dễ hiểu. Mình không nói lại việc khai báo và gán giá trị ban đầu là 10 cho các biến nữa. Chúng ta bắt đầu với đoạn code sau.

so1 += so2; câu lệnh này sẽ lấy giá trị của so1 ban đầu là 10 cộng với so2 cũng là 10, kết quả của phép cộng là 20 sẽ được gán cho so1. Nếu bạn thấy khó hiểu, thì mình xin bật mí cách viết này là viết ngắn gọn của câu lệnh so1 = so1 + so2; mà thôi.

Tương tự so2 -= 5; là cách viết ngắn gọn của so2 = so2 - 5;. Cách này lấy so2 trừ đi cho 5 rồi gán kết quả lại cho so2.

so3 /= 2; cũng giống như so3 = so3 / 2;.

so4 %= 3; giống như so4 = so4 % 3;.

Bạn hãy tự suy luận tương tự với các toán tử còn lại ở bảng trên kia nhé.

Toán Tử Một Ngôi

Một toán tử đặc trưng của lập trình nữa, đó là toán tử một ngôi (unary operator). Với toán tử này, thì chỉ cần một toán tử kết hợp với một toán hạng thôi là đã có thể cho ra kết quả. Các bạn hãy nhìn vào bảng sau.

Toán TửÝ Nghĩa+Toán tử cộng một ngôi. Nó khác với toán tử cộng số học ở bảng trên. Toán tử này biểu diễn số dương. Vì các số dương bình thường không cần phải hiển thị toán tử này, nên bạn cũng sẽ không thấy công dụng của nó.Toán tử trừ một ngôi. Toán tử trừ này biểu diễn số âm.++Toán tử tăng. Toán tử này sẽ làm tăng giá trị của toán hạng lên 1 đơn vị.– –Toán tử giảm. Toán tử này sẽ làm giảm giá trị của toán hạng đi 1 đơn vị.!Toán tử phủ định logic. Toán tử này sẽ đảo ngược giá trị của biến biểu thức logic. Nếu biểu thức logic đang là true thì sẽ bị đảo ngược thành false và ngược lại

Bài Thực Hành Số 5

Bạn hãy nhìn biểu thức dưới đây, soGi sẽ được gán bằng một biểu thức, mà ở đó soDuong được cộng với một toán tử một ngôi biểu thị số âm.

int soDuong = 4;
int soGi = soDuong + -10;
System.out.println("Ket qua la " + soGi);

Và kết quả như sau chắc bạn cũng dễ dàng đoán được.

Ket qua la -6

Bài Thực Hành Số 6

Bạn hãy chú ý vào các toán tử “++” và “–“ sau đây, như đã nói, các toán tử này sẽ làm toán hạng đứng sau nó tăng lên hoặc giảm đi 1 rồi mới thực hiện các phép toán khác.

int so1 = 4;
int so2 = 10;
int soKetQua = ++so1 + --so2;
System.out.println("So1 la " + so1 + ", so2 la " + so2 + ", ket qua la " + soKetQua);

Và kết quả là.

So1 la 5, so2 la 9, ket qua la 14

Mình xin giải thích một chút ở Bài Thực Hành Số 6 trên đây, vì toán tử một ngôi dạng này sẽ hơi lạ với các bạn mới làm quen với lập trình. Với việc thực hiện soKetQua = ++so1 + --so2;, hệ thống sẽ thực hiện biểu thức ++so1 trước và so1 sau đó mang giá trị là 5 (++so1 lúc bấy giờ tương tự như biểu thức so1 = so1 + 1; vậy). Rồi hệ thống cũng thực hiện tiếp --so2 ra giá trị 9 (tương tự thì --so2 cũng sẽ giống như so2 = so2 - 1;). Sau cùng thì tiến hành cộng hai số này lại và gán cho biến soKetQua.

Có bạn nào thắc mắc là hai cách viết ++so1 và so1++ có khác nhau không? Câu trả lời là . Cũng giống như C/C++, khi bạn viết ++so1, Java sẽ thực hiện việc tăng giá trị của so1 trước khi lấy giá trị đó dùng vào trong biểu thức. Còn nếu viết so1++, Java sẽ lấy giá trị của so1 dùng vào trong biểu thức trước khi tăng giá trị của nó.

Để hiểu rõ hơn những ý mình liệt kê trên đây, bạn hãy thử sửa code trên lại một chút như sau và chạy lại nhé.

int so1 = 4;
int so2 = 10;
int soKetQua = so1++ + so2;
System.out.println("So1 la " + so1 + ", so2 la " + so2 + ", ket qua la " + soKetQua);

Kết quả in ra là.

So1 la 5, so2 la 10, ket qua la 14

Với thử nghiệm trên, bạn thấy so1++ không hề được áp dụng tăng giá trị của so1 vào biểu thức, mà so1 vẫn mang giá trị 4 rồi cộng với so2 là 10 ra kết quả 14. Sau khi thự hiện xong biểu thức thì so1 mới được tăng giá trị và vì vậy bạn thấy in ra so1 là 5.

Toán Tử Quan Hệ

Nghe đến quan hệ sao nó… thôi bỏ qua. Nhìn vào nghĩa tiếng Anh thì toán tử quan hệ chính là relational operator, có thể hiểu như là các phép toán thể hiện các mối liên hệ. Chúng sẽ giúp so sánh các biểu thức với nhau để cho ra kết quả là một giá trị boolean, tức là cho ra một trong hai giá trị hay false. Bạn hãy nhìn vào bảng để xem các toán tử quan hệ sau.

Toán TửÝ Nghĩa==Bằng!=Không bằng (khác)>Lớn hơn>=Lớn hơn hoặc bằng<Nhỏ hơn<=Nhỏ hơn hoặc bằng

Chú ý rằng kết quả của toán tử này luôn trả về một giá trị boolean nhé.

Bài Thực Hành Số 7

Bạn thử ngẫm xem kết quả in ra sẽ là giá trị true hay false?

double weight = 71.23;
int height = 191;
boolean married = false;
boolean attached = false;
char gender = 'm';
 
System.out.println("Ket qua 1: " + (!married == attached));
System.out.println("Ket qua 2: " + (gender != 'f'));
System.out.println("Ket qua 3: " + (height >= 180));
System.out.println("Ket qua 4: " + (weight > 90));

Bạn đã có kết quả của riêng mình chưa? Nếu có rồi thì cùng so sánh với kết quả bên dưới nhé.

Ket qua 1: false
Ket qua 2: true
Ket qua 3: true
Ket qua 4: false

Toán Tử Điều Kiện

Các toán tử điều kiện sẽ so sánh các biểu thức mang giá trị truefalse với nhau. Toán tử này còn được gọi là toán tử logic (logical operator). Bạn cứ tưởng tượng toán tử này sẽ hoạt động theo kiểu câu nói “nếu trời không mưa và tôi có tiền thì tôi sẽ đi chơi hôm nay”. Trong đó “trời không mưa” mang một giá trị boolean, và “tôi có tiền” cũng là một giá trị boolean, hai giá trị này được so sánh bởi toán tử “và”. Vậy nếu “trời không mưa”“tôi có tiền” đều mang giá trị true thì kết quả so sánh sẽ là true, tức “tôi sẽ đi chơi hôm nay” là true, tức là tôi sẽ đi chơi. Ngược lại nếu một trong hai vế đầu là false thì kết quả sẽ là false, tức tôi sẽ không đi chơi. Các toán tử điều kiện được nêu trong bảng sau.

Toán TửÝ Nghĩa&&So sánh AND.||So sánh OR.?:So sánh theo điều kiện, sẽ được nhắc đến khi chúng ta học đến cách viết điều kiện if..else.. ở bài học sau.

Sau đây là bảng chân trị, tức các kết quả so sánh điều kiện của các toán tử &&|| như sau.

pqp && qp || qfalsefalsefalsefalsefalsetruefalsetruetruefalsefalsetruetruetruetruetrue

Bài Thực Hành Số 8

Bạn thử gõ các câu lệnh sau và ngẫm kết quả của nó nhé.

int age = 18;
double weight = 71.23;
int height = 191;
boolean married = false;
boolean attached = false;
char gender = 'm';

System.out.println(!married && !attached && (gender == 'm'));
System.out.println(married && (gender == 'f'));
System.out.println((height >= 180) && (weight >= 65) && (weight <= 80));
System.out.println((height >= 180) || (weight >= 90));

Kết quả như sau.

true
false
true
true

Chúng ta thử giải nghĩa dòng in log thứ nhất để hiểu rõ hơn. Đầu tiên biến married có giá trị false, !married đảo ngược giá trị thành true. Tương tự attachedfalse!attachedtrue, (gender==’m’) sẽ là true. Tóm lại chúng ta có true && true && true, và kết quả cuối cùng theo bảng chân trị là true.

Dòng thứ hai, ưu tiên biểu thức trong ngoặc đơn trước (gender == ‘f’) sẽ cho kết quả false. Biến married được khai báo là false. false && false kết quả theo bảng chân trị là false.

Bạn cứ giải nghĩa tương tự cho các dòng còn lại.

Toán Tử Bitwise

Toán tử bitwisetoán tử giúp chúng ta tương tác trực tiếp trên các bit (dạng nhị phân) của các toán hạng. Để hiểu rõ cách tổ chức và cách làm việc với các giá trị nhị phân thì dài dòng lắm, có thể mình sẽ nói rõ hơn ở các bài khác. Nhưng bạn có thể hiểu bản chất của tất cả dữ liệu mà máy tính có thể hiểu và làm việc chính là các dữ liệu dạng nhị phân được biểu diễn chỉ bởi hai giá trị là 01. Mỗi một giá trị 0 hay 1 như vậy là một bit, bạn đã hiểu tại sao lại có tên bitwise rồi đó. Nhờ vào việc đây là ngôn ngữ “mẹ đẻ” của máy tính, nên nếu bạn dùng chính cách thức nhị phân này để “trò chuyện” với máy, sẽ nhanh chóng hơn rất nhiều so với các cách tương tác với các dạng số khác.

Bảng sau là các toán tử bitwise.

Toán TửÝ Nghĩa&AND|OR^XOR~NOT, đảo ngược bit 0 thành 1, và ngược lại 1 thành 0.>>Dịch phải<<Dịch trái

Bạn nên nhớ ANDtoán tử bitwise chỉ có một dấu &, còn ANDtoán tử điều kiện có hai dấu &&. Và một điều khác nhau nữa là && chỉ so sánh các biểu thức boolean với nhau, còn & so sánh dựa trên các bit, vì vậy mà & có thể làm việc với hầu như mọi kiểu dữ liệu nguyên thủy trong Java (trừ kiểu số thực). Tương tự cho khác nhau giữa |||.

Trước khi đi vào bài thực hành toán tử bitwise, bạn hãy xem qua bảng chân trị cho bitwise như sau.

pqp & qp | qp ^ q00000010111001111110

Bài Thực Hành Số 9

Ở bài thực hành này chúng ta cùng code thử các toán tử bitwise như sau, mình sẽ giải thích kết quả tại sao ở bên dưới bài thực hành này.

byte so1 = 5;
byte so2 = 12;
 
System.out.println("Toan tu &: " + (so1 & so2));
System.out.println("Toan tu |: " + (so1 | so2));
System.out.println("Toan tu ^: " + (so1 ^ so2));
System.out.println("Toan tu ~: " + (so1 & ~so2));
System.out.println("Toan tu <<: " + (so1<<1));
System.out.println("Toan tu >>: " + (so2>>2));

Kết quả ở dưới đây.

Toan tu &: 4
Toan tu |: 13
Toan tu ^: 9
Toan tu ~: 1
Toan tu <<: 10
Toan tu >>: 3

Giờ hãy cùng nhau giải thích ý nghĩa của các phép toán. Chúng ta đều biết kiểu dữ liệu byte được hệ thống cấp phát cho 1 byte bộ nhớ, ngoài ra 1 byte = 8 bits, vậy hai biến so1so2 có giá trị lần lượt là 512 sẽ được biểu diễn dạng bit như sau.

5: 0000 0101
12: 0000 1100

so1 & so2: nếu bạn lấy 0000 0101 & 0000 1100, bạn hãy áp dụng bảng chân trị vào so sánh từng bit với nhau, bạn sẽ có kết quả là 0000 0100, đây là biểu diễn bit của số 4, và là kết quả của dòng log đầu tiên.

so1 | so2: tương tự như trên 0000 0101 | 0000 1100 sẽ là 0000 1101, là dạng bit của số 13.

so1 ^ so2: 0000 0101 ^ 0000 1100 sẽ là 0000 1001, là dạng bit của số 9.

so1 & ~so2: ta xét từ ~so2, ~ là toán tử NOT, nó sẽ đảo ngược các bit của so2 thành 1111 0011, vậy so1 & ~so2 sẽ là 0000 0101 & 1111 0011, sẽ là 0000 0001, là dạng bit của số 1.

so1<<1: tức là lấy dãy bit của so1 dịch trái đi 1 bit, sẽ thành 0000 1010, là dạng bit của số 10.

so2>>2: tức là lấy dãy bit của so2 dịch phải đi 2 bit, sẽ thành 0000 0011, là dạng bit của số 3.

Kết Luận

Chúng ta vừa mới đi qua bài học về các toán tử trong Java, qua bài học hôm nay bạn đã hiểu rõ hơn ngôn ngữ Java hơn rồi đúng không nào. Các toán tử hôm nay sẽ được ứng dụng khá nhiều vào các kiến thức và bài thực hành sau này. Bạn hãy cố gắng theo dõi các bài học thú vị phía trước nhé.

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:
– Đánh giá 5 sao ở mỗi bài viết nếu thấy thích.
– Comment bên dưới mỗi bài viết nếu có thắc mắc.
– Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
– Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.
– Ủng hộ blog theo hướng dẫn ở thanh bên phải để blog ngày càng phát triển hơn.

Bài Kế Tiếp

Bạn sẽ cùng nhau xem qua cách thức ép kiểu, và cách ghi chú vào source code nhé.