, , 1 - - PowerPoint PPT Presentation

1
SMART_READER_LITE
LIVE PREVIEW

, , 1 - - PowerPoint PPT Presentation

, , 1 ( , , )


slide-1
SLIDE 1

Пакеты, исключения, дженерики

Валеев Тагир

1

slide-2
SLIDE 2

Имя класса

(интерфейса, перечисления, аннотации)

java.util.PrimitiveIterator.OfInt

Имя пакета Package name Имя класса верхнего уровня Top level class name Простое имя класса Simple name Полноквалифицированное имя класса Fully-qualified class name (FQN)

java/util/PrimitiveIterator$OfInt

Имя класса в виртуальной машине JVM class name

2

slide-3
SLIDE 3

Пакет x.y.z

✓ Располагается в каталоге x/y/z относительно корня элемента classpath ✓ Содержит заголовок “package x.y.z;” ✓ На классы из текущего пакета и из пакета java.lang можно ссылаться по простому имени. ✓ Для использования класса из другого пакета пишем его полное имя “x.y.z.ClassName” ✓ Если полное имя писать неохота, пишем в начале файла “import x.y.z.ClassName;” ✓ Для использования любых классов из пакета по простому имени, пишем “import x.y.z.*;” ✓ По умолчанию классы, поля, методы доступны из текущего пакета ✓ Пакеты “x.y.a”, “x.y.b”, “x.y” в отношениях не состоят.

3

slide-4
SLIDE 4

4

slide-5
SLIDE 5

Имена

✓ Пакет: полностью маленькие буквы, обратное доменное имя, принадлежащее автору или компании. ✓ Нельзя использовать пакеты java. и javax. (они используются стандартной библиотекой и защищены лиценцией). ✓ Класс: каждое слово с большой буквы. ✓ Метод: camelCase (первое слово с маленькой буквы), раньше рекомендовали начинать с глаголов. ✓ Поле, переменная: camelCase (существительное)

5

slide-6
SLIDE 6

Модификаторы доступа

Модификатор Класс Пакет Подкласс Все желающие public Да Да Да Да protected Да Да Да Нет (package-private) Да Да Нет Нет private Да Нет Нет Нет

6

slide-7
SLIDE 7

Protected

// a/AbstractGreeter.java package a; public abstract class AbstractGreeter { private final String recipient; protected AbstractGreeter(String recipient) { this.recipient = recipient; } protected void hello() { System.out.println("Hello "+ recipient +"!"); } }

7

slide-8
SLIDE 8

Protected

// b/Foo.java package b; import a.AbstractGreeter; public class WorldGreeter extends AbstractGreeter { public WorldGreeter() { super("World"); } void test(AbstractGreeter other) { this.hello(); super.hello();

  • ther.hello();

} }

8

slide-9
SLIDE 9

Abstract и final

✓ abstract класс – недоопределённый класс, который надо доопределить через наследование (экземпляр класса создать нельзя). ✓ abstract метод – метод, который надо определить в неабстрактном наследнике (методы интерфейсов abstract по умолчанию). ✓ final класс – класс, который нельзя унаследовать. ✓ final метод – метод, который нельзя переопределить.

9

slide-10
SLIDE 10

Статический импорт

import static java.util.Arrays.*; public class Test { public static void main(String[] args) { int[] data = {5,3,1,7,2,4,6}; sort(data); System.out.println(toString(data)); } }

10

slide-11
SLIDE 11

Статический импорт

import static java.util.Arrays.*; public class Test { public static void main(String[] args) { int[] data = {5,3,1,7,2,4,6}; sort(data); System.out.println(toString(data)); } }

11

slide-12
SLIDE 12

Исключения

✓ Выбрасываются явно оператором throw ✓ Выбрасываются вызванным методом или конструктором (непроверяемые или явно объявленные) ✓ Выбрасываются виртуальной машиной (только непроверяемые)

12

slide-13
SLIDE 13

Исключения

13

public class Test { static class MyException extends Exception { } static void test() throws MyException { throw new MyException(); } public static void main(String[] args) { test(); } }

slide-14
SLIDE 14

Исключения

14

public class Test { static class MyException extends Exception { } static void test() throws MyException { throw new MyException(); } public static void main(String[] args) throws MyException { test(); } }

slide-15
SLIDE 15

Миллион исключений

Throwable Exception Error

RuntimeException AssertionError ThreadDeath VirtualMachineError LinkageError

NoClassDefFoundError NoSuchFieldError NoSuchMethodError AbstractMethodError InstantiationError ClassFormatError ExceptionInInitializerError VerifyError StackOverflowError OutOfMemoryError InternalError IOException SQLException IllegalAccessException NoSuchFieldException NoSuchMethodException ClassNotFoundException InvocationTargetException TimeoutException ExecutionException NullPointerException ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException IllegalArgumentException IllegalStateException UnsupportedOperationException IndexOutOfBoundsException NoSuchElementException ConcurrentModificationException UncheckedIOException 15

slide-16
SLIDE 16

Конструирование исключений

Throwable, Exception, RuntimeException ✓ Throwable(); ✓ Throwable(message); ✓ Throwable(cause); ✓ Throwable(message, cause); ✓ protected Throwable(message, cause, suppression, stackTrace);

16

slide-17
SLIDE 17

Что есть у исключения?

✓Сообщение (getMessage()) ✓Стек (getStackTrace()) ✓Причина (getCause()) ✓Подавленные исключения (addSuppressed()/getSuppressed())

17

slide-18
SLIDE 18

Обработка исключений

18

public static void main(String[] args) { try { test(); } catch (MyException ex) { ex.printStackTrace(); } } Test$MyException at Test.test(Test.java:7) at Test.main(Test.java:12)

slide-19
SLIDE 19

Обработка исключений

✓ Логирование, вывод пользователю: редко, в специальных точках программы. ✓ Восстановление после исключения (например, вторая попытка подключения после обрыва связи). ✓ Исключение для управления потоком (ненормальная ситуация). ✓ Перебрасывание, завернув в исключение другого типа. Всегда сохраняйте исходное исключение в виде причины.

19

slide-20
SLIDE 20

Логирование

✓ Фреймворки: Log4j, Logback, Slf4j, Java Logging API (java.util.logging) ✓ Уровни (насколько всё плохо): ERROR/WARN/INFO/DEBUG ✓ Форматтеры: как логировать? (представление сообщений) ✓ Аппендеры: куда логировать?

20

slide-21
SLIDE 21

Логирование: enterprise style

21

public class PoolComposerPrincipalEventIdentifier { private static final Logger LOG = Logger.getLogger( PoolComposerPrincipalEventIdentifier.class.getName()); public void identifyPrincipalEvent() { try { doIdentifyPrincipalEventUsingPoolComposer(); } catch(Exception ex) { LOG.log(Level.SEVERE, "Error while identifying principal event", ex); } } }

https://projects.haykranen.nl/java/

slide-22
SLIDE 22

Перебрасывание исключений

22

static class MyException extends Exception { public MyException(String message) { super(message); } } void readFile() throws MyException { try { byte[] bytes = Files.readAllBytes(Paths.get("/etc/passwd")); System.out.println(Arrays.toString(bytes)); } catch (IOException e) { throw new MyException("Unable to read file"); } } Test$MyException: Unable to read file at Test.readFile(Test.java:16) at Test.main(Test.java:22)

slide-23
SLIDE 23

Перебрасывание исключений

23

static class MyException extends Exception { public MyException(String message) { super(message); } public MyException(String message, Throwable cause) { super(message, cause); } } void readFile() throws MyException { try { byte[] bytes = Files.readAllBytes(Paths.get("/etc/passwd")); System.out.println(Arrays.toString(bytes)); } catch (IOException e) { throw new MyException("Unable to read file", e); } }

slide-24
SLIDE 24

Перебрасывание исключений

24

Test$MyException: Unable to read file at Test.readFile(Test.java:16) at Test.main(Test.java:22) Caused by: java.nio.file.NoSuchFileException: \etc\passwd at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:7 at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102 at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.j at java.nio.file.Files.newByteChannel(Files.java:361) at java.nio.file.Files.newByteChannel(Files.java:407) at java.nio.file.Files.readAllBytes(Files.java:3152) at Test.readFile(Test.java:13) ... 1 more

slide-25
SLIDE 25

25

https://youtu.be/_0c9Fd9FacU

slide-26
SLIDE 26

А я обойдусь простыми случаями!

26

public static <T, K, U, M extends Map<K, U>> Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapFactory) {…}

slide-27
SLIDE 27

Параметризация типов

✓ Класс или интерфейс может быть объявлен обобщённым (generic, дженерик):

✓ class List<T> ✓ class Map<K, V> ✓ class NumberList<T extends Number> ✓ class X<T extends Y & Z>

✓ Здесь T, K, V – параметры типа, а сам класс задаёт параметризованный тип. ✓ Параметр типа может использоваться внутри нестатических членов класса:

✓ Тип поля, параметра, переменной ✓ Возвращаемый тип метода ✓ Подставляться параметром другого типа

✓ Для использования параметризованного типа необходимо подставить все параметры (с помощью явных непримитивных типов, других параметров типов либо маски)

27

slide-28
SLIDE 28

28

/** A box which is either empty or contains a non-null value */ static class Option<T> { T value; /** Passing null means absent value */ public Option(T value) { this.value = value; } /** Never returns null */ public T get() { if(value == null) throw new NoSuchElementException(); return value; } public T orElse(T other) { return value == null ? other : value; } public boolean isPresent() { return value != null; } }

slide-29
SLIDE 29

29

/** A mutable box which is either empty or contains a non-null value */ static class Shmoption<T> { T value; /** Passing null means absent value */ public Shmoption(T value) { this.value = value; } /** Never returns null */ public T get() { if(value == null) throw new NoSuchElementException(); return value; } public void set(T newValue) { value = newValue; } public T orElse(T other) { return value == null ? other : value; } public boolean isPresent() { return value != null; } }

slide-30
SLIDE 30

30

Shmoption<String> present = new Shmoption<String>("yes"); Shmoption<String> absent = new Shmoption<String>(null); System.out.println(present.isPresent()); System.out.println(present.get()); System.out.println(absent.isPresent()); System.out.println(absent.orElse("no"));

slide-31
SLIDE 31

Оператор ромб (diamond)

31

Shmoption<String> present = new Shmoption<String>("yes"); Shmoption<String> absent = new Shmoption<String>(null); System.out.println(present.isPresent()); System.out.println(present.get()); System.out.println(absent.isPresent()); System.out.println(absent.orElse("no"));

slide-32
SLIDE 32

Маскировочный символ (wildcard)

(“?” = “? extends Object”)

32

Shmoption<?> present = new Shmoption<>("yes"); System.out.println(present.isPresent()); System.out.println(present.get()); Use-site variance (вариативность в точке использования)

slide-33
SLIDE 33

Маскировочный символ

(“?” = “? extends Object”)

33

Shmoption<?> present = new Shmoption<>("yes"); System.out.println(present.isPresent()); Object value = present.get(); System.out.println(value); present.set(???);

slide-34
SLIDE 34

Маскировочный символ

(“?” = “? extends Object”)

34

Shmoption<?> present = new Shmoption<>("yes"); System.out.println(present.isPresent()); Object value = present.get(); System.out.println(value); present.set(???);

slide-35
SLIDE 35

Маскировочный символ

35

Shmoption<?> present = new Shmoption<>("yes"); System.out.println(present.isPresent()); Object value = present.get(); System.out.println(value); present.set(null);

slide-36
SLIDE 36

Маскировочный символ

36

Shmoption<Object> present = new Shmoption<>("yes"); System.out.println(present.isPresent()); Object value = present.get(); System.out.println(value); present.set(123);

slide-37
SLIDE 37

Маскировочный символ

37

Shmoption<? extends Number> number = new Shmoption<>(123); Number n = number.get(); number.set(124);

slide-38
SLIDE 38

Унаследуем

38

class NumberShmoption<N extends Number> extends Shmoption<N> { public NumberShmoption(N value) { super(value); } } class IntegerShmoption extends NumberShmoption<Integer> { public IntegerShmoption(Integer value) { super(value); } }

slide-39
SLIDE 39

39

NumberShmoption<?> number = new NumberShmoption<>(123); Number n = number.get(); number.set(124); IntegerShmoption integer = new IntegerShmoption(123); Integer i = integer.get(); integer.set(124); number = integer;

slide-40
SLIDE 40

Надтипы и подтипы

✓ У типов в Java определён частичный порядок “A > B” A – надтип B или B – подтип A (“A :> B”, если допустимо A = B) ✓ “A :> B” – рефлексивно, антисимметрично, транзитивно (рефлексивно-транзитивное замыкание над предикатом “A >1 B” – прямой надтип). ✓ “A > B” – антирефлексивно, антисимметрично, транзитивно. ✓ Надтип не должен предоставлять больше возможностей, чем предоставляет подтип.

40

slide-41
SLIDE 41

Надтипы и подтипы

S :> T ↛ X<S> :> X<T>

41

slide-42
SLIDE 42

Подтипы

42

IntegerShmoption NumberShmoption<?> Shmoption<?> Shmoption<Double> Shmoption<? extends Number> Shmoption<? super Number> NumberShmoption<Integer> Shmoption<Integer> Shmoption<Number> Shmoption<Object> NumberShmoption<Double>

slide-43
SLIDE 43

Чтение (producer – extends)

43

static double getDoubleValue(Shmoption<Number> shmopt) { return shmopt.get().doubleValue(); } getDoubleValue(new IntegerShmoption(123));

slide-44
SLIDE 44

Чтение (producer – extends)

44

static double getDoubleValue(Shmoption<? extends Number> shmopt) { return shmopt.get().doubleValue(); } getDoubleValue(new IntegerShmoption(123));

slide-45
SLIDE 45

Запись (consumer – super)

45

static void setInteger(Shmoption<Integer> shmopt) { shmopt.set(42); } NumberShmoption<Number> n = new NumberShmoption<>(123.45); setInteger(n);

slide-46
SLIDE 46

Запись (consumer – super)

46

static void setInteger(Shmoption<? super Integer> shmopt) { shmopt.set(42); } NumberShmoption<Number> n = new NumberShmoption<>(123.45); setInteger(n);

slide-47
SLIDE 47

PECS

Producer – extends (covariance) Consumer – super (contravariance)

47

Picture courtesy : Andrey Tyukin https://stackoverflow.com/a/19739576/4856258

slide-48
SLIDE 48

Covariant return type

48

interface Supplier { Object get(); } interface StringSupplier extends Supplier { @Override String get(); }

slide-49
SLIDE 49

Параметризованные методы и конструкторы

49

static <T> void setNotNull(Shmoption<? super T> shmoption, T value) { if (value == null) throw new IllegalArgumentException(); shmoption.set(value); } setNotNull(n, 123); ShmoptionUtils.<Number>setNotNull(n, 123);

slide-50
SLIDE 50

Стирание (erasure)

50

✓ Не все типы известны во время выполнения ✓ В частности, значения параметров типов «стёрты» ✓ Преобразование типов не всегда бывает безопасным (checked) ✓ Если оно небезопасно, вы получите unchecked cast warning ✓ При выполнении это может привести к проблемам (ClassCastException) в дальнейшем ✓ Программа считается безопасной с точки зрения системы типов, если типы выражений в рантайме соответствуют типам во время компиляции (ClassCastException происходит только при явном преобразовании типа). ✓ Если предупреждений нет, то программа безопасна *

* На самом деле нет: Java and Scala’s Type Systems are Unsound https://github.com/namin/unsound/blob/master/doc/unsound-oopsla16.pdf

slide-51
SLIDE 51

Стирание (erasure)

51

Shmoption<Integer> integer = new Shmoption<>(10); Shmoption<String> string = ((Shmoption<String>) integer); // ошибка Shmoption<?> any = integer; Shmoption<String> string2 = (Shmoption<String>) any; // предупреждение String s = string2.get(); // ClassCastException NumberShmoption<Integer> number = (NumberShmoption<Integer>)integer; // нормально

slide-52
SLIDE 52

Raw-type (сырой тип)

52

Shmoption shmoption = new Shmoption(10); shmoption.set("foo"); Object o = shmoption.get();

✓ Нужны для совместимости с Java 1.4.2 и старше ✓ Не используйте их ✓ Не нужно искать в них логику, просто не используйте их ✓ – Доктор, когда я вот так делаю, у меня вон там болит. – Так вы не делайте так!

slide-53
SLIDE 53

Дженерики и массивы

Дружат как кошка с собакой

53

Shmoption<?>[] array = new Shmoption<?>[10]; Shmoption<Integer>[] arrayInt = new Shmoption<Integer>[10];

slide-54
SLIDE 54

Дженерики и массивы

Дружат как кошка с собакой

54

Shmoption<?>[] array = new Shmoption<?>[10]; Shmoption<Integer>[] arrayInt = new Shmoption<Integer>[10]; Shmoption<Integer>[] arrayInt = new Shmoption[10]; // предупреждение Object[] obj = arrayInt;

  • bj[0] = new Shmoption<>("foo");

Shmoption<Integer> shmoption = arrayInt[0]; Integer x = shmoption.get(); System.out.println(x);