Страницы

Поиск по вопросам

суббота, 6 октября 2018 г.

Для чего нужен блок static?

Где в реальной жизни может использоваться такой блок в программировании? Зачем тогда конструктор? Да я понимаю, что конструктор будет вызываться при каждом новом создании экземпляра класса, а статик блок единожды. Но в какой момент пройдет инициализация статик блока и где реально он применяется?


Ответ

Статические блоки вызываются в момент инициализации класса (когда ClassLoader будет грузить его в MetaSpace, подробнее в JLS), и могут использоваться для иницализации статических переменных. Зачем вызывать каждый раз инициализацию статических переменных в конструкторе, если можно сделать это единожды, таким образом не тратить ресурсы на повторные инициализации?

Начало программирования под Android

В общем, я обучаюсь по книге "Head First программирование под Android", почему по ней? А потому что она новая, и рассчитывал на то, что я избегу многие неприятности с "устаревшими" приёмами, библиотеками и т.д. Но не тут то было, по книге мне надо создать ListActivity(нужен макет со списком напитков), а как я понял, он уже устарел, т.к. теперь там много других активностей и из них более мене подходит Master/Detail Flow, но он создает много активностей и макетов, что никак не вписывается в задачу. Подскажите, что в этом случае делать?
У меня все проекты создаются дэфолтно с расширением класса appcompatactivity, а в моей книге просто Activity, это как то связано с обновлениями? Может кто подробно про это рассказать?


Ответ

Начнем с того, что Java вы начали изучать скорее всего не с того, что сразу начали GUI писать в JavaFX и организовывать клиент-серверное взаимодействие, а с самых основ и простейших примеров в консоли. При обучении разработки под Android вам стоит поступить так же - делать простейшие примеры, постепенно усложняя задачи. Фактически фреймворк Android отдельная эко-система, которая только использует язык Java для написания кода и все это требует отдельного обучения "с нуля".
Учиться я бы вам посоветовал по книге от BigNerdRanch: Б.Харди - "Android. Программирование для профессионалов" - 2015 (2-ое издание) - это, пожалуй, единственная достойная книга на русском языке для новичка. Обучение построено на том, что ставится конкретная задача (какое-то приложение) и последовательно, шаг за шагом, с подробными объяснениями, эта задача реализуется. В результате вы напишите реальное работающее приложение (всего их пять, если мне не изменяет память, исходники всех приложений доступны на GitHub и легко находятся по названию) и даже будете понимать, как это делать самому. Так же эта книга даст вам целостное представление об устройстве приложения и взаимодействии его частей, в отличие от книг-справочников или уроков в интернете, где дается разрозненная информация о отдельных элементах, оставляя самому думать о том, как все это соеденить в работающее и не пугающее остальных, кто увидит код, приложение :) При небольшом усердии можно найти бесплатную электронную копию этой книги.
Насчет устаревших классов и или наследников. То, что в реальной разработке использовать ListActivity вам вряд-ли придется, не зависимо от ее устаревшести, так как она наименее гибкая в реализации списка, мы здесь опустим. Дело вот в чем - базовый класс экрана Android-приложения - класс Activity. Используя только этот класс вы безусловно можете реализовать весь необходимый функционал. Наследующиеся же от базового Activity классы лишь добавляют немного какой то функциональности, например, ListActivity реализует слушатель и упрощает подключение разметки, в основном - это делается и в обычной активити в несколько строчек кода. Что касается AppCompatActivity - она создана для того, чтобы поддерживать Material Design на устройствах с API < 21 (до Android 5.0, где этот дизайн по дефолту) вместе с библиотекой поддержки AppCompat и обеспечить взаимодействие ActionBar с этой библиотекой поддержки. Не думаю, что дизайнерские изыски первоочередная задача при начале обучения, главное для вас - научиться работать с фреймворком, украсить вы всегда успеете. Так же стоит заметить, что если вы не собираетесь распространять свои уроки, то беспокоится об обратной совместимости вообще нет нужды. При начале обучения не стоит обращать внимание на "устаревшесть" информации или классов - принципы в базе остаются неизменными и ничего кардинально нового "новые" классы не несут. Напротив, понимание работы с "устаревшими" классами облегчат использование "новых", так как вам нужно будет только понять, что (и зачем) добавилось. В случае с AppCompatActivity вообще можно с некоторыми незначительными оговорками считать ее за Activity, то есть использовать равнозначно.
Таким образом в обучающих проектах вы можете с полной уверенностью использовать класс Activity, ListActivity и любой другой, который требуется для понимания задания, не обращая внимание на его устаревшесть. Когда вы будете понимать принципы работы с фреймворком достаточно, чтобы писать собственное приложение, вы без труда сможете определиться, какой именно тип активити вам нужен для каждого отдельного экрана, не стоит сейчас на этом заморачиваться. Если вас смущает дефолтное создание активити , то просто удалите первых девять букв (оставив extends Activity) и измените тему приложения с AppCompat, на какую-нибудь из Holo, либо не обращайте на это внимание вовсе - AppCompatActivity естественно реализует все базовые методы Activity и на работу примера это никак не повлияет, как правило.
Насчет шаблонов - единственный шаблон, который стоит использовать - Blank Activity, для чего остальные остается тайной за семью печатями :) - новичок не сможет их осилить ввиду крайней перегруженности, человек опытный реализует все самостоятельно, как ему нужно для конкретной задачи, это проще, чем адаптировать чужую заготовку под свое решение. Все эти шаблоны крайне избыточны и неоправданно запутаны.
Насчет уровня знания Java. Владение базовыми возможностями языка на хорошем уровне вполне достаточно для написания полноценного приложения. Наиболее актуально знание самого фреймворка, его классов, структуры приложений, взаимодействие с системой, принципы верстки макетов и тп. В частности жизненный цикл вызывает много непониманий в начале.
Гугл создал очень хороший портал разработчика Android, который включает как полное описание API, так и множество гайдов, примеров и инструкций. Кроме того, здесь вы всегда получите самую актуальную информацию, в частности об отличиях AppCompatActivity от базовой Activity (краткое описание и какие методы добавились к наследуемым и кстати, обратите внимание на цепочку наследования). Приятным бонусом будет то, что портал активно переводится на русский язык и многие статьи можно прочесть на родном языке. Советую вам очень внимательно изучить его после прочтения книги выше и обретения начального понимания принципов разработки под этим фреймворком. Начать можно отсюда
Ну и здесь есть огромное количество как готовых ответов, так же как и людей, всегда готовых ответить на хороший новый вопрос.
PS: если какие то моменты не достаточно понятны, пишите в комментариях, дополню ответ.

Что такое делегат в языке С#?

Объясните простым, человеческим языком, кто такой и зачем нужен делегат в ООП вообще и в С# в частности?


Ответ

Делегат — это объектно-ориентированный способ работы с методом как с переменной. Его более привычный аналог — указатель на функцию, функтор, или даже просто вектор прерывания (спасибо @rdorn за подсказку).
Делегат представляет собой тип, соответствующий определённой сигнатуре функции. Объявив переменную делегатного типа, вы можете записать в неё статический или нестатический метод, передать его как аргумент куда-либо, и вызвать.
Классический пример использования делегатов — сортировка списка объектов по значению какого-либо поля. Вы передаёте в сортирующий метод делегат, который по объекту вычисляет ключ сортировки, то есть, вытаскивает значение поля.

Что быстрее: обход вектора или обход списка?

На собеседовании спросили: что быстрее, обход вектора или обход списка с выводом значений в консоль? Каким образом обходим, не уточнили. Я ответил, что разницы нет. Был ли я прав? Пояснение: имеется контейнер вектор, по которому мы пробегаемся, например, итератором:
std::vector vector{1, 2, 3}; for (auto it = vector.begin(); it != vector.end(); ++it) { qDebug() << *it; }
имеется контейнер список, по которому мы также пробегаемся итератором:
std::list values{1, 2, 3}; for (auto it = values.begin(); it != values.end(); ++it) { qDebug() << *it; }
Какой из циклов будет работать быстрее и почему? Какой из циклов будет работать быстрее при других способах обхода этих контейнеров? Этих циклов не было на собеседовании, я их добавил для наглядности.
P.S. После этого вопроса затем спросили: что такое кэш? Возможно, второй вопрос как-то связан с первым? Если весь вектор или список не попадает в кэш, то время обхода контейнера увеличится?


Ответ

Вектор несколько быстрее - за счет двух факторов:
в нем нет переходов по указателям, нет лишних разыменований в нем нет переходов по указателям - все лежит одной кучей, а значит, с высокой степенью локальности, так что высока вероятность, что все содержимое вектора разместится в кеше процессора (а если и не все из-за очень большого вектора - то большими кусками), т.е. с существенно более высокой скоростью, чем в общем случае в списке, где элементы могут быть разбросаны по всей памяти...

Как определить, является ли строка числом?

Я делал так, но мне кажется такой подход в чем-то неправильным: private static boolean isDigit(String s) throws NumberFormatException { try { Integer.parseInt(s); return true; } catch (NumberFormatException e) { return false; } }


Ответ

Я так понимаю, цель именно на Integer проверить? Тогда можно: s.matches("[-+]?\\d+") // для списка из 1 млн целых чисел и не чисел // (примерно 50/50) эффективность этой строчки практически // не отличается от описанной в вопросе функции. Если double, но без экспоненциальной нотации, то ((-|\\+)?[0-9]+(\\.[0-9]+)?)+ такое регулярное подойдёт. Хотя я бы не парился и сделал бы точно так же, только с Double.parseDouble(s), но я не показатель :) И ещё я обратил внимание на название метода - оно не очень корректное, т.к. во-первых, такой есть в классе Character, во-вторых, по смыслу подходит isNumeric(). Но это просто комментарии из серии "что я думаю по этому поводу".

Чем отличается List от ArrayList?

Чем отличается List от ArrayList. Погуглил, но толком ничего не нашел (как минимум, на русском языке). Насколько я понял, ArrayList является реализацией List, однако различий я особых не заметил. Так в чем же все-таки разница?


Ответ

Так как ArrayList реализует интерфейс List, то у него должны быть все методы List плюс (возможно) какие-то другие. Отсюда внешняя схожесть. При этом в List эти методы вообще никак не реализованы и невозможно создать объект командой new List()
Реализации одного и того же интерфейса могут иметь внешне одни и те же методы, но радикально отличаться их внутренней реализацией. Например, в основе ArrayList - массив, который при необходимости заменяется большим (или меньшим) по размеру с переписыванием содержимого из старого в новый. В основе же LinkedList (другой реализации интерфейса List) лежит двунаправленный связанный список, а каждый элемент списка содержит в себе ссылку на следующий и предыдущий элементы.

Зачем нужен std::invoke?

Увидел сейчас, что в 17ом стандарте появилась новая шаблонная функция std::invoke. Очень сильно обрадовался, т.к. подумал, что это такой же invoke как в .NET, но поискав информацию о нём, так до конца и не понял, зачем он нужен. Я так понял, что он делает вызов функторов и лямбд, но чем это отличается от их прямого вызова? Может ли std::invoke делать этот вызов в определённом потоке, как это умеет делать его собрат из .NET?


Ответ

std::invoke нужен чтобы унифицированным образом вызвать функторы (в т.ч. лямбды), указатели на функции и указатели на функции-члены классов. Последние имеют специфический синтаксис вызова не совпадающий с синтаксисом обычных функторов:
(obj->*mem_fn_ptr)( args... );
Если вы пишите функцию типа std::async, и вам нужно реализовать поддержку всех callable объектов, то проще передать их одним пакетом в invoke, чем писать отдельную шаблонную реализацию для каждого случая. Такой синтаксический сахар.
Аналога .NET invoke в стандарте нет, потому что нет циклов обработки сообщений, и соответственно, "послать задачу в поток" невозможно. Воспользуйтесь std::async, либо std::thread, если нужно просто асинхронное выполнение, либо функциями WinAPI, либо функциями вашей оконной библиотеки (Qt, wxWidgets...), либо организуйте цикл обработки сообщений "вручную", и запихивайте упакованную задачу в соответствующую очередь.