Title: Linguaggi speciali di programmazione 1
1Linguaggi speciali di programmazione 1
2Outline
- New language features of Java 5
- Generics
- Iterators
- Autoboxing/Unboxing
- Annotations
- Enumerated Types
- Covariant return type
- Variable Arguments
3New Language Features
- Generics
- Covariant Return Types
- Enhanced for loop
- Enumerated Types
- Autoboxing (and unboxing)
- Varargs
- Static imports
- Annotations (metadata)
- Concurrency Threading Utilities
4Arrays and collections
- In Java, array elements must all be of the same
type - int counts new int10
- String names "Tom", "Dick", "Harry"
- Hence, arrays are type safe The compiler will
not let you put the wrong kind of thing into an
array - A collection, such as a Vector or ArrayList,
cannot hold primitives, but will accept any type
of Object - Stack someStuff new Stack()someStuff.push("A
String is an Object")someStuff.push(Color.BLUE)
- We can make an array that, like a collection,
holds any Objects - Object whatever new Object100
- Prior to Java 5, there was no easy way to make a
collection type safe
5Making a collection type safe
- Heres how to create a type-safe Stack that holds
only Strings (in Java 1.4 and earlier) - class StackOfStrings private Stack
internalStack new Stack() public boolean
isEmpty() return internalStack.isEmpty()
public String push(String s)
internalStack.push(s) return s
public String pop() return
(String)internalStack.pop() etc.
6Filtering a CollectionToday
- // Removes 4-letter words from c
- // elements must be strings
- static void expurgate(Collection c)
- for (Iterator i c.iterator() i.hasNext() )
- if(((String) i.next()).length() 4)
- i.remove()
-
- // Alternative form - a bit prettier?
- static void expurgate(Collection c)
- for (Iterator i c.iterator() i.hasNext() )
- String s (String) i.next()
- if(s.length() 4)
- i.remove()
-
-
7Generics for type safety in Java 5
- In Java 5, you can easily make any collection
type safe - For example, you can create a Stack that holds
only Strings as follows - StackltStringgt names new StackltStringgt()
- You can write methods that require a type-safe
collection as follows - void printNames(StackltStringgt names)
- String nextName names.pop() // no casting
needed! - names.push("Hello") // works just the same as
before - names.push(Color.RED) // compile-time error!
8What generics are and arent
- You can almost think of generics as defining new
types - For example a StackltStringgt is a stack of strings
- In Java 1.4,
- String s myStack.pop() will not compile
- String s (String)myStack.pop() compiles, with
runtime check - myStack.push(Color.RED) compiles with no
complaint - In Java 5, String s myStack.pop()
- Compiles with no runtime check if myStack was
declared as StackltStringgt - Does not compile if myStack was declared any
other way - myStack.push(Color.RED) is a compiler error (
syntax error)
9What generics are and arent
- However, generics are instructions to the
compiler only - You can still say if (thing instanceof
Stack) ... - but you cannot say if (thing instanceof
StackltStringgt) ... - This is called erasure
- The type information is erased at runtime
10Generics and data structures (1/2)
- Generics are important in studying data
structures because - You can make heavy use of Suns collections, all
of which have been genericized, so we need to
know how to use them - However, non-genericized collections continue to
work - Genericized collections include
- LinkedList, ArrayList, Vector, HashSet, TreeSet,
Stack, HashMap, TreeMap, PriorityQueue, and
others - When we create new data structures,
- In Java 5, it is almost always a good idea to
genericize them - However, Java 5 programs will only work for users
who have upgraded their Java systems - So we may wish to compile for older versions
11Generics and data structures (2/2)
- Generics are not important in data structures
because - Generics are only a convenient way to get type
safety - The data structures themselves have not changed
in any way
12Using an existing collection
- Creation
- Stack plainStack new Stack() // the old way
- Stack s1 new StackltIntegergt() // s1 is still
just a plain stack - StackltIntegergt integerStack new
StackltIntegergt() // correct - StackltIntegergt s2 new Stack() // works with a
warning - Assignments
- plainStack integerStack // no problem with
this - integerStack plainStack // works but is not
type safe - Use of integerStack
- integerStack.push(new Integer(5))
- Integer xxx integerStack.pop() // no cast
necessary - integerStack.push(5) // works, because of
autoboxing - int x integerStack.pop() // works, because of
auto unboxing
13Methods with generics
- private static void fiddle(StackltIntegergt ints)
ints.push(5) - fiddle(integerStack) // good call
- fiddle(plainStack) // legal but not type safe
- fiddle(new StackltStringgt()) // not legal
- static StackltIntegergt myMethod(StackltIntegergt
stk) StackltIntegergt result new
StackltIntegergt() return result - StackltIntegergt newStack myMethod(integerStack)
// good call - StackltIntegergt newStack1 myMethod(plainStack)
// not safe
14Bad news
- Type safe? Only sort of...
- StackltIntegergt stack1 new StackltIntegergt()Stac
k stack2 stack1 // stack2 is alias of
stack1stack2.push(Color.RED)// legal--stack2 is
a plain stackInteger xxx stack1.pop() //
ClassCastException! - A little more explanation...
- Java 5 is upwardly compatible with Java 1.4
- Old programs must continue to work
- Hence you can have non-generic stacks (and stack
assignment) - When you use a generic collection, you should
make it generic everywhere, not just in the
places that Java would otherwise report an error - Eclipse will provide warnings for many unsafe
cases, so pay close attention to those warnings!
15Writing your own generic classes
- public class MyClassltTgt
- T value // in this class, use T just like
any other type - public MyClass(T value)
- this.value value
- public void print(T anotherValue)
- System.out.println(value " "
anotherValue)
16Parameterized Classes Syntax Note
- A class can have multiple parameters, e.g
- public class StuffltA,B,Cgt
- Subclassing parameterized classes allowed, e.g
- / Extending a particular type /
- class IntBox extends BoxltIntegergt
- Or
- / Extending a parameterized type /
- class SpecialBoxltEgt extends BoxltEgt
- SpecialBoxltStringgt is a subclass of BoxltStringgt.
- / Following assignment is legal /
- BoxltStringgt sb new SpecialBoxltStringgt(Hi)
17Parameterized Classes in Methods
- A parameterized class is a type just like any
other class - It can be used in method input types and return
types, for example - BoxltStringgt aMethod(int i, BoxltIntegergt b)
18Parameterized Classes in Methods
- If a class is parameterized, that type parameter
can be used for any type declaration in that
class, for example - public class BoxltEgt
- E data
- public Box(E data)
- this.data data
-
- public E getData()
- return data
-
- public void copyFrom(BoxltEgt b)
- this.data b.getData()
-
-
- //We have added an infinite number of types of
Boxes - //by writing a single class definition
19Bounded Parameterized Types (1/4)
- Sometimes we want restricted parameterization of
classes - We want a box, called MathBox that holds only
Number objects. We cant use BoxltEgt because E
could be anything. We want E to be a subclass of
Number - public class MathBoxltE extends Numbergt extends
BoxltNumbergt - public MathBox(E data)
- super(data)
-
- public double sqrt()
- return Math.sqrt(getData().doubleValue())
-
-
20Bounded Parameterized Types (2/4)
- The ltE extends Numbergt syntax means that the type
parameter of MathBox must be a subclass of the
Number class - We say that the type parameter is bounded
- new MathBoxltIntegergt(5)//Legal
- new MathBoxltDoublegt(32.1)//Legal
- new MathBoxltStringgt(No good!)//Illegal
21Bounded Parameterized Types (3/4)
- Inside a parameterized class, the type parameter
serves as a valid type. So the following is
valid. - public class OuterClassltTgt
- private class InnerClassltE extends Tgt
-
-
-
-
- Syntax note
- The ltA extends Bgt syntax is valid even if B is an
interface.
22Bounded Parameterized Types (4/4)
- Java allows multiple inheritance in the form of
implementing multiple interfaces - So multiple bounds may be necessary to specify a
type parameter. The following syntax is used
then - ltT extends A B C gt
- For instance
- interface A
-
-
- interface B
-
-
- class MultiBoundsltT extends A Bgt
-
-
23Parameterized Methods
- Consider the following class
- public class Foo
- //Foo is not parameterized
- public ltTgt T aMethod(T x)
- //will not compile without ltTgt
- //to indicate that this is a
- //parameterized method.
- return x
-
- public static void
- main(String args)
- Foo foo new Foo()
- int k foo.aMethod(5)
- String s foo.aMethod("abc")
-
-
- public class BarltTgt
- //Bar is parameterized
- public T aMethod(T x)
- return x
-
- public static void
- main(String args)
- BarltIntegergt bar
- new BarltIntegergt()
- int k bar.aMethod(5)
- String s bar.aMethod("abc")
- //Compilation error here
-
-
- Once BarltTgt object is fixed, we are locked to a
specific T.
24Use of Parameterized Methods
- Adding type safety to methods that operate on
different types - Return type dependent on input type
25Upper Bounded Wildcards in Parameterized Types
(1/2)
- We start to run into some new issues when we do
some things that seem normal. For instance, the
following seems reasonable - BoxltNumbergt numBox new BoxltIntegergt(31)
- Compiler comes back with an Incompatible Type
error message. This is because numBox can hold
only a Number object and nothing else, not even
an object of type Integer which is a subclass of
Number. - The type of numBox we desire is a Box of any
type which extends Number. - Boxlt? extends Numbergt numBox new
BoxltIntegergt(31)
26Upper Bounded Wildcards in Parameterized Types
(2/2)
- public class BoxltEgt
- public void copyFrom(BoxltEgt b)
- this.data b.getData()
-
-
- /
- /We have seen this earlier
- //We can rewrite copyFrom() so that it can take a
box - //that contains data that is a subclass of E and
- //store it to a BoxltEgt object
- public class BoxltEgt
- public void copyFrom(Boxlt? extends Egt b)
- this.data b.getData()//b.getData() is a
- //subclass of this.data
-
-
- lt? extends Egt is called upper bounded wildcard
because it defines a type that is bounded by the
superclass E.
27Lower Bounded Wildcards in Parameterized Types
(1/2)
- Suppose we want to write copyTo() that copies
data in the opposite direction of copyFrom(). - copyTo() copies data from the host object to the
given object. This can be done as - public void copyTo(BoxltEgt b)
- b.data this.getData()
-
- Above code is fine as long as b and the host are
boxes of exactly same type. But b could be a box
of an object that is a superclass of E.
28Lower Bounded Wildcards in Parameterized Types
(2/2)
- This can be expressed as
- public void copyTo(Boxlt? super Egt b)
- b.data this.getData()
- //b.data() is a superclass of this.data()
-
- lt? super Egt is called a lower bounded wildcard
because it defines a type that is bounded by the
subclass E.
29Unbounded Wildcards
- Use unbounded wildcards when any type parameter
works. - lt?gt is used to specify unbounded wildcards.
- The following are legal statements.
- Boxlt?gt b1 new BoxltIntegergt(31)
- Boxlt?gt b2 new BoxltStringgt(Hi)
- b1 b2
- Wildcard capture
- The compiler can figure out exactly what type b1
is above from the right hand side of the
assignments. - This capturing of type information means
- The type on the left hand doesnt need to be
specified. - The compiler can do additional type checks
because it knows the type of b1.
30Subclassing a generic class
- import java.awt.Colorpublic class Subclass
extends MyClassltColorgt - // You almost always need to supply a
constructor public Subclass(Color color)
super(color) - public static void main(String args)
Subclass sc new Subclass(Color.GREEN)
sc.print(Color.WHITE)
31Summary (1/2)
- It looks as if generics save you from having to
do casting, at the expense of more work in the
declarations - The real benefit is that they replace run-time
checks (and run-time errors) with compile-time
checks (and syntax errors) - This makes your program both more reliable and
easier to debug
32Summary (2/2)
- When you get an element from a collection, you
have to cast - Casting is a pain
- Casting is unsafe
- Casts may fail at runtime
- Wouldnt it be nice if you could tell the
compiler what type a collection holds? - Compiler could put in the casts for you
- Theyd be guaranteed to succeed
33Collection With Generic
- // Removes 4-letter words from c
- static void expurgate(CollectionltStringgt c)
- for (IteratorltStringgt i c.iterator()
i.hasNext() ) - if (i.next().length() 4)
- i.remove()
-
- Clearer and Safer
- No cast, no extra parentheses, no temporary
variables - Provides compile-time type checking
- Once compiled, typing information is erased
34Iterators
- An iterator gives you every element of a
collection, one at a time - The collection has a type iterator() factory
method to return a new iterator to return objects
of the given type - The method boolean hasNext() tells you if there
are more objects - The method type next() returns the next object
- The method void remove() deletes the last object
gotten - Example
- Iterator iter integerStack.iterator()while
(iter.hasNext()) System.out.println(iter.nex
t())
35The enhanced for loop
- Java 5s new for loop does the iterator work for
you - for (int n integerStack)
System.out.println(n)is the same (except for
the int declaration) asIterator iter
integerStack.iterator()while (iter.hasNext())
System.out.println(iter.next())
36Enhanced for loop
- Simplified iteration over collections
- Applying a method to each element in a Collection
Today - void cancelAll(Collection c)
- for (Iterator i c.iterator() i.hasNext() )
- TimerTask tt (TimerTask) i.next()
- tt.cancel()
-
-
37Collection With Enhanced for
- void cancelAll(Collection c)
- for (Object o c)
- ((TimerTask)o).cancel()
-
- Clearer and Safer
- No iterator-related clutter
- No possibility of using the wrong iterator
- No access to the loop variable
38Collection With Enhanced for
- Combined With Generics
- void cancelAll(CollectionltTimerTaskgt c)
- for (TimerTask task c)
- task.cancel()
-
- Much shorter, clearer and safer
- Code says exactly what it does
39It Works for Arrays, Too
- // Returns the sum of the elements of an array
- int sum ( int a )
- int result 0
- for (int val a)
- result val
- return result
-
- Eliminates array index rather than iterator
- Similar advantages
40The enhanced for loop
- The enhanced for loop can also be used for
arrays, and for any class you write that
implements the Iterator interface - The enhanced for loop is convenient but less
powerful than the old-style for loop, since it
just goes through every element in a forward
direction only
41Autoboxing/Unboxing
- You cant put an int into a collection
- Must use Integer instead
- Its a pain to convert back and forth
- Wouldnt it be nice if compiler did it for you?
42Autoboxing/Unboxing
- Before
- list.add(0, new Integer(42))
- int total (list.get(0)).intValue()
- Integer i new Integer (36)
- i new Integer ( i.intValue() )
- After
- list.add(0,42)
- int total list.get(0)
- Integer i new Integer (36)
- i
43Autoboxing/Unboxing
- Operations work on wrapper types
- Watch performance (based on unboxing)
- Be careful with equality (JVM instance recycling)
44Annotations
- Simple Use
- _at_Debug public void dumpState() ...
- Predefined annotations
- _at_Deprecated public void foo() ...
- _at_Override public void toString() ...
- _at_SuppressWarnings("unchecked","fallthrough")
- Custom declared using _at_interface
- _at_Retention(RUNTIME) _at_interface Debug
- boolean devbuild() default false
-
- Meta-annotations
- Target, Retention, Documented, and Inherited
45Annotation Reflection
- java.lang.reflect.AnnotatedElement interface is
implemented by all program element (Class,
Constructor, Field, ...) - public boolean isAnnotationPresent ( Class
annotationType ) - public Annotation getAnnotation ( Class
annotationType ) - Example
- Class c MyClass.class
- AnnotatedElement el c.getMethod("dumpState")
- Debug debug el.getAnnotation(Debug.class)
- boolean b debug.devbuild()
46Enumerated Types
- Standard approach int enum pattern
- public class Almanac
- public static final int SEASON_WINTER 0
- public static final int SEASON_SPRING 1
- public static final int SEASON_SUMMER 2
- public static final int SEASON_FALL 3
- ...
- // Remainder omitted
-
47Enumerated Types
- Example with Generics and enhanced for
- enum Suit clubs, diamonds, hearts, spades
- enum Rank deuce, three, four, five, six, seven,
- eight, nine, ten, jack, queen,
king, ace - ListltCardgt deck new ArrayListltCardgt()
- for (Suit suit Suit.VALUES)
- for (Rank rank Rank.VALUES)
- deck.add(new Card(suit, rank))
- Collections.shuffle(deck)
- Would require pages of code today!
48Enum Construct
- Compiler support for Typesafe Enum pattern
- Looks like traditional enum (C, C, Pascal)
- enum Season winter, spring, summer, fall
- But more powerful
- Can be used in switch statements
49Covariant return type
- Covariant return types let subclasses introduce
methods with the same names as superclass
methods, but with different return types - This lets developers type the return values for
specific implementations of derived types
50Example 1
- CloneDemo1 class
- class CloneDemo1 implements Cloneable
- int instanceField 3
- public static void main (String args)
- CloneDemo1 cd1 new CloneDemo1 ()
- CloneDemo1 x (CloneDemo1) cd1.clone ()
- System.out.println (x.instanceField)
-
- public Object clone ()
- return new CloneDemo1 ()
-
-
51Example 2
- CloneDemo2 class
- class CloneDemo2 implements Cloneable
- int instanceField 3
- public static void main (String args)
- CloneDemo2 cd2 new CloneDemo2 ()
- CloneDemo2 x cd2.clone ()
- System.out.println (x.instanceField)
-
- public CloneDemo2 clone ()
- return new CloneDemo2 ()
-
-
52Variable Arguments
- Prior to Java 1.5, passing a variable number of
arguments to a method required explict array
creation - You could create an array variable initialized to
the array and pass that variable to a method, as
in - String s "first", "second", "third"
printStrings (s) - Java 1.5 overcomes this problem by introducing
the new variable arguments language feature. - To use variable arguments, conform the parameter
list's rightmost parameter to the following
syntax - type ... variableName
53Example
- Avg class
- public class Avg
- public static void main (String args)
- System.out.println (avg ())
- System.out.println (avg (1, 2, 3))
-
- public static int avg (int ... integers)
- int sum 0 for (int i 0 i lt
integers.length i) - sum integers i
- return (integers.length ! 0) ? sum /
integers.length 0 -
-
54Variable Arguments
- During compilation, the Java compiler converts
the new parameter syntax to the old array
parameter syntax. - This means you can invoke printStrings() using
- printStrings (new String "first", "second",
"third" ) - or using
- printStrings ("first", "second", "third")
- However, if you declare printStrings() with the
old String s parameter syntax and then invoke
the method using printStrings ("first", "second",
"third"), the compiler reports an error