Tĩnh là gì. Công cụ sửa đổi trong Java: tĩnh, cuối cùng, trừu tượng, đồng bộ hóa, nhất thời, dễ bay hơi

Tĩnh là gì

Trong một số trường hợp, cần định nghĩa một thành viên của lớp sẽ được sử dụng độc lập với bất kỳ đối tượng nào của lớp đó. Thông thường, một thành viên của lớp chỉ nên được truy cập cùng với một đối tượng của lớp đó. Tuy nhiên, bạn có thể tạo một thành viên lớp có thể được sử dụng riêng mà không cần tham chiếu đến một phiên bản cụ thể. Để tạo một thành viên như vậy, bạn cần đặt ở đầu phần khai báo của nó từ khóa tĩnh. Khi một thành viên lớp được khai báo tĩnh, nó có thể truy cập được trước khi bất kỳ đối tượng nào của lớp đó được tạo và không cần tham chiếu đến bất kỳ đối tượng nào. Cả phương thức và biến đều có thể được khai báo tĩnh. Ví dụ phổ biến nhất của thành viên tĩnh là phương thức main(). Phương thức này được khai báo tĩnh vì nó phải được khai báo trước khi bất kỳ đối tượng nào được tạo.

Các biến thể hiện được khai báo là tĩnh về cơ bản là các biến toàn cục. Khi khai báo các đối tượng của lớp, chương trình không tạo bất kỳ bản sao nào của biến tĩnh. Thay vào đó, tất cả các phiên bản của một lớp đều có chung một biến tĩnh.

Các phương thức được khai báo là tĩnh phải tuân theo một số hạn chế.

  • Họ chỉ có thể gọi các phương thức tĩnh khác.
  • Họ chỉ nên truy cập các biến tĩnh.
  • Họ không thể đề cập đến các thành viên thuộc loại này hoặc siêu. (Từ khóa super liên quan đến tính kế thừa và sẽ được trình bày ở chương tiếp theo.)

Nếu bạn cần thực hiện các phép tính để khởi tạo các biến tĩnh, bạn có thể khai báo một khối tĩnh sẽ chỉ được thực thi một lần khi lớp được tải lần đầu tiên. Ví dụ sau đây cho thấy một lớp có chứa phương pháp tĩnh, một số biến tĩnh và khối khởi tạo tĩnh:

// Trình diễn các biến, phương thức và khối tĩnh.
lớp UseStatic(
int tĩnh a = 3;
int tĩnh b;
tĩnh void meth(int x) (
System.out.println("x = " + x);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
tĩnh (
System.out.println("Khối tĩnh được khởi tạo.");
b = a * 4;
}

meth(42);
}
}

Ngay sau khi tải lớp UseStatic, chương trình sẽ thực thi tất cả các câu lệnh tĩnh. Đầu tiên, giá trị của a được đặt thành 3, sau đó chương trình thực thi một khối tĩnh in thông báo, sau đó khởi tạo biến b với giá trị a*4 hoặc 12. Sau đó, chương trình gọi phương thức main(), gọi phương thức meth(), truyền giá trị x 42. Ba câu lệnh println() tham chiếu hai biến tĩnh a và b tới một biến cục bộ x.

Đầu ra của chương trình này trông như thế này:

Khối tĩnh được khởi tạo, x = 42 a = 3 b = 12

Bên ngoài lớp mà chúng được định nghĩa, các phương thức và biến tĩnh có thể được sử dụng độc lập với bất kỳ đối tượng nào. Để thực hiện việc này, chỉ cần chỉ định tên lớp của chúng, sau đó là thao tác dấu chấm. Ví dụ: nếu một phương thức kiểu tĩnh cần được gọi từ bên ngoài lớp của nó, thì điều này có thể được thực hiện bằng cách sử dụng mẫu chung sau:

class_name.method()

Ở đây class_name là tên của lớp trong đó phương thức kiểu tĩnh được khai báo. Như bạn có thể thấy, định dạng này tương tự như định dạng được sử dụng để gọi các phương thức không tĩnh thông qua các biến tham chiếu đối tượng. Một biến tĩnh được truy cập theo cách tương tự - thông qua toán tử dấu chấm theo sau tên lớp. Đây là cách Java triển khai các phiên bản được quản lý của các phương thức và biến toàn cục.

Hãy đưa ra một ví dụ. Trong phương thức main(), phương thức tĩnh callme() và biến tĩnh b được truy cập bằng tên lớp StaticDemo của chúng.

lớp TĩnhDemo (
int tĩnh a = 42;
int tĩnh b = 99;
tĩnh void callme() (
System.out.println("a = " + a);
}
}
lớp StaticByName(
public static void main(String args) (
StaticDemo.callme();
System.out.println("b = " + StaticDemo.b);
}
}

Đầu ra của chương trình này trông như thế này.

Chúng ta sẽ nói về các công cụ sửa đổi: công cụ sửa đổi, phạm vi, công cụ sửa đổi cho các lớp, trường, phương thức là gì. Tôi nghĩ nó sẽ không nhàm chán.

Công cụ sửa đổi trong Java là các từ khóa cung cấp cho một lớp, trường lớp hoặc phương thức các thuộc tính nhất định.

Để biểu thị mức độ hiển thị của một lớp các phương thức và trường của nó, có 4 công cụ sửa đổi truy cập:

  • riêng tư các thành viên của lớp chỉ có thể truy cập được trong lớp đó;
  • gói riêng tư hoặc mặc định (mặc định) các thành viên của lớp có thể nhìn thấy được bên trong gói;
  • được bảo vệ các thành viên của lớp có sẵn bên trong gói và trong các lớp con cháu;
  • công cộng các thành viên trong lớp đều có sẵn cho tất cả mọi người.

Nếu bạn còn nhớ, cuối cùng, khi chúng ta đã nhập lớp Cat, chúng ta vẫn gặp lỗi biên dịch.

Vấn đề là chúng tôi chưa chỉ định bất kỳ công cụ sửa đổi truy cập nào cho các trường và phương thức của mình và chúng có thuộc tính mặc định (các thành viên lớp được hiển thị bên trong gói). Để sửa lỗi biên dịch cho mã của chúng ta và cuối cùng chạy nó, chúng ta cần công khai hàm tạo và các phương thức của mình. Sau đó chúng có thể được gọi từ các gói khác.

Bạn có thể bắt đầu tự hỏi: tất cả những điều này để làm gì? Tại sao không hiển thị mã từ bất kỳ gói hoặc lớp nào nhưng bạn cần hạn chế quyền truy cập? Những câu hỏi này sẽ tự biến mất khi đến lúc phải viết những dự án phức tạp và rườm rà. Bây giờ, khi chúng ta viết các ứng dụng có chức năng bị giới hạn ở một hoặc hai lớp, dường như không có ích gì khi giới hạn bất cứ điều gì.

Hãy tưởng tượng rằng bạn có một lớp hiển thị một đối tượng của một sản phẩm nhất định. Ví dụ như một chiếc ô tô. Chiếc xe có thể có giá. Bạn đã tạo một trường giá và nhiều trường khác, một loạt các phương thức chịu trách nhiệm về chức năng. Mọi thứ có vẻ ổn. Chiếc xe đẳng cấp của bạn là một phần của một dự án lớn và mọi người đều vui vẻ. Nhưng giả sử ai đó vô tình hoặc cố ý tạo một phiên bản của loại ô tô và đặt giá âm. Một sản phẩm có thể có giá âm không? Đây là một ví dụ rất nguyên thủy và khó có thể xảy ra trong đời thực, nhưng tôi nghĩ ý tưởng đã rõ ràng. Đôi khi bạn cần cấp quyền truy cập không phải trực tiếp mà thông qua một số phương pháp nhất định. Có thể mã này chịu trách nhiệm về chức năng của mã khác và bạn không muốn ai đó thay đổi và chỉnh sửa một phần mã của mình. Đối với mục đích này, có một hạn chế truy cập.

Công cụ sửa đổi truy cập cho hàm tạo, phương thức và trường có thể là bất kỳ thứ gì. Một lớp chỉ có thể là công khai hoặc mặc định và chỉ có thể có một lớp công khai trong một tệp.

Bây giờ thế là đủ về công cụ sửa đổi quyền truy cập. Trong bài viết “Lập trình hướng đối tượng”, chúng ta sẽ nói về chúng chi tiết hơn, nhưng bây giờ chúng ta hãy nói về các công cụ sửa đổi khác, nhân tiện, có rất nhiều.

Bây giờ đến phần sửa đổi tĩnh. Nó có thể được sử dụng trước một phương thức, trường và thậm chí là một lớp khi chúng ta muốn khai báo một lớp lồng nhau. Trong Java, bạn có thể viết các lớp bên trong các lớp khác và nếu công cụ sửa đổi trước lớp bên trong lớp đó là tĩnh thì lớp đó được gọi là lồng nhau, nếu một công cụ sửa đổi khác là hoặc mặc định thì lớp đó được gọi là nội bộ. Sẽ có một bài viết riêng về các lớp lồng nhau và lớp bên trong, vì mọi thứ ở đó không đơn giản như vậy.

Công cụ sửa đổi tĩnh trước một phương thức hoặc trường cho biết rằng nó không thuộc về một phiên bản của lớp đó. Điều này có ý nghĩa gì với chúng ta? Khi chúng ta đã khai báo một trường lớp hoặc phương thức là tĩnh, nó có thể được gọi mà không cần sử dụng một thể hiện của lớp đó. Đó là, thay vì xây dựng này: Mèo Mèo= Mèo mới(); cat.method(), bạn chỉ cần viết Cat.method(). Với điều kiện là phương thức được khai báo là tĩnh. Các biến tĩnh giống nhau cho tất cả các đối tượng của lớp. Họ có một liên kết.

    Công cụ sửa đổi lớp công khai (

    int tĩnh anotherStaticField = 5;

    public static void myStaticMethod() (

    someField = "Lĩnh vực của tôi" ;

    //nonStaticField = ""; dịch lỗi

    // bạn không thể sử dụng các trường không tĩnh

    // trong các phương thức tĩnh

    public void myNonStaticMethod() (

    anotherStaticField = 4 ; // các trường tĩnh có thể được sử dụng

    // trong các phương thức không tĩnh

    //phương thức chính cũng có một bộ sửa đổi tĩnh

    Công cụ sửa đổi mới() .myNonStaticMethod() ;

    Công cụ sửa đổi.myStaticMethod(); //gọi các phương thức và trường tĩnh

    //thông qua Classname.method

Khác lưu ý quan trọng Một điều cần nói về công cụ sửa đổi tĩnh: các trường tĩnh được khởi tạo khi lớp được tải. Thông thường trong nhiều loại thử nghiệm Java khác nhau, bạn có thể tìm thấy đoạn mã sau:

Câu hỏi: cái gì sẽ được xuất ra bàn điều khiển? Bạn cần nhớ rằng khối tĩnh sẽ được xuất ra đầu tiên trong mọi trường hợp. Tiếp theo sẽ là khối mặc định. Tiếp theo, nhìn vào màn hình giao diện điều khiển:

Công cụ sửa đổi tiếp theo chúng ta sẽ xem xét sẽ là cuối cùng.

Tôi nghĩ từ cuối cùng đã nói lên điều đó. Bằng cách sử dụng công cụ sửa đổi cuối cùng, bạn nói rằng các trường không thể thay đổi, các phương thức không thể bị ghi đè và các lớp không thể được kế thừa (sẽ có một bài viết riêng về tính kế thừa). Công cụ sửa đổi này chỉ áp dụng cho các lớp, phương thức và biến (cả biến cục bộ).

VỚI sửa đổi cuối cùng Chúng ta sẽ nói về các phương thức và lớp trong bài viết OOP.

Tiếp theo sẽ là những sửa đổi sẽ không rõ ràng lắm đối với người mới bắt đầu hoặc những người đọc loạt bài viết này từ đầu. Và mặc dù tôi chưa thể giải thích mọi chuyện cho bạn (vì bạn chưa biết tài liệu liên quan), tôi vẫn khuyên bạn chỉ nên làm quen với chúng. Khi đến lúc sử dụng các từ bổ nghĩa này, bạn sẽ hiểu hầu hết các thuật ngữ được sử dụng bên dưới.

bổ nghĩa đồng bộ- chỉ ra rằng phương thức chỉ có thể được sử dụng bởi một luồng tại một thời điểm. Mặc dù điều này có thể không cho bạn biết điều gì, nhưng bạn sẽ thấy tính hữu ích của công cụ sửa đổi này khi chúng ta nghiên cứu về đa luồng.

bổ nghĩa tạm thời— chỉ ra rằng một trường nhất định sẽ bị bỏ qua trong quá trình tuần tự hóa đối tượng. Theo quy định, các trường như vậy lưu trữ các giá trị trung gian.

bổ nghĩa bay hơi- được sử dụng cho đa luồng. Khi một trường có công cụ sửa đổi dễ bay hơi sẽ được sử dụng và thay đổi bởi nhiều luồng, công cụ sửa đổi này đảm bảo rằng trường đó sẽ được thay đổi lần lượt và sẽ không có sự nhầm lẫn với nó.

bổ nghĩa tự nhiên trước khi khai báo một phương thức, chỉ ra rằng phương thức đó được viết bằng ngôn ngữ lập trình khác. Thông thường bằng ngôn ngữ C.

bổ nghĩa nghiêm ngặt- Cung cấp các phép tính trên số kiểu phao và double (dấu phẩy động) theo chuẩn IEEE 754 Hay đơn giản hơn là đảm bảo trong phương thức, kết quả tính toán sẽ giống nhau trên tất cả các nền tảng.

Tôi chưa nói về công cụ sửa đổi trừu tượng. Tôi sẽ kể cho bạn nghe về điều đó một cách ngắn gọn, vì không biết những điều cơ bản lập trình định hướng Tôi thấy chẳng ích gì khi nói về anh ấy.

Một lớp có công cụ sửa đổi trừu tượng không thể tạo một thể hiện. Mục đích duy nhất của nó là được mở rộng. Lớp trừu tượng có thể chứa cả phương thức trừu tượng và phương thức thông thường.

Chúng ta sẽ nói nhiều hơn về abstract modifier trong bài viết OOP.

Đây là nơi chúng ta có thể kết thúc bài viết về sửa đổi. Nhiều điều chưa được nói về họ. Nhưng điều này là do chúng ta chưa có khái niệm về OOP. Qua một số bài viết, chúng tôi sẽ mở rộng kiến ​​thức về từ bổ nghĩa và lấp đầy những khoảng trống.

Công cụ sửa đổi tĩnh trong Java liên quan trực tiếp đến lớp; nếu trường là tĩnh thì nó thuộc về lớp, nếu phương thức là tĩnh thì tương tự, nó thuộc về lớp. Dựa vào điều này, bạn có thể truy cập một phương thức hoặc trường tĩnh bằng tên lớp. Ví dụ: nếu trường đếm là tĩnh trong lớp Counter thì bạn có thể truy cập biến bằng truy vấn như: Counter.count. Tất nhiên, cần tính đến các công cụ sửa đổi quyền truy cập. Ví dụ: các trường riêng tư chỉ khả dụng trong lớp mà chúng được khai báo. Các trường được bảo vệ có sẵn cho tất cả các lớp trong gói ( bưu kiện), cũng như tất cả các lớp con bên ngoài gói. Để biết thêm thông tin chi tiếtđọc bài viết “riêng tư vs được bảo vệ vs công khai”. Giả sử có một phương thức tĩnh tăng() trong lớp Counter có nhiệm vụ tăng số lượng bộ đếm. Để gọi phương pháp này bạn có thể sử dụng cuộc gọi như Counter.increment() . Không cần phải khởi tạo lớp Counter để truy cập vào trường hoặc phương thức tĩnh. Đây là điểm khác biệt cơ bản giữa các đối tượng tĩnh và KHÔNG tĩnh (thành viên lớp). Lưu ý quan trọng. Hãy nhớ rằng các thành viên của lớp tĩnh trực tiếp thuộc về lớp chứ không thuộc về thể hiện của nó. Nghĩa là, giá trị của biến tĩnh count sẽ giống nhau đối với tất cả các đối tượng thuộc loại Counter. Trong bài viết này, chúng ta sẽ xem xét các khía cạnh cơ bản của việc sử dụng công cụ sửa đổi tĩnh trong Java, cũng như một số tính năng sẽ giúp bạn hiểu các khái niệm lập trình chính.

Những điều mọi lập trình viên nên biết về Công cụ sửa đổi tĩnh trong Java.

Trong phần này, chúng ta sẽ xem xét những điều cơ bản về cách sử dụng các phương thức, trường và lớp tĩnh. Hãy bắt đầu với các biến.

    Bạn không thể truy cập các thành viên không tĩnh của một lớp trong ngữ cảnh tĩnh, chẳng hạn như một phương thức hoặc khối. Biên dịch mã dưới đây sẽ dẫn đến lỗi:

    public class Counter ( int count; public static void main (String args) ( System. out. println (count) ; //lỗi thời gian biên dịch ) )

    Đây là một trong những sai lầm phổ biến nhất Lập trình viên Java, đặc biệt là cho người mới bắt đầu. Vì phương thức chính là tĩnh và biến count không có, nên trong trường hợp này, phương thức println bên trong phương thức chính sẽ đưa ra “Lỗi thời gian biên dịch”.

    Không giống như các biến cục bộ, các trường và phương thức tĩnh KHÔNG an toàn cho luồng trong Java. Trong thực tế, đây là một trong những nguyên nhân phổ biến nhất gây ra các vấn đề liên quan đến tính bảo mật của lập trình đa luồng. Xem xét rằng mỗi phiên bản của một lớp có cùng một bản sao của một biến tĩnh, biến đó cần được bảo vệ - "khóa" bởi lớp. Do đó, khi sử dụng các biến tĩnh, hãy đảm bảo chúng được đồng bộ hóa đúng cách để tránh các vấn đề như điều kiện chạy đua.

    Phương pháp tĩnh có lợi thế khi sử dụng vì... không cần phải tạo một đối tượng mới mỗi lần để truy cập các phương thức đó. Một phương thức tĩnh có thể được gọi bằng cách sử dụng loại lớp mà các phương thức được định nghĩa. Đó là lý do tại sao các phương pháp như vậy lại phù hợp một cách lý tưởng như phương pháp xuất xưởng và phương pháp tiện ích. Lớp java.lang.Math là một ví dụ tuyệt vời trong đó hầu hết tất cả các phương thức đều là tĩnh, đó cũng là lý do khiến các lớp tiện ích trong Java là cuối cùng.

    Cho người khác tâm điểm là bạn KHÔNG thể ghi đè các phương thức tĩnh. Nếu bạn khai báo cùng một phương thức trong một lớp con, tức là có cùng tên và chữ ký, bạn sẽ chỉ “ẩn” phương thức siêu lớp thay vì ghi đè nó. Hiện tượng này được gọi là phương pháp ẩn giấu. Điều này có nghĩa là khi gọi một phương thức tĩnh được khai báo ở cả lớp cha và lớp con, phương thức đó sẽ luôn được gọi vào thời gian biên dịch dựa trên loại biến. Không giống như ghi đè, các phương thức như vậy sẽ không được thực thi khi chương trình đang chạy. Hãy xem một ví dụ:

    lớp Xe ( public static void kmToMiles (int km) ( System. out. println ( "Bên trong lớp cha/phương thức tĩnh") ; ) ) lớp Xe mở rộng Xe ( public static void kmToMiles (int km) ( System. out. println ( "Bên trong lớp con/phương thức tĩnh") ; ) ) public class Demo ( public static void main ( String args ) ( Vehicle v = new Car () ; v. kmToMiles ( 10 ) ; ) )

    Đầu ra của bảng điều khiển:

    Bên trong lớp cha/phương thức tĩnh

    Mã này chứng minh rõ ràng: mặc dù thực tế là đối tượng thuộc loại Ô tô, nhưng phương thức tĩnh từ lớp Xe vẫn được gọi, bởi vì một phương thức đã được gọi trong quá trình biên dịch. Và lưu ý rằng không có lỗi trong quá trình biên dịch!

    Bạn cũng có thể khai báo một lớp tĩnh, ngoại trừ các lớp cấp cao nhất. Các lớp như vậy được gọi là các lớp tĩnh lồng nhau. Chúng rất hữu ích cho việc thể hiện các kết nối được cải thiện. Một ví dụ điển hình của lớp tĩnh lồng nhau là HashMap.Entry, lớp này cung cấp cấu trúc dữ liệu bên trong HashMap. Điều đáng lưu ý là giống như bất kỳ lớp bên trong nào khác, các lớp lồng nhau nằm trong một tệp .class riêng biệt. Vì vậy, nếu bạn khai báo năm lớp lồng nhau trong lớp chính của mình, bạn sẽ có 6 tệp có phần mở rộng .class. Một ví dụ khác về việc sử dụng là khai báo Bộ so sánh của riêng bạn, ví dụ như Bộ so sánh Age trong lớp Nhân viên.

    Công cụ sửa đổi tĩnh cũng có thể được khai báo trong một khối tĩnh, hay còn gọi là khối khởi tạo tĩnh, khối này sẽ được thực thi khi lớp được tải. Nếu bạn không khai báo một khối như vậy, Java sẽ thu thập tất cả các trường tĩnh vào một danh sách và thực thi nó khi lớp được tải. Tuy nhiên, một khối tĩnh không thể ném ra các ngoại lệ bị bắt, nhưng nó có thể ném ra những ngoại lệ chưa bị bắt. Trong trường hợp này, “Lỗi khởi tạo ngoại lệ” sẽ xảy ra. Trong thực tế, bất kỳ ngoại lệ nào được đưa ra trong quá trình thực thi và khởi tạo các trường tĩnh sẽ bị Java bao bọc trong lỗi này. Đây cũng là điều nhất Lý do phổ biến lỗi “No Class Def Found Error”, bởi vì lớp không có trong bộ nhớ khi nó được truy cập.

    Thật hữu ích khi biết rằng các phương thức tĩnh bị ràng buộc tại thời điểm biên dịch, trái ngược với việc ràng buộc các phương thức ảo hoặc không tĩnh, bị ràng buộc trong thời gian chạy trên đối tượng thực. Do đó, các phương thức tĩnh không thể bị ghi đè trong Java vì đa hình thời gian chạy không áp dụng cho chúng. Đây là một hạn chế quan trọng cần cân nhắc khi khai báo một phương thức tĩnh. Điều này chỉ có ý nghĩa khi không có khả năng hoặc không cần phải ghi đè phương thức đó bằng các lớp kế thừa. Phương pháp nhà máy và phương pháp tiện ích mẫu tốt bằng cách sử dụng công cụ sửa đổi tĩnh. Joshua Bloch đã nêu ra một số ưu điểm của việc sử dụng phương thức xuất xưởng tĩnh so với hàm tạo trong cuốn sách Java hiệu quả của mình, cuốn sách mà mọi lập trình viên ngôn ngữ này đều phải đọc.

    Một thuộc tính quan trọng của khối tĩnh là khởi tạo. Các trường hoặc biến tĩnh được khởi tạo sau khi lớp được tải vào bộ nhớ. Thứ tự khởi tạo từ trên xuống dưới, giống như thứ tự được mô tả trong bản gốc tập tin Java lớp học. Vì các trường tĩnh được khởi tạo theo cách an toàn theo luồng nên thuộc tính này cũng được sử dụng để triển khai mẫu Singleton. Nếu bạn không sử dụng danh sách Enum dưới dạng Singleton, vì lý do này hay lý do khác, thì sẽ có một danh sách dành cho bạn thay thế tốt. Nhưng trong trường hợp này, cần phải tính đến việc đây không phải là khởi tạo “lười biếng”. Điều này có nghĩa là trường tĩnh sẽ được khởi tạo TRƯỚC KHI bất kỳ ai “yêu cầu” nó. Nếu đối tượng sử dụng nhiều tài nguyên hoặc hiếm khi được sử dụng thì việc khởi tạo nó trong một khối tĩnh sẽ không có lợi cho bạn.

    Trong quá trình tuần tự hóa, giống như các biến tạm thời, các trường tĩnh không được tuần tự hóa. Thật vậy, nếu bạn lưu bất kỳ dữ liệu nào vào một trường tĩnh, thì sau khi giải tuần tự hóa, đối tượng mới sẽ chứa giá trị chính (mặc định) của nó, ví dụ: nếu trường tĩnh là một biến int, thì giá trị của nó sau khi giải tuần tự hóa sẽ bằng 0, nếu loại float là 0,0, nếu loại Đối tượng là null. Thành thật mà nói, đây là một trong những câu hỏi thường gặp nhất liên quan đến việc tuần tự hóa trong các cuộc phỏng vấn Java. Đừng lưu trữ dữ liệu quan trọng nhất về một đối tượng trong trường tĩnh!

    Và cuối cùng, hãy nói về static import . Công cụ sửa đổi này có rất nhiều điểm chung với toán tử tiêu chuẩn import , nhưng không giống như nó cho phép bạn nhập một hoặc tất cả thành viên tĩnh của một lớp. Khi import các phương thức tĩnh, chúng ta có thể truy cập chúng như thể chúng được định nghĩa trong cùng một lớp, tương tự khi import các trường, chúng ta có thể truy cập chúng mà không cần chỉ định tên lớp. Cơ hội này xuất hiện trong Phiên bản Java 1.5 và khi được sử dụng đúng cách sẽ cải thiện khả năng đọc mã. Thiết kế này thường được tìm thấy nhiều nhất trong các thử nghiệm JUnit, bởi vì Hầu như tất cả các nhà phát triển thử nghiệm đều sử dụng tính năng nhập tĩnh cho các phương thức xác nhận, chẳng hạn như khẳng địnhEquals() và các bản sao bị quá tải của chúng. Nếu không có gì rõ ràng, chào mừng bạn đến để biết thêm thông tin.

    Đó là tất cả. Tất cả những điểm trên về công cụ sửa đổi tĩnh Mọi lập trình viên đều phải biết Java. Bài viết này đã thảo luận thông tin cơ bản về các biến tĩnh, trường, phương thức, khối khởi tạo và nhập. Bao gồm một số tính chất quan trọng, kiến ​​thức về điều này rất quan trọng khi viết và hiểu các chương trình Java. Tôi hy vọng rằng mọi nhà phát triển sẽ hoàn thiện kỹ năng sử dụng các khái niệm tĩnh của mình vì... Điều này rất quan trọng đối với việc lập trình nghiêm túc."

Cập nhật lần cuối: 19/04/2018

Ngoại trừ phương pháp thông thường và các trường, một lớp có thể có các trường, phương thức, hằng và bộ khởi tạo tĩnh. Ví dụ: lớp chính của chương trình có phương thức main là tĩnh:

Public static void main(String args) ( )

Để khai báo các biến, hằng, phương thức và bộ khởi tạo tĩnh, hãy sử dụng từ khóa static trước khi khai báo chúng.

Trường tĩnh

Khi các đối tượng lớp được tạo, mỗi đối tượng có bản sao riêng của các trường thông thường không tĩnh. Và các trường tĩnh là chung cho toàn bộ lớp. Vì vậy chúng có thể được sử dụng mà không cần tạo các đối tượng lớp.

Ví dụ: hãy tạo một biến tĩnh:

Lớp công khai Program( public static void main(String args) ( Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 1 bob.displayId(); // Id = 2 System.out.println(Person.counter); // 3 // thay đổi Person.counter Person.counter = 8; Person sam = new Person(); // Id = 8 ) lớp Person ( int id; static int; counter=1; Person())( id = counter++; ) public void displayId())( System.out.printf("Id: %d \n", id); ) )

Lớp Person chứa một bộ đếm biến tĩnh, được tăng lên trong hàm tạo và giá trị của nó được gán cho biến id. Tức là khi tạo mỗi đối tượng Person mới, biến này sẽ tăng lên nên mỗi đối tượng Person mới sẽ có giá trị trường id lớn hơn giá trị trước đó 1 đơn vị.

Vì biến đếm là tĩnh nên chúng ta có thể tham chiếu nó trong chương trình theo tên lớp:

System.out.println(Person.counter); // lấy giá trị Person.counter = 8; // thay đổi giá trị

Đầu ra giao diện điều khiển của chương trình:

Id = 1 Id = 2 3 Id = 8

Hằng số tĩnh

Ngoài ra tĩnh là các hằng số chung cho toàn bộ lớp.

Lớp công khai Program( public static void main(String args) ( doublebán kính = 60; System.out.printf("Radisu: %f \n", bán kính); // 60 System.out.printf("Diện tích: %f \n", Math.PI * bán kính); // 188.4 ) ) lớp Toán( công khai trận chung kết tĩnh PI kép = 3,14; )

Điều đáng chú ý là trong tất cả các chủ đề trước đó, hằng số tĩnh đã được sử dụng tích cực. Đặc biệt, trong biểu thức:

System.out.println("xin chào");

out chỉ đại diện cho một hằng số tĩnh của lớp System. Do đó, nó được truy cập mà không cần tạo đối tượng của lớp System.

Trình khởi tạo tĩnh

Bộ khởi tạo tĩnh được thiết kế để khởi tạo các biến tĩnh hoặc để thực hiện các hành động được thực hiện khi đối tượng đầu tiên được tạo. Ví dụ: hãy xác định trình khởi tạo tĩnh:

Lớp công khai Program( public static void main(String args) ( Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 105 bob.displayId(); // Id = 106 ) ) class Person( id int riêng; bộ đếm int tĩnh; static( counter = 105; System.out.println("Bộ khởi tạo tĩnh"); ) Person())( id=counter++; System.out.println("Constructor " ); ) public void displayId())( System.out.printf("Id: %d \n", id); ) )

Trình khởi tạo tĩnh được định nghĩa là trình khởi tạo thông thường, chỉ có điều nó được đặt trước từ khóa static . Trong trường hợp này, trong bộ khởi tạo tĩnh, chúng tôi đặt giá trị ban đầu bộ đếm trường tĩnh và hiển thị thông báo trên bảng điều khiển.

Trong chính chương trình, hai đối tượng của lớp Person được tạo. Do đó, đầu ra của bàn điều khiển sẽ trông như thế này:

Trình khởi tạo tĩnh Id trình xây dựng của hàm tạo: 105 Id: 106

Điều đáng lưu ý là trình khởi tạo tĩnh chỉ được gọi trước khi đối tượng lớp đầu tiên được tạo.

Phương pháp tĩnh

Các phương thức tĩnh cũng áp dụng cho toàn bộ lớp. Ví dụ, trong ví dụ trên, biến tĩnh counter có thể truy cập được từ bên ngoài và chúng ta có thể thay đổi giá trị của nó bên ngoài lớp Person. Hãy làm cho nó không thể thay đổi từ bên ngoài nhưng có thể đọc được. Để làm điều này, chúng tôi sử dụng một phương pháp tĩnh:

Lớp công khai Program( public static void main(String args) ( Person.displayCounter(); // Bộ đếm: 1 Person tom = new Person(); Person bob = new Person(); Person.displayCounter(); // Bộ đếm: 3 ) ) class Person( Private int id; private static int counter = 1; Person())( id = counter++; ) // phương thức tĩnh public static void displayCounter())( System.out.printf("Counter: %d \n ", bộ đếm); ) public void displayId())( System.out.printf("Id: %d \n", id); ) )

Bây giờ biến tĩnh không thể truy cập được từ bên ngoài, nó là biến riêng tư. Và giá trị của nó được hiển thị bằng phương thức tĩnh displayCounter. Để truy cập một phương thức tĩnh, hãy sử dụng tên lớp: Person.displayCounter() .

Khi sử dụng các phương thức tĩnh, chúng ta phải tính đến những hạn chế: trong các phương thức tĩnh, chúng ta chỉ có thể gọi các phương thức tĩnh khác và chỉ sử dụng các biến tĩnh.

Nói chung, các phương thức được định nghĩa là tĩnh khi các phương thức đó sẽ không ảnh hưởng đến trạng thái của đối tượng, tức là các trường và hằng không tĩnh của nó và không có ích gì khi tạo một thể hiện của lớp để gọi phương thức. Ví dụ:

Lớp công khai Chương trình( public static void main(String args) ( System.out.println(Operation.sum(45, 23)); // 68 System.out.println(Operation.subtract(45, 23)); // 68 System.out.println(Operation.subtract(45, 23)); // 22 System.out.println(Operation.multiply(4, 23)); // 92 ) class Operation( static int sum(int x, int y)( return x + y; ) static inttrừ(int x, int y )( return x - y; ) static int multi(int x, int y)( return x * y; ) )

Trong trường hợp này, đối với các phương thức tính tổng, trừ, nhân, việc sử dụng phiên bản nào của lớp Operation không quan trọng. Các phương thức này chỉ hoạt động với các tham số mà không ảnh hưởng đến trạng thái của lớp. Vì vậy, chúng có thể được định nghĩa là tĩnh.

Một phương thức tĩnh là một đoạn chương trình được gán một số tên duy nhất và có thể được gọi bằng tên này từ các phần khác của chương trình. Tại thời điểm cuộc gọi diễn ra, các hành động được liệt kê bên trong phương thức (trong phần mô tả hoặc nội dung của nó) sẽ được thực hiện.
Trong lập trình hướng đối tượng, nhiệm vụ chính của các phương thức là thay đổi trạng thái hiện tại của một đối tượng, nhưng chỉ cần các đối tượng chưa được sử dụng trong chương trình thì các phương thức đã có thể được đưa vào. Một phương thức được định nghĩa trong một lớp nhưng được gọi mà không được áp dụng cho một đối tượng cụ thể của lớp đó được gọi là tĩnh.

Ngoài tên và mô tả nêu trên, phương pháp này còn có một số đặc điểm khác:

  1. Một bộ sửa đổi.
  2. Kiểu giá trị trả về.
  3. Một tập hợp các đối số (tham số).

Công cụ sửa đổi phương thức

Để tạo một phương thức tĩnh, bạn phải chỉ định công cụ sửa đổi tĩnh trước tên của nó. Nếu điều này không được thực hiện thì phương thức này chỉ có thể được gọi trong ứng dụng tới một đối tượng cụ thể của lớp này (nó sẽ không tĩnh).

Công cụ sửa đổi công khai chịu trách nhiệm về mức độ truy cập vào phương thức được mô tả. Thay vì công khai, các cấp truy cập riêng tư hoặc bảo vệ có thể được chỉ định hoặc không thể chỉ định gì, trong trường hợp đó cấp truy cập mặc định sẽ được áp dụng.

Chúng ta sẽ làm quen với các cấp độ truy cập chi tiết hơn khi tạo các lớp của riêng mình, nhưng hiện tại, chúng tôi lưu ý rằng quyền truy cập mặc định cho phép truy cập vào một phương thức từ bất kỳ phần nào của gói mà phương thức đó được mô tả. Và cấp độ công khai cho phép truy cập vào phương thức này từ mọi nơi. Bao gồm từ các gói và chương trình khác.

Phương thức chính phải có cấp độ truy cập công khai chính xác vì nó được truy cập máy ảo Java không phải là một phần của bất kỳ gói nào.

Ngoài ra, còn có các công cụ sửa đổi khác, chẳng hạn như cho phép bạn điều chỉnh hoạt động của các phương thức trong quá trình tính toán song song (đa luồng).

Kiểu trả về

Các phương thức trong Java có thể được chia thành hai nhóm: hàm và thủ tục. Nhóm đầu tiên bao gồm các phương thức rất giống với các hàm theo nghĩa toán học. Kết quả công việc của họ là các phương thức như vậy trả về một số kết quả cụ thể cho vị trí trong chương trình mà chúng được gọi. loại hiện có, nghĩa là nó có thể là số nguyên hoặc số thực hoặc giá trị logic (int, double, boolean), mảng (tham chiếu đến nó), đối tượng (tham chiếu đến nó). Giá trị trả về phải được gán cho một biến loại phù hợp hoặc được truyền cho một số phương thức khác làm đối số.

Không giống như các hàm, các phương thức kiểu thủ tục tạo ra một số loại hành động hữu ích, nhưng không đưa ra kết quả hoàn chỉnh có thể được biểu thị bằng một giá trị hoặc đối tượng cụ thể.

Nhân đôi r = Math.random(); /* ngẫu nhiên đề cập đến các hàm */ System.out.println(r); /* println đề cập đến các thủ tục */

Nếu chúng ta tạo một phương thức, như println, sẽ in văn bản ra màn hình, nhưng đồng thời đếm số khoảng trắng trong văn bản và trả về kết quả này, chúng ta sẽ nhận được một hàm. Trong trường hợp này, hàm sẽ tiếp tục thực hiện các hành động hữu ích đặc trưng của thủ tục println. Theo đó, một hàm có tính phổ quát hơn một thủ tục, nhưng không phải lúc nào cũng cần thiết.

Khi tạo một phương thức, bước đầu tiên là xác định xem nó sẽ là hàm hay thủ tục. Đối với các tính toán trung gian, các hàm thường được sử dụng. Các thủ tục cũng có thể phù hợp để rút ngắn các đoạn mã tương tự.

Sau các từ bổ nghĩa, cũng như ở bên trái tên phương thức, loại giá trị mà nó trả về sẽ được chỉ định (nếu phương thức là một hàm, ví dụ: int hoặc double) hoặc từ void (nếu phương thức là một thủ tục).

Nếu một phương thức là một hàm thì nó phải chứa lệnh trả về, sau đó, cách nhau bằng dấu cách, biểu thức có giá trị được trả về là kết quả của phương thức sẽ được chỉ định.

Tất cả các lệnh được chỉ định trong mô tả phương thức sau khi trả về sẽ không còn được thực thi nữa; trả về mà không có đối số có thể được sử dụng bên trong các thủ tục. Nó chỉ đơn giản là chấm dứt thủ tục trước thời hạn (tương tự như ngắt một vòng lặp).

Đối số (tham số)

Khi gọi một phương thức, một tập hợp các giá trị nhất định có thể được truyền cho phương thức đó từ chương trình chính. Để dạy phương pháp chấp nhận chúng (và xử lý chúng bên trong phương thức), trong dấu ngoặc đơn Sau tên phương thức, các cặp có dạng nên được liệt kê: đối số_type đối số_tên được phân tách bằng dấu phẩy.

Sau đó, khi gọi một phương thức, sẽ có thể chỉ định một tập hợp các giá trị tương ứng với các kiểu được mô tả bởi các đối số.

Các giá trị được truyền cho phương thức tại thời điểm gọi được gọi là tham số thực tế và tên của các đối số xuất hiện trong mô tả phương thức được gọi là tham số hình thức.

Mỗi tham số hình thức là một biến cục bộ bên trong phương thức, nghĩa là nó không có sẵn bên ngoài phương thức (bên ngoài khối mô tả của nó). Khi phương thức được gọi, giá trị thực tế sẽ được sao chép vào tham số chính thức.

Đặc biệt, điều này có nghĩa là nếu chúng ta truyền bất kỳ biến nào thuộc loại cơ sở làm tham số cho một phương thức khi nó được gọi, chúng ta sẽ không thể thay đổi giá trị của biến này trong chương trình chính. Nếu bất kỳ đối tượng hoặc mảng nào được truyền tới một phương thức thông qua một đối số thì chỉ một tham chiếu đến đối tượng hoặc mảng đó (tức là địa chỉ của chúng trong bộ nhớ) được sao chép bên trong phương thức đó. Các hành động mà chúng ta thực hiện trên một mảng hoặc đối tượng bên trong một phương thức sẽ ảnh hưởng đến trạng thái của mảng hoặc đối tượng này trong chương trình chính ngay cả sau khi phương thức đó hoàn thành công việc của nó. Bên trong phương thức, chúng tôi đã truy cập cùng một địa chỉ và làm việc với cùng một dữ liệu trong bộ nhớ có sẵn trong chương trình chính.

Nếu tên của tham số thực tế khớp với tên của tham số chính thức, thì điều này không gây ra bất kỳ vấn đề nào: bên trong phương thức có một biến cục bộ, trong đó giá trị của biến toàn cục cùng tên được sao chép khi được gọi. Bằng cách truy cập tên này bên trong phương thức, chúng ta sẽ nhận được một biến cục bộ và sẽ không thể truy cập vào biến toàn cục.

Mô tả phương pháp

Phương thức này phải được mô tả bên trong lớp, nhưng một phương thức không được mô tả bên trong phương thức kia, nghĩa là phương thức đó phải được lồng trực tiếp vào khối lớp.

Sơ đồ chung để mô tả phương pháp:

Công cụ sửa đổi return_value_type tên phương thức (đối số hình thức) ( // các hành động được thực hiện bởi phương thức // có thể, return )

Theo truyền thống, tên phương thức phải bắt đầu bằng một chữ cái nhỏ. Nếu nó bao gồm một số từ, mỗi từ tiếp theo bắt đầu bằng chữ viết hoa. Tên của phương thức được chọn sao cho rõ ràng nó làm gì.

Hãy xem xét một vài ví dụ:

Kvadk tĩnh kép công khai (double) ( double t; t = Math.pow(a, 0.5); return t; )

Bây giờ bên trong phương thức chính chúng ta có thể sử dụng phương thức của mình. Ví dụ như thế này:

Int a = 25; System.out.println(kvadk(a)); // 5.0 System.out.println(a) // 25

Khi truyền các tham số thực tế cho một phương thức, quá trình tự động truyền sẽ xảy ra. Nếu đối số thực tế không khớp với kiểu chính thức thì Java sẽ cố gắng chuyển đối số thực tế sang một kiểu chung hơn (trong trường hợp này, int được chuyển thành double).

Quá tải phương thức

Chữ ký của một phương thức là sự kết hợp giữa tên của nó và một tập hợp các tham số hình thức.
Java cho phép bạn tạo nhiều phương thức với cùng tên, nhưng có chữ ký khác nhau. Việc tạo một phương thức có cùng tên nhưng có tập hợp tham số khác nhau được gọi là nạp chồng. Java xác định phương thức nạp chồng nào sẽ được thực thi khi được gọi dựa trên các tham số thực tế.

Void pr(double a) ( System.out.println(a); ) void pr (Chuỗi a) ( System.out.println(a); ) void pr(int a) ( for (int i=0; i

Một ví dụ về việc sử dụng phương pháp.

Int a = 5; int m = (1, 2, 8, 3) Chuỗi s = "Thế giới"; pr (a) //phương thức ban đầu hoạt động pr (a+s); // Thế giới 5, quá tải đầu tiên đang chạy pr (m); // 1 2 8 3 pr (m+a); // lỗi

Biến a không thuộc loại double, nhưng nó được xử lý bằng phương thức ban đầu, vì có thể tự động chuyển từ int sang double. Điều đó là không thể theo hướng ngược lại. Nếu phương thức có đối số kiểu int thì nó sẽ không thể xuất ra số thực.

Nạp chồng phương thức thực hiện một thuộc tính quan trọng như vậy trong lập trình là tính đa hình. Đa hình là mã phần mềm được liên kết với một tên chung nhưng có cách triển khai khác nhau. Việc triển khai nào sẽ hoạt động được chọn dựa trên bối cảnh mà tên được đề cập. Cụ thể đối với các phương thức, quá tải của chúng là đa hình và việc lựa chọn quá tải thực thi xảy ra theo các tham số.

Tính đa hình: một tên, nhiều dạng.

Ví dụ về việc sử dụng phương pháp

Chương trình sau đây tìm kiếm và hiển thị tất cả các ước số nguyên tố không cần thiết của một số được người dùng nhập từ bàn phím, bắt đầu bằng ước số lớn nhất hoặc báo cáo rằng số đã nhập là số nguyên tố.

Nhập java.util.Scanner; lớp công khai Main ( public static boolean isPrime(int n) ( for(int i = 2; i<= Math.sqrt(n) ; i++) { if(n%i == 0) { return false; } } return true; } public static void main(String args) { Scanner sc = new Scanner(System.in); System.out.print("Введите натуральное число: "); if(sc.hasNextInt()) { int u = sc.nextInt(); if(u >0) ( if(isPrime(u)) ( System.out.println("Bạn đã nhập số nguyên tố"); ) else ( System.out.print("Các thừa số nguyên tố của số: "); for(int i = (int) Math.sqrt(u); i >= 2 ; i--) ( if(u%i == 0 && isPrime(i)) ( System.out.print(i+" "); ) ) .out.println (); ) ) else ( System.out.println("Bạn chưa nhập số dương"); ) ) else ( System.out.println("Bạn chưa nhập số nguyên"); ) ) )

Trong ví dụ sau, một số phương thức có cùng tên sẽ được tạo do quá tải.

Phiên bản đầu tiên của phương thức này sẽ chỉ dịch chuỗi, tức là, nó thực sự sẽ là một từ đồng nghĩa ngắn hơn cho phương thức System.out.println() tích hợp sẵn. Tùy chọn này sẽ không có tham số.

Biến thể thứ hai của phương thức (quá tải đầu tiên của nó), kiểm tra xem đối số số có phân số, nếu không có thì đối số sẽ được chuyển thành số nguyên và hiển thị trên màn hình mà không có phần phân số bằng 0 (3 thay vì 3.0). Phương pháp này sẽ có thể vượt qua không chỉ biến kiểu double, mà còn cả các biến thuộc bất kỳ loại nào khác có thể tự động chuyển đổi thành double (ví dụ: bất kỳ biến số nguyên nào).

Phương thức thứ ba với một tham số chỉ gọi phương thức thứ tư, truyền mảng kết quả dưới dạng tham số, cũng như khoảng trắng làm tham số thứ hai. Xin lưu ý rằng chúng tôi đang gọi một phương thức sẽ được mô tả sau trong chương trình, điều này hoàn toàn có thể chấp nhận được.

Phương thức thứ tư xuất ra một mảng số, xử lý từng phần tử rồi phương pháp hiện có. Sau khi mỗi phần tử được hiển thị, dấu phân cách được truyền trong tham số sẽ được thêm vào.

Lớp công khai Chính ( public static void pr() ( System.out.println(); ) public static void pr(double d) ( if((int)d == d) ( System.out.print((int)d ); ) else ( System.out.print(d); ) ) public static void pr(double m) ( pr(m, " "); ) public static void pr(double m, String s) ( for(int i = 0;< m.length; i++) { pr(m[i]); System.out.print(s); } } public static void main(String args) { double arrn = {1, 2.71, 3.14, 15, -5, 92, 0.5}; double p = 3.0; int k = 13; pr(p); // вывод числа, без дробной части при возможности pr(); // переводит строку pr(arrn); // вывод числового массива в строку pr(); // переводит строку pr(arrn,", "); // вывод числового массива в строку через запятую pr(); // переводит строку pr(k); // вывод целого числа через автоприведение } }

Kết quả khi chương trình đang chạy sẽ hiển thị trên màn hình như sau:

3 1 2.71 3.14 15 -5 92 0.5 1, 2.71, 3.14, 15, -5, 92, 0.5, 1

Nhiệm vụ

  1. Tạo một phương thức tĩnh sẽ có hai tham số nguyên a và b và trả về một số nguyên ngẫu nhiên từ phân đoạn làm giá trị của nó. Sử dụng phương pháp này, điền vào một mảng gồm 20 số nguyên và hiển thị nó trên màn hình.
  2. Tạo một phương thức sẽ hiển thị mảng đã chỉ định trên màn hình dưới dạng một chuỗi. Sử dụng phương thức đã tạo và phương thức từ tác vụ trước, điền vào 5 mảng, mỗi mảng 10 phần tử Số ngẫu nhiên và hiển thị tất cả 5 mảng trên màn hình, mỗi mảng nằm trên một dòng riêng biệt.
  3. Tạo một phương thức sẽ sắp xếp mảng đã chỉ định theo thứ tự tăng dần theo bất kỳ cách nào bạn biết.
  4. Mảng lưu trữ 7 được chỉ định rõ ràng chuỗi văn bản. Viết chương trình sắp xếp và hiển thị các chuỗi trong thứ tự ABC. Ví dụ: nếu các dòng sau được đưa ra:
Pushkin Lermontov Nekrasov Tolstoy L. N. Tolstoy A. N. Yesenin Paustovsky

Chương trình sẽ hiển thị:

Yesenin Lermontov Nekrasov Paustovsky Pushkin Tolstoy A. N. Tolstoy L. N.

Gợi ý: Trước tiên, bạn cần tạo một phương thức thiết lập mối quan hệ thứ tự cho hai chuỗi được truyền vào phương thức làm đối số.

đệ quy

Đệ quy là một phương thức (hàm) tự gọi chính nó trong phần thân của nó.

Hãy xem một ví dụ - tính giai thừa. Để tính n!, chỉ cần biết và nhân (n-1) là đủ! và N.

Hãy tạo một phương thức thực hiện phương thức được mô tả.

Thực tế int tĩnh (int n) ( if (n==1) ( return 1; ) else if (n==2) ( return 2; ) else ( return Fact(n-1) * n; ) )

Phương pháp được chỉ định tính giai thừa của một số tự nhiên.

Hãy xem xét một ví dụ tính số Fibonacci thứ n thông qua đệ quy.

Chúng ta hãy nhớ lại các yếu tố đầu tiên của loạt bài này trông như thế nào: 1 1 2 3 5 8 13 ...

Static int fib (int n) ( if (n==1 || n == 2) ( return 1; ) return fib (n-2) + fib (n-1); )

Lưu ý rằng trong phương pháp này, kết quả trả về thứ hai không được đặt trong khối else cho kết quả đầu tiên. điều hành có điều kiện. Điều này được cho phép, bởi vì nếu điều kiện được đáp ứng và kết quả trả về đầu tiên được kích hoạt thì việc thực thi chương trình sẽ chỉ đạt đến kết quả trả về thứ hai nếu điều kiện không được đáp ứng;

Các phép tính đệ quy thường dẫn đến việc phải lặp lại các hành động tương tự, điều này làm chậm đáng kể chương trình.

Nhiệm vụ

  1. Hãy tìm hiểu bằng thực nghiệm, bắt đầu từ phần tử nào của dãy Fibonacci, việc tính toán bằng đệ quy trở nên không thể chấp nhận được (mất hơn một phút).
  2. Tạo một phương thức kết hợp, đối với n nhỏ, tính số Fibonacci thứ n bằng cách sử dụng đệ quy và đối với các giá trị lớn hơn ngưỡng n bạn tìm thấy trong bài toán trước, tính số Fibonacci thứ n bằng thuật toán lặp (một vòng lặp trong đó giá trị của hai phần tử trước đó của chuỗi).
  3. Tính xem cần phải tính lại phần tử thứ tư của dãy Fibonacci bao nhiêu lần để tính được phần tử thứ mười lăm.

ngăn xếp cuộc gọi

TRONG trường hợp chung chỉ có một có thể được thực hiện tại thời điểm hiện tại phương pháp duy nhất từ toàn bộ chương trình. Điều này có nghĩa là nếu phương pháp MỘTđược thiết kế theo cách mà trong phần thân của nó nó gọi là một phương thức b, Và bạn MỘTđược gọi vào chủ yếu, thì khi chương trình bắt đầu, điều khiển trước tiên sẽ được chuyển sang phương thức chủ yếu, thì phương pháp MỘT, thì phương pháp b. Phương pháp b sẽ trả về kết quả và điều khiển cho MỘT, MỘT sẽ trả về kết quả điều khiển cho chủ yếu, và chỉ khi đó chúng mới được thực thi lệnh cơ bản quy định trong phương pháp chủ yếu trên các dòng còn lại sau cuộc gọi Một.

Toàn bộ hệ thống phân cấp (ai đã gọi cho ai) được lưu trữ trong một vùng bộ nhớ đặc biệt gọi là ngăn xếp cuộc gọi. Các phần tử được thêm vào đoạn bộ nhớ này theo theo nguyên tắc sau: Phần tử cuối cùng được thêm vào phải được truy xuất trước. Khi phương pháp này hoạt động b, hóa ra bên dưới nó trên ngăn xếp có một phương thức Một và phương pháp chủ yếu.

Vì điều này, có nguy cơ tràn ngăn xếp cuộc gọi trong quá trình đệ quy.

Có một cái gọi là đệ quy phức tạp, trong đó phương thức MỘT gọi một phương thức b, b nguyên nhân Với, MỘT Với nguyên nhân MỘT.

2010, Alexey Nikolaevich Kostin. Khoa TIDM, Khoa Toán, Đại học Sư phạm quốc gia Moscow.