JavaRush /Блоги Java /Random-TG /Намудҳои тозакунӣ

Намудҳои тозакунӣ

Дар гурӯҳ нашр шудааст
Салом! Мо силсилаи лекцияхои худро оид ба генерикхо давом дода истодаем. Пештар , мо ба таври умумӣ фаҳмидем, ки ин чист ва чаро он лозим аст. Имрӯз мо дар бораи баъзе хусусиятҳои генерикҳо сӯҳбат хоҳем кард ва ҳангоми кор бо онҳо баъзе хатогиҳоро дида мебароем. Бирав! Намудҳои тозакунӣ - 1Дар лексияи охирин мо дар бораи фарқи байни намудҳои умумӣ ва навъҳои хом сӯҳбат кардем . Агар шумо фаромӯш карда бошед, Type Raw як синфи умумӣ аст, ки навъи он аз он хориҷ карда шудааст.
List list = new ArrayList();
Ана як мисол. Дар ин ҷо мо муайян намекунем, ки кадом намуди an objectҳо дар мо ҷойгир карда мешаванд List. Агар мо кӯшиш кунем, ки як an object эҷод кунем Listва ба он якчанд an object илова кунем, мо дар IDEa огоҳиро мебинем:

“Unchecked call to add(E) as a member of raw type of java.util.List”.
Аммо мо инчунин дар бораи он сӯҳбат кардем, ки генерикҳо танҳо дар versionи Java 5-и забон пайдо мешаванд.То замони нашри он барномасозон бо истифода аз Raw Types codeҳои зиёде навишта буданд ва то он ки он аз кор қатъ нагардад, қобorяти эҷод ва кор бо намудҳои хом дар Java нигоҳ дошта шуд. Бо вуҷуди ин, ин мушкилот хеле васеътар шуд. Тавре ки шумо медонед, codeи Java ба bytecodeи махсус табдил дода мешавад, ки баъдан аз ҷониби мошини виртуалии Java иҷро карда мешавад. Ва агар дар ҷараёни тарҷума мо маълумот дар бораи намудҳои параметрҳоро ба bytecode ҷойгир кунем, он ҳамаи codeҳои қаблан навишташударо мешиканад, зеро пеш аз Java 5 ягон намуди параметр вуҷуд надошт! Ҳангоми кор бо генерикҳо як хусусияти муҳиме вуҷуд дорад, ки шумо бояд дар хотир доред. Он навъи тозакунӣ номида мешавад. Моҳияти он дар он аст, ки ҳеҷ гуна маълумот дар бораи намуди параметри он дар дохor синф нигоҳ дошта намешавад. Ин маълумот танҳо дар марҳилаи тартибдиҳӣ дастрас аст ва дар вақти иҷро тоза карда мешавад (дастрас мешавад). Агар шумо кӯшиш кунед, ки an objectи навъи нодурустро ба худ гузоред List<String>, компилятор хато мекунад. Маҳз ба ҳамин чиз эҷодкорони забон тавассути эҷоди генерикҳо - чекҳо дар марҳилаи таҳия ба даст овардаанд. Аммо вақте ки ҳамаи codeҳои Java, ки шумо менависед, ба byte-code мубаддал мешавад, дар бораи намудҳои параметрҳо маълумот нахоҳад буд. Дар дохor byte-code, рӯйхати List<Cat>гурбаҳои шумо аз сатрҳо фарқ намекунад List<String>. Ҳеҷ чиз дар byte code намегӯяд, ки catsин рӯйхати an objectҳост Cat. Маълумот дар бораи ин ҳангоми ҷамъоварӣ нест карда мешавад ва танҳо маълумоте, ки шумо дар барномаи шумо рӯйхати муайян доред, ба codeи byte ворид мешавад List<Object> cats. Биёед бубинем, ки он чӣ гуна кор мекунад:
public class TestClass<T> {

   private T value1;
   private T value2;

   public void printValues() {
       System.out.println(value1);
       System.out.println(value2);
   }

   public static <T> TestClass<T> createAndAdd2Values(Object o1, Object o2) {
       TestClass<T> result = new TestClass<>();
       result.value1 = (T) o1;
       result.value2 = (T) o2;
       return result;
   }

   public static void main(String[] args) {
       Double d = 22.111;
       String s = "Test String";
       TestClass<Integer> test = createAndAdd2Values(d, s);
       test.printValues();
   }
}
Мо синфи умумии худро таъсис додем TestClass. Ин хеле содда аст: аслан ин "маҷмӯаи" хурди 2 an object аст, ки дарҳол ҳангоми сохтани an object дар он ҷо ҷойгир карда мешаванд. Он ҳамчун майдон 2 an object дорад T. Вақте ки усул иҷро мешавад, createAndAdd2Values()ду an objectи гузаронидашуда бояд Object aба Object bнамуди мо партофта шаванд T, ки пас аз он онҳо ба an object илова карда мешаванд TestClass. Дар усуле , main()ки мо эҷод мекунем TestClass<Integer>, яъне дар сифат Tмо хоҳем дошт Integer. Аммо дар айни замон, createAndAdd2Values()мо рақам Doubleва an objectро ба усули String. Ба фикри шумо, барномаи мо кор хоҳад кард? Дар ниҳоят, мо ҳамчун як намуди параметр нишон додем Integer, аммо Stringонро бешубҳа ба Integer! Биёед усулро иҷро кунем main()ва тафтиш кунем. Натиҷаи консол: 22.111 Сатри санҷиш Натиҷаи ғайричашмдошт! Чаро ин тавр шуд? Маҳз аз сабаби тозакунии навъи. Ҳангоми тартиб додани code маълумот дар бораи намуди параметри Integeran objectи мо TestClass<Integer> testнест карда шуд. Ӯ ба TestClass<Object> test. Параметрҳои мо Doubleбидуни Stringмушкилот Objectба Integer. TestClassИн аст, ки боз як мисоли оддӣ, вале хеле равшанкунандаи навъи тозакунӣ:
import java.util.ArrayList;
import java.util.List;

public class Main {

   private class Cat {

   }

   public static void main(String[] args) {

       List<String> strings = new ArrayList<>();
       List<Integer> numbers = new ArrayList<>();
       List<Cat> cats = new ArrayList<>();

       System.out.println(strings.getClass() == numbers.getClass());
       System.out.println(numbers.getClass() == cats.getClass());

   }
}
Натиҷаи консол: true true Чунин ба назар мерасад, ки мо коллексияҳоро бо се намуди параметрҳои гуногун эҷод кардаем - String, Integer, ва синфе, ки мо офаридаем Cat. Аммо ҳангоми табдилдиҳӣ ба byte code, ҳар се рӯйхат ба , табдил ёфтанд List<Object>, бинобар ин, вақте ки иҷро мешавад, барнома ба мо мегӯяд, ки дар ҳар се ҳолат мо як синфро истифода мебарем.

Ҳангоми кор бо массивҳо ва генерикҳо тозакуниро нависед

Як нуктаи хеле муҳим вуҷуд дорад, ки ҳангоми кор бо массивҳо ва генерикҳо (масалан, List). Инчунин ҳангоми интихоби сохтори додаҳо барои барномаи шумо ба назар гирифтан лозим аст. Генерикҳо бояд навъи тоза карда шаванд. Маълумот дар бораи намуди параметр ҳангоми иҷрои барнома дастрас нест. Баръакс, массивҳо ҳангоми иҷрои барнома маълумотро дар бораи намуди додаҳои худ медонанд ва метавонанд истифода баранд. Кӯшиши гузоштани арзиши навъи нодуруст ба массив истисноро ба вуҷуд меорад:
public class Main2 {

   public static void main(String[] args) {

       Object x[] = new String[3];
       x[0] = new Integer(222);
   }
}
Натиҷаи консол:

Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer
Азбаски байни массивҳо ва генерикҳо фарқияти калон вуҷуд дорад, онҳо метавонанд мушкилоти мутобиқат дошта бошанд. Пеш аз ҳама, шумо наметавонед массиви an objectҳои умумӣ ё ҳатто массиви чопшударо эҷод кунед. Як каме печида садо медиҳад? Биёед муфассалтар дида бароем. Масалан, шумо наметавонед ҳеҷ яке аз инҳоро дар Java иҷро кунед:
new List<T>[]
new List<String>[]
new T[]
Агар мо кӯшиш кунем, ки массиви рӯйхатҳоро эҷод кунем List<String>, мо хатои умумии эҷоди массиви ҷамъоварӣ мегирем:
import java.util.List;

public class Main2 {

   public static void main(String[] args) {

       //ошибка компиляции! Generic array creation
       List<String>[] stringLists = new List<String>[1];
   }
}
Аммо чаро ин кор карда шуд? Чаро эҷоди чунин массивҳо манъ аст? Ин ҳама барои таъмини бехатарии намуди. Агар компилятор ба мо иҷозат диҳад, ки чунин массивҳоро аз an objectҳои умумӣ созем, мо метавонем ба мушкилоти зиёд дучор шавем. Ин аст як мисоли оддӣ аз китоби Ҷошуа Блок "Яваи самаранок":
public static void main(String[] args) {

   List<String>[] stringLists = new List<String>[1];  //  (1)
   List<Integer> intList = Arrays.asList(42, 65, 44);  //  (2)
   Object[] objects = stringLists;  //  (3)
   objects[0] = intList;  //  (4)
   String s = stringLists[0].get(0);  //  (5)
}
Биёед тасаввур кунем, ки эҷоди массив List<String>[] stringListsиҷозат дода мешавад ва компилятор шикоят намекунад. Ин аст он чизе ки мо дар ин ҳолат карда метавонем: Дар сатри 1 мо массиви варақҳоро эҷод мекунем List<String>[] stringLists. Массиви мо як List<String>. Дар сатри 2 мо рӯйхати рақамҳоро эҷод мекунем List<Integer>. Дар сатри 3 мо массивамонро List<String>[]ба тағирёбанда таъин мекунем Object[] objects. Забони Java ба шумо имкон медиҳад, ки ин корро кунед: Xшумо метавонед ҳам an objectҳо Xва ҳам an objectҳои ҳамаи синфҳои кӯдакиро ба массиви an objectҳо ҷойгир кунед Х. Бинобар ин, Objectsшумо метавонед ҳама чизро дар массив ҷойгир кунед. Дар сатри 4 мо як элементи массивро objects (List<String>)бо рӯйхат иваз мекунем List<Integer>. Дар натиҷа, мо List<Integer>дар массивамон ҷойгир кардем, ки танҳо барои нигоҳдорӣ пешбинӣ шуда буд List<String>! Мо бо хатогӣ танҳо вақте рӯ ба рӯ мешавем, ки рамз ба сатри 5 мерасад. Истисно ҳангоми иҷрои барнома партофта мешавад ClassCastException. Аз ин рӯ, манъи сохтани чунин массивҳо ба забони Java ҷорӣ карда шуд - ин ба мо имкон медиҳад, ки аз чунин ҳолатҳо канорагирӣ кунем.

Чӣ тавр ман метавонам аз тозакунии навъи навъи худ гузарам?

Хуб, мо дар бораи тозакунии навъи фаҳмидем. Биёед кӯшиш кунем, ки системаро фиреб диҳем! :) Вазифа: Мо синфи умумӣ дорем TestClass<T>. Мо бояд дар он усулеро эҷод кунем createNewT(), ки an objectи нави навъи типро эҷод ва баргардонад Т. Аммо ин корро кардан ғайриимкон аст, дуруст? Њамаи маълумот дар бораи намуд Тњангоми тартиб додан тоза карда мешавад ва њангоми кор кардани барнома мо наметавонем муайян кунем, ки кадом навъи an objectро бояд созем. Дар асл, як роҳи душвор вуҷуд дорад. Шояд шумо дар хотир доред, ки дар Java синф мавҷуд аст Class. Бо истифода аз он, мо метавонем синфи яке аз an objectҳои худро ба даст орем:
public class Main2 {

   public static void main(String[] args) {

       Class classInt = Integer.class;
       Class classString = String.class;

       System.out.println(classInt);
       System.out.println(classString);
   }
}
Натиҷаи консол:

class java.lang.Integer
class java.lang.String
Аммо дар ин ҷо як хусусияте ҳаст, ки мо дар бораи он сӯҳбат накардаем. Дар ҳуҷҷатҳои Oracle шумо хоҳед дид, ки Class як синфи умумӣ аст! Намудҳои тозакунӣ - 3Ҳуҷҷатҳо мегӯяд: "T навъи синфест, ки аз ҷониби ин an objectи Синф модел шудааст." Агар мо инро аз забони ҳуҷҷатгузорӣ ба забони инсонӣ тарҷума кунем, ин маънои онро дорад, ки синф барои an object Integer.classна танҳо Class, балки Class<Integer>. Навъи an object string.classна танҳо Class, Class<String>, ва ғ. Агар он ҳанӯз равшан набошад, кӯшиш кунед, ки ба мисоли қаблӣ параметри навъи илова кунед:
public class Main2 {

   public static void main(String[] args) {

       Class<Integer> classInt = Integer.class;
       //ошибка компиляции!
       Class<String> classInt2 = Integer.class;


       Class<String> classString = String.class;
       //ошибка компиляции!
       Class<Double> classString2 = String.class;
   }
}
Ва акнун, бо истифода аз ин дониш, мо метавонем аз тозакунии навъи худ гузаред ва мушкилоти худро ҳал кунем! Биёед кӯшиш кунем, ки дар бораи намуди параметр маълумот гирем. Нақши онро синф иҷро мекунад MySecretClass:
public class MySecretClass {

   public MySecretClass() {

       System.out.println("Объект секретного класса успешно создан!");
   }
}
Дар ин ҷо мо ҳалли худро дар амал истифода мебарем:
public class TestClass<T> {

   Class<T> typeParameterClass;

   public TestClass(Class<T> typeParameterClass) {
       this.typeParameterClass = typeParameterClass;
   }

   public T createNewT() throws IllegalAccessException, InstantiationException {
       T t = typeParameterClass.newInstance();
       return t;
   }

   public static void main(String[] args) throws InstantiationException, IllegalAccessException {

       TestClass<MySecretClass> testString = new TestClass<>(MySecretClass.class);
       MySecretClass secret = testString.createNewT();

   }
}
Натиҷаи консол:

Объект секретного класса успешно создан!
Мо танҳо параметри зарурии синфро ба созандаи синфи генералии худ супоридем:
TestClass<MySecretClass> testString = new TestClass<>(MySecretClass.class);
Ба шарофати ин, мо маълумотро дар бораи намуди параметр захира кардем ва онро аз нест кардан муҳофизат кардем. Дар натиҷа, мо тавонистем an objectеро эҷод кунем T! :) Бо хамин лекцияи имруза ба охир мерасад. Тозакунии намуд ҳамеша чизест, ки ҳангоми кор бо генерикҳо дар хотир бояд дошт. Ин чандон қулай ба назар намерасад, аммо шумо бояд фаҳмед, ки генерикҳо ҳангоми сохтани он ҷузъи забони Java набуданд. Ин як хусусияти дертар иловашудаест, ки ба мо дар эҷод кардани коллексияҳои чопшуда ва дарёфти хатогиҳо дар марҳилаи тартибдиҳӣ кӯмак мекунад. Баъзе забонҳои дигаре, ки генерикҳо аз versionи 1 вуҷуд доранд, навъи тозакунӣ надоранд (масалан, C#). Аммо, мо омӯзиши генерикҳоро тамом накардаем! Дар лекцияи навбатй шумо бо боз якчанд хусусиятхои кор бо онхо шинос мешавед. Дар ин миён як-ду масъаларо хал кардан хуб мешуд! :)
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION