1. Đánh máy
Các biến kiểu nguyên thủy (ngoại trừ kiểu boolean
) được sử dụng để lưu trữ các loại số khác nhau. Mặc dù các loại biến không bao giờ thay đổi, nhưng có một nơi mà bạn có thể chuyển đổi từ loại này sang loại khác. Và nơi đó là sự phân công .
Các biến thuộc các loại khác nhau có thể được gán cho nhau. Khi bạn thực hiện điều này, giá trị của một biến thuộc loại này sẽ được chuyển đổi thành giá trị của loại khác và được gán cho biến thứ hai. Về vấn đề này, chúng ta có thể xác định hai loại chuyển đổi loại: mở rộng và thu hẹp.
Mở rộng giống như chuyển một giá trị từ giỏ nhỏ sang giỏ lớn: thao tác này diễn ra liền mạch và không gây khó khăn. Việc thu hẹp xảy ra khi bạn chuyển một giá trị từ giỏ lớn sang giỏ nhỏ: có thể không đủ chỗ và bạn sẽ phải vứt bỏ thứ gì đó.
Dưới đây là các loại, được sắp xếp theo kích thước giỏ:
2. Mở rộng chuyển đổi loại hình
Thường thì cần phải gán một biến kiểu số này cho một biến kiểu số khác. Làm thế nào để bạn làm điều đó?
Java có 4 kiểu số nguyên:
Kiểu | Kích cỡ |
---|---|
byte |
1 byte |
short |
2 bytes |
int |
4 bytes |
long |
8 bytes |
Biến được lưu trữ trong các giỏ nhỏ hơn luôn có thể được gán cho các biến được lưu trữ trong các giỏ lớn hơn.
int
và các biến có thể dễ dàng được gán cho short
các biến. và các biến có thể được gán cho các biến. Và các biến có thể được gán cho các biến.byte
long
short
byte
int
byte
short
Ví dụ:
Mã số | Sự miêu tả |
---|---|
|
Mã này sẽ biên dịch tốt. |
Việc chuyển đổi như vậy, từ loại nhỏ hơn sang loại lớn hơn, được gọi là chuyển đổi loại mở rộng .
Còn số thực thì sao?
Với họ, mọi thứ đều giống nhau — kích thước quan trọng:
Kiểu | Kích cỡ |
---|---|
float |
4 bytes |
double |
8 bytes |
float
các biến có thể được gán cho double
các biến mà không gặp vấn đề gì. Nhưng mọi thứ thú vị hơn với các kiểu số nguyên.
Bạn có thể gán bất kỳ biến số nguyên nào cho một float
biến. Ngay cả long
loại dài 8 byte. Và bạn có thể gán bất cứ thứ gì bạn muốn — bất kỳ biến nguyên hoặc float
biến nào — cho một double
biến:
Mã số | Ghi chú |
---|---|
|
|
Lưu ý rằng việc chuyển đổi sang kiểu thực có thể dẫn đến mất độ chính xác do thiếu các chữ số có nghĩa.
Khi chuyển đổi từ số nguyên sang số dấu phẩy động, phần thứ tự thấp hơn của số có thể bị loại bỏ. Nhưng vì các số phân số được hiểu là lưu trữ các giá trị gần đúng, nên các phép gán như vậy được cho phép.
3. Thu hẹp loại chuyển đổi
Còn những khả năng khác thì sao? Nếu bạn cần gán long
giá trị cho một int
biến thì sao?
Hãy tưởng tượng một biến như một cái giỏ. Chúng tôi có các giỏ có kích thước khác nhau: 1, 2, 4 và 8 byte. Không có vấn đề gì khi chuyển táo từ giỏ nhỏ hơn sang giỏ lớn hơn. Nhưng khi chuyển từ giỏ lớn hơn sang giỏ nhỏ hơn, một số quả táo có thể bị mất.
Sự chuyển đổi này — từ loại lớn hơn sang loại nhỏ hơn — được gọi là chuyển đổi loại thu hẹp . Khi thực hiện thao tác gán như thế này, một phần của số có thể không khớp với biến mới và do đó có thể bị loại bỏ.
Khi thu hẹp một loại, chúng ta phải thông báo rõ ràng với trình biên dịch rằng chúng ta không mắc lỗi, rằng chúng ta đang cố tình loại bỏ một phần của số. Toán tử typecast được sử dụng cho việc này. Nó là một tên loại trong ngoặc đơn .
Trong những tình huống như vậy, trình biên dịch Java yêu cầu lập trình viên chỉ định toán tử định kiểu. Nói chung, nó trông như thế này:
(type) expression
Ví dụ:
Mã số | Sự miêu tả |
---|---|
|
Mỗi lần toán tử typecast phải được chỉ định rõ ràng |
Ở đây a
bằng với 1
, và có lẽ toán tử typecast có vẻ như quá mức cần thiết. Nhưng nếu a
lớn hơn thì sao?
Mã số | Sự miêu tả |
---|---|
|
|
Một triệu hoàn toàn phù hợp với a long
và thành một int
. Nhưng khi gán một triệu cho một short
biến, hai byte đầu tiên sẽ bị loại bỏ và chỉ hai byte cuối cùng được giữ lại. Và khi gán cho a byte
, thứ duy nhất còn lại là byte cuối cùng.
Cách các số được sắp xếp trong bộ nhớ:
Kiểu | ký hiệu nhị phân | Ký hiệu thập phân |
---|---|---|
int |
0b 00000000 00001111 01000010 01000000 | 1000000 |
short |
0b 01000010 01000000 | 16.960 |
byte |
0b 01000000 | 64 |
char
kiểu
A char
, giống như a short
, chiếm hai byte, nhưng để chuyển đổi một byte này sang byte khác, bạn luôn cần sử dụng toán tử định kiểu. Vấn đề ở đây là short
loại được ký và có thể chứa các giá trị từ -32,768
đến +32,767
, nhưng char
loại không được ký và có thể chứa các giá trị từ 0
đến 65,535
.
Số âm không thể được lưu trữ trong tệp char
, nhưng chúng có thể được lưu trữ trong tệp short
. Và a short
không thể lưu trữ các số lớn hơn 32,767
, nhưng các số đó có thể được lưu trữ trong a char
.
4. Loại biểu thức
Điều gì sẽ xảy ra nếu các biến thuộc các loại khác nhau được sử dụng trong cùng một biểu thức? Theo logic, chúng tôi hiểu rằng trước tiên chúng cần được chuyển đổi thành một loại chung. Nhưng cái nào?
Đối với cái lớn hơn, tất nhiên.
Java luôn chuyển đổi sang loại lớn hơn. Nói một cách đại khái, một trong các loại đầu tiên được mở rộng và chỉ sau đó thao tác mới được thực hiện bằng cách sử dụng các giá trị cùng loại.
Nếu an int
và a long
tham gia vào một biểu thức, giá trị của int
sẽ được chuyển đổi thành a long
và chỉ khi đó thao tác mới tiếp tục:
Mã số | Sự miêu tả |
---|---|
|
a sẽ được mở rộng thành a long và sau đó phép cộng sẽ xảy ra. |
số dấu phẩy động
Nếu một số nguyên và một số dấu phẩy động ( float
hoặc double
) có liên quan trong một biểu thức, thì số nguyên đó sẽ được chuyển đổi thành một số dấu phẩy động ( float
hoặc double
), và chỉ khi đó thao tác mới được thực hiện.
Nếu thao tác liên quan đến a float
và a double
, thì a float
sẽ được chuyển đổi thành a double
. Đó là thực sự mong đợi.
, và các loại luôn được chuyển đổi thành khi byte
tương tác với nhau. Có một lý do chính đáng tại sao loại này được coi là loại số nguyên tiêu chuẩn.short
char
int
int
Nếu bạn nhân a byte
với a short
, bạn sẽ nhận được một int
. Nếu bạn nhân a byte
với a byte
, bạn sẽ nhận được một int
. Ngay cả khi bạn thêm a byte
và a byte
, bạn vẫn nhận được một int
.
Cái này có một vài nguyên nhân. Ví dụ:
Mã số | Sự miêu tả |
---|---|
|
110 * 120 is 13,200 , lớn hơn một chút so với giá trị tối đa của byte loại:127 |
|
110 + 120 is 230 , cũng lớn hơn một chút so với giá trị tối đa của byte loại:127 |
Nói chung, khi nhân một số 8 bit (1 byte) với một số 8 bit (1 byte), ta được một số chiếm 16 bit (2 byte)
Do đó, tất cả các hoạt động với các loại số nguyên nhỏ hơn int
luôn được chuyển đổi ngay lập tức thành int
s. Và điều đó có nghĩa là nếu bạn muốn lưu trữ kết quả của phép tính trong một biến có loại nhỏ hơn int
, thì bạn sẽ luôn cần chỉ định rõ ràng toán tử định kiểu.
Ví dụ:
Mã số | Sự miêu tả |
---|---|
|
Biểu byte * byte thức sẽ là mộtint |
|
Biểu byte + byte thức sẽ là mộtint |
|
Biểu byte + int thức sẽ là một int Biểu thức theo nghĩa đen là một int . |
5. Một sắc thái quan trọng
Toán tử typecast có mức độ ưu tiên khá cao.
Điều đó có nghĩa là nếu một biểu thức chứa, chẳng hạn như phép cộng và toán tử định kiểu, thì phép định kiểu sẽ được thực hiện trước phép cộng.
Ví dụ:
Mã số | Sự miêu tả |
---|---|
|
Toán tử typecast sẽ chỉ được áp dụng cho a biến đã là một biến byte . Mã này sẽ không biên dịch. |
|
Đây là cách chính xác. |
Nếu bạn muốn chuyển đổi toàn bộ biểu thức thành một kiểu cụ thể chứ không chỉ một thành phần của biểu thức, thì hãy đặt toàn bộ biểu thức trong dấu ngoặc đơn và đặt toán tử định kiểu ở phía trước.
GO TO FULL VERSION