[Java Core] B3: Cách Java quản lý dữ liệu

[Java Core] B3: Cách Java quản lý dữ liệu
This entry is part 3 of 7 in the series Java Core

Mục lục:

  • Cách Java lưu trữ dữ liệu (Kiểu dữ liệu nguyên thuỷ, Object, Wrapper class, Auto-boxing, Auto-unboxing)
  • Constructor, Super, This
  • Pass by value
  • Garbage Collector

I. Cách Java lưu trữ dữ liệu (Kiểu dữ liệu nguyên thuỷ, Object, Wrapper class, Auto-boxing, Auto-unboxing)

1. Kiểu dữ liệu nguyên thuỷ (Primitive data type)

  • Trong Java, có 8 kiểu dữ liệu nguyên thuỷ (Primitive data type): byteshortintlongfloatdoublebooleanchar.
  • Kiểu dữ liệu nguyên thuỷ là các kiểu dữ liệu mà không phải là đối tượng, không có các phương thức, thuộc tính, … như các đối tượng.
  • Tức là, bạn không thấy các phương thức toString()equals()hashCode(), … trong các kiểu dữ liệu nguyên thuỷ.
inta=1;

// a không có hàm hay biến như các object// a.toString() không tồn tại// a.equals() không tồn tại// a.(gì đó) không tồn tại
Primitive data type
  • Ví dụ, khi khai báo 1 biến int a = 1;, thì Java sẽ cấp phát 1 vùng nhớ có kích thước 4 byte để lưu giá trị 1 vào biến a. Thực chất trong bộ nhớ nó được lưu theo binary là 00000000 00000000 00000000 00000001. (1 byte = 8 bit)
  • Do có các 32 bit, nên int có thể lưu giá trị từ -2^31 đến 2^31 – 1. (1 bit để lưu dấu)
  • Tương tự, các kiểu dữ liệu khác cũng được lưu theo binary, và có kích thước khác nhau.

2. Object

2.1 Object là gì?

image 6 - quochung.cyou PTIT
[Java Core] B3: Cách Java quản lý dữ liệu 18
  • Trong Java, mọi thứ đều là đối tượng (Object). Vậy nên các kiểu dữ liệu nguyên thuỷ cũng là đối tượng.
  • Hiện tại các em chưa học về kế thừa, nhưng cứ tạm hiểu, khi ta nói về 1 tập đối tượng, ví dụ: Xe Ô Tô, hay class Car, có các thuộc tính, phương thức gì đó. Xe máy, hay class Motorbike, cũng có các thuộc tính, phương thức gì đó. Vậy thì Xe Ô Tô và Xe Máy đều là đối tượng, và chúng có các thuộc tính, phương thức giống nhau.
  • Vậy ta gọi tập đối tượng có cả xe máy và xe ô tô, không chứa các phương thức đặc thù như chạydừng, … là gì? Đó là tập đối tượng Xe, hay class Vehicle. Vậy nên, Xe Ô Tô và Xe Máy đều là Xe, hay Vehicle. Tập hợp Vehicle có thể nằm trong tập hợp to hơn là Phương Tiện Giao Thông, hay class Transportation.
  • Trong Java cũng như vậy, mọi class các em tạo ra mặc định đều thuộc 1 tập hợp chung là Object. Và class này luôn cung cấp cho mọi object tạo ra từ các class khác các phương thức, thuộc tính như toString()equals()hashCode(), … như đã nói ở trên.

2.2 Object được lưu thế nào trong Java

image 7 - quochung.cyou PTIT
[Java Core] B3: Cách Java quản lý dữ liệu 19
  • Hiểu đơn giản, giá trị cách lưu object thực sự rất phức tạp, điều đó đều do Java quản lý, và ta không cần quan tâm. Ta chỉ cần biết, khi tạo ra 1 object, ta chỉ lưu 1 địa chỉ tới object đó. Và từ địa chỉ này, ta có thể ra lệnh từ xa để lấy các thuộc tính, phương thức của object đó.
  • Vậy nên, khi ta gán 1 object cho 1 biến, thực chất ta đang gán 1 địa chỉ tới object đó cho biến đó.
Studentobj=newStudent();

// obj là 1 địa chỉ tới object Student
  • Vậy nên ta không thể so sánh 2 object với nhau bằng toán tử ==, mà phải dùng phương thức equals().
Studentobj1=newStudent();

Studentobj2=newStudent();

// obj1 != obj2// obj1.equals(obj2) == false

2.3 Wrapper class

  • Wrapper class là các class được tạo ra để bao bọc các kiểu dữ liệu nguyên thuỷ. Ví dụ: IntegerFloatDoubleBooleanCharacter, …
  • Wrapper class cung cấp các phương thức để thao tác với các kiểu dữ liệu nguyên thuỷ. Ví dụ: Integer.parseInt()Integer.toString()Integer.valueOf(), …
Primitive data typeWrapper class
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean
charCharacter
  • Các kiểu dữ liệu lưu dạng object này tuân theo cách Java lưu trữ object, tức là không lưu trực tiếp object, mà chỉ lưu địa chỉ tới object đó.
Ưu điểmNhược điểm
Có thể sử dụng các phương thức của objectTốn bộ nhớ hơn
  • Ví dụ, ở Java ta có thể chuyển String thành số, từ các số hay từ 1 object bất kì sang String rất nhanh bằng toString(), ngoài ra khi nó là Object, ta có thể sử dụng các kĩ thuật OOP như kế thừa, đa hình, … (sẽ nói ở các buổi sau).
inta=1;

// a không có hàm hay biến như các object// a.toString() không tồn tạiIntegerb=1;

// b có hàm toString()// b.toString() tồn tại

2.4 Auto-boxing và Auto-unboxing

  • Auto-boxing là quá trình chuyển đổi từ kiểu dữ liệu nguyên thuỷ sang kiểu dữ liệu lưu dạng object.
  • Auto-unboxing là quá trình chuyển đổi từ kiểu dữ liệu lưu dạng object sang kiểu dữ liệu nguyên thuỷ.
  • Ví dụ:
inta=1;

Integerb=1;

// Auto-boxingIntegerc= a;

// Auto-unboxingintd= b;

  • Auto-boxing và Auto-unboxing là 2 quá trình tự động, do Java tự động thực hiện. Vậy nên các em không cần phải quan tâm đến nó.
  • Tuy nhiên, khi sử dụng Auto-boxing và Auto-unboxing, các em cần phải cẩn thận, vì nó có thể gây ra lỗi.
Integera=null;

intb= a; // NullPointerException
  • Vậy nên, khi sử dụng Auto-boxing và Auto-unboxing, các em cần phải kiểm tra giá trị null trước khi sử dụng.
Integera=null;

intb= a == null ? 0 : a;

  • Auto-boxing và Auto-unboxing có thể gây ra lỗi khi sử dụng toán tử ==.
Integera=1;

Integerb=1;

Integerc=128;

Integerd=128;

System.out.println(a == b); // true

System.out.println(c == d); // false
  • Autoboxing và Auto-unboxing giúp cho việc sử dụng các kiểu dữ liệu nguyên thuỷ và object trở nên dễ dàng hơn. Ví dụ, khi ta muốn sử dụng HashMap, thì ta không thể sử dụng kiểu dữ liệu nguyên thuỷ là int, mà phải sử dụng Integer.

HashMap<Integer, String> map = newHashMap<>();

map.put(1, "Hello");

map.put(2, "World");

System.out.println(map.get(1)); // Hello

System.out.println(map.get(2)); // World
  • Nếu không có Auto-boxing và Auto-unboxing, thì ta phải làm như sau:

HashMap<Integer, String> map = newHashMap<>();

map.put(Integer.valueOf(1), "Hello");

map.put(Integer.valueOf(2), "World");

System.out.println(map.get(Integer.valueOf(1))); // Hello

System.out.println(map.get(Integer.valueOf(2))); // World
  • Tuy nhiên, trong nhiều trường hợp nên hạn chế dùng các kiểu Object do chúng tốn bộ nhớ
for (Integeri=0; i < 1000000; i++) {

  // ...

}

// Tốn bộ nhớ hơn// Vì i là object, nên phải tạo ra 1 object mới mỗi lần tăng i// Còn nếu dùng int, thì chỉ cần tạo ra 1 biến int i, và tăng i mỗi lần

3. Các phương thức khởi tạo (Constructor) trong Java

  • Constructor là một phương thức đặc biệt, nó được gọi khi ta khởi tạo một đối tượng. Constructor có tên giống với tên class, và không có kiểu trả về.
  • Constructor được sử dụng để khởi tạo các giá trị ban đầu cho đối tượng. Ví dụ như ta có một class Student, trong đó có các thuộc tính nameageaddressmathliteratureenglish. Ta có thể tạo một constructor như sau:
classStudent {
  String name;
  int age;
  String address;
  float math;
  float literature;
  float english;

  Student(String name, int age, String address, float math, float literature, float english) {
    this.name = name;
    this.age = age;
    this.address = address;
    this.math = math;
    this.literature = literature;
    this.english = english;
  }
}

  • Constructor có thể có hoặc không có tham số. Nếu không có tham số, thì constructor đó được gọi là constructor mặc định. Nếu có tham số, thì constructor đó được gọi là constructor có tham số.
  • Constructor có thể có nhiều tham số, và các tham số đó có thể là bất kỳ kiểu dữ liệu nào.
  • Constructor có thể có nhiều hơn một, và các constructor đó có thể có số lượng tham số khác nhau.
  • Constructor có thể gọi constructor khác của cùng một class bằng từ khóa this(). Ví dụ:
classStudent {
  String name;
  int age;
  String address;
  float math;
  float literature;
  float english;

  Student(String name, int age, String address, float math, float literature, float english) {
    this.name = name;
    this.age = age;
    this.address = address;
    this.math = math;
    this.literature = literature;
    this.english = english;
  }

  Student(String name, int age, String address) {
    this(name, age, address, 0, 0, 0);
  }
}

4. Các khái niệm cơ bản về Garbage Collector (GC)

image 8 - quochung.cyou PTIT
[Java Core] B3: Cách Java quản lý dữ liệu 20
image 9 - quochung.cyou PTIT
[Java Core] B3: Cách Java quản lý dữ liệu 21
  • Trong quá trình thực thi chương trình, Java sẽ liên tục tìm các Object không được tham chiếu tới Heap Memory (mang giá trị null hoặc một vài trường hợp khác). Sau đó Garbage Collector sẽ tự động giải phóng bộ nhớ cho các ô nhớ chứa tham chiếu đó.
  • Điều này kiến lập trình viên không cần phải giải phóng bộ nhớ thủ công như C/C++. Thay vào đó, để giải phóng bộ nhớ, lập trình viên chỉ cần loại bỏ tham chiếu của Object.

5. Cách Java truyền tham số | Pass-by-value

Cách Java truyền tham số

5.1. Pass-by-value

  • Trong Java, khi ta truyền tham số vào một hàm, thì tham số đó sẽ được copy ra một vùng nhớ khác, và hàm sẽ thao tác với tham số ở vùng nhớ mới này.
  • Vậy nên, khi ta thay đổi giá trị của tham số trong hàm, thì giá trị của tham số bên ngoài hàm không bị thay đổi.
publicclassMain {
  publicstaticvoidmain(String[] args) {
    inta=1;
    System.out.println(a); // 1
    change(a);
    System.out.println(a); // 1
  }

  publicstaticvoidchange(int a) {
    a = 2;
  }
}

  • Tuy nhiên, nó sẽ lại thay đổi được các thuộc tính của object.
publicclassMain {
  publicstaticvoidmain(String[] args) {
    Studentstudent=newStudent();
    student.name = "A";
    System.out.println(student.name); // A
    change(student);
    System.out.println(student.name); // B
  }

  publicstaticvoidchange(Student student) {
    student.name = "B";
  }
}

classStudent {
  String name;
}

5.2. Tại sao pass-by-value mà String lại thay đổi được?

image 13 - quochung.cyou PTIT
[Java Core] B3: Cách Java quản lý dữ liệu 22
  • Ta hãy quay trở lại khái niệm vừa nhắc tới Khi ta truyền một biến nguyên thuỷ, hay trong trường hợp trên là age, ta đang như tạo một bản sao của một tờ giấy bình thường, tờ giấy đó ghi số là 20, ta đưa cho người khác. Họ sửa chúng thành 90, 100 hay gì đi chăng nữa, thì tờ giấy ban đầu của ta vẫn là 20
  • Tuy nhiên, khi ta truyền một biến reference (tham chiếu) của Object person, ta đang truyền bản sao của “tham chiếu” của nó. Hay đơn giản là, ta đang tạo ra bản sao của một cái điều khiển, vậy thì cái điều khiển bản sao này khi đưa cho người khác, vẫn sẽ bật tắt được tivi ban đầu của mình.
Series Navigation<< [Java Core] B2: Class và Object (Lớp và đối tượng)[Java Core] B4: Tính chất đóng gói, kế thừa và đa hình trong Java >>

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply