3-bo‘lim
Turlar va o'zgaruvchilar
Primitiv va havola turlari, butun va kasr sonlar, BigDecimal, var va final, turlarni aylantirish, avtoqutilash va Integer keshi tuzog'i.
Ushbu bo‘lim mundarijasi
Java qat'iy turlangan til: har bir o'zgaruvchining turi bor va u o'zgarmaydi. Bu ko'proq yozishni talab qiladi, lekin xatolarning katta qismini ishga tushirishdan oldin topadi.
Primitiv turlar #
Java'da sakkizta primitiv tur bor. Ular obyekt emas - shunchaki qiymat.
| Tur | Hajmi | Diapazon yoki maqsad |
|---|---|---|
byte | 1 bayt | -128 .. 127 |
short | 2 bayt | -32 768 .. 32 767 |
int | 4 bayt | ±2 milliardgacha - odatiy tanlov |
long | 8 bayt | Juda katta butun sonlar |
float | 4 bayt | Kasr son, kam aniqlik |
double | 8 bayt | Kasr son - odatiy tanlov |
char | 2 bayt | Bitta belgi: 'A' |
boolean | - | true yoki false |
Chegaralarni o'zingiz ko'rishingiz mumkin:
public class Chegaralar {
public static void main(String[] args) {
System.out.println("int: " + Integer.MIN_VALUE
+ " .. " + Integer.MAX_VALUE);
System.out.println("long: " + Long.MIN_VALUE
+ " .. " + Long.MAX_VALUE);
System.out.println("byte: " + Byte.MIN_VALUE
+ " .. " + Byte.MAX_VALUE);
}
}
int: -2147483648 .. 2147483647
long: -9223372036854775808 .. 9223372036854775807
byte: -128 .. 127
To'lib ketish #
public class Tolish {
public static void main(String[] args) {
int katta = Integer.MAX_VALUE;
System.out.println("MAX_VALUE: " + katta);
System.out.println("MAX_VALUE + 1: " + (katta + 1));
long togri = (long) katta + 1;
System.out.println("long bilan: " + togri);
}
}
MAX_VALUE: 2147483647
MAX_VALUE + 1: -2147483648
long bilan: 2147483648
int chegarasidan oshganda Java xato bermaydi - son eng kichik
qiymatga "aylanib" o'tadi.
Bu haqiqiy tizimlarda jiddiy xatolarga sabab bo'lgan. Masalan
millisekundlarni int da saqlasangiz, 24 kundan keyin to'lib ketadi.
Ikki himoya usuli:
- Katta bo'lishi mumkin bo'lgan qiymatlar uchun
longishlating; - Tekshiruv kerak bo'lsa
Math.addExactchaqiring - u to'lishda istisno tashlaydi.
public class Xavfsiz {
public static void main(String[] args) {
try {
Math.addExact(Integer.MAX_VALUE, 1);
} catch (ArithmeticException x) {
System.out.println("Ushlandi: " + x.getMessage());
}
}
}
Ushlandi: integer overflow
Primitiv va havola turlari #
Bu Java'dagi eng muhim ajratish.
import java.util.Arrays;
public class Turlar {
public static void main(String[] args) {
int a = 5;
int b = a;
b = 9;
System.out.println("Primitiv: a = " + a + ", b = " + b);
int[] x = {5};
int[] y = x;
y[0] = 9;
System.out.println("Havola: x = " + Arrays.toString(x)
+ ", y = " + Arrays.toString(y));
}
}
Primitiv: a = 5, b = 9
Havola: x = [9], y = [9]
Ko'p manbada "obyektlar havola bo'yicha uzatiladi" deb yoziladi. Bu noto'g'ri.
Java'da har doim qiymat nusxalanadi. Obyektlarda esa nusxalanadigan qiymat - bu havolaning o'zi, obyekt emas.
Farq amalda ko'rinadi:
public class Uzatish {
public static void main(String[] args) {
int[] massiv = {1};
Ozgartir(massiv);
System.out.println("Element o'zgardi: " + massiv[0]);
Almashtir(massiv);
System.out.println("Massivning o'zi: " + massiv[0]);
}
static void Ozgartir(int[] m) {
m[0] = 99; // obyekt ichini o'zgartiradi
}
static void Almashtir(int[] m) {
m = new int[]{777}; // faqat lokal nusxani almashtiradi
}
}
Element o'zgardi: 99
Massivning o'zi: 99
Birinchi metod obyekt ichini o'zgartirdi - bu tashqarida ko'rindi. Ikkinchisi havolaning o'zini almashtirdi - bu faqat metod ichida qoldi.
Kasr sonlar va aniqlik #
public class Kasr {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
System.out.println("0.1 + 0.2 == 0.3 : " + (a + b == 0.3));
System.out.println("Haqiqiy natija : " + (a + b));
}
}
0.1 + 0.2 == 0.3 : false
Haqiqiy natija : 0.30000000000000004
double sonni ikkilik kasrda saqlaydi va 0.1 ni ikkilikda aniq
ifodalab bo'lmaydi - xuddi 1/3 ni o'nlik kasrda aniq yozib
bo'lmagani kabi.
double ishlatmangPul hisobida bu xatolar to'planib, haqiqiy zararga aylanadi. Java'da
buning uchun BigDecimal bor:
import java.math.BigDecimal;
public class Pul {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal jami = a.add(b);
System.out.println("Yig'indi: " + jami);
System.out.println("0.3 ga tengmi: "
+ jami.equals(new BigDecimal("0.3")));
}
}
Yig'indi: 0.3
0.3 ga tengmi: true
Ikkita muhim tafsilot:
- Satrdan yarating:
new BigDecimal("0.1").new BigDecimal(0.1)debdoublebersangiz, o'sha aniqsizlik ichkariga kirib ketadi. +amali ishlamaydi - Java'da operator qayta yuklash yo'q.add,subtract,multiplymetodlarini chaqirasiz.
var - turni kompilyator aniqlaydi #
Java 10 dan lokal o'zgaruvchi turini yozmaslik mumkin:
import java.util.*;
public class Var {
public static void main(String[] args) {
var yosh = 25; // int
var narx = 12.5; // double
var ism = "Malika"; // String
var royxat = new ArrayList<String>();
royxat.add("Namangan");
System.out.println(ism + ": " + yosh);
System.out.println("Ro'yxat: " + royxat);
System.out.println("narx turi: "
+ ((Object) narx).getClass().getSimpleName());
}
}
Malika: 25
Ro'yxat: [Namangan]
narx turi: Double
var turni yo'q qilmaydi - uni kompilyator o'ng tomondan aniqlaydi va
keyin o'zgartirib bo'lmaydi.
var faqat lokal o'zgaruvchilar uchunvar ni quyidagi joylarda ishlatib bo'lmaydi:
- sinf maydonlarida;
- metod parametrlarida;
- metod qaytish turida.
Bundan tashqari, var x = null; ham xato - kompilyator turni
aniqlay olmaydi.
Qoida: o'ng tomonga qarab tur ko'rinib tursa var yozing
(var royxat = new ArrayList<String>()), ko'rinmasa - to'liq turni
yozing.
final #
public class Doimiy {
static final double PI_TAXMINAN = 3.14159;
static final String MAKTAB = "14-maktab";
public static void main(String[] args) {
final int yosh = 25;
System.out.println(MAKTAB + ", yosh: " + yosh);
System.out.println("Aylana: " + (2 * PI_TAXMINAN * 5));
}
}
14-maktab, yosh: 25
Aylana: 31.4159
final o'zgaruvchini bir marta o'zlashtirishga ruxsat beradi. Doimiy
nomlari BOSH HARFLAR bilan yoziladi.
Turlarni aylantirish #
public class Aylantirish {
public static void main(String[] args) {
int kichik = 42;
long katta = kichik; // kengaytirish - o'zi bo'ladi
double kasr = kichik;
System.out.println(katta + " va " + kasr);
double narx = 19.99;
int butun = (int) narx; // toraytirish - oshkora yozish shart
System.out.println(narx + " -> " + butun);
System.out.println("Yaxlitlash: " + Math.round(narx));
}
}
42 va 42.0
19.99 -> 19
Yaxlitlash: 20
(int) yaxlitlamaydi - kesib tashlaydi(int) 19.99 natijasi 19, 20 emas. Oshkora aylantirish kasr
qismini shunchaki tashlab yuboradi.
Yaxlitlash kerak bo'lsa Math.round ishlating. E'tibor bering:
Math.round(double) natijasi long, Math.round(float) esa
int qaytaradi.
Avtoqutilash va Integer keshi #
Java'da har bir primitiv turning obyekt ko'rinishi bor: int →
Integer, double → Double. Kompilyator ular orasida avtomatik
o'tadi.
public class Qutilash {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
Integer c = 1000;
Integer d = 1000;
System.out.println("a == b (100): " + (a == b));
System.out.println("c == d (1000): " + (c == d));
System.out.println("c.equals(d): " + c.equals(d));
}
}
a == b (100): true
c == d (1000): false
c.equals(d): true
Bir xil kod, bir xil mantiq - lekin 100 uchun true, 1000 uchun
false.
Sababi: JVM -128 dan 127 gacha bo'lgan Integer obyektlarini
oldindan yaratib qo'yadi va qayta ishlatadi. Shu diapazonda a va
b aynan bitta obyekt, shuning uchun == rost bo'ladi.
1000 esa har safar yangi obyekt - ikki xil manzil, == yolg'on.
Qoida: obyektlarni hech qachon == bilan solishtirmang. ==
faqat primitivlar uchun. Obyektlar uchun har doim equals.
Bu qoida String uchun ham amal qiladi va keyingi bo'limda yana
qaytadi.
| Holat | Tanlov |
|---|---|
| Oddiy hisob, sikl hisoblagichi | primitiv (int) |
| Kolleksiyada saqlash | obyekt (Integer) - boshqa yo'l yo'q |
| "Qiymat yo'q" holatini ifodalash | obyekt - u null bo'la oladi |
| Tezlik muhim, million element | primitiv - qutilash qimmat |
List<int> deb yozib bo'lmaydi - faqat List<Integer>. Bu Java'ning
tarixiy cheklovi.
- Sakkizta primitiv turning har biri uchun o'zgaruvchi e'lon qiling.
Integer.MAX_VALUEga 1 qo'shib, natijani ko'ring.Math.addExactbilan to'lishni ushlang.- Primitiv va havola nusxalanishini massiv misolida tekshiring.
- Metodga massiv uzatib, ichini o'zgartiring - tashqarida ko'rinishini ko'ring.
0.1 + 0.2nidoublevaBigDecimalda solishtiring.new BigDecimal(0.1)vanew BigDecimal("0.1")farqini ko'ring.varbilan to'rtta o'zgaruvchi yarating.Integerni 100 va 1000 qiymatlarida==bilan solishtiring.- Nega
List<int>yozib bo'lmasligini tushuntiring.
Xulosa #
- Java'da sakkizta primitiv tur bor; qolgan hamma narsa - obyekt.
intto'lib ketganda xato bermaydi -longyokiMath.addExactishlating.- Primitiv qiymat nusxalanadi, obyektda esa havola nusxalanadi - lekin ikkala holatda ham uzatish qiymat bo'yicha.
doublekasr sonlarni aniq saqlamaydi; pul uchunBigDecimalva uni satrdan yarating.- Java'da operator qayta yuklash yo'q -
BigDecimaldaaddchaqiriladi. varfaqat lokal o'zgaruvchilar uchun.(int)yaxlitlamaydi, kesadi; yaxlitlash uchunMath.round.- Obyektlarni
==bilan solishtirmang -Integerkeshi tufayli natija diapazonga bog'liq bo'lib qoladi.
Keyingi bo'limda satrlar bilan ishlashni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.