воскресенье, 30 апреля 2017 г.

Just run it

Пора написать что-то, что не относилось бы к программированию вообще, и к Java, в частности. Просто из-за большой нагрузки на работе не удается посвящать этому столько времени, скольхо хотелось бы - успеваю разве что пройти тест по Java раз в день и иногда немного почитать/послушать/посмотреть что-нибудь обучающее. Поэтому востребованным оказывается то, что требует меньше времени, а именно - физкультура и чтение книг по саморазвитию. Событие сегодняшнего дня - пробежка в лесу!
В лесу я не бегал с прошлого года, наверное, с сентября. Это было очень классно! Надо сказать, что за последний месяц мне удалось пройти 10 тренировок (громкое слово "бодибилдинг"), а потому тело хочет нагрузок. А хорошая погода стимулирует желание быть быстрым и легким. Сегодня все сошлось, и я доволен.

воскресенье, 12 марта 2017 г.

A programmer: Java #6: A a = new B();

Долго не мог разобраться с тем, что означает выражение

A a = new B(); // B extends A

Первый мой ответ на этот вопрос был таким:

Когда на объекте а вызывется метод, будет вызван тот его вариант, который переопределен в классе-наследнике. То есть:

Класс-наследник, кроме собственных методов, имеет все методы классов-родителей. Последние могут быть переопределны в классе-наследнике:

Пусть у класса А есть метод do() { // реализация для А};
И у класса В есть метод do() { // реализация для В}

Соответственно, в нашем случае - для a.do(); будет выбрана реализация для В:

Class Животное {
    издатьЗвук() {
        "Звук-Звук";
    };
}

Class Cобака extends Животное {
    издатьЗвук() {
        "Гав-Гав";
    };
}
Животное животное = new Собака();
животное.издатьЗвук();

Результат: "Гав-Гав".

Но возникал вопрос: а что в данном случае происходит с полями? Будут это поля из А или из В?

Я рассуждал так, что поля должны быть из А, потому что методы из В берутся только в том случае, если они переопределены, а поля ведь не могут быть переопределены, значит, они должны остаться от А.

Но правильный ответ - нет, потому что в нашем случае объект а - это объект класса В, который приведен к типу А. Что это значит? Мне посоветовали читать "Философию Java", но хороший ответ нашел тут: "Преобразование типов".

Это значит, что если а - это объект класса В, то поля относятся к классу В. А "приведение ссылочных типов" означает только то, что в приведенном объекте не видны те поля, которых нет в классе-родителе (хотя они есть!). Следовательно, логика тут такая - обрезать то, чего нет в родителе, а в оставшихся полях будут значения из класса-наследника.

Другими словами, если у Животного не предусмотрен Хвост (а предусмотрен только у Собаки), то у нас будет Собака, которой нельзя использовать Хвост (хотя он есть). А если у Животного Хвост предусмотрен, то это будет Хвост Собаки.


UPD: На самом деле поля будут и от А, и от В. Но в случае прямого приведения типов ((А) а) поля от В будут скрыты (как если бы их не было). Другими словами Хвост будет не Хвостом Собаки, а Хвостом Животного.

На эту тему также посмотреть можно здесь, здесь, здесь и здесь.

понедельник, 6 февраля 2017 г.

A programmer: Time checking

Очень коротко о времени. Помнится, я собирался заниматься программированием 1 час в день (см.: A programmer: Time is experience). Как же обстоят дела спустя год?


В течении года были разные периоды. Например, иногда у меня по разным не получалось заниматься неделями и даже месяцами, и я очень переживал по этому поводу. С ноября я пошел на курсы, которые существенно активизировали работу, и поэтому смог наверстать упущенное. Таким образом, в итоге оказалось, что за 2016 год я потратил на программирование 384 часа (что больше, чем в среднем 1 час в день :)). Учитывая, что за этот год на данный момент я занимался 97 часов, а это почти 3 часа в день, то такая динамика мне весьма нравится. И дело не во времени как таковом - я вижу результат. Он, конечно, пока не такой, как хотелось бы, но я думаю, что около 20% того результата, при котором я мог бы чувствовать себя уверенным программистом (разумеется, при наличии постоянной практики - включительно), у меня уже есть. С одной стороны, получается, что, если динамика сохранится, то до 100% результата мне надо еще около 2 лет (а не 33 :) - уже хорошо). С другой, и динамика может измениться, и чувство уверенности прийти раньше, да и в не совсем уверенном состоянии тоже можно утверждаться в качестве программиста.

пятница, 6 января 2017 г.

A programmer: Java #5: Abstract and Final classes

Небольшая заметка для себя насчет abstract и final классов.

Abstract - класс, от которого нельзя создать экземпляр (инстанциироваться). Обычно нужен, чтобы от него наследовались другие классы. Соответственно, он может иметь только статические методы и переменные - для их вызова не нужны экземпляры.

Final - класс, от которого нельзя наследоваться. Тем самым - нельзя переопределять его переменные и методы (то есть они неявно тоже final). Но создавать экземпляры такого класса можно.

Класс может быть одновременно и abstract, и final. В этом случае, соответственно, доступны только его собственные статические методы и переменные, поскольку, как было сказано, у abstract класса не может быть экземпляров.

понедельник, 2 января 2017 г.

A programmer: Java #4: Annotations


После долгих (и не очень нужных, видимо) моральных приготовлений возвращаюсь не просто к блогу, но к Java. Сегодняшняя тема — аннотации.

Когда я учился Java, я видел код — переменные, методы, циклы и прочее, а вот некоторых вещей не видел, и встретил впервые только на курсах. В числе этих невиданных штук были аннотации — это такие надписи со значком @. Очевидно, они для чего-то нужны. Иногда мне рассказывали, для чего, но вот как они работают, я понять не мог очень долго. Мне посоветовали написать аннотацию самому. Но результативно помочь мне в этом лучше всего остального смогла книга Уоллс К. Spring в действии. – М.: ДМК Пресс, 2013 и одно волшебное слово. Про книгу напишу в следующий раз, а про волшебное слово сейчас.

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

@MyAnnotation(здесь могут быть описаны параметры аннотации)

Аннотации основаны на механизме интерфейса, поэтому ключевое слово @interface и будет свидетельствовать о том, что это аннотация:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String info() default "";
int val() default 42;
}

Здесь @Target(ElementType.METHOD) и @Retention(RetentionPolicy.RUNTIME) указывают, что аннотация применима к методу и что она исполняется при выполнении программы, соответственно (разумеется, предусмотрены и другие опции). Для того, чтобы это работало, надо импортировать соответствующие пакеты:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

В дальнейшем таким же образом нужно будет импортировать пакет с нашей аннотацией, чтобы она была рабочей.

Как уже говорилось, значения описанных в аннотации переменных (если они иные, чем по умолчанию) могут указываться при применении аннотации.

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

Один из типичных примеров аннотаций для валидаций в коде выглядит так:
@Size(min=3, max=20, message="Username must be between 3 and 20 characters long.")
Когда я стал разбираться, как устроены аннотации для валидаций, то выяснилось, что, кроме обычных уже вещей, они содержат еще одну аннтоацию для аннотаций (вот заветное волшебное слово): @Constraint. После него и указывается файл, в котором и происходит соответствующая проверка:
@Constraint(validatedBy = BlaBlaBlaValidator.class)

То есть, кроме собственно аннотации надо написать соответствующий класс. Другое дело, что у стандартных аннотаций этот класс уже «встроен», как я понял.

Волшебное слово лучше всего описано здесь:
Spring MVC кастомная аннотация для валидации форм (http://devcolibri.com/2664)
и здесь:

Другие материалы по аннотациям:

1. Об аннотациях вообще:

 - The Java™ Tutorials. Lesson: Annotations (http://docs.oracle.com/javase/tutorial/java/annotations/index.html);
 - Аннотации в Java (http://www.quizful.net/post/annotations-in-java);
 - Аннотации в Java - Annotation Types (http://www.javenue.info/post/79);
 - Spring. Аннотации. Конфигурация с помощью аннотаций - 9 - The Basics of Spring Framework (Юрий Ткач) (https://www.youtube.com/watch?v=cIYUAKDnFo4&list=PL6jg6AGdCNaWF-sUH2QDudBRXo54zuN1t&index=9);
 - Аннотации в Hibernate(http://java-course.ru/student/book2/hibernate-annotation/);
 - Как написать свою Аннотацию в Java? (http://devcolibri.com/1253);

2. Об аннотации @Autowired (как пример):

 - Использование аннотации @Autowired в Spring 3 (http://www.seostella.com/ru/article/2012/02/12/ispolzovanie-annotacii-autowired-v-spring-3.html);

3. Валидация:

 -  Проверка данных формы с помощью аннотаций (@Size, @Email и др) в Spring MVC (http://www.seostella.com/ru/article/2012/06/21/proverka-dannyh-formy-s-pomoschyu-annotaciy-size-email-i-dr-v-spring-mvc.html);
 - Spring. Проверка введенных данных (http://spring-projects.ru/guides/validating-form-input/);
 - Как создать собственный валидатор для Sping MVC (http://www.javacore.ru/topic/96-mvc-spring.htm);
 - Проверка входных данных Spring (http://src-code.net/proverka-vxodnyx-dannyx-spring/).