Java собеседование. Коллекции

С недавнего времени у меня появилась настойчивая мысль, что профессиональное развитие сильно замедлилось и это хочется как-то исправить. Да, читаю книги, слушаю курсы, но в то же время приходит и понимание того, что возможно пришло время сменить работу, здесь вроде как все изучено, плавно уходим в рутину. Данная мысль сподвигла меня на рассылку своего резюме в несколько компаний — лидеров рынка. После прохождения собеседования в 3 из них, я решил, как водится внести свои 5 копеек в освещение обширной темы собеседования, а именно технических вопросов по Java коллекциям, с которыми приходится сталкиваться. Да, знаю, читатель скажет: «коллекции — избитая тема, сколько можно», но часть из приведенных ниже вопросов, я задавал своим знакомым разработчикам, которые занимают именно позиции разработчиков («крепких середнячков», по меркам недалекой от Москвы глубинки, которые уверенно справляются со своей работой на практике, а вот в теории скажем так есть пробелы, потому, что работа не требует решения каких-то нетривиальных задач, да и потому что не всем это интересно — изучать как внутри работает структура данных), вызывало растерянность. Думаю, что рассмотренный материал будет не очень интересен разработчикам выше уровня Junior (я попрошу их комментировать, дополнять и критиковать изложенный здесь материал), а вот Junior`ы уверен, найдут в этой статье интересное для себя.

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

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

1. Чем отличается ArrayList от LinkedList?

В моем рейтинге это один из двух самых популярных вопросов о коллекции, задают в 90% случаев. Вызвал у меня проблему на моем первом собеседовании на Junior Developer`а. Вкратце ответ на этот вопрос сводится к следующему: ArrayList это список, реализованный на основе массива, а LinkedList — это классический связный список, основанный на объектах с ссылками между ними.

Преимущества ArrayList: в возможности доступа к произвольному элементу по индексу за постоянное время (так как это массив), минимум накладных расходов при хранении такого списка, вставка в конец списка в среднем производится так же за постоянное время. В среднем потому, что массив имеет определенный начальный размер n (в коде это параметр capacity), по умолчанию n = 10, при записи n+1 элемента, будет создан новый массив размером (n * 3) / 2 + 1, в него будут помещены все элементы из старого массива + новый, добавляемый элемент. В итоге получаем, что при добавлении элемента при необходимости расширения массива, время добавления будет значительно больше, нежели при записи элемента в готовую пустую ячейку. Тем не менее, в среднем время вставки элемента в конец списка является постоянным. Удаление последнего элемента происходит за константное время. Недостатки ArrayList проявляются при вставке/удалении элемента в середине списка — это взывает перезапись всех элементов размещенных «правее» в списке на одну позицию влево, кроме того, при удалении элементов размер массива не уменьшается, до явного вызова метода trimToSize().

LinkedList наоборот, за постоянное время может выполнять вставку/удаление элементов в списке (именно вставку и удаление, поиск позиции вставки и удаления сюда не входит). Доступ к произвольному элементу осуществляется за линейное время (но доступ к первому и последнему элементу списка всегда осуществляется за константное время — ссылки постоянно хранятся на первый и последний, так что добавление элемента в конец списка вовсе не значит, что придется перебирать весь список в поисках последнего элемента). В целом же, LinkedList в абсолютных величинах проигрывает ArrayList и по потребляемой памяти и по скорости выполнения операций. LinkedList предпочтительно применять, когда происходит активная работа (вставка/удаление) с серединой списка или в случаях, когда необходимо гарантированное время добавления элемента в список.

Для углубленного и в то же время экспресс обучения очень рекомендую к прочтению замечательные статьи tarzan82 о ArrayList и LinkedList. Так же порекомендую статью от lany о потреблении памяти коллекциями — очень познавательно.

2. Что вы обычно используете (ArrayList или LinkedList)? Почему?

Это вопрос является слегка замаскированной версией предыдущего, так как ответ на этот вопрос приведет к постепенному изложению ответа на предыдущей вопрос. В 90% случае ArrayList будет быстрее и экономичнее LinkedList, так что обычно используют ArrayList, но тем не менее всегда есть 10% случаев для LinkedList. Я говорю, что обычно ArrayList использую, ссылаясь на тесты и последний абзац из предыдущего вопроса, но не забываю и про LinkedList (в каких случаях? так же последний абзац предыдущего вопроса помогает).

3. Что быстрее работает ArrayList или LinkedList?

Еще одна замаскированная версия первого вопроса. Хитрее приведенных выше вариантов, что постановка вопроса подразумевает односложный ответ с выбором одного из предложенных вариантов, что, по задумке автора вопроса, как я понимаю, должно сразу выявить человека с неглубокими познаниями в collections. Правильным же действием будет встречный вопрос о том, какие действия будут выполняться над структурой. В итоге, диалог плавно переходит к ответу на первый вопрос.

4. Необходимо добавить 1млн. элемент, какую структуру вы используете?

Тоже довольно популярная скрытая версия первого вопроса. Так же постановка предполагает выбор одного из предложенных вариантов, хотя на самом деле информации для однозначного выбора нет. Нужно задавать дополнительные вопросы: в какую часть списка происходит добавление элементов? есть ли информация о том, что потом будет происходить с элементами списка? какие то ограничения по памяти или скорости выполнения? В целом, все тот же первый вопрос, но немного с другой стороны: вы через дополнительные вопросы, показываете глубину понимания работы Array и Linked List.
Однажды я сам «клюнул» на этот крючок, домыслив про себя, что добавить — это «вставить» в конец списка и усиленно продвигал ArrayList, хотя ничего не знал (и не пытался узнать) про дальнейшие действие с этим списком и возможные ограничения.

5. Как происходит удаление элементов из ArrayList? Как меняется в этом случае размер ArrayList?

Опять же, ответ на вопрос 1 содержит ответ и на этот вопрос. При удалении произвольного элемента из списка, все элементы находящиеся «правее» смещаются на одну ячейку влево и реальный размер массива (его емкость, capacity) не изменяется никак. Механизм автоматического «расширения» массива существует, а вот автоматического «сжатия» нет, можно только явно выполнить «сжатие» командой trimToSize().

6. Предложите эффективный алгоритм удаления нескольких рядом стоящих элементов из середины списка, реализуемого ArrayList.

Неизбитый, по моим меркам вопрос, встречался мне всего однажды, когда я не знал механизма удаления элементов из ArrayList. В итоге вызвал у меня серьезные затруднения. На самом деле все довольно просто и очевидно, когда знаешь как происходит удаление одного элемента. Допустим нужно удалить n элементов с позиции m в списке. Вместо выполнения удаления одного элемента n раз (каждый раз смещая на 1 позицию элементы, стоящие «правее» в списке), нужно выполнить смещение всех элементов, стоящих «правее» n+m позиции на n элементов левее к началу списка. Таким образом, вместо выполнения n итераций перемещения элементов списка, все выполняется за 1 проход.

7. Как устроена HashMap?

Это второй из списка самых популярных вопросов по коллекциям. Уж даже не помню был ли случай, когда этот вопрос мне не задавали.

Вкратце, HashMap состоит из «корзин» (bucket`ов). С технической точки зрения «корзины» — это элементы массива, которые хранят ссылки на списки элементов. При добавлении новой пары ключ-значение, вычисляет хеш-код ключа, на основании которого вычисляется номер корзины (номер ячейки массива), в которую попадет новый элемент. Если корзина пустая, то в нее сохраняется ссылка на вновь добавляемый элемент, если же там уже есть элемент, то происходит последовательный переход по ссылкам между элементами в цепочке, в поисках последнего элемента, от которого и ставится ссылка на вновь добавленный элемент. Если в списке был найден элемент с таким же ключом, то он заменяется. Добавление, поиск и удаление элементов выполняется за константное время. Вроде все здорово, с одной оговоркой, хеш-функций должна равномерно распределять элементы по корзинам, в этом случае временная сложность для этих 3 операций будет не ниже lg N, а в среднем случае как раз константное время.

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

Опять же, рекомендую к прочтению статью tarzan82 по HashMap.

8. Какое начальное количество корзин в HashMap?

Довольно неожиданный вопрос, опять же меня он когда-то заставил угадывать число корзин при использовании конструктора по умолчанию.

Ответ здесь — 16. Отвечая, стоит заметить, что можно используя конструкторы с параметрами: через параметр capacity задавать свое начальное количество корзин.

9. Какая оценка временной сложности выборки элемента из HashMap? Гарантирует ли HashMap указанную сложность выборки элемента?

Ответ на первую часть вопроса, можно найти в ответе на вопрос 7 — константное время необходимо для выборки элемента. Вот на второй части вопроса, я недавно растерялся. И устройство HashMap знал и про хеш-функцию тоже знал, а вот к такому вопросу не был готов, в уме кинулся вообще в другом направлении и сосредоточился на строении HashMap откинув проблему хеш-кода, который в голове всегда привык считать хеш-кодом с равномерным распределением. На самом деле ответ довольно простой и следует из ответа вопроса 7.

Если вы возьмете хеш-функцию, которая постоянно будет возвращать одно и то же значение, то HashMap превратится в связный список, с отвратной производительностью. Затем даже, если вы будете использовать хеш-функцию с равномерным распределением, в предельном случае гарантироваться будет только временная сложность lg N. Так что, ответ на вторую часть вопроса — нет, не гарантируется.

10. Роль equals и hashCode в HashMap?

Ответ на этот вопрос следует из ответа на вопрос 7, хотя явно там и не прописан. hashCode позволяет определить корзину для поиска элемента, а equals используется для сравнения ключей элементов в списке внутри корзины и искомого ключа.

11. Максимальное число значений hashCode()?

Здесь все довольно просто, достаточно вспомнить сигнатуру метода: int hashCode(). То есть число значений равно диапазону типа int — 2^32 (точного диапазона никогда не спрашивали, хватало такого ответа).

12. Как и когда происходит увеличение количества корзин в HashMap?

Вот это довольно тонкий вопрос. Как показал мой мини-опрос, если суть устройства HashMap себе представляют многие более-менее ясно, то этот вопрос часто ставил собеседника в тупик.

Помимо capacity в HashMap есть еще параметр loadFactor, на основании которого, вычисляется предельное количество занятых корзин (capacity*loadFactor). По умолчанию loadFactor = 0,75. По достижению предельного значения, число корзин увеличивается в 2 раза. Для всех хранимых элементов вычисляется новое «местоположение» с учетом нового числа корзин.

13. В каком случае может быть потерян элемент в HashMap?

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

14. Почему нельзя использовать byte[] в качестве ключа в HashMap?

Еще один вопрос от LeoCcoder. Как обычно, все оказалось довольно просто — хеш-код массива не зависит от хранимых в нем элементов, а присваивается при создании массива (метод вычисления хеш-кода массива не переопределен и вычисляется по стандартному Object.hashCode() на основании адреса массива). Так же у массивов не переопределен equals и выполняет сравнение указателей. Это приводит к тому, что обратиться к сохраненному с ключом-массивом элементу не получится при использовании другого массива такого же размера и с такими же элементами, доступ можно осуществить лишь в одном случае — при использовании той же самой ссылки на массив, что использовалась для сохранения элемента. За ответ на этот вопрос отдельная благодарность уходит пользователю @dark_dimius.

15. В чем отличия TreeSet и HashSet?

Начнем с того, что Set — это множество (так же называют «набором»). Set не допускает хранение двух одинаковых элементов. Формально говоря, термин «множество» и так обозначает совокупность различных элементов, очень важно, что именно различных элементов, так как это главное свойство Set. С учетом такого определения, пояснение про хранение одинаковых элементом не требуется, но в обиходе, понятие «множество» потеряло свой строгий смысл касательно уникальности элементов, входящих в него, поэтому все же уточняйте отдельно данное свойство множества.

TreeSet обеспечивает упорядоченно хранение элементов в виде красно-черного дерева. Сложность выполнения основных операций в TreeSet lg N. HashSet использует для хранения элементов такой же подход, что и HashMap, за тем отличием, что в HashSet в качестве ключа выступает сам элемент, кроме того HashSet (как и HashMap) не поддерживает упорядоченное хранение элементов и обеспечивает временную сложность выполнения операций аналогично HashMap.

16. Устройство TreeSet?

Этот вопрос задают вместо вопроса 14 и здесь достаточно краткого ответа, что TreeSet основан на красно-черном дереве. Как правило этого хватает и собеседник сразу переходит к следующему вопросу, у меня ни разу не спрашивали механизм балансировки дерева или другие подробности его реализации.

Для экспресс углубления знаний по красно-черному дереву рекомендую вот эту статью.

17. Что будет, если добавлять элементы в TreeSet по возрастанию?

Обычно данный вопрос собеседник предваряет фразой, что в основе TreeSet лежит бинарное дерево и если добавлять элементы по возрастанию, то как они будут распределены по дереву.

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

Заключение

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

P.S. Немного меркантильного интереса: поиски нового места работы продолжаются и если кто-то из хабраюзеров в процессе поиска Java разработчика в компанию с современным подходом к разработке и интересными задачами или просто может порекомендовать присмотреться к какой-либо подходящей вакансии — я буду благодарен, прошу в личку.

Java Games

https://libgdx.badlogicgames.com/download.html

 

 

Ссылка на youtube-трансляцию:
https://www.youtube.com/watch?v=SqdKS_h6Ji0
По материалам
Архив с проектом прикрепил.(на этой странице есть кнопка материалы)
Если будете открывать из IDEA:
Import Project->build.gradle->убираете галочку(create separate module…)->OK
после того как один раз импортировали, следующие разы открываете через:
Open project->StarCommX5.ipr
Используемые инструменты
Среда разработки:
https://www.jetbrains.com/idea/download/#section=windows
Инструменты разработчика:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
LibGDX:
http://libgdx.badlogicgames.com/download.html
Для работы с Android нужен Android SDK(или если хотите разрабатывать приложение под Android, то может лучше поставить Android Studio)
Литература для начинающих(постарался расположить сверху-вних от простого к сложному):
● К. Сьерра, Б. Бейтс Изучаем Java // Пер. с англ. – М.: Эксмо, 2012. – 720 с.
● Г. Шилдт Java 8: Руководство для начинающих. // 6-е изд.: Пер. с англ. – М.: Вильямс, 2015. – 720 с
● Кей С. Хорстманн, Гари Корнелл Java. Библиотека профессионала. Том 1. Основы // Пер. с англ. – М.: Вильямс, 2014. – 864 с. (тоже считаю хорошая книга для начинающих)
● Брюс Эккель Философия Java // 4-е изд.: Пер. с англ. – СПб.: Питер, 2016. – 1168 с.
ДЗ на интенсивах нет
Архив с проектами прикрепил (лежит в пункте Материалы, на странице справа вверху)

Ссылки на вебинары с GeekWeek 2017:
https://geekbrains.ru/events/707
https://geekbrains.ru/events/706

Java onClick

How exactly does the android:onClick XML attribute differ from setOnClickListener?

 

XML  

<?xml version="1.0" encoding="utf-8"?>
<!-- layout elements -->
<Button android:id="@+id/mybutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click me!"
    android:onClick="myFancyMethod" />
<!-- even more layout elements -->

 

Button btn = (Button) findViewById(R.id.mybutton);

btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        myFancyMethod(v);
    }
});

// some more code

public void myFancyMethod(View v) {
    // does something very interesting
}

 

 

Java synchronized

public class Main {



class Tq {

     private int c = 0;

     public  synchronized void increment() {
         c++;
     }

     public synchronized  void decrement() {
         c--;
     }

     public  synchronized int value() {
         return c;
     }

 }


    public static void main(String[] args) {
        Tq c  = new Main().new Tq();
        c.value();
        Thread t1 =  new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1");
                for (int i = 0; i < 1000000 ; i++) {
                    c.increment();
                }
            }
        });


        Thread t2 =  new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000000 ; i++) {
                    c.decrement();
                }
                System.out.println("thread2");
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch ( Exception e ) {
            System.out.println("no");
        }
        System.out.println( c.value() );
    }



Generic Types

Generic Types

generic type is a generic class or interface that is parameterized over types. The following Box class will be modified to demonstrate the concept.

A Simple Box Class

Begin by examining a non-generic Box class that operates on objects of any type. It needs only to provide two methods: set, which adds an object to the box, and get, which retrieves it:

public class Box {
    private Object object;

    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
}

Since its methods accept or return an Object, you are free to pass in whatever you want, provided that it is not one of the primitive types. There is no way to verify, at compile time, how the class is used. One part of the code may place an Integer in the box and expect to get Integers out of it, while another part of the code may mistakenly pass in a String, resulting in a runtime error.

A Generic Version of the Box Class

generic class is defined with the following format:

class name<T1, T2, ..., Tn> { /* ... */ }

The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variablesT1T2, …, and Tn.

To update the Box class to use generics, you create a generic type declaration by changing the code “public class Box” to “public class Box<T>“. This introduces the type variable, T, that can be used anywhere inside the class.

With this change, the Box class becomes:

/**
 * Generic version of the Box class.
 * @param <T> the type of the value being boxed
 */
public class Box<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

As you can see, all occurrences of Object are replaced by T. A type variable can be any non-primitive type you specify: any class type, any interface type, any array type, or even another type variable.

This same technique can be applied to create generic interfaces.

Type Parameter Naming Conventions

By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the variable naming conventions that you already know about, and with good reason: Without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name.

The most commonly used type parameter names are:

  • E – Element (used extensively by the Java Collections Framework)
  • K – Key
  • N – Number
  • T – Type
  • V – Value
  • S,U,V etc. – 2nd, 3rd, 4th types

You’ll see these names used throughout the Java SE API and the rest of this lesson.

Invoking and Instantiating a Generic Type

To reference the generic Box class from within your code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer:

Box<Integer> integerBox;

You can think of a generic type invocation as being similar to an ordinary method invocation, but instead of passing an argument to a method, you are passing a type argument — Integer in this case — to the Box class itself.


Type Parameter and Type Argument Terminology: Many developers use the terms “type parameter” and “type argument” interchangeably, but these terms are not the same. When coding, one provides type arguments in order to create a parameterized type. Therefore, the T in Foo<T> is a type parameter and the String in Foo<String> f is a type argument. This lesson observes this definition when using these terms.


Like any other variable declaration, this code does not actually create a new Box object. It simply declares that integerBox will hold a reference to a “Box of Integer“, which is how Box<Integer> is read.

An invocation of a generic type is generally known as a parameterized type.

To instantiate this class, use the new keyword, as usual, but place <Integer> between the class name and the parenthesis:

Box<Integer> integerBox = new Box<Integer>();

The Diamond

In Java SE 7 and later, you can replace the type arguments required to invoke the constructor of a generic class with an empty set of type arguments (<>) as long as the compiler can determine, or infer, the type arguments from the context. This pair of angle brackets, <>, is informally called the diamond. For example, you can create an instance of Box<Integer> with the following statement:

Box<Integer> integerBox = new Box<>();

For more information on diamond notation and type inference, see Type Inference.

Multiple Type Parameters

As mentioned previously, a generic class can have multiple type parameters. For example, the generic OrderedPair class, which implements the generic Pair interface:

public interface Pair<K, V> {
    public K getKey();
    public V getValue();
}

public class OrderedPair<K, V> implements Pair<K, V> {

    private K key;
    private V value;

    public OrderedPair(K key, V value) {
	this.key = key;
	this.value = value;
    }

    public K getKey()	{ return key; }
    public V getValue() { return value; }
}

The following statements create two instantiations of the OrderedPair class:

Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
Pair<String, String>  p2 = new OrderedPair<String, String>("hello", "world");

The code, new OrderedPair<String, Integer>, instantiates K as a String and V as an Integer. Therefore, the parameter types of OrderedPair‘s constructor are String and Integer, respectively. Due toautoboxing, it is valid to pass a String and an int to the class.

As mentioned in The Diamond, because a Java compiler can infer the K and V types from the declaration OrderedPair<String, Integer>, these statements can be shortened using diamond notation:

OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);
OrderedPair<String, String>  p2 = new OrderedPair<>("hello", "world");

To create a generic interface, follow the same conventions as for creating a generic class.

Parameterized Types

You can also substitute a type parameter (i.e., K or V) with a parameterized type (i.e., List<String>). For example, using the OrderedPair<K, V> example:

OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));

How to create and throw a custom exception in Java

Java exceptions FAQ: How do I create a custom exception in Java?

Here’s a quick example of how to create and throw a custom exception class in Java. In this tutorial I’ll demonstrate how to (1) create a custom exception class in Java; (2) throw our custom Java exception; (3) catch our custom exception; and (4) look at the output from our custom exception when we print a stack trace.

A Java custom exception class

To get started, here’s our simple Java custom exception class. As you can see, to create a custom exception class, all you have to do is extend the Java Exception class, and create a simple constructor:

/**
 * My custom exception class.
 */
class AlsCustomException extends Exception
{
  public AlsCustomException(String message)
  {
    super(message);
  }
}

As you’ll see later there are more Exception class constructors you can override, but this is a good start for our example.

A method to throw a custom Java exception

To demonstrate how to throw our exception, here’s a small example class with a method named getBar that will throw our custom exception (AlsCustomException) if the method is given the value of zero as a parameter (sorry, not much imagination there, just trying to keep it simple):

/**
 * Our test class to demonstrate our custom exception.
 */
class Foo
{
  public String getBar(int i)
  throws AlsCustomException
  {
    if (i == 0)
    {
      // throw our custom exception
      throw new AlsCustomException("Anything but zero ...");
    }
    else
    {
      return "Thanks";
    }
  }
}

As you can see, all you need to do to throw your custom exception is (1) create a new instance of the exception (new AlsCustomException(“Anything but zero …”)), and then (2) throw that exception with the throw keyword.

A driver class to test (throw) the custom Java exception

With those two pieces in place, we’ll create a “driver” class with a mainmethod to test our custom Java exception. In our main method, we’ll create a new instance of our Foo class, then call the getBar method with the value of zero, which makes that method throw our custom Java exception:

/**
 * A class to test (throw) the custom exception we've created.
 * @author alvin alexander, devdaily.com
 *
 */
public class JavaCustomExceptionExample
{
  public static void main(String[] args)
  {
    // create a new foo
    Foo foo = new Foo();
    
    try
    {
      // intentionally throw our custom exception by
      // calling getBar with a zero
      String bar = foo.getBar(0);
    }
    catch (AlsCustomException e)
    {
      // print the stack trace
      e.printStackTrace();
    }
  }
}

Output from a driver class

With all those pieces in place, when we compile and run our Java source code, we get the following output when we print our stack trace:

AlsCustomException: Anything but zero ...
	at Foo.getBar(JavaCustomExceptionExample.java:37)
	at JavaCustomExceptionExample.main(JavaCustomExceptionExample.java:18)

As you can see, our custom exception output looks a lot like the output from any other Java exception that you’ve seen. The name of our exception is shown on the first line of the stack trace, followed by our error message.

I hope this is all pretty straightforward. As a friend of mine used to say, “this isn’t too hard … once you know how to do it.” 🙂

Java Exception class constructors

For more information on the topic of Java exceptions, check out the Java Exception class javadoc. As you’ll see in that javadoc, the Exception class has the following constructors. We only overloaded one of these constructors, but in your own custom exception class you may want to override several of them:

  1. Exception()
  2. Exception(String message)
  3. Exception(String message, Throwable cause)
  4. Exception(Throwable cause)

 

Download the custom exception source code

If you’re interested in running your own Java custom exception tests, feel free to download our Java custom exception example source code. All of the Java source code shown above is included in this one file.

 

 

 

 

My Code

 

public class Controller {
    public void init() {

        String arr[][] = {
                {"q","w","e","r"},
                {"q","w","e","r"},
                {"q","w","e","r"},
                {"q","w","e","r"}
        };
 
                try {
                    this.taskOne(arr);
                } catch (MyArraySizeException e){
                    System.out.println("Ошибка размерности " +e);
                }
    } 
    public void taskOne(String array[][]) throws  MyArraySizeException  {
         if (true) throw new MyArraySizeException ("Invalid array size");
    }
}




class MyArraySizeException extends Exception
{
    public MyArraySizeException(String message)
    {
        super(message);
    }
}

 

 

==========

php

class customException extends Exception {
public function errorMessage2() {
//error message
$errorMsg = ‘Error ))) ‘ ;
return $errorMsg;
}
}

$email = “someone@example…com”;

try {

throw new customException($email);

} catch (customException $e) {
//display custom message
echo $e->errorMessage2();
}
 

 

 

 

 

 

 

 

 

 

 

 


package com.batiaev.java2.lesson2;

public class Main {
    public static void main(String[] args) {

        String[][] arrays = new String[][]{
                {"1", "1", "1", "1"},
                {"1", "1", "1", "1"},
                {"1", "1", "1", "1"},
                {"1", "1", "1", "1"}
        };

        try {
            int sum = calculateSum(arrays);
            System.out.println("Array sum = " + sum);
        } catch (MyArraySizeException e) {
            System.out.println("Size problem: " + e.getMessage());
        } catch (MyArrayDataException e) {
            System.out.println("Value problem: " + e.getMessage());
        }
    }


    private static int calculateSum(String[][] data)
            throws MyArraySizeException, MyArrayDataException {

        int sum = 0;
        if (data.length != 4) throw new MyArraySizeException("Invalid array size", data.length);

        for (int i = 0; i < data.length; i++) {
            String[] val = data[i];
            for (int j = 0; j < val.length; j++) {
                if (val.length != 4)
                    throw new MyArraySizeException("Invalid inner array size", data.length);

                try {
                    sum += Integer.parseInt(val[j]);
                } catch (NumberFormatException e) {
                    throw new MyArrayDataException("Invalid element value", val[j], i, j);
                }
            }

        }
        return sum;
    }
}