oop java.generics

31
Новосибирск, 2004 (С) Всеволод Рылов, все права защищены 1 Основы программирования на языке Java Пакет java.lang, синтаксический «сахар», родовые компоненты (generics) Java

Upload: muqaddasm

Post on 27-Jul-2015

55 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 1

Основы программирования на языке Java

Пакет java.lang, синтаксический «сахар»,

родовые компоненты (generics) Java

Page 2: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 2

Пакет java.lang – поддержка языка и платформы

ErrorException

Comparable

Cloneable

Double

Character

Byte

Boolean

Compiler

Float Integer Long

Math

NumberNullPointerException

Object Package

ProcessRuntimeRuntimeException

Short

String StringBuffer

System

Runnable

ClassLoaderThread -target

Throwable Class

Void

Page 3: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 3

Классы поддержки основных механизмов

Базовый класс для загрузчиков классов в системе

ClassLoader

Интерфейс используемый классом потока для запуска параллельных действий

Runnable

Базовый класс потокаThread

Класс, объекты которого хранят информацию о пакетах во время исполнения

Package

Класс, объекты которого хранят служебную информацию о классах во время исполнения

Class<T>

Класс для взаимодействия со средой исполненияRuntime

Класс-утилита для взаимодействия с системойSystem

Маркерный интерфейс для классов, реализующих метод public Object clone()

Cloneable

Базовый класс для всех классов. Object

Page 4: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 4

Классы поддержки системы типов

Базовый класс для классов – оберток числовых типов

Number

Классы – обертки для числовых типовByte, Short, Integer, Long, Float, Double

Интерфейс, реализуемый классами для объектов которых определено отношение порядка

Comparable <T>

Объектная обертка для типа voidVoid

Объектная обертка для логического типаBoolean

Объектная обертка для символьного типаCharacter

Символьный буфер, используемый для оптимизации работы со строками

StringBuffer

Класс для работы со строками String

Page 5: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 5

Класс java.lang.System (основные методы)

Методы для манипуляции с загружаемыми native библиотеками (dll , ld.so )

load(), loadLibrary(), mapLibraryName()

Принудительный вызов сборщика мусораgc()

Прекращение работы виртуальной машины и завершение процесса

exit()

Взятие текущего времени в миллисекундах с момента 00 часов 1 января 1970 года

currentTimeMillis()

Набор методов для работы со стандартными свойствами (настройками) java машины

getProperties(), getProperty(), setProperties(), setProperty()

Метод для быстрого копирования содержимого массивов

arraycopy()

Статические переменные содержащие ссылки на стандартные потоки ввода, вывода и ошибок

err, in, out

Page 6: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 6

Класс java.lang.Runtime (основные методы)

Запуск сборщика мусора и финализатораgc(), runFinalization()

Установка и удаления перехватчиков, вызываемых при остановке виртуальной машины

addShutdownHook(), removeShutdownHook()

Загрузка динамических native библиотекloadLibrary(), load()

Методы для получения информации о доступной памяти

freeMemory()totalMemory()

Shutdown и остановка java машиныexit(int status), halt()

Семейство вызовов для запуска отдельного процесса (программы) в операционной системе

Process exec()

Статический метод для получения объекта Runtime

getRuntime()

Page 7: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 7

java.lang.Class (основные методы)

Загрузка ресурсов (файлов настроек, картинок и т.д.) расположенных на файловой системе или в архиве jar

getResource(), getResourceAsStream()

Получение информации о суперклассе, реализуемых интерфейсах и пакете

getSuperClass(), getInterfaces(), getPackage()

Получение загрузчика с помощью которого был загружен данных класс

ClassLoader getClassLoader()

Создает новый объект данного класса. Необходимо чтобы класс определял конструктор по умолчанию.

Object newInstance()

Используется для динамической загрузки класса по имени в виртуальную машину

static Class<?> forName(String name)

Дополнительно имеется множество методов для работы с полями, агрегатами и методами определенными в классе

Page 8: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 8

Классы-обертки для основных типов Используются тогда, когда нужно работать с значениями

примитивных типов как с объектами Используются для получения разнообразной

информации о диапазонах значений и специальных значениях данного типа

Используются для преобразования типов между собой, между различными системами счисления, в строковый формат и наоборот из строкового формата (наследники класса java.lang.Number)

Объекты классов оберток, ровно как и объекты класса String не могут быть изменены после создания. При операциях с ними могут создаваться новые объекты

Page 9: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 9

Пример класса обертки – java.lang.Integer

Формируют строковое представление числа в различных системах счисления

toBinaryString(), toHexString(), toOctalString()

Методы для преобразования числовых типов

doubleValue(), shortValue(), longValue(), doubleValue(), floatVlaue()

Используются для разбора числа заданного в строковом формате. Выбрасывают java.lang.NumberFormatException

int parseInt(…)Integer valueOf(…)

Используется для сравнения с другими объектами данного типа

compareTo(…)

Конструкторы для создания нового объекта

Integer(int value), Integer(String s)

Статические поля, содержащие информацию о диапазоне и ссылку на объект типа Class

MAX_VALUE, MIN_VALUE, TYPE

Page 10: Oop java.generics

Автоматическая обертка boxing/unboxing С целью поддержки наглядности компилятор может осуществлять

автоматическое преобразование примитивных типов в объектные и наоборот:

Integer i = 5; // Integer i = new Integer(5);Integer array[] = new Integer[] { new Integer(1), new Integer(2), new

Integer(3) };// можно заменить :Integer array [] = { 1, 2, 3}; Необходимо соблюдать осторожность при обратных

преобразованиях во избежание NullPointerExceptionclass Foo {

static Integer doSomething() { … } }…int i = Foo.doSomething(); // вероятен NullPointerException Integer theI = Foo.doSomething(); int i = (theI != null) ? theI, 0;

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 10

Page 11: Oop java.generics

Оптимизация цикла for для массивовclass Foo {

public static void main(String args[] ) {for (String s : args ) {

System.out.println(s);}

} }// Эквивалентно… for (int i = 0; i < args.length; i++) {

System.out.println( args[i] ) ; }

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 11

Page 12: Oop java.generics

Переменное количество аргументов При необходимости можно оптимизировать передачу

массива однотипных значений с помощью синтаксиса с переменным количеством аргументов

class Bar {public static void someFunction( String s, int … array) {

int sum = 0;for (int i : array ) {

sum += i;}

}}…Bar.someFunction(“one”, 1, 2, 3, 4, 5); // аргументы одного типа// эквивалентноstatic void someFunction(String s, int[ ] array) {…}

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 12

Page 13: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 13

Математические средства платформы java java.lang.StrictMath – класс-утилита, содержащий

основные математические функции. Гарантирует точную повторяемость числовых результатов вплоть до бита

java.lang.Math – класс-утилита, работающая быстрее чем StrictMath (на старых версиях машины) но не гарантирующая точное воспроизводство числовых результатов для иррациональных чисел.

В версии 1.6 java.lang.Math делегирует вызовы StrictMath java.math.BigDecimal, java.math.BigInteger – классы для

работы с числами произвольного размера и точности

Page 14: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 14

Родовые компоненты – обобщения (generics) Позволяют объявлять классы, интерфейсы и методы,

где тип данных и ограничения на него, которыми они оперируют указан в виде параметра

Позволяют реализовать код, который будет работать единообразно с разными типами данных

В отличие от использования ссылок на тип Object предоставляют безопасные с точки зрения типизации средства обобщенного программирования

Спецификация параметра задается явно (классы, интерфейсы и ссылки) или выводится на основании аргументов (вызов методов)

Соответствие типа проверяется на стадии компиляции

Page 15: Oop java.generics

Простейший пример До java 1.5:public class Envelope {

private Object ref;public Envelope (Object arg) { ref = arg; }public Object get() { return ref; }

}…Envelope e = new Envelope(new

MyClass());…MyClass m = (MyClass) e.get(); //OK// ClassCastException in runtime:Another a = (Another) e.get();

Необходимо знать и учитывать объект какого типа был сохранен

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 15

Начиная с 1.5:public class Envelope <T> {

private T ref;public Envelope (T arg) {

ref = arg; }public T get() { return ref; }

}…Envelope <MyClass> e = new

Envelope<MyClass>(new MyClass());…MyClass m = e.get();//compile time error:Another a = e.get();

Проверка типа осуществляется на стадии компиляции

Page 16: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 16

Грамматика родового классаClassDeclaration: NormalClassDeclaration EnumDeclaration

NormalClassDeclaration: ClassModifiersopt class Identifier TypeParametersopt Superopt Interfacesopt ClassBody

TypeParameters : < TypeParameterList > TypeParameterList : TypeParameterList , TypeParameter | TypeParameter

TypeParameter: TypeVariable TypeBoundopt

TypeBound: extends ClassOrInterfaceType AdditionalBoundListopt

AdditionalBoundList: AdditionalBound AdditionalBoundList AdditionalBound

AdditionalBound: & InterfaceType

Page 17: Oop java.generics

Грамматика родового интерфейса и методаInterfaceDeclaration:

NormalInterfaceDeclaration

AnnotationTypeDeclaration

NormalInterfaceDeclaration:

InterfaceModifiersopt interface Identifier TypeParametersopt

ExtendsInterfacesopt InterfaceBody

MethodDeclaration:

MethodHeader MethodBody

MethodHeader:

MethodModifiersopt TypeParametersopt ResultType MethodDeclarator Throwsopt

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 17

Page 18: Oop java.generics

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 18

Основные отличия от C++ При объявлении специфической ссылки имеющей

типом родовой класс или интерфейс не происходит генерация кода класса (интерфейса)

Все объекты – специфические экземпляры родового класса разделяют один и тот же обобщенный тип

Параметрами родового компонента могут быть только типы

На параметры родового компонента можно наложить ограничения по наследованию определенного типа и/или интерфейса (интерфейсов)

Исключения и перечисления не могут быть родовыми типами

В качестве значений параметров при спецификации не могут использоваться примитивные типы java

Page 19: Oop java.generics

Использование параметров - типов В теле родового компонента можно использовать параметр типа для

объявления ссылок и спецификации значений аргументов других параметризуемых типов

class MyGeneric <T> { private T t;private AnotherGeneric< T > at = new AnotherGeneric<T>();

}

Нельзя инстанцировать объект или массив имеющий типом – параметр:

class SomeGeneric<T> { T t = new T(); //compile time error T array = new T[10]; //compile time error}

Параметр типа недоступен в статическом контекстеclass HasStatic<T> {

static T t; //compile time error}

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 19

Page 20: Oop java.generics

Ограниченные типыclass Stats <T extends Number> {

private T [ ] nums;

public Stats ( T [] array ) { nums = array; }

public double average ( ) { double sum = 0.0; for (T n : nums ) {

//все типы наследники Number реализуют метод doubleValue() sum += n.doubleValue();

} return sum / nums.length();}

}

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 20

Page 21: Oop java.generics

«Шаблоны» параметров - wildcards Допустим мы хотим сравнивать средние значения объектов

Stats<T>:class Stats <T extends Number> {

private T [ ] nums;public Stats ( T [] array ) { nums = array; }public double average ( ) { … }

public boolean sameAvg ( Stats<T> another) {return average() == another.average();

}}//Проблема – нельзя сравнить среднее разных спецификаций:Integer intArray[] = { 1, 2, 4, 7 };Double doubleArray [] = { 6.0, 7.8, 22.0 };Stats<Integer> intStats = new Stats<Integer> (intArray);intStats.sameAvg (new Stats<Double>(doubleArray) ); //Compile time error

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 21

Page 22: Oop java.generics

Решение – использование «?» class Stats <T extends Number> {

private T [ ] nums;public Stats ( T [] array ) { nums = array; }public double average ( ) { … }

public boolean sameAvg ( Stats<?> another) {return average() == another.average();

}} ? можно использовать для спецификации обобщенных ссылок и generic-

type массивов

Stats<?> anyStats = new Stats<Integer> ( ); Stats<?> array[] = new Stats<?> [10]; ? следует применять при проверках instanceof Stats<Integer> iStats = new Stats<Integer> ( new Integer[]{ 1, 2, 3,

4} );iStats instanceof Stats<?> // true

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 22

Page 23: Oop java.generics

Ограниченные wildcardsabstract class Shape {

public abstract void draw(Canvas c);}public class Ellipse extends Shape { … }public class Polygon extends Shape { … }…public static void drawAll (List<? extends Shape> shapesList, Canvas c )

{for (Shape s : shapesList) s.draw ( c );

} // При этом следующий код не работает:public void addPolygon(List<? extends Shape> shapes ) {

shapes.add(new Polygon(…)); //compile time error} <? extends Bar> - при спецификации может использоваться

любой наследник включая сам класс Bar <? super Foo> - может использоваться только суперкласс Foo

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 23

Page 24: Oop java.generics

Родовые методыclass Bar {

public static <T> void fromArrayToCollection (T[] a, Collection <T> c) {

for (T v: a) c.add(v);}

}…Integer[] ia = new Integer[100];Collection<Integer> ic = new ArrayList<Integer>();Bar.fromArrayToCollection (ia, ic); //спецификация на основе

аргументов//Можно использовать совместно с wildcards:public class Collections {

public static <T> void copy(List<T> dest, List<? extends T> src) { … }

}Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 24

Page 25: Oop java.generics

Что лучше использовать?interface Collection <E> {

public boolean containsAll (Collection <?> c);public boolean addAll (Collection<? extends E> c);

}//илиinterface Collection <E> {

public <T> boolean containsAll(Collection <T> c);public <T extends E> boolean addAll(Collection <T> c);

} Замечания по именованию

Обычно используется параметр T Если параметров несколько – то буквы близкие по алфавиту,

например T совместно с S Если родовой метод (класс) вложен в другой родовой компонент,

то лучше использовать отличную от параметра этого компонента букву

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 25

Page 26: Oop java.generics

Raw типы и совместимость Для совместимости с ранним кодом можно использовать

родовые компоненты без спецификации параметровList rawList = new LinkedList();Integer i = 5; // помним о boxingrawList.add( i ); // реально rawList.add( (Object) i);…Integer v = (Integer) rawList.get(0);List<Number> nList = new ArrayList<Number>();…rawList = nList; // безопасно, но теряем защиту по типу…List<Integer> iList = (List<Integer) rawList; //Допустимо но

опасно!int v = iList.get(0); // ClassCastException !

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 26

Page 27: Oop java.generics

Родовые компоненты и наследование Родовые классы (интерфейсы) могут наследоваться от

обычных классов (интерфейсов) и наоборот Возможно приведение ссылки дочернего родового

класса (интерфейса) на базовый только в том случае, если совпадают значения аргументов – типов заданные при спецификации

Если классы A и B связаны наследованием (A extends B), то это не значит, что специфицированные ссылки параметризованных типов которым переданы эти классы в качестве параметров-типов совместимы между собой !

// параметры совпадают, класс LinkedList<T> реализует интерфейс List<T>

List<String> stringList = new LinkedList<String> (); //OK// значения параметров у ссылок не совпадают, присваивание невозможно:

List<Object> objectList = stringList; //compile time error

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 27

Page 28: Oop java.generics

Реализация обобщенных интерфейсовinterface MinMax <T extends Comparable<T>> {

T min();T max();

}

//Класс реализующий родовой интерфейс должен быть родовымclass MinMaxArray <T extends Comparable <T>> implements MinMax {

T [ ] vals; MinMaxArray (T arg[ ] ) { vals = arg; }public T min () { … } public T max () { … }

}…Character chrs [ ] = { ‘c’, ‘f’ , ‘k’, ‘a’ }; // boxing Character maxChar = (new MinMaxArray<Character> (chrs)).max();

//Однако можно наследовать специфицированный интерфейсclass MinMaxIntegerArray extends MinMax<Integer> { … }

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 28

Page 29: Oop java.generics

Перегрузка и наследованиеpublic class Base <T> {

private T val;public Base(T v) { val = v;}public T getVal() { return val;}

}public class Derived<T,S> extends Base<T> {

private S another;public Derived (T v, S s) {

super(v);another = s;

}public T getVal () { … } //Перегруженный метод

}//Допустимо:Base<Integer> b = new Derived <Integer, String> (5, “Hello!”);

Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 29

Page 30: Oop java.generics

«Очистка параметров» при компиляции Из соображений совместимости вся информация о параметрах – типах

при компиляции удаляется При этом происходит замена параметров типа на реально их

ограничивающий класс class Bar<T extends Number> {…} - T заменяется на Number class Foo<T> {…} - T заменяется на Object

class GenStr <T extends String> {

T str;

GenStr ( T val) { str = val; }

T getStr () {return str;}

} // откомпилируется как будто был написан так:

class GenStr extends Object {

java.lang.String str;

GenStr (java.lang.String val) {str = val;}

java.lang.String getStr() { return str; }

}Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 30

Page 31: Oop java.generics

Дополнительные проблемы Методы – мосты (генерируются компилятором)class Base <T> {

public T f () { … } // откомпилируется в Object f() {…}}class Derived extends Base<String> {

public String f() { return super.f(); } // нужен мост} Потенциальная неоднозначностьclass Foo <T,S> {

T t;

S s;

void set (T targ) { t = targ; } // компилируется в set(Object o) {…}

void set (S sarg) { s = sarg; } // компилируется в set(Object o) {…}

}Новосибирск, 2004

(С) Всеволод Рылов, все права защищены 31