Cú pháp khởi tạo mảng khi không khai báo


141

Tôi có thể viết:

AClass[] array = {object1, object2}

Tôi cũng có thể viết:

AClass[] array = new AClass[2];
...
array[0] = object1;
array[1] = object2;

nhưng tôi không thể viết:

AClass[] array;
...
array = {object1, object2};

Tại sao điều này bị chặn bởi Java?

Tôi biết làm thế nào để làm việc xung quanh nó, nhưng theo thời gian nó sẽ đơn giản hơn.

Ví dụ:

public void selectedPointsToMove(cpVect coord) {

    if (tab == null) {
        if (arePointsClose(coord, point1, 10)) {
            cpVect[] tempTab = {point1};
            tab = tempTab;
        } else if (arePointsClose(point2, coord, 10)) {
            cpVect[] tempTab = {point2};
            tab = tempTab;
        } else {
            cpVect[] tempTab = {point1,point2};
            tab = tempTab;
        }
    }
}

Câu hỏi đơn giản này đã làm tôi khó chịu khi tôi học cách chơi với các mảng trong Java.


Xin lỗi về định dạng văn bản nhưng vì một số lý do tại Trung Quốc, các nút bố cục văn bản không xuất hiện: S
Jason Rogers

đối với mã, chỉ cần đảm bảo rằng nó được thụt lề với 4 khoảng trắng trở lên.
Mat

vấn đề khác là bạn có các ký tự TAB trong mã bạn đã dán. Điều này làm rối định dạng.
Stephen C

Oki cảm ơn, nhật thực sử dụng các tab trong vết lõm để khi tôi sao chép dán nó làm mọi thứ rối tung lên. cảm ơn vì đã chỉnh sửa
Jason Rogers

Eclipse có thể và nên được cấu hình lại để không sử dụng các ký tự TAB để thụt lề. Xin đừng sử dụng nó như một cái cớ
Stephen C

Câu trả lời:


137

Tại sao điều này bị chặn bởi Java?

Bạn phải hỏi các nhà thiết kế Java. Có thể có một số lý do ngữ pháp tinh tế cho sự hạn chế. Lưu ý rằng một số cấu trúc khởi tạo / khởi tạo mảng không có trong Java 1.0 và (IIRC) đã được thêm vào trong Java 1.1.

Nhưng "tại sao" là không quan trọng ... hạn chế là có, và bạn phải sống với nó.

Tôi biết làm thế nào để làm việc xung quanh nó, nhưng theo thời gian nó sẽ đơn giản hơn.

Bạn có thể viết điều này:

AClass[] array;
...
array = new AClass[]{object1, object2};

9
w / o khai báo mới sẽ không có sự khác biệt giữa khối lệnh và trình khởi tạo mảng (như trong javascript, có thể gây hiểu nhầm}
bestsss 22/03/2016

10
sẽ gây nhầm lẫn ... và khó phân tích. Xem xét nếu {o1()}là một biểu thức hợp lệ và {o1();}là một khối câu lệnh hợp lệ. Trình phân tích cú pháp phải đến '}' hoặc ';' trước khi nó có thể phân biệt hai trường hợp. Vấn đề ngữ pháp không tinh tế chút nào !!
Stephen C

19

Tôi sẽ cố gắng trả lời câu hỏi tại sao: Mảng Java rất đơn giản và thô sơ so với các lớp như ArrayList, năng động hơn. Java muốn biết tại thời điểm khai báo nên phân bổ bao nhiêu bộ nhớ cho mảng. Một ArrayList năng động hơn nhiều và kích thước của nó có thể thay đổi theo thời gian.

Nếu bạn khởi tạo mảng của mình với độ dài bằng hai và sau đó, hóa ra bạn cần độ dài ba, bạn phải loại bỏ những gì bạn có và tạo một mảng hoàn toàn mới. Do đó, từ khóa 'mới'.

Trong hai ví dụ đầu tiên của bạn, bạn cho biết tại thời điểm khai báo có bao nhiêu bộ nhớ để phân bổ. Trong ví dụ thứ ba của bạn, tên mảng trở thành một con trỏ không có gì cả, và do đó, khi nó được khởi tạo, bạn phải tạo một mảng rõ ràng để phân bổ lượng bộ nhớ phù hợp.

Tôi sẽ nói rằng (và nếu ai đó biết rõ hơn, xin vui lòng sửa cho tôi) ví dụ đầu tiên

AClass[] array = {object1, object2}

thực sự có nghĩa là

AClass[] array = new AClass[]{object1, object2};

nhưng những gì các nhà thiết kế Java đã làm, là tạo ra cách viết nhanh hơn nếu bạn tạo mảng tại thời điểm khai báo.

Các giải pháp đề xuất là tốt. Nếu thời gian sử dụng hoặc bộ nhớ là quan trọng trong thời gian chạy, hãy sử dụng mảng. Nếu nó không quan trọng và bạn muốn mã dễ hiểu và dễ làm việc hơn, hãy sử dụng ArrayList.


2
Đây là một phím tắt như bạn đã nêu, Trích dẫn Oracle: "Ngoài ra, bạn có thể sử dụng cú pháp phím tắt để tạo và khởi tạo một mảng" . Lý do có thể là một mảng phải được cung cấp một số không gian trong bộ nhớ bằng cách sử dụng mới tại một số điểm. Mới là ẩn trong phím tắt, nhưng phím tắt chỉ có giá trị trong khai báo. Ở những nơi khác, không có lối tắt nào được cho phép và mới là bắt buộc.
phút

3
Tôi xin lỗi, nhưng nỗ lực của bạn trong việc trả lời câu hỏi "tại sao" không giữ được nước. Trình biên dịch sẽ có thể tìm ra mức độ lớn của mảng cần thiết bằng cách đếm các biểu thức giữa {}... giống như đối với các biểu mẫu khởi tạo được phép.
Stephen C

8

Tôi không thể trả lời tại sao một phần.

Nhưng nếu bạn muốn một cái gì đó năng động thì tại sao bạn không xem xét Collection ArrayList.

ArrrayList có thể thuộc bất kỳ loại Object nào.

Và nếu như là một sự bắt buộc, bạn muốn nó như là một mảng, bạn có thể sử dụng phương thức toArray () trên nó.

Ví dụ:

            ArrayList<String> al = new ArrayList<String>();
            al.add("one");
            al.add("two");
            String[] strArray = (String[]) al.toArray(new String[0]);

Tôi hy vọng điều này có thể giúp bạn.


2
Không cần truyền kiểu trả về của Array thành String []. Theo hợp đồng, mảng trả về có cùng loại với mảng được chỉ định. docs.oracle.com/javase/6/docs/api/java/util/ Kẻ
Ankur Agarwal

4

Đối với những người bạn, những người không thích new AClass[] { ... }cú pháp quái dị này , đây là một số đường:

public AClass[] c(AClass... arr) { return arr; }

Sử dụng chức năng nhỏ này như bạn muốn:

AClass[] array;
...
array = c(object1, object2);
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.