CodeGym /Blog Java /Ngẫu nhiên /Mở rộng và thu hẹp các kiểu nguyên thủy

Mở rộng và thu hẹp các kiểu nguyên thủy

Xuất bản trong nhóm
CHÀO! Khi bạn tiến bộ qua CodeGym, bạn đã nhiều lần gặp phải các kiểu nguyên thủy. Dưới đây là danh sách ngắn những gì chúng ta biết về họ:
  1. Chúng không phải là đối tượng và đại diện cho một giá trị được lưu trữ trong bộ nhớ
  2. Có một số loại
    • Số nguyên: byte , short , int , long
    • Số dấu phẩy động (phân số): floatdouble
    • Giá trị logic: boolean
    • Các giá trị tượng trưng (để biểu thị các chữ cái và số): char
  3. Mỗi loại có phạm vi giá trị riêng:

loại nguyên thủy Kích thước trong bộ nhớ Phạm vi giá trị
byte 8 bit -128 đến 127
ngắn 16 bit -32768 đến 32767
than 16 bit 0 đến 65536
int 32 bit -2147483648 đến 2147483647
dài 64 bit -9223372036854775808 đến 9223372036854775807
trôi nổi 32 bit (2 mũ -149) đến ((2 - (2 mũ -23)) * 2 mũ 127)
gấp đôi 64 bit (-2 mũ 63) đến ((2 mũ 63) - 1)
boolean 8 (khi được sử dụng trong mảng), 32 (nếu không được sử dụng trong mảng) đúng hay sai
Nhưng ngoài việc có các giá trị khác nhau, chúng còn khác nhau về dung lượng mà chúng chiếm trong bộ nhớ. Một int chiếm nhiều hơn một byte. Và một dài lớn hơn một ngắn. Dung lượng bộ nhớ mà người nguyên thủy chiếm giữ có thể được so sánh với búp bê lồng nhau của Nga: Mở rộng và thu hẹp các loại nguyên thủy - 2 Mỗi búp bê lồng nhau đều có sẵn không gian bên trong. Búp bê làm tổ càng lớn thì càng có nhiều không gian. Một con búp bê làm tổ lớn ( dài ) sẽ dễ dàng chứa một con búp bê nhỏ hơn int . Nó dễ dàng phù hợp và bạn không cần phải làm gì khác. Trong Java, khi làm việc với nguyên thủy, điều này được gọi là chuyển đổi ngầm định. Hay nói cách khác, nó được gọi là mở rộng.

Mở rộng trong Java

Đây là một ví dụ đơn giản về chuyển đổi mở rộng:

public class Main {

   public static void main(String[] args) {
      
       int bigNumber = 10000000;

       byte littleNumber = 16;

       bigNumber = littleNumber;
       System.out.println(bigNumber);
   }
}
Ở đây chúng tôi gán một giá trị byte cho một biến int . Việc gán thành công mà không gặp bất kỳ sự cố nào: giá trị được lưu trữ trong một byte chiếm ít bộ nhớ hơn giá trị mà một int có thể chứa. Con búp bê làm tổ nhỏ (giá trị byte) dễ dàng nằm gọn bên trong con búp bê làm tổ lớn ( biến int ). Sẽ là một vấn đề khác nếu bạn cố gắng làm ngược lại, tức là đặt một giá trị lớn vào một biến mà phạm vi của nó không thể chứa được loại dữ liệu lớn như vậy. Với những con búp bê làm tổ thực sự, con số đơn giản là không phù hợp. Với Java, nó có thể, nhưng có nhiều sắc thái. Hãy thử đặt một int vào một biến ngắn :

public static void main(String[] args) {

   int bigNumber = 10000000;
  
   short littleNumber = 1000;

   littleNumber = bigNumber;// Error!
   System.out.println(bigNumber);
}
Lỗi! Trình biên dịch hiểu rằng bạn đang cố gắng làm điều gì đó bất thường bằng cách nhét một con búp bê lồng nhau lớn ( int ) vào trong một con búp bê nhỏ ( short ). Trong trường hợp này, lỗi biên dịch là một cảnh báo từ trình biên dịch: "Này, bạn có hoàn toàn chắc chắn rằng bạn muốn làm điều này không?" Nếu bạn chắc chắn, thì bạn nói với trình biên dịch: "Mọi thứ đều ổn. Tôi biết mình đang làm gì!" Quá trình này được gọi là chuyển đổi loại rõ ràng hoặc thu hẹp.

Thu hẹp trong Java

Để thực hiện chuyển đổi thu hẹp, bạn cần chỉ rõ loại mà bạn muốn chuyển đổi giá trị của mình sang. Nói cách khác, bạn cần trả lời câu hỏi của trình biên dịch: "Chà, bạn muốn đặt con búp bê làm tổ lớn này vào cái nào trong số những con búp bê làm tổ nhỏ này?" Trong trường hợp của chúng tôi, nó trông như thế này:

public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = (short) bigNumber;
   System.out.println(littleNumber);
}
Chúng tôi chỉ ra rõ ràng rằng chúng tôi muốn đặt một int vào một biến ngắn và chúng tôi sẽ chịu trách nhiệm. Thấy rằng một loại hẹp hơn đã được chỉ định rõ ràng, trình biên dịch sẽ thực hiện chuyển đổi. Kết quả là gì? Đầu ra bảng điều khiển: -27008 Điều đó hơi bất ngờ. Tại sao chính xác chúng ta đã nhận được điều đó? Trên thực tế, tất cả đều rất đơn giản. Ban đầu, giá trị là 10000000. Nó được lưu trữ trong một biến int , chiếm 32 bit. Đây là đại diện nhị phân của nó:
Mở rộng và thu hẹp các loại nguyên thủy - 3
Chúng tôi viết giá trị này vào một biến ngắn , chỉ có thể lưu trữ 16 bit! Theo đó, chỉ 16 bit đầu tiên của số của chúng tôi sẽ được chuyển đến đó. Phần còn lại sẽ bị loại bỏ. Kết quả là biến short nhận giá trị như sau
Mở rộng và thu hẹp các loại nguyên thủy - 4
mà ở dạng thập phân bằng -27008 Đó là lý do tại sao trình biên dịch yêu cầu bạn "xác nhận" bằng cách chỉ ra một chuyển đổi thu hẹp rõ ràng sang một loại cụ thể. Đầu tiên, điều này cho thấy rằng bạn đang chịu trách nhiệm về kết quả. Và thứ hai, nó cho trình biên dịch biết cần phân bổ bao nhiêu dung lượng khi quá trình chuyển đổi diễn ra. Xét cho cùng, trong ví dụ trước, nếu chúng ta gán một giá trị int cho biến byte thay vì short , thì chúng ta sẽ chỉ có 8 bit tùy ý sử dụng chứ không phải 16 và kết quả sẽ khác. Các loại phân số ( floatdouble ) có quy trình riêng để thu hẹp chuyển đổi. Nếu bạn thử chuyển một số nhóm thành một loại số nguyên, phần phân số sẽ bị loại bỏ.

public static void main(String[] args) {

   double d = 2.7;

   long x = (int) d;
   System.out.println(x);
}
Đầu ra bảng điều khiển: 2

than

Bạn đã biết rằng char được sử dụng để hiển thị các ký tự riêng lẻ.

public static void main(String[] args) {

   char c = '!';
   char z = 'z';
   char i = '8';
  
}
Nhưng loại dữ liệu này có một số tính năng quan trọng cần hiểu. Hãy xem lại bảng phạm vi giá trị:
loại nguyên thủy Kích thước trong bộ nhớ Phạm vi giá trị
byte 8 bit -128 đến 127
ngắn 16 bit -32768 đến 32767
than 16 bit 0 đến 65536
int 32 bit -2147483648 đến 2147483647
dài 64 bit -9223372036854775808 đến 9223372036854775807
trôi nổi 32 bit (2 mũ -149) đến ((2 - (2 mũ -23)) * 2 mũ 127)
gấp đôi 64 bit (-2 mũ 63) đến ((2 mũ 63) - 1)
boolean 8 (khi được sử dụng trong mảng), 32 (nếu không được sử dụng trong mảng) đúng hay sai
Phạm vi từ 0 đến 65536 được chỉ định cho loại char . Nhưng điều đó có nghĩa gì? Xét cho cùng, một ký tự không chỉ đại diện cho các số mà còn cả các chữ cái, dấu chấm câu… Vấn đề là trong Java các giá trị ký tự được lưu trữ ở định dạng Unicode. Chúng ta đã gặp Unicode trong một trong các bài học trước. Bạn có thể nhớ rằng Unicode là một tiêu chuẩn mã hóa ký tự bao gồm các ký hiệu của hầu hết các ngôn ngữ viết trên thế giới. Nói cách khác, đó là một danh sách các mã đặc biệt đại diện cho gần như mọi ký tự trong bất kỳ ngôn ngữ nào. Toàn bộ bảng Unicode rất lớn, và tất nhiên, bạn không cần phải học thuộc lòng. Đây là một phần nhỏ của nó: Mở rộng và thu hẹp các loại nguyên thủy - 5 Điều chính là hiểu cách các ký tự được lưu trữ và nhớ rằng nếu bạn biết mã cho một ký tự cụ thể, bạn luôn có thể tạo ký tự đó trong chương trình của mình. Hãy thử với một số số ngẫu nhiên:

public static void main(String[] args) {

   int x = 32816;

   char c = (char) x ;
   System.out.println(c);
}
Đầu ra của bảng điều khiển: 耰 Đây là định dạng được sử dụng để lưu trữ tự trong Java. Mỗi biểu tượng tương ứng với một số: mã số 16 bit (hai byte). Trong Unicode, 32816 tương ứng với ký tự tiếng Trung 耰. Hãy lưu ý điểm sau đây. Trong ví dụ này, chúng tôi đã sử dụng một biến int . Nó chiếm 32 bit trong bộ nhớ, trong khi char chiếm 16. Ở đây chúng tôi chọn int , vì số của chúng tôi (32816) sẽ không vừa với short . Mặc dù kích thước của char (giống như short ) là 16 bit, nhưng không có số âm trong phạm vi char , vì vậy phần "dương" của charphạm vi lớn gấp đôi (65536 thay vì 32767 cho loại ngắn ). Chúng ta có thể sử dụng int miễn là mã của chúng ta ở dưới 65536. Nhưng nếu bạn tạo một giá trị int lớn hơn 65536, thì nó sẽ chiếm hơn 16 bit. Và điều này sẽ dẫn đến việc thu hẹp chuyển đổi

char c = (char) x;
các bit thừa sẽ bị loại bỏ (như đã thảo luận ở trên) và kết quả sẽ khá bất ngờ.

Các tính năng đặc biệt của việc thêm ký tự và số nguyên

Hãy xem xét một ví dụ bất thường:

public class Main {

   public static void main(String[] args) {

      char c = '1';

      int i = 1;

       System.out.println(i + c);
   }
}
Đầu ra của bảng điều khiển: 50 O_О Điều đó có ý nghĩa như thế nào? 1+1. 50 đến từ đâu?! Bạn đã biết rằng charcác giá trị được lưu trữ trong bộ nhớ dưới dạng các số trong phạm vi từ 0 đến 65536 và các số này là biểu diễn Unicode của một ký tự. Mở rộng và thu hẹp các kiểu nguyên thủy - 6 Khi chúng ta thêm một ký tự và một số loại số nguyên, ký tự đó được chuyển đổi thành số Unicode tương ứng. Trong mã của chúng tôi, khi chúng tôi thêm 1 và '1', ký hiệu '1' được chuyển thành mã riêng của nó, là 49 (bạn có thể xác minh điều này trong bảng ở trên). Do đó, kết quả là 50. Một lần nữa, hãy lấy người bạn cũ 耰 của chúng ta làm ví dụ và thử thêm nó vào một số nào đó.

public static void main(String[] args) {

   char c = '耰';
   int x = 200;

   System.out.println(c + x);
}
Kết quả bảng điều khiển: 33016 Chúng tôi đã phát hiện ra rằng 耰 tương ứng với 32816. Và khi cộng số này với 200, chúng tôi nhận được kết quả: 33016. :) Như bạn có thể thấy, thuật toán ở đây khá đơn giản, nhưng bạn đừng quên nó .
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION