Skip to content
Etsu edited this page Sep 17, 2017 · 28 revisions
                                     ____.                    
                                    |    |____ ___  _______   
                                    |    \__  \\  \/ /\__  \  
                                /\__|    |/ __ \\   /  / __ \_
                                \________(____  /\_/  (____  /
                                              \/           \/ 

Java

Install Java

sudo add-apt-repository ppa:webupd8team/java
aptitude update
aptitude search oracle
aptitude install oracle-java8-installer oracle-java7-installer

Compilation

javac HelloWorld.java
javap -v HelloWorld.class 
java HelloWorld
java -classpath classes_dir HelloWorld

Компиляция со сторонними классами (библиотеками)

java -classpath lib.jar HelloWorld.java
java -classpath lib.jar:hw.jar HelloWorld

JAR

Упаковка

jar cfe hw.jar HelloWorld HelloWorld.class

Просмотреть содержимое архива без распаковки

jar tf hw.jar

Распаковка архива

jar xf hw.jar

Запуск

Запуск программы, если прописан главный класс

java -jar hw.jar

Else:

java -classpath hw.jar HelloWorld

Codestyle

Более подробно о рекомендуемом стиле кода можно почитать здесь:

Assembly:

Ant - build.xml

Gradle - build.gradle

Maven - pom.xml

Print type

System.out.println(variable.getClass().getName());

Классы-обёртки (wrapper classes)

int primitive = 0
// boxing
Integer reference = Integer.valueOf(primitive);
// unboxing
int backToPrimitive = reference.intValue();

Конвертация в строку и обратно

long fromString = Long parseLong("12345");
String fromLong = Long.toString(12345);
String concatenation = "area" + 51;

Simple way to print a Java array

String[] array = new String[] {"John", "Mary", "Bob"};
System.out.println(Arrays.toString(array));

Arrays

Varargs

static int maxArray(int[] numbers) { ... };
maxArray(new int[] {1, 2, 3});

static int maxVarargs(int... numbers) { ... };
maxVarargs(1, 2, 3);

Array equals

import java.util.Arrays;

int[] a = {1, 2, 3};
int[] b = {4, 5, 6};
boolean equals = Arrays.equals(a, b);
boolean equals = Arrays.deepEquals(a, b);

Print Array

int[] a = {1, 2, 3};
System.out.println(Arrays.toString(a));
System.out.println(Arrays.deepToString(a));

Strings

char[] charArray = {'a', 'b', 'c'};
String string = new String(charArray);
char[] charFromString = string.toCharArray();

String s = "stringIsImmutable";
int length = s.length();
char firstChar = s.charAt(0);

boolean endsWithTable = s.endsWith("table");
booalen containsIs = s.contains("Is");
String substr = s.substring(0, 6);

String afterReplace = s.replace("Imm", "M");
String allCapitals = s.toUpperCase();
boolean equal2 = s1.equalsIgnoreCase(s2);

If-Else

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

        int testscore = 76;
        char grade;

        if (testscore >= 90) {
            grade = 'A';
        } else if (testscore >= 80) {
            grade = 'B';
        } else if (testscore >= 70) {
            grade = 'C';
        } else if (testscore >= 60) {
            grade = 'D';
        } else {
            grade = 'F';
        }
        System.out.println("Grade = " + grade);
    }
}

Ternary operator

if (weatherIsGood) {
    System.out.println("Wheater is good");
} else {
    System.out.println("Wheater is bad");
}

// same effect, but much shorter
System.out.println("Wheater is "
        + (wheaterIsGood ? "good" : "bad"));

Switch

switch (digit) {
    case 0: 
        text = "zero";
        break;
        
    case 1:
        text = "one";
        break;
        
    // ...
    
    default:
        text = "???";
        
}

Circles

Do while

do {
    goShopping();
} while (haveTime() && haveMoney());

Foreach

for (String arg : args) {
    System.out.printls(arg);
}

Про страшные слова

final

final с примитивами - readonly (const)
final на объектах позволяет модифицировать их стейт, но не сам объект
final с методами означает что метод не может быть переопределён (override)

static

static поля и методы не привязываются к экземпляру, а привязываются к классу

Анонимные классы

OOP

Classes

// Друг за другом может быть объявлено несколько классов, 
//                                      но только один из них может быть public
// Его имя должно соответствовать имени файла

public final class Integer {
// Ключевое слово final означает что от класса нельзя наследоваться
}

Fields (variables of classes)

public final class Integer {
    // final - означает что значение полю можно присвоить только один раз
    // Мб также применён к методам и локальным переменным
    private final int value;

    // Явное присвоение значения полю можно сделать 
    //                                   прямо в объявлении поля или в конструкторе
    private final int zero_value = 0;  // 0, null, false в зависимости от типа поля
    
    public Integer(int value) {
        this.zero_value = zero_value;
    // Компилятор проверит, что к моменту выхода из конструктора  
    //                                    значение полю будет обязательно присвоено
    // Иначе - ошибка компиляции
    }

    
}

Constructors

// Констуктор - метод, вызываемый при создании класса
// Например, когда кто-то в программе применяет оператор new (new Integer(33))

// Задача конструктора - инициализировать состояние объекта 
//                                           и подготовить его к использованию
package java.lang;

// Когда в классе не объявлен ни один конструктор, 
//               то неявно создаётся конструктор по умолчанию (без параметров)
// Т.е. даже когда у класса нет конструкторов, 
//                        его экземпляр можно создать при помощи оператора new

public final class Integer {
    
    private final int value;
    
    // Объявление конструктора состоит из модификатора доступа и имени класса
    // Конструктор может принимать параметры
    public Integer(int value){
        // Если параметр конструктора принимает такой же параметр как имя класса, 
        //                то для доступа к полю класса используется префикс this
        // this - это ссылка на текущий экземпляр, 
        //        в контексте которого выполняется текущий конструктор или метод
        // Обычно писать this не нужно, но в случае конфликта имён 
        //                                поля и локальных параметров необходимо
        this.value = value;
    }
    
    // ...
}
package java.math;

public final class Math {

    // Если нужно запретить создание экземпляров класса, 
    //                                   то нужно сделать конструктор приватным
    /**
     * Don't let anyone instantiate this class.
     */
    private Math() {}

    // ...
}
package java.math;

public class BigInteger {
    
    // В классе может быть несколько 
    //         перегруженных версий конструкторов с разными наборами параметров
    public BigInteger(String val){
        // Из одного конструктора можно вызывать другой
        this.(val, 10);  // defaul value
    }
    
    public BigInteger(String val, int radix){
        // ...
    }

}

Methods

package java.lang;

public final class Integer {

    private final int value;

    // Объявление метода состоит из модификатора доступа, 
    //                          типа возвращаемого значения, имени и параметров

    // Метод может иметь модификатор final,
    //   тогда данный метод не может быть переопределён в классах наследниках
    // Если класс уже объявлен как final, то расставлять на методах избыточно
    public int intValue() {
        // Метод исполняется в контексте текущего экземпляра класса, 
        //              поэтому он может обращаться к полям объекта
        return value;
    }

    // ...
}
// Поля и методы могут быть статическими (с модификатором static)
// В каждой программе присутствует хотя бы он статический метод - метод main()

// Статические поля и методы существуют независимо от экземпляров класса
// и могут вызываться просто по имени класса (например, Integer.rotateRight(5, 7))

// Статический метод исполняется в контексте класса, а не конкретного экземпляра,
// поэтому он не имеет доступа к this и нестатическим полям и методам

package java.lang;

public final class Integer {

    // В комбинации с final, static используется для объявления констант
    // Имена констант принято записывать в верхнем регистре, 
    //                                    разделяя слова подчёркиваниями
    public static final int MIN_VALUE = 0x80000000;

    public static int rotateRight(int i, int distance) {
        return (i >>> distance) | (i << -distance);
    }

    // ...
}

Nested Classes

package java.util;

// ArrayList - коллекция, контейнер для однотипных элементов
//              в отличие от массива может динамически изменять свой размер
public class ArrayList<E> {

    Object[] elementData;

    // Когда необходимо обойти и обработать все элементы коллекции, 
    //                                        используется итератор 
    //     (объект, по очереди возвращающий все элементы коллекции)
    // Итератор должен помнить текущую коллекцию, 
    //                     которую он обходит (чтобы получать её элементы),
    //                                       а также текущую позицию обхода
    public Iterator<E> iterator() {
        return new Itr();
    }

    // Каждый экземпляр итератора будет иметь собственное состояние, 
    //                                       хранящееся в его полях, 
    //          а также неявную ссылку на экземпляр внешнего класса
    // То есть из кода итератора можно будет напрямую обращаться 
    //     к полям экземпляра ArrayList, в том числе к приватным
    private class Itr implements Iterator<E> {
        int cursor;
        // ...
    }

    // ...
}
package java.util;

public class Collections {

    public static final List EMPTY_LIST = new EmptyList<>();

    public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
    }

    // Если вложенный класс снабжён модификатором static,
    //                           то неявная связь с внешним классом теряется
    // Экземпляры вложенного класса будут независимы

    // При этом размещение одного класса внутри другого мотивируется:
    // - либо желанием скрыть вложенный класс, сделав его приватным
    // - либо тесной логической связью внешнего и вложенных классов, 
    //               требующий доступа к приватным полям друг друга
    private static class EmptyList<E> {
        //...
    }
}

Enums

package java.time;

// Перечисления - это полноценный ссылочный тип
// Его можно воспринимать как класс с фиксированным количеством экземпляров
// Перечисленные в enum значения эквиваленты public static final полям класса
public enum DayOfWeek {
    MONDAY,  // <- public static final
    TUESDAY,
    WEDNESDAY,
    THURSDAY(args),
    FRIDAY,
    SATURDAY,
    SUNDAY;
    
    // fields, methods
    // В перечислениях можно объявлять fields, methods как в обычном классе

    // Можно также объявить констуктор, в том числе принимающий параметры
    // Тогда в объявлении нужно описать эти параметры
}

// В любом перечислении доступны методы name(), ordinal(),
//                                      а также статический метод values()

// name - возвращает строку (имя элемента перечисления как в исходном коде)
// ordinal - порядковый номер элемента, начиная с 0 как в исходном коде
// values - массив возможных перечислений в том же порядке
for (DayOfWeek day : DayOfWeek.values()) {
    System.out.println(day.ordinal() + " " + day.name());
}

Inheritance

package java.lang;

// Наследоваться можно только от одного класса
// Унаследованный класс автоматически получает все поля и методы класса
// Пользоваться ими может как он сам, 
//        так и другие классы программы (с учётом модификаторов доступа)
// Иерархия наследования может быть произвольной глубины

// В класс наследника можно добавлять поля и методы, 
//                                    тем самым расширяя родительский класс
// Методы также можно переопределять 
//  (завести в классе наследника метод с такими же названием и параметрами, 
//                                                    как в базовом классе)
// Тип возвращаемого значения должен быть аналогичным 
//      или подтипом возвращаемого значения метода базового класса, а также 
//                модификатор доступа должен быть тем же или более открытым

public final class BigDecimal extends Number {

    public int intValue() {
        //...
    }

    // no shortValue() method,
    // it's inherited from Number

    // bd.intValue() bd.shortValue()
}

Inheritance & Override

package java.lang;

public final class StringBuilder
    extends AbstractStringBuilder {
    
    // Переопределение метода append, принимающего строку
    // Возвращаемый StringBuilder - подкласс AbstractStringBuilder
    // Иначе, если бы тип возвращаемого значения не совпал, 
    //                                   была бы ошибка компиляции
    // Сигнатуры методов не должны расходиться
    @Override
    public StringBuilder append(String str){
        // ...
    }
    
    // base method in AbstractStringBuilder:
    // AbstractStringBuilder append(String str)
}

Overloading vs. Overriding

Static vs. Dynamic binding (Статическое и динамическое присваивание / Статический и динамический полиморфизм)

Static - private static, final statiс
Статическое присваивание работает с типом

Dynamic - JVM узнает какой метод вызвать только во время Runtime
Это уже overriding (переопределение метода)
Динамическое работает с объектом
Перегрузка (Overloading)
Определение методов с одной и той же сигнатурой, но разным количеством параметров
Происходит во время статического присваивания
Методы были все в одном классе и с определённой сигнатурой
JVM во время компиляции знает какой из этих методов вызвать

Переопределение (Overriding)
Динамическое присваивание

Super

package java.lang;

// Создание экземпляра класса наследника всегда включает в себя 
//              инициализацию базового класса т.е. вызов его конструктора
// Когда у базового класса есть конструктор без параметров, то компилятор
//                              автоматически поставит его вызов в начало 
//                                    тела конструктора класса наследника
public final class StringBuilder
    extends AbstractStringBuilder {
    
    // Вызов конструктора с параметрами необходимо указывать явно
    public StringBuilder() {
        // Вызов конструктора суперкласса должен идти перед другим кодом,
        //                                     размещённым в конструкторе
        super(16);
    }
    
    @Override
    public StringBuilder append(String str) {
        // Вызов реализации из метода базового класса, 
        //                           несмотря на наличие переопределённой 
        //                                 версии метода в текущем классе
        super.append(str);
        // Использование ключевого слова super разрешено 
        //                                только в теле класса наследника
        // Поэтому из класса наследника всегда будет вызываться
        //                          только переопределённая версия метода
        return this;
    }
    
    // ...
}

java.lang.Object

package java.lang;

public final class String /*extends Object*/ {
    // ...
}

Extends Object

  • equals() - сравнение по содержимому (массивы все ещё сравниваются по ссылке)
  • toString() - обычно java.lang.Object@35fe45
  • hashCode() - для хранения объектов в хэш-таблицах вычисляет хэш-код объекта
Если два объекта равны с точки зрения equals, 
                                     то у них должны быть одинаковые хэш-коды
Поэтому либо переопределять и equals() и hashCode(), либо не переопределять вовсе
Модификатор native означает что реализация данного метода в нативном Сишном коде

Override equals()

package java.lang;

public final class String /*extends Object*/ {

    @Override
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
     
        // instanceof - проверяет, является ли объект, находящийся по ссылке
        //                                 экземпляром класса или подклассом
        // null instanceof -> false
        if (anObject instanceof String) {
            String other = (String)anObject;
            // ...
        }
        return false;
    }
    // ...
}

Read from console

import java.util.Scanner;

class Main {
  public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    int a = s.nextInt();
    int b = s.nextInt();
    System.out.println(a + b);
  }
}

Modifiers

// модификаторы protected и private не применимы к классам верхнего уровня
public class ModifiersDemo {
    // доступ отовсюду
    public static void visibleEverywhere() {}

    // доступ только для классов наследников и классов текущего пакета
    protected static void inSubclasses() {}

    // (отсутствие модификатора) доступ только в пределах пакета
    static void inPackage() {}

    // доступ только в пределах класса
    private void inClass() {}
}

Abstract Class

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

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

Interface

// Интерфейсы могут иметь только константы и только объявления методов
// Все методы интерфейса публичны и абстрактны
// Интерфейс служит простым регламентом
// Поля в интерфейсе могут быть только public static final (константы)
// Ничего непубличного объявить в интерфейсе нельзя
// Могут быть статические публичные методы (с Java8)
package org.stepic.java.orders;

import java.time.LocalDate;

public interface OrderService {
    Order[] getOrdersByClient(long clientId);
    
    // Чтобы при добавлении нового интерфейса не отъезжал код,
    // завязанный на старый, добавлена реализация default-методов
    // Order[] getOrdersByClient(long clientId, LocalDate date);
    
    default Order[] getOrdersByClient(
            long clientId, LocalDate date) {
        Order[] allOrders = getOrdersByClient(clientId);
        return Orders.filterByDate(allOrders, date);
    }
}
// В Java можно объявлять классы, реализующие множество интерфейсов
// Реализуемые классом интерфейсы перечисляются после
//                  ключевого слова implements через запятую
// Класс может реализовывать интерфейсы 
//               вдобавление к наследованию от произвольного класса
public class OrderServiceImpl
       extends ServiceBase
       implements OrderService {

    public Order[] getOrdersByClient(long clientId) {
        // ...
    }
}
package java.lang;

// Последовательность символов
public interface CharSequence {

    int length();  // длина последовательности
    char charAt(int index);  // запрос символа по индексу
    CharSequence subSequence(int start, int end);  // взятие подпоследовательности

// Реализации CharSequence -  String и StringBuilder
}
package java.lang;

public interface Appendable {

    Appendable append(CharSequence csq);
    Appendable append(CharSequence csq, int start, int end);
    Appendable append(char c);
}
package java.lang;
// Абстрактное нечто, которое можно запустить :)

// У функциональных интерфейсов единственный абстрактный метод
// Если добавить аннотацию, то компилятор это проверит
@FunctionalInterface
public interface Runnable {
    void run();
}
package java.lang;
// Умеет сравнивать пары объектов и говорить, какое из них больше
// Если первый объект < второго, то возвращается отрицательное число
//                    ==                         0
//                    >                          положительное

@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
}
// Функциональные интерфейсы можно кратко описать в виде:
//   - лямбда-выражений
//   - ссылок на метод
package timer;

import java.math.BigDecimal;

public class Main {

    public static void main(String[] args) {
        Timer timer = new Timer();
        long time = timer.measureTime(new BigDecimalPower());
        System.out.println(time);
    }
    
    private static class BigDecimalPower implements Runnable {
    
        @Override
        public void run() { 
            new BigDecimal("1234567").pow(100000); 
        }
    }
}

// ===========================================================
package timer;

import java.math.BigDecimal;

public class Main {

    public static void main(String[] args) {
        Timer timer = new Timer();
        // Объявление класса внутри метода measureTime
        // Объявляется анонимный класс, реализующий интерфейс Runnable
        //                                   и создаётся его экземпляр
        long time = timer.measureTime(new Runnable() {
    
            @Override
            public void run() { 
                new BigDecimal("1234567").pow(100000); 
            }
        });
        System.out.println(time);
    }
}

// ===========================================================
package timer;

import java.math.BigDecimal;

public class Main {

    public static void main(String[] args) {
        Timer timer = new Timer();
        // Java8 - magic!
        // Лямбда-выражение
        // Начинается с круглых скобок, в которых указываются параметры
        // В данном случае метод run() не предполагает никаких параметров
        // Параметры указываются без типов, т.к. они известны компилятору
        //                                        из объявения интерфейса
        // После стрелочки идёт тело лямбда-выражения
        // В нашем случае одна строка, если нужно больше, 
        //                                       то нужны фигурные скобки 
        long time = timer.measureTime(() -> new BigDecimal("1234567").pow(100000)); 
        // Такое выражение порождает объект, реализующий интерфейс Runnable
        //                                   с указанным телом метода run()
        // Лямбдой можно заменить только реализацию функционального интерфейса
        System.out.println(time);
    }
}

// ===========================================================
package timer;

import java.math.BigDecimal;

public class Main {
// Получение экземпляра интерфейса при помощи ссылки на метод с подходящей сигнатурой
    public static void main(String[] args) {
        Timer timer = new Timer();
        // Ссылка на метод состоит из имени класса или переменной (Main),
        // двух двоеточий и имени метода (bigDecimalPower)
        long time = timer.measureTime(Main::bigDecimalPower);
        System.out.println(time);
    }
    
    // Значением выражения является объект, реализующий функциональный интерфейс 
    //                        и вызывающий код при вызове своего главного метода 
    private static void bigDecimalPower() {
        new BigDecimal("1234567").pow(100000);
    }
}

Exceptions

// Исключения - события, которые случаются во время работы программы и 
//                             прерывают стандартный ход её выполнения
// Программа переход в режим поиска обработчика внештатной ситуации
// Такой обработчик может вернуть программу в штатное выполнение
// Если обработчика не нашлось, то JVM завершит программу, но
//                           обеспечит подробные логи падения
// Stack Trace - вся цепочка вызовов от входа в программу до падения

Object nullRef = null;
// java.lang.NullPointerException (NPE)
// Обращение по нулевой ссылке (JVM)
nullRef.toString();

int[] array = {1, 2, 3};
// java.lang.ArrayIndexOutOfBoundsException
// Обращение к несуществующим элементам массива
array[10];

// StringIOOBE при обращении к несуществующему символу в строке

// java.io.FileNotFoundException
new FileInputStream("not_existing_file");
// Является подклассом более общего IOException
// Его экземпляры бросаются при ошибках ввода-вывода

// Когда JVM не хватает памяти на создание нового объекта,
//                           она бросает исключение типа OutOfMemoryError
// Его можно обработать, но лучше этого не делать, 
//    т.к. предпринять что-то разумное в данной ситуации проблематично :)
// Исключение в Java - это объект, экземпляр какого-то класса, который
// наследуется от java.lang.Throwable, который наследуется от Object
// Ключевое св-во экземпляров java.lang.Throwable - возможность быть брошенными

// Бросание - ключевое слово throw и объект типа Throwable
// Stack Trace определяется тем где был создан экземпляр исключения,
//                                  а не тем, где оно было выброшено
throw new IllegalStateException(
"Invalid user. " +
"Please replace user and continue.");
// Exception Classification:
//   Исключительные ситуации в JVM
     java.lang.Error

//   Исключительные ситуации в пользовательском коде
//       Проверяемые (checked)
         java.lang.Exception

//       Непроверяемые (unchecked)
         java.lang.RuntimeException


// Er -> Th
// Re -> Ex -> Th
java.lang.Error

java.lang.OutOfMemoryError
java.lang.NoClassDefFoundError
java.lang.VerifyError  // что-то не так с байт-кодом
// JVM плохо, но не настолько чтобы умереть
// Такие исключения не надо обрабатывать, помочь JVM уже ничем не получится
// Exception и RuntimeException - ошибки уровня программы
// Некорректные параметры, некорректные состояния, недопустимые действия
// Можно пытаться обрабатывать :)

// За Exception следит компилятор, 
//                       например, следующий код не скомпилится:
import java.io.IOException;
public class ExceptionDemo {
    public void someMethod() {
        // ...
        throw new IOException("Failed to read file");
        // ...
    }
}

// Для компиляции в этом же методе должен быть обработчик
//      данного исключения, либо на методе должно быть явно написано
//                            что из него может вылетать IOException 
//         (нужно вешать throws на все методы, вызывающие наш метод)
// Таким образом, компилятор обеспечивает, что в сигнатуре метода 
// видны все проверяемые исключения, которые могут из него вылетать
// Их может быть несколько (через запятую)
import java.io.IOException;
public class ExceptionDemo {
    public void someMethod() throws IOException {
        // ...
        throw new IOException("Failed to read file");
        // ...
    }
}
java.lang.RuntimeException
// Такие исключения могут вылететь в любой части программы

java.lang.NullPointerException
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArithmeticException  // деление на ноль

Собственное исключение

public class CalculatorException extends RuntimeException {

    public CalculatorException(String message) {
        super(message);
    }

    public CalculatorException(String message, Throwable cause) {
        super(message, cause);
    }
}
public class CalculatorImpl implements Calculator {

    @Override
    public double calculate(String expr) {
        // ...
        throw new CalculatorException("Unsupported operator found");
        // ...
    }
}

Try-Catch

for (;;) {
    System.out.print("Enter expression: ");
    String expr = readUserInput();
    if (expr == null || "exit".equalsIgnoreCase(expr)) {
        break;
    }
    try {
        double result = calculator.calculate(expr);
        System.out.println("Result: " + result);
    } catch (CalculatorException e) {
        System.out.print("Bad expression: " + e.getMessage());  // без стек-трейсов
        System.out.print("Please try again: ");
    }
}
// Для любых типов exception (как проверяемых, так и непроверяемых), кроме runtime
catch (Exception e)
// Поймает все exception, в том числе, виртуальной машины
catch (Throwable t)
try {
    // ...
} catch (FirstException e) {
    e.printStackTrace();
} catch (FirstException e) {
    e.printStackTrace();
}

// since Java 7 can be replaced with:
try {
    // ...
} catch (FirstException | SecondException e) {
    e.printStackTrace();
}
// В блоке finally обычно занимаются освобождением ресурсов (закрытием файлов, снятием блокировок)
// Finally не является обработчиком исключений
InputStream is = new FileInputStream("a.txt");
try {
    readFromInputStream(is);
} finally {
    is.close();
}
// Если в finally случилось исключение, то потеряется исключение из блока try, hotfix на это:
// Исключение из finally здесь явно отлавливается и игнорируется чтобы не перебивать исходную ошибку
InputStream is = new FileInputStream("a.txt");
try {
    readFromInputStream(is);
} finally {
    try {
        is.close();
    } catch (IOException e) {
        // ignore
    }
}
// Но в Java 7 добавили плюшку в виде трая с ресурсами:
try (InputStream is =
        new FileInputStream("a.txt")) {
    readFromInputStream(is);
}
// После ключевого слова try в круглых скобках выделяются ресурсы,
//                       с которыми будет работать этот блок (если несколько, то через ;)
// Гарантируется, что при выходе из блока все ресурсы будут освобождены
// Будет вызван close() для всех ресурсов даже если exception не будет (как finally),
// но exception из close() не перебьёт, а будет добавлен в качестве заглушенного (suppressed)
// Смахивает на этот код:
InputStream is = new FileInputStream("a.txt");
try {
    readFromInputStream(is);
} catch (Throwable t) {
    try {
        is.close();
    } catch (Throwable t2) {
        t.addSuppressed(t2);
    }
    throw t;
}
is.close();

// Ресурс - любой объект, реализующий java.lang.AutoCloseable
package java.lang;
public interface AutoCloseable {
    void close() throws Exception;
}
// Можно реализовывать этот интерфейс в своих классах и 
//                     тогда можно будет их использовать в блоке try с ресурсами

Оборачивание исключения

try {
    // code throwing MyException
} catch (NumberFormatException e) {
    throw new CalculatorException(e);
}
String string = object == null
        ? "null"
        : object.toString();

System.out.println(string);

Pass by reference or pass by value

Clone this wiki locally