1. Trang chủ
  2. » Công Nghệ Thông Tin

Câu hỏi phỏng vấn + vấn đáp Java Đại học Khoa học Tự Nhiên ĐHQGHN

11 21 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 11
Dung lượng 111 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Java Interview Question 1 Java program anatomy 1 1 What is package? Một package trong java đc sử dụng để nhóm các lớp liên quan, giống như một thư mục trong thư mục tệp Các package đc sử dụng để tránh xung đột tên và viết mã có thể bảo trì tốt hơn 1 2 Why do you need to import packages? Import packages hoặc class để có thể sử dụng được thư viện 1 3 What is the diference between argument and parameter? (sự khác nhau giữa đối số và tham số) Tham số là một biến trong khai báo hàm Đối số là giá trị.

Trang 1

Java Interview Question

1. Java program anatomy

1.1 What is package?

- Một package trong java đc sử dụng để nhóm các lớp liên quan, giống như một thư mục trong thư mục tệp Các package đc sử dụng để tránh xung đột tên và viết mã có thể bảo trì tốt hơn

1.2 Why do you need to import packages?

- Import packages hoặc class để có thể sử dụng được thư viện

1.3 What is the diference between argument and parameter?

(sự khác nhau giữa đối số và tham số)

- Tham số là một biến trong khai báo hàm

- Đối số là giá trị thực của biến này được chuyển đến hàm

- Khi một phương thức được gọi, các đối số là dữ liệu bạn truyền vào các tham số của phương thức

2. Compliling and executing java code in JVM

2.1 explain the process of java code compilation and execution?

(giải thích quá trình biên dịch và thực thi mã trong java)

- Biên dịch:

Đầu tiên tệp nguồn java được chuyển qua trình biên dịch, trình biên dịch này sau đó

mã hóa mã nguồn thành một mã hóa độc lập với máy, được gọi là bytecode Nội dung của mỗi lớp có trong tệp nguồn được lưu trữ trong tệp class riêng biệt Trong khi chuyển đổi mã nguồi thành mã bytecode, trình biên dịch sẽ thực hiện theo các bước sau:

B1: Phân tích cú pháp: đọc một tập hợp các tệp nguồn java và ánh xạ chuỗi mã thông báo kết quả vào AST – node

B2: Enter: nhập ký hiệu cho các định nghĩa vào bảng kí hiệu

B3: Xử lý chú thích: nếu được yêu cầu, xử lý chú thích được tìm thấy trong các đơn

vị biên dịch được chỉ định

B4: Thuộc tính: thuộc tính của cây cú pháp, bước này gồm phân giải tên, kiểm tra kiểu và gấp liên tục

B5: Luồng: thực hiện phân tích luồng dữ liệu trên các cây từ bước trước, bao gồm kiểm tra các nhiệm vụ và khả năng truy cập lại

B6: Desugar: viết lại AST và dịch bớt một số đường cú pháp

B7: tạo tệp class

- Thực thi:

Các tệp lớn do trình biên dịch tạo ra độc lập với máy hoặc hệ điều hành, cho phép chúng chạy trên bất kỳ hệ thống nào Để chạy, tệp lớp chính (lớp chứa phương thức chính) được chuyển đến JVM và sau đó trải qua 3 giai đoạn chính trước khi mã máy cuối cùng được thực thi Các giai đoạn này là:

Giai đoạn 1: bộ nạp lớp

Giai đoạn 2: Trình xác minh

Trang 2

Giai đoạn 3: Trình biên dịch Just – In - Time

2.2 What is the difference between bytecode and source code? (sự khác nhau giữa bytecode và mã nguồn)

Trang 3

2.3 What is JVM? Is it same or different for different Operating Systems?

(JVM là gì? Nó giống hay khác nhau đối với các hệ điều hành khác nhau)

JVM (java virtual machine) là 1 máy ảo java – đc dùng để thực thi các chương trình java hay hiểu nôm na là trình thông dịch của java Nó cung cấp môi trường để code java có thể được thực thi Chương trình java khi biên dịch sẽ tạo ra các mã máy gọi là bytecodes

Mỗi hệ điều hành khác nhau (windows, android, linux…) lại có một loại JVM khác nhau được cài đặt Chương trình java chạy đc trên window/linux/IOS vì nó có JVM chạy được trên các nền tảng đó

JVM giống nhau cho tất cả các phiên bản Windows, chỉ có sự khác biệt là kiến trúc

2.4 What is the role of class loader in JVM?

(vai trò của trình nạp lớp JVM là gì?)

3. Data Types

3.1 What are primitive data types?

(kiểu dữ liệu nguyên thủy là gì?)

Dữ liệu nguyên thủy là các kiểu dữ liệu được java cung cấp sẵn cho chúng ta sử dụng

Có 8 kiểu dữ liệu cơ bản sau: byte, short, int, long, char, boolean, float và double

3.2 If a variable of primitive data type is not assigned, what does it contain?

(nếu một biến của kiểu nguyên thủy k đc gán thì nó chứa j?)

Nếu một biến của kiểu nguyên thủy không được khai báo trước thì nó sẽ chứa các giá trị mặc định

3.3 What happens when you assign a variable of primitive data type to another variable of same type?

(điều gì xảy ra khi bạn gán một biến kiểu dữ liệu nguyên thủy cho một biến khác cùng kiểu?)

3.4 What are reference data types?

(các kiểu dữ liệu tham chiếu là gì?)

Có 8 kiểu dữ liệu là tham trị, còn lại thì là kiểu dữ liệu tham chiếu

Ví dụ như: object, list, array… và tất cả các class mà bạn tạo ra

Trang 4

3.5 What happens when you assign a variabla of reference data type to another variable

of same reference type?

(điều gì xảy ra khi bạn gán một biến thể của kiểu dữ liệu tham chiếu cho một biến khác có cùng kiểu tham chiếu?)

3.6 What are the differences between primitive data types and reference data types? (sự khác nhau giữa kiểu dữ liệu nguyên thủy và kiểu dữ liệu tham chiếu?)

Sự khác nhau cơ bản nhất giữa 2 kiểu dữ liệu này là cách thức mà chúng lưu trữ dữ liệu, bên cạnh đó các kiểu dữ liệu nguyên thủy đều không có các phương thức đi kèm, trong khi các kiểu dữ liệu tham chiếu đều có các phương thức đi kèm như ArrayList thì có add(), remove(), Object thì có toString()…

Cụ thể:

- Kiểu dữ liệu nguyên thủy lưu trữ dữ liệu trong chính bản thân nó

- Kiểu dữ liệu tham chiếu chỉ lưu trữ 1 giá trị là địa chỉ đến vùng nhớ mà nó tham chiếu đến

3.7 If a variable of reference data type is not assigned, what does it contain?

(nếu một biến kiểu dữ liệu tham chiếu không đc gán thì nó chứa gì?)

4. Access Modifiers (công cụ sửa đổi quyền truy cập)

4.1 what is the purpose of access modifier?

(mục đích của access modifiers?)

Có hai loại access modifier trong java là access modifier và non-access modifier Access modifier trong java xác định phạm vi có thể truy cập của biến, phương thức, constructor hoặc class

4.2 What is the scope of private, protected and public access modifiers?

(phạm vi của access modifiers)

- Phạm vi truy cập của access modifier: private, default, protected, public

- Ngoài ra có nhiều non-access modifier như static, abstract, native,…

4.3 What happens when no access modifier is specified with the class?

(điều gì xảy ra khi không có access modifier nào đc chỉ định với lớp)

5. Static

5.1 What are static variables?

(biến tĩnh là gì?)

Biến tĩnh là biến sẽ được tạo ra duy nhất một lần khi gọi hàm lần đầu tiên và nó sẽ không bị xóa đi để tạo lại khi gọi lại hàm đấy

5.2 What are static methods?

(phương thức tĩnh là gì?)

Trang 5

Một phương thức tĩnh là một phương thức có thể được gọi sử dụng mà không cần thông qua việc tạo đối tượng các phương thức tĩnh không thuộc về một đối tượng thực thể của lớp mà thuộc về bản thân lớp đó

5.3 Does static method has access to an instance member? Why?

(phương thức tĩnh có quyền truy cập vào một thành viên thể hiện k? tại sao)

6. Final

6.1 Explain final class? What are the benefits of declaring a class final?

(giải thích lớp final? Lợi ích của việc khai báo lớp final là j?)

Lớp final: từ khóa final được sử dụng cho một lớp, lớp này sẽ không thể được kế thừa

6.2 Explain final method? What are the benefits of declaring a method final?

Khi một phương thức được khai báo với từ khóa final, các class con kế thừa sẽ không thể ghi đè (override) phương thức này

6.3 Explain final variable? What are the benefits of declaring a variable final?

Khi một biến được khai báo với từ khóa final, nó chỉ chứa một giá trị duy nhất trong toàn bộ chương trình (nói dễ hiểu hơn là biến hằng)

6.4 When you declare a variable final, can you change it to reference another object? Nếu bạn tạo bất cứ biến nào là final, bạn không thể thay đổi giá trị của biến final (nó

sẽ là hằng số)

7. Pass by value or Pass by reference

7.1 What is the difference between pass by value and pass by reference?

(sự khác nhau giữa truyền tham trị và truyền tham chiếu)

Truyền tham chiếu: truyền địa chỉ của biến vào hàm

Truyền tham trị: truyền giá trị của biến vào hàm

Khi truyền theo tham trị thì giá trị của biến được chép thành một bản sao, việc tính toán sẽ thực hiện trên bản sao đã tạo => giá trị biến truyền vào không thay đổi

Khi truyền theo tham chiếu, địa chỉ của biến sẽ được truyền vào hàm, việc thực hiện các phép tính toán trong hàm đối với biến này đều thực hiện trực tiếp trên địa chỉ chứa giá trị của biến đó => giá trị biến truyền vào thay đổi

7.2 How are the reference type arguments passed in java; by reference or by value? Trong java, chúng ta chỉ có thể truyền các tham số theo giá trị Điều này có nghĩa là một bản sao của giá trị sẽ được chuyển cho một phương thức nhưng việc truyền một bản sao của giá trị cũng làm thay đổi giá trị thực của đối tượng

7.3 If a copy of reference is passed by value, how can the method get access to the object that the reference is pointing to?

(nếu một bản sao của tham chiếu được truyền theo giá trị, thì làm cách nào để phương thức có thể truy cập vào đối tượng mà tham chiếu đang trỏ tới)

7.4 If a copy of reference is passed by value, can you change the value of reference? (nếu một bản sao của tham chiếu được chuyển theo giá trị, bạn có thể thay đổi giá trị của ham chiếu không?)

8. Naming Concvention (quy ước đặt tên)

8.1 what is naming convention?

Quy tắc đặt tên là một quy ước phải tuân theo khi quyết định nên đặt tên bất kỳ một định danh nào đó như class, package, variable, constant, method…

Trang 6

Quy tắc chính được tuân theo bởi mọi định dạng: tên không đc chứa bất kỳ khoẳng trắng nào, tên k nên bắt đầu bằng các ký tự đặc biệt…

8.2 Why do you need naming convention?

(tại sao cần quy đặt tên)

Tất cả các class, interface, package, method… đều được đưa ra quy ước đặt tên, nếu không tuân theo quy ước này, có thể tạo ra sự nhầm lẫn hoặc sai sót khi viết code Ngoài ra khi tuân theo quy ước đặt tên còn giúp code của bạn dễ đọc hơn cho chính bản thân và cả các lập trình viên khác

8.3 What is the difference between Upper Camel Case and Lower Camel Case?

8.4 Explain naming convention for interface, class, method, variable, constant, enum and acronyms?

(giải thích quy ước đặt tên cho interface, class, method, variable, constant, enum và từ viết tắt)

- Tên interface trong java nên tuân theo những quy ước sau:

Bắt đầu bằng chữ in hoa

Phải là một tính từ, sử dụng các từ thích hợp thay vì các từ viết tắt

- Tên class:

Bắt đầu bằng chữ in hoa

Phải là một danh từ, sử dụng các từ ngữ thích hợp thay vì các từ viết tắt

- Tên method:

Nên bắt đầu bằng chữ thường

Phải là một động từ như main(), print()…

Nếu tên chứa nhiều từ, hãy bắt đầu nó bằng một chữ cái viết thường theo sau là một chữ cái viết hoa

- Tên biến (variable):

Nên bắt đầu bằng một chữ cái viết thường như id, name, radius…

Không nên bắt đầu bằng các ký tự đặc biệt như $ hay _

Nếu tên chứa nhiều từ, hãy bắt đầu bằng chữ cái viết thường theo sau là chữ cái viết hoa như firstName, lastName

- Tên hằng (constant):

Nên được viết bằng chữ in hoa như RED, YELLOW

Nếu tên chứa nhiều từ, nó phải được phân cách bằng dấu gạch dưới

Có thể chứa các số nhưng không được bắt đầu bằng số

9. Polymorphism (tính đa hình)

9.1 what is Polymorphism?

Đa hình lúc runtime là quá trình gọi phương thức đã được ghi đè trong thời gian thực thi chương trình Trong quá trình này, một phương thức được ghi đè được gọi thông qua biến tham chiếu của một lớp cha

9.2 What are different ways to achieve polymorphism?

(các cách khác nhau để đạt được tính đa hình?)

Có hai kiểu đa hình trong java:

- Đa hình tĩnh static/compile: khi trình biên dịch quyết định phân tích đa hình trong quá trình biên dịch, chúng ta có thể gọi tính đa hình này là đa hình trong thời gian biên dịch hoặc đa hình tĩnh

Trang 7

- Đa hình động Dynamic/run: đa hình động hay đa hình trong runtime là đa hình giải quyết các hành động tại thời gian chạy chứ không phải thời gian biên dịch được gọi hay nói cách khác, đa hình lúc runtime là quá trình gọi phương thức đã được ghi đè trong thời gian thực thi chương trình

9.3 How is inheritance useful to achieve polymorphism?

9.4 What are the benefits of polymorphism?

- Tính đa hình cho phép một lớp cha xác định các phương thức chung cho tất cả các lớp dẫn xuất của nó trong khi cho phép các lớp con chỉ định việc triển khai bổ sung của một số hoặc tất cả các phương thức đó

- Ghi đè phương thức được hỗ trợ bởi tính đa hình động, một khía cạnh chính của tính

đa hình liên kết động hoặc thời gian chạy

- Tính đa hình cung cấp khả năng cho một phương pháp thực hiện những việc khác nhau trên cơ sở đối tượng mà nó đang tác động

10. Subtype polymorphism

10.1 what is Subtype Polymorphism?

11. Overriding (ghi đè phương thức)

11.1 what is method overriding?

Overriding được sử dụng trong trường hợp lớp con kế thừa từ lớp cha và muốn định nghĩa lại một phương thức đã có mặt ở lớp cha Một lớp cha thông thường có thể có nhiều lớp con kế thừa, tuy nhiên phương thức ở lớp cha có thể phù hợp với lớp con này nhưng không phù hợp với lớp con khác, do đó lớp con cần ghi đè lại phương thức

đó cho phù hợp

11.2 What dynamic polymorphism?

(đa hình động là gì?)

Đa hình động (overriding) là đa hình lúc thực thi (runtime), cho phép tạo các lớp trừu tượng (abstract class) được sử dụng để cung cấp triển khai lớp một phần của giao diện

11.3 Why can’t you override static methods defined in super class or interface?

11.4 Can you override a final method defined in super class?

12. Overloading (nạp chồng phương thức)

12.1 explain method overloading?

Trong java, overloading là định nghĩa là nạp chồng phương thức, có nghĩa là nếu trong một lớp có nhiều phương thức cùng tên nhưng:

- khác nhau về số đối số truyền vào và các đối số có cùng kiểu dữ liệu

- có cùng số đối số truyền vào và các đối số không có cùng kiểu dữ liệu

- khác nhau trình tự kiểu dữ liệu của các đối số

12.2 What is static polymorphism?

(tính đa hình tĩnh là gì?)

Khi trình biên dịch quyết định phân tích đa hình trong quá trình biên dịch, chúng ta có thể gọi tính đa hình này là đa hình trong tgian biên dịch hoặc đa hình tĩnh Trong java

có thể thực hiện hoặc đạt được tính đa hình trong thời gian biên dịch với sự hỗ trợ của phương thức nạp chồng

12.3 What is the difference between static and dynamic polymorphism?

- Đa hình động (thời gian chạy) là đa hình tồn tại trong thời gian chạy ở đây, trình biên dịch java không hiểu phương thức nào được gọi tại thời điểm biên dịch Chỉ JVM

Trang 8

quyết định phương thức nào được gọi vào thời gian chạy Quá tải phương thức và ghi

đè phương thức bằng các phương thức thể hiện là ví dụ cho đa hình động

- Đa hình tĩnh (thời gian biên dịch): là đa hình được thể hiện tại thời gian biên dịch Ở đây, trình biên dịch java biết phương thức nào được gọi Phương thức nạp chồng và phương thức ghi đè bằng phương thức tĩnh; ghi đè phương thức bằng các phương thức riêng tư hoặc cuối cùng là các ví dụ cho đa hình tĩnh

12.4 Can you override a method such that all the parameters are same with the

difference only in the return type?

12.5 What are the benefits of method overloading?

- Sử dụng nạp chồng phương thức giúp tăng khả năng đọc hiểu chương trình

- Sử dụng khi trong cùng một phương thức, chúng ta lại muốn làm thêm một công việc khác

12.6 What is the difference between overriding and overloading?

- Overriding đc sử dụng khi trong cùng một phương thức, chúng ta muốn thay đổi phần thân của phương thức đó

- Overloading được sử dụng khi trong cùng một phương thức chúng ta lại muốn thêm một công việc khác

13. Abstraction (trừu tượng)

13.1 What is abstraction?

tính trừu tượng trong java là tính chất không thể hiện cụ thể mà chỉ nêu tên vấn đề

Đó là một quá trình che giấu các hoạt động bên trong và chỉ hiển thị những tính năng thiếu yếu của đối tượng người dùng

13.2 How abstraction is different from encapsulation?

(trừu tượng khác với đóng gói ntn)

- Đóng gói là việc đóng gói dữ liệu và các chức năng hoạt động trên dữ liệu đó thành một thành phần duy nhất và hạn chế quyền truy cập vào một số thành phần của đối tượng

- Đóng gói có nghĩa là biểu diễn bên trong của một đối tượng thường bị ẩn khỏi chế độ xem bên ngoài định nghĩa của đối tượng

- Trừu tượng là một cơ chế đại diện cho các tính năng thiếu yếu mà không bao gồm các chi tiết thực hiện

- Đóng gói: ẩn thông tin

- Trừu tượng: thực hiện ẩn

13.3 What are the benefits of abstraction?

- Cho phép các lập trình viên loại bỏ tính chất phức tạp của đối tượng bằng cách chỉ đưa ra các thuộc tính và phương thức cần thiết của đối tượng trong lập trình, cải thiện khả năng bảo trì của hệ thống

Trang 9

- Tính trừu tượng giúp chúng ta tập trung vào những cốt lõi cần thiết của đối tượng thay vì quan tâm đến cách nó thực hiện

- Tính trừu tượng cung cấp nhiều tính năng mở rộng khi sử dụng kết hợp với tính đa hình và kế thừa trong lập trình hướng đối tượng

14. Inheritance (thừa kế)

14.1 Explain inheritance?

- Kế thừa trong java là sự liên quan giữa hai class với nhau, trong đó có class cha (superclass) và class con (subclass) Khi kế thừa class con được hưởng tất cả các phương thức và thuộc tính của class cha Tuy nhiên, nó chỉ truy cập được các thành viên public và protected của class cha Nó không được phép truy cập đến thành viên private của class cha

14.2 What is the purpose of inheritance?

- Lớp con có thể tận dụng lại các thuộc tính và phương thức của lớp cha

- Lớp con có thể định nghĩa thêm thuộc tính và phương thức mới của riêng nó và có thể định nghĩa lại phương thức được kế thừa từ lớp cha cho phù hợp với mục đích của nó

14.3 What should be the criteria to decide inheritance relation between two classes?

14.4 How inheritance plays an important role in polymorphism?

14.5 Can you inherit final class?

14.6 What happens if you don’t use super keyword to call an overridden member?

15. Composition (hợp thành)

15.1 Explain composition?

Khai báo biến tham chiếu của một class trong một class khác được gọi là composition (sự hợp thành)

Compositon trong java là kỹ thuật thiết kế để thực thi các mối quan hệ has – a trong các class Chúng ta có thể sử dụng java Inheritance hoặc Object composition trong java để sử dụng lại code

15.2 What is the difference between inheritance and composition?

- Kế thừa là khả năng cho một lớp kế thừa các thuộc tính và hành vi từ một lớp cha bằng cách mở rộng nó

- Thành phần là khả năng của một lớp chứa các đối tượng của các lớp khác nhau làm

dữ liệu thành viên

- Nếu một lớp được mở rộng, nó kế thừa tất cả các thuộc tính/hành vi công khai và được bảo vệ và các hành vi đó có thể bị lớp con ghi đè Nhưng nếu một lớp được chứa trong một lớp khác, container không có khả năng thay đổi hoặc thêm hành vi vào trong lớp Kế thừa đại diện cho một mối quan hệ là một mối quan hệ trong OOP, trong khi thành phần là đại diện cho một mối quan hệ có một mối quan hệ

15.3 What should be the criteria to decide composition relation between two classes? (đâu là tiêu chí quyết định mối quan hệ thành phần giữa hai nhóm?)

- Composition đại diện cho quan hệ part-of (là một phần)

- Trong compositon, cả hai thực thể đều phụ thuộc vào nhau

- Khi có một mối quan hệ hợp thành giữa hai thực thể, đối tượng composed không thể tồn tại mà không có thực thể khác

15.4 Explain few problems with inheritance that can be avoided by using composition? (giải thích một số vấn đề về kế thừa có thể tránh được bằng cách sử dụng

composition)

Trang 10

- Giải quyết được vấn đề tạo ra 1 big hirachy khi dùng kế thừa

- Compositon giúp dễ rang reuse code giữa các đối tượng 1 cách linh hoạt

- Khi thêm mới / thay đổi các hành vi của đối tượng thì không cần phải thay đổi quá nhiều code hiện có, chỉ cần viết thêm code và thay thế các hành vi mới vào hành vi hiện tại

- Để reuse code mà có liên quan đến UI kéo thả thì sử dụng inheritance là bất khả thi, còn composition vẫn có thể giải quyết được

15.5 When would you prefer composition over inheritance and vice versa?

(khi nào bạn thích composition hơn inheritance và ngược lại?)

- Sự kế thừa có ý nghĩa hơn ở những nơi có tính đa hình động Nếu không thì

composition thích hợp hơn Composition có nhiều dạng, bao gồm thêm thành viên dữ liệu hoặc thêm đối số mẫu…

16. String Immutability (tính bất biến của chuỗi)

16.1 Why String objects are called immutable?

(tại sao các đối tượng chuỗi được gọi là bất biến?)

- Security: các tham số thường được biểu diễn dưới dạng String trong các kết nối mạng, url kết nối cơ sở dữ liệu…

- Đồng bộ hóa và đồng thời: làm cho chuỗi bất biến tự động là cho chúng trở thành chuổi an toàn do đó giải quyết các vấn đề đồng bộ hóa

- Bộ nhớ đệm: khi trình biên dịch tối ưu hóa các đối tượng chuỗi, nó sẽ thấy nếu hai đối tượng có cùng giá trị thì chỉ cần một đối tượng chuỗi

- Tải lớp: String được sử dụng làm đối số cho tải lớp nếu có thể thay đổi, nó có thể dẫn đến lớp sai được tải

16.2 How is string object created in memory?

(đối tượng chuỗi được tạo như thế nào trong bộ nhớ)

16.3 What are the advantages and disadvantages of String Immutability?

17. String Literal vs Object

17.1 What is String literal?

17.2 What are the differences between String Literal and String Object?

17.3 How are the String Literals stores?

18. What is String interning?

18.1 what is String interning?

18.2 How can you intern a String object?

18.3 What happens when you store a new String literal value that is already present in the string pool?

18.4 What are the drawbacks of creating large number of String literals?

19. String Pool Memory Management

19.1 Explain String Pool Memory Management?

19.2 How are String Literals stored in memory?

19.3 How are String Objects stored in memory?

20. StringBuilder vs StringBuffer

20.1 what are the similarities and differences between StringBuffer and StringBuilder?

20.2 When would you prefer StringBuffer to StringBuilder?

21. Stack vs Heap

21.1 What is stack?

Ngày đăng: 17/04/2022, 20:48

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w