JavaRush /Блоги Java /Random-TG /Муқоисаи объектҳо: амалия
articles
Сатҳи

Муқоисаи объектҳо: амалия

Дар гурӯҳ нашр шудааст
Ин дуввумин мақолаҳоест, ки ба муқоисаи an objectҳо бахшида шудаанд. Дар навбати аввал дар бораи асосхои назариявии мукоиса — чи тавр ичро карда мешавад, барои чй ва дар кучо истифода мешавад. Дар ин мақола мо бевосита дар бораи муқоисаи ададҳо, ашёҳо, ҳолатҳои махсус, нозукиҳо ва нуктаҳои норавшан сӯҳбат хоҳем кард. Аниқтараш, мо дар ин бора сӯҳбат мекунем:
Муқоисаи an objectҳо: амалия - 1
  • Муқоисаи сатр: ' ==' ваequals
  • УсулString.intern
  • Муқоисаи ибтидоии воқеӣ
  • +0.0Ва-0.0
  • МаъноиNaN
  • Java 5.0. Усулҳои тавлид ва муқоиса тавассути ' =='
  • Java 5.0. Autoboxing/Unboxing: ' ==', ' >=' ва ' ' ' <=' барои печонидани an objectҳо.
  • Java 5.0. Муқоисаи унсурҳои рақамӣ (навъ enum)
Пас биёед оғоз кунем!

Муқоисаи сатр: ' ==' ваequals

Аа ин сатрхо... Яке аз навъхои маъмултарин, ки боиси мушкилоти зиёд мегардад. Дар асл, дар бораи онҳо мақолаи алоҳида мавҷуд аст . Ва дар ин чо ба масъалахои мукоиса дахл мекунам. Албатта, сатрҳоро метавон бо истифода аз equals. Илова бар ин, онҳо БОЯД тавассути equals. Бо вуҷуди ин, нозукиҳое ҳастанд, ки бояд дониста шаванд. Пеш аз ҳама, сатрҳои якхела воқеан як an objectи ягона мебошанд. Инро тавассути иҷро кардани рамзи зерин ба осонӣ тафтиш кардан мумкин аст:
String str1 = "string";
String str2 = "string";
System.out.println(str1==str2 ? "the same" : "not the same");
Натиҷа "ҳамин" хоҳад буд . Ин маънои онро дорад, ки истинодҳои сатр баробаранд. Ин дар сатҳи компилятор анҷом дода мешавад, бешубҳа барои сарфаи хотира. Компилятор ЯК мисоли сатрро эҷод мекунад ва ба ин мисол истинод таъин str1мекунад str2. Аммо, ин танҳо ба сатрҳои ҳамчун литерал дар code эълоншуда дахл дорад. Агар шумо сатрро аз порчаҳо созед, пайванд ба он гуногун хоҳад буд. Тасдиқ - ин мисол:
String str1 = "string";
String str2 = "str";
String str3 = "ing";
System.out.println(str1==(str2+str3) ? "the same" : "not the same");
Натиҷа "якхела нест" . Шумо инчунин метавонед бо истифода аз созандаи нусхабардорӣ an objectи нав эҷод кунед:
String str1 = "string";
String str2 = new String("string");
System.out.println(str1==str2 ? "the same" : "not the same");
Натиҷа низ "якхела нест" . Ҳамин тариқ, баъзан сатрҳоро тавассути муқоисаи истинод муқоиса кардан мумкин аст. Аммо беҳтар аст, ки ба ин такя накунед. Ман мехоҳам ба як усули хеле ҷолибе дахл кунам, ки ба шумо имкон медиҳад, ки тасвири ба истилоҳ каноникии сатр ба даст оред - String.intern. Биёед дар ин бора муфассалтар гап занем.

Усули String.intern

Биёед бо он оғоз кунем, ки синф Stringяк ҳавзи сатрро дастгирӣ мекунад. Ҳамаи адабҳои сатри дар синфҳо муайяншуда, на танҳо онҳо, ба ин ҳавз илова карда мешаванд. Ҳамин тавр, усул ба шумо имкон медиҳад, ки аз ин ҳавз як сатр гиред, ки аз нуқтаи назари internмавҷуда (онест, ки метод дар он номида мешавад) баробар аст . Агар дар ҳавз чунин сатр мавҷуд набошад, он ҷо сатри мавҷуда ҷойгир карда мешавад ва истиноди он баргардонида мешавад. Ҳамин тариқ, ҳатто агар истинодҳо ба ду сатри баробар гуногун бошанд (чунон ки дар ду мисоли дар боло овардашуда), зангҳо ба ин сатрҳо истинодро ба ҳамон an object бармегардонанд: internequalsintern
String str1 = "string";
String str2 = new String("string");
System.out.println(str1.intern()==str2.intern() ? "the same" : "not the same");
Натиҷаи иҷрои ин порчаи code "якхела" хоҳад буд . Ман аниқ гуфта наметавонам, ки чаро ин тавр шуд. Ин усул internмодарӣ аст ва ростқавлона, ман намехоҳам ба ваҳшӣ аз рамзи C дохил шавам. Эҳтимол, ин барои оптимизатсияи истеъмоли хотира ва иҷрои кор анҷом дода мешавад. Дар ҳар сурат, дар бораи ин хусусияти амалӣ донистан бамаврид аст. Биёед ба қисми оянда гузарем.

Муқоисаи ибтидоии воқеӣ

Барои оғоз, ман мехоҳам як савол диҳам. Хеле содда. Маблағи зерин - 0.3f + 0.4f чист? Чаро? 0.7f? Биёед тафтиш кунем:
float f1 = 0.7f;
float f2 = 0.3f + 0.4f;
System.out.println("f1==f2: "+(f1==f2));
Дар натиҷа? Мисли? Ман ҳам. Барои онҳое, ки ин порчаро пурра накардаанд, мегӯям, ки натиҷааш...
f1==f2: false
Чаро ин тавр шуда истодааст?.. Боз як озмоиши дигар мегузаронем:
float f1 = 0.3f;
float f2 = 0.4f;
float f3 = f1 + f2;
float f4 = 0.7f;
System.out.println("f1="+(double)f1);
System.out.println("f2="+(double)f2);
System.out.println("f3="+(double)f3);
System.out.println("f4="+(double)f4);
Ба табдил додан ба double. Ин барои он анҷом дода мешавад, ки шумораи бештари нуқтаҳои даҳӣ. Натиҷа:
f1=0.30000001192092896
f2=0.4000000059604645
f3=0.7000000476837158
f4=0.699999988079071
Ба таври қатъӣ, натиҷа пешгӯишаванда аст. Тасвири қисми касрӣ бо истифода аз силсилаи ниҳоии 2-n анҷом дода мешавад ва аз ин рӯ, дар бораи ифодаи дақиқи адади худсарона интихобшуда сухан рондан лозим нест. Тавре ки аз мисол дида мешавад, дурустии намояндагӣ float7 адади даҳиро ташкил медиҳад. Ба таври қатъӣ, намояндагӣ float ба мантисса 24 бит ҷудо мекунад. Ҳамин тариқ, шумораи ҳадди ақали мутлақ, ки метавон бо истифода аз он float (бе назардошти дараҷа, зеро сухан дар бораи дақиқӣ меравад) 2-24≈6*10-8 аст. Маҳз бо ин қадам арзишҳо дар намояндагӣ воқеан мераванд float. Ва азбаски квантизатсия вуҷуд дорад, хато низ вуҷуд дорад. Аз ин рӯ, хулоса мебарояд: рақамҳоро дар намояндагӣ floatтанҳо бо дақиқии муайян муқоиса кардан мумкин аст. Ман тавсия медиҳам, ки онҳоро ба адади даҳии шашум (10-6) яклухт кунед ё беҳтараш арзиши мутлақи фарқияти байни онҳоро тафтиш кунед:
float f1 = 0.3f;
float f2 = 0.4f;
float f3 = f1 + f2;
float f4 = 0.7f;
System.out.println("|f3-f4|<1e-6: "+( Math.abs(f3-f4) < 1e-6 ));
Дар ин ҳолат, натиҷа рӯҳбаландкунанда аст:
|f3-f4|<1e-6: true
Албатта, тасвир маҳз бо навъи double. Ягона фарқият дар он аст, ки барои мантисса 53 бит ҷудо карда шудааст, бинобар ин, дақиқии муаррифӣ 2-53≈10-16 аст. Бале, арзиши квантизатсия хеле хурдтар аст, аммо он ҷост. Ва он метавонад шӯхии бераҳмона бозӣ кунад. Воқеан, дар китобхонаи санҷишии JUnit , дар усулҳои муқоисаи ададҳои воқеӣ, дақиқӣ ба таври возеҳ нишон дода шудааст. Онхое. усули муќоиса се параметрро дар бар мегирад - адад, он бояд ба чї баробар бошад ва дурустии муќоиса. Дар омади гап, ман мехостам нозукиҳои марбут ба навиштани ададҳоро дар шакли илмӣ бо нишон додани дараҷа зикр намоям. Савол. Чӣ тавр 10-6 нависед? Амалия нишон медиҳад, ки зиёда аз 80% ҷавоб медиҳанд - 10e-6. Дар ҳамин ҳол, ҷавоби дуруст 1e-6 аст! Ва 10e-6 10-5 аст! Мо ногаҳон дар яке аз лоиҳаҳо ба ин раке қадам гузоштем. Онҳо муддати хеле тӯлонӣ хатогиро ҷустуҷӯ карданд, 20 маротиба ба константаҳо нигоҳ карданд.Ва ҳеҷ кас ба дурустии онҳо шубҳа надошт, то рӯзе, ки аксаран тасодуфӣ, доимии 10e-3 чоп карда шуд ва онҳо ду ёфтанд. рақамҳо пас аз нуқтаи даҳӣ ба ҷои се интизорӣ. Аз ин рӯ, эҳтиёт бошед! Биёед пеш равем.

+0,0 ва -0,0

Ҳангоми муаррифии рақамҳои воқеӣ бит муҳимтарин имзо карда мешавад. Агар ҳамаи битҳои дигар 0 бошанд, чӣ мешавад? Баръакси ададҳои бутун, ки дар чунин ҳолат натиҷа рақами манфӣ аст, ки дар ҳудуди поёни диапазони намояндагӣ ҷойгир аст, рақами воқеӣ бо танҳо битҳои муҳимтарин ба 1 таъиншуда низ маънои 0-ро дорад, танҳо бо аломати минус. Ҳамин тариқ, мо ду сифр дорем - +0,0 ва -0,0. Саволи мантиқӣ ба миён меояд: оё ин рақамҳоро баробар ҳисоб кардан лозим аст? Мошини виртуалӣ маҳз ҳамин тавр фикр мекунад. Аммо, ин ду рақами гуногун мебошанд , зеро дар натиҷаи амалиёт бо онҳо арзишҳои гуногун ба даст меоянд:
float f1 = 0.0f/1.0f;
float f2 = 0.0f/-1.0f;
System.out.println("f1="+f1);
System.out.println("f2="+f2);
System.out.println("f1==f2: "+(f1==f2));
float f3 = 1.0f / f1;
float f4 = 1.0f / f2;
System.out.println("f3="+f3);
System.out.println("f4="+f4);
... ва натиҷа:
f1=0.0
f2=-0.0
f1==f2: true
f3=Infinity
f4=-Infinity
Аз ин рӯ, дар баъзе мавридҳо ба +0,0 ва -0,0 ҳамчун ду рақами гуногун муносибат кардан маъно дорад. Ва агар мо ду an object дошта бошем, ки дар яке аз онҳо майдон +0,0 ва дар дигараш -0,0 аст, ин an objectҳоро низ нобаробар донистан мумкин аст. Саволе ба миён меояд - чӣ тавр шумо метавонед фаҳмед, ки рақамҳо нобаробаранд, агар муқоисаи мустақими онҳо бо мошини виртуалӣ дода шавад true? Ҷавоб ин аст. Гарчанде ки мошини виртуалӣ ин рақамҳоро баробар мешуморад, намояндагии онҳо то ҳол гуногун аст. Аз ин рӯ, ягона коре, ки метавон кард, муқоисаи назарҳост. Ва барои ба даст овардани он, усулҳои int Float.floatToIntBits(float)ва вуҷуд доранд long Double.doubleToLongBits(double), ки каме намояндагӣ дар шакл intва longмутаносибан бармегарданд (идомаи мисоли қаблӣ):
int i1 = Float.floatToIntBits(f1);
int i2 = Float.floatToIntBits(f2);
System.out.println("i1 (+0.0):"+ Integer.toBinaryString(i1));
System.out.println("i2 (-0.0):"+ Integer.toBinaryString(i2));
System.out.println("i1==i2: "+(i1 == i2));
Натиҷа хоҳад буд
i1 (+0.0):0
i2 (-0.0):10000000000000000000000000000000
i1==i2: false
Ҳамин тариқ, агар шумо +0.0 ва -0.0 рақамҳои гуногун дошта бошед, пас шумо бояд тағирёбандаҳои воқеиро тавассути муаррифии бит муқоиса кунед. Чунин ба назар мерасад, ки мо +0.0 ва -0.0-ро ҷудо кардаем. Аммо, -0,0 ягона ногаҳонӣ нест. Чунин чизе низ вуҷуд дорад, ки ...

Арзиши NaN

NaNбарои Not-a-Number. Ин ќимат дар натиљаи амалњои нодурусти математикї, масалан, таќсими 0,0 ба 0,0, беохир ба беохир ва ѓайра пайдо мешавад. Хусусияти ин арзиш дар он аст, ки вай ба худ баробар нест. Онҳо.:
float x = 0.0f/0.0f;
System.out.println("x="+x);
System.out.println("x==x: "+(x==x));
... натиҷа хоҳад дод ...
x=NaN
x==x: false
Ҳангоми муқоисаи an objectҳо ин чӣ гуна мешавад? Агар майдони an object ба , баробар бошад NaN, он гоҳ муқоиса медиҳад false, яъне. an objectхои нобаробар дониста шудани онхо кафолат дода мешавад. Ҳарчанд, аз рӯи мантиқ, мо метавонем баръакс бихоҳем. Бо истифода аз усул шумо метавонед натиҷаи дилхоҳ ба даст оред Float.isNaN(float). Он бармегардад, trueагар аргумент бошад NaN. Дар ин ҳолат, ман ба муқоисаи намояндагии бит такя намекунам, зеро стандартизатсия карда нашудааст. Шояд ин дар бораи ибтидоӣ басанда бошад. Биёед ҳоло ба нозукиҳое, ки дар Java аз versionи 5.0 пайдо шудаанд, мегузарем. Ва аввалин нуктае, ки мехостам ба он дахл кунам

Java 5.0. Усулҳои тавлид ва муқоиса тавассути ' =='

Дар тарроҳӣ намунае вуҷуд дорад, ки усули истеҳсолӣ номида мешавад. Баъзан истифодаи он назар ба истифодаи конструктор хеле фоиданоктар аст. Ичозат дихед ба шумо як мисол оварам. Ман фикр мекунам, ки ман қабати an objectро хуб медонам Boolean. Ин синф тағирнопазир аст ва метавонад танҳо ду арзиш дошта бошад. Яъне, дар асл, барои ҳама гуна ниёзҳо, танҳо ду нусха кофӣ аст. Ва агар шумо онҳоро пешакӣ эҷод кунед ва сипас онҳоро баргардонед, ин назар ба истифодаи конструктор хеле тезтар хоҳад буд. Чунин усул вуҷуд дорад Boolean: valueOf(boolean). Он дар versionи 1.4 пайдо шуд. Усулҳои шабеҳи истеҳсолот дар versionи 5.0 дар синфҳои Byte, Character, Short, Integerва синфҳо ҷорӣ карда шуданд Long. Вақте ки ин синфҳо бор карда мешаванд, массивҳои мисолҳои онҳо ба диапазони муайяни арзишҳои ибтидоӣ мувофиқанд, сохта мешаванд. Ин диапазонҳо чунинанд:
Муқоисаи an objectҳо: амалия - 2
Ин маънои онро дорад, ки ҳангоми истифодаи усул, valueOf(...)агар аргумент дар доираи муқарраршуда афтад, ҳамон an object ҳамеша баргардонида мешавад. Шояд ин суръатро каме афзоиш диҳад. Аммо дар баробари ин, мушкилоте ба миён меоянд, ки табиатан ба қаъри он расидан хеле душвор аст. Дар бораи он бештар хонед. Дар назария, усули истеҳсолот ҳам ба синфҳо ва ҳам синфҳо valueOfилова карда шудааст . Тавсифи онҳо мегӯяд, ки агар ба шумо нусхаи нав лозим набошад, пас беҳтар аст, ки ин усулро истифода баред, зеро афзоиши суръат ва гайра дода метавонад. ва ғайра. Аммо, дар татбиқи ҷорӣ (Java 5.0), дар ин усул як мисоли нав сохта мешавад, яъне. Истифодаи он кафолат дода намешавад, ки суръатро афзоиш диҳад. Гузашта аз ин, барои ман тасаввур кардан душвор аст, ки ин усулро чӣ гуна суръат бахшидан мумкин аст, зеро аз сабаби пайвастагии арзишҳо, дар он ҷо кэш ташкил карда намешавад. Ба ғайр аз ададҳои бутун. Дар назар дорам, бе қисми касрӣ.FloatDouble

Java 5.0. Autoboxing/Unboxing: ' ==', ' >=' ва ' ' ' <=' барои печонидани an objectҳо.

Ман гумон мекунам, ки усулҳои истеҳсолӣ ва кэши мисол ба печендаҳо барои ибтидоии бутун барои оптимизатсияи амалиёт илова карда шудаанд autoboxing/unboxing. Биёед ба шумо хотиррасон кунам, ки ин чист. Агар an object бояд дар амалиёт ҷалб карда шавад, аммо примитив иштирок дошта бошад, пас ин примитив ба таври худкор дар печи an object печонида мешавад. Ин autoboxing. Ва баръакс - агар примитив бояд дар амалиёт ҷалб карда шавад, шумо метавонед дар он ҷо қабати an objectро иваз кунед ва арзиш аз он ба таври худкор васеъ карда мешавад. Ин unboxing. Табиист, ки шумо бояд барои чунин роҳат пардохт кунед. Амалиёти табдилдиҳии худкор барномаро то андозае суст мекунад. Аммо, ин ба мавзӯи ҳозира дахл надорад, бинобар ин биёед ин саволро тарк кунем. Ҳама чиз хуб аст, то даме ки мо бо амалиётҳое сарукор дорем, ки ба таври возеҳ ба примитивҳо ё снарядҳо алоқаманданд. Амалиёти '' чй мешавад ==? Фарз мекунем, ки мо ду an object дорем Integer, ки дар дохor он арзиши якхела доранд. Онҳо чӣ гуна муқоиса хоҳанд кард?
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println("i1==i2: "+(i1==i2));
Натиҷа:
i1==i2: false

Кто бы сомневался... Сравниваются они How an objectы. А если так:Integer i1 = 1;
Integer i2 = 1;
System.out.println("i1==i2: "+(i1==i2));
Натиҷа:
i1==i2: true
Акнун ин ҷолибтар аст! Агар autoboxing-e ҳамон an objectҳо баргардонида шаванд! Ин аст, ки дом дар куҷост. Вақте ки мо мефаҳмем, ки ҳамон an objectҳо баргардонида мешаванд, мо ба озмоиш шурӯъ мекунем, то бубинем, ки оё ин ҳамеша чунин аст. Ва мо чанд арзишро тафтиш хоҳем кард? Як? Даҳ? Сад? Эҳтимол, мо худро ба сад дар ҳар як самт тақрибан сифр маҳдуд хоҳем кард. Ва мо дар ҳама ҷо баробарӣ мегирем. Чунин ба назар мерасад, ки ҳама чиз хуб аст. Бо вуҷуди ин, каме ба ақиб нигоҳ кунед, дар ин ҷо . Оё шумо фаҳмидед, ки сайд чист?.. Бале, мисолҳои қабатҳои an objectӣ ҳангоми автобокс бо истифода аз усулҳои истеҳсолӣ сохта мешаванд. Инро санҷиши зерин хуб нишон медиҳад:
public class AutoboxingTest {

    private static final int numbers[] = new int[]{-129,-128,127,128};

    public static void main(String[] args) {
        for (int number : numbers) {
            Integer i1 = number;
            Integer i2 = number;
            System.out.println("number=" + number + ": " + (i1 == i2));
        }
    }
}
Натиҷа чунин хоҳад буд:
number=-129: false
number=-128: true
number=127: true
number=128: false
Барои арзишҳое, ки дар доираи кэш ҷойгиранд , an objectҳои якхела, барои онҳое, ки берун аз он ҳастанд, an objectҳои гуногун баргардонида мешаванд. Ва аз ин рӯ, агар дар ягон ҷои барнома снарядҳо ба ҷои ибтидоӣ муқоиса карда шаванд, имкони ба даст овардани хатои даҳшатнок вуҷуд дорад: хатои шинокунанда. Азбаски рамз эҳтимолан дар доираи маҳдуди арзишҳо санҷида мешавад, ки дар он ин хатогӣ пайдо намешавад. Аммо дар кори хакикй он вобаста ба натичахои баъзе хисобхо ё пайдо мешавад ё аз байн меравад. Девона шудан осонтар аз ёфтани чунин хато. Аз ин рӯ, ман ба шумо маслиҳат медиҳам, ки то ҳадди имкон аз автобокс худдорӣ кунед. Ва ин нест. Математикаро ба хотир меорем, на аз синфи 5. Бигузор нобаробарй A>=Bва А<=B. Дар бораи муносибатҳо чӣ гуфтан мумкин аст Aва B? Танҳо як чиз вуҷуд дорад - онҳо баробаранд. Шумо розӣ ҳастед? Ман фикр мекунам ҳа. Биёед санҷишро иҷро кунем:
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println("i1>=i2: "+(i1>=i2));
System.out.println("i1<=i2: "+(i1<=i2));
System.out.println("i1==i2: "+(i1==i2));
Натиҷа:
i1>=i2: true
i1<=i2: true
i1==i2: false
Ва ин барои ман аҷибтарин чизи аҷиб аст. Ман аслан намефаҳмам, ки чаро ин хусусият ба забон ворид шудааст, агар ин гуна зиддиятҳоро ворид кунад. Умуман, ман бори дигар такрор мекунам — агар бе autoboxing/unboxing. Мавзӯи охирине, ки ман мехоҳам ба он муроҷиат кунам, ин аст... Java 5.0. мукоисаи элементхои руйхатгирй (навъи enum) Тавре ки шумо медонед, аз versionи 5.0 Java чунин намудро ба мисли enum - enumeration ворид кардааст . Намунаҳои он ба таври нобаёнӣ ном ва рақами пайдарпайро дар эъломияи мисол дар синф дарбар мегиранд. Мувофиқи он, вақте ки тартиби эълон тағир меёбад, рақамҳо тағир меёбанд. Аммо, тавре ки ман дар мақолаи 'Сермализатсия он тавре ки ҳаст' гуфтам , ин мушкилотро ба вуҷуд намеорад. Ҳама унсурҳои рӯйхат дар як нусха вуҷуд доранд, ки ин дар сатҳи мошини виртуалӣ назорат карда мешавад. Аз ин рӯ, онҳоро метавон мустақиман бо истифода аз пайвандҳо муқоиса кард. * * * Шояд ин ҳама барои имрӯз дар бораи ҷанбаи амалии татбиқи муқоисаи an object бошад. Шояд ман чизеро гум кардаам. Чун ҳамеша, ман интизори шарҳҳои шумо ҳастам! Ҳоло иҷозат диҳед, ки рухсатии худро гирам. Ташаккур ба ҳама барои таваҷҷӯҳатон! Пайванд ба манбаъ: Муқоисаи an objectҳо: амалия
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION