Tại sao mọi người vẫn sử dụng các kiểu nguyên thủy trong Java?


163

Kể từ Java 5, chúng tôi đã có quyền anh / bỏ hộp các kiểu nguyên thủy để intđược bao bọc java.lang.Integer, và cứ thế tiếp tục.

Tôi thấy rất nhiều dự án Java mới gần đây ( chắc chắn yêu cầu JRE ít nhất là phiên bản 5, nếu không phải là 6) đang sử dụng intchứ không phải làjava.lang.Integer sử dụng cái sau thuận tiện hơn, vì nó có một vài phương thức trợ giúp để chuyển đổi để longgiá trị et al.

Tại sao một số vẫn sử dụng các kiểu nguyên thủy trong Java? Có bất kỳ lợi ích hữu hình?


49
Đã bao giờ nghĩ về tiêu thụ bộ nhớ và hiệu suất?
Tedil

76
Tôi đã thêm thẻ autoboxing ... và phát hiện ra rằng ba người thực sự theo dõi nó. Có thật không? Mọi người theo thẻ AUTOBOXING?
corsiKa

4
@glowcoder Họ không phải là người thực tế, họ chỉ là những khái niệm trừu tượng giả định dạng người để trả lời trên SO. :)
biziclop

9
@TK Kocheran Chủ yếu là vì new IntegeR(5) == new Integer(5)nên theo quy tắc, đánh giá thành sai.
biziclop

10
Xem Bộ sưu tập GNU Trove hoặc Mahout hoặc HPPC hoặc ... để biết các giải pháp cho bộ sưu tập các kiểu nguyên thủy. Những người trong chúng ta quan tâm đến tốc độ dành thời gian của chúng tôi bằng cách sử dụng các loại nguyên thủy hơn , không phải ít hơn.
bmargulies

Câu trả lời:


395

Trong Java hiệu quả của Joshua Bloch , Mục 5: "Tránh tạo các đối tượng không cần thiết", anh ta đăng ví dụ mã sau:

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

và phải mất 43 giây để chạy. Đưa Long vào nguyên thủy sẽ giảm xuống còn 6,8 giây ... Nếu đó là bất kỳ dấu hiệu nào cho thấy tại sao chúng ta sử dụng nguyên thủy.

Sự thiếu bình đẳng giá trị bản địa cũng là một mối quan tâm ( .equals()khá dài dòng so với== )

cho biziclop:

class Biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

Kết quả trong:

false
false
true
false

EDIT Tại sao (3) trở lại truevà (4) trở lại false?

Bởi vì chúng là hai đối tượng khác nhau. 256 số nguyên gần nhất với 0 [-128; 127] được lưu trữ bởi JVM, vì vậy chúng trả về cùng một đối tượng cho các đối tượng đó. Tuy nhiên, ngoài phạm vi đó, chúng không được lưu trong bộ nhớ cache, do đó, một đối tượng mới được tạo. Để làm cho mọi thứ phức tạp hơn, JLS yêu cầu ít nhất 256 bánh đà được lưu trữ. Những người triển khai JVM có thể bổ sung thêm nếu họ muốn, có nghĩa là điều này có thể chạy trên một hệ thống có 1024 bộ nhớ cache gần nhất và tất cả chúng đều trả về đúng ... #awkward


54
Bây giờ hãy tưởng tượng nếu iđược tuyên bố Longlà tốt!
ColinD

14
@TREE - thông số kỹ thuật thực sự yêu cầu VM tạo flyweights trong một phạm vi nhất định. Nhưng thật đáng buồn, nó cho phép họ mở rộng phạm vi đó, có nghĩa là các chương trình có thể hoạt động khác nhau trên các máy ảo khác nhau. Quá nhiều cho nền tảng chéo ...
Daniel Earwicker

12
Java đã đi xuống, với ngày càng nhiều lựa chọn thiết kế tồi. Autoboxing là một thất bại hoàn toàn, nó không mạnh mẽ, có thể dự đoán hoặc di động. Tôi thực sự thực sự tự hỏi họ đang nghĩ gì ... thay vì sửa chữa tính đối ngẫu nguyên thủy của đối tượng nguyên thủy đáng sợ mà họ đã làm cho nó tồi tệ hơn ở nơi đầu tiên.
Pop Catalin

34
@Cirthin Tôi không đồng ý với bạn rằng autoboxing là một thất bại hoàn toàn. Nó có một số sai sót, không khác gì bất kỳ thiết kế nào có thể được sử dụng (bao gồm cả không có gì.) Họ nói rất rõ những gì bạn có thể và không thể mong đợi, và giống như bất kỳ thiết kế nào khác mà họ mong đợi các nhà phát triển biết và tuân theo hợp đồng của những thiết kế đó.
corsiKa

9
@NaftuliTzviKay Đó không phải là một "thất bại." Họ làm cho RẤT RAR RÀNG rằng ==toán tử thực hiện so sánh nhận dạng tham chiếu trên Integerbiểu thức và so sánh giá trị bằng nhau trên intbiểu thức. Integer.equals()tồn tại vì chính lý do này. Bạn không bao giờ nên sử dụng ==để so sánh các giá trị trong bất kỳ loại không nguyên thủy nào. Đây là Java 101.
NullUserException

86

Autounboxing có thể dẫn đến khó phát hiện NPE

Integer in = null;
...
...
int i = in; // NPE at runtime

Trong hầu hết các tình huống, việc gán null inlà rất ít rõ ràng hơn ở trên.


43

Các loại đóng hộp có hiệu suất kém hơn và đòi hỏi nhiều bộ nhớ hơn.


40

Các loại nguyên thủy:

int x = 1000;
int y = 1000;

Bây giờ đánh giá:

x == y

Đó là true. Hầu như không ngạc nhiên. Bây giờ hãy thử các loại đóng hộp:

Integer x = 1000;
Integer y = 1000;

Bây giờ đánh giá:

x == y

Đó là false. Có lẽ. Phụ thuộc vào thời gian chạy. Lý do đó đã đủ chưa?


36

Bên cạnh các vấn đề về hiệu năng và bộ nhớ, tôi muốn đưa ra một vấn đề khác: ListGiao diện sẽ bị hỏng nếu không có int.
Vấn đề là remove()phương thức quá tải ( remove(int)so với remove(Object)). remove(Integer)sẽ luôn giải quyết việc gọi cái sau, vì vậy bạn không thể xóa phần tử theo chỉ mục.

Mặt khác, có một cạm bẫy khi cố gắng thêm và xóa int:

final int i = 42;
final List<Integer> list = new ArrayList<Integer>();
list.add(i); // add(Object)
list.remove(i); // remove(int) - Ouch!

7
Nó sẽ bị phá vỡ, vâng. Tuy nhiên, remove (int) là một lỗ hổng thiết kế IMO. Tên phương thức không bao giờ bị quá tải nếu có cơ hội trộn lẫn nhỏ nhất.
MrBackend 9/2/2015

4
@MrBackend Hội chợ đủ. Thật thú vị, Vectorđã có removeElementAt(int)từ đầu. remove(int)đã được giới thiệu với khung bộ sưu tập trong Java 1.2.
xehpuk

6
@MrBackend: khi ListAPI được thiết kế, không Generics cũng không autoboxing tồn tại, vì vậy không có cơ hội trộn lên remove(int)remove(Object)...
Holger

@Franklin Yu: chắc chắn, nhưng khi thiết kế một ngôn ngữ / phiên bản mới không có ràng buộc tương thích, bạn sẽ không dừng lại ở việc thay đổi sự quá tải đáng tiếc đó. Bạn chỉ đơn giản là sẽ thoát khỏi sự phân biệt của các nguyên thủy và các giá trị được đóng hộp hoàn toàn, để câu hỏi sử dụng sẽ không bao giờ xuất hiện.
Holger

27

Bạn thực sự có thể tưởng tượng một

  for (int i=0; i<10000; i++) {
      do something
  }

vòng lặp với java.lang.Integer thay thế? Một java.lang.Integer là bất biến, do đó, mỗi vòng tăng vòng lặp sẽ tạo ra một đối tượng java mới trên heap, thay vì chỉ tăng int trên ngăn xếp với một lệnh JVM duy nhất. Việc thực hiện sẽ là diabolical.

Tôi thực sự không đồng ý rằng việc sử dụng java.lang.Integer hơn int. Trái lại. Autoboxing có nghĩa là bạn có thể sử dụng int trong trường hợp bạn buộc phải sử dụng Integer và trình biên dịch java sẽ đảm nhiệm việc chèn mã để tạo đối tượng Integer mới cho bạn. Autoboxing là tất cả về việc cho phép bạn sử dụng một int nơi mà Integer được mong đợi, với trình biên dịch chèn cấu trúc đối tượng có liên quan. Nó không có cách nào loại bỏ hoặc làm giảm sự cần thiết của int ở nơi đầu tiên. Với autoboxing bạn có được điều tốt nhất của cả hai thế giới. Bạn tự động nhận được một Số nguyên khi bạn cần một đối tượng java dựa trên heap và bạn có được tốc độ và hiệu quả của một int khi bạn chỉ thực hiện các phép tính số học và cục bộ.


19

Các loại nguyên thủy nhanh hơn nhiều :

int i;
i++;

Số nguyên (tất cả Số và cả Chuỗi) là loại không thay đổi : một khi được tạo, nó không thể thay đổi. Nếu ilà Integer, i++thì sẽ tạo ra một đối tượng Integer mới - đắt hơn nhiều về bộ nhớ và bộ xử lý.


Bạn không muốn một biến thay đổi nếu bạn thực hiện i++trên một biến khác, do đó, Integer hoàn toàn cần phải bất biến để có thể làm điều này (hoặc ít nhất điều này i++sẽ phải tạo một đối tượng Integer mới). (Và các giá trị nguyên thủy cũng không thay đổi - bạn không nhận xét điều này vì chúng không phải là đối tượng.)
Paŭlo Ebermann

4
@ Paŭlo: Nói rằng các giá trị nguyên thủy là bất biến là loại vô nghĩa. Khi bạn gán lại một biến nguyên thủy cho một giá trị mới, bạn sẽ không tạo ra bất cứ điều gì mới. Không có phân bổ bộ nhớ có liên quan. Quan điểm của Peter là: i ++ đối với người nguyên thủy không cấp phát bộ nhớ, nhưng đối với một đối tượng thì nó nhất thiết phải làm.
Eddie

@Eddie: (Không nhất thiết phải cấp phát bộ nhớ, nó cũng có thể trả về giá trị được lưu trong bộ nhớ cache. Đối với một số giá trị nhỏ, tôi nghĩ vậy.) Quan điểm của tôi là tính bất biến của Số nguyên ở đây không phải là điểm quyết định, dù sao bạn cũng muốn để có một đối tượng khác, bất kể bất biến.
Paŭlo Ebermann

@ Paŭlo: điểm duy nhất của tôi là Integer là một thứ tự cường độ chậm hơn so với nguyên thủy. Và điều này là do thực tế là các loại hình hộp là bất biến và mỗi khi bạn thay đổi một giá trị, một đối tượng mới được tạo. Tôi không khẳng định có điều gì đó không ổn với họ hoặc thực tế là họ bất biến. Chỉ là họ chậm hơn và một lập trình viên nên biết điều đó. Hãy xem cách Groovy giá vé mà không có các loại nguyên thủy jcont.com/rant/entry/why_is_groovy_so_slow
Peter Knego

1
Bất biến và ++là một cá trích đỏ ở đây. Hãy tưởng tượng Java đã được tăng cường để điều hành hỗ trợ quá tải một cách thực sự đơn giản, chẳng hạn rằng nếu một lớp học (ví dụ như Integercó một phương pháp plus, sau đó bạn có thể viết i + 1thay cho i.plus(1). Và cũng có thể giả định rằng trình biên dịch là đủ thông minh để mở rộng i++thành i = i + 1. Bây giờ bạn có thể nói i++và hiệu quả "tăng biến i" mà không Integerbị biến đổi.
Daniel Earwicker

16

Đầu tiên và quan trọng nhất, thói quen. Nếu bạn đã mã hóa bằng Java trong tám năm, bạn sẽ tích lũy được một lượng quán tính đáng kể. Tại sao thay đổi nếu không có lý do thuyết phục để làm như vậy? Nó không phải như thể sử dụng nguyên thủy đóng hộp đi kèm với bất kỳ lợi thế bổ sung.

Lý do khác là để khẳng định rằng đó nullkhông phải là một lựa chọn hợp lệ. Sẽ là vô nghĩa và sai lệch khi khai báo tổng của hai số hoặc một biến vòng lặp là Integer.

Cũng có khía cạnh hiệu suất của nó, trong khi sự khác biệt hiệu năng không quan trọng trong nhiều trường hợp (mặc dù khi đó, nó khá tệ), không ai thích viết mã có thể được viết dễ dàng theo cách nhanh hơn chúng ta đã đã từng.


15
Tôi không đồng ý. Các khía cạnh hiệu suất có thể rất quan trọng. Rất ít trong số này có lẽ là quán tính hoặc lực lượng của thói quen.
Eddie

7
@Eddie Nó có thể, nhưng nó rất hiếm khi. Tin tôi đi, đối với hầu hết mọi người, các đối số hiệu suất chỉ là một cái cớ.
biziclop

3
Tôi cũng muốn bảo vệ các đối số hiệu suất. Trên Android với Dalvik, mỗi đối tượng bạn tạo sẽ làm tăng "rủi ro" của việc gọi GC và càng nhiều đối tượng bạn có các lần tạm dừng sẽ càng lâu. Vì vậy, việc tạo các số nguyên thay vì int trong một vòng lặp có thể sẽ khiến bạn mất một số khung hình bị rơi.
Igor ordaš

1
@PSIXO Đó là một điểm công bằng, tôi đã viết nó với ý tưởng hoàn toàn về phía máy chủ. Thiết bị di động là một động vật hoàn toàn khác nhau. Nhưng quan điểm của tôi là ngay cả các nhà phát triển, những người viết mã khủng khiếp mà không quan tâm đến hiệu suất sẽ trích dẫn điều này như một lý do, từ họ điều này nghe có vẻ như là một cái cớ.
biziclop

12

Nhân tiện, Smalltalk chỉ có các đối tượng (không có nguyên thủy), và họ đã tối ưu hóa các số nguyên nhỏ của mình (không sử dụng tất cả 32 bit, chỉ 27 hoặc hơn) để không phân bổ bất kỳ không gian heap nào, mà chỉ sử dụng một mẫu bit đặc biệt. Ngoài ra các đối tượng phổ biến khác (đúng, sai, null) có các mẫu bit đặc biệt ở đây.

Vì vậy, ít nhất là trên các JVM 64 bit (với không gian tên con trỏ 64 bit), không nên có bất kỳ đối tượng nào của Integer, Character, Byte, Short, Boolean, Float (và Long Long) bằng cách rõ ràng new ...()), chỉ các mẫu bit đặc biệt, có thể được các toán tử bình thường thao tác khá hiệu quả.


Tôi nên nói "một số triển khai", vì điều này không bị chi phối bởi các đặc tả ngôn ngữ, tôi nghĩ vậy. (Và đáng buồn là tôi không thể trích dẫn bất kỳ nguồn nào ở đây, nó chỉ từ những gì tôi nghe được ở đâu đó.)
Paŭlo Ebermann

ŭlo, JIT đã giữ meta trong con trỏ; bao gồm, con trỏ có thể giữ thông tin GC hoặc Klass (tối ưu hóa Class là ý tưởng tốt hơn nhiều so với tối ưu hóa các số nguyên mà tôi có thể quan tâm ít hơn). Thay đổi con trỏ sẽ yêu cầu, thay đổi mã / cmp / jnz (hoặc đại loại như thế) trước mỗi lần tải con trỏ. Chi nhánh có thể sẽ không được dự đoán rất tốt bởi phần cứng (vì nó có thể là cả Loại giá trị và Đối tượng bình thường) và nó sẽ dẫn đến hiệu năng.
bestsss

3
Tôi đã làm Smalltalk trong một số năm. Việc tối ưu hóa vẫn còn khá tốn kém, vì với mỗi thao tác trên một int họ phải vạch mặt và áp dụng lại chúng. Hiện tại java ngang hàng với C khi thao tác các số nguyên thủy. Với mặt nạ + mặt nạ, nó có thể sẽ chậm hơn> 30%.
R.Moeller

9

Tôi không thể tin rằng không ai đã đề cập đến những gì tôi nghĩ là lý do quan trọng nhất: "int" là như vậy, rất dễ gõ hơn "Integer". Tôi nghĩ mọi người đánh giá thấp tầm quan trọng của một cú pháp súc tích. Hiệu suất thực sự không phải là lý do để tránh chúng bởi vì hầu hết thời gian khi một người đang sử dụng các số nằm trong chỉ mục vòng lặp, và tăng và so sánh các chi phí đó không có gì trong bất kỳ vòng lặp không tầm thường nào (cho dù bạn đang sử dụng int hay Integer).

Một lý do khác được đưa ra là bạn có thể nhận được NPE nhưng điều đó cực kỳ dễ tránh với các loại được đóng hộp (và nó được đảm bảo tránh được miễn là bạn luôn khởi tạo chúng thành các giá trị khác 0).

Lý do khác là (Long mới (1000)) == (Long mới (1000)) là sai, nhưng đó chỉ là một cách khác để nói rằng ".equals" không hỗ trợ cú pháp cho các loại được đóng hộp (không giống như các toán tử <,> , =, v.v.), vì vậy chúng tôi quay lại lý do "cú pháp đơn giản hơn".

Tôi nghĩ ví dụ về vòng lặp không nguyên thủy của Steve Yegge minh họa rất rõ quan điểm của tôi: http://sites.google.com.vn/site/steveyegge2/lingu-trickery-and-ejb

Hãy nghĩ về điều này: tần suất bạn sử dụng các loại hàm trong các ngôn ngữ có cú pháp tốt cho chúng (như bất kỳ ngôn ngữ chức năng nào, python, ruby ​​và thậm chí C) so với java nơi bạn phải mô phỏng chúng bằng các giao diện như Runnable và Callable và lớp không tên.


8

Một vài lý do để không loại bỏ nguyên thủy:

  • Khả năng tương thích ngược.

Nếu nó bị loại bỏ, bất kỳ chương trình cũ nào thậm chí sẽ không chạy.

  • Viết lại JVM.

Toàn bộ JVM sẽ phải được viết lại để hỗ trợ điều mới này.

  • Dấu chân bộ nhớ lớn hơn.

Bạn cần lưu trữ giá trị và tham chiếu, sử dụng nhiều bộ nhớ hơn. Nếu bạn có một mảng byte lớn, việc sử dụng bytesẽ nhỏ hơn đáng kể so với sử dụng Byte.

  • Vấn đề con trỏ Null.

Tuyên bố int isau đó làm công cụ với isẽ không có vấn đề gì, nhưng khai báo Integer ivà sau đó làm tương tự sẽ dẫn đến một NPE.

  • Vấn đề bình đẳng.

Xem xét mã này:

Integer i1 = 5;
Integer i2 = 5;

i1 == i2; // Currently would be false.

Sẽ là sai. Các nhà khai thác sẽ phải bị quá tải, và điều đó sẽ dẫn đến việc viết lại chính các công cụ.

  • Chậm

Các hàm bao đối tượng chậm hơn đáng kể so với các đối tác nguyên thủy của chúng.


i1 == i2; sẽ chỉ sai nếu i1> = 128. Vì vậy, ví dụ hiện tại là sai
Geniy

7

Các đối tượng nặng hơn nhiều so với các kiểu nguyên thủy, vì vậy các kiểu nguyên thủy hiệu quả hơn nhiều so với các thể hiện của các lớp bao bọc.

Các kiểu nguyên thủy rất đơn giản: ví dụ int là 32 bit và chiếm chính xác 32 bit trong bộ nhớ và có thể được thao tác trực tiếp. Một đối tượng Integer là một đối tượng hoàn chỉnh, mà (giống như bất kỳ đối tượng nào) phải được lưu trữ trên heap và chỉ có thể được truy cập thông qua một tham chiếu (con trỏ) đến nó. Nó rất có thể cũng chiếm hơn 32 bit (4 byte) bộ nhớ.

Điều đó nói rằng, việc Java có sự phân biệt giữa các kiểu nguyên thủy và không nguyên thủy cũng là một dấu hiệu tuổi của ngôn ngữ lập trình Java. Các ngôn ngữ lập trình mới hơn không có sự khác biệt này; trình biên dịch của một ngôn ngữ như vậy đủ thông minh để tự mình tìm ra nếu bạn đang sử dụng các giá trị đơn giản hoặc các đối tượng phức tạp hơn.

Chẳng hạn, trong Scala không có kiểu nguyên thủy; có một lớp Int cho các số nguyên và một Int là một đối tượng thực (mà bạn có thể phương thức trên v.v.). Khi trình biên dịch biên dịch mã của bạn, nó sử dụng các int nguyên thủy phía sau hậu trường, vì vậy sử dụng một Int cũng hiệu quả như sử dụng một int nguyên thủy trong Java.


1
Tôi đã giả định rằng JRE sẽ đủ "thông minh" để làm điều này với các nguyên hàm được bao bọc bởi Java. Thất bại.
Naftuli Kay

7

Ngoài những gì người khác đã nói, các biến cục bộ nguyên thủy không được phân bổ từ heap, mà thay vào đó là trên ngăn xếp. Nhưng các đối tượng được phân bổ từ đống và do đó phải được thu gom rác.


3
Xin lỗi, điều này là sai. Một JVM thông minh có thể thực hiện phân tích thoát trên bất kỳ phân bổ đối tượng nào và, nếu chúng không thể thoát, hãy phân bổ chúng trên ngăn xếp.
rlibby

2
Vâng, đây là bắt đầu là một tính năng của các JVM hiện đại. Trong năm năm, những gì bạn nói sẽ đúng với hầu hết các JVM sau đó được sử dụng. Hôm nay thì không. Tôi gần như bình luận về điều này, nhưng quyết định không bình luận về nó. Có lẽ tôi nên nói điều gì đó.
Eddie

6

Các loại nguyên thủy có nhiều ưu điểm:

  • Mã đơn giản để viết
  • Hiệu suất sẽ tốt hơn vì bạn không khởi tạo một đối tượng cho biến
  • Vì chúng không đại diện cho một tham chiếu đến một đối tượng, nên không cần kiểm tra null
  • Sử dụng các loại nguyên thủy trừ khi bạn cần tận dụng các tính năng của quyền anh.

5

Thật khó để biết loại tối ưu hóa nào đang diễn ra dưới vỏ bọc.

Để sử dụng cục bộ, khi trình biên dịch có đủ thông tin để tối ưu hóa ngoại trừ khả năng của giá trị null, tôi hy vọng hiệu suất sẽ giống hoặc tương tự .

Tuy nhiên, mảng nguyên thủy rõ ràng rất khác nhau so với các bộ sưu tập nguyên thủy đóng hộp. Điều này có ý nghĩa khi có rất ít tối ưu hóa có thể nằm sâu trong một bộ sưu tập.

Hơn nữa, Integercó một chi phí logic cao hơn nhiều so với int: bây giờ bạn phải lo lắng về việc có int a = b + c;ném ngoại lệ hay không .

Tôi sẽ sử dụng các nguyên thủy càng nhiều càng tốt và dựa vào các phương thức xuất xưởng và hộp tự động để cung cấp cho tôi các loại hình hộp mạnh hơn về mặt ngữ nghĩa khi cần thiết.


5
int loops = 100000000;

long start = System.currentTimeMillis();
for (Long l = new Long(0); l<loops;l++) {
    //System.out.println("Long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around Long: "+ (System.currentTimeMillis()- start));

start = System.currentTimeMillis();
for (long l = 0; l<loops;l++) {
    //System.out.println("long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around long: "+ (System.currentTimeMillis()- start));

Một phần nghìn giây được thực hiện để lặp lại '100000000' khoảng Long: 468

Một phần nghìn giây được thực hiện để lặp lại '100000000' khoảng thời gian dài: 31

Bên cạnh đó, tôi không phiền khi thấy một cái gì đó như thế này tìm thấy nó vào Java.

Integer loop1 = new Integer(0);
for (loop1.lessThan(1000)) {
   ...
}

Trong đó vòng lặp for tự động tăng loop1 từ 0 lên 1000 hoặc

Integer loop1 = new Integer(1000);
for (loop1.greaterThan(0)) {
   ...
}

Trong đó vòng lặp for tự động giảm vòng lặp1 1000 xuống 0.


2
  1. Bạn cần nguyên thủy để thực hiện các phép toán
  2. Người nguyên thủy chiếm ít bộ nhớ như đã trả lời ở trên và hoạt động tốt hơn

Bạn nên hỏi tại sao loại Class / Object là bắt buộc

Lý do có loại Đối tượng là làm cho cuộc sống của chúng ta dễ dàng hơn khi chúng ta đối phó với Bộ sưu tập. Nguyên thủy không thể được thêm trực tiếp vào Danh sách / Bản đồ thay vì bạn cần phải viết một lớp bao bọc. Readymade Kiểu lớp Integer giúp bạn ở đây cộng với nó có nhiều phương thức tiện ích như Integer.pareseInt (str)


2

Tôi đồng ý với các câu trả lời trước đây, sử dụng các đối tượng trình bao bọc nguyên thủy có thể tốn kém. Nhưng, nếu hiệu suất không quan trọng trong ứng dụng của bạn, bạn sẽ tránh bị tràn khi sử dụng các đối tượng. Ví dụ:

long bigNumber = Integer.MAX_VALUE + 2;

Giá trị của bigNumberlà -2147483647 và bạn sẽ mong đợi nó là 2147483649. Đó là một lỗi trong mã sẽ được sửa bằng cách thực hiện:

long bigNumber = Integer.MAX_VALUE + 2l; // note that '2' is a long now (it is '2L').

bigNumbersẽ là 2147483649. Những loại lỗi này đôi khi rất dễ bị bỏ qua và có thể dẫn đến hành vi hoặc lỗ hổng không xác định (xem CWE-190 ).

Nếu bạn sử dụng các đối tượng trình bao bọc, mã tương đương sẽ không biên dịch.

Long bigNumber = Integer.MAX_VALUE + 2; // Not compiling

Vì vậy, dễ dàng hơn để ngăn chặn các loại vấn đề này bằng cách sử dụng các đối tượng trình bao bọc nguyên thủy.

Câu hỏi của bạn đã được trả lời rồi, tôi trả lời chỉ để thêm một chút thông tin không được đề cập trước đó.


1

Bởi vì JAVA thực hiện tất cả các hoạt động toán học trong các loại nguyên thủy. Xem xét ví dụ này:

public static int sumEven(List<Integer> li) {
    int sum = 0;
    for (Integer i: li)
        if (i % 2 == 0)
            sum += i;
        return sum;
}

Ở đây, không thể áp dụng các thao tác nhắc nhở và unary plus trên loại Integer (Reference), trình biên dịch thực hiện unboxing và thực hiện các thao tác.

Vì vậy, hãy chắc chắn có bao nhiêu hoạt động autoboxing và unboxing xảy ra trong chương trình java. Vì, phải mất thời gian để thực hiện các hoạt động này.

Nói chung, tốt hơn là giữ các đối số của kiểu Tham chiếu và kết quả của kiểu nguyên thủy.


1

Các loại nguyên thủynhanh hơn nhiều và đòi hỏi nhiều ít bộ nhớ . Do đó, chúng tôi có thể muốn sử dụng chúng.

Mặt khác, đặc tả ngôn ngữ Java hiện tại không cho phép sử dụng các kiểu nguyên thủy trong các kiểu được tham số hóa (generic), trong các bộ sưu tập Java hoặc API Reflection.

Khi ứng dụng của chúng tôi cần các bộ sưu tập với số lượng lớn các phần tử, chúng ta nên xem xét sử dụng các mảng với loại càng nhiều càng tiết kiệm càng tốt.

* Để biết thông tin chi tiết, hãy xem nguồn: https://www.baeldung.com/java-primologists-vs-objects


0

Nói ngắn gọn: các kiểu nguyên thủy nhanh hơn và cần ít bộ nhớ hơn các kiểu đóng hộp

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.