I18N språkoberoende java -Duser.region=SE -Duser.language=sv cachet.ui.main java -Duser.region=US -Duser.language=en cachet.ui.main Fil: cachet/ui/lang.properties: ui.ok = Ok ui.cancel = Cancel Fil: cachet/ui/lang_sv.properties: ui.ok = Okej ui.cancel = Avbryt ResourceBundle rb = ResourceBundle.getBundle( cachet.ui.lang ); String okstring = rb.getstring( ui.ok ); JButton okbutton = new JButton(okString); ResourceBundle Läs javadoc för RB.getBundle() + alla getbundle-metoderna Bra om man enkelt kan se i resurs-filen var texten används: ui.menu.exit.name ui.menu.exit.mne Bättre än: exit=exit = Exit = x Färg Theme; färgläggning++ javax.swing.plaf.metal. DefaultMetalTheme Provkör och se kod: /it/sw/java/jdk/1.4.1/d emo/jfc/metalworks Ikoner URL u = Client.class.getResource("exit.gif"); JButton exitbutton = new JButton(new ImageIcon(u)); Förutsätter att exit.gif ligger brevid Client.class Alltså så måste man kopiera över sådan (runtime-)data efter kompilering Data ska ligga i src, eftersom det är den katalogen man sparar i CVS Javadoc http://java.sun.com/j2se/javadoc/faq/index.html Se exempel i källkoden; mappen src /it/sw/java/jdk/1.4.1 Meny http://java.sun.com/docs/books/tutorial/uis wing/components/menu.html 1
Log public class Main extends JFrame { /** Set level of what should be logged */ private static Logger log = Logger.geLogger(Main.class.getName()); static { log.setlevel(level.debug); // log.debug // log.info // log.warn // log.error Byte av logger Bättre konfiguration och läsbarhet Kräver ett paket log4j.jar i lib/ Kräver att man checkar in separat! Flytta lib/log4j.jar till annan katalog innan ni importerar koden i CVS Efter import flytta tillbaka filen och addera som en binär fil cvs add kb log4j.jar Kräver att man packar upp log4j.jar för att grupp.jar ska bli körbar! Se Makefile Collections Eckel: kapitel 11, Collections of Objects List - lagrar objekt i en ordning Set - lagrar unika objekt i en rymd Map - associerar ett värde till en nyckel Iterators Är en abstrakt nivå, där man inte behöver beskymra sig om den underliggande lagringen. Dvs, lagringen av data (t.ex. Person) kan ske i en array, hashtabell eller vektor men programmet behöver inte veta det! Iteratorer är lightweight och tar endast lite tid/kraft att skapa. Skapa en Iterator genom att göra dincollection.iterator() Hämta nästa element genom next() Se om det finns flera element genom hasnext() Iterator, exempel // så här gör man inte i Java! public Vector getnames0() { Person[] p = new Person[100];... // ej så bra heller public Vector getnames1() { Vector names = new Vector(); for (int i = 0; i < db.size(); i++) { String name = ((Person)db.elementAt(i)).getName(); names.add(name); return names; // YES public Vector getnames2(collection col) { Vector names = new Vector(); Iterator it = col.iterator(); while (it.hasnext()) { String name = ((Person)it.next()).getName(); names.add(name); return names; Map import java.util.*; class Counter { int i = 1; public String tostring() {return Integer.toString(i); class Statistics { public static void main(string[] args) { HashMap ht = new HashMap(); for (int i = 0; i < 10000; i++) { Integer r = new Integer((int)(Math.random() * 20)); if (ht.containskey(r)) ((Counter)ht.get(r)).i++; else ht.put(r, new Counter()); System.out.println(ht); 2
Collections public class Log { private static final int MAX = 1000; private Map map = new HashMap(); private List list = new Vector(); private Set set = new HashSet(); Log() { Random rnd = new Random(); for (int i = 0; i < 10; i++) { map.put(new Integer((int)(System.currentTimeMillis() % MAX)), "foo"); list.add(new Integer(rnd.nextInt(MAX))); set.add(new Integer(rnd.nextInt(MAX))); dump(map.keyset()); dump(list); dump(set); public void dump(collection c) { Iterator iterator = c.iterator(); System.out.println("\n" + "Collection: " + c); while (iterator.hasnext()) { System.out.println("" + iterator.next()); public static void main(string[] argv){ Log l = new Log(); SortedSet // create a sorted set SortedSet s = new TreeSet(); s.add("string1"); s.add("string2"); s.add("string3"); s.add("string4"); s.add("string5"); // get a subset of the set and display it Set sub = s.subset("a", "ZZZZZZ"); Iterator i = sub.iterator(); while (i.hasnext()) { System.out.println(i.next()); System.out.println(); // remove an element from the original set s.remove("string3"); // display the subset again i = sub.iterator(); while (i.hasnext()) { System.out.println(i.next()); Inner classes, kap. 8 public class Parcel1 { class Contents { private int i = 11; public int value() { return i; class Destination { private String label; Destination(String whereto) { label = whereto; String readlabel() { return label; public void ship(string dest) { Contents c = new Contents(); Destination d = new Destination(dest); System.out.println(d.readLabel()); public static void main(string[] args) { Parcel1 p = new Parcel1(); p.ship("tanzania"); Inner class public public class Bar { int k = i; void test() { A a = new A(); B b = new B(); Inner class public public class Bar { int k; public static void main(string args[]) { A a = new A(); A.B ab = a.new B(); // svårt exempel Inner classes, upcasting interface Sedlar { int getnoof100(); public class Bankomat { public Sedlar getsedelstatus() { return new S(); // we only have 500! private class S implements Sedlar { public int getnoof100() { return 0; public int get500() { return 42; 3
Inner classes, anonymous interface Sedlar { int getnoof100(); public class Bankomat { public Sedlar getsedelstatus() { return new Sedlar() { public int getnoof100(){return 0; ; ; Är det någon skillnad? interface Sedlar { int get100(); Sedlar s1 = new Sedlar() { public int get100() { return 0; ; class Foo implements Sedlar { public int get100() { return 0; Sedlar s2 = new Foo(); Scope for inner class If you re defining an anonymous inner class and want to use an object that s defined outside the anonymous inner class, the compiler requires that the argument reference be final, like the argument to dest( ). If you forget, you ll get a compile-time error message. En inre klass ser yttre omgivande klass (dess globala var.) variabler deklarerade som final Scope class Bank { void bills() { int k = 0; final f = 7; Sedlar s1 = new Sedlar() { // ser i & f, ej k public int get100() { return 0; ; // Bank ActionListener (AL) // KASS, ej OOP class Foo implements ActionListener { b.addactionlistener(this); // ugly! AL 2 // Nja, ibland ok oftast inte class Bar implements ActionListener { b.addactionlistener(new Bar()); 4
AL 2.1 class Bar implements ActionListener { Bar bar = new Bar(); JButton b1 = new JButton(); JButton b2 = new JButton(); b1.addactionlistener(bar); b2.addactionlistener(bar); // smart, delar action AL 3 // Bra! b.addactionlistener(new ActionListener() { ); AL 4 scope? private int k = 0; final m = 0; b.addactionlistener(new ActionListener() { // ser i och m, ej k ); 5