Често задавани въпроси в интервю за Java програмист

Blinky

Administrator
Екип
1. С какво се характеризира обектно ориентираното програмиране?
За да бъде един програмен език обектно-ориентиран, той трябва не само да позволява работа с класове и обекти, но и трябва да дава възможност за имплементирането и използването на принципите и концепциите на ООП: наследяване, абстракция, капсулация и полиморфизъм.

2. Кои IDEs за работа с JAVA познавате?
Eclipse, IntelliJ IDEA, NetBeans, Java Inventor, NaviCoder, Jcoder Java, SkyIDE, Enide Studio, ObjectScript, DrJava, Javelin, Asterix IDE, jEdit, jGRASP, JSource, JotAzul

3. Какво означава API?
Приложно-програмният интерфейс (на английски: Application Programming Interface, API) e интерфейсът на изходния код, който операционната система или нейните библиотеки от ниско ниво предлагат за поддръжката на заявките от приложния софтуер или компютърните програми.

4. Каква е разликата между абстрактен клас и интерфейс?
Разликата между абстрактен клас и интерфейс може да се определи по следния начин: един клас който е абстрактен може да има имплементация на някой от методите си докато интерфейса няма имплементация на неговите методи, той съдържа единствено декларация на методи.

Когато клас наследява интерфейс, то тогава класа трябва да имплементира всичките методи или свойства на интерфейса. В случай, че клас наследи интерфейс, който пък наследява друг интерсфейс, то тогава класа трябва да имплементира всички свойства и методи на двата интерфейса.

Абстрактният клас е клас който е създаден да се наследява и неможе да съществува самостоятелно.

5. Каква е разликата между обект и клас?
Клас (class) наричаме описание на даден обект от реалността. Класът представлява шаблон, който описва видовете състояния и поведението на обектите (екземплярите), които биват създавани от този клас (шаблон).

Обект (object) наричаме екземпляр създаден по дефиницията (описанието) на даден клас. Когато един обект е създаден по описанието, което един клас дефинира, казваме, че обектът е от тип "името на този клас".

6. Какво означава един метод да е абстрактен?
Абстрактите методи се декларират с модификатор abstract, с което се указва, че това са само прототипи на методи - отстъства тялото на метода.

Абстрактните методи са само декларирани, но не са реални. Тяхната реализация задължително се извършва с подкласа. Класовете, които съдържат поне един абстрактен метод се декларират като абстрактни със същия модификатор abstract.

7. Какво означава инстанция?
Създаването на обект от вече дефиниран клас наричаме инстанциране (instantiation). Инстанция (instance) е фактическият обект, който се създава от класа по време на изпълнение на програмата. Всеки обект е инстанция на конкретен клас.

8. Какво означава конструктор?
Конструктор (constructor) – това е псевдометод, който се използва за създаване на нови обекти.

9. Какво е Garbage Collector?
Garbage collection (GC) е форма на автоматичен мениджър на паметта. Той се опитва да регенерира боклука или паметта, която се заема от обекти, които вече не се използват от програмата. Често се стартира, когато се изчерпва паметта на работещото приложението.

++ В Java съществуват 3 типа генерации на Garbage Collection: Млада генерация - повечето от ново създадените обекти са локализирани там. Тъй като някои обекти стават нечетими, много от тях се създават в младата генерация, а след това изчезват. Обектите, които не стават нечетими и оцеляват от младата генерация се записани тук. По-голяма е от младата генерация. Постоянната (трета) генерация запазва класовете или ограничава символните низове. Тази област определено не е за обекти, които са оцелее след старата генерация, за да останат постоянни. В .Net са 4 типа.

10. Какво означава статична променлива?
Полета, които се наричат статични променливи. Те са общи за всички обекти от даден клас. Тяхната декларация изисква поставянето на специалната дума static пред типа на обекта.

11. Каква е разликата между private и protected?
Ако наследяването е тип protected, то се допуска достъп до членовете на неговия собствен клас, на неговия базов клас, но не се допуска достъп на функции външни за класа. Ако наследяването е тип private, то производният клас няма достъп до private елементите на базовия клас и външни функции.

12. Как трябва да се дефинира метод, който хвърля Exception дефиниран в програмата?
Изключенията се предизвикват или "хвърлят" (throw an exception) от програмен код, който трябва да сигнализира на изпълняващата се програма за грешка или необичайна ситуация. Например ако се опитваме да отворим файл, който не съществува, кодът, който отваря файла, ще установи това и ще хвърли изключение с подходящо съобщение за грешка.

13. Защо казваме, че класът String е immutable?
Класът String има важна особеност - последователностите от символи, записани в променливата от класа, са неизменими (immutable). Веднъж записано, съдържанието на променливата не се променя директно -ако опитаме да променим стойността, тя ще бъде записана на ново място в динамичната памет, а променливата ще започне да сочи към него.

14. Какъв подход бихте избрали при генериране на дълъг символен низ?
Използването на StringBuilder – диманичен обект, даващ възможност да се разшири броя на символите в низа, като посочим стойност за максималния брой знаци, който може да побере.

15. Може ли абстрактен клас да наследява друг абстрактен клас?
Да.
 
16. С какво се отличават абстрактните методи?
Абстрактни са тези методи в клас, чиято реализация не е имплементирана. С други думи ние сме декларирали, че такъв метод трябва да има, но той все още не е описан как ще работи. Класове, които съдържат в себе си абстрактни методи наричаме „абстрактни класове“.

17. Какво означава една колекция да е Generic?
Generic колекция може да присвоява променливи от различен тип.

18. Какво е характерно за типът данни Queue и кога бихте го използвали?
Queue или още познато като опашката представлява Generic и може да работи със всички типове обекти. Структурата от данни тук е стек от тип FIFO (first in first out - първият влязъл елемент „излиза“ първи). Използваме я когато искаме да имплементираме свързах списък - add вкарва елемент в колекцията, а remove - изкарва.

19. Какво е означава overloading на функция?
Overload функции, т.е работят по натоварване. Такива фунцкии или процедури се наричат, overloaded, когато са декларирани фунции с едно и също име, с разлика вид и брой аргументи. При извикване на такива функции, зависи от това какви агрументи са подадени, за да се включи съответната функция.

20. Има ли значение как са подредени catch блоковете при прихващане на Exceptions?
Да, има. Добра практика е всяко възможно изключение в програмния код да се прихваща и да е обработва. Един try..catch..finally блок може да има множество catch части ако искаме да прихващаме изключение от различен тип. Винаги по-конкретните изключения трябва да стоят в по-преден блок, а общият клас за всички изключения (Exception) да бъде последен.

21. С какво трябва да внимаваме при работа с потоци?
Съществуват двата основни типа потоци в Java – текстови и бинарни. Текстовите потоци служат за четене и писане на текстова информация, а бинарните – за четене и писане на двоична информация. Базов за всички входни текстови потоци е интерфейсът java.io.Reader, а за всички изходни текстови потоци – java.io.Writer. Винаги при четене от текстови потоци е възможно да бъдат прочетени по-малко на брой символи, отколкото са заявени и това е една от важните особености, с които трябва да се съобразяваме, когато четем от текстови потоци. Много удобен за четене от текстови потоци е класът java.io.BufferedReader, защото предлага метод за четене на цял текстов ред readLine(), а това често се налага.

22. Можем ли да извикаме един конструктор от друг конструктор в JAVA?
При наследяване на един клас, нашите конструктори задължително трябва да извикат конструктор на базовия клас, за да може и той да инициализира член-променливите си. Ако не го направим изрично, в началото на всеки наш конструктор компилаторът поставя извикване на базовия конструктор без параметри: super(). Ако базовият клас няма конструктор по подразбиране (без параметри), нашите конструктори трябва да извикат изрично някои от другите конструктори на базовия клас. Липсата на изрично извикване предизвиква грешка при компилация.

23. Какво знаете за методът toString?
Един от най-използваните методи, идващи от класа Object, е toString(). Той връща текстово представяне на обекта. Всеки обект има такъв метод и следователно всеки метод има текстово представяне. Този метод се използва, когато отпечатваме обект чрез System.out.println().

24. Трябва ли main методът на една програма да бъде static?
Да. Най-простият пример за метод е "Main(…)", който винаги го декларираме между отварящата и затварящата скоба на нашия клас. Методът е достъпен извън класа, което е необходимо за да може да бъде извикан метода от интерпретатора.

25. Трябва ли всеки try блок да бъде последван от catch блок?
Всяка една catch-секция трябва да се асоциира с try-блок. В един try-блок се групират един или повече оператори, които могат да генерират изключения с една или повече catch-секции, но може и да се асоциира или само с finally-блок. Catch не е задължителен, ако присъства finally.

26. Кога бихте използвали private конструктор?
Правилното използване на Private конструктора е в Singleton Pattern. По този начин можем да гарантираме, че само една инстанция на класа е активна. Друга негова употреба може да създаде удобен клас, който съдържа само статични методи.

27. Кога използваме break в JAVA?
Операторът break се използва за преждевременно излизане от цикъл, преди той да е завършил изпълнението си по естествения си начин. При срещане на оператора break цикълът се прекратява и изпълнението на програмата продължава от следващия ред веднага след тялото на цикъла. Прекратяването на цикъл с оператора break може да стане само от неговото тяло, когато то се изпълнява в поредната итерация на цикъла. Когато break се изпълни кодът след него в тялото на цикъла се прескача и не се изпълнява.

28. Може ли interface да наследява друг интерфейс?
Да, един interface може да наследи друг interface.

29. Какво е byte code?
За разлика от читаемият от човека изходен код, bytecodes са компактни цифрови кодове, константи, както и препратки (обикновено числови адреси), които кодират резултата от разбора (parsing) и семантичния анализ на нещата като вид, обхват и дълбочинно "гнездене (nesting)" на програмните обекти. Следователно, те позволяват много по-добра производителност от директната интерпретация на изходния код.

30. Как и защо сравняваме Strings в JAVA?
В Java проверката дали два стрингови низа са еднакви (съдържат еднакви символи) става посредством метода equals. Стандартното сравняване посредством оператора == сравнява референциите в паметта. В по-новите версии на Java операторът == сравнява по стойност.

Допълнителни:

1. Каква е разликата между префиксен и постфиксен запис?

Полският запис, още префиксен запис, е форма на логически, аритметичен и алгебричен запис (нотация), разработен от полския математик Ян Лукашевич около 1920 година с цел улесняване на съждителното смятане. Негова отличителна черта е, че операторите се поставят пред (вляво от) операндите и четенето (оценяването) на израза се извършва отляво надясно (-ab). Постфиксният запис (Обратен полски запис) е обратен запис, където четенето се извършва от дясно на ляво (ab-).

2. Каква е разликата между While и Do While?

Циклите do-while (прави-докато) са подобни на циклите while, с тази разлика, че вместо в началото, изразът за истинност се проверява в края на всяка итерация. Основната разлика от обикновените цикли while е, че първата итерация на цикъл do-while със сигурност ще се изпълни (условието се проверява единствено в края на итерацията), докато при циклите while не е задължително да се изпълни (условието се проверява в началото на всяка итерация, така че ако се изчисли на FALSE от самото начало, цикълът ще завърши незабавно). Задължително трябва да има точка и запетая (;) след скобите на while в оператора do-while.
 
Прекалено стриктен ми идва Java. Веднъж се бях запънал, не ми дава променлива от тип String да приеме стойност от тип Char. Трябваше с някакви функции да cast-вам Char-a към String и тогава. Още се чудя каква е логиката на това и от какво пази.
 
Прекалено стриктен ми идва Java. Веднъж се бях запънал, не ми дава променлива от тип String да приеме стойност от тип Char. Трябваше с някакви функции да cast-вам Char-a към String и тогава. Още се чудя каква е логиката на това и от какво пази.
Ами Char-a винаги е един, а String-a може да е празен, а може и да е безкрайно* дълъг.
В паметта са представени различно.
С единия тип можеш да правиш едни неща, с другия - други.

Представи си че String = List<Char>, тогава няма логика да искаш да сложиш едно нещо на мястото на списък, нали? :)
 
Да, това ми е якото на този език, за разлика от JavaScript-а, е строго типизиран, което е добре, по-малко недоразумения се получават.
TypeScript тогава ползвай. Само избягвай тип any 😅

@cloxy
Строго типизираните езици могат само да те научат да разполагаш правилно с паметта. Ако си решил някъде да ползваш Char вместо String означава че или си имал причина, или не си разбирал разликите.
 
TypeScript тогава ползвай. Само избягвай тип any 😅

@cloxy
Строго типизираните езици могат само да те научат да разполагаш правилно с паметта. Ако си решил някъде да ползваш Char вместо String означава че или си имал причина, или не си разбирал разликите.
Java и жалена на RAM в едно изречение. :) Може и да има нещо такова, но винаги съм ги мислил за антоними. :)

Работил съм с Java, но нещо не ме повлече, а като видях как локално се редеше визуалната част, викат това ме влече и май Java не е езика за мен. Макар, че много се възхищавам на Java-рите, дори може би повече от тия с C#. :)
 
Зависи какво правиш. Java вече бутат навсякъде, така че може и да ти се наложи да боравиш по прецизно с паметта, но да - вярвам, че е радък случая това да се налага.

Преди учих Java, но покрай работа се наложи да се запозная с ASP.NET и като цяло ми допадна.
 
Зависи какво правиш. Java вече бутат навсякъде, така че може и да ти се наложи да боравиш по прецизно с паметта, но да - вярвам, че е радък случая това да се налага.

Преди учих Java, но покрай работа се наложи да се запозная с ASP.NET и като цяло ми допадна.
Покрай моята - какво ли не се изливаше, от Java, пък пом едно време PHP, и след мине не мине време пак някой от "кул" езиците и последно се спрях на JS, като това най-ми харесва за момента, защото си падам повече по фронт-енд отколкото по бек-енд. :) Винаги ме е радвало да гледам едно нещо как да го изпипаш за клиента, а някой да се мъчи отзад това да го навърже логично с друга простотия и после с базата. :)
 
Строго типизираните езици определено учат на дисциплина.
То си има цял клон на математиката, type theory, който развива тази идея направо до небесата.

Javaта обаче си е известна със своето verbosity. Конструктори, гетери, билдери – положението е спасяемо единствено с плъгини като lombok, които да автогенерират всичкия този boilerplate, така че да не задръства изходния код.

И още нещо – за някой като мен, минал преди това през управлението на паметта в C++ – RAII, деструктори (дори само в еднонишковия случай), обаче, често остава едно усещане, че в java обекти се пилеят на поразия и се оставят на боклукчията да ги събира, въпреки че за програмиста е абсолютно ясно какъв е техния обхват (scope на бг?). Донякъде завиждам на rust'джиите по тая тема, макар да не съм минавал през болки от неправилно управление на паметта в паралелния свят.
 
Да, който не е писал микросървиси, не е бил в риил гейм. :)

Да допълня, че въпросите са някакво плавно преминаване от Junior въпроси, за към то Senior. Като задълбаването може да бъде различно според това какво последно е правил и е чел като новост за езика, така лесно може да се проследи.
 
Джавата си е тегаво език по мои наблюдения. Да, не е като C или С++, но определено не е и като PHP или C#. Малко последните години го изместиха от това да е най-предпочитан за апове, излязоха къде къде по-добро решения. И в същото време е доста търсен и заплатите за него не са никак малки. Дори и да си джуниър.
 
Ами Char-a винаги е един, а String-a може да е празен, а може и да е безкрайно* дълъг.
В паметта са представени различно.
С единия тип можеш да правиш едни неща, с другия - други.

Представи си че String = List<Char>, тогава няма логика да искаш да сложиш едно нещо на мястото на списък, нали? :)
Мерси за разяснението. Не се бях замислял, но има логика наистина.
 
От това, с което съм се сблъсквал този език ми е направи такова впечатление и най-вече с контрола на рамта. В общи линии най-вече около Java heap. Ако искаш и повече обяснение, но според мен от всичко, с което съм работил Java-та най го няма за нищо RAM-та. :) Вече съм и съгласен е, че код и оптимизация при производителност, но по дефолт си е тежка машина.
 
Ако не освобождаваш заетата и неизползвана памет - нормално да търси още. Java си има GC, ама за обекти, които не се ползват. Ако наблъскаш обекта книга например, който държи 2000 обекта страница, в обекта библиотека, който държи още 1000 такива книги - GC няма да ти помогне. GC чисти само обекти, към които няма референции.
Можеш да сетнеш лимит на RAM на JVM, но ако случая ти е като горния, ще гърми с OutOfMemoryException.
 
Java наистина си е лакома за памет, в сравнение с други GC езици (например Go). Но пък откъм performance хич не е зле.
 
Не знам как е при Go, имам желание да го разуча, но не ми остава време. Аз лично проблеми с паметта не съм имал... тоест, с JVM съм нямал, иначе по моя вина съм имал доста фрапиращи.
 
Не знам как е при Go, имам желание да го разуча, но не ми остава време. Аз лично проблеми с паметта не съм имал... тоест, с JVM съм нямал, иначе по моя вина съм имал доста фрапиращи.
Тежичък ми беше и като работех през IDE , мисля, че ползвахме тогава Еклипса или Интелиджей. Но да си признаят не съм закачаш функции за чистене на рам и натрупването му. Просто имах и възможност да го сравня успоредно с друг език по това време. Бях впечатлен, и за пръв път изучавайки го, разбрах за гарбидж колектора. И си викам уоу, някой го е мислил добре. ;)
 
Не е перфектен обаче. Не трябва да бъдеш от типа програмисти, които си казват "той GC ще се оправи".

Имахме проблем с единия API който писахме на .НОТ и в определени моменти запълваше всичката РАМ памет. Трябваше с dotMemory да се установи къде е проблема. Ставаше така, че разни референции все още се пазеха след завършването на рекуеста и това се натрупваше постоянно.

Същото е и в PHP. Разочарован съм колко рядко се ползват итератори и генератори, и хората постоянно пипат memory limit-a само и само да изпълнят голяма задача.
 

Back
Горе