Java ядросы
9. Java тіліндегі статикалық және динамикалық байланыстырудың айырмашылығы неде?
Мен бұл сұраққа осы мақаланың 18-сұрағында статикалық және динамикалық полиморфизм туралы жауап бердім , мен оны оқуға кеңес беремін.10. Интерфейсте жеке немесе қорғалған айнымалыларды қолдануға болады ма?
Жоқ болмайды. Интерфейсті жариялаған кезде Java компиляторы интерфейс әдістерінің алдында жалпы және дерексіз кілт сөздерді және деректер мүшелерінің алдында жалпы , статикалық және соңғы кілт сөздерді автоматты түрде қосады. Шын мәнінде, егер сіз private немесе protected қоссаңыз , қақтығыс туындайды және компилятор келесі хабармен қатынас модификаторына шағымданады: «'<таңдалған модификатор>' модификаторына бұл жерде рұқсат етілмейді. Неліктен компилятор public , static және final қосады. интерфейстегі айнымалылар? Оны анықтап көрейік:- public – интерфейс клиентке an objectімен әрекеттесуге мүмкіндік береді. Егер айнымалылар жалпыға қолжетімді болмаса, клиенттер оларға қол жеткізе алмас еді.
- статикалық - интерфейстерді құру мүмкін емес (дәлірек айтқанда, олардың an objectілері), сондықтан айнымалы статикалық.
- қорытынды - интерфейс 100% абстракцияға қол жеткізу үшін пайдаланылғандықтан, айнымалы өзінің соңғы түріне ие (және өзгертілмейді).
11. Classloader дегеніміз не және ол не үшін қолданылады?
Classloader - немесе Class Loader - Java сыныптарын жүктеуді қамтамасыз етеді. Дәлірек айтқанда, жүктеу оның ұрпақтарымен қамтамасыз етіледі - белгілі бір класты тиегіштер, өйткені ClassLoader өзі дерексіз. .class файлы жүктелген сайын, мысалы, конструкторды немесе сәйкес сыныптың статикалық әдісін шақырғаннан кейін, бұл әрекет ClassLoader класының ұрпақтарының бірі арқылы орындалады . Мұрагерлердің үш түрі бар:-
Bootstrap ClassLoader — JVM деңгейінде іске асырылған және орындалу ортасынан кері байланысы жоқ негізгі жүктеуші, өйткені ол JVM ядросының бөлігі және жергілікті codeта жазылған. Бұл жүктегіш барлық басқа ClassLoader даналарының ата-анасы ретінде қызмет етеді.
Негізінен JDK ішкі сыныптарын, әдетте rt.jar және $JAVA_HOME/jre/lib каталогында орналасқан басқа негізгі кітапханаларды жүктеуге жауапты . Әртүрлі платформаларда осы класс жүктеушісінің әртүрлі іске асырулары болуы мүмкін. -
Extension Classloader - кеңейту жүктеушісі, негізгі жүктеуші класының ұрпағы. Стандартты Java базалық сыныптарының кеңейтімін жүктеуге қамқорлық жасайды. JDK кеңейтімдері каталогынан жүктеледі, әдетте $JAVA_HOME/lib/ext немесе java.ext.dirs жүйелік сипатында аталған кез келген басқа каталог (бұл опцияны кеңейтімдердің жүктелуін басқару үшін пайдалануға болады).
-
System ClassLoader — JVM жүйесіне қолданба деңгейіндегі барлық сыныптарды жүктеуді қамтамасыз ететін JRE деңгейінде жүзеге асырылған жүйелік жүктеуші. Ол сынып ортасының айнымалы -classpath немесе -cp пәрмен жолы опциясында табылған файлдарды жүктейді.
-
System Classloader өзінің кэшінде сыныпты табуға тырысады.
-
1.1. Егер сынып табылса, жүктеу сәтті аяқталды.
-
1.2. Егер сынып табылмаса, жүктеу Extension Classloader-ге беріледі.
-
-
Extension Classloader сыныпты өзінің кэшінде табуға тырысады.
-
2.1. Егер сынып табылса, ол сәтті аяқталады.
-
2.2. Егер сынып табылмаса, жүктеу Bootstrap Classloader-ге беріледі.
-
-
Bootstrap Classloader сыныпты өзінің кэшінде табуға тырысады.
-
3.1. Егер сынып табылса, жүктеу сәтті аяқталды.
-
3.2. Егер сынып табылмаса, негізгі Bootstrap Classloader оны жүктеуге тырысады.
-
-
Жүктеп жатса:
-
4.1. Сәтті - сыныпты жүктеу аяқталды.
-
4.2. Егер ол сәтсіз болса, басқару кеңейтім класс жүктеушісіне тасымалданады.
-
-
5. Extension Classloader сыныпты жүктеуге тырысады, ал егер жүктелсе:
-
5.1. Сәтті - сыныпты жүктеу аяқталды.
-
5.2. Егер ол сәтсіз болса, басқару Жүйе Класс жүктеушісіне тасымалданады.
-
-
6. System Classloader класты жүктеуге тырысады, ал егер жүктелсе:
-
6.1. Сәтті - сыныпты жүктеу аяқталды.
-
6.2. Сәтті өтпеді - ерекше жағдай жасалды - ClassNotFoundException.
-
12. Орындалу уақыты деректер аймақтары дегеніміз не?
Run-Time Data Ares - JVM орындалу уақытының деректер аймақтары. JVM бағдарламаны орындау кезінде қажет кейбір орындалу уақытының деректер аймақтарын анықтайды. Олардың кейбіреулері JVM іске қосылғанда жасалады. Басқалары ағынды жергілікті болып табылады және ағын жасалғанда ғана жасалады (және жіп жойылған кезде жойылады). JVM жұмыс уақыты деректер аймақтары келесідей көрінеді:-
ДК тізілімі әрбір ағынға жергілікті болып табылады және ағын қазіргі уақытта орындалып жатқан JVM нұсқаулығының мекенжайын қамтиды.
-
JVM Stack — жергілікті айнымалылар мен уақытша нәтижелерді сақтау ретінде пайдаланылатын жад аймағы. Әрбір ағынның өзінің жеке стекі бар: ағын аяқтала салысымен бұл стек де жойылады. Айта кету керек, стектің үймеден артықшылығы өнімділік, ал үйменің сақтау масштабында артықшылығы бар.
-
Native Method Stack - жергілікті (Java емес) әдістерді орындау үшін JVM стекіне ұқсас деректер элементтерін сақтайтын әр ағындық деректер аймағы.
-
Үйме – барлық ағындар орындалу уақытында жасалған нысандарды, класс метадеректерін, массивтерді және т.б. қамтитын қойма ретінде пайдаланылады. Бұл аймақ JVM іске қосылғанда жасалады және ол өшірілгенде жойылады.
-
Әдіс аймағы - бұл орындалу аймағы барлық ағындар үшін ортақ және JVM іске қосылғанда жасалады. Ол әр сыныпқа арналған құрылымдарды сақтайды, мысалы, Runtime Constant Pool, конструкторлар мен әдістерге арналған code, әдіс деректері және т.б.
13. Өзгермейтін an object дегеніміз не?
Мақаланың осы бөлігінде , 14 және 15-сұрақтарда бұл сұраққа жауап бар, сондықтан уақытты босқа өткізбей қараңыз.14. String класының ерекшелігі неде?
Бұрын талдау барысында біз String-тің белгілі бір мүмкіндіктері туралы бірнеше рет айтқан болатынбыз (бұл үшін бөлек бөлім болған). Енді String мүмкіндіктерін қорытындылайық :-
Бұл Java тіліндегі ең танымал нысан және әртүрлі мақсаттарда қолданылады. Қолдану жиілігі бойынша ол тіпті қарабайыр түрлерден де кем түспейді.
-
Бұл сыныптың an objectісін new кілт сөзін қолданбай-ақ жасауға болады - тікелей тырнақшалар арқылы String str = “string”; .
-
Жол – өзгермейтін класс : осы класстың an objectісін жасау кезінде оның деректерін өзгерту мүмкін емес (белгілі бір жолға + «басқа жолды» қосқанда, нәтижесінде жаңа, үшінші жолды аласыз). String класының өзгермейтіндігі оны ағынды қауіпсіз етеді.
-
String класы аяқталды ( соңғы модификаторы бар ), сондықтан оны мұраға алу мүмкін емес.
-
Жолдың өз жолдық пулы, өзі жасайтын жол мәндерін кэштейтін үймедегі жады аймағы бар . Серияның осы бөлігінде , 62-сұрақта, мен жол пулын сипаттадым.
-
Java-да String аналогтары бар , сонымен қатар жолдармен жұмыс істеуге арналған - StringBuilder және StringBuffer , бірақ айырмашылығы олар өзгермелі. Олар туралы толығырақ осы мақалада оқи аласыз .
15. Типтік ковариация дегеніміз не?
Ковариантты түсіну үшін мысалды қарастырамыз. Бізде жануарлар класы бар делік:public class Animal {
void voice() {
System.out.println("*тишина*");
}
}
Және кейбір ит класы оны кеңейтеді :
public class Dog extends Animal {
@Override
public void voice() {
System.out.println("Гав, гав, гав!!!");
}
}
Еске салсақ, мұрагер түрінің нысандарын ата-ана түріне оңай тағайындай аламыз:
Animal animal = new Dog();
Бұл полиморфизмнен басқа ештеңе болмайды. Ыңғайлы, икемді емес пе? Ал, жануарлардың тізімі ше? Жалпы Animal бар тізімге Dog нысандары бар тізім бере аламыз ба ?
List<Dog> dogs = new ArrayList<>();
List<Animal> animals = dogs;
Бұл жағдайда жануарлар тізіміне иттердің тізімін тағайындау жолының асты қызыл түспен сызылады, яғни. компилятор бұл codeты өткізбейді. Бұл тапсырма әбден қисынды болып көрінгенімен (ақыр соңында, Animal түріндегі айнымалыға Dog нысанын тағайындай аламыз ), оны орындау мүмкін емес. Себебі, рұқсат етілсе, біз тізімде тек иттер бар деп ойлай отырып, бастапқыда ит болуға арналған тізімге Animal нысанын енгізе алатын едік . Содан кейін, мысалы, ит деп ойлап, иттер тізімінен нысанды алу үшін get() әдісін қолданамыз және ондағы Dog нысанының жануарда жоқ қандай да бір әдісін шақырамыз . Сіз түсінгендей, бұл мүмкін емес - қате пайда болады. Бірақ, бақытымызға орай, компилятор ата-аналар тізіміне ұрпақтар тізімін тағайындау арқылы бұл логикалық қатені жіберіп алмайды (және керісінше). Java тілінде сәйкес генериктері бар айнымалылар тізіміне тізім нысандарын ғана тағайындай аласыз. Бұл инвариация деп аталады. Егер олар мұны істей алса, ол ковариация деп аталады. Яғни, егер ArrayList<Dog> түріндегі нысанды List<Animal> түріндегі айнымалыға орната алатын болсақ, ковариация болып табылады . Java-да ковариацияға қолдау көрсетілмейді екен? Қалай болса да! Бірақ бұл өзіндік ерекше жолмен жасалады. Дизайн не үшін қолданылады ? Жануарды ұзартады . Ол тізім нысанын орнатқымыз келетін айнымалының жалпы белгісімен, ұрпақтың жалпыламасымен орналастырылған. Бұл жалпы құрылым Animal түрінің ұрпағы болып табылатын кез келген түр жасайтынын білдіреді (және Animal түрі де осы жалпыламаға жатады). Өз кезегінде Animal тек сынып қана емес, сонымен қатар интерфейс болуы мүмкін ( extens кілт сөзіне алданып қалмаңыз ). Алдыңғы тапсырмамызды келесідей орындай аламыз:
List<Dog> dogs = new ArrayList<>();
List<? extends Animal> animals = dogs;
Нәтижесінде IDE-де компилятор бұл құрылысқа шағымданbyteынын көресіз. Осы дизайнның функционалдығын тексерейік. Бізде оған өткен барлық жануарлардың дыбыс шығаруына себеп болатын әдіс бар делік:
public static void animalsVoice(List<? extends Animal> animals) {
for (Animal animal : animals) {
animal.voice();
}
}
Оған иттердің тізімін берейік:
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
dogs.add(new Dog());
animalsVoice(dogs);
Консольде біз келесі нәтижені көреміз:
List<Dog> dogs = new ArrayList<>();
List<? extends Animal> animals = dogs;
animals.add(new Dog());
dogs.add(new Animal());
Шын мәнінде, соңғы екі жолда компилятор нысандарды қызыл түспен кірістіруді ерекшелейді. Бұл қандай типтегі нысандар тізімі жалпы <<? Animal> кеңейтеді . Мен контрварианстық туралы да айтқым келеді , өйткені әдетте бұл ұғым әрқашан коварианспен бірге жүреді және әдетте олар туралы бірге сұралады. Бұл концепция коварианттыққа біршама қарама-қарсы, өйткені бұл құрылым мұрагер түрін пайдаланады. Біз Dog нысанының ата-бабалары болып табылмайтын типтік нысандардың тізімін тағайындауға болатын тізімді алғымыз келеді делік . Дегенмен, олардың нақты қандай түрлері болатынын алдын ала білмейміз. Бұл жағдайда пішіннің құрылысы ? супер ит , оның барлық түрлері қолайлы - ит класының тектері :
List<Animal> animals = new ArrayList<>();
List<? super Dog> dogs = animals;
dogs.add(new Dog());
dogs.add(new Dog());
Біз Dog типті нысандарды тізімге осындай генерикпен қауіпсіз түрде қоса аламыз , өйткені кез келген жағдайда оның кез келген ата-бабаларының барлық енгізілген әдістері бар. Бірақ біз Animal түріндегі нысанды қоса алмаймыз , өйткені оның ішінде, мысалы, Dog емес, осы түрдегі нысандар болатынына сенімділік жоқ . Ақыр соңында, біз осы тізімнің элементінен Animal- да жоқ Dog класының әдісін сұрай аламыз . Бұл жағдайда компиляция қатесі орын алады. Сондай-ақ, егер біз алдыңғы әдісті жүзеге асырғымыз келсе, бірақ осы жалпы әдіспен:
public static void animalsVoice(List<? super Dog> dogs) {
for (Dog dog : dogs) {
dog.voice();
}
}
for циклінде компиляция қатесін алатын едік , өйткені қайтарылған тізімде Dog түріндегі нысандар бар екеніне және оның әдістерін еркін пайдалануға болатынына сенімді бола алмаймыз. Бұл тізімдегі dogs.get(0) әдісін шақырсақ . - Object типті an objectіні аламыз . Яғни, animalsVoice() әдісі жұмыс істеуі үшін , кем дегенде, деректер түрін тарылту арқылы шағын манипуляцияларды қосу керек:
public static void animalsVoice(List<? super Dog> dogs) {
for (Object obj : dogs) {
if (obj instanceof Dog) {
Dog dog = (Dog) obj;
dog.voice();
}
}
}
GO TO FULL VERSION