Ən yaxşı 50 Java Əsas Müsahibə Sualları və Cavabları. 1-ci hissə
Kolleksiyalar
25. Java-da Collections dedikdə nə nəzərdə tutulur?
Kolleksiya obyektləri saxlamaq və manipulyasiya etmək üçün nəzərdə tutulmuş çərçivədir. Aşağıdakı əməliyyatları yerinə yetirmək üçün istifadə olunur:- axtarış;
- çeşidləmə;
- manipulyasiya;
- əlavə;
- silinmə.
java.util
.
26. Collection çərçivəsində hansı siniflər və interfeyslər mövcuddur?
İnterfeyslər:- Kolleksiya;
- Siyahı;
- Set;
- Xəritə;
- Sorted Set;
- Sorted Map;
- Növbə.
- Siyahılar:
- ArrayList;
- LinkedList;
- Vektor (köhnəlmişdir).
- Dəstlər:
- HashSet;
- LinkedHashSet;
- TreeSet.
- Xəritələr:
- HashMap
- TreeMap
- HashTable (köhnəlmişdir)
- LinkedHashMap
- Növbə
- Prioritet növbəsi.
27. Kolleksiyalarda çeşidlənmiş və sıralanmış dedikdə nə başa düşülür?
Sifariş verildi:
Bu o deməkdir ki, kolleksiyada saxlanılan əşyalar kolleksiyaya əlavə edilmiş dəyərlərə əsaslanır. Beləliklə, kolleksiyadakı dəyərləri müəyyən bir ardıcıllıqla təkrarlaya bilərik. Başqa sözlə desək, bu o deməkdir ki, kolleksiyanın elementlərinin özünəməxsus düzülüşü var, ona görə düzülür. Daha yaxşı başa düşmək üçün sifariş olunmayan kolleksiya öz elementlərini təsadüfi qaydada saxlayır. Məsələn, Set.Çeşidləndi:
Bu o deməkdir ki, bir qrup element kolleksiya elementinin məlumatlarına əsasən kolleksiyaya çeşidlənir. Yəni təkcə kolleksiya sifariş olunmur, həm də elementlərin sırası onların dəyərlərindən asılıdır. Fərqli element dəyərinə görə çeşidləsəniz, bu sıra dəyişə bilər.28. List interfeysi ilə hansı kolleksiyalar var? List ilə necə işləyirsiniz?
Vərəqdəki elementlərin dəyərləri onların indeksinə əsaslanır - onlar indekslə sıralanır. Elementlərin təkrarlanmasına icazə verilir (yəni, eyni obyekti kolleksiyaya bir neçə dəfə əlavə edə bilərsiniz və yaxşı olacaq).ArrayList:
Ən çox yayılmış kolleksiya. Əslində, dinamik olaraq genişlənən ölçüsü olan bir massivdir. Massivin ölçüsünü idarə etmək işi kolleksiyanın üzərinə düşür. Əksər hallarda bundan istifadə etməli olduğumuzu başa düşmək bizim üçün vacibdir. Xüsusiyyətlər:- sürətli axtarış və sürətli indeks axtarışı;
- kolleksiya indeks üzrə sıralanır, lakin çeşidlənmir;
- RandomAccess interfeysini həyata keçirir;
- yavaş-yavaş siyahının ortasına əlavə olunur.
public class A {
public static void main(String[] args) {
ArrayList names = new ArrayList<>();
names.add("John");
names.add("John");
names.add("Roman");
names.add("Ivan");
}
}
>> çıxış
[John, John, Roman, Ivan]
Çıxış göstərir ki, bunlar təkrarlana bilən elementlərdir. Onlar qeydə alındıqları ardıcıllıqla göstərilir. Başqa nə oxumalı? Bəli, çoxlu məlumat var, hətta JavaRush-u tərk etməyə ehtiyac yoxdur:
Əlaqədar Siyahı:
Bu, hər bir elementin əvvəlki və sonrakı elementlərlə əlaqəsi olan kolleksiyadır. Bu keçidlər bir elementdən digərinə keçməyə imkan verir. Element əlavə edərkən əvvəlki və sonrakı elementlərə keçidlər sadəcə olaraq dəyişir:- elementlər bir-birinə bağlıdır, yəni ikiqat əlaqəli siyahı həyata keçirilir;
- ümumi əməliyyat sürəti ArrayList-dən nəzərəçarpacaq dərəcədə aşağıdır;
- massivin ortasına çoxlu sayda əlavələr və silmələr üçün əla seçimdir;
- Queue və Deque siyahısı interfeyslərini həyata keçirir və buna görə də onların işləmə üsullarına malikdir.
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("One");
linkedList.add("Two");
linkedList.add("Three");
29. Xəritə kolleksiyası və onun tətbiqi haqqında bizə məlumat verin?
Xəritə əsas dəyər kolleksiyasıdır. Unikal açar və bu dəyərə uyğun dəyər var. Açarın unikallığını müəyyən etmək üçün metodlardanequals()
da istifadə olunur.hashcode()
HashMap:
- çeşidlənməmiş və sifariş edilməmişdir;
- sifariş və çeşidləmə vacib olmadıqda istifadə olunur;
- null düyməsini dəstəkləyir.
public class CollectionExample {
public static void main(String[] args) {
HashMap positions = new HashMap<>();
positions.put("junior", "Ivan");
positions.put("middle", "Roman");
positions.put("senior", "Vasily");
positions.put("team lead", "Anton");
positions.put("arthitect", "Andrew");
positions.put("senior", "John");
System.out.println(positions);
}
}
// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}
Açarlar həmişə unikaldır, ona görə də yalnız bir yaşlı qeydə alınır.
LinkedHashMap:
- daxiletmə qaydasını saxlayır;
- HashMap-dən daha yavaş;
- iterasiyanın HashMap-dan daha sürətli olacağı gözlənilir.
public class CollectionExample {
public static void main(String[] args) {
LinkedHashMap<String, String> positions = new LinkedHashMap<>();
positions.put("junior", "Ivan");
positions.put("middle", "Roman");
positions.put("senior", "Vasily");
positions.put("team lead", "Anton");
positions.put("arthitect", "Andrew");
positions.put("senior", "John");
System.out.println(positions);
}
}
// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}
TreeMap:
Girişləri açarlarının təbii sırasına görə sıralayan və ya daha yaxşısı, xəritə yaradılarkən konstruktorda təmin edildiyi təqdirdə müqayisəedicidən istifadə edən xəritə tətbiqi. Misal:-
Müqayisəsiz
public class CollectionExample { public static void main(String[] args) { TreeMap<Integer, String> positions = new TreeMap<>(); positions.put(1, "Ivan"); positions.put(3, "Roman"); positions.put(2, "Vasily"); positions.put(10, "Anton"); positions.put(7, "Andrew"); positions.put(1, "John"); System.out.println(positions); } } // вывод в консоль // {1=John, 2=Vasily, 3=Roman, 7=Andrew, 10=Anton}
-
Müqayisə ilə
public class CollectionExample { public static void main(String[] args) { //используем реализацию Strategy Pattern'a и добавим компаратор: TreeMap<Integer, String> positions = new TreeMap<>(Comparator.reverseOrder()); positions.put(1, "Ivan"); positions.put(3, "Roman"); positions.put(2, "Vasily"); positions.put(10, "Anton"); positions.put(7, "Andrew"); positions.put(1, "John"); System.out.println(positions); } } // вывод в консоль // {10=Anton, 7=Andrew, 3=Roman, 2=Vasily, 1=John}
30. Set kolleksiyası və onun həyata keçirilməsi haqqında bizə məlumat verin?
Dəst unikal elementlər toplusudur və bu onun əsas xüsusiyyətidir. Yəni Set eyni elementlərin təkrarlanmasına icazə vermir. Burada əlavə olunan obyektlərin həyata keçirilən metodu olması vacibdirequals
.
HashSet:
- çeşidlənməmiş və sifariş edilməmişdir. Başlıq altında dəyər üçün yer tutucusu olan HashMap var. Özünüz baxın ;)
- obyektləri əlavə etmək üçün hashCode istifadə edir;
- Unikal obyektlərə sahib olmaq lazım olduqda istifadə edilməlidir və onların sırası vacib deyil.
public class CollectionExample {
public static void main(String[] args) {
HashSet<String> positions = new HashSet<>();
positions.add("junior");
positions.add("junior");
positions.add("middle");
positions.add("senior");
positions.add("team lead");
positions.add("architect");
System.out.println(positions);
}
}
// вывод в консоль
// [senior, middle, team lead, architect, junior]
Burada iki dəfə əlavə edilmiş "kiçik" elementin yalnız bir nümunədə olduğunu görə bilərsiniz. Və sifariş əlavə edərkən olduğu kimi deyil.
LinkedHashSet:
- HashSet-in sifarişli versiyası;
- bütün elementlər üçün ikiqat əlaqəli siyahını dəstəkləyir;
- İterasiyanızda sifariş lazım olduqda istifadə edin.
public class CollectionExample {
public static void main(String[] args) {
LinkedHashSet<String> positions = new LinkedHashSet<>();
positions.add("junior");
positions.add("junior");
positions.add("middle");
positions.add("senior");
positions.add("team lead");
positions.add("architect");
System.out.println(positions);
}
}
// вывод в консоль
// [senior, middle, team lead, architect, junior]
Ağac dəsti:
- iki çeşidlənmiş kolleksiyadan biri;
- qırmızı-qara ağac quruluşundan istifadə edir və elementlərin artan ardıcıllıqla olmasını təmin edir;
- Başlıq altında bu, dəyərlər üzərində qaralama ilə TreeMap var. Və TreeSet elementləri TreeMap-ın açarlarıdır (həmçinin bax;)).
public class CollectionExample {
public static void main(String[] args) {
TreeSet<String> positions = new TreeSet<>();
positions.add("junior");
positions.add("junior");
positions.add("middle");
positions.add("senior");
positions.add("team lead");
positions.add("architect");
System.out.println(positions);
}
}
// вывод в консоль
// [architect, junior, middle, senior, team lead]
İstisnalar
31. İstisna nədir?
İstisna icra zamanı baş verə biləcək problemdir. Bu, müəyyən səbəblərdən yaranan müstəsna bir vəziyyətdir. İstisna irsi diaqramı belə görünür (bunu əzbər bilmək lazımdır ;)): Diaqram göstərir ki, ümumiyyətlə, bütün istisnalar iki qrupa bölünür - istisnalar və səhvlər. Xəta - JVM-lər səhvləri göstərmək üçün istifadə olunur, bundan sonra tətbiqin mənası yoxdur. Məsələn, yığının dolu olduğunu və proqramın artıq işləyə bilməyəcəyini söyləyən StackOverFlowError. İstisna - kodda proqramlı şəkildə yaradılan istisnalar. Yoxlanılan və yoxlanılan müxtəlif istisnalar var, amma əsas odur ki, onlar mövcuddur və onlar tutula bilər və tətbiq işləməyə davam edə bilər. İstisnalar, öz növbəsində, RuntimeException-dan miras qalanlara və İstisnanın digər nəslinə bölünür. Bu məsələ ilə bağlı kifayət qədər məlumat var. Aşağıda yoxlanılan/işlənilməmiş istisnaların nə olduğu barədə danışacağıq.32. JVM istisnaları necə idarə edir?
Bu necə işləyir? İstisna harasa atılan kimi iş vaxtı İstisna Obyekti yaradır (ExcObj kimi qeyd olunur). İş üçün lazım olan bütün məlumatları saxlayır - atılan istisnanın özü və baş verdiyi yer. YaradılmasıExcObj
və icra müddətinə ötürülməsi “istisna atmaqdan” başqa bir şey deyil. ExcObj
istisnanın atıldığı yerə çatmaq üçün istifadə edilə bilən üsulları ehtiva edir. Bu üsullar toplusu Call Stack adlanır. Sonra, iş vaxtı sistemi İstisnamızı idarə edə biləcək Zəng Yığmasında bir metod axtarır. Əgər o, müvafiq işləyici tapırsa, yəni istisna növü işləyicidəki tipə uyğun gəlirsə, hər şey qaydasındadır. Əgər onu tapmasa, iş vaxtı hər şeyi cavab hazırlayan və çıxış edən standart istisna işləyicisinə keçir. Vizual olaraq necə görünür:
/**
* Пример, в котором показываются две опции — когда находится обработчик для исключения и когда нет.
*/
class ThrowerExceptionExample {
public static void main(String[] args) throws IllegalAccessException {
ThrowerExceptionExample example = new ThrowerExceptionExample();
System.out.println(example.populateString());
}
/**
* Здесь происходит перехват одного из возможных исключений — {@link IOException}.
* А вот второй будет пробрасываться дальше вверх по вызову.
*/
private String populateString() throws IllegalAccessException {
try {
return randomThrower();
} catch (IOException e) {
return "Caught IOException";
}
}
/**
* Здесь две опции: or бросается {@link IOException} or {@link IllegalAccessException}.
* Выбирается случайным образом.
*/
private String randomThrower() throws IOException, IllegalAccessException {
if (new Random().nextBoolean()) {
throw new IOException();
} else {
throw new IllegalAccessException();
}
}
}
Bizim vəziyyətimizdə CallStack sxematik olaraq belə görünəcək:
randomThrower() => populateString() => main(String[] args)
İki seçim var: bir və ya digər istisna təsadüfi olaraq atılacaq. IOException üçün hər şey qaydasındadır, əgər yaradılıbsa, işin nəticəsi belə olacaq: "Caught IOException"
. Ancaq işləyici olmayan ikinci bir istisna varsa, proqram aşağıdakı çıxışla dayanacaq:
Exception in thread "main" java.lang.IllegalAccessException
at ThrowerExceptionExample.randomThrower(CollectionExample.java:38)
at ThrowerExceptionExample.populateString(CollectionExample.java:24)
at ThrowerExceptionExample.main(CollectionExample.java:15)
33. Proqramçılar istisnaları necə idarə edirlər?
Yuxarıdakı suallarda istisnalarla işləmək üçün artıq müəyyən açar sözlərdən istifadə etmişik, indi onlar haqqında daha ətraflı danışmalıyıq. Açar sözlər hansılardır?- cəhd edin
- tutmaq
- atmaq
- atır
- nəhayət
try-catch-finally
bir istisnanı düzgün tutmağa və idarə etməyə imkan verən konstruksiyadır.try
- yalnız bir zaman ola bilər, məntiq burada baş verir;catch
— bir növ istisna qəbul edən blok; onların çoxu ola bilər. Məsələn, bir sınaq bloku bir-biri ilə heç bir əlaqəsi olmayan bir neçə istisna atacaq;finally
- "nəhayət" bu blok. Bu, try, catch-da nə edildiyindən asılı olmayaraq istənilən halda icra olunacaq blokdur.
try {
// сюда передают тот code, который может вызвать исключение.
} catch (IOException e) {
// первый catch блок, который принимает IOException и все его подтипы(потомки).
// Например, нет file при чтении, выпадает FileNotFoundException, и мы уже соответствующе
// обрабатываем это.
} catch (IllegalAccessException e) {
// если нужно, можно добавить больше одного catch блока, в этом нет проблем.
} catch (OneException | TwoException e) {
// можно даже объединять несколько в один блок
} catch (Throwable t) {
// а можно сказать, что мы принимаем ВСЁ))))
} finally {
// этот блок может быть, а может и не быть.
// и он точно выполнится.
}
Nümunənin təsvirini diqqətlə oxuyun və hər şey aydın olacaq)
34. Java-da atmaq və atmaq
atmaq
throw
açıq şəkildə yeni bir istisna yaratmaq lazım olduqda istifadə olunur. Xüsusi istisnalar yaratmaq və atmaq üçün istifadə olunur. Məsələn, doğrulama ilə bağlı istisnalar. Adətən, doğrulama üçün onlar miras alırlar RuntimeException
. Misal:
// пример пробрасывания исключения
throw new RuntimeException("because I can :D");
Bu konstruksiyanın yalnız ondan miras qalan bir şey tərəfindən istifadə edilə bilməsi vacibdir Throwable
. Yəni bunu deyə bilməzsiniz:
throw new String("How тебе такое, Илон Маск?");
Sonra, mövzunun işi dayandırılır və onu emal edə biləcək bir işləyici üçün axtarış başlayır. Onu tapmadıqda, onu çağıran metoda keçir və buna görə də axtarış müvafiq işləyicini tapana və ya tətbiqi işlək vəziyyətdə saxlayana qədər zənglər cərgəsinə qalxacaq. Baxaq:
// Пример, который демонстрирует работу throw
class ThrowExample {
void willThrow() throws IOException {
throw new IOException("Because I Can!");
}
void doSomething() {
System.out.println("Doing something");
try {
willThrow();
} catch (IOException e) {
System.out.println("IOException was successfully handled.");
}
}
public static void main(String args[]) {
ThrowExample throwExample = new ThrowExample();
throwExample.doSomething();
}
}
Proqramı işə salsaq, aşağıdakı nəticəni alırıq:
Doing something
IOException was successfully handled.
atır
throws
— metodun bir və ya daha çox istisnaları ata biləcəyi mexanizm. Onlar vergüllə ayrılaraq əlavə olunur. Bunun nə qədər asan və sadə olduğunu görək:
private Object willThrow() throws RuntimeException, IOException, FileNotFoundException
Üstəlik, qeyd etmək lazımdır ki, həm yoxlanılmış, həm də yoxlanılmamış istisnalar ola bilər. Əlbəttə ki, yoxlanılmamış istisnalar əlavə edilə bilməz throws
, lakin yaxşı davranışlar bunun əksini deyir. Bunlar yoxlanıla bilənlərdirsə, onları yaradan metoddan istifadə edərək, birtəhər emal etməlisiniz. İki seçim var:
try-catch
Müvafiq və yuxarıdakı miras istisnası ilə yazın .throws
Ondan eyni şəkildə istifadə edin ki, başqasının artıq bu problemi var :D
35. Java-da yoxlanılmış və yoxlanılmış istisnalar
Java-da iki növ istisna var - yoxlanılmış və işarəsiz.Yoxlanmış istisnalar:
Bunlar kompilyasiya zamanı yoxlanılan istisnalardır. İstisna zamanı metoddakı bəzi kod yoxlanılmış istisnanı atırsa, metod onu ya istifadə edərək emal etməlitry-catch
, ya da onu daha da irəli göndərməlidir. Məsələn, "/users/romankh3/image.png" yolundan şəkli oxuyan onu yeniləyir. bir şəkildə (bizim üçün bu vacib deyil) və onu geri saxlayır.
class CheckedImageExample {
public static void main(String[] args) {
File imageFile = new File("/users/romankh3/image.png");
BufferedImage image = ImageIO.read(imageFile);
updateAndSaveImage(image, imageFile);
}
private static void updateAndSaveImage(BufferedImage image, File imageFile) {
ImageIO.write(image, "png", imageFile);
}
}
Bu cür kod tərtib edilməyəcək, çünki statik metodlar yoxlanılan və müvafiq olaraq idarə edilməli olan IOException ImageIO.read()
atır . ImageIO.write()
Burada artıq yuxarıda müzakirə etdiyimiz iki seçim var: ya istifadə edin try-catch
, ya da irəli. Daha yaxşı assimilyasiya üçün biz bunu və bunu edəcəyik. Yəni, updateAndSave
biz onu yalnız metodda yönləndirəcəyik və sonra əsas metodda istifadə edəcəyik try-catch
:
class CheckedImageExample {
public static void main(String[] args) {
File imageFile = new File("/users/romankh3/image.png");
try {
BufferedImage image = ImageIO.read(imageFile);
updateAndSaveImage(image, imageFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void updateAndSaveImage(BufferedImage image, File imageFile) throws IOException {
ImageIO.write(image, "png", imageFile);
}
}
Yoxlanılmamış istisnalar:
Bunlar tərtib mərhələsində yoxlanılmayan istisnalardır. Yəni, metod RuntimeException yarada bilər, lakin kompilyator onu necə idarə etməyi sizə xatırlatmayacaq. Aşağıda göstərildiyi kimi, bizdə RuntimeException-dan miras qalan hər şey var və Xəta yoxlanılıb. Aşağıdakı Java proqramını nəzərdən keçirin. Kod yaxşı tərtib edilir, lakin işə salındıqda istisna yaradırArrayIndexOutOfBoundsException
. Kompilyator onu tərtib etməyə icazə verir, çünki ArrayIndexOutOfBoundsException
bu, yoxlanılmamış bir istisnadır. Massivlə bağlı ümumi vəziyyət, ola bilər:
class CheckedImageExample {
public static void main(String[] args) {
int[] array = new int[3];
array[5] = 12;
}
}
Nəticə belə olacaq:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at main(CheckedImageExample.java:12)
Yeri gəlmişkən, Java-da heç kimin qısa adlar vermədiyini görmüsünüzmü? Nə qədər böyük olsa, bir o qədər yaxşıdır. O, Spring Framework bu işdə çox müvəffəq oldu: sadəcə BeanFactoryPostProcessor sinfini götürün)))
36. Resursları sınamaq hansılardır?
Bu, bütün resursların düzgün bağlanmalı olduğu mexanizmdir. Bu, bir növ aydın deyil, elə deyilmi?) Əvvəla, resurs nədir... Resurs bir obyektdir, onunla işlədikdən sonra onu bağlamaq lazımdır, yəniclose()
. Resurs interfeysi həyata keçirən bütün obyektlərdir AutoClosable
, o da öz növbəsində interfeysi həyata keçirir Closeable
. InputStream
Hər şeyin bir resurs olduğunu OutpuStream
və düzgün və uğurla buraxılması lazım olduğunu başa düşmək bizim üçün vacibdir . try-with-resource
Məhz buna görə də strukturdan istifadə etməliyik . Göründüyü kimi:
private void unzipFile(File zipFile) throws IOException {
try(ZipInputStream zipOutputStream = new ZipInputStream(new FileInputStream(zipFile))) {
ZipEntry zipEntry = zipOutputStream.getNextEntry();
while (zipEntry != null) {
}
}
}
private void saveZipEntry(ZipEntry zipEntry) {
// логика сохранения
}
Bu nümunədə resurs ZipInputStream
, işlədikdən sonra onu bağlamalı olacaqsınız. Və metodu çağırmaq barədə düşünməmək üçün close()
biz sadəcə olaraq bu dəyişəni nümunədə göstərildiyi kimi try blokunda təyin edirik və bu blok daxilində lazım olan hər şeyi edirik. Nümunə nə edir? Zip arxivini açacaq. Bunu etmək üçün 'om istifadə etməlisiniz InputStream
. Birdən çox dəyişən təyin edə bilərsiniz, onlar nöqtəli vergüllə ayrılır. Problem nədir? Ancaq bir blokdan istifadə edə bilərsiniz finally
, deyə bilərsiniz. Bu yanaşma ilə bağlı problemləri ətraflı izah edən bir məqalə . O, həmçinin bu dizayndan istifadə etməyə laqeyd yanaşan birinin başına gələ biləcək uğursuzluqların bütün siyahısını təsvir edir. Onu oxumağı məsləhət görürəm ;) Yekun hissədə Multithreading mövzusunda suallar/cavablar var. Mənim GitHub profilim
GO TO FULL VERSION