hằng số

"Anh bạn, bạn có biết rằng trong Java không phải tất cả các biến đều có thể thay đổi được không?"

"Sao thế, Kim? Thật vậy, chính từ 'biến' đã nói lên sự thay đổi."

"Không nghi ngờ gì về điều đó. Giống như nhiều ngôn ngữ lập trình khác, Java có các hằng số , nghĩa là các biến có giá trị không thể thay đổi được . Và chính từ 'hằng số' đã nói lên sự không đổi."

"Và chúng dùng để làm gì?"

"Thông thường, chúng được sử dụng cho một số thứ cơ bản chẳng hạn như số Pihoặc số ngày trong các tháng trong năm. Điều đó nói rằng, về nguyên tắc, một lập trình viên có thể biến bất kỳ biến nào thành hằng số, nếu người đó quyết định làm như vậy." như vậy là cần thiết."

"Ý anh là tên, màu xe, hay tên một ngày trong tuần?"

"Bạn đã có một ý tưởng đúng. Bất cứ điều gì không nên thay đổi."

"Và những hằng số này trông như thế nào trong Java?"

"Java có một từ khóa đặc biệt dành cho chúng: final. Việc tạo một biến bất biến giống như tạo một biến thông thường. Điểm khác biệt duy nhất là trước loại biến bạn cần viết từ final, như sau:

final Type name = value;

"Điều gì xảy ra nếu bạn tạo một hằng số và sau đó thử gán một giá trị khác cho nó?"

"Đó là câu hỏi đúng! Và câu trả lời đúng là: nếu bạn cố gắng gán một giá trị khác cho một finalbiến, thì chương trình của bạn sẽ không biên dịch được."

"Điều gì sẽ xảy ra nếu bạn khai báo một finalbiến nhưng không gán giá trị cho nó?"

"Không ích gì khi làm điều này, vì vậy nó cũng không được phép trong Java. Một finalbiến phải được khởi tạo khi nó được khai báo, nghĩa là bạn phải gán một giá trị cho nó. Có một ngoại lệ đối với quy tắc này: bạn có thể di chuyển việc khởi tạo của một biến lớp tĩnh thành một hàm tạo, nhưng bạn sẽ tìm hiểu về điều đó sau.

"Điều đó nói rằng, không phải mọi thứ là finalmột hằng số. Để giảm số lượng từ khóa, các nhà phát triển Java sử dụng từ này finalkhông chỉ để khai báo các hằng số. Nó finalcòn có thể áp dụng cho các phương thức và thậm chí cả các lớp. Các phương thức được khai báo là finalkhông thể bị ghi đè và một lớp được tuyên bố là finalkhông thể kế thừa."

"Uh... Bị ghi đè? Kế thừa? Bây giờ bạn đang nói ngôn ngữ gì?"

"Ngôn ngữ của lập trình hướng đối tượng. Bạn sẽ sớm hiểu được nó. Cho đến lúc đó, hãy tận hưởng những thuật ngữ đẹp đẽ."

"Được rồi. Vì vậy, finalcó thể được đặt trước các biến, lớp và phương thức, và từ khóa này làm cho chúng trở nên bất biến theo một nghĩa nào đó?"

"Có. Hơn nữa, finalcông cụ sửa đổi có thể được thêm vào trước bất kỳ biến nào: biến cục bộ, tham số phương thức, trường lớp và biến lớp tĩnh.

"Đây là điều quan trọng cần nhớ: finaltrước một tên biến chỉ là sự bảo vệ chống lại bất kỳ thay đổi nào đối với biến đó . Nếu một biến lưu trữ một tham chiếu đến một đối tượng, thì đối tượng đó vẫn có thể được thay đổi."

"Tôi không hiểu lắm."

"Bạn sẽ hiểu thực sự sớm thôi. Đây là một ví dụ:

final int[] data = {1, 2, 3, 4, 5, 6};

data = {6, 7, 8, 9};

data[0] = 0;
data[1] = 0;
data[2] = 0;
Chúng tôi tạo một mảng.

Điều này không được phép: biến datađược khai báo là final.

Nhưng bạn có thể làm điều này.
Và cả điều này nữa.

"Hiểu rồi. Khó đấy."

hằng số toàn cầu

"Bạn nghĩ hằng số toàn cầu là gì?"

"Tôi đoán các hằng số toàn cầu có lẽ giống như các biến toàn cầu, chỉ có hằng số?"

"Chính xác. Nếu bạn cần khai báo các hằng số toàn cầu trong chương trình của mình, hãy tạo các biến lớp tĩnh và đặt chúng publicfinal. Có một kiểu đặc biệt cho tên của các biến như vậy: chúng được viết bằng tất cả các chữ in hoa, với ký tự gạch dưới được sử dụng để các từ riêng biệt.

Ví dụ:

class Solution
{
   public static final String SOURCE_ROOT = "c:\\projects\\my\\";
   public static final int DISPLAY_WIDTH = 1024;
   public static final int DISPLAY_HEIGHT = 768;
}

bóng biến

"Như tôi đã nói trước đây, bạn không thể tạo nhiều biến cục bộ có cùng tên trong một phương thức. Trong các phương thức khác nhau, bạn có thể."

"Tôi biết điều đó!"

"Nhưng điều mà bạn có thể không biết là các biến trong một lớp và các biến cục bộ trong một phương thức có thể có cùng tên.

Ví dụ:

Mã số khả năng hiển thị thay đổi
public class Solution
{
   public int count = 0;
   public int sum = 0;

   public void add(int data)
   {
     sum = sum + data;
     int sum = data * 2;
     count++;
   }
}

count, sum
count, sum
count, sum
count, sum
count, sum
count, sum, data
count, sum, data
count, sum, data
count, sum, data
count, sum

"Trong addphương thức, chúng tôi đã khai báo một biến cục bộ có tên sum. Cho đến khi kết thúc phương thức, nó sẽ che khuất (hoặc che khuất ) sumbiến thể hiện."

"Hmm... Tôi có thể nói theo một nghĩa nào đó thì đây là hành vi được mong đợi."

"Nhưng đó chưa phải là kết thúc của câu chuyện. Hóa ra là nếu một biến thể hiện bị che khuất bởi một biến cục bộ, thì vẫn có cách để tham chiếu đến biến thể hiện trong phương thức. Chúng tôi làm điều này bằng cách viết từ khóa trước tên của thisnó :

this.name

"Đây là một ví dụ trong đó xung đột tên được giải quyết thành công:

Mã số khả năng hiển thị thay đổi
public class Solution
{
   public int count = 0;
   public int sum = 0;

   public void add(int data)
   {
     int sum = data * 2;
     this.sum = this.sum + data;
     count++;
   }
}

this.count, this.sum
this.count, this.sum
this.count, this.sum
this.count, this.sum
this.count, this.sum
this.count, this.sum, data
this.count, this.sum, data, sum
this.count, this.sum, data, sum
this.count, this.sum, data, sum
this.count, this.sum

Các biến countsumcó sẵn ở mọi nơi có hoặc không có thistừ khóa. Trên các dòng mà sumbiến cục bộ che khuất sumbiến thể hiện, sumbiến thể hiện chỉ có thể được truy cập bằng thistừ khóa.

"Rõ ràng, tôi sẽ cần phải thực hành điều này."

"Bạn sẽ quản lý."

"Điều gì sẽ xảy ra nếu một biến lớp tĩnh bị che khuất thay vì chỉ là một biến thể hiện (không tĩnh)? Bạn không thể truy cập nó thông qua this?"

"Đúng vậy. Từ khóa này sẽ không hoạt động. Bạn cần tham khảo nó thông qua tên lớp:

ClassName.name

Ví dụ:

Mã số khả năng hiển thị thay đổi
public class Solution
{
   public static int count = 0;
   public static int sum = 0;

   public void add(int data)
   {
     int sum = data * 2;
     Solution.sum = Solution.sum + data;
     count++;
   }
}

Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum, data
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum

"Hãy chú ý: bạn có thể truy cập các biến tĩnh countsumbiến ở mọi nơi có hoặc không sử dụng tên lớp Solutionlàm tiền tố. Ở những dòng mà sumbiến cục bộ che khuất biến đối tượng sum, chỉ có thể truy cập vào sumbiến lớp khi sử dụng Solutionlàm tiền tố.

Các biến bên trong một forvòng lặp

"Và một sự thật nhỏ nhưng thú vị nữa. Cũng có một nơi mà một biến được khai báo theo một cách đặc biệt — tôi đang nói về bên trong một forvòng lặp ." Thông thường, một forvòng lặp có một counterbiến trong ngoặc đơn. Và khả năng hiển thị của biến này sẽ như thế nào? Rốt cuộc, nó không nằm trong phần thân của vòng lặp. Có phải là toàn bộ phương pháp? Hay không?"

"Tôi đã nghe điều gì đó về điều này. Theo tôi hiểu, một biến được khai báo trong tiêu đề của vòng lặp forchỉ hiển thị trong phần thân của vòng lặp và trong tiêu đề của forvòng lặp ."

"Làm tốt lắm, Amigo. Tuy nhiên, hãy xem một ví dụ để củng cố tài liệu này:

Mã số khả năng hiển thị thay đổi
public static void main(String[] args)
{
   int a = 0;

   for (int i = 0; i < 10; i++)
   {
     System.out.println(i);
   }

   System.out.println("end");
}


a
a
a, i
a, i
a, i
a
a
a

"Vì vậy, bạn đang nói rằng trong mã của tôi, tôi có thể viết một số vòng lặp lần lượt với một biến đếm có cùng tên và sẽ không có vấn đề gì?"

"Sẽ không có vấn đề gì. Đây, nhìn này:

Mã số khả năng hiển thị thay đổi
public static void main(String[] args)
{
   int a = 0;

   for (int i = 0; i < 10; i++)
   {
     System.out.println(i);
   }

   for (int i = 0; i < 10; i--)
   {
     System.out.println(i);
   }

   System.out.println("end");
}


a
a
a, i
a, i
a, i
a
a
a, i
a, i
a, i
a
a
a