Skip to content

Lidt sjov med Java

Vi kender det alle - man bruger en finally fordi man er sikker på at den altid vil blive kørt... Men er vi nu også helt sikker på det? Nææh, men ideen er da god:
try {
    if (choice) {
        while (true) ;
    } else {
        System.exit(1);
    }
} finally {
    code.to.cleanup();
}

Bare fordi det står i bøgerne skal man ikke altid tro på det.

Null flag bug pattern

Nogle gange er man som Java-programmør "fristet" til at returnere en null-pointer når man arbejder med exceptions. Dette er ikke altid praktisk - faktisk er det skidt for ens kode, da kvaliteten af koden falder. At returnere en null-pointer (eller blot null) er også kendt som null flag bug pattern.

I stedet for at returnere null burde man overveje at smide en exception. Lad os tage et eksempel:
public Object next() {
    try {
        String result = internal.readLine();
        if (result == null)
            throw new NoSuchElementException();
        else
            return result;
        catch (IOException e)
            throw new NoSuchElementException(e.toString());
    }
}

(kode-stumpen er taget herfra)


Hvis det ikke er let at se hvorfor det er bedre at smide NoSuchElementException i stedet for at returnere null, vil jeg henlede læseren opmærksomhed på null flag bug pattern. Den er forholdsvis kort og overskue, og giver en let måde at øge kvaliteten af ens kode. 

Sjov med Java SE 6 Beta 2 på boxen

På min arbejdsplads bruger vi J2EE 1.3 - hvorfor er en lang historie jeg ikke vil bruge tid på her. Jeg kan blot sige at generics, som kom med i Java 1.5 ligger langt ude i fremtiden... Desværre.

Derfor kan man jo godt lege med Mustang, som er kodenavnet for Java 1.6. Specielt på desktoppen sker der en masse. En af tingene som kommer er splash screens (de små billeder/logoer som dukker op mens applikationen starter op).

Dette bliver meget let at lave i 1.6. Henter man Java SE 6 Beta 2 fra java.sun.com (Java Runtime Environment (JRE) 6 Beta 2 er også fint hvis man bare vil teste følgende) kan man køre dette:
java -splash:filnavn.gif SplashTest

hvor filnavn.gif er navnet på den gif-fil man vil bruge som splash screen. Mere skal der ikke til - og det må jo siges at være let.

Hvad så med selve koden? Tja, den er også ligetil. Man kunne f.eks. læse lidt på dokumentationen, men det er jo ikke sjovt - vel? Følgende kode opretter et object af SplashScreen og kalder getGraphics() derpå (billedet kommer ind som argument til programmet ved opstart eller man kan finde det i Manifest-filen (SplashScreen-Image: filnavn.gif)). Så gør man nogle småting ved billedet som at måle størrelsen osv., og til sidst tegner (/opdater) man så billedet bliver vist.
SplashScreen splash = SplashScreen.getSplashScreen();
Graphics2D g = (Graphics2D)splash.getGraphics();
Dimension size = splash.getDimension();
g.setComposite(AlphaComposite.Clear);
g.fillRect(0, 0, size.width, size.height);
g.setPaintMode();

Man kan bruge både Swing og AWT som man har lyst til. Der er sågar mulighed for at gøre noget ovenpå billedet mens programmet loader. Det kunne f.eks. være man vil have en procent-bar, som viser status - eller en anden ting. Ja, muligheder er der skam nok af :-)

"java.io.IOException: CreateProcess" fejl under Windows

Det er ikke fordi jeg ikke er glad for mit arbejde, jeg tror bare dette problem kunne være løst lettere (måske helt undgået) hvis jeg ikke skulle have siddet i Windows - men lad det nu ligge.

Dette problem har været oppe og vende en del gange på nettet. Især i forbindelse med Ant og J2EE. Det skal dog understreges at problemet ikke har noget med Windows eller Ant at gøre.
   [ejbc20] java.io.IOException: CreateProcess: javac -nowarn -classpath ...
   [ejbc20]       at java.lang.Win32Process.create(Native Method)
   [ejbc20]       at java.lang.Win32Process.(Win32Process.java:66)
   [ejbc20]       at java.lang.Runtime.execInternal(Native Method)
   [ejbc20]       at java.lang.Runtime.exec(Runtime.java:491)
   [ejbc20]       at java.lang.Runtime.exec(Runtime.java:457)
   [ejbc20]       at weblogic.utils.Executable.exec(Executable.java:133)
   [ejbc20]       at weblogic.utils.compiler.CompilerInvoker.compileMaybeExit(CompilerInvoker.java:572)
   [ejbc20]       at weblogic.utils.compiler.CompilerInvoker.compile(CompilerInvoker.java:373)
   [ejbc20]       at weblogic.ejb20.ejbc.EJBCompiler.doCompile(EJBCompiler.java:245)
   [ejbc20]       at weblogic.ejbc20.runBody(ejbc20.java:470)
   [ejbc20]       at weblogic.utils.compiler.Tool.run(Tool.java:126)
   [ejbc20]       at weblogic.ejbc.main(ejbc.java:29)
   [ejbc20] Exec failed .. exiting

Ved første øjekast ligner problemet noget med ejbc20-tasken, som Ant kalder. Efter en ½ dags søgning fandt jeg frem til dette link: http://marc.theaimsgroup.com
Som man kan læse her har det noget med ens path at gøre, og dette er noget crap. Fejlen er nemlig så simpel som at man skal tilføje sin sti til der hvor man har installeret JDK'en.

Men hvorfor nu det? Jeg kan jo køre programmer skrevet i Java. Ja, men jeg kan ikke compile nye. Jeg kan altså i en console (som vist nok hedder prompt i Windows) ikke køre code>javac men godt java. Problemet er så at ens sti peger på den JRE, man har fået installeret. Og en JRE indeholder ikke værktøj til at compile med (javac), hvilket jo også gør fejlen lidt mere logisk.

Summa summarum er, at får du denne fejl skal du checke dine paths.

Badness i projektet?

Det er sådan når man arbejder med LaTeX, så får man nogle gange noget som hedder badness 10000 f.eks. Vores projekt er lige pt. på hele 224.338. Hvordan har jeg så regnet det ud? Tjo, lad os antage at LaTeX smider en log som hedder Master.log. Denne kigger man bare i, lægger tallene sammen og vupti. Men jeg er doven, så jeg bruger dette script:
#!/bin/sh
#
#Author: Peter Sönder
#Created: 2006-05-30
#
#Badness factor in LaTeX

#Name of tmp file
FILE=BADNESS

#Colors are pretty
reset="\E[00;38m"
color="\E[01;33m"

if ( test -r Master.log ); then
#Saving badness level
sed -n '/badness/p' Master.log | sed 's/\\vbox (badness / /g;s/Underfull / /g;s/\\hbox (badness / /' | sed 's/^[ \t]*//' | sed 's/)//' | awk '{print $1}' > $FILE

#Check if exists, then open $FILE and add values
if ( test -r BADNESS ); then
echo -e $color"Badness factor:"$reset
awk 'BEGIN{s=0}{s+=$1}END{print s}' $FILE

#Deleting the files after use
rm -f $FILE
fi
else echo "Badness is 0?!? Master.log not present!";
fi

Det er sikkert ikke det pæneste kode jeg har lavet, men jeg kan fortælle at det virker efter hensigten. Ren bash-slam-kode :-) Du kan også hente det her.

PVision har fået en hjemmeside

Hvad sker der lige - jeg har lige lavet en hjemmeside for PVision. Du kan se den her eller her.

Samtidig har jeg lavet en ny version, som kan hentes her. Der er tale om en mindre "bug-fix". Ud over at have lavet en opdatering har jeg frigivet sourcen under GPL. Den kan derfor hentes her.

Tilbage har jeg kun at sige god fornøjelse :-)

PVision - version 0.4

Jeg har før sagt at jeg nogle gange keder mig - og det sker nu stadig. Faktisk så meget at jeg kan sige at PVision er kommet i version 0.4 og en version 0.5 skulle snart være på vej (måske?).

Om ikke alt, så kan du hente den her: pv-0.4.jar

Denne gang er der komme splash-screen og startbilled med. Omg, hvad sker der? Tja, ikke andet end et par patte og numser hænger på din skærm :-)

Lidt brugbar information vil jeg da også lige remse op (igen). Det kræver at du har Java installeret. Hvis du bare skal køre den gøres det således:
java -jar pv-0.4.jar

Sidder du bag en proxy (som jeg gør herude på uni) gøres det sådan her:
java -Dhttp.proxyHost=HOST -Dhttp.proxyPort=PORT -jar pv-0.4.jar


Genvejsknapper er:
alt + u for refresh (hent ny)
alt + p for patter
alt + n for numser
alt + r for random skift mellem de to ovenstående
alt + q for quit (som om det skulle være nødvendigt...)

Jar-filer og billeder

Denne lille "feature" har jeg ledt længe efter - og nu har jeg fundet den. Har man et billed som man bruger i sin applikation og gerne vil have den pakket ind i en jar-fil, er det jo ligetil. Når man så henviser til den skal man ikke gøre som man normalt gør:
String image = "./billeder/billed.jpg";
ImageIcon icon = new ImageIcon (image);

Man skal i stedet for bruge URL til at henvise med. Her kommer man så frem til dette:
URL image = this.getClass().getResource("/billeder/billed.jpg");
ImageIcon icon = new ImageIcon(image);

Her er det også værd at bemærke at man bare henviser med / og ikke ./ samt at det er blevet pakket ind i en URL (som bliver lavet uden new-operatoren). Det er måske meget ligetil hvis man er vant til den slags, men jeg brugte vist lidt for længe på det... :-)

PVision - version 0.1 (sweet vision)

Nogle gange keder man sige - andre gange mere end normalt. Det er også sket lidt for mig (som vel sker for alle). Jeg har i min "spild-tid" lavet PVision (pv.jar), som er kodet i Java.

Der er lige lidt information som kan være brugbart. Hvis du bare skal køre den gøres det således:
java -jar pv.jar

Sidder du bag en proxy (som jeg gør herude på uni) gøres det sådan her:
java -Dhttp.proxyHost=HOST -Dhttp.proxyPort=PORT -jar pv.jar

hvor HOST er URL'en på din proxy og PORT er - ja, gæt.

Genvejsknapper er:
alt + r for refresh (hent ny)
alt + q for quit


Første udgave er døbt sweet vision - måske også sidste udgave (who knows?)

Arbejde er nu skønt

Det er nu altid godt at have noget at give sig til. Jeg har længe haft lyst til at lave en todo-liste. Jeg har haft flere overvejelser om hvordan det skulle laves, og nu har jeg taget hul på denne - i form af en gang php. Siden kan ses her, og jeg forventer at der stille og roligt vil blive arbejdet med den. Planerne er store, men dog overskuelige - jeg har bare lige en masse jeg skal nå, men det er altid godt med lidt at hoppe tilbage på.

Jeg vil ikke sige for meget om hvad der kommer - så bliver jeg bare skuffet hvis jeg ikke får det lavet :-)

Lidt om Java annotations

Hvad er der så godt ved Java 1.5 annotations? Der er jo nogle regler man skal overholde - og de skal overholdes. Annotations er meget begrænset. Faktisk til at skulle være af typen primitiv, String, Class, enum, annotation (selv) og arrays af en af de forgående typer. Faktisk kan default værdien ikke være null, hvilket kan være irriterende (måske?). Det vil sige at en default værdi (her String) kan være "", hvilket er mere tidskrævende at checke for end hvis den kunne være null. En anden ting er at man så ikke ved om det var input "" eller om det var den satte default værdi. Dette er man så også nødt til at checke for hvis man skal særbehandle default værdien.

Så må man jo bare håbe at det kan bruges til projektet :-)

Trimme en string i perl

Det er faktisk meget let. Antag at vi har en string, $string, og vil fjerne efterfølgende mellemrum. Dette kan vi let gøre med dette:

$string =~ s/^\s+//;
$string =~ s/\s+$//;

Man kan også lave en funktion som returnerer den nye værdi. Igen bruger vi $string som eksempel:

$string = trim($string);

sub trim {
    my $string = shift;
    for ($string) {
       s/^\s+//;
       s/\s+$//;
    }
    return $string;
}

Der er ingen som siger at det det behøves være svært at kode. Nogle gange er det bare ikke lige så logisk :-)