Как комментируют функции и библиотеки
В комментариях к файлам и библиотекам указывают информацию о проекте, назначении модуля, заносят в них имя разработчика, номер версии продукта и лицензию на программное обеспечение.
Например, документирующий комментарий из заголовка библиотеки Lodash для JavaScript выглядит так:
Кроме этого, в заголовочных комментариях к функциям указывают стандартный набор сведений:
- описание того, что и как делает функция/процедура;
- условия, при которых она работает или не работает;
- описание входные параметров, если есть;
- описание возвращаемого значения.
Пример из той же библиотеки Lodash:
Главное здесь — избегать бессмысленных комментариев. Вот пример плохого описания процедуры на языке 1С:
Так что же это?
Понятие «объектная гимнастика» ввёл Джефф Бэй (Jeff Bay) в своей книге «The ThoughtWorks Anthology» (на русском не издавалась. — Пер.). Так он назвал группу упражнений на объектно-ориентированное программирование.
Применяя объектную гимнастику, можно сделать код:
- читабельнее;
- удобнее:
• для отладки,
• тестирования,
• повторного использования
• и сопровождения.
Считайте это упражнением. Вам нужно научиться выполнять эти правила при кодинге. А вот в повседневном программировании какими-то из них всегда можно пожертвовать — если следовать им слишком сложно или результат того не стоит.
String
Класс String используется в Java для хранения и представления не модифицируемых строк. После того как создан
экземпляр этого класса, строка уже не может быть модифицирована. Для создания объекта String можно использовать
различные варианты конструктора. Наиболее простой — если содержимое строки известно на этапе компиляции — это
использовать один из следующих подходов :
String abc = "abc"; String cde = new String("cde");
На первый взгляд, эти варианты создания строк отличаются только синтаксисом. На самом деле различие есть, хотя в
большинстве случаев его можно и не заметить. Каждый строковый литерал имеет внутреннее представление, как экземпляр
класса String.
Классы в JAVA могут иметь целый набор таких строк и, когда класс компилируется, экземпляр представляющий литерал,
добавляется в этот набор. Однако, если такой литерал уже имеется где-то в другом месте класса, т.е. уже представлен
в наборе строковых объектов, то новый экземпляр (фактически копирующий уже существующий) создан не будет. Вместо
этого будет создана ссылка на уже имеющийся объект. Т.к. строки не являются модифицируемыми объектами, то это не
нанесет никакого урона другим фрагментам программы. С другой стороны, если объект-строка создается с помощью явного
вызова конструктора, то даже если эти строки будут совершенно идентичными, экземпляры класса String будут отличаться.
В объекте String определен метод equals() который сравнивает две строки на предмет идентичности. В следующем примере
сравниваются две строковых переменных с одинаковыми значениями.
public class StringTest { public StringTest() {} public static void main(String[] args) { Test t = new Test(); String s1 = "Hello world"; String s2 = "Hello world"; System.out.println("String`s equally = " + (s1.equals(s2))); System.out.println("Strings are the same = " + (s1 == s2)); } }
В консоль будет выведено следующее сообщение :
String`s equally = true Strings are the same = true
Но вот, если строку определения переменной s2 определить следующим образом :
String s2 = new String("Hello world");
то сообщение в консоле изменится :
String`s equally = true Strings are the same = false
При первом варианте для создания двух строк используются строковые литералы, поэтому ссылки
s1 и s2 ссылаются на один и тот же объект. Во втором случае для строки s2 используется конструктор.
Поэтому, несмотря на то, что строки идентичны, переменные ссылаются на разные объекты, которые,
в сущности, создаются во время выполнения программы и не находятся во множестве строковых констант,
которое создается на момент компиляции.
Необходимо отметить, что при создании экземпляров строк во время выполнения (run-time), они не
помещаются в набор строковых констант. Однако, можно явно указать на необходимость поместить,
вновь создаваемый экземпляр класса String в этот набор, применив метод intern(), т.е. если
определить строку s2 следующим образом :
String s2 = new String("Hello world!!!").intern();
то в консоль будет выведено первое сообщение.
Если все строки находятся в наборе, сформированном при компиляции, то для сравнения строк,
вместо метода equals() можно использовать оператор ‘==’, который выполняется значительно быстрее.
Метод trim() класса String позволяет удалить пробелы в строке, расположенные в начале и в конце
строки.
Помните, что после выполнения операций trim и concat создается новый объект.
Строка состоит из шестнадцатибитовых UNICODE символов. Однако во многих случаях требуется работать с
восьмибитовыми символами (ввод/вывод, работа с базой данных и т.д.). Преобразование строки в последовательность
байтов (восьмибитовые символы) производится методами :
- byte[] getBytes(); — возвращает последовательность байтов, в кодировке принятой по умолчанию.
- byte[] getBytes(String encoding); — возвращает последовательность байтов, в кодировке encoding;
- String(byte[] bytes); — создает строку из последовательности байтов в кодировке принятой по умолчанию;
- String(byte[] bytes,String encoding); — создает строку из последовательности байтов в указанной кодировке.
Оператор ‘+’ для класса String переопределен. Так если оператор ‘+’ применить к экземплярам класса String, то
будет осуществлена конкатенация строк и, если один из операндов не принадлежит классу String (не первый), то он
будет неявно приведен к этому типу, как будто бы был использован метод String.valueOf(). Например :
System.out.println("1" + 5) выведет на консоль 15 System.out.println(1 + 5) выведет на консоль 6
Блок Статического Инициализатора
Чтобы иметь неудачный инициализатор статического блока, мы намеренно разделим целое число на ноль:
public class StaticBlock { private static int state; static { state = 42 / 0; } }
Теперь, если мы инициализируем инициализацию класса с помощью чего-то вроде:
new StaticBlock();
Тогда мы увидим следующее исключение:
java.lang.ExceptionInInitializerError at com.baeldung...(ExceptionInInitializerErrorUnitTest.java:18) Caused by: java.lang.ArithmeticException: / by zero at com.baeldung.StaticBlock.(ExceptionInInitializerErrorUnitTest.java:35) ... 23 more
Как упоминалось ранее, Java создает исключение ExceptionInInitializerError , сохраняя при этом ссылку на первопричину:
assertThatThrownBy(StaticBlock::new) .isInstanceOf(ExceptionInInitializerError.class) .hasCauseInstanceOf(ArithmeticException.class);
Также стоит упомянуть, что метод является методом инициализации класса в JVM.
Создание своих объектов-исключений
Когда вы выбираете исключение, которое будет бросать ваш код в какой-либо ситуации, вы можете выбрать создание своего нового класса исключения.
Вам следует написать свои собственные классы исключений, если вы ответите «Да» на любой из следующих вопросов, в противном случае вам, вероятно, следует использовать какое-нибудь из существующих исключений:
- Вам нужно исключение типа, который не предоставлен платформой Java?
- Поможет ли это пользователям, если они смогут отличать ваши исключения от исключений, брошенных другими производителями?
- Бросает ли ваш код более одного связанного исключения?
- Если вы используете чьи-то другие исключения, то смогут ли пользователи получить доступ к этим исключениям? Или должен ли быть пакет независимым и самодостаточным?
Предположим, что вы описываете игровую логику, то вам, возможно, потребуется различать следующие виды исключений:
В качестве родительского класса для своего исключения
GameLogicException логичнее всего выбрать класс
Exception, так как в нашем случае нужны именно проверяемые исключения.
Согласно соглашению о кодировании в Java имена исключений должны заканчиваться на
Exception.
Пример возможного кода для исключения
GameLogicException:
GameLogicException.java
Java
public class GameLogicException extends Exception {
// Конструкторы, вызывающие конструкторы базового класса.
public GameLogicException() {
super();
}
public GameLogicException(String message) {
super(message);
}
public GameLogicException(String message, Throwable cause) {
super(message, cause);
}
public GameLogicException(Throwable cause) {
super(cause);
}
// остальные методы.
}
1 |
publicclassGameLogicExceptionextendsException{ // Конструкторы, вызывающие конструкторы базового класса. publicGameLogicException(){ super(); } publicGameLogicException(Stringmessage){ super(message); } publicGameLogicException(Stringmessage,Throwable cause){ super(message,cause); } publicGameLogicException(Throwable cause){ super(cause); } // остальные методы. } |
Основные аннотации Spring: внедрение зависимостей с помощью @Autowired
В предыдущем разделе мы определили, зачем нужен Spring, какие проблемы он решает и как подключить Spring Framework в свое приложение. Теперь рассмотрим основной функционал Spring, и как с его помощью можно повлиять на поведение приложения. Давайте пройдемся по самым часто используемым аннотациям.
Самая популярная в Spring аннотация — определенно . И разработчики часто пренебрегают ею, используют в неположенном месте и просто надеются на магию Spring. Давайте разберемся, для чего она нужна, и какие правила использования существуют.
Аннотация отвечает в Spring за внедрение зависимостей. Ею можно пометить место внедрения (сеттер, поле или конструктор), и Spring автоматически свяжет нужный бин с этим местом. Используем в нашем коде внедрение зависимости через сеттер с помощью :
@Autowired
Создадим Java-конфигурацию вместе с аннотацией — с ее помощью нам больше не нужно будет явно указывать наши бины в коде:
@Autowired
Существует три вида внедрения зависимостей (DI) при помощи , и каждая — со своими правилами применения:
- ;
- ;
- .
Давайте рассмотрим каждый тип зависимостей более детально.
Сonstructor Injection
Внедрение через конструктор следует использовать когда зависимость является обязательной, или ее необходимо сделать неизменяемой (с помощью ключевого слова ).
Благодаря также легче заметить «суперклассы» — перегруженные классы с большим количеством зависимостей. Если в классе все зависимости подключаются через конструктор, то в глаза сразу бросается большое количество параметров. И у разработчика появится ощущение, что он делает что-то не так.
Setter Injection
Внедрение через сеттер следует использовать, когда зависимость является опциональной.
позволяет делать опциональные зависимости — такие зависимости можно внедрять повторно. Но использование внедрения через сеттер для обязательной зависимости может привести к и остановке приложения. Хоть и существует способ избежать этого с помощью аннотации , все равно следует внимательно следить за этим типом DI.
часто используется в классах, которые должны легко поддаваться реконфигурации. Помимо этого, сеттеры дают возможность определять зависимости в интерфейсе.
Field Injection и основные причины его избегать
Внедрение зависимостей при помощи не рекомендуется делать по нескольким причинам:
- при этом типе внедрения нельзя сделать зависимость неизменяемой;
- плотная зависимость от IoC-контейнера — если вы захотите заменить спринговый IoC-контейнер или просто его убрать, то перед этим придется переписывать много кода;
- ряд дополнительных сложностей с рефлексией при написании юнит-тестов;
- слишком простая процедура добавления зависимостей, в результате которой легко создать «суперкласс» и перезагрузить код программы.
Setter или Constructor Injection?
До недавнего времени мнения насчет того, какой тип внедрения зависимости использовать, разнились даже у самих разработчиков Spring Framework. До версии 4.0 команда создателей Spring рекомендовала внедрять зависимости через сеттер. Он объясняли это тем, что большое количество аргументов конструктора может стать очень громоздким. Особенно, когда их свойства являются необязательными.
Но начиная с версии 4.0, команда Spring начала явно выступать за внедрение зависимостей через . Это позволяет реализовать компоненты приложения как неизменяемые объекты. Таким образом можно гарантировать, что требуемые нам зависимости будут точно проинициализированы.
Вы всегда вправе выбрать любой тип внедрения зависимостей и при необходимости даже смешивать их. Главное помнить, что выбор типа внедрения всегда должен быть основан на ваших потребностях и потребностях разрабатываемого вами ПО.
Решение ошибки «Необрабатываемое исключение в приложении»
Метод №1 Удаление антивируса
Бесплатные антивирусы могут достаточно полезны в качестве защитника вашей системы, однако они также могут вызывать множество проблем на компьютере. Попробуйте заменить антивирус, который вы используйте в данный момент, на другой. Вот что вам потребуется сделать, чтобы удалить антивирус:
- нажмите правой кнопкой мыши на Пуск;
- кликните на пункт «Приложения и возможности»;
- найдите в списке установленных приложений ваш антивирус и выберите его;
- нажмите на кнопку «Удалить»;
- проследуйте инструкциям на экране для удаления антивируса;
- перезагрузите компьютер.
Проверьте, появляется ли ошибка «Необрабатываемое исключение в приложении» теперь, когда старого антивируса больше нет. Если проблема решена, то дело действительно заключалось в антивирусе, препятствующим нормальной работе вашей системы.
Метод №2 Выполнение чистого запуска
Различные программы и службы могут вызывать неполадки в работе Microsoft .NET Framework. Первый делом — убедитесь, что это не вина антивирусной программы. Если он не виноват, то стоит попробовать кое-что другое: чистый запуск системы. Выполняется он следующим образом:
- нажмите комбинацию Windows+R;
- впишите команду «msconfig» и нажмите Enter;
- перейдите во вкладку «Загрузка» и уберите галочку с пункта «Безопасный режим»;
- пройдите в «Общие», выберите «Выборочный запуск» и уберите галочку с пункта «Загружать элементы автозагрузки»;
- перейдите во вкладку «Службы», поставьте галочку возле «Не отображать службы Майкрософт» и нажмите кнопку «Отключить все»;
- во вкладке «Автозагрузка» нажмите на пункт «Открыть диспетчер задач»;
- во вкладке «Автозагрузка» диспетчера задач нажмите правой кнопкой мыши на каждую из программ и выберите «Отключить»;
- перезагрузите компьютер, а затем активируйте каждый из отключенных элементов поочередно, чтобы понять, в чем заключалась проблема.
Возможно, именно одна из отключенных проблем и вызывала ошибку «Необрабатываемое исключение в приложении».
Метод №3 Установка последней версии .NET Framework
На каждом компьютере должны быть установлены библиотеки .NET Framework различных версий. Они крайне важны как для корректной работы операционной системы Windows, так и для запуска современных программ и видеоигр.
- Воспользуйтесь для загрузки установщика .NET Framework последней версии;
- после установки нажмите комбинацию Windows+R;
- в пустую строку впишите значение «control.exe» и нажмите Enter;
- нажмите на пункт «Удаление программы»;
- кликните на пункт «Включение или отключение компонентов Windows»;
- убедитесь, что все версии .NET Framework активированы в этом списке; активируйте, если какие-то из них не помечены;
- перезагрузите компьютер и проверьте, была ли решена проблема.
Метод №4 Использование утилиты SFC
Ошибка «Необрабатываемое исключение в приложении» могла появиться из-за повреждения некоторых системных файлов, включая и файлов .NET Framework. Чтобы это исправить, вы можете попробовать воспользоваться такой полезной системной программой, как System File Checker. Вот как ее запустить:
- нажмите Windows+R;
- напишите в пустую строчку «cmd» и нажмите Enter;
- впишите в вызванную командную строку «sfc /scannow» и нажмите Enter;
- по окончанию работы программы перезагрузите компьютер.
Использовав предложенные методы, вы обязательно устраните ошибку «Необрабатываемое исключение в приложении».
23
25
Прекращена работа программы Java(TM) Platform SE binary
- Появление ошибки после первого запуска приложения свидетельствует о возможном отсутствии модуля Джава на ПК. Даже если есть какие-то следы ПО, то их лучше удалить и скачать плагин заново.
- Если Джава установлена на компьютере, сравните ее разрядность с аналогичным параметром операционной системы. Для этого найдите плагин в панели управления. Название, не содержащее цифр, говорит о версии x64, в противном случае установлена x32.
После исключения отсутствия модуля или несовместимости остается только один источник проблемы – видеокарта. Выполните следующие действия:
- Создайте новую переменную среды. О том, как это сделать, рассказано выше. Напишите следующие параметры: имя – _JAVA_OPTIONS, значение – -Xmx256M.
- Сохраните переменную, перейдите к настройкам в игре.
- Отключите следующие параметры: VSync, VBos, Smooth Lighting.
- FOV должно иметь значение Normal.
Для закрепления результата обновите драйвера для видеокарты и перезагрузите компьютер.
Как исправить NullPointerException
В нашем простейшем примере мы можем исправить NPE, присвоив переменной n1 какой-либо объект (то есть не null):
Integer n1 = 16; System.out.println(n1.toString());
Теперь не будет исключения при доступе к методу toString и наша программа отработает корректно.
Если ваша программа упала из-за исключение NullPointerException (или вы перехватили его где-либо), вам нужно определить по стектрейсу, какая строка исходного кода стала причиной появления этого исключения. Иногда причина локализуется и исправляется очень быстро, в нетривиальных случаях вам нужно определять, где ранее по коду присваивается значение null.
Иногда вам требуется использовать отладку и пошагово проходить программу, чтобы определить источник NPE.
Как автоматизировать создание комментариев
В различных IDE есть возможность автоматизировать создание комментариев. Это делается с использованием тегов — дескрипторов, которые начинаются с символа @. Вот самые популярные:
- @author — идентифицирует автора исходного кода;
- @param — определяет параметр метода;
- @see — ссылка;
- @since — версия программного обеспечения;
- @return — тип возвращаемых процедурой или функцией данных.
Из таких комментариев автоматически формируется документация программы. Для этого используют генераторы документации, например, javadoc для языка Java, phpDocumentor для PHP, doxygen для C и C++, Epydoc для Pithon и другие.
Принцип работы прост. Генератор обрабатывает файл с исходным текстом, находит там имена классов, их членов, свойств, методов, процедур и функций, а затем связывает их с данными из наших комментариев с тегами. Из этой информации формируется документация в формате HTML, PDF, RTF или других.
При разработке библиотек и фреймворков обычно создается документация для API. Со временем она устаревает — в неё не успевают или просто забывают вносить изменения.
Ошибка exceptioninitializererror
ExceptionInInitializerError указывает, что в статическом инициализаторе произошло непредвиденное исключение . В принципе, когда мы видим это исключение, мы должны знать, что Java не удалось вычислить статический блок инициализатора или создать экземпляр статической переменной.
Фактически, каждый раз, когда какое-либо исключение происходит внутри статического инициализатора, Java автоматически обертывает это исключение внутри экземпляра класса ExceptionInInitializerError . Таким образом, он также поддерживает ссылку на фактическое исключение в качестве основной причины.
Теперь, когда мы знаем причину этого исключения, давайте рассмотрим его на практике.
Funny mistakes
Все упомянутые выше ошибки можно назвать «серьезными», однако есть и «смешные». Так, например, выражение I feel myself fine заставляет задуматься о действиях говорящего, ведь в таком сочетании feel переводится как «трогать», «ощупывать» и фраза I feel myself fine звучит достаточно странно, не так ли? Если же вы хотите сказать, что прекрасно себя чувствуете, то следует сказать I feel_fine.
Почему-то возникают проблемы при ответе на простые вопросы «Как дела?», «Какая сегодня погода?». Рассмотрим примеры:
- How are you? (как дела?) – I am good (я хороший). Конечно же, вы хороший человек, но ответить нужно: I am well / fine (у меня все хорошо).
- How are you doing? (как дела?) – I am doing nothing (я ничего не делаю). Никто не спрашивает, что вы делаете. Ожидается услышать как у вас дела, т. е. I am well / fine.
- What is the weather like today? (какая сегодня погода?) – Yes, I like it (да, она мне нравится) → The weather is fine today (сегодня хорошая погода).
Очень часто можно услышать, как вас все любят и нуждаются в вас:
- English needs me for my job (английский нуждается во мне) вместо I need English for my job (мне нужен английский для работы). Английский обойдется и без вас. English doesn’t need you!
- These new shoes like me (эти новые туфли любят меня) вместо I like these new shoes (мне нравятся эти новые туфли).
Встречаются также ученики с завышенной или заниженной самооценкой:
- I am interesting (я интересный) вместо I am interested in it (мне это интересно).
- I am very good (я очень хороший) вместо I am very well (дела очень хорошо).
- I am boring (я скучный) вместо I am bored (мне скучно).
- I am scary (я ужасный) вместо I am scared (я напуган).
А некоторые пошли туда, не знаю куда:
I went to the magazine (magazine – журнал) вместо I went to the shop (я пошел в магазин).
Представим вышеупомянутые ошибки в виде таблицы, которую необходимо распечатать и повесить над письменным столом (рядом с таблицей неправильных глаголов). Здесь собраны самые частотные примеры:
↓ Скачать таблицу “Top 40 most common mistakes made by our students” (*.pdf, 361 Кб)
Top 40 most common mistakes made by our students | ||
---|---|---|
№ | Ошибка | Правильный вариант |
1 | Colleague | Colleague |
2 | Hotel | Hotel |
3 | Also | Also |
4 | Since | Since |
5 | Policeman | Policeman |
6 | Society | Society |
7 | Stopped , worked | Stopped , worked |
8 | I went to somewhere | I went_somewhere |
9 | I phoned to him | I phoned_him |
10 | I came to home | I came_home |
11 | I went to holiday | I went on holiday |
12 | To influence on smth | To influence_smth |
13 | It depends from smth | It depends on smth |
14 | Discuss about smth | Discuss_smth |
15 | In last week | _Last week |
16 | In Monday | On Monday |
17 | In 5 o’clock | At 5 o’clock |
18 | In the weekend | At the weekend |
19 | Childrens, peoples, mans, womans | Children, people, men, women |
20 | A lot of advices | A lot of advice |
21 | I am agree | I_agree |
22 | I_tired | I am tired |
23 | It’s mean that | It means that |
24 | I_afraid / I don’t afraid | I am afraid / I am not afraid |
25 | I very much like it | I like it very much |
26 | He said what | He said that |
27 | I haven’t a car | I don’t have a car / I haven’t got a car |
28 | If the weather will be fine, we’ll go for a walk | If the weather is fine, we’ll go for a walk |
29 | I feel myself fine | I feel_fine |
30 | I forgot my book at work | I left my book at work |
31 | It’s often rain | It often rains |
32 | How are you? – I am good | How are you? – I am well / fine |
33 | How are you doing? – I am doing nothing | How are you doing? – I am well / fine |
34 | What is the weather like today? – Yes, I like it | What is the weather like today? – The weather is fine today |
35 | English needs me for my job | I need English for my job |
36 | These new shoes like me | I like these new shoes |
37 | I am interesting | I am interested in it |
38 | I am boring | I am bored |
39 | I am scary | I am scared |
40 | I went to the magazine | I went to the shop |
Если вы учите английский язык давно, то у вас тоже должны быть «любимые грабли» – ошибки, которые не хотят уходить. Поделитесь ими с нами, и, может, тогда мы сможем вместе бороться с ними!
P.S. Благодарю моих коллег за помощь в подборке материала!
P.P.S. Отдельная благодарность Светлане за идею для написания статьи!
Думаете, что вы не допускаете подобных ошибок? Проверьте себя, выполнив тест на самые распространенные ошибки в английском языке:
ТестТест на самые распространенные ошибки в английском языке
Как проверить canonical
Проверить, для каких страниц вы настроили canonical и какие канонические страницы указали, можно с помощью сервиса Screaming Frog SEO Spider.
Результаты проверки страниц краулером
Узнать, какую страницу Google считает основной для конкретного URL, можно через .
Проверить, как поступил Яндекс, можно в Вебмастере: если вы верно указали каноническую страницу, дубли пропадут из поиска. Посмотрите страницу «Индексирование» — «Страницы в поиске». Если страницу исключили из результатов, она будет в блоке «Исключённые страницы».
Проверка наличия дубля в выдаче
Рассказывайте, о каких необходимых вариантах использования canonical мы забыли, и какие еще ошибки настройки вы встречали в своей практике!
StringBuffer
Класс StringBuffer используется для создания и модификации строковых выражений, из которых можно создать String. В отличии от неизменяемого
String он реализован на основе массива char[] и, после создания объекта, значение содержащейся в нем строки может быть изменено.
Наиболее часто используемые конструкторы класса StringBuffer :
- StringBuffer () — пустой объект StringBuffer;
- StringBuffer (String s) — объект со строкой s;
- StringBuffer (int capacity) — объект c заранее заданным размером массива.
Определение размера массива не означает, что нельзя будет манипулировать со строками, размер которых более указанной при создании объекта.
Это всего лишь говорит о том, что при манипулировании строками, длина которых меньше указанной, не потребуется выделения дополнительной
памяти.
Пример использования StringBuffer
package example; public class StringBufferExample { void addString(StringBuffer sb, final String text) { sb.append(text); } public static void main(String[] args) { StringBuffer sb = new StringBuffer("Привет"); System.out.println("До : '" + sb + "'"); StringBufferExample sbe = new StringBufferExample(); sbe.addString(sb, " мир!"); System.out.println("После : '" + sb.toString() + "'"); } }
В результате в консоль будет выведено следующее сообщение :
До : 'Привет' После : 'Привет мир!'
Основные методы, используемые для модификации StringBuffer
/** * Метод добавления строки str к уже имеющейся в объекте */ append(String str) /** * Метод вставки строки str начиная с позиции offset (пропуская offset символов) */ insert(int offset, String str)