29
301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini [email protected] Tutor: Lillo GalleBa [email protected] Department of Computer Science, Pisa Academic Year 2017/18 AP-2017-14: Java Generics

301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini [email protected]

  • Upload
    votruc

  • View
    221

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

301AA-AdvancedProgramming[AP-2017]

Lecturer:[email protected]:[email protected]

DepartmentofComputerScience,PisaAcademicYear2017/18

AP-2017-14: JavaGenerics

Page 2: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Outline

•  Javagenerics•  Typebounds•  Genericsandsubtyping•  Covariance,contravarianceinJavaandotherlanguages

•  SubtypingandarraysinJava•  Wildcards•  Typeerasure•  LimitaQonsofgenerics

2

Page 3: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

ClassificaQonofPolymorphism

Polymorphism

Universal

Ad hoc

Parametric

Inclusion

Overloading

Coercion Implicit

Bounded

Overriding

Explicit

Covariant

Invariant

Contravariant

Bounded

Page 4: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

JavaGenerics

•  Classes,Interfaces,Methodscanhavetypeparameters

•  ThetypeparameterscanbeusedarbitrarlyinthedefiniQon

•  TheycanbeinstanQatedbyprovidingarbitrary(reference)typearguments

•  WediscussonlyafewissuesaboutJavagenerics…

4

List<Integer> List<Number> List<String> List<List<String>> …

interface List<E> { boolean add(E n); E get(int index); }

ExplicitParametricPolymorphism

TutorialsonJavagenerics:https://docs.oracle.com/javase/tutorial/java/generics/index.html!http://thegreyblog.blogspot.it/2011/03/

! !java-generics-tutorial-part-i-basics.html!

Page 5: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Genericmethods

•  Methodscanusethetypeparametersoftheclasswheretheyaredefined,ifany

•  Theycanalsointroducetheirowntypeparameters

public static <T> T getFirst(List<T> list)!

!•  InvocaQonsofgenericmethodsmustinstanQateall

typeparameters,eitherexplicitlyorimplicitly– Aformoftypeinference

5

Page 6: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

BoundedTypeParameters interface List<E extends Number> { void m(E arg) { arg.asInt(); // OK, Number and its subtypes // support asInt() } }

•  OnlyclassesimplemenQngNumbercanbeusedastypearguments

•  Methoddefinedinthebound(Number)canbeinvokedonobjectsofthetypeparameter

6

Page 7: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

TypeBounds<TypeVar extends SuperType> –  upperbound;SuperTypeandanyofitssubtypeareok.

<TypeVar extends ClassA & InterfaceB & InterfaceC & …> –  Mul4pleupperbounds

<TypeVar super SubType> –  lowerbound;SubTypeandanyofitssupertypeareok

•  TypeboundsformethodsguaranteethatthetypeargumentsupportstheoperaQonsusedinthemethodbody

•  UnlikeC++whereoverloadingisresolvedandcanfailaderinstanQaQngatemplate,inJavatypecheckingensuresthatoverloadingwillsucceed

7

Page 8: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Agenericalgorithmwithtypebounds

8

public static <T> int countGreaterThan(T[] anArray, T elem) {! int count = 0;! for (T e : anArray)! if (e > elem) // compiler error! ++count;! return count;!}!

public interface Comparable<T> { !// classes implementing! public int compareTo(T o); !// Comparable provide a !} ! !// default way to compare their objects!

public static <T extends Comparable<T>> !! ! ! !int countGreaterThan(T[] anArray, T elem) {!

int count = 0;! for (T e : anArray)! if (e.compareTo(elem) > 0) !// ok, it compiles! ++count;! return count;!}!

Page 9: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Genericsandsubtyping

•  IntegerissubtypeofNumber!

•  IsList<Integer>subtypeofList<Number>?

•  NO!

9

Number

Integer

List<Number>

List<Integer>?

Page 10: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

WhatareJavarules?•  GiventwoconcretetypesAandB,MyClass<A>hasno

rela9onshiptoMyClass<B>,regardlessofwhetherornotAandBarerelated.

•  Formally:subtypinginJavaisinvariantforgenericclasses.

•  Note:ThecommonparentofMyClass<A>andMyClass<B>isMyClass<?>:the“wildcard”?Willbediscussedlater.

•  Ontheotherhand,asexpected,ifAextendsBandtheyaregenericclasses,foreachtypeCwehavethatA<C>extendsB<C>.

•  Thus,forexample,ArrayList<Integer>issubtypeofList<Integer>

10

Page 11: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

List<Number>eList<Integer>interface List<T> { boolean add(T elt); T get(int index); }

typeList<Number>has: boolean add(Number elt); Number get(int index);

typeList<Integer>has: boolean add(Integer elt); Integer get(int index);

IstheSubs9tu9onPrinciplesaQsfiedineitherdirecQon?ThusList<Number>isneitherasupertypenorasubtypeofList<Integer>:Javarulesareadequatehere 11

Number

Integer

List<Integer> lisInt = new …;!List<Number> lisNum = new …; !lisNum = lisInt; !// ???!lisNum.add(new Number(…));//no!listInt = lisNum; !// ???!Integer n = lisInt.get(0); //no!

Page 12: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

ButinmorespecificsituaQons…interface List<T> { T get(int index); }

typeList<Number>: Number get(int index);

typeList<Integer>: Integer get(int index);

Acovariantno9onofsubtypingwouldbesafe:–  List<Integer>canbesubtypeofList<Number> –  NotinJava

•  Ingeneral:covarianceissafeifthetypeisread-only

12

Number

Integer

Page 13: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Viceversa…contravariance!interface List<T> { boolean add(T elt); }

typeList<Number>: boolean add(Number elt);

typeList<Integer>: boolean add(Integer elt);

Acontravariantno9onofsubtypingwouldbesafe:

–  List<Number>canbeasubtypeofList<Integer> –  ButJava…..

Ingeneral:contravarianceissafeifthetypeiswrite-only

13

Number

Integer

Page 14: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

GenericsandsubtypesinC#•  InC#,thetypeparameterofagenericclasscanbe

annotatedout(covariant)orin(contravariant),otherwiseitisinvariant.Examples:

•  Ienumeratoriscovariant,becausetheonlymethodreturnsanenumerator,whichaccessesthecollecQoninread-only

•  IComparableiscontravariant,becausetheonlymethodhasanargumentoftypeT

14

public interface IEnumerable<out T> : […] {!!public […]IEnumerator<out T> GetEnumerator ();!

}!

public interface IComparable<in T> {!!public int CompareTo (T other);!

}!

Page 15: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Co-andContra-varianceinScala

•  AlsoScalasupportsco/contra-varianceannotaQons(-and+)fortypeparameters:

!class VendingMachine[+A]{…}!!class GarbageCan[-A]{…}!!trait Function1[-T, +R] extends AnyRef !{ def apply(v1: T): R }!

15

http://blog.kamkor.me/Covariance-And-Contravariance-In-Scala/!

Page 16: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Adigression:Javaarrays

•  Arraysarelikebuilt-incontainers–  LetType1beasubtypeofType2.–  HowareType1[]eType2[]related?

•  Considerthefollowinggenericclass,mimickingarrays:class Array<T> {! public T get(int i) { … “op” … }! public T set(T newVal, int i) { … “op” … }!}!AccordingwithJavarules,Array<Type1>andArray<Type2>arenotrelatedbysubtyping

16

Page 17: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Butinstead…

•  InJava,ifType1isasubtypeofType2,thenType1[]isasubtypeofType2[].ThusJavaarraysarecovariant.

•  Java(andalsoC#,.NET)fixedthisrulebeforetheintroducQonofgenerics.

•  Why?Thinkto•  Notconvenienttochangeitbecauseofretro-compabilityconsideraQons.

•  Covarianceworksfine,providedyoudonotchangethecontentofanarray…

17

void sort(Object[] o);!

Page 18: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Asafeuseofcovarianceinarraysvoid maybeSwap(LibraryHolding[] arr) { if(arr[17].dueDate() < arr[34].dueDate()) // … swap arr[17] and arr[34] } // client Book[] books = …; maybeSwap(books); // uses covariance of arrays

18

LibraryHolding

Book CD

Page 19: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

ButinserQoncausesfailure

void replace17(LibraryHolding[] arr, LibraryHolding h) { arr[17] = h; }

// the client Book[] books = …; LibraryHolding theWall = new CD("Pink Floyd", "The Wall", …); replace17(books, theWall); Book b = books[17]; // contains a CD b.getChapters(); // problem!!

19

LibraryHolding

Book CD

Page 20: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Java’schoices•  Foreachreferencevariable,thedynamictype(typeoftheobject

referredbyit)mustbeasubtypeofthesta9cone(typeofdeclaraQon).–  ViolatedforBook b

•  Javadesignchoices:–  ThedynamictypeofanarrayisknownatrunQme(Book[],or

beBer[Lmypackage.Book;inJVMtypesyntax)–  EveryJavaarray-updateincludesrun-9mecheck–  AssigninganobjectofasupertypetoanarraythrowsanArrayStoreException

•  Thusreplace17throwsanexcepQon

20

Page 21: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Asimplerexample

21

Apple[] apples = new Apple[1];!Fruit[] fruits = apples;!fruits[0] = new Strawberry();! // JVM throws ArrayStoreException !

Page 22: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Aseriousconsequence•  EveryJavaarray-updateincludesrun-Qmecheck,but•  GenerictypesarenotpresentatrunQmeduetotypeerasure,thus

•  ArraysofgenericsarenotsupportedinJava•  InfacttheywouldcausetypeerrorsnotdetectableatrunQme,breakingJavastrongtypesafety

22

List<String>[] lsa = new List<String>[10]; // illegal!Object[] oa = lsa; // OK by covariance of arrays !List<Integer> li = new ArrayList<Integer>();!li.add(new Integer(3));!oa[0] = li; // should throw ArrayStoreExeception, ! !// but JVM only sees “oa[0]:List = li:ArrayList”!String s = lsa[0].get(0); // type error !!!

Page 23: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Wildcardsforcovariance

•  InvarianceofgenericclassesisrestricQve•  Wildcardscanalleviatetheproblem•  Whatisa“generalenough”typeforaddAll?

interface Set<E> { // Adds to this all elements of c // (not already in this) void addAll(??? c); }

•  void addAll(Set<E> c) // andList<E>? •  void addAll(Collection<E> c)

// andcollecQonsof T <: E? •  void addAll(Collection<? extends E> c); // ok 23

Page 24: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Wildcards,forbothco-andcontra-variance

Syntaxofwildcards:–  ? extends Type,denotesanunknownsubtypeofType –  ?,shorthandfor? extends Object –  ? super Type,denotesanunknownsupertypeofType

wildcard=anonymousvariable–  ?Unknowntype–  Wildcardareusedwhenatypeisusedexactlyonce,andthenameis

unknown–  Theyareusedforuse-sitevariance(notdeclara9on-sitevariance)

24

Page 25: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

The“PECSprinciple”:ProducerExtends,ConsumerSuper

Whenshouldwildcardsbeused?–  Use? extends Twhenyouwanttogetvalues(fromaproducer):supportscovariance

–  Use? super Twhenyouwanttoinsertvalues(inaconsumer):supportscontravariance

–  Donotuse?(Tisenough)whenyoubothobtainandproducevalues.

Example: <T> void copy(List<? super T> dst, List<? extends T> src);

25

Page 26: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Whatabouttypesafety?

•  Arrayscovariance:

•  Covariancewithwildcards:

26

Apple[] apples = new Apple[1];!Fruit[] fruits = apples;!fruits[0] = new Strawberry();! // JVM throws ArrayStoreException !

List<Apple> apples = new ArrayList<Apple>();!List<? extends Fruit> fruits = apples;!fruits.add(new Strawberry()); !

!// compile-time error!!!!

Page 27: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Thepricetopaywithwildcards•  Awildcardtypeisanonymous/unknown,andalmostnothingcanbedone:

27

List<Apple> apples = new ArrayList<Apple>();!List<? extends Fruit> fruits = apples; //covariance!fruits.add(new Strawberry()); // compile-time error! OK!Fruits f = apples.get(0); // OK!fruits.add(new Apple()); // compile-time error??? !fruits.add(null); //ok, the only thing you can add ! !

List<Fruit> fruits = new ArrayList<Fruits>();!List<? super Apples> apples = fruits; //contravariance!fruits.add(new Apple()); // OK!fruits.add(new FujiApple()); // OK!fruits.add(new Fruit()); // compile-time error, OK!Fruits f = apples.get(0); // compile-time error???!Object o = apples.get(0); //ok, the only way to get!

Page 28: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

Typeerasure

AlltypeparametersofgenerictypesaretransformedtoObjectortotheirfirstboundadercompilaQon– MainReason:backwardcompaQbilitywithlegacycode

– Thusatrun-Qme,alltheinstancesofthesamegenerictypehavethesametype

List<String> lst1 = new ArrayList<String>(); List<Integer> lst2 = new ArrayList<Integer>(); lst1.getClass() == lst2.getClass() // true 28

Page 29: 301AA - Advanced Programming [AP-2017] - unipi.itpages.di.unipi.it/corradini/Didattica/AP-17/SLIDES/AP...301AA - Advanced Programming [AP-2017] Lecturer: Andrea Corradini andrea@di.unipi.it

LimitaQonsofJavaGenerics•  CannotInstanQateGenericTypeswithPrimiQveTypesArrayList<int> a = … //does not compile•  CannotCreateInstancesofTypeParameters•  CannotDeclareStaQcFieldsWhoseTypesareTypeParameterspublic class C<T>{ public static T local; …}!•  CannotUseCastsorinstanceofWithParameterizedTypes(list instanceof ArrayList<Integer>) // does not compile!(list instanceof ArrayList<?>) // ok•  CannotCreateArraysofParameterizedTypes•  CannotCreate,Catch,orThrowObjectsofParameterizedTypes•  CannotOverloadaMethodWheretheFormalParameterTypesofEach

OverloadErasetotheSameRawTypepublic class Example { // does not copile!public void print(Set<String> strSet) { } !public void print(Set<Integer> intSet) { } }!

29