bung Softwareentwicklung 2 fr Wirtschaftsinformatik - PowerPoint PPT Presentation

1 / 17
About This Presentation
Title:

bung Softwareentwicklung 2 fr Wirtschaftsinformatik

Description:

Car [] cars = {new Car('VW'); new Car(''Audi')} Collection Car carsCol; fromArrayToCollection(car, carsCol) ... The 'Dirty Trick' Used in Collection Classes ... – PowerPoint PPT presentation

Number of Views:28
Avg rating:3.0/5.0
Slides: 18
Provided by: tkUnil
Category:

less

Transcript and Presenter's Notes

Title: bung Softwareentwicklung 2 fr Wirtschaftsinformatik


1
Übung Softwareentwicklung 2für
Wirtschaftsinformatik
UE04Generics
mit freundlicher Unterstützung des SSW
2
Generics
Object
ListltObjectgt
String
ListltStringgt
  • ListltStringgt listString new ArrayListltStringgt()
    //1
  • ListltObjectgt listObject listString //2
  • FRAGE Ist eine Liste von Strings eine Liste von
    Objekten?

listObject.add(new Object()) // 3
listObject.add(new String()) // 4
listString.add(new String()) // 5
listString.add(new Object()) // 6
String s listString.get(0) //
7 s.concat("Hugo")
gt attempts to assign an Object to a String!
gt would fail, since get(0) liefert ein Object!
Wenn A ein Subtyp von B is und G ist eine
Gernerische Typ-Deklaration, dann ist GltAgt NICHT
ein Subtyp von GltBgt!
3
Generics
  • void printCollection(Collection c)
  • Iterator i c.iterator()
  • for (k 0 k lt c.size() k)
  • System.out.println(i.next())

ACHTUNG Ungetyp sollte vermieden werden!
Collections für beliebige Typen?!
Versuch void printCollection(CollectionltObjectgt
c) for (Object e c) System.out.println(
e)
ABER CollectionltObjectgt, is wie zuvor gezeigt
kein Supertyp von allen Collections!
4
Generics
  • void printCollection(Collection c)
  • Iterator i c.iterator()
  • for (k 0 k lt c.size() k)
  • System.out.println(i.next())
  • Richtig
  • void printCollection(Collectionlt?gt c)
  • for (Object e c)
  • System.out.println(e)
  • ? wildcard type steht für jeden beliebigen Typ

ACHTUNG Ungetyp sollte vermieden werden!
5
Generics
  • void printCollection(Collectionlt?gt c)
  • for (Object e c) // anything you get is an
    Object
  • System.out.println(e)

ABER Collectionlt?gt c new ArrayListltStringgt()
c.add(new Object())
// compile time error
c ist eine Collection unbekannten Typs. Die
add()-Methode ist nur zulässig mit Objekten des
Typs mit dem die Collection definiert wurde. Dies
ist allerings ? (unbekannt). Die add()-Methode
kann aber nur Sub-Typen eines unbekannten Typen
übernehmen und da wir diesen Typen nicht kennen
können ist dies nicht zulässig. Der einzige
zulässige Parameter wäre null, da null von jedem
Typ ist.
6
Generics
  • public abstract class Shape
  • public abstract void draw(Canvas c)
  • public class Circle extends Shape
  • private int x, y, radius
  • public void draw(Canvas c) ...
  • public class Rectangle extends Shape
  • private int x, y, width, height
  • public void draw(Canvas c) ...

Soll für alle Shapes gehen!
These classes can be drawn on a canvas public
class Canvas public void draw(Shape s)
s.draw(this) public void
drawAll(ListltShapegt shapes) for (Shape s
shapes) s.draw(this)
ABER drawAll läßt sich nur mit einer Liste genau
vom Typ Shape aufrufen
7
Generics
  • public abstract class Shape
  • public abstract void draw(Canvas c)
  • public class Circle extends Shape
  • private int x, y, radius
  • public void draw(Canvas c) ...
  • public class Rectangle extends Shape
  • private int x, y, width, height
  • public void draw(Canvas c) ...

Typisiert mit einem Typ, der zumindes Shapes ist
(Shapes oder Sub-Klass davon)
? extends ermöglicht das Spezifizieren eines
Parameters, der eine Liste von Shapes oder eines
Subtyps davon sein muss.
These classes can be drawn on a canvas public
class Canvas public void draw(Shape s)
s.draw(this) public void drawAll(Listlt?
extends Shapegt shapes) for (Shape s shapes)
s.draw(this)
8
Generics
  • public void addRectangle(Listlt? extends Shapegt
    shapes)
  • shapes.add(new Rectangle())

// compile-time error!
  • Weil addRectangle() könnte ja auch mit einer
    Liste von Circles aufgerufen werden!
  • ListltShapegt anyShapesList // ok
  • ListltRectanglesgt recShapesList // ok
  • ListltCirclesgt circlesShapesList // NOT OK!

9
Generics
  • Generic Methods
  • Beispiel Methode die ein Array von Objekten nimmt
    und dieses in eine Collection eines beliebigen
    Typs gibt.
  • static void fromArrayToCollection(Object a,
    Collectionlt?gt c)
  • for (Object o a)
  • c.add(o)

// compile time error
WEIL Objekte nicht in eine Collections eines
unbekannten Typs eingefügt werden können. Car
cars new Car("VW") new Car("'Audi") Collectio
nltCargt carsCol fromArrayToCollection(car,
carsCol) Car c1 carsCol.get() // Problem, da
hier ein Object gelesen wird
10
Generics
  • Generic Methods
  • Beispiel Methode die ein Array von Objekten nimmt
    und dieses in eine Collection eines beliebigen
    Typs gibt.
  • static ltTgt void fromArrayToCollection(T a,
    CollectionltTgt c)
  • for (T o a)
  • c.add(o) // correct
  • Car cars new Car("VW") new Car("'Audi")
  • CollectionltCargt carsCol
  • fromArrayToCollection(car, carsCol)
  • Car c1 carsCol.get() // Kein Problem, da hier
    ein sicher ein Car gelesen wird

11
Generic for Contructor Calls?!
  • Because of erasure, ListltIntegergt and
    ListltStringgt are the same class, and the compiler
    only generates one class when compiling ListltVgt
    (unlike in C). As a result, the compiler
    doesn't know what type is represented by V when
    compiling the ListltVgt class, and so you can't do
    certain things with a type parameter (the V in
    ListltVgt) within the class definition of ListltVgt
    that you could do if you knew what class was
    being represented.
  • Because the runtime cannot tell a ListltStringgt
    from a ListltIntegergt (at runtime, they're both
    just Lists), constructing variables whose type is
    identified by a generic type parameter is
    problematic. This lack of type information at
    runtime poses a problem for generic container
    classes and for generic classes that want to make
    defensive copies.

class FooltTgt public void doSomething(T param)
...
public void doSomething(T param) T copy new
T(param) // illegal
12
Generic for Contructor Calls?!
  • Consider the generic class Foo
  • Suppose the doSomething() method wants to make a
    defensive copy of the param argument on entry?
    You don't have many options. You'd like to
    implement doSomething() like this

class FooltTgt public void doSomething(T param)
...
public void doSomething(T param) T copy new
T(param)
// illegal
  • But you cannot use a type parameter to access a
    constructor because, at compile time, you don't
    know what class is being constructed and
    therefore what constructors are available.
  • There's no way to express a constraint like "T
    must have a copy constructor" (or even a no-arg
    constructor) using generics, so accessing
    constructors for classes represented by generic
    type parameters is out.

13
Using clone()?!
  • What about clone()?
  • Let's say Foo was defined to make T extend
    Cloneable

class FooltT extends Cloneablegt public void
doSomething(T param) T copy (T)
param.clone()
// illegal
  • Unfortunately, you still can't call
    param.clone().
  • Why?
  • Because clone() has protected access in Object
    and, to call clone(), you have to call it through
    a reference to a class that has overridden
    clone() to be public.
  • But T is not known to redeclare clone() as
    public, so cloning is also out.

14
Using Wildcards?!
  • What about wildcard types?
  • Suppose you want to make a defensive copy of a
    parameter whose type is Setlt?gt. You know that Set
    has a copy constructor. You've also been told
    it's better to use Setlt?gt instead of the raw type
    Set when you don't know the type of the set's
    contents, because that approach is likely to emit
    fewer unchecked conversion warnings. So you try
    this

class Foo public void doSomething(Setlt?gt set)
Setlt?gt copy new HashSetlt?gt(set)

// illegal
  • Unfortunately, you can't invoke a generic
    constructor with a wildcard type argument, even
    though you know such a constructor exists.
  • However, you can do this
  • This construction is not the most obvious, but it
    is type-safe and will do what you think new
    HashSetlt?gt(set) would do.

class Foo public void doSomething(Setlt?gt set)
Setlt?gt copy new HashSetltObjectgt(set)
15
Constructing Arrays
  • How would you implement ArrayListltVgt?
  • The ArrayList class is supposed to manage an
    array of V, so you might expect the constructor
    for ArrayListltVgt to create an array of V

class ArrayListltVgt private V backingArray
public ArrayList() backingArray new
VDEFAULT_SIZE
// illegal
  • But this code does not work -- you cannot
    instantiate an array of a type represented by a
    type parameter!
  • The compiler doesn't know what type V really
    represents, so it cannot instantiate an array of
    V.

16
The "Dirty Trick" Used in Collection Classes
  • The Collections classes use an ugly trick to get
    around this problem, one that generates an
    unchecked conversion warning when the Collections
    classes are compiled. The constructor for the
    real implementation of ArrayList looks likes
    this
  • Why does this code not generate an
    ArrayStoreException (indicate that an attempt has
    been made to store the wrong type of object into
    an array of objects) when backingArray is
    accessed?
  • After all, you can't assign an array of Object to
    an array of String.

class ArrayListltVgt private V backingArray
public ArrayList() backingArray (V)
new ObjectDEFAULT_SIZE
  • Well, because generics are implemented by
    erasure, the type of backingArray is actually
    Object, because Object is the erasure of V.
    This means that the class is really expecting
    backingArray to be an array of Object anyway, but
    the compiler does extra type checking to ensure
    that it contains only objects of type V.
  • So this approach will work, but it's ugly, and
    not really something to emulate (even the authors
    of the generified Collections framework say so).

17
Passing Type
  • The best approach would be to pass a class
    literal (Foo.class) into the constructor, so that
    the implementation could know, at runtime, the
    value of T.
  • The reason this approach was not taken was for
    backward compatibility -- then the new generified
    collection classes would not be compatible with
    previous versions of the Collections framework.
  • Here's how ArrayList would have looked under this
    approach

public class ArrayListltVgt implements ListltVgt
private V backingArray private ClassltVgt
elementType public ArrayList(ClassltVgt
elementType) this.elementType elementType
backingArray (V) Array.newInstance(elementT
ype, DEFAULT_LENGTH)
  • But wait! There's still an ugly, unchecked cast
    there when calling Array.newInstance().
  • Why? Again, it's because of backward
    compatibility. The signature of
    Array.newInstance() is

public static Object newInstance(Classlt?gt
componentType, int length)
  • instead of the type-safe

public staticltTgt T newInstance(ClassltTgt
componentType, int length)
  • All to preserve backward compatibility. To create
    an array of a primitive type, such as int, you
    call Array.newInstance() with the TYPE field from
    the appropriate wrapper class (in the case of
    int, you would pass Integer.TYPE as the class
    literal). Generifying Array.newInstance() with a
    parameter of ClassltTgt instead of Classlt?gt would
    have been more type-safe for reference types, but
    would have made it impossible to use
    Array.newInstance() to create an instance of a
    primitive array. Perhaps in the future, an
    alternate version of newInstance() will be
    provided for reference types so you can have it
    both ways.
Write a Comment
User Comments (0)
About PowerShow.com