Hỏi đáp về IT
Mã xác nhận Thay đổi một
Ngô Quang Hải quanghaisoft@yahoo.com Bigdata engineering - Backend-IT - MWG

Hơn 50 Câu Hỏi Và Câu Trả Lời Phỏng Vấn Java Cốt Lõi Hàng Đầu

Duyệt qua: 71

 

Câu hỏi và câu trả lời phỏng vấn Java thường gặp nhất với các ví dụ:

Trong hướng dẫn này, chúng tôi đã đề cập đến gần 50+ câu hỏi phỏng vấn Java cốt lõi quan trọng dành cho những ứng viên mới bắt đầu và có kinh nghiệm.

Bài đăng về Câu hỏi phỏng vấn JAVA này được chuẩn bị để giúp bạn hiểu các khái niệm cơ bản về lập trình Java cho mục đích phỏng vấn. Tất cả các khái niệm JAVA quan trọng được giải thích ở đây với các ví dụ để bạn dễ hiểu.

Hướng dẫn này bao gồm các chủ đề JAVA như định nghĩa Java cơ bản, khái niệm OOP, công cụ xác định Access, Bộ sưu tập, Ngoại lệ, Chủ đề, Chuỗi tuần tự, v.v., với các ví dụ để bạn sẵn sàng hoàn hảo để đối mặt với bất kỳ cuộc phỏng vấn JAVA nào một cách tự tin.

 

Câu Hỏi Và Câu Trả Lời Phỏng Vấn Java Phổ Biến Nhất

Dưới đây là danh sách đầy đủ các câu hỏi phỏng vấn lập trình Java cơ bản và nâng cao quan trọng và thường được hỏi nhất với câu trả lời chi tiết.

Q # 1) JAVA là gì?

Trả lời: Java là một ngôn ngữ lập trình cấp cao và độc lập với nền tảng.

Java là một tập hợp các đối tượng. Nó được phát triển bởi Sun Microsystems. Có rất nhiều ứng dụng, trang web và trò chơi được phát triển bằng Java.

Q # 2) Các tính năng của JAVA là gì?

Trả lời: Các tính năng của Java như sau:

  • Khái niệm OOP
    • Hướng đối tượng
    • Di sản
    • Đóng gói
    • Tính đa hình
    • Trừu tượng
  • Nền tảng độc lập: Một chương trình duy nhất hoạt động trên các nền tảng khác nhau mà không cần bất kỳ sửa đổi nào.
  • Hiệu suất cao: JIT (trình biên dịch Just In Time) cho phép hiệu suất cao trong Java. JIT chuyển đổi mã bytecode thành ngôn ngữ máy và sau đó JVM bắt đầu thực thi.
  • Đa luồng: Một luồng thực thi được gọi là Luồng. JVM tạo một luồng được gọi là luồng chính. Người dùng có thể tạo nhiều luồng bằng cách mở rộng lớp luồng hoặc bằng cách triển khai giao diện Runnable.

Q # 3) Làm cách nào để Java kích hoạt hiệu suất cao?

Trả lời: Java sử dụng trình biên dịch Just In Time để kích hoạt hiệu suất cao. Nó được sử dụng để chuyển đổi các hướng dẫn thành mã bytecodes.

Q # 4) Đặt tên cho Java IDE?

Trả lời: Eclipse và NetBeans là IDE của JAVA.

Q # 5) Ý bạn là gì về Constructor?

Trả lời: Constructor có thể được giải thích chi tiết với các điểm ưu tiên:

  • Khi một đối tượng mới được tạo trong một chương trình, một hàm tạo sẽ được gọi tương ứng với lớp.
  • Hàm tạo là một phương thức có cùng tên với tên lớp.
  • Nếu người dùng không tạo một hàm tạo thì mặc nhiên một hàm tạo mặc định sẽ được tạo.
  • Hàm tạo có thể được nạp chồng.
  • Nếu người dùng đã tạo một phương thức khởi tạo có tham số thì anh ta nên tạo một phương thức khởi tạo khác một cách rõ ràng mà không có tham số.

Câu hỏi # 6) Biến cục bộ và biến cá thể có nghĩa là gì?

Câu trả lời:

Các biến cục bộ được xác định trong phương thức và phạm vi của các biến tồn tại bên trong chính phương thức đó.

Biến thể hiện được định nghĩa bên trong lớp và bên ngoài phương thức và phạm vi của các biến tồn tại trong suốt lớp.

Q # 7) Lớp là gì?

Trả lời: Tất cả các mã Java được định nghĩa trong một Lớp. Nó có các biến và phương thức.

Các biến là các thuộc tính xác định trạng thái của một lớp.

Các phương pháp là nơi mà logic nghiệp vụ chính xác phải được thực hiện. Nó chứa một tập hợp các câu lệnh (hoặc) hướng dẫn để đáp ứng yêu cầu cụ thể.

Thí dụ:

public class Addition{ //Class name declaration
int a = 5; //Variable declaration
int b= 5;
public void add(){ //Method declaration
int c = a+b;
}
}

Q # 8) Đối tượng là gì?

Câu trả lời: Một thể hiện của một lớp được gọi là một đối tượng. Đối tượng có trạng thái và hành vi.

Bất cứ khi nào JVM đọc từ khóa “new ()” thì nó sẽ tạo một thể hiện của lớp đó.

Thí dụ:

public class Addition{
public static void main(String[] args){
Addion add = new Addition();//Object creation
}
}

Đoạn mã trên tạo đối tượng cho lớp Addition.

H # 9) Các khái niệm OOP là gì?

Trả lời: Các khái niệm OOP bao gồm:

  • Di sản
  • Đóng gói
  • Tính đa hình
  • Trừu tượng
  • Giao diện

Đề xuất Đọc = >> Câu hỏi phỏng vấn OOPs hàng đầu

Q # 10) Thừa kế là gì?

Trả lời: Kế thừa có nghĩa là một lớp có thể mở rộng sang lớp khác. Vì vậy, các mã có thể được sử dụng lại từ lớp này sang lớp khác. Lớp hiện có được gọi là lớp Siêu trong khi lớp dẫn xuất được gọi là lớp con.

Thí dụ:

Super class:
public class Manupulation(){
}
Sub class:
public class Addition extends Manipulation(){
}

Kế thừa chỉ áp dụng cho công chúng và các thành viên được bảo vệ. Các thành viên riêng tư không thể được kế thừa.

Q # 11) Encapsulation là gì?

Trả lời: Mục đích của việc đóng gói:

  • Bảo vệ mã khỏi những người khác.
  • Khả năng bảo trì mã.

Thí dụ:

Chúng tôi đang khai báo 'a' là một biến số nguyên và nó không được âm.

public class Addition(){
int a=5;
}

Nếu ai đó thay đổi biến chính xác thành “ a = -5” thì đó là điều tồi tệ.

Để khắc phục sự cố, chúng ta cần làm theo các bước sau:

  • Chúng ta có thể đặt biến ở chế độ riêng tư hoặc được bảo vệ.
  • Sử dụng các phương thức của trình truy cập công khai như set <property> và get <property>.

Vì vậy, mã trên có thể được sửa đổi thành:

public class Addition(){
private int a = 5; //Here the variable is marked as private
}

Đoạn mã dưới đây hiển thị getter và setter.

Điều kiện có thể được cung cấp trong khi thiết lập biến.

get A(){
}
set A(int a){
if(a>0){// Here condition is applied
.........
}
}

Để đóng gói, chúng ta cần đặt tất cả các biến cá thể là riêng tư và tạo setter và getter cho các biến đó. Do đó, điều này sẽ buộc người khác gọi bộ cài đặt thay vì truy cập dữ liệu trực tiếp.

Q # 12) Đa hình là gì?

Trả lời: Đa hình có nghĩa là nhiều dạng.

Một đối tượng duy nhất có thể tham chiếu đến lớp siêu hoặc lớp con tùy thuộc vào kiểu tham chiếu được gọi là đa hình.

Thí dụ:

Public class Manipulation(){ //Super class
public void add(){
}
}
public class Addition extends Manipulation(){ // Sub class
public void add(){
}
public static void main(String args[]){
Manipulation addition = new Addition();//Manipulation is reference type and Addition is reference type
addition.add();
}
}

Sử dụng kiểu tham chiếu Thao tác, chúng ta có thể gọi phương thức “add ()” của lớp Addition. Khả năng này được gọi là Đa hình. Tính đa hình có thể áp dụng cho ghi đè và không áp dụng cho quá tải .

Câu hỏi # 13) Ghi đè phương thức nghĩa là gì?

Trả lời: Việc ghi đè phương thức xảy ra nếu phương thức lớp con thỏa mãn các điều kiện dưới đây với phương thức lớp siêu cấp:

  • Tên phương pháp phải giống nhau
  • Đối số phải giống nhau
  • Loại trả lại cũng phải giống nhau

Lợi ích chính của việc ghi đè là Lớp con có thể cung cấp một số thông tin cụ thể về kiểu lớp con đó hơn lớp siêu cấp.

Thí dụ:

public class Manipulation{ //Super class
public void add(){
………………
}
}
 
Public class Addition extends Manipulation(){
Public void add(){
………..
}
Public static void main(String args[]){
Manipulation addition = new Addition(); //Polimorphism is applied
addition.add(); // It calls the Sub class add() method
}
}

Phương thức add.add () gọi phương thức add () trong lớp con chứ không phải lớp cha. Vì vậy, nó ghi đè phương thức Siêu lớp và được gọi là Ghi đè phương thức.

Q # 14) Quá tải nghĩa là gì?

Trả lời: Quá tải phương thức xảy ra đối với các lớp khác nhau hoặc trong cùng một lớp.

Để nạp chồng phương thức, phương thức lớp con phải thỏa mãn các điều kiện dưới đây với phương thức (hoặc) phương thức siêu lớp trong cùng một lớp:

  • Cùng một tên phương pháp
  • Các kiểu đối số khác nhau
  • Có thể có các loại trả lại khác nhau

Thí dụ:

public class Manipulation{ //Super class
public void add(String name){ //String parameter
………………
}
}
 
Public class Addition extends Manipulation(){
Public void add(){//No Parameter
………..
}
Public void add(int a){ //integer parameter
 
}
Public static void main(String args[]){
Addition addition = new Addition();
addition.add();
}
}

Ở đây phương thức add () có các tham số khác nhau trong lớp Addition được nạp chồng trong cùng một lớp như với siêu lớp.

Lưu ý: Tính đa hình không được áp dụng cho quá trình nạp chồng phương thức.

Q # 15) Giao diện nghĩa là gì?

Câu trả lời: Không thể đạt được nhiều kế thừa trong java. Để khắc phục vấn đề này, khái niệm Giao diện được giới thiệu.

Giao diện là một khuôn mẫu chỉ có khai báo phương thức chứ không phải triển khai phương thức.

Thí dụ:

Public abstract interface IManupulation{ //Interface declaration
Public abstract void add();//method declaration
public abstract void subtract();
}
  • Tất cả các phương thức trong giao diện là khoảng trống trừu tượng công khai bên trong .
  • Tất cả các biến trong giao diện là nội bộ công khai tĩnh cuối cùng là hằng số.
  • Các lớp có thể triển khai giao diện và không mở rộng.
  • Lớp triển khai giao diện phải cung cấp một triển khai cho tất cả các phương thức được khai báo trong giao diện.
public class Manupulation implements IManupulation{ //Manupulation class uses the interface
Public void add(){
……………
}
Public void subtract(){
…………….
}
}

Q # 16) Lớp Trừu tượng nghĩa là gì?

Trả lời: Chúng ta có thể tạo lớp Abstract bằng cách sử dụng từ khóa "Abstract" trước tên lớp. Một lớp trừu tượng có thể có cả phương thức “Trừu tượng” và phương thức “Không trừu tượng” là một lớp cụ thể.

Phương pháp trừu tượng:

Phương thức chỉ có phần khai báo và không có phần thực thi được gọi là phương thức trừu tượng và nó có từ khóa là “abstract”. Các khai báo kết thúc bằng dấu chấm phẩy.

Thí dụ:

public abstract class Manupulation{
public abstract void add();//Abstract method declaration
Public void subtract(){
}
}
  • Một lớp trừu tượng cũng có thể có một phương thức không trừu tượng.
  • Lớp con cụ thể mở rộng lớp Abstract nên cung cấp việc triển khai các phương thức trừu tượng.

Q # 17) Sự khác biệt giữa Mảng và Danh sách Mảng.

Trả lời: Sự khác biệt giữa Mảng và Danh sách Mảng có thể được hiểu từ bảng dưới đây:

                        Mảng                                      

   Lập danh sách    
Kích thước phải được cung cấp tại thời điểm khai báo mảng.

String [] name = new String [2]
Kích thước có thể không được yêu cầu. Nó thay đổi kích thước động.

Lập danh sách name = new ArrayList
Để đưa một đối tượng vào mảng, chúng ta cần chỉ định chỉ mục.

name [1] = “sách”
Không yêu cầu chỉ mục.

name.add (“sách”)
Mảng không được tham số hóa kiểu ArrayList trong java 5.0 được tham số hóa.

Ví dụ: Dấu ngoặc nhọn này là một tham số kiểu có nghĩa là một danh sách các Chuỗi.

Q # 18) Sự khác biệt giữa Chuỗi, Trình tạo chuỗi và Bộ đệm chuỗi.

Câu trả lời:

Chuỗi: Các biến chuỗi được lưu trữ trong một “nhóm chuỗi không đổi”. Khi tham chiếu chuỗi thay đổi giá trị cũ tồn tại trong “nhóm chuỗi không đổi”, nó không thể bị xóa.

Thí dụ:

String name = “book”;

Nhóm chuỗi không đổi

.

Nếu tên-giá trị đã thay đổi từ “sách” thành “bút”.

Nhóm chuỗi không đổi

Sau đó, giá trị cũ hơn vẫn còn trong nhóm chuỗi không đổi.

Bộ đệm chuỗi:

  • Ở đây các giá trị chuỗi được lưu trữ trong một ngăn xếp. Nếu các giá trị được thay đổi thì giá trị mới sẽ thay thế giá trị cũ hơn.
  • Bộ đệm chuỗi được đồng bộ hóa, an toàn cho chuỗi.
  • Hiệu suất chậm hơn Trình tạo chuỗi.

Thí dụ:

String Buffer name = ”book”;

Khi giá trị tên đã được thay đổi thành “bút” thì “sách” sẽ bị xóa trong ngăn xếp.

Trình tạo chuỗi:

Điều này giống với String Buffer ngoại trừ String Builder không được phân luồng một cách an toàn và không được đồng bộ hóa. Vì vậy, rõ ràng là hiệu suất là nhanh chóng.

H # 19) Giải thích về các chỉ định truy cập Công cộng và Riêng tư.

Trả lời: Các phương thức và biến thể hiện được gọi là thành viên.

Công cộng:

Các thành viên công cộng có thể nhìn thấy trong cùng một gói cũng như gói bên ngoài dành cho các gói khác.

Các thành viên công khai của Lớp A được hiển thị cho Lớp B (cùng một gói) cũng như Lớp C (các gói khác nhau).

Riêng tư:

Các thành viên private chỉ hiển thị trong cùng một lớp và không hiển thị cho các lớp khác trong cùng gói cũng như các lớp trong gói bên ngoài.

Các thành viên riêng trong lớp A chỉ hiển thị trong lớp đó. Nó là vô hình đối với lớp B cũng như lớp C.

H # 20) Sự khác biệt giữa các chỉ định truy cập Mặc định và Được bảo vệ.

Câu trả lời:

Mặc định: Các phương thức và biến được khai báo trong một lớp mà không có bất kỳ mã xác định quyền truy cập nào được gọi là mặc định.

Các thành viên mặc định trong Lớp A có thể nhìn thấy đối với các lớp khác bên trong gói và không hiển thị với các lớp bên ngoài gói.

Vì vậy, các thành viên Lớp A có thể nhìn thấy được với Lớp B và vô hình với Lớp C.

Được bảo vệ:

             .

Protected cũng giống như Mặc định nhưng nếu một lớp mở rộng thì nó sẽ hiển thị ngay cả khi nó nằm ngoài gói.

Các thành viên Lớp A có thể nhìn thấy đối với Lớp B vì nó nằm trong gói. Đối với Lớp C nó là vô hình nhưng nếu Lớp C mở rộng Lớp A thì các thành viên sẽ hiển thị với Lớp C ngay cả khi nó nằm ngoài gói.

H # 21) Sự khác biệt giữa HashMap và HashTable.

Trả lời: Có thể thấy sự khác biệt giữa HashMap và HashTable dưới đây:

Bản đồ băm HashTable
Các phương thức không được đồng bộ hóa Các phương pháp chính được đồng bộ hóa
Không an toàn luồng Chủ đề an toàn
Iterator được sử dụng để lặp lại các giá trị Enumerator được sử dụng để lặp lại các giá trị
Cho phép một khóa null và nhiều giá trị null Không cho phép bất kỳ thứ gì rỗng
Hiệu suất cao hơn HashTable Hiệu suất chậm

H # 22) Sự khác biệt giữa HashSet và TreeSet.

Trả lời: Có thể thấy sự khác biệt giữa HashSet và TreeSet dưới đây:

HashSet TreeSet
Các phần tử được chèn theo thứ tự ngẫu nhiên Duy trì các phần tử theo thứ tự đã sắp xếp
Có thể lưu trữ các đối tượng rỗng Không thể lưu trữ các đối tượng rỗng
Hiệu suất nhanh Hiệu suất chậm

Q # 23) Sự khác biệt giữa lớp Trừu tượng và Giao diện.

Trả lời: Sự khác biệt giữa Lớp trừu tượng và Giao diện như sau:

Lớp Tóm tắt:

  • Các lớp trừu tượng có một phương thức khởi tạo mặc định và nó được gọi bất cứ khi nào lớp con cụ thể được khởi tạo.
  • Nó chứa các phương thức Trừu tượng cũng như các phương thức Không trừu tượng.
  • Lớp mở rộng lớp Abstract không yêu cầu thực hiện tất cả các phương thức, chỉ các phương thức trừu tượng mới cần được triển khai trong lớp con cụ thể.
  • Lớp trừu tượng chứa các biến thể hiện.

Giao diện:

  • Nó không có bất kỳ hàm tạo nào và không thể được khởi tạo.
  • Phương thức trừu tượng chỉ nên được khai báo.
  • Các lớp triển khai giao diện phải cung cấp việc triển khai cho tất cả các phương thức.
  • Giao diện chỉ chứa các hằng số.

# 24) Ý nghĩa của Collections trong Java là gì?

Trả lời: Bộ sưu tập là một khung được thiết kế để lưu trữ các đối tượng và thao tác thiết kế để lưu trữ các đối tượng.

Bộ sưu tập được sử dụng để thực hiện các hoạt động sau:

  • Đang tìm kiếm
  • Sắp xếp
  • Thao tác
  • Chèn
  • Xóa

Một nhóm đối tượng được gọi là tập hợp. Tất cả các lớp và giao diện để thu thập đều có sẵn trong gói sử dụng Java.

Q # 25) Tất cả các Lớp và Giao diện có sẵn trong bộ sưu tập là gì?

Trả lời: Dưới đây là các Lớp và Giao diện có sẵn trong Bộ sưu tập:

Giao diện:

  • Bộ sưu tập
  • Danh sách
  • Bộ
  • Bản đồ
  • Tập hợp đã sắp xếp
  • Bản đồ được sắp xếp
  • Xếp hàng

Các lớp học:

  • Danh sách:
  • Lập danh sách
  • Véc tơ
  • Danh sách liên kết

Bộ:

  • Bộ băm
  • Bộ băm được liên kết
  • Bộ cây

Bản đồ:

  • Bản đồ băm
  • Bảng băm
  • TreeMap
  • Bản đồ băm được liên kết

Xếp hàng:

  • Hàng đợi ưu tiên

Q # 26) Có thứ tự và sắp xếp trong bộ sưu tập có nghĩa là gì?

Câu trả lời:

Có thứ tự:  Có nghĩa là các giá trị được lưu trữ trong một bộ sưu tập dựa trên các giá trị được thêm vào bộ sưu tập. Vì vậy, chúng tôi có thể lặp lại các giá trị từ bộ sưu tập theo một thứ tự cụ thể.

Sắp xếp: Cơ chế sắp  xếp có thể được áp dụng bên trong hoặc bên ngoài để nhóm đối tượng được sắp xếp trong một tập hợp cụ thể dựa trên các thuộc tính của đối tượng.

Q # 27) Giải thích các danh sách khác nhau có sẵn trong bộ sưu tập.

Trả lời: Các giá trị được thêm vào danh sách dựa trên vị trí chỉ mục và nó được sắp xếp theo vị trí chỉ mục. Các bản sao được cho phép.

Các loại Danh sách là:

a) Danh sách mảng:

  • Lặp lại nhanh chóng và truy cập ngẫu nhiên nhanh chóng.
  • Nó là một tập hợp có thứ tự (theo chỉ mục) và không được sắp xếp.
  • Nó thực hiện Giao diện truy cập ngẫu nhiên.

Thí dụ:

public class Fruits{
public static void main (String [ ] args){
ArrayList <String>names=new ArrayList <String>();
names.add (“apple”);
names.add (“cherry”);
names.add (“kiwi”);
names.add (“banana”);
names.add (“cherry”);
System.out.println (names);
}
}

Đầu ra:

[Táo, anh đào, kiwi, chuối, anh đào]

Từ đầu ra, Danh sách Mảng duy trì thứ tự chèn và nó chấp nhận các bản sao. Nhưng nó không được sắp xếp.

b) Vectơ:

Nó cũng giống như Array List.

  • Các phương thức vectơ được đồng bộ hóa.
  • Chủ đề an toàn.
  • Nó cũng thực hiện Truy cập Ngẫu nhiên.
  • An toàn chủ đề thường gây ra một lần truy cập hiệu suất.

Thí dụ:

public class Fruit {
public static void main (String [ ] args){
Vector <String> names = new Vector <String> ( );
 names.add (“cherry”);
names.add (“apple”);
names.add (“banana”);
names.add (“kiwi”);
names.add (“apple”);
System.out.println (“names”);
}
}

Đầu ra:

[anh đào, táo, chuối, kiwi, táo]

Vector cũng duy trì thứ tự chèn và chấp nhận các bản sao.

c) Danh sách liên kết:

  • Các yếu tố được liên kết kép với nhau.
  • Hiệu suất chậm hơn danh sách Mảng.
  • Lựa chọn tốt để chèn và xóa.
  • Trong Java 5.0, nó hỗ trợ các phương thức hàng đợi phổ biến peek (), Pool (), Offer (), v.v.

Thí dụ:

public class Fruit {
public static void main (String [ ] args){
Linkedlist <String> names = new linkedlist <String> ( ) ;
names.add(“banana”);
names.add(“cherry”);
names.add(“apple”);
names.add(“kiwi”);
names.add(“banana”);
System.out.println (names);
}
}

Đầu ra:

[chuối, anh đào, táo, kiwi, chuối]

Duy trì thứ tự chèn và chấp nhận các bản sao.

Câu hỏi # 28) Giải thích về Tập hợp và các loại của chúng trong một tập hợp.

Trả lời: Set quan tâm đến tính độc đáo. Nó không cho phép trùng lặp. Ở đây, phương thức “equals ()” được sử dụng để xác định xem hai đối tượng có giống hệt nhau hay không.

a) Bộ băm:

  • Không có thứ tự và không được sắp xếp.
  • Sử dụng mã băm của đối tượng để chèn các giá trị.
  • Sử dụng điều này khi yêu cầu là "không có bản sao và không quan tâm đến đơn đặt hàng".

Thí dụ:

public class Fruit {
public static void main (String[ ] args){
HashSet<String> names = new HashSet <=String>( ) ;
names.add(“banana”);
names.add(“cherry”);
names.add(“apple”);
names.add(“kiwi”);
names.add(“banana”);
System.out.println (names);
}
}

Đầu ra:

[chuối, anh đào, kiwi, táo]

Nó không tuân theo bất kỳ thứ tự chèn nào. Các bản sao không được phép.

b) Bộ băm được liên kết:

  • Một phiên bản có thứ tự của bộ băm được gọi là Bộ băm được liên kết.
  • Duy trì danh sách được Liên kết kép của tất cả các phần tử.
  • Sử dụng điều này khi yêu cầu một thứ tự lặp lại.

Thí dụ:

public class Fruit {
public static void main (String[ ] args){
LinkedHashSet<String>; names = new LinkedHashSet <String>( ) ;
 names.add(“banana”);
 names.add(“cherry”);
 names.add(“apple”);
 names.add(“kiwi”);
 names.add(“banana”);
 System.out.println (names);
 }
}

Đầu ra:

[chuối, anh đào, táo, kiwi]

Nó duy trì thứ tự chèn mà chúng đã được thêm vào Tập hợp. Các bản sao không được phép.

c) Bộ cây:

  • Nó là một trong hai bộ sưu tập đã được sắp xếp.
  • Sử dụng cấu trúc cây “Đọc-Đen” và đảm bảo rằng các phần tử sẽ theo thứ tự tăng dần.
  • Chúng ta có thể xây dựng một tập hợp cây với hàm tạo bằng cách sử dụng một bộ so sánh có thể so sánh được (hoặc).

Thí dụ:

public class Fruits{
public static void main (String[ ]args) {
Treeset<String> names= new TreeSet<String>( ) ;
names.add(“cherry”);
names.add(“banana”);
names.add(“apple”);
names.add(“kiwi”);
names.add(“cherry”);
System.out.println(names);
}
}

Đầu ra:

[táo, chuối, anh đào, kiwi]

TreeSet sắp xếp các phần tử theo thứ tự tăng dần. Và các bản sao không được phép.

Câu hỏi # 29) Giải thích về Bản đồ và các loại của nó.

Trả lời: Bản đồ quan tâm đến định danh duy nhất. Chúng tôi có thể ánh xạ một khóa duy nhất đến một giá trị cụ thể. Nó là một cặp khóa / giá trị. Chúng tôi có thể tìm kiếm một giá trị, dựa trên khóa. Giống như tập hợp, bản đồ cũng sử dụng phương thức “equals ()” để xác định xem hai khóa giống nhau hay khác nhau.

Bản đồ có các loại sau:

a) Bản đồ băm:

  • Bản đồ không có thứ tự và không được sắp xếp.
  • Hashmap là một lựa chọn tốt khi chúng ta không quan tâm đến thứ tự.
  • Nó cho phép một khóa null và nhiều giá trị null.

Thí dụ:

Public class Fruit{
Public static void main(String[ ] args){
HashMap<Sting,String> names =new HashMap<String,String>( );
names.put(“key1”,“cherry”);
names.put (“key2”,“banana”);
names.put (“key3”,“apple”);
names.put (“key4”,“kiwi”);
names.put (“key1”,“cherry”);
System.out.println(names);
}
 }

Đầu ra:

{key2 = banana, key1 = cherry, key4 = kiwi, key3 = apple}

Các khóa trùng lặp không được phép trong Bản đồ.

Nó không duy trì bất kỳ thứ tự chèn nào và không được sắp xếp.

b) Bảng băm:

  • Giống như khóa vectơ, các phương thức của lớp được đồng bộ hóa.
  • Chủ đề an toàn và do đó làm chậm hiệu suất.
  • Nó không cho phép bất cứ điều gì là null.

Thí dụ:

public class Fruit{
public static void main(String[ ]args){
Hashtable<Sting,String> names =new Hashtable<String,String>( );
names.put(“key1”,“cherry”);
names.put(“key2”,“apple”);
names.put(“key3”,“banana”);
names.put(“key4”,“kiwi”);
names.put(“key2”,“orange”);
System.out.println(names);
}
 }

Đầu ra:

{key2 = apple, key1 = cherry, key4 = kiwi, key3 = banana}

Các khóa trùng lặp không được phép.

c) Bản đồ băm được liên kết:

  • Duy trì thứ tự chèn.
  • Chậm hơn bản đồ Hash.
  • Tôi có thể mong đợi một sự lặp lại nhanh hơn.

Thí dụ:

public class Fruit{
public static void main(String[ ] args){
LinkedHashMap<Sting,String> names =new LinkedHashMap<String,String>( );
 names.put(“key1”,“cherry”);
 names.put(“key2”,“apple”);
 names.put(“key3”,“banana”);
 names.put(“key4”,“kiwi”);
 names.put(“key2”,“orange”);
 System.out.println(names);
 }
 }

Đầu ra:

{key2 = apple, key1 = cherry, key4 = kiwi, key3 = banana}

Các khóa trùng lặp không được phép.

d) Bản đồ cây:

  • Bản đồ được sắp xếp.
  • Giống như Tree set, chúng ta có thể xây dựng một thứ tự sắp xếp với hàm tạo.

Thí dụ:

public class Fruit{
public static void main(String[ ]args){
TreeMap<Sting,String> names =new TreeMap<String,String>( );
names.put(“key1”,“cherry”);
names.put(“key2”,“banana”);
names.put(“key3”,“apple”);
names.put(“key4”,“kiwi”);
names.put(“key2”,“orange”);
System.out.println(names);
}
}

Đầu ra:

{key1 = cherry, key2 = banana, key3 = apple, key4 = kiwi}

Nó được sắp xếp theo thứ tự tăng dần dựa trên khóa. Các khóa trùng lặp không được phép.

Câu hỏi # 30) Giải thích Hàng đợi Ưu tiên.

Trả lời: Giao diện hàng đợi

Hàng đợi ưu tiên:  Lớp danh sách liên kết đã được cải tiến để triển khai giao diện hàng đợi. Hàng đợi có thể được xử lý bằng một danh sách được liên kết. Mục đích của hàng đợi là "Ưu tiên vào, Ưu tiên ra".

Do đó các phần tử được sắp xếp theo thứ tự tự nhiên hoặc theo bộ so sánh. Thứ tự các phần tử thể hiện mức độ ưu tiên tương đối của chúng.

Câu hỏi # 31) Ngoại lệ nghĩa là gì?

Trả lời: Ngoại lệ là sự cố có thể xảy ra trong quá trình thực thi bình thường. Một phương thức có thể ném ra một ngoại lệ khi có thứ gì đó kêu trong thời gian chạy. Nếu ngoại lệ đó không thể được xử lý, thì việc thực thi sẽ bị chấm dứt trước khi nó hoàn thành nhiệm vụ.

Nếu chúng tôi xử lý ngoại lệ, thì quy trình bình thường sẽ tiếp tục. Ngoại lệ là một lớp con của java.lang.Exception.

Ví dụ để xử lý Ngoại lệ:

try{
//Risky codes are surrounded by this block
}catch(Exception e){
//Exceptions are caught in catch block
}

H # 32) Các loại Ngoại lệ là gì?

Trả lời: Có hai loại Ngoại lệ. Chúng được giải thích chi tiết bên dưới.

a) Ngoại lệ được Kiểm tra:

Các ngoại lệ này được trình biên dịch kiểm tra tại thời điểm biên dịch. Các lớp mở rộng lớp Có thể ném ngoại trừ ngoại lệ Thời gian chạy và Lỗi được gọi là Ngoại lệ đã kiểm tra.

Các ngoại lệ được chọn phải khai báo ngoại lệ bằng cách sử dụng từ khóa throws (hoặc) được bao quanh bởi try / catch thích hợp.

Ví dụ,  ngoại lệ ClassNotFound

b) Ngoại lệ không được chọn:

Các ngoại lệ này không được trình biên dịch kiểm tra trong thời gian biên dịch. Trình biên dịch không buộc xử lý những ngoại lệ này. Nó bao gồm:

  • Ngoại lệ số học
  • ArrayIndexOutOfBounds Exception

Q # 33) Các cách khác nhau để xử lý các trường hợp ngoại lệ là gì?

Trả lời: Hai cách khác nhau để xử lý các ngoại lệ được giải thích dưới đây:

a) Sử dụng try / catch:

Mã rủi ro được bao quanh bởi khối thử. Nếu một ngoại lệ xảy ra, thì nó sẽ bị chặn bởi khối catch được theo sau bởi khối try.

Thí dụ:

class Manipulation{
public static void main(String[] args){
add();
}
Public void add(){
try{
addition();
}catch(Exception e){
e.printStacktrace();
}
}
}

b) Bằng cách khai báo từ khóa throws:

Ở cuối phương thức, chúng ta có thể khai báo ngoại lệ bằng từ khóa throws.

Thí dụ:

class Manipulation{
public static void main(String[] args){
add();
}
public void add() throws Exception{
addition();
}
}

Q # 34) Ưu điểm của xử lý Ngoại lệ là gì?

Trả lời: Những ưu điểm như sau:

  • Luồng thực thi bình thường sẽ không bị chấm dứt nếu một ngoại lệ được xử lý
  • Chúng tôi có thể xác định vấn đề bằng cách sử dụng khai báo bắt

 Câu hỏi # 35) Các từ khóa xử lý Ngoại lệ trong Java là gì?

Trả lời: Dưới đây là hai Từ khoá Xử lý Ngoại lệ:

một sự cố gắng:

Khi một mã rủi ro được bao quanh bởi một khối thử. Một ngoại lệ xảy ra trong khối try bị chặn bởi khối catch. Thử có thể được theo sau bởi bắt (hoặc) cuối cùng (hoặc) cả hai. Nhưng bất kỳ một trong các khối là bắt buộc.

b) bắt:

Tiếp theo là một khối thử. Các trường hợp ngoại lệ được bắt gặp ở đây.

c) cuối cùng:

Tiếp theo là khối try (hoặc) khối catch. Khối này được thực thi bất kể ngoại lệ. Vì vậy, nói chung mã làm sạch được cung cấp ở đây.

Câu hỏi # 36) Giải thích về Truyền dẫn Ngoại lệ.

Trả lời: Ngoại lệ đầu tiên được ném ra từ phương thức ở trên cùng của ngăn xếp. Nếu nó không bắt được, thì nó sẽ bật lên phương thức và chuyển đến phương thức trước đó, v.v. cho đến khi chúng được nhận.

Đây được gọi là sự lan truyền ngoại lệ.

Thí dụ:

public class Manipulation{
public static void main(String[] args){
add();
}
public void add(){
addition();
}

Từ ví dụ trên, ngăn xếp trông giống như hình dưới đây:

           

Nếu một ngoại lệ xảy ra trong cộng () phương pháp không bị bắt, sau đó nó chuyển sang phương pháp add () . Sau đó, nó được chuyển đến phương thức main () và sau đó nó sẽ dừng quá trình thực thi. Nó được gọi là Tuyên truyền ngoại lệ.

Câu hỏi # 37) Từ khóa cuối cùng trong Java là gì?

Câu trả lời:

Biến cuối cùng:  Khi một biến được khai báo là cuối cùng, thì giá trị của biến đó không thể thay đổi. Nó giống như một hằng số.

Thí dụ:

int cuối cùng = 12;

Phương thức cuối cùng:  Không thể ghi đè từ khóa cuối cùng trong một phương thức. Nếu một phương thức được đánh dấu là cuối cùng, thì nó không thể bị lớp con ghi đè.

Lớp cuối cùng:  Nếu một lớp được khai báo là lớp cuối cùng, thì lớp đó không thể được phân lớp. Không có lớp nào có thể kéo dài lớp cuối cùng.

Q # 38) Chủ đề là gì?

Trả lời: Trong Java, luồng thực thi được gọi là Luồng. Mỗi chương trình java đều có ít nhất một luồng gọi là luồng chính, luồng chính do JVM tạo ra. Người dùng có thể xác định các luồng của riêng họ bằng cách mở rộng lớp Thread (hoặc) bằng cách triển khai giao diện Runnable. Các luồng được thực thi đồng thời.

Thí dụ:

public static void main(String[] args){//main thread starts here
}

Q # 39) Làm thế nào để bạn tạo một luồng trong Java?

Trả lời: Có hai cách có sẵn để tạo một luồng.

a) Mở rộng lớp Thread:  Mở rộng một lớp Thread và ghi đè phương thức run. Chủ đề có sẵn trong java.lang.thread.

Thí dụ:

Public class Addition extends Thread {
public void run () {
}
}

Nhược điểm của việc sử dụng một lớp luồng là chúng ta không thể mở rộng bất kỳ lớp nào khác vì chúng ta đã mở rộng lớp luồng. Chúng ta có thể nạp chồng phương thức run () trong lớp của mình.

b) Triển khai giao diện Runnable:  Một cách khác là thực hiện giao diện runnable. Đối với điều đó, chúng ta nên cung cấp triển khai cho phương thức run () được định nghĩa trong giao diện.

Thí dụ:

Public class Addition implements Runnable {
public void run () {
}
}

Câu hỏi # 40) Giải thích về phương thức join ().

Trả lời: Phương thức Join () được sử dụng để nối một luồng với phần cuối của luồng hiện đang chạy.

Thí dụ:

public static void main (String[] args){
Thread t = new Thread ();
t.start ();
t.join ();
}

Dựa trên đoạn mã trên, luồng chính đã bắt đầu thực thi. Khi nó đạt đến mã t.start () thì 'luồng t' bắt đầu ngăn xếp riêng để thực thi. JVM chuyển đổi giữa luồng chính và 'luồng t'.

Khi nó đạt đến mã t.join () thì 'luồng t' một mình được thực thi và hoàn thành nhiệm vụ của nó, sau đó chỉ có luồng chính bắt đầu thực thi.

Nó là một phương thức không tĩnh. Phương thức Join () có một phiên bản quá tải. Vì vậy, chúng ta có thể đề cập đến khoảng thời gian trong phương thức join () cũng là “.s”.

Q # 41) Phương thức lợi nhuận của lớp Thread làm gì?

Trả lời: Một phương thức result () di chuyển luồng hiện đang chạy sang trạng thái có thể chạy được và cho phép các luồng khác thực thi. Vì vậy, các chủ đề ưu tiên như nhau có cơ hội chạy. Nó là một phương thức tĩnh. Nó không phát hành bất kỳ khóa nào.

Phương thức Yield () chỉ di chuyển luồng trở lại trạng thái Runnable và không chuyển luồng tới khối sleep (), wait () (hoặc).

Thí dụ:

public static void main (String[] args){
Thread t = new Thread ();
t.start ();
}
public void run(){
Thread.yield();
}
}

Câu hỏi # 42) Giải thích về phương thức wait ().

Trả lời: phương thức wait () được sử dụng để tạo luồng chờ trong nhóm chờ. Khi phương thức wait () được thực thi trong quá trình thực thi một luồng thì ngay lập tức luồng đó từ bỏ khóa đối tượng và chuyển đến vùng chờ. Phương thức Wait () yêu cầu luồng đợi trong một khoảng thời gian nhất định.

Sau đó, luồng sẽ thức dậy sau khi phương thức thông báo () (hoặc) thông báo all () được gọi.

Wait () và các phương thức khác được đề cập ở trên không cung cấp khóa trên đối tượng ngay lập tức cho đến khi luồng hiện đang thực thi hoàn thành mã được đồng bộ hóa. Nó chủ yếu được sử dụng trong đồng bộ hóa.

Thí dụ:

public static void main (String[] args){
Thread t = new Thread ();
t.start ();
Synchronized (t) {
Wait();
}
}

Câu hỏi # 43) Sự khác biệt giữa phương thức thông báo () và phương thức thông báoAll () trong Java.

Trả lời: Sự khác biệt giữa phương thức thông báo () và phương thức thông báoAll () được nêu dưới đây:

thông báo () tifyAll ()
Phương thức này được sử dụng để gửi tín hiệu đánh thức một luồng duy nhất trong vùng chờ. Phương thức này gửi tín hiệu để đánh thức tất cả các luồng trong một cuộn chờ.

Q # 44) Làm thế nào để dừng một chuỗi trong java? Giải thích về phương thức sleep () trong một luồng?

Trả lời: Chúng ta có thể dừng một chuỗi bằng cách sử dụng các phương thức chuỗi sau:

  • Đang ngủ
  • Đang chờ đợi
  • Bị chặn

Sleep:  Phương thức Sleep () được sử dụng để ngủ chuỗi đang thực thi trong một khoảng thời gian nhất định. Khi luồng được đánh thức, nó có thể chuyển sang trạng thái chạy được. Vì vậy, phương thức sleep () được sử dụng để trì hoãn việc thực thi trong một khoảng thời gian nào đó.

Nó là một phương thức tĩnh.

Thí dụ:

Chủ đề. Ngủ (2000)

Vì vậy, nó trì hoãn luồng ở chế độ ngủ 2 mili giây. Phương thức Sleep () ném ra một ngoại lệ không bị gián đoạn, do đó chúng ta cần bao quanh khối bằng try / catch.

public class ExampleThread implements Runnable{
public static void main (String[] args){
Thread t = new Thread ();
t.start ();
}
public void run(){
try{
Thread.sleep(2000);
}catch(InterruptedException e){
}
}

Q # 45) Khi nào sử dụng giao diện Runnable Vs lớp Thread trong Java?

Trả lời: Nếu chúng ta cần lớp của mình để mở rộng một số lớp khác ngoài luồng thì chúng ta có thể sử dụng giao diện runnable vì trong java chúng ta chỉ có thể mở rộng một lớp.

Nếu chúng ta không mở rộng bất kỳ lớp nào thì chúng ta có thể mở rộng lớp luồng.

Q # 46) Sự khác biệt giữa phương thức start () và run () của lớp luồng.

Trả lời: Phương thức start () tạo một luồng mới và mã bên trong phương thức run () được thực thi trong luồng mới. Nếu chúng ta gọi trực tiếp phương thức run () thì một luồng mới không được tạo và luồng hiện đang thực thi sẽ tiếp tục thực thi phương thức run ().

Q # 47) Đa luồng là gì?

Trả lời: Nhiều luồng được thực thi đồng thời. Mỗi luồng bắt đầu ngăn xếp của chính nó dựa trên mức độ ưu tiên của luồng (hoặc) của các luồng.

Chương trình ví dụ:

public class MultipleThreads implements Runnable
{
public static void main (String[] args){//Main thread starts here
Runnable r = new runnable ();
Thread t=new thread ();
t.start ();//User thread starts here
Addition add=new addition ();
}
public void run(){
go();
}//User thread ends here
}

Trên thực thi dòng đầu tiên, JVM gọi phương thức chính và ngăn xếp luồng chính trông như hình bên dưới.

Khi quá trình thực thi đạt đến,  dòng t.start () sau đó một luồng mới được tạo và ngăn xếp mới cho luồng cũng được tạo. Bây giờ JVM chuyển sang luồng mới và luồng chính trở lại trạng thái chạy được.

Hai ngăn xếp trông như hình dưới đây.

Bây giờ, luồng người dùng đã thực thi mã bên trong phương thức run ().

Khi phương thức run () đã hoàn thành, JVM sẽ chuyển trở lại luồng chính và luồng người dùng đã hoàn thành nhiệm vụ và ngăn xếp đã biến mất.

JVM chuyển đổi giữa từng luồng cho đến khi hoàn thành cả hai luồng. Đây được gọi là Đa luồng.

Câu hỏi # 48) Giải thích vòng đời của luồng trong Java.

Trả lời: Chủ đề có các trạng thái sau:

  • Mới
  • Runnable
  • Đang chạy
  • Không chạy được (Bị chặn)
  • Đã chấm dứt

  • Mới: Ở trạng thái Mới, một cá thể Thread đã được tạo nhưng phương thức start () vẫn chưa được gọi. Bây giờ chủ đề không được coi là sống.
  • Runnable : Luồng ở trạng thái chạy được sau khi gọi phương thức start (), nhưng trước khi phương thức run () được gọi. Nhưng một luồng cũng có thể trở lại trạng thái chạy được từ chờ / ngủ. Ở trạng thái này, luồng được coi là còn sống.
  • Đang chạy : Luồng ở trạng thái đang chạy sau khi nó gọi phương thức run (). Bây giờ luồng bắt đầu thực hiện.
  • Non-Runnable (Bị chặn): Luồng vẫn tồn tại nhưng nó không đủ điều kiện để chạy. Nó không ở trạng thái chạy được mà còn, nó sẽ trở lại trạng thái chạy được sau một thời gian. Ví dụ: chờ, ngủ, chặn.
  • Đã kết thúc : Khi phương thức chạy được hoàn thành thì nó sẽ bị kết thúc. Bây giờ chủ đề không còn sống.

Câu hỏi # 49) Đồng bộ hóa là gì?

Trả lời: Đồng bộ hóa chỉ làm cho một luồng truy cập một khối mã tại một thời điểm. Nếu nhiều chủ đề truy cập vào khối mã, thì sẽ có cơ hội cho kết quả không chính xác ở cuối. Để tránh vấn đề này, chúng tôi có thể cung cấp đồng bộ hóa cho khối mã nhạy cảm.

Từ khóa được đồng bộ hóa có nghĩa là một luồng cần một khóa để truy cập vào mã được đồng bộ hóa.

Ổ khóa cho mỗi đối tượng. Mọi đối tượng Java đều có một khóa. Một ổ khóa chỉ có một chìa khóa. Một luồng chỉ có thể truy cập một phương thức được đồng bộ hóa nếu luồng đó có thể lấy khóa cho các đối tượng để khóa.

Đối với điều này, chúng tôi sử dụng từ khóa "Đồng bộ hóa".

Thí dụ:

public class ExampleThread implements Runnable{
 public static void main (String[] args){
 Thread t = new Thread ();
 t.start ();
 }
 public void run(){
 synchronized(object){
 {
 }
}

Q # 50) Nhược điểm của Đồng bộ hóa là gì?

Trả lời: Không nên đồng bộ hóa để triển khai tất cả các phương pháp. Bởi vì nếu một luồng truy cập vào mã được đồng bộ hóa thì luồng tiếp theo phải đợi. Vì vậy, nó làm cho một hiệu suất chậm ở đầu bên kia.

Q # 51) Serialization có nghĩa là gì?

Trả lời: Chuyển đổi một tệp thành một luồng byte được gọi là Serialization. Các đối tượng trong tệp được chuyển đổi thành byte cho mục đích bảo mật. Đối với điều này, chúng ta cần triển khai một giao diện java.io.Serializable. Nó không có phương pháp để xác định.

Các biến được đánh dấu là tạm thời sẽ không phải là một phần của tuần tự hóa. Vì vậy, chúng ta có thể bỏ qua tuần tự hóa cho các biến trong tệp bằng cách sử dụng từ khóa tạm thời.

Tìm hiểu thêm = >> Có thể nối tiếp và có thể sao chép

Câu hỏi # 52) Mục đích của biến tạm thời là gì?

Trả lời: Các biến tạm thời không phải là một phần của quá trình tuần tự hóa. Trong quá trình giải mã hóa, giá trị của các biến tạm thời được đặt thành giá trị mặc định. Nó không được sử dụng với các biến tĩnh.

Thí dụ:

số int tạm thời;

Q # 53) Phương pháp nào được sử dụng trong quá trình Serialization và Deserialization?

Trả lời: Các lớp ObjectOutputStream và ObjectInputStream là java.io cấp cao hơn. gói hàng. Chúng tôi sẽ sử dụng chúng với các lớp cấp thấp hơn FileOutputStream và FileInputStream.

ObjectOutputStream.writeObject —-> Tuần tự hóa đối tượng và ghi đối tượng được tuần tự hóa vào một tệp.

ObjectInputStream.readObject ->  Đọc tệp và giải mã hóa đối tượng.

Để được tuần tự hóa, một đối tượng phải triển khai giao diện có thể tuần tự hóa. Nếu lớp cha thực hiện Serializable, thì lớp con sẽ tự động có thể serializable.

Câu hỏi # 54) Mục đích của Biến số là gì?

Trả lời: Các giá trị biến động luôn được đọc từ bộ nhớ chính chứ không phải từ bộ nhớ đệm của luồng. Điều này được sử dụng chủ yếu trong quá trình đồng bộ hóa. Nó chỉ áp dụng cho các biến.

Thí dụ:

số int biến động;

Câu hỏi # 55) Sự khác biệt giữa Serialization và Deserialization trong Java.

Trả lời: Đây là những khác biệt giữa tuần tự hóa và giải mã hóa trong java:

Serialization Hủy đăng ký
Serialization là quá trình được sử dụng để chuyển đổi các đối tượng thành luồng byte Deserialization là quá trình ngược lại của tuần tự hóa, nơi chúng ta có thể lấy lại các đối tượng từ luồng byte.
Một đối tượng được tuần tự hóa bằng cách viết nó một ObjectOutputStream. Một đối tượng được deserialized bằng cách đọc nó từ ObjectInputStream.

Câu hỏi # 56) SerialVersionUID là gì?

Trả lời: Bất cứ khi nào một đối tượng được Serialized, đối tượng được đóng dấu với số ID phiên bản cho lớp đối tượng. ID này được gọi là SerialVersionUID. Điều này được sử dụng trong quá trình giải mã hóa để xác minh rằng người gửi và người nhận tương thích với Serialization.

Phần kết luận

Đây là một số câu hỏi phỏng vấn JAVA cốt lõi bao gồm cả khái niệm Java cơ bản và nâng cao để lập trình cũng như phỏng vấn nhà phát triển, và đây là những câu hỏi đã được các chuyên gia JAVA của chúng tôi trả lời.

Tôi hy vọng rằng hướng dẫn này sẽ cung cấp cho bạn một cái nhìn sâu sắc về các khái niệm mã hóa lõi JAVA một cách chi tiết. Những giải thích được đưa ra ở trên sẽ thực sự làm giàu kiến ​​thức của bạn và tăng hiểu biết của bạn về lập trình JAVA.

Hãy sẵn sàng để tự tin phỏng vấn JAVA.

bigdata 2020/11/11 22:06

Để lại dấu chân

Bước trên một chân

Bình luận

copyright © bigdata 2010-2020
Processed in 0 seconds, 0 queries