Sự khác biệt giữa khai báo và định nghĩa trong Java là gì?


81

Tôi rất bối rối giữa hai thuật ngữ. Tôi đã kiểm tra trên stackoverflow và có một câu hỏi tương tự cho C ++ nhưng không cho java.

Ai đó có thể giải thích sự khác biệt giữa hai thuật ngữ cho java?


2
Khai báo là yêu cầu tối thiểu để mã khác có thể gọi nó hoặc tham chiếu đến nó. Khi bạn đang biên dịch mã khác, đây là mức tối thiểu bạn cần. Định nghĩa là cần thiết cho nó để làm một cái gì đó, nó chỉ có được biên dịch một lần (không phải một lần mỗi người gọi)
Peter Lawrey

1
có thể ghi nhớ qua: de-finite, fin = end, "để kết thúc nó"; de-clare, clarus = clear, "làm cho rõ ràng". Tuyên bố làm rõ sự tồn tại, loại và tên. Định nghĩa là mã "công việc thực sự" mà sau đó bạn có thể "nói xong về nó". Chúng được sử dụng ngôn ngữ bất khả tri, vì vậy câu hỏi của bạn có nghĩa là Java sử dụng những khái niệm chung này là gì.
n611x007

Câu trả lời:


99

Sự khác biệt về khái niệm rất đơn giản:

  • Tuyên bố : Bạn đang tuyên bố rằng một cái gì đó tồn tại, chẳng hạn như là một lớp, chức năng hoặc biến. Bạn không nói bất cứ điều gì về những gì mà lớp học hoặc chức năng có vẻ như, bạn chỉ cần nói rằng nó tồn tại.

  • Định nghĩa : Bạn định nghĩa như thế nào một cái gì đó được thực hiện, chẳng hạn như là một lớp, chức năng hay thay đổi, tức là bạn nói những gì nó thực sự là.

Trong Java , có rất ít sự khác biệt giữa cả hai và nói một cách chính thức, một khai báo không chỉ bao gồm định danh mà còn bao gồm cả định nghĩa của nó. Đây là cách cá nhân tôi giải thích các điều khoản một cách chi tiết:

  • Các lớp : Java không thực sự tách biệt các khai báo và định nghĩa như C / C ++ (trong tệp tiêu đề và cpp). Bạn xác định chúng tại điểm mà bạn khai báo chúng.

  • Hàm : Khi bạn đang viết một giao diện (hoặc một lớp trừu tượng), bạn có thể nói rằng bạn đang khai báo một hàm mà không cần định nghĩa nó. Tuy nhiên, các hàm thông thường luôn được định nghĩa ngay tại nơi chúng được khai báo. Hãy xem phần thân của hàm như định nghĩa của nó nếu bạn muốn.

  • Các biến : Một khai báo biến có thể trông như thế này:

    int x;
    

    (bạn đang khai báo rằng một biến xtồn tại và có kiểu int) nếu đó là một biến cục bộ hoặc trường thành viên. Trong Java, không còn thông tin nào xđể xác định , ngoại trừ khả năng nó sẽ giữ những giá trị nào, được xác định bởi các phép gán cho nó.

Dưới đây là bản tóm tắt sơ bộ về cách tôi sử dụng các điều khoản:

abstract class SomeClass {                // class decl.
                                          //                           \
    int x;                                // variable decl.            |
                                          //                           |
    public abstract void someMethod();    // function decl.            |
                                          //                           |
    public int someOtherMethod() {        // function decl.            |
                                          //                           | class
        if (Math.random() > .5)           // \                         | def.
            return x;                     //  |  function definition   |
        else                              //  |                        |
            return -x;                    // /                         |
                                          //                           |
    }                                     //                           |
}                                         //                          /

Thật không may, điều này không được hỗ trợ bởi JLS. Theo JLS, một khai báo lớp BAO GỒM phần thân của lớp. Và điều tương tự cũng áp dụng cho các phương thức và hàm tạo.
Stephen C,

Đúng. Từ quan điểm chính thức, tôi hoàn toàn đồng ý với bạn (ngoại trừ trường hợp phương thức trừu tượng / giao diện).
aioobe,

Tôi tin rằng điều này cũng áp dụng cho javascript, phải không? Có lẽ nên thêm thẻ JS.
Griffin

Theo định danh trong mã của javac, khai báo lớp dường như đồng nghĩa với định nghĩa lớp. Hãy xem xét ví dụ public void visitClassDef(JCClassDecl tree).
aioobe

@Griffin - Ý tưởng tồi. Câu hỏi đặc biệt là về Java.
Stephen C

28

Đặc tả ngôn ngữ Java chỉ định và sử dụng thuật ngữ "khai báo" một cách rộng rãi, nhưng nó không sử dụng "định nghĩa" ngoại trừ như một từ tiếng Anh thông thường.

Bằng chứng của tôi là thuật ngữ "khai báo" xuất hiện nhiều lần trong mục lục và chỉ mục của JLS, nhưng từ "định nghĩa" cũng không xuất hiện trong đó.

Vì vậy, khi bạn thấy ai đó sử dụng từ "định nghĩa" trong ngữ cảnh của Java, họ đang sử dụng nó theo nghĩa phi kỹ thuật, hoặc họ đang cẩu thả với thuật ngữ của mình.

Trong trường hợp sau, chúng có thể có nghĩa giống như thuật ngữ kỹ thuật "tuyên bố", hoặc chúng có thể có nghĩa khác. Và nếu họ có ý khác, bạn cần hỏi họ ý của họ. Nếu họ đã định nghĩa nó ... đủ công bằng, nhưng nó không phải là thuật ngữ tiêu chuẩn.


Các câu trả lời nêu rõ rằng "định nghĩa" đề cập đến điểm mà tại đó biến được khởi tạo cụ thể là không thể hỗ trợ được ... trong ngữ cảnh của Java. Trong Java, việc khởi tạo một biến sẽ xảy ra tại điểm khai báo hoặc trong lần gán sau. Trong trường hợp thứ hai, không có thuật ngữ đặc biệt nào được sử dụng ... hoặc cần thiết ... ngoài việc gán và / hoặc khởi tạo. Không có điểm cụ thể nào mà tại đó bộ nhớ được cấp phát cho biến. Thật vậy, rất có thể không gian cho chính biến đó được cấp phát trước khi đạt đến khai báo.


Lý do mà thuật ngữ "định nghĩa" không được sử dụng trong Java trong đặc tả JLS là nó không cần thiết.

  • Vì Java cho phép các thành viên được khai báo theo bất kỳ thứ tự nào, nên không cần "khai báo chuyển tiếp". Đó là bối cảnh cần phải phân biệt giữa hai khái niệm.
  • Trong Java, không gian ngăn xếp cần thiết cho một biến là một hằng số thời gian biên dịch, do đó, các tính toán bù đắp ngăn xếp xảy ra tại thời điểm biên dịch. (Hãy nhớ rằng trong Java, một mảng là một tham chiếu đến một đối tượng heap ... và chỉ tham chiếu được giữ trong khung ngăn xếp.)
  • Cách Java xử lý "định nghĩa mà không cần khởi tạo" của một trường hoặc biến không yêu cầu một điểm "khai báo" duy nhất. Nếu một biến được yêu cầu khởi tạo, nó có thể xảy ra ở nhiều điểm trong mã nguồn.

(Nơi duy nhất trong Java mà họ có thể đã sử dụng khai báo so với định nghĩa là trong các phương thức trừu tượng. Ngoại trừ việc nếu họ đã làm như vậy, họ sẽ phải tham chiếu đến khai báo phương thức thông thường như một định nghĩa ... để nhất quán ... và điều đó sẽ khó hiểu. Vì vậy, họ chỉ gọi trường con "trừu tượng" là một khai báo của một phương thức trừu tượng.)

C và C ++ xử lý những thứ khác nhau, và do đó làm cần phân biệt "tuyên bố" và "định nghĩa" về trong mô tả kỹ thuật của họ. Định nghĩa của tôi về "Sun Glossary" là chúng là C / C ++-centric.


6

Từ định nghĩa của bảng chú giải thuật ngữ Mặt trời :

khai báo: Một câu lệnh thiết lập một định danh và liên kết các thuộc tính với nó mà không nhất thiết phải dành bộ nhớ của nó (cho dữ liệu) hoặc cung cấp việc triển khai (cho các phương thức).

định nghĩa: Một khai báo dự trữ lưu trữ (cho dữ liệu) hoặc cung cấp triển khai (cho các phương thức).

Cách tôi đọc bảng chú giải thuật ngữ Mặt trời sẽ như thế này:

List i;              // declaration - variable on the stack  
i = new ArrayList(); // definition - gives variable a reference

4
1) JLS KHÔNG sử dụng thuật ngữ "định nghĩa" để mô tả câu lệnh thứ hai. Về mặt cú pháp, nó là một phép gán. Về mặt ngữ nghĩa, nó được mô tả là "khởi tạo" biến. 2) Câu lệnh thứ 2 không phải là một khai báo, vì vậy nó không thể là một định nghĩa ... "định nghĩa: Một khai báo rằng ..." . 3) Các liên kết bị phá vỡ ...
Stephen C

Tôi đã đề xuất một chỉnh sửa để sửa liên kết. Câu hỏi và câu trả lời không nói lên điều gì về JLS.
Matthew Đọc

4

1. Khai báo có nghĩa là tạo một primitive or Object reference variable, nhưng không có gán giá trị hoặc đối tượng tương ứng ..

ví dụ:

          int x;   // declaration of x of type int

          Cat myCat;  //  declaration of myCat an Object of type Cat

2. Định nghĩa là khi chúng ta gán giá trị hoặc Đối tượng cho chúng.

         int x = 5;

         Cat myCat = new Cat();

3. Trong trường hợp của Method, nó giống như thế này ...

public abstract void go();       // Method Declaration (Abstract method)

   public void go(){               // Method Defination

            // Your code      

    }

1
Thuật ngữ này KHÔNG được hỗ trợ bởi JLS.
Stephen C,

1
@Kumar Vivek Mitra - nếu định dạng là "int x = 5", vậy sự khác biệt giữa định dạng và intialization là gì?
khan,

@SSK khởi là, định nghĩa và ngược lại ..... yêu cầu của bạn dường như nhiều thách thức hơn là thanh toán bù trừ nghi ngờ của bạn ... vì vậy thời gian tiếp theo làm thêm "xin vui lòng"
Kumar Vivek Mitra

Yup ... xem loạt Head First Java bởi Kathy Sierra và Bert Bates
Kumar Vivek Mitra

2

Tôi nghĩ rằng tôi có thể giải thích câu hỏi này tốt hơn một số điều như sau:

Hãy nghĩ về tình huống sau:

Có một vị trí tuyển dụng mới của Kỹ sư phần mềm trong công ty của bạn. Điều này có nghĩa là người bạn sẽ chọn để điền vào vị trí này sẽ là một kỹ sư phần mềm, (bạn không thể chọn một nhân viên tiếp thị cho bài đăng này). Vì vậy việc tạo bài này cũng tương tự như khai báo.

Bây giờ khi bạn xác định những gì người có bài đăng này có thể / không thể làm, những gì anh ta có thẩm quyền, những hạn chế của anh ta, thì đây được gọi là định nghĩa.

Vì vậy, nói

SoftwareEngineer se;

có nghĩa là Tuyên bố;

class SoftwareEngineer {

// define role and responsibilities
}

nghĩa là định nghĩa. Hy vọng nó sẽ giúp bạn.


2

Java ngôn ngữ định nghĩa chỉ khai báo thuật ngữ không sử dụng định nghĩa.

Tờ khai:

class A{}// class declaration

String str;// variable declaration

0

khai báo : Một câu lệnh thiết lập một mã định danh và liên kết các thuộc tính với nó mà không nhất thiết phải dành bộ nhớ của nó (cho dữ liệu) hoặc cung cấp việc triển khai (cho các phương thức).

         or

         1. Declaration means creating a primitive or Object reference variable, 
         but with no assignment of value or object respectively..

định nghĩa : Một khai báo dự trữ lưu trữ (cho dữ liệu) hoặc cung cấp triển khai (cho các phương thức).

        or

         Defination is when we assign values or Object to them.

**Ex:** 
List i;              // declaration - variable on the stack  
i = new ArrayList(); // definition - gives variable a reference

-1
  1. Đối với một đối tượng hoặc nguyên thủy

Khai báo : Chỉ định kiểu của một đối tượng hoặc nguyên thủy

Định nghĩa : Chỉ định giá trị của một đối tượng hoặc nguyên thủy

  1. Đối với một phương pháp

Khai báo : Chỉ định chữ ký của một phương thức

Định nghĩa : Chỉ định việc triển khai một phương thức

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.