Kan nu ersättas med:
List<Integer> myIntList = new LinkedList<Integer>();
myIntList.add(new Integer(0));
Integer x = myIntList.iterator().next();
Fördelen är att samlingen nu är typsäker. Vinsten
med generics är alltså att programmet blir typsäkert,
punkt. Det är garanterat att
if
your entire application has been compiled without unchecked warnings
using javac -source 1.5, it is type safe.
2.1.2 Arkitektur
Det finns två centrala punkter som förklarar det mesta av
hur generics funkar i java:
2.1.3 Mer syntax
Detta är inte allt, se länken nedan för mer information.
- <?> Betyder
vilken typ som helst.
- Dessa tre är lämpliga när T bara returneras:
- <? extends T>
betyder vilken typ som helst som också är av typen T, dvs T eller någon subklass
till den.
- <? extends MyClass>
betyder vilken typ som helst som också är av typen MyClass, dvs MyClass eller någon
subklass till den.
- <T extends MyClass>
betyder vilken typ som helst som också är av typen MyClass, dvs MyClass eller någon
subklass till den.
- Dessa tre är lämpliga när T bara är en inparameter:
- <? super T>
betyder T eller
någon superklass till den.
- <? super MyClass>
betyder MyClass eller
någon superklass till den.
- <T super MyClass>
betyder MyClass eller
någon superklass till den.
- Typvariabler får inte användas i deklarationer av
arrayer.
- Om A är en
subklass till B och G är en generisk
deklaration gäller inte
att G<A> är en
subtyp till G<B>.
- Kom ihåg att kompilatorn kräver typsäkerhet.
2.1.4 Exempel
Ett program som använder typsäkra samlingar,
CollectionTest.java.
Ett exempel på deklaration av typvariabler. Programmet visar
också i vilken mån
Class.newInstance()
kan användas typsäkert,
ObjectFactory.java.
2.1.5 Slutsats
Det är mycket lämpligt att använda generics för att
göra ett program typsäkert.
2.1.6 Mer om generics
Detta är en tämligen utförlig men ändå tydlig
redogörelse:
http://java.sun.com/j2se/5.0/docs/guide/language/generics.html
2.2 Ny typ av for-loop (for-each)
En ny typ av for-loop som kan användas på alla samlingar som
implementerar
java.lang.Iterable.
Nedanstående loop
for (Iterator<MyClass> i = aCollection.iterator(); i.hasNext();) {
i.next().doSomething();
}
kan ersättas med:
for (MyClass mc : aCollection) { //Pronounced "for each MyClass c i aCollection".
mc.doSomething();
}
När det gäller arrayer kan
for (int i=0; i<anArray.length; i++) {
anArray[i].doSomething();
}
ersättas med
for (TypeInArray tia : anArray) {
tia.doSomething();
}
Här är ett program som illustrerar det senaste exemplet,
ForEachTest.java.
2.3 Autoboxing
Det finns två nya typer av conversions: boxing conversion och
unboxing conversion. Dessa omvandlar (vid exekvering) mellan primitiva
typer och deras wrapper-klasser. Det innebär att boxing och
unboxing kan ske automatiskt, vilket kallas autoboxing respektive
autounboxing. Här kommer ett litet exempel,
AutoboxTest.java. Notera att
detta enbart är en konvertering, det finns fortfarande både
primitiva variabler och referensvariabler. Här kommer några
klurigheter:
- Två olika primitiva variabler är identiska om de
har samma värde medans två olika referensvariabler är
identiska om de refererar samma objekt.
- Autounboxing av null resulterar i ett NullPointerException.
- Det kostar exekveringstid att autoboxa och autounboxa.
Denna funktionalitet är främst avsedd för att hantera
primitiva typer i samlingar. Exemplat ovan är alltså inte
särskilt bra.
2.4 Uppräkningsbara typer (enumerations)
Detta följer i stort Item 21 i Bloch:
Effective Java
Programming Language
Guide. Uppräkningsbara typer deklareras så här:
enum MyType {VALUE1, VALUE2, VALUE3}.
Detta leder till att kompilatorn skapar en subklass till
java.lang.Enum som heter
MyType och har tre statiska
fält av typen
MyType.
Dessa innehåller tre olika objekt som heter
VALUE1,
VALUE2 och
VALUE3. Objekten har en
toString() som skriver ut deras
namn. De har också lämpliga implementationer av
equals() och
hashCode(). De är
Serializable,
Comparable och
final. De är inte
Clonable. Klassen har två
statiska metoder,
valueOf()
som tar en typ och ett namn och returnerar objektet av den typen med
det namnet samt
values()
som returnerar en array med alla typens värden i den ordning de
är deklarerade. Klassen
EnumTest.java
använder den uppräkningsbara typen
Fruit.java.
Objekten som skapas kan ha konstruktorer och metoder, se
ListMonths.java och
Month.java.
Klienterna till en uppräkningsbar typ påverkas inte om
värdena byter plats, om nya värden läggs till eller om
värden tas bort (förutsatt att de inte använder de
borttagna värdena). Serialiserade objekt av den
uppräkningsbara typen fungerar även de bra även om
sådana förändringar görs.
Det går utmärkt att använda collection-API:et men det
finns två nya samlingar som är snabbare för
uppräkningsbara typer,
java.util.EnumSet
och
java.util.EnumMap. Alla
element i
EnumSet och
alla nycklar i
EnumMap
måste vara av samma uppräkningsbara typ.
2.5 Varargs
Det sista argumentet i en metods parameterlista kan deklareras så
här
method(int... lastArg).
Det innebär att den aktuella parametern vid anropet kan
utgöras av ett godtyckligt antal värden eller av en array. I
metoden är parametern alltid en array med så många
element som det skickades värden till metoden. Här är
ett exempel,
VarargsTest.java.
2.6 Static Import
Det går att importera statiska deklarationer från en klass.
Det görs så här,
import
static java.lang.Math.PI, eller så här,
import static java.lang.Math.*.
De importerade statiska deklarationerna kan sedan användas utan
att kvalificeras med klassnamnet.
Jag är frestad att säga att det här aldrig ska
användas eftersom det smutsar ner klassens namnrymd och gör
det svårt för den som läser koden att förstå
var en viss deklaration finns. Möjligtvis kan det vara bra om
någon enstaka statisk deklaration från en annan klass
används väldigt ofta. Det är i alla fall bättre
än antimönstret Constant Interface eftersom de importerade
deklarationerna inte blir en del av klassens publika gränssnitt.
2.7 Annotations
Det går att defineiera egna annotations (dvs godtycklig
information) och sedan koppla dem till vilken deklaration som helst
(klass, interface, metod...). Syftet är att de ska användas
som metadata om deklarationen, dvs för att ange fakta om den.
Metadatat kan sedan anändas av något verktyg för att
processa den annoterade deklarationen på något sätt.
Ett möjligt användningsområde vore att annotera
EJB-implementationer. Sedan skulle ett verktyg kunna processa
källkoden för EJB:n och generera deployment descriptorn,
remote/local interfacet och home interfacet. Det finns ett verktyg
(apt) som kan läsa annoterade filer. Åtgärdena som ska
vidtas måste dock programmeras i Java-klasser, vilka sedan kan
anropas av apt.
3 Förändringar i java.lang och java.util som inte
nämnts ovan
3.1 ProcessBuilder
En ny klass som ska användas i stället för Runtime.exec
för att starta subprocesser. En skillnad är att
ProcessBuilder kan modifiera subprocessens operativsystemsvariabler.
3.2 Formattering i c-stil
Klassen
java.util.Formatter
kan hantera formattering av samma typ som i
printf i C. I
java.io.PrintWriter finns
metoder (
format() och
printf()) som formatterar
på det sätt som anges i
java.util.Format.
3.3 java.util.Scanner
Denna klass kan scanna en text och (bla) dela upp den i tokens samt
konvertera tokens i den till prmitiva typer. Indata är någon
form av ström. En intressant detalj är att dess metoder
endast kastar runtime exceptions. Det krävs alltså inte
några
catch-satser
för att använda den. Klassen kan hantera regexps.
3.4 Trådhantering
3.4.1 Utility-klasser för trådprogrammering
Paketen
java.util.concurrent,
java.util.concurrent.atomic
och
java.util.concurrent.locks
innehåller en massa bra-att-ha-klasser för
trådprogrammering. Exempel på vad som finns är
trådpol, samlingar (både nya definitioner och nya
implementationer av gamla klasser som är snabbare i
flertrådade program), atomära variabler (som är
snabbare än att använda
synchronized),
lås, klassiska synkroniseringsklasser som tex semaforer och mutex
samt tidtagning med (ungefär) en nanosekunds upplösning.
3.4.2 klassen java.lang.Thread
Några av ändringarna i denna klass:
- Det finns en uppräkningsbar typ, Thread.State som hanterar
trådars tillstånd.
- Det går att hämta stacktrace:ar programmatiskt.
- Det går att sova mindre än en ms.
3.5 Några ändringar i collection-api:et som inte
nämnts ovan
- En ny typ av samling, kö, som definieras av interfacet java.util.Queue.
- Nya implementationer av List
och Set (CopyOnWriteArrayList och CopyOnWriteArraySet) som
är snabbare när det sker många fler läsningar
än skrivningar).
- Metoden Collections.checkedCollectiontype() returnerar
en samling som kastar ett undantag så snart ett objekt av fel typ
placeras i den. Det kan vara lämpligt om samlingen hanteras av ett
API vi inte har kontroll över eller om det (vid debuggning)
är oklart när elementet av fel typ läggs in.
- Klassen java.util.Arrays
har metoder hashCode()
och toString() som
hanterar alla element i en array. Det går nu lätt att tex
skriva ut alla element i en array med anropet System.out.println(Arrays.toString(a)).
I en multidimensionell array blir det System.out.println(Arrays.deepToString(a)).
3.6 Utökning av bytekoden vid runtime
Paketet java.lang.instrument innehåller ett API för att
lägga till bytekod i befintliga class-filer. Det är avsett
att användas av verktyg.
4. java.net
Inte särskilt mycket, men det som finns handlar bla om cookies,
proxys och IPv6.
5. Säkerhets-api:erna
Främst för Kerberos, SSL, kryptering och Simple
Authentication and Security Layer (SASL).
6. Monitoring och Management
JMX ingår numera i J2SE (i paketen
javax.management.
*). Dessutom finns, i paketet
java.lang.management, en
definition av ett api som bygger på jmx och kan användas
för att övervaka en javamotor. Det finns även diverse
kommandoradsverktyg för övervakning. En implementation av
nyss nämnda api finns i
com.sun.management.
7. RMI
Bland annat kan stubbar skapas automatiskt, utan att
rmic behöver användas
av utvecklaren. Det är även lättare än tidigare att
använda rmi över ssl.
8. Databashantering
Nytt i JDBC 3.0 är bla annat att nedanstående fem
implementationer av
RowSet
ingår.
JdbcRowSet
- used to encapsulate a result set or a
driver
that is implemented to use JDBC technology
CachedRowSet
- disconnects from its data source and
operates
independently except when it is getting data from the data source or
writing
modified data back to the data source. This makes it a lightweight
container
for as much data as it can store in memory.
FilteredRowSet
- extends CachedRowSet
and is used
to get a subset of data
JoinRowSet
- extends CachedRowSet
and
is used
to get an SQL JOIN
of data from multiple RowSet
objects
WebRowSet
- extends CachedRowSet
and
is used
for XML data. It describes tabular components in XML using a
standardized XML
schema.
9. Java2D
Bland annat stöd för hårdvaruaccelererad OpenGL.
10. Image I/O
Bland annat kan bmp och wbmp både läsas och skrivas nu.
11. AWT
Bland annat en hel del förbättringar och bugfixar av DnD och
data transfer.
12. Swing
Bland annat detta:
- Redan från 1.4.2 fanns två nya look and feel: XP och
GTK.
- Ny default look and feel, ocean.
- En ny look and feel, synth, som är "skinnable" och kan
konfigureras mha en fil, helt utan programmatiska ingrepp.
- Popup-menyer kan visas utan händelsehantering.
- JTable kan skrivas ut.
- JFrame.add() kan
användas i stället för JFrame.getContentPane().add().
13. Java Plug-in och Java Web Start
Bland annat hanterar de ett nytt format av jar-filer, Pack200, som (i
bästa fall) reducerar filerna till 1/8 av en jar-fils storlek.