Tại sao Java có các nguyên hàm cho các số kích thước khác nhau?


20

Trong Java có các kiểu dữ liệu byte, short, intlongvà điều tương tự cho floatdouble. Tại sao cần phải có một người đặt bao nhiêu byte nên được sử dụng cho một giá trị nguyên thủy? Không thể xác định kích thước một cách linh hoạt tùy thuộc vào số lượng lớn được chuyển vào là bao nhiêu?

Có 2 lý do tôi có thể nghĩ ra:

  1. Tự động thiết lập kích thước của dữ liệu có nghĩa là nó cũng cần có khả năng thay đổi linh hoạt. Điều này có khả năng gây ra vấn đề hiệu suất?
  2. Có lẽ lập trình viên sẽ không muốn ai đó có thể sử dụng một số lượng lớn hơn một kích thước nhất định và điều này cho phép họ giới hạn nó.

Tôi vẫn nghĩ rằng có thể có rất nhiều để đạt được bằng cách đơn giản bằng cách sử dụng một loại intvà một floatloại, có lý do cụ thể nào mà Java quyết định không đi theo con đường này không?


4
Để downvoters, tôi sẽ thêm rằng câu hỏi này được kết nối với một câu hỏi mà các nhà nghiên cứu trình biên dịch đang tìm cách trả lời .
rwong

Vì vậy, nếu bạn thêm vào một số bạn nghĩ rằng loại nên được thay đổi động? Tôi thậm chí có muốn loại thay đổi? Nếu số được khởi tạo là intUn Unknown alpha = a + b; Bạn có nhận được rằng sẽ có một chút khó khăn trên trình biên dịch. Tại sao điều này là cụ thể cho java?
paparazzo

@Paparazzi Có các ngôn ngữ lập trình và môi trường thực thi hiện có (trình biên dịch, trình thông dịch, v.v.) sẽ lưu trữ số nguyên chiều rộng động dựa trên giá trị thực của nó lớn như thế nào (ví dụ: kết quả của hoạt động bổ sung). Hậu quả là: mã được thực thi trên CPU trở nên phức tạp hơn; kích thước của số nguyên đó trở nên động; đọc một số nguyên chiều rộng động từ bộ nhớ có thể cần nhiều hơn một chuyến đi; cấu trúc (đối tượng) và mảng chứa số nguyên chiều rộng động bên trong các trường / phần tử của chúng cũng có thể có kích thước động.
rwong

1
@tofro Tôi không hiểu. Chỉ cần gửi số theo bất kỳ định dạng nào bạn thích: thập phân, nhị phân, v.v ... Nối tiếp là một mối quan tâm hoàn toàn trực giao.
vườn

1
@gardenhead Đó là trực giao, vâng, nhưng ... hãy xem xét trường hợp bạn muốn giao tiếp giữa một máy chủ được viết bằng Java và một máy khách được viết bằng C. Tất nhiên điều này có thể được giải quyết bằng cơ sở hạ tầng chuyên dụng. Ví dụ: có những thứ như developers.google.com/protatio-buffers . Nhưng đây là một búa tạ lớn cho hạt nhỏ chuyển số nguyên qua mạng. (Tôi biết, đây không phải là một lập luận mạnh mẽ ở đây, nhưng có lẽ là một điểm cần xem xét - thảo luận về các chi tiết nằm ngoài phạm vi của các bình luận).
Marco13

Câu trả lời:


16

Giống như rất nhiều khía cạnh của thiết kế ngôn ngữ, nó đánh đổi sự thanh lịch chống lại hiệu suất (không đề cập đến một số ảnh hưởng lịch sử từ các ngôn ngữ trước đó).

Lựa chọn thay thế

Chắc chắn có thể (và khá đơn giản) để tạo ra một ngôn ngữ lập trình chỉ có một loại số tự nhiên duy nhất nat. Hầu như tất cả các ngôn ngữ lập trình được sử dụng cho nghiên cứu học thuật (ví dụ PCF, Hệ thống F) đều có loại số duy nhất này, đây là giải pháp thanh lịch hơn, như bạn đã đoán. Nhưng thiết kế ngôn ngữ trong thực tế không chỉ là về sự thanh lịch; chúng ta cũng phải xem xét hiệu suất (mức độ mà hiệu suất được xem xét phụ thuộc vào ứng dụng dự định của ngôn ngữ). Việc thực hiện bao gồm cả những hạn chế về thời gian và không gian.

Không gian hạn chế

Để lập trình viên chọn số byte phía trước có thể tiết kiệm không gian trong các chương trình bị hạn chế bộ nhớ. Nếu tất cả các số của bạn sẽ được ít hơn 256, sau đó bạn có thể sử dụng 8 lần như nhiều bytenhư là longs, hoặc sử dụng các lưu trữ lưu cho các đối tượng phức tạp hơn. Nhà phát triển ứng dụng Java tiêu chuẩn không phải lo lắng về các ràng buộc này, nhưng chúng xuất hiện.

Hiệu quả

Ngay cả khi chúng tôi bỏ qua không gian, chúng tôi vẫn bị CPU ràng buộc, chỉ có các hướng dẫn hoạt động trên một số byte cố định (8 byte trên kiến ​​trúc 64 bit). Đó là phương tiện thậm chí còn cung cấp một 8-byte đơn longloại sẽ làm cho việc thực hiện của ngôn ngữ đơn giản hơn việc có loại số tự nhiên vô biên đáng kể, bằng việc có thể để lập bản đồ phép tính số học trực tiếp đến một đơn hướng dẫn CPU cơ bản. Nếu bạn cho phép lập trình viên sử dụng các số lớn tùy ý, thì một thao tác số học duy nhất phải được ánh xạ tới một chuỗi các lệnh máy phức tạp, điều này sẽ làm chậm chương trình. Đây là điểm (1) mà bạn đã đưa lên.

Các loại dấu phẩy động

Các cuộc thảo luận cho đến nay chỉ có số nguyên liên quan. Các kiểu dấu phẩy động là một con thú phức tạp, với ngữ nghĩa và trường hợp cạnh cực kỳ tinh tế. Như vậy, mặc dù chúng ta có thể dễ dàng thay thế int, long, short, và bytevới một đĩa đơn natloại, nó không phải là rõ ràng những gì loại số dấu chấm động thậm chí . Rõ ràng, chúng không phải là số thực, vì số thực không thể tồn tại trong ngôn ngữ lập trình. Chúng cũng không phải là những con số khá hợp lý (mặc dù nó rất đơn giản để tạo ra một loại hợp lý nếu muốn). Về cơ bản, IEEE đã quyết định một cách sắp xếp các số thực gần đúng và tất cả các ngôn ngữ (và lập trình viên) đã bị mắc kẹt với chúng kể từ đó.

Cuối cùng:

Có lẽ lập trình viên sẽ không muốn ai đó có thể sử dụng một số lượng lớn hơn một kích thước nhất định và điều này cho phép họ giới hạn nó.

Đây không phải là một lý do hợp lệ. Đầu tiên, tôi không thể nghĩ đến bất kỳ tình huống nào trong đó các loại có thể mã hóa giới hạn số một cách tự nhiên, chưa kể các cơ hội thấp về mặt thiên văn mà các giới hạn mà lập trình viên muốn thực thi sẽ tương ứng chính xác với kích thước của bất kỳ loại nguyên thủy nào.


2
chìa khóa thực sự cho việc chúng ta có phao là chúng ta có phần cứng dành riêng cho chúng
jk.

cũng mã hóa giới hạn số trong một loại hoàn toàn xảy ra trong các ngôn ngữ loại phụ thuộc và ở mức độ thấp hơn các ngôn ngữ khác, ví dụ như enums
jk.

3
Enums không tương đương với số nguyên. Enums chỉ là một chế độ sử dụng các loại tổng. Việc một số ngôn ngữ mã hóa trong suốt dưới dạng số nguyên là một lỗ hổng ngôn ngữ, không phải là một tính năng có thể khai thác.
vườn

1
Tôi không quen thuộc với Ada. Tôi có thể giới hạn số nguyên cho bất kỳ loại nào, ví dụ type my_type = int (7, 2343)?
vườn

1
Vâng. Cú pháp sẽ là: gõ my_type là phạm vi 7..2343
Devsman

9

Lý do rất đơn giản: hiệu quả . Theo nhiều cách.

  1. Các kiểu dữ liệu gốc: Các kiểu dữ liệu của ngôn ngữ càng gần với các kiểu dữ liệu cơ bản của phần cứng, thì ngôn ngữ đó càng được coi là hiệu quả. (Không phải theo nghĩa là các chương trình của bạn sẽ nhất thiết phải hiệu quả, nhưng theo nghĩa là bạn có thể, nếu bạn thực sự biết những gì bạn đang làm, hãy viết mã sẽ chạy hiệu quả như phần cứng có thể chạy nó.) Các loại dữ liệu được cung cấp bởi Java tương ứng với byte, từ, doublewords và quadwords của phần cứng phổ biến nhất hiện có. Đó là cách hiệu quả nhất để đi.

  2. Chi phí không chính đáng trên các hệ thống 32 bit: Nếu quyết định được đưa ra để ánh xạ mọi thứ thành kích thước 64 bit cố định, điều này sẽ áp dụng một hình phạt rất lớn đối với các kiến ​​trúc 32 bit cần nhiều chu kỳ xung nhịp hơn để thực hiện 64- hoạt động bit hơn hoạt động 32 bit.

  3. Lãng phí bộ nhớ: Có rất nhiều phần cứng không quá cầu kỳ về việc căn chỉnh bộ nhớ, (các kiến ​​trúc Intel x86 và x64 là ví dụ về điều đó,) vì vậy một mảng 100 byte trên phần cứng đó chỉ có thể chiếm 100 byte bộ nhớ. Tuy nhiên, nếu bạn không có byte nữa và thay vào đó bạn phải sử dụng một byte dài, cùng một mảng sẽ chiếm một thứ tự bộ nhớ lớn hơn. Và mảng byte là rất phổ biến.

  4. Tính kích thước số: Khái niệm của bạn về việc xác định kích thước của một số nguyên động tùy thuộc vào mức độ lớn của số được truyền vào là quá đơn giản; không có một điểm nào là "đi vào" một con số; việc tính toán số lượng lớn cần phải được thực hiện trong thời gian chạy, trên mỗi thao tác có thể yêu cầu kết quả của kích thước lớn hơn: mỗi lần bạn tăng một số, mỗi lần bạn thêm hai số, mỗi lần bạn nhân hai số số, v.v.

  5. Hoạt động trên các số có kích thước khác nhau: Sau đó, có số lượng kích thước khác nhau có khả năng trôi nổi trong bộ nhớ sẽ làm phức tạp tất cả các hoạt động: Ngay cả để chỉ so sánh hai số, trước tiên, thời gian chạy sẽ phải kiểm tra xem cả hai số có được so sánh giống nhau không kích thước và nếu không, thay đổi kích thước của cái nhỏ hơn để phù hợp với kích thước của cái lớn hơn.

  6. Các hoạt động yêu cầu kích thước toán hạng cụ thể: Các hoạt động bit khôn ngoan nhất định dựa vào số nguyên có kích thước cụ thể. Không có kích thước cụ thể được xác định trước, các hoạt động này sẽ phải được mô phỏng.

  7. Overhead of đa hình: Thay đổi kích thước của một số trong thời gian chạy về cơ bản có nghĩa là nó phải là đa hình. Đến lượt điều này có nghĩa là nó không thể là một nguyên thủy có kích thước cố định được phân bổ trên ngăn xếp, nó phải là một đối tượng, được phân bổ trên heap. Đó là không hiệu quả khủng khiếp. (Đọc lại số 1 ở trên.)


6

Để tránh lặp lại những điểm đã được thảo luận trong các câu trả lời khác, thay vào đó tôi sẽ cố gắng phác thảo nhiều quan điểm.

Từ quan điểm thiết kế ngôn ngữ

  • Chắc chắn có thể thiết kế và thực hiện ngôn ngữ lập trình và môi trường thực thi của nó sẽ tự động chứa kết quả của các hoạt động số nguyên không phù hợp với chiều rộng của máy.
  • Lựa chọn của nhà thiết kế ngôn ngữ là có nên biến các số nguyên có chiều rộng động như vậy thành loại số nguyên mặc định cho ngôn ngữ này hay không.
  • Tuy nhiên, nhà thiết kế ngôn ngữ phải xem xét các nhược điểm sau:
    • CPU sẽ phải thực thi nhiều mã hơn, mất nhiều thời gian hơn. Tuy nhiên, có thể tối ưu hóa cho trường hợp thường xuyên nhất trong đó số nguyên phù hợp với một từ máy. Xem đại diện con trỏ được gắn thẻ .
    • Kích thước của số nguyên đó trở nên động.
    • Đọc một số nguyên chiều rộng động từ bộ nhớ có thể cần nhiều hơn một chuyến đi.
    • Cấu trúc (đối tượng) và mảng chứa số nguyên chiều rộng động bên trong các trường / phần tử của chúng sẽ có kích thước tổng (chiếm) cũng là động.

Lý do lịch sử

Điều này đã được thảo luận trong bài viết Wikipedia về lịch sử của Java và cũng được thảo luận ngắn gọn trong câu trả lời của Marco13 .

Tôi sẽ chỉ ra rằng:

  • Các nhà thiết kế ngôn ngữ phải đấu tranh giữa một tư duy thẩm mỹ và thực dụng. Tư duy thẩm mỹ muốn thiết kế một ngôn ngữ không thiên về các vấn đề nổi tiếng, chẳng hạn như tràn số nguyên. Tư duy thực dụng nhắc nhở người thiết kế rằng ngôn ngữ lập trình cần phải đủ tốt để thực hiện các ứng dụng phần mềm hữu ích và tương tác với các phần mềm khác được triển khai bằng các ngôn ngữ khác nhau.
  • Các ngôn ngữ lập trình có ý định chiếm thị phần từ các ngôn ngữ lập trình cũ có thể có xu hướng thực dụng hơn. Một hậu quả có thể xảy ra là họ sẵn sàng kết hợp hoặc mượn các cấu trúc và phong cách lập trình hiện có từ các ngôn ngữ cũ hơn.

Lý do hiệu quả

Khi nào thì hiệu quả quan trọng?

  • Khi bạn có ý định quảng cáo một ngôn ngữ lập trình là phù hợp để phát triển các ứng dụng quy mô lớn.
  • Khi bạn cần làm việc trên hàng triệu và hàng tỷ vật phẩm nhỏ, trong đó mỗi bit hiệu quả sẽ tăng lên.
  • Khi bạn cần cạnh tranh với một ngôn ngữ lập trình khác, ngôn ngữ của bạn cần thực hiện một cách dứt khoát - nó không cần phải là tốt nhất, nhưng chắc chắn nó sẽ giúp đạt được hiệu suất tốt nhất.

Hiệu quả lưu trữ (trong bộ nhớ hoặc trên đĩa)

  • Bộ nhớ máy tính đã từng là một nguồn tài nguyên khan hiếm. Ngày xưa, kích thước của dữ liệu ứng dụng có thể được xử lý bằng máy tính bị giới hạn bởi dung lượng bộ nhớ máy tính, mặc dù có thể tranh cãi về việc sử dụng lập trình thông minh (sẽ tốn nhiều chi phí hơn để thực hiện).

Hiệu quả thực thi (trong CPU, hoặc giữa CPU và bộ nhớ)

  • Đã thảo luận trong câu trả lời của người làm vườn .
  • Nếu một chương trình cần xử lý các mảng rất lớn với số lượng nhỏ được lưu trữ liên tiếp, hiệu quả của biểu diễn trong bộ nhớ có ảnh hưởng trực tiếp đến hiệu năng thực thi của nó, bởi vì lượng dữ liệu lớn khiến thông lượng giữa CPU và bộ nhớ trở thành nút cổ chai. Trong trường hợp này, việc đóng gói dữ liệu dày đặc hơn có nghĩa là một đường truyền bộ đệm duy nhất có thể truy xuất nhiều mẩu dữ liệu hơn.
  • Tuy nhiên, lý do này không áp dụng nếu dữ liệu không được lưu trữ hoặc xử lý liên tiếp.

Nhu cầu về ngôn ngữ lập trình để cung cấp một sự trừu tượng cho các số nguyên nhỏ, ngay cả khi bị giới hạn trong các bối cảnh cụ thể

  • Những nhu cầu này thường phát sinh trong việc phát triển các thư viện phần mềm, bao gồm các thư viện tiêu chuẩn của ngôn ngữ. Dưới đây là một số trường hợp như vậy.

Khả năng tương tác

  • Thông thường, các ngôn ngữ lập trình cấp cao hơn cần tương tác với hệ điều hành hoặc các phần mềm (thư viện) được viết bằng các ngôn ngữ cấp thấp khác. Các ngôn ngữ cấp thấp hơn này thường giao tiếp bằng cách sử dụng "cấu trúc" , đây là một đặc điểm kỹ thuật cứng nhắc của bố cục bộ nhớ của bản ghi bao gồm các trường thuộc các loại khác nhau.
  • Ví dụ: ngôn ngữ cấp cao hơn có thể cần xác định rằng một hàm ngoại nhất định chấp nhận một charmảng có kích thước 256. (Ví dụ.)
  • Một số trừu tượng được sử dụng bởi các hệ điều hành và hệ thống tệp yêu cầu sử dụng các luồng byte.
  • Một số ngôn ngữ lập trình chọn cung cấp các hàm tiện ích (ví dụ BitConverter) để giúp đóng gói và giải nén các số nguyên hẹp thành luồng bit và luồng byte.
  • Trong những trường hợp này, các kiểu số nguyên hẹp hơn không cần phải là kiểu nguyên thủy được xây dựng trong ngôn ngữ. Thay vào đó, chúng có thể được cung cấp như một loại thư viện.

Xử lý chuỗi

  • Có những ứng dụng có mục đích thiết kế chính là thao tác chuỗi. Do đó, hiệu quả xử lý chuỗi rất quan trọng đối với các loại ứng dụng đó.

Xử lý định dạng tệp

  • Rất nhiều định dạng tập tin được thiết kế với tư duy giống như C. Như vậy, việc sử dụng các trường chiều rộng hẹp là phổ biến.

Mong muốn, chất lượng phần mềm và trách nhiệm của lập trình viên

  • Đối với nhiều loại ứng dụng, tự động mở rộng số nguyên thực sự không phải là một tính năng mong muốn. Không phải là bão hòa cũng không phải là bao quanh (mô đun).
  • Nhiều loại ứng dụng sẽ được hưởng lợi từ thông số kỹ thuật rõ ràng của lập trình viên về các giá trị được phép lớn nhất trong các điểm quan trọng khác nhau trong phần mềm, chẳng hạn như ở cấp API.

Hãy xem xét các kịch bản sau đây.

  • API phần mềm chấp nhận yêu cầu JSON. Yêu cầu chứa một loạt các yêu cầu con. Toàn bộ yêu cầu JSON có thể được nén bằng thuật toán Deflate.
  • Một người dùng độc hại tạo một yêu cầu JSON chứa một tỷ yêu cầu con. Tất cả các yêu cầu con là giống hệt nhau; người dùng độc hại dự định hệ thống sẽ ghi một số chu kỳ CPU làm công việc vô ích. Do nén, các yêu cầu con giống hệt nhau này được nén với tổng kích thước rất nhỏ.
  • Rõ ràng là giới hạn được xác định trước về kích thước nén của dữ liệu là không đủ. Thay vào đó, API cần áp đặt giới hạn được xác định trước đối với số lượng yêu cầu con có thể có trong đó và / hoặc giới hạn được xác định trước đối với kích thước bị lệch của dữ liệu.

Thông thường, phần mềm có thể mở rộng một cách an toàn nhiều đơn đặt hàng cường độ phải được thiết kế cho mục đích đó, với độ phức tạp tăng dần. Nó không tự động đến ngay cả khi vấn đề tràn số nguyên được loại bỏ. Điều này đi đến một vòng tròn đầy đủ trả lời cho quan điểm thiết kế ngôn ngữ: thông thường, phần mềm từ chối thực hiện công việc khi xảy ra tràn số nguyên ngoài ý muốn (bằng cách ném lỗi hoặc ngoại lệ) tốt hơn phần mềm tự động tuân thủ các hoạt động lớn về mặt thiên văn.

Điều này có nghĩa là quan điểm của OP,

Tại sao cần phải có một người đặt bao nhiêu byte nên được sử dụng cho một giá trị nguyên thủy?

không đúng Lập trình viên nên được cho phép, và đôi khi được yêu cầu, để chỉ định cường độ tối đa mà giá trị nguyên có thể lấy, tại các phần quan trọng của phần mềm. Như câu trả lời của người làm vườn chỉ ra, các giới hạn tự nhiên được áp đặt bởi các loại nguyên thủy không hữu ích cho mục đích này; ngôn ngữ phải cung cấp các cách để các lập trình viên tuyên bố cường độ và thực thi các giới hạn đó.


2

Tất cả đều xuất phát từ phần cứng.

Một byte là đơn vị bộ nhớ có địa chỉ nhỏ nhất trên hầu hết các phần cứng.

Mỗi loại bạn vừa đề cập được xây dựng từ một số nhiều byte.

Một byte là 8 bit. Với điều đó, bạn có thể thể hiện 8 booleans nhưng bạn không thể tìm kiếm từng cái một. Bạn địa chỉ 1, bạn đang giải quyết tất cả 8.

Và nó đã từng đơn giản như vậy nhưng sau đó chúng tôi đã đi từ một chiếc xe buýt 8 bit đến một chiếc xe buýt 16, 32 và bây giờ là 64 bit.

Điều đó có nghĩa là trong khi chúng ta vẫn có thể giải quyết ở mức byte, chúng ta không thể truy xuất một byte từ bộ nhớ nữa mà không nhận được các byte lân cận.

Đối mặt với phần cứng này, các nhà thiết kế ngôn ngữ đã chọn cho phép chúng tôi chọn các loại cho phép chúng tôi chọn các loại phù hợp với phần cứng.

Bạn có thể tuyên bố rằng một chi tiết như vậy có thể và nên được trừu tượng hóa đặc biệt là trong một ngôn ngữ nhằm chạy trên bất kỳ phần cứng nào. Điều này sẽ có những lo ngại về hiệu suất nhưng bạn có thể đúng. Nó đã không xảy ra theo cách đó.

Java thực sự cố gắng để làm điều này. Byte được tự động thăng cấp lên Ints. Một thực tế sẽ khiến bạn phát điên khi lần đầu tiên bạn cố gắng thực hiện bất kỳ công việc chuyển bit nghiêm trọng nào trong đó.

Vậy tại sao nó không hoạt động tốt?

Điểm bán hàng lớn của Java trở lại theo cách mà bạn có thể ngồi xuống với một thuật toán C tốt đã biết, nhập nó vào Java và với các điều chỉnh nhỏ, nó sẽ hoạt động. Và C rất gần với phần cứng.

Giữ kích thước đi và trừu tượng hóa ra khỏi các loại tích phân chỉ không hoạt động cùng nhau.

Vì vậy, họ có thể có. Họ chỉ không làm thế.

Có lẽ lập trình viên sẽ không muốn ai đó có thể sử dụng một số lượng lớn hơn một kích thước nhất định và điều này cho phép họ giới hạn nó.

Đây là suy nghĩ hợp lệ. Có những phương pháp để làm điều này. Các chức năng kẹp cho một. Một ngôn ngữ có thể đi xa đến mức nướng các giới hạn tùy ý vào các loại của chúng. Và khi các giới hạn đó được biết tại thời điểm biên dịch sẽ cho phép tối ưu hóa trong cách các số đó được lưu trữ.

Java không phải là ngôn ngữ đó.


" Một ngôn ngữ có thể đi xa đến mức nướng các giới hạn tùy ý vào các kiểu của chúng " Và thực sự Pascal có một dạng này với các kiểu phụ.
Peter Taylor

1

Có khả năng, một lý do quan trọng tại sao các loại này tồn tại trong Java là đơn giản và cực kỳ phi kỹ thuật:

C và C ++ cũng có những loại này!

Mặc dù thật khó để đưa ra bằng chứng cho thấy đây là lý do, nhưng có ít nhất một số bằng chứng mạnh mẽ: Đặc tả ngôn ngữ Oak (Phiên bản 0.2) có đoạn văn sau:

3.1 Các loại số nguyên

Các số nguyên trong ngôn ngữ Oak tương tự như trong C và C ++, với hai trường hợp ngoại lệ: tất cả các loại số nguyên đều độc lập với máy và một số định nghĩa truyền thống đã được thay đổi để phản ánh các thay đổi trên thế giới kể từ khi C được giới thiệu. Bốn loại số nguyên có độ rộng 8, 16, 32 và 64 bit và được ký trừ khi có tiền tố bởiunsigned sửa đổi.

Vì vậy, câu hỏi có thể sôi lên:

Tại sao ngắn, int và dài được phát minh trong C?

Tôi không chắc câu trả lời cho câu hỏi thư có thỏa đáng trong bối cảnh câu hỏi được hỏi ở đây không. Nhưng kết hợp với các câu trả lời khác ở đây, có thể thấy rõ rằng có thể có ích khi có các loại này (bất kể sự tồn tại của chúng trong Java chỉ là một di sản từ C / C ++).

Những lý do quan trọng nhất tôi có thể nghĩ đến là

  • Một byte là đơn vị bộ nhớ có địa chỉ nhỏ nhất (như CandiedOrange đã đề cập). A bytelà khối dữ liệu xây dựng cơ bản, có thể được đọc từ một tệp hoặc qua mạng. Một số đại diện rõ ràng về điều này nên tồn tại (và nó tồn tại trong hầu hết các ngôn ngữ, ngay cả khi đôi khi nó được ngụy trang).

  • Trong thực tế, trong thực tế, sẽ có ý nghĩa khi biểu diễn tất cả các trường và biến cục bộ bằng một loại duy nhất và gọi loại này int. Có một câu hỏi liên quan về vấn đề đó trên stackoverflow: Tại sao API Java sử dụng int thay vì ngắn hoặc byte? . Như tôi đã đề cập trong câu trả lời của mình ở đó, một lời biện minh cho việc có các loại nhỏ hơn ( byteshort) là bạn có thể tạo các mảng của các loại này: Java có một đại diện của các mảng vẫn khá "gần với phần cứng". Ngược lại với các ngôn ngữ khác (và trái ngược với mảng các đối tượng, như một Integer[n]mảng), một int[n]mảng không phải là một tập hợp các tham chiếu trong đó các giá trị nằm rải rác trong heap. Thay vào đó, nó sẽtrong thực tế là một khối liên tiếpn*4byte - một đoạn bộ nhớ với kích thước và bố cục dữ liệu đã biết. Khi bạn có lựa chọn lưu trữ 1000 byte trong một tập hợp các đối tượng giá trị nguyên có kích thước tùy ý hoặc trong một byte[1000](mất 1000 byte), thì sau này thực sự có thể tiết kiệm một số bộ nhớ. (Một số ưu điểm khác của điều này có thể tinh tế hơn và chỉ trở nên rõ ràng khi giao tiếp Java với các thư viện gốc)


Về những điểm mà bạn đặc biệt hỏi về:

Không thể xác định kích thước một cách linh hoạt tùy thuộc vào số lượng lớn được chuyển vào là bao nhiêu?

Tự động thiết lập kích thước của dữ liệu có nghĩa là nó cũng cần có khả năng thay đổi linh hoạt. Điều này có khả năng gây ra vấn đề hiệu suất?

Có thể có khả năng tự động đặt kích thước của các biến, nếu người ta cân nhắc thiết kế một ngôn ngữ lập trình hoàn toàn mới từ đầu. Tôi không phải là một chuyên gia về xây dựng trình biên dịch, nhưng nghĩ rằng thật khó để có thể thu thập các bộ sưu tập các loại thay đổi linh hoạt - đặc biệt, khi bạn có một ngôn ngữ được gõ mạnh . Vì vậy, nó có thể sẽ sôi sục với tất cả các số được lưu trữ trong một "loại dữ liệu số chính xác chung, tùy ý", chắc chắn sẽ có tác động hiệu suất. Tất nhiên, có những ngôn ngữ lập trình được gõ mạnh và / hoặc cung cấp các loại số có kích thước tùy ý, nhưng tôi không nghĩ rằng có một ngôn ngữ lập trình có mục đích chung thực sự đi theo cách này.


Ghi chú bên:

  • Bạn có thể đã tự hỏi về công cụ unsignedsửa đổi đã được đề cập trong thông số Oak. Trên thực tế, nó cũng chứa một nhận xét: " unsignedchưa được thực hiện; nó có thể không bao giờ." . Và họ đã đúng.

  • Ngoài việc tự hỏi tại sao C / C ++ có các loại số nguyên khác nhau này, bạn có thể tự hỏi tại sao chúng lại làm chúng rối tung khủng khiếp đến mức bạn không bao giờ biết có bao nhiêu bit int. Các biện minh cho điều này thường liên quan đến hiệu suất, và có thể được tìm kiếm ở nơi khác.


0

Nó chắc chắn cho thấy bạn chưa được dạy về hiệu suất và kiến ​​trúc.

  • Đầu tiên, không phải bộ xử lý nào cũng có thể xử lý các loại lớn, vì vậy, bạn cần biết những hạn chế và làm việc với điều đó.
  • Thứ hai, loại nhỏ hơn có nghĩa là hiệu suất cao hơn khi thực hiện các hoạt động.
  • Ngoài ra, vấn đề kích thước, nếu bạn phải lưu trữ dữ liệu trong tệp hoặc cơ sở dữ liệu, kích thước sẽ ảnh hưởng đến cả hiệu suất và kích thước cuối cùng của tất cả dữ liệu, giả sử bạn có một bảng có 15 cột và bạn kết thúc bằng một số cột hàng triệu hồ sơ. Sự khác biệt giữa chọn kích thước nhỏ như cần thiết cho mỗi cột hoặc chỉ chọn loại lớn nhất sẽ là sự khác biệt của Gigs dữ liệu và thời gian có thể có trong việc thực hiện các hoạt động.
  • Ngoài ra, nó được áp dụng trong các tính toán phức tạp, trong đó kích thước của dữ liệu đang được xử lý sẽ có tác động lớn, như trong các trò chơi chẳng hạn.

Bỏ qua tầm quan trọng của kích thước dữ liệu luôn đạt hiệu suất, bạn phải sử dụng càng nhiều tài nguyên cần thiết, nhưng không còn nữa, luôn luôn!

Đó là sự khác biệt giữa một chương trình hoặc hệ thống thực hiện những điều thực sự đơn giản và không hiệu quả đáng kinh ngạc đòi hỏi nhiều nguồn lực và làm cho việc sử dụng hệ thống đó thực sự tốn kém; hoặc một hệ thống làm rất nhiều, nhưng chạy nhanh hơn các hệ thống khác và thực sự rẻ để chạy.


0

Có một vài lý do tốt

(1) trong khi việc lưu trữ một biến byte trong một câu dài là không đáng kể, việc lưu trữ hàng triệu trong một mảng là rất đáng kể.

(2) Số học "bản địa phần cứng" dựa trên kích thước số nguyên cụ thể có thể hiệu quả hơn rất nhiều và đối với một số thuật toán trên một số nền tảng, điều đó có thể quan trọng.

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.