JavaRush /Blog Java /Random-MS /Jenis primitif di Jawa: Mereka tidak begitu primitif

Jenis primitif di Jawa: Mereka tidak begitu primitif

Diterbitkan dalam kumpulan

pengenalan

Pembangunan aplikasi boleh dianggap sebagai bekerja dengan beberapa data, atau sebaliknya, menyimpan dan memprosesnya. Hari ini saya ingin menyentuh aspek utama yang pertama. Bagaimanakah data disimpan dalam Java? Di sini kami mempunyai dua format yang mungkin: rujukan dan jenis data primitif . Mari kita bincangkan tentang jenis jenis primitif dan kemungkinan bekerja dengannya (apa pun yang boleh dikatakan, ini adalah asas pengetahuan kita tentang bahasa pengaturcaraan). Jenis data primitif Java adalah asas di mana segala-galanya terletak. Tidak, saya tidak keterlaluan sama sekali. Oracle mempunyai Tutorial berasingan khusus untuk primitif: Jenis Data Primitif Jenis primitif di Jawa: Mereka tidak begitu primitif - 1 Sedikit sejarah. Pada mulanya ada sifar. Tetapi sifar adalah membosankan. Dan kemudian sedikit muncul . Kenapa dia dipanggil begitu? Ia dinamakan demikian daripada singkatan “ bi nary digi t ” (nombor binari). Iaitu, ia hanya mempunyai dua makna. Dan kerana ia adalah sifar, adalah logik bahawa sekarang ia sama ada 0 atau 1. Dan kehidupan menjadi lebih menyeronokkan. Serpihan mula berkumpul dalam kumpulan. Dan kawanan ini mula dipanggil bait (bait). Dalam dunia moden, bait = 2 kepada kuasa ketiga, i.e. 8. Tetapi ternyata ini tidak selalu berlaku. Terdapat banyak tekaan, lagenda dan khabar angin tentang dari mana nama bait itu berasal. Sesetengah orang berpendapat bahawa ini semua tentang pengekodan pada masa itu, manakala yang lain berpendapat bahawa membaca maklumat dengan cara ini lebih menguntungkan. Bait ialah sekeping ingatan terkecil yang boleh dialamatkan. Ia adalah bait yang mempunyai alamat unik dalam ingatan. Terdapat legenda bahawa ByTe ialah singkatan untuk Binary Term - perkataan mesin. Kata mesin - secara ringkasnya, ini ialah jumlah data yang boleh diproses oleh pemproses dalam satu operasi. Sebelum ini, saiz perkataan mesin adalah sama dengan memori terkecil yang boleh dialamatkan. Di Java, pembolehubah hanya boleh menyimpan nilai bait. Seperti yang saya katakan di atas, terdapat dua jenis pembolehubah di Jawa:
  • jenis primitif java secara langsung menyimpan nilai bait data (kita akan melihat jenis primitif ini dengan lebih terperinci di bawah);
  • jenis rujukan, menyimpan bait alamat objek dalam Heap, iaitu, melalui pembolehubah ini kita mendapat akses terus ke objek itu sendiri (semacam alat kawalan jauh untuk objek)

bait Java

Jadi, sejarah memberi kita bait - jumlah minimum memori yang boleh kita gunakan. Dan ia terdiri daripada 8 bit. Jenis data integer terkecil dalam java ialah byte. Ini adalah jenis 8-bit yang ditandatangani. Apakah maksudnya? Jom kira. 2^8 ialah 256. Tetapi bagaimana jika kita mahu nombor negatif? Dan pembangun Java memutuskan bahawa kod binari "10000000" akan mewakili -128, iaitu, bit paling ketara (bit paling kiri) akan menunjukkan sama ada nombor itu negatif. Perduaan "0111 1111" bersamaan dengan 127. Iaitu, 128 tidak boleh ditetapkan dalam apa jua cara, kerana ia akan menjadi -128. Pengiraan penuh diberikan dalam jawapan ini: Mengapa julat bait -128 hingga 127 di Jawa? Untuk memahami bagaimana nombor itu diperoleh, anda harus melihat gambar:
Jenis primitif di Jawa: Mereka tidak begitu primitif - 2
Sehubungan itu, untuk mengira saiz 2^(8-1) = 128. Ini bermakna had minimum (dan ia mempunyai tolak) ialah -128. Dan maksimum ialah 128 – 1 (tolak sifar). Iaitu, maksimum ialah 127. Sebenarnya, kami tidak begitu kerap menggunakan jenis bait pada "tahap tinggi". Ini terutamanya pemprosesan data "mentah". Contohnya, apabila bekerja dengan penghantaran data melalui rangkaian, apabila data adalah satu set 0s dan 1s yang dihantar melalui beberapa jenis saluran komunikasi. Atau apabila membaca data daripada fail. Ia juga boleh digunakan apabila bekerja dengan rentetan dan pengekodan. Contoh kod:
public static void main(String []args){
        byte value = 2;
        byte shortByteValue = 0b10; // 2
        System.out.println(shortByteValue);
        // Начиная с JDK7 мы можем разделять литералы подчёркиваниями
        byte minByteValue = (byte) 0B1000_0000; // -128
        byte maxByteValue = (byte) 0b0111_1111; // 127
        byte minusByteValue = (byte) 0b1111_1111; // -128 + 127
        System.out.println(minusByteValue);
        System.out.println(minByteValue + " to " + maxByteValue);
}
Dengan cara ini, jangan fikir bahawa menggunakan jenis bait akan mengurangkan penggunaan memori. Byte digunakan terutamanya untuk mengurangkan penggunaan memori apabila menyimpan data dalam tatasusunan (contohnya, menyimpan data yang diterima melalui rangkaian dalam beberapa penimbal, yang akan dilaksanakan sebagai tatasusunan bait). Tetapi apabila melakukan operasi pada data, menggunakan bait tidak akan memenuhi jangkaan anda. Ini disebabkan oleh pelaksanaan Java Virtual Machine (JVM). Oleh kerana kebanyakan sistem adalah 32 atau 64 bit, bait dan pendek semasa pengiraan akan ditukar kepada int 32-bit, yang akan kita bincangkan kemudian. Ini menjadikan pengiraan lebih mudah. Untuk butiran lanjut, lihat Adakah penambahan bait ditukar kepada int kerana peraturan bahasa java atau kerana jvm? . Jawapannya juga mengandungi pautan ke JLS (Java Language Specification). Selain itu, menggunakan bait di tempat yang salah boleh menyebabkan detik janggal:
public static void main(String []args){
        for (byte i = 1; i <= 200; i++) {
            System.out.println(i);
        }
}
Akan ada gelung di sini. Oleh kerana nilai pembilang mencapai maksimum (127), limpahan akan berlaku dan nilai akan menjadi -128. Dan kita tidak akan pernah keluar dari kitaran.

pendek

Had untuk nilai bait agak kecil. Oleh itu, untuk jenis data seterusnya kami memutuskan untuk menggandakan bilangan bit. Iaitu, kini ia bukan 8 bit, tetapi 16. Iaitu, 2 bait. Nilai boleh dikira dengan cara yang sama. 2^(16-1) = 2^15 = 32768. Ini bermakna julat adalah dari -32768 hingga 32767. Ia jarang digunakan untuk sebarang kes khas. Sebagai dokumentasi bahasa Java memberitahu kami: " anda boleh menggunakan pendek untuk menyimpan memori dalam tatasusunan besar ."

int

Jadi kami sampai kepada jenis yang paling kerap digunakan. Ia memerlukan 32 bit, atau 4 bait. Secara umum, kami terus menggandakan. Julat nilai adalah dari -2^31 hingga 2^31 – 1.

Nilai int maksimum

Nilai maksimum int 2147483648 ialah 1, yang tidak kecil sama sekali. Seperti yang dinyatakan di atas, untuk mengoptimumkan pengiraan, kerana Ia adalah lebih mudah untuk komputer moden, dengan mengambil kira kedalaman bit mereka, untuk mengira; data boleh secara tersirat ditukar kepada int. Berikut ialah contoh mudah:
byte a = 1;
byte b = 2;
byte result = a + b;
Kod yang tidak berbahaya itu, tetapi kami mendapat ralat: "ralat: jenis tidak serasi: kemungkinan penukaran lossy dari int ke bait." Anda perlu membetulkannya kepada hasil bait = (bait)(a + b); Dan satu lagi contoh yang tidak berbahaya. Apa yang berlaku jika kita menjalankan kod berikut?
int value = 4;
System.out.println(8/value);
System.out.println(9/value);
System.out.println(10/value);
System.out.println(11/value);
Dan kita akan dapat kesimpulannya
2
2
2
2
*bunyi panik*
Hakikatnya ialah apabila bekerja dengan nilai int, selebihnya dibuang, hanya meninggalkan keseluruhan bahagian (dalam kes sedemikian, lebih baik menggunakan dua kali ganda).

panjang

Kami terus menggandakan. Kami mendarab 32 dengan 2 dan mendapat 64 bit. Mengikut tradisi, ini adalah 4 * 2, iaitu, 8 bait. Julat nilai adalah dari -2^63 hingga 2^63 – 1. Lebih daripada cukup. Jenis ini membolehkan anda mengira nombor yang besar dan besar. Selalunya digunakan apabila bekerja dengan masa. Atau dalam jarak yang jauh, sebagai contoh. Untuk menunjukkan bahawa nombor itu panjang, letakkan huruf L – Panjang selepas nombor. Contoh:
long longValue = 4;
longValue = 1l; // Не ошибка, но плохо читается
longValue = 2L; // Идеально
Saya ingin mendahului diri saya sendiri. Seterusnya, kami akan mempertimbangkan fakta bahawa terdapat pembungkus yang sepadan untuk primitif, yang memungkinkan untuk bekerja dengan primitif sebagai objek. Tetapi ada ciri yang menarik. Berikut ialah contoh: Menggunakan pengkompil dalam talian Tutorialspoint yang sama, anda boleh menyemak kod berikut:
public class HelloWorld {

     public static void main(String []args) {
        printLong(4);
     }

    public static void printLong(long longValue) {
        System.out.println(longValue);
    }
}
Kod ini berfungsi tanpa ralat, semuanya baik-baik saja. Tetapi sebaik sahaja jenis dalam kaedah printLong digantikan dari panjang ke Panjang (iaitu jenis menjadi bukan primitif, tetapi objek), ia menjadi tidak jelas kepada Java parameter apa yang kita lalui. Ia mula menganggap bahawa int sedang dihantar dan akan berlaku ralat. Oleh itu, dalam kes kaedah, adalah perlu untuk menunjukkan secara eksplisit 4L. Selalunya panjang digunakan sebagai ID apabila bekerja dengan pangkalan data.

Java float dan Java double

Jenis ini dipanggil jenis titik terapung. Iaitu, ini bukan jenis integer. Jenis apungan ialah 32 bit (seperti int), dan double dipanggil jenis ketepatan berganda, jadi ia adalah 64 bit (darab dengan 2, sama seperti yang kita suka). Contoh:
public static void main(String []args){
        // float floatValue = 2.3; lossy conversion from double to float
        float floatValue = 2.3F;
        floatValue = 2.3f;
        double doubleValue = 2.3;
        System.out.println(floatValue);
        double cinema = 7D;
}
Dan berikut ialah contoh perbezaan nilai (disebabkan oleh ketepatan jenis):
public static void main(String []args){
        float piValue = (float)Math.PI;
        double piValueExt = Math.PI;
        System.out.println("Float value: " + piValue );
        System.out.println("Double value: " + piValueExt );
 }
Jenis primitif ini digunakan dalam matematik, sebagai contoh. Inilah buktinya, pemalar untuk mengira nombor PI . Secara umum, anda boleh melihat API kelas Matematik. Inilah perkara lain yang perlu penting dan menarik: malah dokumentasi mengatakan: “ Jenis data ini tidak boleh digunakan untuk nilai yang tepat, seperti mata wang. Untuk itu, anda perlu menggunakan kelas java.math.BigDecimal sebaliknya.Nombor dan Rentetan merangkumi BigDecimal dan kelas berguna lain yang disediakan oleh platform Java. " Maksudnya, wang dalam float dan double tidak perlu dikira. Contoh tentang ketepatan menggunakan contoh kerja di NASA: Java BigDecimal, Menangani pengiraan ketepatan tinggi Baiklah, rasai sendiri:
public static void main(String []args){
        float amount = 1.0000005F;
        float avalue = 0.0000004F;
        float result = amount - avalue;
        System.out.println(result);
}
Ikuti contoh ini, dan kemudian tambah 0 sebelum nombor 5 dan 4. Dan anda akan melihat semua kengerian) Terdapat laporan menarik dalam bahasa Rusia tentang terapung dan berganda mengenai topik: https://youtu.be/1RCn5ruN1fk Contoh kerja dengan BigDecimal boleh dilihat di sini: Buat sen dengan BigDecimal By the way, float dan double boleh mengembalikan lebih daripada sekadar nombor. Sebagai contoh, contoh di bawah akan mengembalikan Infinity:
public static void main(String []args){
        double positive_infinity = 12.0 / 0;
        System.out.println(positive_infinity);
}
Dan yang ini akan mengembalikan NAN:
public static void main(String []args){
        double positive_infinity = 12.0 / 0;
        double negative_infinity = -15.0 / 0;
        System.out.println(positive_infinity + negative_infinity);
}
Ia jelas tentang infiniti. Apakah NaN? Ini Bukan nombor , bermakna hasilnya tidak boleh dikira dan bukan nombor. Berikut ialah contoh: Kami ingin mengira punca kuasa dua bagi -4. Punca kuasa dua bagi 4 ialah 2. Iaitu, 2 mesti kuasa dua dan kemudian kita mendapat 4. Apakah kuasa dua untuk mendapat -4? Ia tidak akan berfungsi, kerana... jika terdapat nombor positif, maka ia akan kekal. Dan jika ia negatif, maka tolak dengan tolak akan memberikan tambah. Iaitu, ia tidak boleh dikira.
public static void main(String []args){
        double sqrt = Math.sqrt(-4);
        System.out.println(sqrt + 1);
        if (Double.isNaN(sqrt)) {
           System.out.println("So sad");
        }
        System.out.println(Double.NaN == sqrt);
}
Berikut ialah satu lagi gambaran keseluruhan hebat mengenai topik nombor titik terapung: Di manakah titik anda?
Apa lagi yang perlu dibaca:

boolean Java

Jenis seterusnya ialah Boolean (jenis logik). Ia hanya boleh menerima nilai benar atau salah, iaitu kata kunci. Digunakan dalam operasi logik seperti gelung while, dan dalam percabangan menggunakan jika, suis. Apakah perkara menarik yang boleh anda ketahui di sini? Nah, sebagai contoh, secara teorinya, kita hanya memerlukan 1 bit maklumat, 0 atau 1, iaitu benar atau palsu. Tetapi pada hakikatnya, Boolean akan mengambil lebih banyak memori dan ini bergantung pada pelaksanaan JVM tertentu. Biasanya kos ini sama dengan int. Pilihan lain ialah menggunakan BitSet. Berikut ialah penerangan ringkas daripada buku Java Fundamentals: BitSet

Java char

Sekarang kita telah mencapai jenis primitif terakhir. Jadi, data dalam char mengambil 16 bit dan menerangkan watak. Java menggunakan pengekodan Unicode untuk char. Simbol boleh ditetapkan mengikut dua jadual (anda boleh melihatnya di sini ):
  • Jadual aksara Unikod
  • Jadual aksara ASCII
Jenis primitif di Jawa: Mereka tidak begitu primitif - 3
Contoh di studio:
public static void main(String[] args) {
    char symbol = '\u0066'; // Unicode
    symbol = 102; // ASCII
    System.out.println(symbol);
}
Ngomong-ngomong, char, pada dasarnya adalah nombor, menyokong operasi matematik seperti jumlah. Dan kadang-kadang ini boleh membawa kepada akibat lucu:
public class HelloWorld{

    public static void main(String []args){
        String costForPrint = "5$";
        System.out.println("Цена только для вас " +
        + costForPrint.charAt(0) + getCurrencyName(costForPrint.charAt(1)));
    }

    public static String getCurrencyName(char symbol) {
        if (symbol == '$') {
            return " долларов";
        } else {
            throw new UnsupportedOperationException("Not implemented yet");
        }
    }

}
Saya sangat mengesyorkan menyemak IDE dalam talian dari tutorialspoint . Apabila saya melihat teka-teki ini di salah satu persidangan, ia menaikkan semangat saya. Saya harap anda juga menyukai contoh itu) DIKEMASKINI: This was at Joker 2017, report: " Java Puzzlers NG S03 - Dari mana kamu semua datang?! "

Literal

Literal ialah nilai yang dinyatakan secara eksplisit. Menggunakan literal, anda boleh menentukan nilai dalam sistem nombor yang berbeza:
  • Sistem perpuluhan: 10
  • Perenambelasan: 0x1F4, bermula dengan 0x
  • Sistem perlapanan: 010, bermula dari sifar.
  • Sistem binari (sejak Java7): 0b101, bermula pada 0b
Saya akan pergi ke sedikit lebih terperinci mengenai sistem oktal, kerana ia lucu:
int costInDollars = 08;
Baris kod ini tidak akan disusun:
error: integer number too large: 08
Nampak macam mengarut. Sekarang mari kita ingat tentang sistem binari dan oktal. Tiada dua dalam sistem binari, kerana terdapat dua nilai (bermula dari 0). Dan sistem perlapanan mempunyai 8 nilai, bermula dari sifar. Iaitu, nilai 8 itu sendiri tidak wujud. Oleh itu, ini adalah ralat yang pada pandangan pertama kelihatan tidak masuk akal. Dan yang perlu diingat, berikut ialah peraturan "susulan" untuk menterjemah nilai:
Jenis primitif di Jawa: Mereka tidak begitu primitif - 4

Kelas pembalut

Primitif di Jawa mempunyai kelas pembungkusnya sendiri supaya anda boleh bekerja dengannya sebagai objek. Iaitu, untuk setiap jenis primitif terdapat jenis rujukan yang sepadan. Jenis primitif di Jawa: Mereka tidak begitu primitif - 5Kelas pembungkus tidak boleh diubah: ini bermakna apabila objek dicipta, keadaannya—nilai medan nilai—tidak boleh diubah. Kelas pembungkus diisytiharkan sebagai muktamad: objek, boleh dikatakan, baca sahaja. Saya juga ingin menyatakan bahawa tidak mungkin untuk mewarisi daripada kelas ini. Java secara automatik membuat penukaran antara jenis primitif dan pembalutnya:
Integer x = 9;          // autoboxing
int n = new Integer(3); // unboxing
Proses menukar jenis primitif kepada jenis rujukan (int->Integer) dipanggil autoboxing , dan sebaliknya dipanggil unboxing . Kelas ini memungkinkan untuk menyimpan primitif di dalam objek, dan objek itu sendiri akan berkelakuan seperti Objek (baik, seperti objek lain). Dengan semua ini, kami mendapat sejumlah besar kaedah statik yang berbeza dan berguna, seperti membandingkan nombor, menukar simbol kepada huruf besar, menentukan sama ada simbol ialah huruf atau nombor, mencari nombor minimum, dsb. Set fungsi yang disediakan hanya bergantung pada pembungkus itu sendiri. Contoh pelaksanaan pembungkus untuk int anda sendiri:
public class CustomerInt {

   private final int value;

   public CustomerInt(int value) {
       this.value = value;
   }

   public int getValue() {
       return value;
   }
}
Pakej utama, java.lang, sudah mempunyai pelaksanaan kelas Boolean, Byte, Short, Character, Integer, Float, Long, Double, dan kami tidak perlu mencipta apa-apa dari kami sendiri, tetapi hanya menggunakan semula yang sudah siap. satu. Sebagai contoh, kelas sedemikian memberi kita keupayaan untuk mencipta, katakan, Senarai , kerana Senarai seharusnya hanya mengandungi objek, yang mana primitifnya bukan. Untuk menukar nilai jenis primitif, terdapat kaedah statik valueOf, sebagai contoh, Integer.valueOf(4) akan mengembalikan objek jenis Integer. Untuk penukaran terbalik terdapat kaedah intValue(), longValue(), dll. Pengkompil memasukkan panggilan ke valueOf dan *Value sendiri, ini adalah intipati autoboxing dan autounboxing. Apakah contoh pembungkusan automatik dan penyahkemasan yang dibentangkan di atas sebenarnya:
Integer x = Integer.valueOf(9);
int n = new Integer(3).intValue();
Anda boleh membaca lebih lanjut tentang autopacking dan autounpacking dalam artikel ini .

Pelakon

При работе с примитивами существует такое понятие How приведение типов, одно из не очень приятных свойств C++, тем не менее приведение типов сохранено и в языке Java. Иногда мы сталкиваемся с такими ситуациями, когда нам нужно совершать взаимодействия с данными разных типов. И очень хорошо, что в некоторых ситуациях это возможно. В случае с ссылочными переменными, там свои особенности, связанные с полиморфизмом и наследованием, но сегодня мы рассматриваем простые типы и соответственно приведение простых типов. Существует преобразование с расширением и преобразование сужающее. Всё на самом деле просто. Если тип данных становится больше (допустим, был int, а стал long), то тип становится шире (из 32 бит становится 64). И в этом случае мы не рискуем потерять данные, т.к. если влезло в int, то в long влезет тем более, поэтому данное приведение мы не замечаем, так How оно осуществляется автоматически. А вот в обратную сторону преобразование требует явного указания от нас, данное приведение типа называется — сужение. Так сказать, чтобы мы сами сказали: «Да, я даю себе отчёт в этом. В случае чего — виноват сам».
public static void main(String []args){
   int intValue = 128;
   byte value = (byte)intValue;
   System.out.println(value);
}
Whatбы потом в таком случае не говорor что «Ваша Джава плохая», когда получат внезапно -128 instead of 128 ) Мы ведь помним, что в byteе 127 верхнее meaning и всё что находилось выше него соответственно можно потерять. Когда мы явно превратor наш int в byte, то произошло переполнение и meaning стало -128.

Область видимости

Это то место в codeе, где данная переменная будет выполнять свои функции и хранить в себе Howое-то meaning. Когда же эта область закончится, переменная перестанет существовать и будет стерта из памяти и. How уже можно догадаться, посмотреть or получить ее meaning будет невозможно! Так что же это такое — область видимости? Jenis primitif di Jawa: Mereka tidak begitu primitif - 6Область определяется "блоком" — вообще всякой областью, замкнутой в фигурные скобки, выход за которые сулит удаление данных объявленных в ней. Или How минимум — сокрытие их от других блоков, открытых вне текущего. В Java область видимости определяется двумя основными способами:
  • Классом.
  • Методом.
Как я и сказал, переменная не видна codeу, если она определена за пределами блока, в котором она была инициализирована. Смотрим пример:
int x;
x = 6;
if (x >= 4) {
   int y = 3;
}
x = y;// переменная y здесь не видна!
И How итог мы получим ошибку:

Error:(10, 21) java: cannot find symbol
  symbol:   variable y
  location: class com.javaRush.test.type.Main
Области видимости могут быть вложенными (если мы объявor переменную в первом, внешнем блоке, то во внутреннем она будет видна).

Заключение

Сегодня мы познакомorсь с восемью примитивными типами в Java. Эти типы можно разделить на четыре группы:
  • Целые числа: byte, short, int, long — представляют собой целые числа со знаком.
  • Числа с плавающей точкой — эта группа включает себе float и double — типы, которые хранят числа с точностью до определённого знака после запятой.
  • Булевы значения — boolean — хранят значения типа "истина/ложь".
  • Watak - kumpulan ini termasuk jenis aksara.
Seperti yang ditunjukkan oleh teks di atas, primitif di Jawa tidak begitu primitif dan membolehkan anda menyelesaikan banyak masalah dengan berkesan. Tetapi ini juga memperkenalkan beberapa ciri yang perlu kita ingat jika kita tidak mahu menghadapi tingkah laku yang tidak dapat diramalkan dalam program kita. Seperti yang mereka katakan, anda perlu membayar untuk segala-galanya. Jika kita mahukan primitif dengan julat "curam" (luas) - seperti panjang - kita mengorbankan peruntukan sekeping memori yang lebih besar dan ke arah yang bertentangan. Dengan menyimpan memori dan menggunakan bait, kami mendapat julat terhad dari -128 hingga 127.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION