JavaRush /Java блогу /Random-KY /Шилтемелердин түрлөрүн кеңейтүү жана кыскартуу

Шилтемелердин түрлөрүн кеңейтүү жана кыскартуу

Группада жарыяланган
Салам! Мурунку лекциялардын биринде биз примитивдүү типтерди кастингди талкуулаганбыз. Эмне жөнүндө сөз кылганыбызды кыскача эстейли. Шилтемелердин түрлөрүн кеңейтүү жана кыскартуу - 1Биз примитивдүү типтерди (бул учурда сандык) алар ээлеген эс тутумдун көлөмүнө жараша уя куурчактары катары көрсөттүк. Эсиңизде болсо, кичинекей куурчакты чоңураак куурчакка коюу чыныгы жашоодо да, Java программалоодо да оңой болот.
public class Main {
   public static void main(String[] args) {
        short smallNumber = 100;
        int bigNumber =  smallNumber;
        System.out.println(bigNumber);
   }
}
Бул автоматтык түрдө конвертациялоонун же кеңейтүүнүн мисалы . Бул өзүнөн өзү болот, ошондуктан кошумча code жазуунун кереги жок. Акыр-аягы, биз адаттан тыш эч нерсе кылып жаткан жокпуз: биз жөн гана кичинекей куурчакты чоңураак куурчакка салып жатабыз. Тескерисинче, чоң матрешканы кичирээк куурчакка салсак, бул башка маселе. Бул жашоодо мүмкүн эмес, бирок программалоодо муну жасоого болот. Бирок бир эскертүү бар. intЭгерде биз өзгөрмөгө маани коюуга аракет кылсак short, ал оңой менен иштебейт. Акыры, өзгөрмөгө 16 бит гана маалымат туура келет short, бирок маани int32 битти алат! Натыйжада, берилген маани бурмаланат. Компилятор бизге ката берет (“ досум, сен шектүү бир нерсе кылып жатасың! ”), бирок биз баалуулугубузду кайсы түргө чыгарып жатканыбызды ачык көрсөтсөк, ал дагы эле ушундай операцияны аткара берет.
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
Жогорудагы мисалда биз дал ушундай кылдык. Операция аяктады, бирок short32 биттин 16сы гана өзгөрмөгө туура келгендиктен, акыркы маани бурмаланып, натыйжада -27008 санын алдык . Бул операция ачык конversion же тарытуу деп аталат .

Шилтемелердин түрлөрүн узартуу жана кыскартуу мисалдары

Эми биз ошол эле операциялар жөнүндө сүйлөшөбүз, бирок примитивдүү типтерге эмес, an objectтерге жана шилтеме өзгөрмөлөргө тиешелүү ! Бул Javaда кантип иштейт? Чынында абдан жөнөкөй. Бири-бири менен байланышпаган an objectилер бар. Аларды бири-бирине ачык же автоматтык түрдө айландыруу мүмкүн эмес деп болжолдоо логикалык болмок:
public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Dog();//error!

   }

}
Бул жерде биз, албетте, ката алабыз. Класстар бири-бирине байланыштуу Catэмес Dog, биринен экинчисине “конверт” жазган эмеспиз. Биз муну кыла албай турганыбыз логикалык: компилятор бул an objectтерди бири-бирине кантип айландырууну билбейт. Объекттер бири-бири менен байланышкан болсо, бул башка маселе! Кантип? Биринчиден, мурасты колдонуу. Келгиле, тукум куучулук менен чакан класстык системаны түзүүгө аракет кылалы. Бизде жаныбарларды чагылдырган жалпы класс болот:
public class Animal {

   public void introduce() {

       System.out.println("i'm Animal");
   }
}
Жаныбарлар, сиз билгендей, үй жана жапайы болуп саналат:
public class WildAnimal extends Animal {

   public void introduce() {

       System.out.println("i'm WildAnimal");
   }
}

public class Pet extends Animal {

   public void introduce() {

       System.out.println("i'm Pet");
   }
}
Мисалы, иттерди алалы - үй ити менен чөө:
public class Dog extends Pet {

   public void introduce() {

       System.out.println("i'm Dog");
   }
}





public class Coyote extends WildAnimal {

   public void introduce() {

       System.out.println("i'm Coyote");
   }
}
Биздин класстар аларды кабыл алууну жеңилдетүү үчүн атайылап эң примитивдүү класстар. Бул жерде бизге талаалардын кереги жок, бир эле ыкма жетиштүү. Келгиле, төмөнкү codeду иштетүүгө аракет кылалы:
public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
Консолго эмне чыгат деп ойлойсуз? introduceКласс Petже класс методу иштейби Animal? Окууну улантуудан мурун жообуңузду негиздөөгө аракет кылыңыз. Жана жыйынтык мына! Мен Петмин Эмне үчүн жооп мындай болуп калды? Баары оңой. Бизде ата-эне өзгөрмө жана бала an object бар. жазуу менен:
Animal animal = new Pet();
Биз шилтеме түрүн кеңейттикPet жана анын an objectисин өзгөрмөдө сактадык Animal. Примитивдик типтер сыяктуу эле, Java'да маалымдама түрлөрүн кеңейтүү автоматтык түрдө ишке ашырылат. Бул үчүн кошумча code жазуунун кереги жок. Эми бизде ата-эне шилтемеге тиркелген бала an objectи бар жана натыйжада биз метод бала класста чакырылганын көрөбүз. Бул code эмне үчүн иштеп жатканын дагы эле толук түшүнбөсөңүз, аны жөнөкөй тилде кайра жазыңыз:
Животное животное = new ДомашнееЖивотное();
Мында эч кандай көйгөй жок, туурабы? Бул чыныгы жашоо экенин элестетиңиз жана бул учурда шилтеме "Жаныбар" деп жазылган жөнөкөй кагаз тег. Мындай кагазды алып, каалаган үй жаныбарынын жакасына жабышса, баары жакшы болот. Кандайдыр бир үй жаныбары дагы эле жаныбар! Тескери процесс, башкача айтканда, мурас дарагынан ылдый мураскорлорго көчүү, бир тароо болуп саналат:
public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Көрүнүп тургандай, бул жерде биз an objectибизди кайсы класска чыгаргыбыз келерин ачык көрсөтөбүз. Мурда бизде өзгөрмө бар болчу WildAnimal, азыр болсо Coyoteмурас дарагына түшүп кетет. Компилятор мындай операцияны ачык көрсөтүүсүз өткөрүп жибербей турганы логикалык, бирок кашаанын ичинде түрүн көрсөтсөңүз, баары иштейт. Шилтемелердин түрлөрүн кеңейтүү жана кыскартуу - 2 Келгиле, дагы бир мисалды карап көрөлү, кызыктуураак:
public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//error!
   }
}
Компилятор ката кетирет! Мунун себеби эмнеде? Чындыгында, сиз бала өзгөрмөгө ата-энелик an objectти дайындоого аракет кылып жатасыз. Башкача айтканда, сиз муну кылгыңыз келет:
ДомашнееЖивотное домашнееЖивотное = new Животное();
Бирок, балким, биз чыгарууга аракет кылып жаткан түрүбүздү ачык көрсөтсөк, ийгorкке жетебиз? Сандар иштеп жатат окшойт, аракет кылалы! :)
public class Main {

   public static void main(String[] args) {

       Pet pet = (Pet) new Animal();
   }
}
"main" java.lang.ClassCastException жипиндеги өзгөчө жагдай: Жаныбарларды Pet Error үчүн чыгарууга болбойт! Бул жолу компилятор нааразы болгон жок, бирок натыйжада биз өзгөчөлүк алдык. Биз буга чейин эле себебин билебиз: биз бала өзгөрмөгө ата-энелик an objectти дайындоого аракет кылып жатабыз. Эмне үчүн, чынында, бул мүмкүн эмес? Анткени бардык жаныбарлар үй жаныбарлары эмес. Сиз an object түздүңүз Animalжана аны өзгөрмөгө дайындоого аракет кылып жатасыз Pet. Бирок, мисалы, чөө дагы Animal, бирок ал Petүй жаныбары эмес. Башка сөз менен айтканда, сиз жазганда:
Pet pet = (Pet) new Animal();
Ал жерде new Animal()ар кандай жаныбар болушу мүмкүн жана ал үй болушу шарт эмес! Албетте, сиздин өзгөрмөңүз Pet petүй жаныбарларын (жана алардын урпактарын) сактоо үчүн гана ылайыктуу, бирок бардыгы үчүн эмес. Ошондуктан, мындай учурлар үчүн Javaда өзгөчө өзгөчөлүк түзүлгөн - ClassCastExceptionкласстарды чыгарууда ката. Түшүнүктүү болуш үчүн дагы бир жолу айта кетели. Аталык өзгөрмө (маалымат) тукум класстын an objectисин көрсөтө алат:
public class Main {

   public static void main(String[] args) {

       Pet pet =  new Pet();
       Animal animal = pet;

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
Мисалы, биз бул жерде эч кандай көйгөй болбойт. PetБизде шилтеме менен көрсөтүлгөн an object бар Pet. Андан кийин жаңы шилтеме ошол эле an objectти көрсөтө баштады Animal. Андан кийин биз конversionны animalжасайбыз Pet. Айтмакчы, эмне үчүн мындай кылдык? Акыркы жолу бизде өзгөчөлүк бар! Анткени бул жолу биздин баштапкы an object Pet pet!
Pet pet =  new Pet();
Ал эми мурунку мисалда бул an object болгон Animal:
Pet pet = (Pet) new Animal();
Сиз түпкү an objectти тукум өзгөрмөгө дайындай албайсыз. Тескерисинче, сиз муну кыла аласыз.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION