You are on page 1of 18

Đề 1

Câu 1: các nguyên lý:


-Trừu tượng hóa
• Là quá trình loại bỏ đi các thông tin cụ thể và giữ lại những thông tin chung.
• Tập trung vào các đặc điểm cơ bản của thực thể, các đặc điểm phân biệt nó với các loại thực thể
khác.
• Phụ thuộc vào góc nhìn
• Quan trọng trong ngữ cảnh này nhưng lại không có ý nghĩa nhiều trong ngữ cảnh khác
-Đóng gói
+Che giấu, ẩn đi chi tiết thực hiện bên trong
+Cung cấp cho thế giới bên ngoài một giao diện
+Người dùng không phụ thuộc vào việc sửađổi sự thực thi bên trong rong ngữ cảnh khác.

+Cho phép điều khiển:


Việc sửdụng đối tượng được kiểm soát thông qua các method public
+Hỗ trợ sự thayđổi:
Việc sửdụng đối tượng không bị ảnh hưởng nếu dữ liệu nội tại (private) bị thay đổi
+Cho phép module hóa
• Chia nhỏ hệ thống phức tạp thành những thành phần nhỏ có thể quản lý được.
• Cho phép người dùng hiểu được về hệ thống
- Thừa kế
• Phân cấp
+Xếp hạng hay xếp thứ tự các mức trừu tượng vào một cấu trúc cây
+Các phần tử ở cùng cấp trong sơ đồ phân cấp thì có cùng mức trừu tượng hóa
+Tổ chức để phân loại. Sửdụng phân cấp rất dễ dàng
nhận ra sửgiống và khác nhau giữa các đối tượng

-Đa hình
• Polymorphism: Nhiều hình thức thực hiện, nhiều kiểu tồn tại
• Đa hình trong lập trình
+Đa hình phương thức: Phương thức trùng tên, phân biệt bởi danh sách tham số.
• Đa hình đối tượng : Nhìn nhận đối tượng theo nhiều kiểu khác nhau
• Các đối tượng khác nhau cùng đáp ứng chung danh sách các thông điệp có giải nghĩa thông điệp
theo cách thức khác nhau.
 Mã java nguyên lý kế thừa:
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
public void wagTail() {
System.out.println("Dog wags its tail");
}
}
class Cat extends Animal {
@Override
public void sound() {
System.out.println("Cat meows");
}
public void purr() {
System.out.println("Cat purrs");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound();
dog.wagTail();
Cat cat = new Cat();
cat.sound();
cat.purr();
}
}
Câu 2:
+---------------------------------+
| CourseSystem |
+---------------------------------+
| - courses: List<Course> |
+---------------------------------+
| + addCourse(course: Course): void |
| + removeCourse(course: Course): void |
| + getCourseList(): List<Course> |
+---------------------------------+

+-----------------------+ +---------------------+
| Course |<>---------| Student |
+-----------------------+ +---------------------+
| - courseId: int | | - studentId: int |
| - courseName: String | | - studentName: String |
| - instructor: String | | - coursesTaken: List<Course> |
| - maxStudents: int | +---------------------+
| - enrolledStudents: int |
+-----------------------+
| + addStudent(student: Student): boolean |
| + removeStudent(student: Student): boolean |
| + getEnrolledStudents(): int |
+-----------------------+

Câu 3:
Dưới đây là kết quả của chương trình và giải thích từng dòng lệnh:
30 20
Giải thích từng dòng lệnh:
1. Integer[] arr = {10, 20};: Tạo một mảng arr với hai phần tử là 10 và 20.
2. Exam.exam(30, arr[1], arr, arr.length);: Gọi phương thức static exam() của lớp Exam với
các đối số là 30, arr[1] (20), arr (mảng), và arr.length (độ dài của mảng).
3. static void exam(int i, Integer wi, Integer[] a, int len): Định nghĩa phương thức exam() với
các tham số là i, wi, a và len. Trong phương thức này:
 a[0] = wi;: Gán giá trị của wi (20) vào phần tử đầu tiên của mảng a (arr).
 wi = a[len-1];: Gán giá trị của phần tử cuối cùng của mảng a (arr) vào wi (20).
 wi = i;: Gán giá trị của i (30) vào wi.
4. System.out.println(arr[0]);: In ra giá trị của phần tử đầu tiên của mảng arr, sau khi đã qua
xử lý trong phương thức exam(). Do đó, kết quả là 30.
5. System.out.println(arr[1]);: In ra giá trị của phần tử thứ hai của mảng arr, không thay đổi
sau khi đã qua xử lý trong phương thức exam(). Do đó, giá trị vẫn là 20.
Đề 2:
Câu 1: Trong Java, có hai loại kiểu dữ liệu chính là kiểu dữ liệu tham chiếu (reference types)
và kiểu dữ liệu nguyên thủy (primitive types).
1. Kiểu dữ liệu tham chiếu (Reference Types):
 Kiểu dữ liệu tham chiếu đề cập đến các đối tượng được lưu trữ trong bộ nhớ heap và
được tham chiếu bởi biến. Biến chỉ lưu trữ địa chỉ của đối tượng trong bộ nhớ heap,
chứ không phải giá trị thực sự của đối tượng đó.
 Các kiểu dữ liệu tham chiếu bao gồm các lớp, giao diện, mảng(array) và kiểu dữ liệu
đặc biệt như String.
 Kiểu dữ liệu tham chiếu có thể trỏ đến null, tức là không có tham chiếu đến đối tượng
nào.
Ví dụ:
// Kiểu dữ liệu tham chiếu: String String str = "Hello"; // str là một biến tham chiếu đến một
đối tượng String
2. Kiểu dữ liệu nguyên thủy (Primitive Types):
 Kiểu dữ liệu nguyên thủy đề cập đến các kiểu dữ liệu cơ bản như số nguyên(integer),
số thực(float,double), ký tự(char) và boolean.
 Các kiểu dữ liệu nguyên thủy được lưu trữ trực tiếp trong bộ nhớ stack hoặc trong các
thanh ghi của CPU, không cần phải tạo đối tượng như kiểu dữ liệu tham chiếu.
 Các kiểu dữ liệu nguyên thủy không thể trỏ đến null, vì chúng không phải là đối
tượng.
Ví dụ:
int num = 10; // num là một biến nguyên thủy chứa giá trị 10
Câu 2:
1. Mã nguồn (Source code):
 Mã nguồn là phiên bản của chương trình được viết bằng ngôn ngữ lập trình, có thể
hiểu được bởi con người. Nó thường được biên dịch hoặc thông dịch thành mã máy
để thực thi.
2. Mã máy (Machine code):
 Mã máy là mã nhị phân được hiểu bởi máy tính, là hình thức cuối cùng của một
chương trình sau khi đã được biên dịch hoặc thông dịch từ mã nguồn.
3. Chương trình (Program):
 Chương trình là một tập hợp các hướng dẫn hoặc câu lệnh được viết trong một ngôn
ngữ lập trình nhất định, được thiết kế để thực hiện một tác vụ cụ thể trên máy tính.
4. Tiến trình (Process):
 Tiến trình là một chương trình đang chạy trên máy tính, bao gồm mã máy đang thực
thi, dữ liệu, các tài nguyên hệ thống và một bộ đăng ký trạng thái.
Để biên dịch một file mã nguồn Main.java và tạo ra bytecode trong một thư mục khác, bạn có
thể sử dụng lệnh javac trong terminal. Dưới đây là cách để thực hiện điều này:
 Mở terminal và di chuyển đến thư mục chứa file Main.java.
Sử dụng lệnh sau để biên dịch file Main.java và tạo ra bytecode:
javac -d <đường_dẫn_đến_thư_mục_đích> Main.java
Trong đó:
-d: Tham số này chỉ định thư mục đích để lưu trữ các file bytecode được tạo ra.
<đường_dẫn_đến_thư_mục_đích>: Đường dẫn tới thư mục mà bạn muốn lưu trữ các file
bytecode.
Main.java: Tên của file mã nguồn bạn muốn biên dịch.
Câu 3:
Kết quả:
0 medium
Giải thích từng dòng lệnh:
1. public class Main {: Bắt đầu khai báo lớp Main.
2. class Exam {: Bắt đầu khai báo lớp Exam bên trong lớp Main.
3. private int id = 0;: Khai báo một biến private có tên id và gán giá trị là 0. Biến này không thể
truy cập trực tiếp từ bên ngoài lớp Exam.
4. String difficulty = "medium";: Khai báo một biến có phạm vi mặc định là medium.
5. String getDifficulty() { return this.difficulty; }: Khai báo một phương thức getDifficulty()
để trả về giá trị của biến difficulty.
6. Main main = new Main();: Tạo một đối tượng của lớp Main.
7. Exam exam01 = main.new Exam();: Tạo một đối tượng Exam từ lớp Main.
8. System.out.println(exam01.id);: In ra giá trị của biến id của đối tượng exam01. Mặc dù id
là private, nhưng vẫn có thể truy cập thông qua đối tượng.
9. System.out.println(exam01.difficulty);: In ra giá trị của biến difficulty của đối tượng
exam01.
ĐỀ 3:
Câu 1:Khi sử dụng kiểu dữ liệu tham chiếu trong Java, dữ liệu được lưu trữ trong bộ nhớ dưới
dạng tham chiếu đến vị trí của đối tượng trong bộ nhớ heap. Dữ liệu thực sự của đối tượng
được lưu trữ ở vị trí đó.
Dưới đây là một ví dụ minh họa về cách dữ liệu được lưu trữ trong bộ nhớ khi sử dụng kiểu
dữ liệu tham chiếu:
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
// Tạo một đối tượng Student và lưu tham chiếu đến nó trong biến student
Student student = new Student("John");
// student là một tham chiếu đến vị trí của đối tượng Student trong bộ nhớ heap }}

Câu 2:
public class MyDate {
private int year;
private int month;
private int day;
public MyDate(int y, int m, int d) {
year = y;
month = m;
day = d;
}
public MyDate(String date) {
if (date.length() != 8) {
throw new IllegalArgumentException("Invalid date format. Please provide a string
with 8 characters in format 'yyyymmdd'.");
}
try {
year = Integer.parseInt(date.substring(0, 4));
month = Integer.parseInt(date.substring(4, 6));
day = Integer.parseInt(date.substring(6, 8));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid date format. Please provide a string
with 8 characters in format 'yyyymmdd'.");
}
}
// Các phương thức getter và setter không được hiển thị để rút ngắn ví dụ
// Bạn có thể triển khai các phương thức này tùy thích. }
Câu 3:
Kết quả:
0 medium
Giải thích từng dòng lệnh:
1. public class Main {: Bắt đầu khai báo lớp Main.
2. class Exam {: Bắt đầu khai báo lớp Exam bên trong lớp Main.
3. private int id = 0;: Khai báo một biến private có tên id và gán giá trị là 0. Biến này không thể
truy cập trực tiếp từ bên ngoài lớp Exam.
4. String difficulty = "medium";: Khai báo một biến có phạm vi mặc định là medium.
5. String getDifficulty() { return this.difficulty; }: Khai báo một phương thức getDifficulty()
để trả về giá trị của biến difficulty.
6. Main main = new Main();: Tạo một đối tượng của lớp Main.
7. Exam exam01 = main.new Exam();: Tạo một đối tượng Exam từ lớp Main.
8. System.out.println(exam01.id);: In ra giá trị của biến id của đối tượng exam01. Mặc dù id
là private, nhưng vẫn có thể truy cập thông qua đối tượng.
9. System.out.println(exam01.difficulty);: In ra giá trị của biến difficulty của đối tượng
exam01.
ĐỀ 4:
Câu 1:
Hàm x2SoNguyen(Integer i) trong ví dụ của bạn không làm thay đổi giá trị của tham số truyền vào vì
trong Java, tham số của hàm được truyền theo giá trị (pass-by-value), không phải theo tham chiếu
(pass-by-reference).
Khi bạn truyền một đối tượng Integer vào hàm x2SoNguyen(Integer i), một bản sao của giá trị của
đối tượng Integer đó được tạo ra và truyền vào hàm. Trong hàm, bạn thay đổi giá trị của bản sao này,
nhưng không ảnh hưởng đến đối tượng Integer gốc mà bạn đã truyền vào.
Nếu bạn muốn thay đổi giá trị của đối tượng Integer gốc, bạn có thể sử dụng kiểu trả về của hàm để
trả về giá trị mới và gán lại cho biến gốc trong chương trình gọi hàm.
Câu 2:
// Trong file Account.java
package mypackage;
public class Account {
void processTransaction() {
System.out.println("Processing transaction...");
}
}
// Trong file OtherClass.java
package otherpackage;
import mypackage.Account;
public class OtherClass {
public static void main(String[] args) {
Account account = new Account();
account.processTransaction(); // Lỗi biên dịch: Không thể truy cập processTransaction() vì nó có
chỉ định truy cập mặc định và nằm ở gói khác
}}
Cau 3:
Dưới đây là kết quả khi dịch và chạy hàm main:
10 20
Giải thích từng dòng lệnh trong hàm main:
1. Integer[] arr = {10, 20};: Khai báo và khởi tạo một mảng arr với hai phần tử là 10 và 20.
2. Exam.exam(30, arr[1], arr, arr.length);: Gọi phương thức exam() từ lớp Exam với các đối
số là 30, giá trị của phần tử thứ hai của mảng arr (20), mảng arr và độ dài của mảng arr.
3. Trong phương thức exam():
 a[0] = wi;: Gán giá trị của wi (20) vào phần tử đầu tiên của mảng a (tức là phần tử
đầu tiên của arr).
 wi = a[len-1];: Gán giá trị của phần tử cuối cùng của mảng a (tức là phần tử thứ hai
của arr, vì len là độ dài của mảng arr) vào wi.
 wi = i;: Gán giá trị của i (30) vào wi. Tuy nhiên, giá trị này không ảnh hưởng đến
biến arr[1] đã được truyền vào phương thức vì wi chỉ là một bản sao của giá trị được
truyền vào, không phải tham chiếu đến arr[1].
4. System.out.println(arr[0]);: In ra giá trị của phần tử đầu tiên của mảng arr, đã bị thay đổi
bởi phương thức exam(). Do đó, kết quả là 10.
5. System.out.println(arr[1]);: In ra giá trị của phần tử thứ hai của mảng arr, không bị thay đổi
bởi phương thức exam(). Do đó, kết quả vẫn là 20.
ĐỀ 5:
Câu 1:
Trong Java, để so sánh hai đối tượng có kiểu String, có hai cách thường được sử dụng là so sánh theo
định dạng chuỗi và so sánh theo tham chiếu.
1. So sánh theo định dạng chuỗi:
 Khi so sánh hai đối tượng String bằng toán tử == hoặc phương thức equals(), Java sẽ
so sánh giá trị của hai chuỗi (nội dung của chuỗi) để xác định xem chúng có giống
nhau hay không.
 Ví dụ:
String str1 = "hello"; String str2 = "hello";
System.out.println(str1 == str2); // Kết quả là true, vì cả hai đều trỏ đến cùng một chuỗi trong pool
chuỗi
System.out.println(str1.equals(str2)); // Kết quả là true, vì nội dung của cả hai chuỗi giống nhau
2. So sánh theo tham chiếu:
 Nếu bạn sử dụng toán tử == để so sánh hai đối tượng String, nó sẽ kiểm tra xem hai
đối tượng có trỏ đến cùng một vị trí bộ nhớ hay không.
 Ví dụ:
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1 == str2); // Kết quả là false, vì hai đối tượng được tạo ra riêng biệt trong bộ
nhớ
Trong hầu hết các trường hợp, bạn nên sử dụng phương thức equals() để so sánh hai chuỗi trong Java
vì nó so sánh nội dung của chuỗi. Tuy nhiên, nếu bạn muốn kiểm tra xem hai đối tượng String có trỏ
đến cùng một vị trí bộ nhớ hay không, bạn có thể sử dụng toán tử ==.
Câu 2:
Dưới đây là một ví dụ minh họa về việc sử dụng thuộc tính với chỉ định truy cập protected trong lớp
Product, và sau đó truy cập nó từ một lớp con nằm trong gói khác:
Trong package package1:
// Trong file Product.java package package1;
public class Product { protected String name;
public Product(String name) { this.name = name; } }
Trong package package2:
// Trong file OtherClass.java package package2;
import package1.Product;
public class OtherClass extends Product
{ public OtherClass(String name)
{ super(name); }
public void displayProductName() {
System.out.println("Product name: " + name); // Truy cập thuộc tính protected từ lớp cha } }
Dưới đây là lệnh để biên dịch và chạy chương trình:
javac -d . package1/Product.java
javac -d . package2/OtherClass.java
java package2.OtherClass
Trong ví dụ này:
 Trong package package1, chúng ta có lớp Product với thuộc tính protected String name.
 Trong package package2, chúng ta có lớp OtherClass kế thừa từ lớp Product. Do đó, nó có
quyền truy cập vào thuộc tính name của lớp Product.
 Trong phương thức displayProductName() của lớp OtherClass, chúng ta có thể trực tiếp
truy cập vào thuộc tính name với chỉ định truy cập protected.
Câu 3:
Kết quả khi chạy chương trình:
5 10 7
Giải thích từng dòng lệnh:
1. int arr_i = 10;: Khai báo và khởi tạo biến arr_i có giá trị là 10.
2. int[] i = {1, 2, 3};: Khai báo và khởi tạo mảng i có các phần tử là 1, 2, và 3.
3. Integer[] arr_wi = {3, 4, 5};: Khai báo và khởi tạo mảng arr_wi có các phần tử là 3, 4, và 5.
4. Exam.exam(i, arr_i, arr_wi[1]);: Gọi phương thức exam() của lớp Exam với các đối số là
mảng i, biến arr_i, và phần tử thứ hai của mảng arr_wi. Phương thức này sẽ tính tổng của
arr_i và phần tử thứ hai của arr_wi, và gán kết quả vào phần tử đầu tiên của mảng i.
5. Exam.exam(arr_i, i[0], arr_wi);: Gọi phương thức exam() của lớp Exam với các đối số là
biến arr_i, phần tử đầu tiên của mảng i, và mảng arr_wi. Phương thức này sẽ tính hiệu của
arr_i và phần tử đầu tiên của i, và gán kết quả vào phần tử đầu tiên của mảng arr_wi.
6. System.out.println(i[0] + " " + arr_i + " " + arr_wi[0]);: In ra giá trị của phần tử đầu tiên
của mảng i, biến arr_i, và phần tử đầu tiên của mảng arr_wi.
ĐỀ 6:
Câu 1:
Trong Java, thành viên tĩnh (static member) là các thành viên của một lớp mà thuộc về lớp chứ không
phải là các đối tượng cụ thể của lớp đó. Dưới đây là các đặc điểm của thành viên tĩnh:

 Truy cập từ lớp: Thành viên tĩnh có thể được truy cập trực tiếp từ lớp mà không cần tạo ra
một đối tượng của lớp đó
 Chia sẻ giữa các đối tượng: Tất cả các đối tượng của lớp chia sẻ cùng một bản sao của thành
viên tĩnh. Nếu một đối tượng thay đổi giá trị của thành viên tĩnh, thì thay đổi đó sẽ ảnh hưởng
đến tất cả các đối tượng khác.
 Không thể truy cập các thành viên không tĩnh: Thành viên tĩnh không thể truy cập các
thành viên không tĩnh của lớp mà không thông qua một đối tượng cụ thể.
 Không thể truy cập từ phương thức không tĩnh: Không thể truy cập các thành viên không
tĩnh từ bên trong một phương thức tĩnh. Tuy nhiên, các thành viên tĩnh có thể được truy cập
từ bên trong các phương thức không tĩnh.

Dưới đây là một ví dụ minh họa các đặc điểm của thành viên tĩnh trong Java:
public class MyClass {
static int staticVar; // Thành viên tĩnh
int instanceVar; // Thành viên không tĩnh
static void staticMethod() {
System.out.println("This is a static method.");
}
void instanceMethod() {
System.out.println("This is an instance method."); }}
public class Main {
public static void main(String[] args) {
// Truy cập thành viên tĩnh mà không cần tạo ra một đối tượng MyClass
MyClass.staticVar = 10;
System.out.println(MyClass.staticVar);
// Khởi tạo một đối tượng MyClass
MyClass obj = new MyClass();
// Truy cập thành viên không tĩnh thông qua đối tượng obj
obj.instanceVar = 20;
System.out.println(obj.instanceVar);
// Gọi phương thức staticMethod mà không cần tạo ra một đối tượng MyClass
MyClass.staticMethod();
// Gọi phương thức instanceMethod thông qua đối tượng obj
obj.instanceMethod();
}}
Kết quả:
10
20
This is a static method.
This is an instance method.
Câu 2: public class Main {
public static void main(String[] args) {
MyMethod myMethod = new MyMethod();
// Sử dụng phương thức so sánh hai số thực
double num1 = 10.5;
double num2 = 7.8;
System.out.println("Is num1 larger than num2? " + myMethod.a_is_larger_than_b(num1,
num2));
// Sử dụng phương thức so sánh hai xâu kí tự
String str1 = "axxxyyyzz";
String str2 = "byyyzzz";
System.out.println("Is str1 larger than str2? " + myMethod.a_is_larger_than_b(str1, str2));
}
}
Kết quả:
Is num1 larger than num2? true
Is str1 larger than str2? False
Caau3:
Kết quả khi chạy đoạn chương trình trên sẽ là:
Copy code
7
Giải thích từng dòng lệnh:
1. System.out.println(func(5));: Gọi phương thức func() với đối số là 5 và in kết quả ra màn
hình.
2. public static int func(int x) {: Khai báo phương thức func() nhận một tham số nguyên x và
trả về một giá trị nguyên.
3. int sum = 0;: Khởi tạo biến sum có giá trị ban đầu là 0.
4. outer: for (int i=0; i<x; i++){: Bắt đầu vòng lặp outer với biến i chạy từ 0 đến x (khi x là 5).
5. sum++;: Mỗi lần lặp, tăng giá trị của sum lên 1.
6. if (i==4) continue;: Nếu i bằng 4, tiếp tục vòng lặp outer với giá trị i tiếp theo mà không thực
hiện phần code dưới đây.
7. inner: for (int j=0; j<x; j++){: Bắt đầu vòng lặp inner trong vòng lặp outer, với biến j chạy
từ 0 đến x.
8. if (j==i) continue outer;: Nếu j bằng i, tiếp tục vòng lặp outer với giá trị j tiếp theo mà
không thực hiện phần code dưới đây.
9. if (i==3) break;: Nếu i bằng 3, thoát khỏi vòng lặp inner.
10. if (i==2) break outer;: Nếu i bằng 2, thoát khỏi vòng lặp outer.
11. }: Kết thúc vòng lặp inner.
12. }: Kết thúc vòng lặp outer.
13. return sum;: Trả về giá trị của biến sum. Trong quá trình tính toán, sum sẽ được tăng lên 1
mỗi lần lặp của vòng lặp outer, ngoại trừ các trường hợp khi i bằng 4, 3, hoặc 2. Do đó, giá
trị cuối cùng của sum là 7.
ĐỀ 7:
Caua1: Cách thể hiện biểu đồ lớp trong lập trình hướng đối tượng

1. Cấu trúc cơ bản:

 Tên lớp: Viết hoa chữ cái đầu tiên, đặt tên theo mô tả chức năng của lớp.
 Thuộc tính:
o Tên thuộc tính: Viết thường chữ cái đầu tiên.
o Kiểu dữ liệu: Ghi rõ kiểu dữ liệu của thuộc tính.
o Chỉ định truy cập:
 + (public): Truy cập được từ mọi nơi.
 - (private): Chỉ truy cập được trong lớp.
 # (protected): Truy cập được trong lớp và các lớp kế thừa.
o Giá trị tĩnh: Khai báo bằng static.
 Hàm khởi tạo:
o Tên trùng với tên lớp.
o Khởi tạo giá trị cho các thuộc tính.
 Getter/Setter:
o Dùng để truy cập và thay đổi giá trị thuộc tính private.
o Tên: getTenThuocTinh() và setTenThuocTinh(value).

2. Ví dụ minh họa:

Lớp SinhVien với các thuộc tính hoTen, ngaySinh, diemThi.

public class SinhVien {


private String hoTen;
private String ngaySinh;
private double diemThi;

public SinhVien() {
}

public SinhVien(String hoTen, String ngaySinh, double diemThi) {


this.hoTen = hoTen;
this.ngaySinh = ngaySinh;
this.diemThi = diemThi;
}

public String getHoTen() {


return hoTen;
}

public void setHoTen(String hoTen) {


this.hoTen = hoTen;
}

public String getNgaySinh() {


return ngaySinh;
}

public void setNgaySinh(String ngaySinh) {


this.ngaySinh = ngaySinh;
}

public double getDiemThi() {


return diemThi;
}

public void setDiemThi(double diemThi) {


this.diemThi = diemThi; }}

Caau2:
public class OneClass {
// Khai báo các thuộc tính
private int intValue; // Kiểu số nguyên thủy
private String stringValue; // Kiểu tham chiếu
private boolean booleanValue;// Kiểu boolean
public static void main(String[] args) {
// Khởi tạo một đối tượng của lớp OneClass
OneClass obj = new OneClass();
// In ra giá trị mặc định của các thuộc tính
System.out.println("Giá trị mặc định của intValue: " + obj.intValue);
System.out.println("Giá trị mặc định của stringValue: " + obj.stringValue);
System.out.println("Giá trị mặc định của booleanValue: " + obj.booleanValue);
}}

Câu 3:

Trong đoạn chương trình trên, lớp Ticket và lớp Main không có mối quan hệ kế thừa hoặc
sử dụng. Thay vào đó, lớp Main đang tạo một đối tượng của lớp Ticket và truy cập vào
các thành viên dữ liệu của nó.

Khi chạy hàm main(), đoạn mã sẽ tạo một đối tượng của lớp Ticket thông qua dòng
Ticket t = new Ticket();, sau đó in ra giá trị của các thành viên dữ liệu của lớp
Ticket thông qua các câu lệnh System.out.println().

Giải thích:
 info: Là một biến thành viên không static (non-static member variable) có quyền truy cập mặc
định, nên cả Ticket.info và t.info đều có thể truy cập được và in ra giá trị của info.
 content: Là một biến thành viên private, chỉ có thể truy cập từ bên trong lớp Ticket, nên khi
cố gắng truy cập Ticket.content hoặc t.content từ bên ngoài lớp Ticket, sẽ gây ra lỗi biên
dịch.
 detail: Là một biến thành viên static, có thể truy cập trực tiếp từ lớp Ticket hoặc từ một đối
tượng của lớp Ticket. Do đó, cả Ticket.detail và t.detail đều in ra giá trị của detail.
 data: Là một biến thành viên public, có thể truy cập trực tiếp từ bên ngoài lớp Ticket, do đó
cả Ticket.data và t.data đều in ra giá trị của data.
ĐỀ 8:
cÂU 1:
Ví dụ sử dụng tự tham chiếu this trong Java:
Trường hợp:
Giả sử bạn muốn viết một phương thức trong lớp Person để tính toán chỉ số khối cơ thể (BMI) dựa
trên chiều cao và cân nặng của người đó. Phương thức này cần truy cập vào cả hai thuộc tính height
(chiều cao) và weight (cân nặng) của đối tượng Person.
Mã Java
public class Person {
private double height;
private double weight;
public Person(double height, double weight) {
this.height = height;
this.weight = weight;
}
public double calculateBMI() {
// Sử dụng `this` để truy cập vào thuộc tính `height` và `weight`
return weight / (height * height);
}}
Giải thích:
 Trong phương thức calculateBMI(), ta sử dụng từ khóa this để tham chiếu đến đối tượng
hiện tại đang được gọi phương thức.
 Nếu không sử dụng this, mã sẽ bị lỗi vì không có biến nào tên là height và weight trong phạm
vi phương thức.
 Việc sử dụng this giúp tăng tính rõ ràng và dễ đọc cho mã code.
Lợi ích của việc sử dụng this:
 Rõ ràng: Giúp xác định rõ ràng rằng bạn đang truy cập vào thuộc tính của đối tượng hiện tại,
tránh nhầm lẫn với biến cục bộ.
 Dễ đọc: Làm cho mã code dễ đọc và dễ hiểu hơn.
 Tính bảo mật: Giúp bảo vệ thuộc tính khỏi truy cập trái phép.
Ngoài ra, this còn có thể được sử dụng trong các trường hợp sau:
 Gọi các phương thức khác của lớp hiện tại.
 Truyền đối tượng hiện tại làm đối số cho một phương thức khác.
 Phân biệt giữa biến cục bộ và biến thành viên.
Câu 2:
public class BankAccount {
private double balance;
// Phương thức private để rút tiền từ tài khoản
private void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawal successful. Remaining balance: " + balance);
} else {
System.out.println("Withdrawal failed. Insufficient funds.");
} }
// Phương thức public để truy cập phương thức withdraw từ bên ngoài lớp
public void attemptWithdrawal(double amount) {
withdraw(amount); }
// Phương thức public để lấy số dư hiện tại của tài khoản
public double getBalance() {
return balance; }
public static void main(String[] args) {
BankAccount account = new BankAccount();
account.balance = 1000; // Gán giá trị cho balance
// Cố gắng rút 500 đơn vị từ tài khoản
account.attemptWithdrawal(500);
// Cố gắng truy cập trực tiếp vào phương thức withdraw (sẽ gây lỗi biên dịch)
// account.withdraw(200);
}}

cÂU 3:
Đoạn mã Java có lỗi và sẽ không chạy được. Dưới đây là giải thích từng dòng lệnh và lý do gây
lỗi:
Lớp Parent:
 private double pi = 3.14;: Biến pi kiểu double, private (chỉ truy cập được trong lớp Parent).
 protected double len;: Biến len kiểu double, protected (truy cập được trong Parent và các lớp
con).
 String desc = "SHAPE";: Biến desc kiểu String, public (truy cập được mọi nơi).
 public String display() { ... }: Phương thức public display() trả về chuỗi. Nối các biến desc,
len, pi thành một chuỗi nhưng len chưa được khởi tạo nên có thể gây lỗi.
Lớp Child:
 String s = "Child Assets";: Biến s kiểu String, public (truy cập được mọi nơi).
 public String displayParent() { ... }: Lỗi: Phương thức public displayParent()
o Gọi super.displayParent() nhưng lớp Parent không có phương thức displayParent().

Lớp Main:
 Child c = new Child();: Tạo đối tượng Child mới tên c.
 System.out.println(c.displayParent());: Lỗi: Gọi phương thức displayParent() của c nhưng nó
gây ra lỗi ở trên.
Kết quả:
Do lỗi biên dịch, chương trình sẽ không chạy được và không có kết quả in ra.
Giải pháp sửa lỗi:
1. Sửa displayParent(): Đổi super.displayParent() thành super.display() để gọi phương thức
display() được thừa kế từ lớp Parent.
2. Khởi tạo len (tùy chọn): Khởi tạo giá trị cho len trong lớp Parent hoặc sử dụng toán tử null-
coalescing (??) trong phương thức display() để tránh lỗi khi len chưa được khởi tạo.
Chạy với code đã sửa (ví dụ):
Giả sử bạn sửa lỗi theo hướng dẫn 1 và khởi tạo len với giá trị 10 trong lớp Parent, kết quả in ra có thể
là:
SHAPE 10.0 meter, 3.14 Child Assets
ĐỀ 9:
Câu 1:
Thể hiện quan hệ kết tập trên biểu đồ lớp trong lập trình hướng đối tượng
Quan hệ kết tập là một mối quan hệ giữa hai lớp, trong đó một lớp (lớp chứa) có thể chứa nhiều đối
tượng của lớp khác (lớp thành phần). Mối quan hệ này được thể hiện trên biểu đồ lớp bằng cách sử
dụng các ký hiệu sau:
1. Ký hiệu:
 Mũi tên: Mũi tên được vẽ từ lớp thành phần đến lớp chứa, thể hiện chiều của mối quan hệ.
 Tên mối quan hệ: Tên mối quan hệ được ghi chú gần mũi tên, thường mô tả bản chất của
mối quan hệ.
 Độ bội: Độ bội được ghi chú gần lớp thành phần, thể hiện số lượng đối tượng của lớp thành
phần có thể tồn tại trong một đối tượng của lớp chứa.
2. Ví dụ:
Lớp Giỏ hàng:
 Chứa nhiều đối tượng Sản phẩm.
 Mỗi Giỏ hàng có thể chứa số lượng Sản phẩm khác nhau.
Biểu đồ lớp:
Giỏ hàng ----(1..*)---- Sản phẩm
Giải thích:
 Mũi tên từ Sản phẩm đến Giỏ hàng thể hiện mối quan hệ kết tập.
 Tên mối quan hệ là (1..*), nghĩa là mỗi Giỏ hàng có thể chứa tối thiểu 1 và tối đa không giới
hạn Sản phẩm.
3. Ví dụ khác:
 Lớp Đơn hàng: Chứa nhiều đối tượng Chi tiết đơn hàng.
 Lớp Lớp học: Chứa nhiều đối tượng Học sinh.
4. Lưu ý:
 Quan hệ kết tập thể hiện mối quan hệ có hướng.
 Độ bội có thể là một số nguyên, một khoảng hoặc một biểu thức.
 Có thể sử dụng các công cụ UML để vẽ biểu đồ lớp.
Câu 2: Phương thức toString() trong lớp OneClass
Đặc điểm:
 Khai báo:
Java
public String toString() {
}
 Tính chất:
o Public: Truy cập được từ mọi nơi.

o Non-static: Thuộc về đối tượng, không thuộc về lớp.

o Trả về kiểu String: Biểu diễn chuỗi của đối tượng.

Hai cách gọi phổ biến:


1. Gọi trực tiếp:
OneClass obj = new OneClass();
String str = obj.toString();
System.out.println(str);
2. Gọi thông qua System.out.println():
OneClass obj = new OneClass();
System.out.println(obj);
Cách gọi thứ hai sử dụng phương thức toString() được kế thừa từ lớp Object. Khi gọi
System.out.println() với đối tượng, trình biên dịch sẽ tự động gọi phương thức toString() của đối
tượng đó.
Lợi ích:
 Cung cấp cách thức thống nhất để biểu diễn đối tượng dưới dạng chuỗi.
 Giúp việc gỡ lỗi và in thông tin về đối tượng dễ dàng hơn.
Ví dụ:
public class OneClass {
private String name;
public OneClass(String name) {
this.name = name;
}
@Override
public String toString() {
return "OneClass: " + name;
}
public static void main(String[] args) {
OneClass obj = new OneClass("Example");
System.out.println(obj); // In ra "OneClass: Example"
}}
ĐỀ 10
Caua1: Ví dụ sử dụng lớp bao trong Java
Lớp bao (wrapper class) trong Java là lớp dùng để "bọc" các kiểu dữ liệu nguyên thủy (primitive data
types) thành các đối tượng. Lớp bao cung cấp nhiều phương thức tiện lợi để thao tác với các kiểu dữ
liệu nguyên thủy.
Ví dụ:
Giả sử bạn muốn so sánh hai giá trị int a và b. Cách so sánh trực tiếp bằng toán tử == chỉ so sánh giá
trị, không so sánh địa chỉ. Do đó, nếu a và b có cùng giá trị nhưng được lưu trữ ở các vị trí nhớ khác
nhau, so sánh bằng == sẽ trả về false.
Để so sánh địa chỉ của hai giá trị int, bạn cần sử dụng lớp bao Integer. Lớp Integer cung cấp phương
thức equals() so sánh địa chỉ của hai đối tượng Integer.
int a = 10;
int b = 10;
// So sánh giá trị
System.out.println(a == b); // In ra true
// So sánh địa chỉ
Integer aWrapper = new Integer(a);
Integer bWrapper = new Integer(b);
System.out.println(aWrapper.equals(bWrapper)); // In ra false
Ngoài ra, lớp bao còn được sử dụng trong các trường hợp sau:
 Chuyển đổi kiểu dữ liệu: Chuyển đổi giữa các kiểu dữ liệu nguyên thủy và các kiểu dữ liệu
khác như String.
 Truy cập các phương thức tiện lợi: Lớp bao cung cấp nhiều phương thức tiện lợi để thao tác
với dữ liệu, ví dụ: Integer.parseInt() để chuyển đổi chuỗi sang kiểu int.
 Tăng tính bảo mật: Lớp bao giúp bảo mật dữ liệu bằng cách cung cấp các phương thức kiểm
tra giá trị đầu vào.
Câu 2: Phạm vi truy cập của thuộc tính lớp Course với chỉ định truy cập mặc định
1. Phạm vi truy cập:
Thuộc tính lớp Course với chỉ định truy cập mặc định có thể được truy cập trong:
 Lớp Course: Nơi thuộc tính được khai báo.
 Các lớp con của Course: Có thể truy cập trực tiếp thuộc tính được kế thừa.
 Lớp khác trong cùng package: Có thể truy cập trực tiếp thuộc tính.
2. Code minh họa:
Lớp Course: public class Course {
String name; // Thuộc tính mặc định
public void printName() {
System.out.println(name); // Truy cập trực tiếp thuộc tính name
}}
Lớp con ChildCourse: public class ChildCourse extends Course {
public void printInfo() {
System.out.println(name); // Truy cập trực tiếp thuộc tính name được kế thừa
}}

Lớp Main:public class Main {


public static void main(String[] args) {
Course course = new Course();
course.name = "Java Programming"; // Truy cập trực tiếp thuộc tính name
ChildCourse childCourse = new ChildCourse();
childCourse.name = "Python Programming"; // Truy cập trực tiếp thuộc tính name
System.out.println("Course name: " + course.name);
System.out.println("Child course name: " + childCourse.name);
}}
Lệnh dịch code:
javac Course.java ChildCourse.java Main.java
java Main
Kết quả:
Course name: Java Programming
Child course name: Python Programming
3. Giải thích:
 Thuộc tính name được khai báo với chỉ định truy cập mặc định, nên có thể truy cập trực tiếp
trong lớp Course, lớp con ChildCourse và các lớp khác trong cùng package.
 Lớp Main nằm trong cùng package với Course và ChildCourse, nên có thể truy cập trực tiếp
thuộc tính name của hai lớp này.
.

You might also like