AptechVietnam 1/114
Chương 1: Giới thiệu về Java
Mục tiêu bài học
Kết thúc bài học này, học viên có thể:
Tìm hiểu các thực thể trong thế giới thực như là các đối tượng
Định nghĩa một đối tượng phần mềm
Tìm hiểu và giải thích cấu trúc của một lớp
So sánh các lớp và các đối tượng
Tìm hiểu tầm quan trọng của Java
Tìm hiểu bộ JDK và các công cụ của nó
Tìm hiểu về máy ảo Java - Java Virtual Machine (JVM)
1.1 Giới thiệu về lớp và đối tượng
Các đối tượng (object) và các lớp (class) là nền tảng để xây dựng Java. Lớp là
một khuôn mẫu, bao gồm một tập các đối tượng có tính chất tượng tự nhau. Lớp
mô tả tất cả các thuộc tính của một tập các đối tượng cụ thể.
1.1.1 Các thực thể trong thế giới thực như là các đối tượng
Đối tượng là khái niệm dùng để mô tả các thực thể trong thế giới thực. Ví dụ các
đối tượng có thể nhainf thấy quanh ta như: Chó - Dogs, Ô tô - Cars, bông hoa -
Flowers, ngôi nhà – Houses, … Bất kỳ một thực thể hữu hình hoặc có thể sờ mó
được nào đó, đều có thể xem như như một đối tượng trong thế giới thực.
Mỗi đối tượng có các thuộc tính hoặc tính chất nhằm mô tả nó là cái gì. Ví dụ,
các thuộc tính của đối tượng Dog là:
Giống
Màu lông
Tuổi
Ngoài ra, một đối tượng có thể thực hiện các hành động. Chẳng hạn, các hành
động của Dog có thể thực hiện là:
Sủa
Ăn
Learn Java by Example
2/114 AptechVietnam
Chạy
Như vậy, hai yếu tố quan trọng nhất của đối tượng trong thế giới thực là: thuộc
tính (Attribute) và hành động (Action). Nhờ đó, đối tượng có thể được định nghĩa
như một thực thể tồn tại, có các thuộc tính và hành động hoàn toàn xác định.
Tương tự như vậy, trong phạm vi của công nghệ phần mềm, các đối tượng cũng
được mô tả dựa theo trạng thái và hành vi của nó. Trạng thái của một đối tượng
phần mềm được định nghĩa bởi các thuộc tính của nó. Các hoạt động của một
đối tượng phần mềm được định nghĩa như là các hành vi của nó.
Hãy xem xét một đối tượng trong thế giới thực, chẳng hạn Dog, một con chó.
Nếu đối tượng này được ánh xạ đến một đối tượng phần mềm, trạng thái của nó
có thể là màu lông, giống và tuổi. Hành vi của đối tượng Dog có thể là sủa, ăn,
chạy, …
Vì vậy, một đối tượng phần mềm là một thực thể bao gồm các trạng thái (thuộc
tính) và hành vi (hành động). Nó lưu giữ các trạng thái của nó trong các trường,
được gọi là các biến trong ngôn ngữ lập trình. Còn các hành vi được xem như là
các phương thức, giống như các hàm trong ngôn ngữ lập trình. Một phương
thức là một chuỗi các câu lệnh được đặt tên nhằm thực hiện các tác vụ cụ thể
nào đó.
Tham khảo hình 1.1, đây là ví dụ về đối tượng „Cashier‟ (Thủ quỹ)
Hình 1.1: Đối tượng „Cashier‟ và đối tượng „Customer‟
Các thuộc tính của đối tượng „Cashier‟ là:
Tên
Chức vụ
Tuổi
Một đối tượng thực thi một số hành động. Các hành động của đối tượng
‟Cashier‟ là:
Chương 1 Giới thiệu về Java
3/114
Thu tiền từ khách hàng
In hoá đơn
Sự thuận lợi khi sử dụng đối tượng là:
Nó giúp chúng ta hiểu hơn về thế giới thực
Nó ánh xạ các thuộc tính và các hành động của các đối tượng trong thế
giới thực thành trạng thái và hành vi của các đối tượng phần mềm.
1.1.2 Class (Lớp)
Như đề cập ở trên, Dog là một ví dụ về một đối tượng trong thế giới thực. Tuy
nhiên, trong thế giới thực có nhiều loại động vật khác như mèo, cừu, cọp, …Vì
vậy, Dog chỉ là một thể hiện của lớp động vật.
Các thuộc tính và hành động chung của một số đối tượng được nhóm lại thành
một đơn vị. Đơn vị này có thể được dùng để tạo ra một đại diện của loại tương
ứng, gọi là lớp. Mỗi một lớp mô tả một tập các đối tượng riêng lẻ.
Một lớp là một khuôn mẫu hoặc bản thiết kế định nghĩa đặc điểm chính của trạng
thái và hành vi cho tất cả các đối tượng thuộc về lớp. Tất cả các thể hiện của
lớp, được gọi là đối tượng, sẽ có chung các trạng thái và hành vi.
Tuy nhiên, các thuộc tính và hành động có thể được gán chỉ sau khi một đối
tượng được tạo ra. Khi đối tượng được tạo ra ta mới có một đại diện thật sự của
thực thể. Vì vậy, lớp là một mô hình khái niệm của thực thể. Nó mô tả các thuộc
tính và hành động chung chứ không riêng cho một đối tượng cụ thể nào.
Ví dụ, xem xét một lớp có tên Animal (Động vật) như trong bảng 1.1. Lớp chứa
các thuộc tính (trạng thái) và hành động (hành vi) của động vật.
Class Animal
Type
Animal Name
Color
Motion
Breathing
Eating
Bảng 1.1: Mô tả lớp Animal
Lớp này có trạng thái „Type‟, „Animal Name‟ và „Color‟.
Trong đó,
Type - Mô tả loài động vật.
Animal name - Tên loại động vật, chẳng hạn cừu, cọp, ếch, …
Learn Java by Example
4/114 AptechVietnam
Color - Mô tả màu da/ lông của loài đó
„Motion‟ (Di chuyển), „Breathing‟ (Thở) và „Eating‟ (Ăn) là các hành vi của lớp
Animal.
1.1.3 So sánh giữa lớp (class) và đối tượng (object)
Có sự khác biệt giữa một lớp và một đối tượng. Một lớp mô tả một thực thể,
trong khi một đối tượng là một thực thể thật sự.
Đối tượng là vật thật, trong khi lớp là một mô hình khái niệm định nghĩa tất cả
các trạng thái và hành vi cần thiết của một đối tượng.
Một lớp là một nguyên mẫu (prototype) của một đối tượng. Nó định rõ các hành
động và các tính chất cần thiết cho một loại đối tượng cụ thể. Bảng 1.2 là ví dụ
về lớp và đối tượng.
Class
(Lớp)
Object
(Đối tượng)
Animal
Cat
Dog
Car
Honda City
Benz
Bảng 1.2: Ví dụ về lớp và đối tượng
Lớp không thay đổi, trong khi dữ liệu chứa trong một đối tượng có thể thay đổi.
Các thuộc tính của lớp được thiết lập trong suốt thời gian chay chương trình,
không thể thêm bớt thuộc tính trong lúc chương trình đang chạy. Khi một đối
tượng được tạo từ một lớp, nó sẽ là một thành phần của lớp đó cho đến khi bị
huỷ bỏ. Sự tồn tại của đối tượng có hạn chế, đối tượng sẽ được tạo ra và hủy bỏ
theo đúng trình tự.
Mỗi đối tượng được gọi là một thể hiện của một lớp. Trong ví dụ bên dưới,
Employee là một lớp, còn các đối tượng là: Cashier, System Administrator, Stock
Manager, Salesman, Purchase Manager.
Chương 1 Giới thiệu về Java
5/114
Hình 1.2: Các đối tượng và lớp.
1.2 Giới thiệu về Java
Vào năm 1995, hãng Sun Microsystem giới thiệu một ngôn ngữ lập trình mới là
Java. Cho đến giờ, từ “Java” chỉ có nghĩa là tên một hòn đảo ở Indonesia hoặc
một kiểu cách pha café nào đó.
1.2.1 Sự cần thiết của Java
Java là một ngôn ngữ dành cho các nhà lập trình chuyên nghiệp. Java được xây
dựng trên cơ sở ngôn ngữ lập trình C và C++. Nó kế thừa cú pháp của C và các
nét đặc trưng của C++. Một nhóm kỹ sư của hãng Sun Microsystem cần thiết kế
một ngôn ngữ cho các thiết bị điện tử như tivi, máy giặt, …Vì vậy, mục đích cơ
bản là phát triển ngôn ngữ để tạo ra phần mềm có thể nhúng trong các thiết bị
điện tử. Trong ngôn ngữ C và C++ trình biên dịch phụ thuộc vào loại CPU riêng
biệt.
Các trình biên dịch rất đắt và mất nhiều thời gian để tạo ra. Do đó, không thể có
trình biên dịch cho mọi loại CPU. Và yêu cầu là cần có cách dễ dàng và hiệu quả
để tạo ra các trình biên dịch. Ngoài ra, phần mềm phải nhỏ, nhanh, hiệu quả và
độc lập nền tảng, nghĩa là mã chương trình có thể thực hiện trên nhiều CPU
khác nhau dưới các môi trường khác nhau. Trong nỗ lực tạo ra một ngôn ngữ
độc lập nền tảng và khả chuyển, James Gosling và nhóm cộng sự đi tiên phong
Learn Java by Example
6/114 AptechVietnam
trong vấn đề này. Kết quả là sự ra đời của ngôn ngữ Java. Đầu tiên nó được gọi
là “Oak”, sau đó được đổi tên thành Java. Ngày nay, Java đã có những bước
phát triển hết sức thành công và được chấp nhận bởi hàng triệu lập trình viên
trên toàn thế giới.
Java là một ngôn ngữ lập trình phổ dụng, được dùng để viết các chương trình có
thể chạy được trên Internet. Nét đặc trưng chính của Java là ngôn ngữ hướng
đối tượng và độc lập nền tảng. Độc lập nền tảng có nghĩa là chương trình có thể
chạy trên nhiều nền tảng khác nhau như: Microsoft Windows, Apple Macintosh,
Linux, …Java không những được dùng cho các ứng dụng độc lập, các chương
trình trên mạng, mà còn được dùng trong các thiết bị tiêu dùng như: điện thoại,
các thiết bị cầm tay, …
1.2.2 Các đặc trưng của ngôn ngữ Java
Hướng đối tượng (Object-oriented)
Java là một ngôn ngữ hướng đối tượng. Trong Java không có các hằng, biến
hoặc hàm độc lập. Nghĩa là tất cả đều là một phần của đối tượng. Các hằng,
biến và hàm được truy nhập thông qua các lớp và các đối tượng.
Các ngôn ngữ hướng đối tượng lai ghép khác như C++, có đặc điểm của ngôn
ngữ cấu trúc cộng thêm sự mở rộng đối tượng. Ví dụ, C++ là một ngôn ngữ
hướng đối tượng, nhưng lập trình theo hướng cấu trúc, phương thức main() nằm
ngoài bất kỳ lớp và đối tượng nào. Java thì không cho phép cách khai báo này.
Trong Java, phương thức main() chỉ được khai báo bên trong một lớp.
Độc lập nền tảng (Platform independent)
Java là một nền tảng để phát triển ứng dụng. Nó có thể được dùng như một
ngôn ngữ. Nền tảng ở đây là sự kết hợp giữa phần cứng và phần mềm hệ thống
mà hầu hết các phần mềm đều chạy được. Ví dụ, bộ xử lý Intel chạy trên nền
Windows XP là một nền tảng.
Độc lập nền tảng nói đến khả năng của chương trình di chuyển từ một nền tảng
này sang một nền tảng khác không có bất kỳ một khó khăn nào. Độc lập nền
tảng trong Java ở mức mã nguồn và mã bytecode (mã trung gian).
Java là một ngôn ngữ định kiểu mạnh mẽ, nghĩa là phải cần khai báo kiểu dữ
liệu cho mọi biến. Kiểu dữ liệu trong Java là đồng nhất trong tất cả các nền tảng
phát triển. Java có các lớp thư viện cơ sở. Điều này cho phép các lập trình viên
có thể di chuyển mã từ nền tảng này đến một nền tảng khác mà không cần viết
lại mã.
Chương 1 Giới thiệu về Java
7/114
Nói tóm lại, độc lập nền tảng ở mức mã nguồn cho phép di chuyển mã nguồn từ
một hệ thống này sang một hệ thống khác, biên dịch và thực hiện êm xuôi trên
mọi hệ thống.
Sử dụng mã bytecode, Java đã giải quyết vấn đề độc lập nền tảng. Không giống
như trình biên dịch của C, trình biên dịch Java đưa ra một định dạng đặc biệt, đó
là bytecode, giống nhau trên mọi nền tảng.
Các chương trình Java được biên dịch thành bytecode vẫn cần một trình thông
dịch để thực thi nó trên bất kỳ một nền tảng đã định sẵn nào. Công việc của trình
thông dịch là đọc mã bytecode và chuyển nó thành ngôn ngữ máy.
Để chạy Java trên một máy tính hoặc một hệ điều hành mới, chỉ cần trình thông
dịch và một vài gói thư viện cần thiết. Bởi vì bytecode là độc lập nền tảng.
Mạnh mẽ
Java là ngôn ngữ định kiểu mạnh mẽ. Nó được thiết kế để viết các phần mềm có
độ tin cậy cao và mạnh. Tuy nhiên, nó yêu cầu phải khai báo các phương thức
một cách rõ ràng. Java kiểm tra lỗi cú pháp tại thời điểm biên dịch, và tại thời
điểm thông dịch. Vì vậy, nó chắc chắn loại bỏ một số lỗi trong lập trình.
Java không có con trỏ và phép tính con trỏ. Nó kiểm tra tất cả truy nhập đến
mảng và chuỗi tại thời điểm chạy chương trình. Ngoài ra nó còn kiểm tra sự
chuyển kiểu của đối tượng từ kiểu này đến kiểu khác tại thời điểm chạy chương
trình.
Trong các môi trường lập trình truyền thống, lập trình viên phải tự cấp phát bộ
nhớ. Kết thúc chương trình, lập trình viên phải giải phóng vùng bộ nhớ này. Các
sự cố sẽ nảy sinh khi lập trình viên quên giải phóng bộ nhớ. Trong Java, lập trình
viên không cần quan tâm đến việc giải phóng bộ nhớ. Nó được thực hiện tự
động bởi bộ thu gom rác (garbage collection).
An toàn (Secure)
Virus máy tính là nguyên nhân gây ra sự lo lắng trong việc sử dụng máy tính.
Trước khi có Java, các lập trình viên phải quét virus các tập tin trước khi tải về
và thực hiện chúng. Thông thường việc này cũng không loại trừ hoàn toàn virus.
Ngoài ra, chương trình khi thực thi có khả năng tìm kiếm và đọc các thông tin
nhạy cảm trên máy của người sử dụng mà người sử dụng không hề hay biết.
Java cung cấp một môi trường quản lý việc thực thi chương trình. Nó cho rằng
không có một đoạn mã nào là an toàn cả. Vì thế, Java không chỉ là ngôn ngữ lập
Learn Java by Example
8/114 AptechVietnam
trình thuần tuý mà còn cung cấp nhiều mức để kiểm soát tính an toàn khi thực thi
chương trình.
Ở mức đầu tiên, dữ liệu và các phương thức được truy nhập thông qua các
interface (giao tiếp) do lớp cung cấp. Java không hỗ trợ các phép toán con trỏ.
Do đó, nó không cho phép truy nhập trực tiếp đến các vùng nhớ và cung cấp cơ
chế thu gom rác giúp thu hồi bộ nhớ không sử dụng. Các đặc trưng này giúp
Java an toàn tối đa và có khả năng khả chuyển cao.
Trong mức thứ hai, trình biên dịch kiểm soát để đảm bảo mã là an toàn, và tuân
theo các nguyên tắc của Java.
Mức thứ ba, được đảm bảo bởi trình thông dịch. Chúng kiểm tra xem bytecode
phải đảm bảo các qui tắc an toàn trước khi thực thi.
Mức thứ tư, kiểm soát việc nạp các lớp vào bộ nhớ để giám sát việc vi phạm giới
hạn truy xuất trước khi nạp vào hệ thống.
Phân tán (Distributed)
Java có thể được dùng để phát triển các ứng dụng trên nhiều nền tảng, hệ điều
hành và nhiều giao tiếp người dùng đồ hoạ. Java được thiết kế để hỗ trợ các
ứng dụng trên mạng. Do đó, Java được dùng như là một công cụ phát triển trên
môi trường Internet.
Đa luồng (Multithreaded)
Đa luồng là yếu tố cần thiết cho một ngôn ngữ như Java. Một ứng dụng thực
hiện một tác vụ trong khi đang chờ người dùng nhập liệu. Trong một ứng dụng
đồ hoạ trên mạng như một trình duyệt web, thường có rất nhiều tác vụ xảy ra tại
một thời điểm. Java cung cấp hỗ trợ cho xử lý gọi là “multithreading” để thực
hiện nhiều tác vụ đồng thời. Java cung cấp cơ chế đồng bộ nhiều xử lý. Cơ chế
này cũng hỗ trợ cho luồng (thread) giúp các ứng dụng tương tác trên mạng chạy
êm xuôi.
Động (Dynamic)
Java được thiết kế như một ngôn ngữ động để đáp ứng cho những môi trường
mở. Mã nguồn Java được lưu trữ trong tập tin có dạng .java. Trình biên dịch sẽ
biên dịch chúng thành bytecode chứa trong tập tin .class. Mỗi tập tin .java
thường được biên dịch thành một tập tin .class.
Đầu tiên trình biên dịch kiểm tra đường dẫn trên thư mục hiện hành và các thư
mục khác được xác định trong biến môi trường CLASSPATH. Điều này cần thiết
giúp xác định các lớp khác được tham chiếu trong tập tin nguồn. Ví dụ, nếu tập
tin được biên dịch phụ thuộc vào các tập tin không được biên dịch khác, trình
biên dịch sẽ cố tìm và biên dịch chúng. Trình biên dịch có thể điều khiển sự phụ
thuộc vòng tròn cũng như các phương thức được sử dụng trước khi được khai
báo. Nó cũng xác định tập tin nguồn có thay đổi so với lần biên dịch cuối cùng
hay không. Vì vậy, trình biên dịch khá thông minh.
Chương 1 Giới thiệu về Java
9/114
Kiến trúc trung lập (Architecture-neutral)
Công nghệ Java được thiết kế để hỗ trợ các ứng dụng sẽ được triển khai trong
các môi trường không đồng nhất trên mạng. Trong các môi trường như vậy, các
ứng dụng phải có khả năng thực thi tốt trên nhiều kiến trúc phần cứng.
Các chương trình Java được biên dịch thành một định dạng bytecode không phụ
thuộc kiến trúc có thể thực thi trên nhiều nền tảng phần cứng và phần mềm. Vì
vậy, vấn đề phân phối nhị phân và phiên bản được giải quyết bởi bản chất thông
dịch của công nghệ Java.
Các chương trình Java chạy trên bất kỳ hệ thống nào có hỗ trợ máy ảo Java.
Điều này không những hữu ích trên mạng mà còn có ích trên các hệ thống phân
tán.
Khả chuyển (Portable)
Khả chuyển là hệ quả của kiến trúc trung lập. Công nghệ Java có được khả năng
khả chuyển là nhờ vào định nghĩa chặt chẽ của ngôn ngữ. Nó chỉ rõ kích thước
của các kiểu dữ liệu cơ bản để loại trừ sự phụ thuộc cài đặt và hành vi của các
toán tử số học. Hệ thống Java bản thân là khả chuyển. Trình biên dịch Java
được viết bằng Java, trong khi hệ thống thực thi Java được viết bằng ANSI C với
ranh giới khả chuyển rõ ràng.
Hiệu suất cao (high performance)
Hiệu suất luôn được cân nhắc. So với các ngôn ngữ kịch bản thông dịch mức
cao, Java có hiệu suất cao nhất. Bộ thu gom rác tự động thực hiện như luồng
ngầm bên dưới, có độ ưu tiên thấp nhất, đảm bảo khả năng khả chuyển cao
nhất. Sun khẳng định khả năng thực thi của bytecode chuyển thành mã máy tốt
gần như C hoặc C++.
1.3 Giới thiệu JDK
Sun Microsystems cung cấp ngôn ngữ Java trong sản phẩm gọi là Java
Development Kit (JDK). JDK bao gồm các công cụ phát triển, môi trường thực thi
(Java Runtime Environment hay JRE), các thư viện, các chương trình demo và
mã nguồn. Một số công cụ nằm trong JDK dùng phát triển các ứng dụng Java
được mô tả dưới đây:
Trình biên dịch Java, „Javac‟
Trình biên dịch dịch mã nguồn Java thành tập tin class. Trình biên dịch javac
được dùng để biên dịch các tập tin mã nguồn Java thành bytecode. Mã nguồn
Java có thể được tạo ra bằng bất kỳ trình soạn thảo văn bản nào, chẳng hạn
Notepad
Cú pháp:
Javac [option] source
Learn Java by Example
10/114 AptechVietnam
Trong đó,
source - 1 hoặc nhiều tên tập tin có phần mở rộng là .java
option - Các tuỳ chọn dòng lệnh
Ví dụ,
Javac FirstProgram.java
Câu lệnh này sẽ tạo ra một tập tin có tên „FirstProgram.class‟. Tập tin class này
sẽ chạy trên máy ảo Java (JVM). Một vài tuỳ chọn của câu lệnh javac được mô
tả trong bảng 1.3
Tùy chọn
(Option)
Mô tả
-classpath
Xác định rõ vị trí chứa các lớp được tham chiếu
trong mã nguồn (được lưu trong biến môi trường
CLASSPATH)
-d
Xác định thư mục đích chứa các tập tin .class
-g
In tất cả các thông tin gỡ lỗi thay cho số dòng và
tên tập tin mặc định.
-verbose
Hiển thị các thông tin đầu ra mỗi lần lớp được nạp
và tập tin nguồn được biên dịch.
-version
Hiển thị thông tin về phiên bản
-sourcepath
Cho biết vị trí lớp
-help
Hiển thị các tuỳ chọn chuẩn
Bảng 1.3: Các tuỳ chọn của trình biên dịch Javac
Xem xét ví dụ sau sử dụng tuỳ chọn –d:
javac –d c:\FirstProgram.java
Câu lệnh này sẽ biên dịch và lưu tập tin „FirstProgram.class‟ trong ổ đĩa C.
Trình thông dịch Java, „Java‟
Trình thông dịch Java được sử dụng để thực thi mã bytecode. Nó lấy đối số là
tên tập tin .class để thực thi hoặc tên tập tin lưu trữ Java gọi là jar.
Cú pháp:
Chương 1 Giới thiệu về Java
11/114
java [option] classname [arguments]
Trong đó,
option - Các tuỳ chọn dòng lệnh
classname - Tên tập tin class được dùng
arguments - Đối số được truyền vào cho hàm main
Ví dụ,
Java FirstProgram
Một vài tuỳ chọn của câu lệnh Java được mô tả trong bảng 1.4
Tùy chọn
Mô tả
-classpath
Xác định rõ vị trí chứa các lớp cần (được lưu
trong biến môi trường CLASSPATH)
-v hoặc
–verbose
Hiển thị các thông tin đầu ra mỗi lần lớp được
nạp và tập tin nguồn được biên dịch.
-version
Hiển thị thông tin về phiên bản và thoát
-jar
Sử dụng tên tập tin JAR thay cho tập tin class
-help
Hiển thị thông tin trợ giúp về lệnh Java và thoát
-X
Hiển thị thông tin và các tùy chọn phi chuẩn và
thoát
Bảng 1.4: Các tuỳ chọn của trình thông dịch Java
1.4 Máy ảo Java (Java Virtual Machine - JVM)
Máy ảo Java là trái tim của ngôn ngữ lập trình Java. Môi trường Java bao gồm
năm phần tử sau:
Ngôn ngữ
Ðịnh nghĩa Bytecode
Các thư viện lớp Java/Sun
Máy ảo Java (JVM)
Cấu trúc của tập tin .class
Learn Java by Example
12/114 AptechVietnam
Đặc tính khả chuyển của tập tin .class cho phép các chương trình Java viết một
lần chạy mọi nơi (“Write once, run anywhere”). Đặc tính này có được nhờ sự cài
đặt máy ảo Java (JVM).
1.4.1 Máy ảo Java là gì?
Lập trình viên cần thiết phải biết máy ảo Java là gì và cách làm việc của nó. Điều
này sẽ giúp ta tận dụng được điểm mạnh của JVM và tránh những điểm yếu.
Máy ảo là một khái niệm phần mềm dựa trên ý tưởng của máy tính tưởng tượng.
Nó có tập hợp các lệnh logic để xác định các hoạt động của máy tính. Máy ảo có
thể được xem như một hệ điều hành thu nhỏ. Nó thiết lập các lớp trừu tượng
cho: phần cứng bên dưới, hệ điều hành, mã biên dịch.
Trình biên dịch chuyển mã nguồn thành tập các lệnh của máy ảo không phụ
thuộc vào phần cứng riêng biệt. Trình thông dịch là một ứng dụng hiểu các lệnh
của máy ảo và chuyển các lệnh đó thành các lệnh thực hiện trên phần cứng bên
dưới. Máy ảo, về cơ bản, tạo ra một hệ thống thực thi giúp thực hiện các mã
lệnh bằng cách:
Nạp các tập tin .class
Các trình “Class Loaders” là một trong các thành phần cơ bản của kiến
trúc máy ảo Java. Nó cho phép máy ảo Java nạp các lớp mà không cần
biết bất cứ thứ gì về ngữ nghĩa hệ thống tập tin và cho phép các ứng
dụng nạp các lớp Java như các module mở rộng.
Quản lý bộ nhớ
Máy ảo Java quản lý bộ nhớ theo các cách sau:
Khi một máy ảo Java được triệu gọi để chạy một ứng dụng, nó yêu
cầu hệ điều hành cấp đủ bộ nhớ cho bản thân JVM chạy và bộ nhớ
trống cho các ứng dụng tạo các đối tượng mới.
Khi một đối tượng mới được tạo, JVM cấp phát bộ nhớ cho đối
tượng đó từ vùng nhớ trống.
Khi vùng nhớ trống giảm xuống sau khi tạo một số đối tượng, JVM
yêu cầu hệ điều hành cấp thêm.
Khi một đối tượng không còn được dùng nó sẽ bị huỷ bỏ. Bộ nhớ bị
chiếm dụng sẽ được giải phóng và trả lại vùng bộ nhớ trống.
Khi vùng nhớ trống bị chiếm giữ, và không thể xin cấp thêm vùng
nhớ từ hệ điều hành thì JVM tạm dừng ứng dụng và đưa ra thông
báo lỗi “Out of memory error”.
Thực hiện thu gom “rác” (Garbage Collection)
Quá trình thu gom rác là giải phóng bộ nhớ đang sử dụng của một đối tượng
ngay khi nó kết thúc, nghĩa là đối tượng đó không được truy nhập sau một thời
Chương 1 Giới thiệu về Java
13/114
gian dài. Quá trình này xảy ra tự động và an toàn đối với các đối tượng không
còn cần tham chiếu đến nữa.
Khi máy ảo Java thực thi mã, một thanh ghi cục bộ gọi là „program counter‟ được
dùng. Thanh ghi này trỏ đến các lệnh đang được thực thi hiện tại. Nếu cần thiết,
các lệnh này sửa nội dung thanh ghi này để thay đổi luồng thực thi. Mặt khác,
luồng được thực hiện tuần tự nên nó trỏ từ lệnh này đến lệnh khác.
Một khái niệm phổ biến khác được dùng trong Java là trình biên dịch JIT – Just-
In-Time. Các trình duyệt web như Netscape Navigator, Internet Explorer bao
gồm trình biên dịch JIT nhằm tăng tốc độ thực thi mã Java. Mục đích chính của
JIT là chuyển đổi mã bytecode sang mã máy ứng với từng bộ vi xử lý cụ thể.
Các lệnh này được lưu trữ và dùng bất cứ lúc nào, được gọi như là một phương
thức xác định. Hình 1.3 hiển thị mối quan hệ giữa trình biên dịch Java và JIT.
Hình 1.3: Mối quan hệ giữa trình biên dịch Java và JIT
Mã chương trình được biên dịch và chạy thông qua một máy ảo thay cho vi xử lý
của máy tính. Bằng cách sử dụng cách tiếp cận này, mã nguồn Java có thể chạy
trên bất kỳ nền tảng nào, nó được biên dịch và chạy thông qua máy ảo Java.
Máy ảo Java không biết gì về ngôn ngữ lập trình Java, nó chỉ nhận ra một định
dạng nhị phân xác định của một file gọi là file class. Các chương trình Java được
biên dịch thành mã bytecode có thể tuyền trên mạng và thực thi bởi máy ảo
Java. Mỗi file class chứa định nghĩa của một lớp hoặc một giao tiếp. File
bytecode có phần tên mở rộng là .class
Learn Java by Example
14/114 AptechVietnam
Tóm Tắt Bài Học
Một đối tượng là một thể hiện của một lớp.
Một lớp định nghĩa một thực thể trên giới hạn của các tính chất và hành
động phổ biến.
Một lớp định nghĩa một thực thể, trong khi đó một đối tượng là một thực
thể thực sự.
Java là một ngôn ngữ thông dịch và biên dịch.
Các tính năng của Java:
o Hướng đối tượng
o Độc lập nền tảng
o Mạnh mẽ
o An toàn
o Phân tán
o Đa luồng
o Động
o Kiến trúc trung lập
o Khả chuyển
o Hiệu suất cao
Sun Microsystems giới thiệu ngôn ngữ Java như là một sản phẩm dưới
tên gọi Java Development Kit (JDK)
Bên trong máy ảo, Java tạo ra một hệ thống thời gian thực giúp thực thi
mã lệnh như sau:
o Nạp các files .class
o Quản lý bộ nhớ
o Thực thi việc thu gom rác
AptechVietnam 15/114
t
Chương 2: Biến và toán tử
Mục tiêu bài học
Kết thúc bài học này, học viên có thể:
Cú pháp khai báo biến
Định nghĩa các kiểu dữ liệu cơ bản
Tìm hiểu và giải thích cấu trúc của một lớp
Mô tả các kiểu định dạng
Mô tả các ký tự đặc biệt (escape sequences)
Xác định các toán tử khác nhau
2.1 Biến
Biến là đơn vị lưu trữ cơ bản trong chương trình Java. Biến là các thành phần
xác định dữ liệu và được dùng để tham chiếu đến các giá trị xác định được tạo
ra trong chương trình. Đặt tên các biến có ý nghĩa giúp ta dễ dàng đọc hiểu mã
nguồn hơn.
2.1.1 Khai báo biến
Tất cả các biến phải được khai báo trước khi sử dụng. Dạng khai báo biến cơ
bản là:
datatype variablename;
Trong đó,
datatype - Kiểu dữ liệu hợp lệ
variablename - Tên biến hợp lệ
Các biến có thể khai báo và khởi tạo theo nhiều cách khác nhau, được minh hoạ
trong đoạn mã 1.
Đoạn mã 1:
Line0: int x,y,z; //Khai báo 3 biến kiểu int x,y
//và z
Learn Java by Example
16/114 AptechVietnam
Line1: int a=5,b,c=10; //Khai báo 3 biến kiểu int
//, khởi tạo a và c
Line2: byte num=20; // Khai báo 1 biến num có kiểu
//byte và khởi tạo giá trị là 20
Line3: char c=‟c‟; //Khai báo c là biến có kiểu
//char, khởi tạo giá trị là c
Line4: int num1=num2=10; //Giá trị 10 được lưu trữ
//trong num1 và num2
Line0 và Line1 là các ví dụ về khai báo danh sách các biến được cách nhau bởi
dấu phẩy và Line4 là ví dụ về gán một giá trị cho một hoặc nhiều biến lúc khai
báo biến.
Đoạn mã 2 là một ví dụ về gán các giá trị hệ bát phân (8) và hệ thập lục phân
(16) cho các biến.
Đoạn mã 2:
Line1: int decVal = 10;//giá trị 10 trong hệ
// thập phân (hệ 10)
Line2: int octVal = 012;//giá trị 10 trong hệ
// bát phân (hệ 8)
Line3: int hexVal = 0xa;//giá trị 10 trong hệ
// thập lục phân (hệ 16)
Đoạn mã 2 hiển thị cú pháp đúng để chứa các giá trị trong hệ bát phân và hệ
thập lục phân. Line2 biểu diễn một định dạng trong hệ bát phân với tiếp đầu ngữ
0. Hệ thống số bác phân có 8 ký tự số từ 0 đến 7 để mô tả các số.
Line3 biểu diễn định dạng trong hệ thập lục phân với tiếp đầu ngữ 0x. Hệ thống
số thập lục phân có 16 ký tự số để mô tả các số, từ 0 đến 9 và từ ký tự A đến F.
Từ A đến F tương ứng từ 10 đến 15. Ví dụ, giá trị 26 trong hệ 16 là:
int hexVal = 0x1a;
Hệ thống thập phân được mô tả trong Line1, là cách dùng thông dụng trong lập
trình.
Chương 2 Biến và toán tử
17/114
2.1.2 Khai báo hằng (literals)
Hằng là một giá trị không đổi và được mô tả trực tiếp trong đoạn mã mà không
cần đến tính toán. Ví dụ,
Đoạn mã 3:
Line1: int val = 50;
Line2: float num = 35.7F;
Line3: char x = „x‟;
Một hằng được sử dụng ở bất kỳ nơi nào cho phép kiểu giá trị của nó. Tuy
nhiên, có nhiều kiểu hằng khác nhau. Một vài trong số chúng là:
Hằng nguyên (Integer literals)
Hằng nguyên được dùng để biểu diễn một giá trị nguyên (int), trong Java là một
giá trị số nguyên 32 bit. Trong một chương trình, số nguyên là kiểu thường được
sử dụng nhất. Bất kỳ một giá trị số nguyên nào đều là một hằng số nguyên.
Các số nguyên có thể biểu diễn như:
Các giá trị thập phân được biểu diễn trong hệ cơ số 10
Các giá trị bát phân được biểu diễn trong hệ cơ số 8
Các giá trị thập lục phân được biểu diễn trong hệ cơ số 16
Mỗi một loại trên có hằng tương ứng. Một hằng số nguyên có thể được gán đến
một kiểu số nguyên khác như byte hoặc long. Khi một giá trị hằng được gán đến
một biến kiểu byte hoặc short, sẽ không có lỗi nếu giá trị hằng nằm trong phạm vi
của kiểu đích. Các số nguyên có thể được biểu diễn với một ký tự hoa („L‟)hoặc
thường („l‟) ở cuối, để biểu diễn một số nguyên dài 64 bit.
Hằng dấu chấm động (floating-point literals)
Các hằng số thực biểu diễn các giá trị thập phân với phần lẻ. Các hằng số thực
có các thành phần sau:
Thành phần số, ví dụ 0, 1, 2, …, 9
Dấu thập phân, ví dụ 4.90, 3.141
Số mũ được biểu diễn bởi E hoặc e đi theo sau một số thập phân
có thể dương hoặc âm. Ví dụ: e+208, 7.436E6, 23763E-05, …
Kiểu hậu tố D, d, F hoặc f
Learn Java by Example
18/114 AptechVietnam
Trong Java, các hằng số thực, ngầm định, có độ chính xác double. Một hằng
float được biểu diễn bởi F hoặc f, theo sau là giá trị, và một hằng số thực double
được biểu diễn bởi D hoặc d.
Hằng Boolean (boolean literals)
Các hằng boolean đơn giản và chỉ có hai giá trị logic là true và false. Các giá trị
này không thể chuyển đổi đến bất kỳ hệ thống số nào. Trong Java, true không
bằng 1 và false không bằng 0. Nó chỉ có thể gán đến các biến được khi báo là
boolean hoặc dùng trong các biểu thức với các toán tử boolean.
Hằng ký tự (character literals)
Các hằng ký tự được đặt trong cặp dấu ngoặc đơn. Tất cả các ký tự ASCII hợp
lệ có thể đặt trực tiếp trong cặp dấu ngoặc đơn, như „g‟, „$‟ và „z‟.
Hằng Null (null literals)
Khi một đối tượng được tạo, lượng bộ nhớ xác định được cấp phát cho đối
tượng. Địa chỉ bắt đầu của bộ nhớ được lưu trong đối tượng, đó là, một biến
tham chiếu. Tuy nhiên đôi khi, biến tham chiếu không tham chiếu đến đối tượng.
Trong hợp này, biến tham chiếu được gán một hằng null như ví dụ bên dưới:
obj = null ;
Hằng chuỗi (String literals)
Hằng chuỗi chứa chuỗi các ký tự trong cập dấu ngoặc kép. Các ký tự có thể là
ký tự thường, có thể đọc được trên màn hình, hoặc ký tự điều khiển, không nhìn
thấy được trên màn hình. Các dấu vạch chéo ngược, dấu nháy kép và các ký tự
điều khiển khác có thể được biểu diễn bằng dấu chéo ngược (\) đi kèm với mã
điều khiển, các ký tự này còn gọi là escape sequences. Ví dụ sau là một xâu
thường, không có ký tự điều khiển:
“Welcome to Java”
2.2 Kiểu dữ liệu (Data type)
Chương 2 Biến và toán tử
19/114
Các ứng dụng xử lý dữ liệu đầu vào và xuất dữ liệu kết quả. Đầu vào, đầu ra, và
kết quả của các quá trình tính toán đều liên quan đến dữ liệu. Trong môi trường
tính toán, dữ liệu được phân lớp theo các tiêu chí khác nhau phụ thuộc vào bản
chất của nó. Ở mỗi tiêu chí, dữ liệu có một tính chất xác định và có một kiểu thể
hiện riêng biệt.
Java cung cấp một vài kiểu dữ liệu mà chúng được hỗ trợ trên tất cả các nền
tảng. Ví dụ, dữ liệu loại int (integer) của Java được thể hiện bằng 4 bytes trong
bộ nhớ của tất cả các loại máy bất luận ở đâu chạy chương trình Java. Bởi vậy
các chương trình Java không cần phải thay đổi khi chạy trên các nền khác nhau.
Trong Java kiểu dữ liệu được chia thành hai loại:
Các kiểu dữ liệu nguyên thủy (primitive)
Các kiểu dữ liệu tham chiếu (reference)
2.2.1 Các kiểu dữ liệu nguyên thuỷ (Primitive Data Type)
Java hỗ trợ tám kiểu dữ liệu nguyên thuỷ được chia ra thành 4 nhóm:
Kiểu số nguyên (Integer)
Trong nhóm này có các kiểu dữ liệu: byte, short, int và long và, hầu hết, biểu
diễn các giá trị số nguyên có dấu.
Kiểu dấu chấm động (Floating-point)
Trong nhóm này có các kiểu dữ liệu: float và double và biểu diễn các số có phần
thập phân.
Kiểu ký tự (Character)
Nhóm này có kiểu dữ liệu char, biểu diễn các ký hiệu trong tập hợp các ký tự
như ký tự chữ cái và ký tự số.
Kiểu Boolean
Kiểu dữ liệu boolean thuộc nhóm này và biểu diễn cho hai giá trị true (Đúng)
hoặc false (Sai).
Learn Java by Example
20/114 AptechVietnam
Kiểu dữ liệu số nguyên gồm 4 loại:
Kiểu byte
Dùng để lưu trữ lượng dữ liệu nhỏ. Đây là kiểu dữ liệu có độ dài 8 bit, phạm vi
lưu trữ từ -128 đến 127. Nó thường được dùng khi làm việc với luồng dữ liệu từ
mạng hoặc từ file. Kiểu dữ liệu này thường dùng khi làm việc với dữ liệu nhị
phân chuẩn và có thể không tương thích với các kiểu dữ liệu khác của Java. Từ
khoá byte được dùng trong khai báo một biến kiểu này. Ví dụ:
byte val;
Kiểu short
Đây là kiểu dữ liệu ít dùng nhất. Có độ dài 16 bit và phạm vi lưu trữ từ -
32.768 đến 32.767. Kiểu dữ liệu này thường dùng cho các ứng dụng trên các
máy tính 16 bit. Kiểu dữ liệu này cũng được dùng để lưu trữ dữ liệu số nhỏ. Từ
khoá short dùng để khai báo biến kiểu này.
Kiểu int
Đây là kiểu dữ liệu thường dùng nhất. Nó có độ dài 32 bit, với phạm vi lưu trữ từ
-2.147.483.648 đến 2.147.483.647. Kiểu int là kiểu linh hoạt và hiệu quả nhất. Ví
dụ: Tổng số lương phải trả cho tất cả nhân viên trong công ty.
Kiểu long
long là kiểu dữ liệu 64 bit có dấu, với phạm vi lưu trữ từ
-9.223.372.036.854.775.808 đến +9.223.372.036.854.775.807. Nó được dùng
khi kiểu int không đủ để lưu một số lớn hơn phạm vi của nó. Ví dụ, dân số của
một nước.
2.2.2 Các kiểu dữ liệu tham chiếu
Trong Java, các đối tượng và các mảng là các biến tham chiếu. Khi một đối
tượng hoặc một mảng được tạo, một vùng nhớ nhất định được gán cho nó và
địa chỉ của vùng nhớ này được lưu trữ trong biến tham chiếu. Nói cách khác,
kiểu dữ liệu tham chiếu là địa chỉ của một đối tượng hoặc một mảng được tạo ra
trong bộ nhớ.
Chương 2 Biến và toán tử
21/114
2.3 Định dạng nhập và xuất
Bất cứ khi nào kết quả hiển thị trên màn hình, thì cần phải được định dạng. Java
cung cấp các ký tự điều khiển định dạng (escape sequence) để thực hiện định
dạng các dữ liệu nhập và xuất
2.3.1 Định dạng xuất
Có thể định dạng theo 2 cách:
print() và println()
format()
Các phương thức này hoạt động tương tự nhau. Phương thức format()dùng lớp
Java.util.Formatter để thực hiện nhiều định dạng phức tạp hơn.
Các phương thức print() và println()
Các phương thức này chuyển dữ liệu dùng phương thức toString thích hợp và
trả lại một giá trị chuỗi. Hãy xem xét đoạn mã 4.
Đoạn mã 4:
int num1 = 5;
int num2 = 10;
int sum = num1 + num2;
System.out.print(“The sum of”);
System.out.print(num1);
System.out.print(“ and ”);
System.out.print(num2);
System.out.print(“ is “);
System.out.print(sum);
System.out.println(“.”);
Learn Java by Example
22/114 AptechVietnam
int num3 = 2;
sum = num1 + num2 + num3;
System.out.println(“The sum of ” + num1 + “, ” + num2 + “
and ” + num3 + “ is ” + sum + “.”);
Kết quả của đoạn mã trên là:
The sum of 5 and 10 is 15.
The sum of 5, 10, and 2 is 17.
Biến sum được định dạng hai lần: lần đầu trong lệnh print; lần thứ hai bằng mã
chuyển được tự động tạo ra bởi trình biên dịch Java và sử dụng phương thức
toString. Trong trường hợp này, bất kỳ giá trị nào cũng có thể được định dạng.
Phương thức format()
Phương thức này định dạng nhiều đối số dựa trên một chuỗi định dạng. Chuỗi
định dạng chứa cả phần định dạng lẫn hằng chuỗi bình thường nhưng nó không
kết hợp với bất kỳ một đối số nào. Các chuỗi định dạng hỗ trợ nhiều đặc tính.
Thành phần định dạng bắt đầu bằng dấu %. Ví dụ,
System.out.println(“%d”, + sum);
Câu lệnh này hiển thị giá trị nguyên của biến sum.
Cú pháp của một chuỗi định dạng như sau:
Cú pháp:
%[arg_index$][flags][width][.precision]conversion character
Trong đó,
arg_index – Là một số nguyên theo sau là $. Số nguyên cho biết đối số sẽ
được in tại vị trí được đề cập.
flags – Có nhiều biến cờ khác nhau trong Java như bảng 2.1
Flag (Cờ)
Mô tả
“-“
Đối số được canh thẳng theo bên trái
“+”
Chèn một dấu + hoặc - với đối số này
Chương 2 Biến và toán tử
23/114
“0”
Dẫn đầu đối số này với các số 0
“,”
Dùng dấu ngăn cách nhóm
“(“
Số âm được bao quanh bằng dấu
ngoặc đơn
Bảng 2.1: Kiểu của các flag
width - Xác định số tối thiểu các ký tự sẽ được in
precision – xác định số ký tự số sẽ được in sau dấu thập phân. Dùng với
các số dấu chấm động.
conversion character - Kiểu của đối số được định dạng. Ví dụ, b là
boolean, c là char, d là số nguyên, ….
Các giá trị đặt trong cặp dấu “[]” là tùy chọn. Chỉ các thành phần yêu cầu xác
định định dạng là dấu % và ký tự chuyển đổi.
Đoạn mã 5 minh họa cách sử dụng phương thức format()
int val = 5;
double sq = 2.236068;
System.out.format("The square root of %d is %f.%n",val,sq);
Kết quả của đoạn mã trên như sau:
The square root of 5 is 2.236068.
2.3.2 Ký tự điều khiển (escape sequences)
Ký tự điều khiển được dùng để biểu diễn các ký tự đặc biệt. Các ký tự điều khiển
có thể dùng cho hằng ký tự hoặc hằng chuỗi.
Bảng 2.2 giới thiệu một vài ký tự đặc biệt trong Java
Learn Java by Example
24/114 AptechVietnam
Ký tự đặc biệt
Giá trị ký tự
\f
Cuộn trang giấy vào máy in (Form feed)
\r
Xuống hàng (Carriage return)
\xxx
Ký tự tương ứng với giá trị bát phân xxx, xxx nằm
trong khoảng 000 đến 0377.
\uxxxx
Ký tự unicode với mã hoá xxxx, trong đó xxxx là
một số thập lục phân gồm 4 ký số.
Bảng 2.2: Ký tự điều khiển (Escape sequence)
Để biểu diễn một ký tự unicode , ký tự điều khiển unicode \u có thể được dùng
trong chương trình Java. Một ký tự unicode có thể được biểu diễn bằng một
chuỗi thập lục phân hoặc bát phân. Đoạn mã 6 minh hoạ vấn đề này.
Đoạn mã 6:
// In „Hello‟ sử dụng chuỗi thập lục phân
System.out.println("\u0048\u0065\u006C\u006C\u006F" +
"!\n");
//In „Blake‟ sử dụng chuỗi bát phân cho ký tự „a‟
System.out.println("Bl\141ke\"2007\"");
Chú ý: Các ký tự điều khiển thập lục phân bắt đầu với \u, theo sau là 4 ký số hệ
thập lục phân. Các ký tự điều khiển bát phân gồm 3 ký số sau dấu \. Ví dụ:
\xyy
Trong đó, x có thể bất kỳ ký số nào từ 0 đến 3, y từ 0 đến 7.
Kết quả đoạn mã 6 là:
Hello!
Blake”2007”
Hai kiểu ký tự điều khiển có thể có nghĩa khác nhau bởi vì ký tự đặc biệt \u được
xử lý trước các ký tự đặc biệt khác.
Chương 2 Biến và toán tử
25/114
2.4 Các toán tử
Các toán tử kết hợp với các biến đơn hoặc các biểu thức thành các biểu thức
mới phức tạp hơn mà nó trả lại các giá trị.
2.4.1 Loại toán tử
Java cung cấp các loại toán tử khác nhau như sau:
Toán tử số học
Các toán tử số học được dùng trong các biểu thức toán học. Các toán hạng của
các toán tử số học phải ở dạng số. Các toán hạng kiểu boolean không sử dụng
được, song các toán hạng ký tự cho phép sử dụng với loại toán tử này.
Toán tử quan hệ
Các toán tử quan hệ kiểm tra mối quan hệ giữa hai toán hạng. Kết quả của một
biểu thức có dùng các toán tử quan hệ là những giá trị boolean, true (đúng) hoặc
false (sai).
Toán tử logic
Các toán tử logic làm việc với các toán hạng boolean.
Toán tử gán
Toán tử gán là một dấu bằng, =, dùng để gán giá trị cho một biến. Có thể gán giá
trị cho một hoặc nhiều biến kế tiếp nhau. Nghĩa là, có thể sử dụng một dãy các
phép gán.
Toán tử thao tác bit (bitwise)
Một toán tử bitwise cho phép ta thao tác trên từng bit riêng biệt trong các kiểu dữ
liệu nguyên thuỷ. Toán tử bitwise dựa trên cơ sở đại số boolean. Nó thực hiện