- Привет, Амиго! Сегодня я расскажу тебе о стилях кода и важности стилей кода.
Начну с самого главного. Код в Java должен быть легко читаем. Общий подход к коду такой – код пишется один раз, а читается сто.
Например, ты и еще 10 программистов занимаетесь написанием программы. Программа пишется три года, с промежуточными релизами каждые три месяца.
- Так долго?
- Это Java, детка! Как насчет Enterprise-системы, которая работает на десятке серверов и которую пишут более 6 лет около 100 человек? Бывает и такое.
- Ничего себе.
- Так вот, главный критерий, главное требование к коду – он должен легко читаться другими разработчиками.
В других языках программирования люди часто работают маленькими командами над маленькими задачами, поэтому у них может быть другой главный критерий, например – «Это работает? Вот и отлично»
За пару лет в написанный тобой код успеют по нескольку раз внести изменения все члены команды. И каждый раз им придется разбираться, а как же работает этот код?
И если код просто отлично делал свое дело, но был непонятен, то поменять его трудно. Его выкинут и напишут по-своему. Поэтому, пиши код, понятный другим. Если можешь улучшить код – улучши его. Если его можно улучшить, значит, его нужно улучшить!
Если ты написал код за 15 минут и два часа улучшаешь его – ты все делаешь правильно. Сколько времени ты экономишь команде?
«2 часа на разбор твоего кода» x «100 раз, когда люди будут в нем разбираться» = 200 часов.
Эти цифры взяты с потолка, но я хочу, чтобы ты понял проблему и ее масштаб. Твой код создается для чтения другими программистами. Все остальное – вторично.
Код плохо работает? Исправим. Не оптимально? Оптимизируем. Не документирован? Прокомментируем.
Код плохо читаем? Выкинуть его нафиг и написать все заново!
- Не думал, что это такая проблема.
- Java поэтому и один из лидирующих языков программирования, что весь ее код пишется, чтобы читаться другими программистами.
Теперь перейдем к вопросу номер два – «А как писать максимально читаемый код?».
Любому понятно, когда с ним говорят на родном языке, родными знакомыми словами. Так и тут. Код легко читаем, когда программист, читающий его, с легкостью догадывается:
А) Что делает каждый метод
Б) Какой цели служит каждый класс
В) Что именно хранится в каждой переменной.
Все это определяется по названию: имени класса, имени метода, имени переменной. Кроме того, есть еще стиль именования переменных. И стиль кода.
- Я готов слушать.
- В основе программирования лежит… английский язык! Хорошо написанная программа читается, как обычная техническая документация на английском языке.
Начнем с имен.
Имя метода должно кратко описывать, что этот метод делает. Тогда программист может читать программу, как простой текст.
Программа |
---|
public String downloadPhoto(String url) { String resultFileName = TempHelper.createTempFileName(); Downloader downloader = new SingleFileDownloader(new Url(url)); downloader.setResultFileName(resultFileName) downloader.start(); while(downloader.isDone()) { Thread.sleep(1000); } if (downloader.hasError()) return null; return resultFileName; } |
Вот как читается такая программа.
Строка 1.
Метод называется «downloadPhoto», похоже, что он загружает файл с фотографией из интернета. Куда загружает? Пока неизвестно. Откуда? В параметрах метода передан url – скорее всего это и есть ссылка для загрузки.
Строка 3.
Объявляется переменная resultFileName, в нее ложится значение, отданное методом TempHelper.createTempFileName();
Имя переменной resultFileName дословно переводится как «имя-файла-результата». Значит это локальный путь к файлу на диске, куда мы будем сохранять наш скачиваемый файл.
Название TempHelper – ничего не говорит. Суффикс Helper говорит, что это разновидность утилитных классов, которые не содержат в себе серьезной бизнес логики, а используются для упрощения часто возникающих рутинных задач.
Имя метода createTempFileName говорит о том, что этот метод создает и возвращает нам имя временного файла (temp-file). Temp file – это временный файл, который создается на время, и обычно удалятся после закрытия программы или раньше.
Строка 5.
Создается объект типа SingleFileDownloader и кладется в переменную downloader.
Название переменной downloader переводится как загрузчик. Этот объект и будет загружать наш файл из интернета.
В переменную downloader кладется объект типа SingleFileDownloader. Из названия можно предположить, что в программе есть несколько видов классов-загрузчиков файлов. Один из них написан для загрузки единственного файла (single file), и скорее всего можно ожидать встретить в коде и загрузчики для группы файлов с названиями вроде: MultiFileDownloader, GroupFileDownloader или DirectoryDownloader
Строка 6.
Объекту downloader устанавливаем в свойство resultFileName значение переменной resultFileName. Т.е. мы говорим загрузчику, куда сохранять скачиваемый им файл. Что и следовало ожидать. Т.е. мы уже практически предсказываем код!
Строка 7.
Вызов метода start. Начало загрузки. Логично. Интересно, как будет происходить загрузка: кусочками, в отдельной нити или сразу до конца. Если сразу, то это может быть долго и иметь последствия.
Строки 8-11.
Ага. Тут мы видим обычный цикл, который ждет завершения загрузки. Объект downloder имеет свойство done («готово») и метод, который его возвращает isDone(). Т.к. метод называется isDone(), а не getDone(), то переменная done имеет тип boolean, ну или Boolean.
Строки 13-14.
Если в процессе скачивания произошла ошибка, то метод downloadPhoto возвращает null. Хорошо, что он обрабатывает состояние ошибки. Плохо, что он просто возвращает null – что за ошибка – не ясно. Лучше бы кинул исключение с информацией об ошибке.
Строка 16.
Возвращаем путь к локальному файлу, который содержит скачанный файл.
- Ничего себе!
- Из текста этой программы абсолютно ясно, что она делает. Можно даже делать предположения, как устроена программа и какие еще классы/методы мы будем встречать.
- Теперь я понял, как важны имена.
- Еще насчет имен. Очень часто можно угадать какие у объекта/класса есть методы. Вот например, если объект – коллекция, то скорее всего у него будут методы size() или count(), чтобы получить количество его элементов. Так же, вероятно, методы add(добавить) или put(вставить). Методы get/getItem, getElement используются для получения элементов у классов-коллекций.
Если переменная называется i, j ,k – скорее всего это счетчик цикла.
Если переменная называется m, n – скорее всего это размер массива/коллекции.
Если переменная называется name то, скорее всего она имеет тип String и содержит чье-то имя.
Если класс называется FileInputStream, то он одновременно является файлом (так и есть) и потоком для чтения – InputStream (так и есть).
Чем больше ты видел кода, тем легче читать чужой код.
Но иногда есть код, который читать очень сложно. На этот случай есть один очень дельный совет:
Совет |
---|
Пишите свой код так, как будто поддерживать его будет склонный к насилию психопат, который знает, где вы живете. |
- Смешно и не смешно одновременно.
- Теперь немного расскажу о стилях именования переменных.
В Java переменным и методам стараются давать максимально информативные имена. Поэтому такие названия часто состоят из нескольких слов. Есть 4 стиля написания составных имен.
1) Lowercase (нижний регистр) – все слова с маленькой буквы. Пример:
Green house превращается в greenhouse
Hollywood girl превращается в hollywoodgirl
В таком стиле пишутся названия пакетов (package).
2) Uppercase (верхний регистр) – все слова пишутся с большой буквы, разделенные знаком подчеркивания. Примеры:
Max value превращается в MAX_VALUE
Cats count превращается в CATS_COUNT
В таком стиле пишутся названия переменных-констант (final static).
3) CamelCase (верблюжий стиль) – все слова пишутся с маленькими буквами, первая буква каждого слова – большая. Примеры:
Green house превращается в GreenHouse
Hollywood girl превращается в HollywoodGirl
В таком стиле пишутся названия классов и интерфейсов.
4) Lower CamelCase (смешанный стиль) – все слова пишутся маленькими буквами, первая буква каждого слова – большая, первая буква первого слова - маленькая. Примеры:
Get width превращается в getWidth
Get Hollywood girl name превращается в getHollywoodGirlName
В таком стиле пишутся названий переменных и методов.
Т.е. правил не так уж и много.
1) Всё пишется в Lower Camel Case.
2) Имена классов и интерфейсов – всегда с большой буквы.
3) Имена пакетов – всегда маленькими.
4) Константы - всегда большими.
Есть еще пара нюансов, но в целом так и есть.
Теперь насчет методов. Имена методов практически всегда начинаются с глагола! Имя метод count – плохое имя. Лучше назвать getCount(). Метод выполняет какое-то действие над объектом: startDowbload (начать загрузку), interrupt (прервать), sleep (спать), loadPirateMusic(загрузить пиратскую музыку).
Для работы со свойствами/полями объекта, как ты уже знаешь, есть getter’ы и setter’ы. getName/setName, getCount/setCount и т.д.
Единственное исключение делается для типа boolean. Для него getter пишется не через get, а через is: isDone, isEmpty. Так ближе к английскому языку.
- Т.е. знание английского обязательно для умения программировать?
- Не обязательно, но зная английский и имея пару лет опыта за плечами, ты сможешь очень быстро разбираться в чужом коде. Как насчет тратить на работу не 8 часов в день, а два? Заманчивое предложение?
- Ага!
- То-то и оно. Основное требование у Java Junior - это отличное знание основ Java – Java Core. Но чем опытнее ты становишься, тем сильнее тебе нужен английский. Чем раньше начнешь его учить – тем лучше.
- У меня еще вопрос. Почему такие разные методы для получения количества элементов?
Класс | Метод для получения количества элементов |
---|---|
String | метод length() |
Array | свойство length |
ArrayList | метод size() |
ThreadGroup | метод activeCount() |
Во-первых, Java была придумана более 20 лет назад, когда требований вроде setCount/getCount еще не было, и в ходу был подход из языка С++ «сделай это как можно короче»
Во-вторых, тут играет роль семантика английского языка. Так уж получилось, что когда говорят про массив, употребляют length, а когда про коллекцию – size.
В русском языке тоже есть такие устоявшиеся выражения:
1) Тарелка на столе стоит, а на полу – лежит.
2) Ботинок на столе лежит, а на полу – стоит.
- Какая интересная лекция.
- Хотелось бы рассказать больше, но боюсь, что всего ты все равно сразу не запомнишь. Лучше давать снова по чуть-чуть.
Еще хотел бы коснуться стиля скобок {}. Есть два подхода:
1) Скобка каждый раз ставится на новой строке
2) Открывающая скобка ставится в конце предыдущей строки, закрывающая – на новой. Такой стиль еще называют «египетскими скобками».
Честно говоря – тебе выбирать, как писать. Многие пишут открывающую скобку на той же строке, многие - на новой. Это как спор – с какого конца разбивать яйцо: с тупого или острого.
Единственное, что могу посоветовать – это придерживайся того же стиля, что и в проекте, в котором ты работаешь. Не стоит менять чужой код, как тебе удобнее. Люди несовершенны, это я тебе как доктор Билаабо говорю.
- Спасибо за интересную лекцию, Билаабо. Пойду обдумывать услышанное.
- Привет, Амиго!
Задачи |
---|
1. Рефакторинг в соответствии с Naming and Code Convention Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга) Не оставлять комментариев, проверяется строгое соответствие стандарту Подсказка: IDEA не умеет правильно переименовывать имена классов, если меняется только регист. Переименуйте имя класса во вспомогательное имя, а потом в это же в правильном регистре. |
2. Рефакторинг в соответствии с Naming and Code Convention 2 Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга) Не оставлять комментариев, проверяется строгое соответствие стандарту |
- Привет, Амиго!
Сегодня я расскажу про autoboxing. Box – это коробка. Boxing – упаковка. А AutoBoxing – это соответственно – автоматическая упаковка.
Насколько ты помнишь, в Java есть как типы, унаследованные от класса Object, так и примитивные типы. Но, как оказалось, такая удобная вещь как коллекции и generic’и могут работать только с типами, унаследованными от Object.
Тогда было приятно решение сделать не примитивный аналог каждого примитивного типа.
Примитивный тип | Не-примитивный аналог |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
void | Void |
Но каждый раз преобразовывать эти типы друг в друга оказалось не очень удобно:
int x = 3; Integer y = new Integer(x+1); int z = y.intValue(); |
Особенно, если работать сразу с коллекциями:
Пример |
---|
int[] numbers = new int[10]; ArrayList<Integer> list = new ArrayList<Integer>(); for (int i=0;i { list.add( new Integer(i)); } |
Поэтому разработчики Java придумали автоматическую «упаковку» (boxing) и «распаковку» (unboxing) примитивных типов в их непримитивные аналоги.
Вот как это работает:
Видимый код | Что происходит на самом деле |
---|---|
int x = 3; Integer y = x+1; |
int x = 3; Integer y = Integer.valueOf( x+1); |
int z = y; | int z = y.intValue(); |
Boolean b = Boolean.FALSE; boolean a = b; |
Boolean b = Boolean. FALSE; boolean a = b.booleanValue(); |
Integer x = null; int y = x; |
Integer x = null; int y = x.intValue(); //кинется исключение |
Все просто. Ты можешь присваивать типы int и Integer друг-другу, об остальном позаботится компилятор.
- Это очень удобно.
- Ага. Но есть нюансы, о которых я расскажу дальше.
- Раз уж разработчики могли придумывать классы, которые описывают числа, они решили подойти к этому делу творчески, как настоящие разработчики.
Во-первых, придумали абстрактный класс Number (число), от которого унаследованы типы Byte, Short,Integer, Long, Float, Double. У него есть методы, которые помогают преобразовывать числа к другим числовым типам.
Методы класса Number | |
---|---|
1 | int intValue() |
2 | long longValue() |
3 | float floatValue() |
4 | double doubleValue() |
5 | byte byteValue() |
6 | short shortValue() |
- Действительно, ведь уже не напишешь:
Long x = 100000; Integer y = (Integer) x; |
- Ага. Типы то не примитивные. Поэтому используют методы класса Number:
Long x = 100000; Integer y = x.intValue(); |
Но тут есть еще пара моментов. Т.к. Integer – это не int, то объекты такого типа нельзя сравнивать классическим знаком «==».
Сравнение примитивных типов |
---|
int x = 500; int y = 500; x == y; //true |
Сравнение непримитивных типов: |
Integer x = 500; Integer y = 500; x == y; //false x.equals(y); //true |
- Точно. Как-то я сразу об этом не подумал.
- Но и это еще не все.
- Господи, что же там еще-то?
- Когда мы присваиваем переменной типа Integer значение типа int, при этом вызывается метод Integer.valueOf:
Код | Что происходит на самом деле |
---|---|
Integer x = 5; | Integer x = Integer.valueOf(5); |
- Ага. Я это понял еще примером выше.
- Так вот, функция valueOf не всегда создает новый объект типа Integer.
- Т.е. как это не всегда?
- Она кэширует значения от -128 до 127.
Код | Что происходит на самом деле | Описание |
---|---|---|
Integer x = 300; Integer y = 300; Integer z = 300; |
Integer x = Integer.valueOf(300); Integer y = Integer.valueOf(300); Integer z = Integer.valueOf(300); |
Все переменные x,y,z содержат ссылки на разные объекты |
Integer x = 100; Integer y = 100; Integer z = 100; |
Integer x = Integer.valueOf(100); Integer y = Integer.valueOf(100); Integer z = Integer.valueOf(100); |
Все переменные x,y,z содержат ссылки на один и тот же объект. |
Integer x = new Integer(10) Integer y = new Integer(10) Integer z = 10; Integer t = 10; |
Integer x = new Integer(10) Integer y = new Integer(10) Integer z = Integer.valueOf(10); Integer t = Integer.valueOf(10); |
Все переменные z,t содержат ссылки на один и тот же объект. |
Т.е. ситуация такая:
1) Если мы пишем new Integer(), то гарантированно создается новый объект.
2) Если мы вызываем Integer.valueOf(), явно или при autoboxing, то этот метод может вернуть для нас как новый объект, так и отдать объект из кэша, если переданное число лежит в диапазоне от -128 до 127.
- Ага. А можно устанавливать/менять приоритет нити после ее запуска? Или тут как с setDaemon – обязательно выставить значение до старта нити?
- Приоритет можно менять и после старта. Как я уже говорила, кардинальных изменений это не влечет.
- А что в этом такого страшного, если метод вернет объект из кэша?
- Да ничего. Просто нужно знать, что иногда, когда этого не ожидаешь, объекты могут быть равны. Там с равенством вообще все сложно. Если мы сравниваем примитивный тип и не примитивный, то они сравниваются как примитивы:
Пример проблемы со сравнением: |
---|
int x = 300; Integer y = 300; Integer z = 300; x==y; //true (сравниваются как примитивы по значению) x==z; //true (сравниваются как примитивы по значению) y==z; //false (сравниваются по ссылке) |
Этот пример еще интереснее. Тут уже в дело вступает кэш |
int x = 100; Integer y = 100; Integer z = 100; x==y; //true (сравниваются как примитивы по значению) x==z; //true (сравниваются как примитивы по значению) y==z; //true (сравниваются по ссылке, ссылаются на один и тот же объект) |
А тут кэш уже не работает |
int x = 100; Integer y = new Integer(100); Integer z = 100; x==y; //true (сравниваются как примитивы по значению) x==z; //true (сравниваются как примитивы по значению) y==z; //false (сравниваются по ссылке, ссылаются на различные объекты) |
- М-да. И как все это запомнить…
- Не нужно это запоминать. Надо просто понять, как это все устроено и что происходит на самом деле, когда в дело вступает примитивный тип и его непримитивный аналог.
Еще советую тебе посмотреть на методы класса Integer, у него довольно много хороших и полезных методов. Ты даже одним из них часто пользовался.
- Ага. Помню. Integer.parseInt();
- Привет, Амиго!
Задачи |
---|
1. И еще раз рефакторинг 1. Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга) 2. Просмотрите методы класса ConcurrentMap. 3. В строке "String previousEntry = null;" у concurrentMap вызовите метод, который вставит пару (randomInt, text) только для ключа, которого нет в concurrentMap. Метод должен возвращать предыдущее значение либо null для новой пары. |
2. Особенности автобоксинга Исправьте ошибку в методе getValueByIndex. Читайте доп. статью про особенности автобоксинга. |
- Привет, Амиго!
- Привет, Ким.
- Я тебе расскажу про тип Boolean. Это тоже «обертка» над типом boolean и он прост как доска. Немного упрощенный код класса Boolean:
Код |
---|
class Boolean { public static final Boolean TRUE = new Boolean(true); public static final Boolean FALSE = new Boolean(false); private final boolean value; public Boolean(boolean value) { this.value = value; } public boolean booleanValue() { return value; } public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); } } |
- Т.е. класс просто является «оберткой» над типом boolean.
- Ага. А еще у него есть две константы TRUE и FALSE, которые являются аналогами примитивных значений true/false.
С автобоксингом у него тоже все просто:
Код | Что происходит на самом деле |
---|---|
Boolean a = true; Boolean b = true; Boolean c = false; boolean d = a; |
Boolean a = Boolean.valueOf(true); Boolean b = Boolean.valueOf(true); Boolean c = Boolean.valueOf(false); boolean d = a.booleanValue(); |
А вот как происходят сравнения между типами boolean и Boolean:
Пример |
---|
boolean a = true; Boolean b = true; //будет равен Boolean.TRUE Boolean c = true; //будет равен Boolean.TRUE a == b; //true (сравниваются как примитивы по значению) a == c; //true (сравниваются как примитивы по значению) b == c; //true (сравниваются по ссылке, но указывают на один и тот же объект) |
Если очень нужно создать независимый объект Boolean, то надо создать его явно:
Пример |
---|
boolean a = true; Boolean b = new Boolean(true); //новый объект Boolean Boolean c = true; //будет равен Boolean.TRUE a == b; //true (сравниваются как примитивы по значению) a == c; //true (сравниваются как примитивы по значению) b == c; //false (сравниваются по ссылке, указывают на различные объекты) |
Собственно на этом все.
- Да, твои лекции покороче, чем у Билаабо.
А можно использовать Boolean внутри if ?
Boolean less = (2<3); if (less) { …. } |
- Да, только не забудь, что если less будет null, то выкинется исключение NullPointer.
- Да, я это уже понял. Только не держу все время в голове.
- Привет, Амиго!
Задачи |
---|
1. Странные ошибки О_о Исправьте 2 ошибки: 1) возникновение исключения 2) подвисание Сделайте минимальные изменения. |
2. Особенности автобоксинга - 2 Исправьте ошибку реализации, приводящую к NullPointerException, в методе getValue. Читайте доп. статью про особенности автобоксинга. |
- Привет, Амиго! Это снова я. Хотела тебе рассказать еще об одном достаточно простом классе-обёртке. Сегодня речь пойдет о Character – обертка над char.
Этот класс тоже довольно-таки прост.
Код |
---|
class Character { private final char value; Character(char value) { this.value = value; } public char charValue() { return value; } static final Character cache[] = new Character[127 + 1]; public static Character valueOf(char c) { if (c <= 127) return cache[(int)c]; return new Character(c); } public int hashCode() { return (int)value; } public boolean equals(Object obj) { if (obj instanceof Character) { return value == ((Character)obj).charValue(); } return false; } } |
В нем есть:
1) Конструктор, который принимает внутреннее значение и метод charValue, который его возвращает.
2) Метод valueOf, который возвращает новые объекты Character, но кэширует объекты со значениями от -128 до 127. Как в Integer, Short и Byte.
3) Методы hashCode() & equals – тут нас тоже ничем не удивишь.
А еще в нем есть много полезных методов (не показаны выше). Некоторые из них я тебе сейчас перечислю:
Метод | Описание |
---|---|
boolean isDefined(char) | Является ли символ символом Unicode? |
boolean isDigit(char) | Является ли символ цифрой? |
boolean isISOControl(char) | Является ли символ управляющим? |
boolean isLetter(char) | Является ли символ буквой? |
boolean isJavaLetterOrDigit() | Является ли символ буквой или цифрой? |
boolean isLowerCase(char) | Это символ в нижнем регистре (строчная буква)? |
boolean isUpperCase(char) | Это символ в верхнем регистре (заглавная буква)? |
boolean isSpaceChar(char) | Является ли символ пробелом или его аналогом (есть много невидимых символов)? |
boolean isTitleCase(char) | Является ли символ титульным? |
- Спасибо, Ким, думаю, некоторые из этих методов мне точно пригодятся.
- Привет, Амиго!
Задачи |
---|
1. Этот странный BigDecimal Исправьте ошибку реализации, приводящую к погрешности вычисления, в методе getValue. Сигнатуру метода не менять. Округление не использовать. Читайте доп. статью про особенности автобоксинга. |
2. Кеширование В CacheComputeManager реализуйте логику пустого метода. Догадайтесь, что он должен делать по названию метода и по логике класса. |
- Привет, Амиго! И снова маленькая и интересная тема. Тип Void.
- А зачем может понадобиться такой тип? Ну, c void-то понятно. Чтобы привести к общему знаменателю функции и процедуры. Теперь у нас нет процедур, зато есть функции, которые возвращают void (ничего).
- Ага. А ты помнишь, недавно Элли тебе рассказывала про интерфейс-шаблон Callable<T>?
- Ага.
- А что туда нужно передать в качестве типа-параметра тоже помнишь?
- Да, тип результата:
Пример задания, которое ничего не делает: |
---|
class EmptyJob implements Callable<String> { public String call() throws Exception { return null; } } |
- Ага. А если тебе нужно, чтобы метод call возвращал значение int? Как тогда?
- Теперь я знаю, что для этого есть autoboxing. Я просто передам Integer, и все будет работать как часы:
Пример задания, которое ничего не делает: |
---|
class EmptyJob implements Callable<Integer> { public Integer call() throws Exception { return null; } } |
- Отлично. А если метод ничего не должен возвращать?
- Я понял твою мысль. Тогда мы используем Void как аналог void?
- Ага.
- А не проще сделать просто Object и возвращать null.
- Иногда, но не всегда.
Ты знаешь, что там имелся в виду void, а ты написал Object, но другой программист может этого и не знать и будет думать, а почему это ты возвращаешь null.
Или код, вызывающий этот метод будет ожидать значения в качестве результата.
А когда написано Void то всем сразу понятно, что это – обертка над void, хотя возвращать null все же придётся.
Пример задания, которое ничего не делает: |
---|
class EmptyJob implements Callable<Void> { public Void call() throws Exception { return null; } } |
- Гм. Действительно, метод, который всегда возвращает null, внушает некоторые сомнения. А метод, который объявлен Void, может это делать без лишних пояснений.
Читабельность кода - прежде всего. Мне нравится Java!
- Отлично. Рада, что тебе понравилось. На сегодня закончим.
- Привет, Амиго!
Продолжаем наши уроки – учимся гуглить.
Вот тебе несколько заданий:
Задания на поиск в интернете: | |
---|---|
1 | Как средствами Intellij IDEA переименовать(rename) переменную? |
2 | Как средствами Intellij IDEA сделать замену(replace) одного кода на другой? |
3 | Как средствами Intellij IDEA сделать так, чтобы переменная, на которой стоит курсор, подсвечивалась во всем коде? |
4 | Как средствами Intellij IDEA переименовать метод? |
5 | Как средствами Intellij IDEA переименовать класс? |
6 | Как средствами Intellij IDEA обернуть часть кода в try-catch? |
7 | Как средствами Intellij IDEA быстро создать конструктор? |
8 | Как средствами Intellij IDEA создать getter’ы и setter’ы? |
9 | Как средствами в Intellij IDEA реализовать (implements) недостающие методы класса? |
10 | Как средствами Intellij IDEA переопределить методы класса-родителя? |
- Привет, Амиго!
Вот тебе дополнительный материал по теме.
- Привет, Амиго. Ты почему такой грустный?
- Здравствуй. Не могу решить несколько задач.
- А знаешь что я делаю когда мне грустно?
- Что?
- Смотрю видео.
- Отличная идея.
- Привет, Амиго!
Вопросы к собеседованиям | |
---|---|
1 | Что такое autoboxing? |
2 | Зачем используется autoboxing? |
3 | Альтернативы autoboxing? |
4 | Типы-обертки для примитивных типов mutable или immutable? |
5 | Как примитивные типы приводятся к непримитивным аналогам? |
6 | Как непримитивные типы приводятся к примитивным? |
7 | Как сравниваются примитивные и непримитивные типы? |
8 | Всегда ли создается новый объект при операции autoboxing? |
9 | Как работает кэширование при операции autoboxing? |
10 | Для каких типов и/или значений работает кэширование? |
- Привет, Амиго!
- В секретных лабораториях проекта JavaRush уже разрабатываются сверхсложные задачи нового поколения. Как только задача будет закончена, отлажена и протестирована, тут появится ее условие. А пока немного подожди.