3.2. System un programmu parametri

Ievads

Mērķi

  • Uzrakstīt programmu, kura lieto komandrindas argumentus un sistēmas īpašības
  • Raksturot novecinātas klases un izskaidrot, kā migrēt kodu no JDK 1.0 vai JDK 1.1 uz Java 2 SDK

Ievadjautājumi

  • Bieži gadās, ka daži programmai vajadzīgi parametri stila prasību un vieglākas instalējamības dēļ netiek "iešūti" programmas tekstā (piemēram failu vārdi vai datubāzes nosaukums). Kā programma var šādiem elementiem piekļūt izpildes laikā
  • Citi ārēji resursi, piemēram, valodu resursi arī jāuzdod izpildes laikā

Komandrindas argumenti

  • Katra Javas aplikācija var izmantot komandrindas argumentus
  • Stringu argumentus norāda komandrindā, kura palaiž Javas interpretatoru pēc klases nosaukuma:
java TestArgs arg1 arg2 "another arg"

Katrs komandrindas arguments tiek ielikts args masīvā, kuru kā argumentu saņem statiskā main metode:

public class TestArgs {
    public static void main(String[] args) { ... }
}

Komandrindas argumenti

1  public class TestArgs {
2    public static void main(String[] args) {
3      for ( int i = 0; i < args.length; i++ ) {
4        System.out.println("args[" + i + "] is '" + args[i] + "'");
5      }
6    }
7  }
java TestArgs arg1 arg2 "another arg"

Šāds ir programmas izvads:

args[0] is 'arg1'
args[1] is 'arg2'
args[2] is 'another arg'

Sistēmas īpašības

  • Sistēmas īpašības (system properties) Javā aizstāj jēdzienu vides mainīgie (environment variables), jo pēdējais ir platformatkarīgs jēdziens.
  • Statiskā metode System.getProperties atgriež Properties objektu
  • Metode getProperty atgriež String mainīgo, kurš glabā nosauktās īpašības vārdu.
  • Izmantojiet JVM komandrindas -D opciju, lai iekļautu jaunu īpašību.

Klase Properties

  • Properties klase implementē attēlojumu (asociatīvu masīvu) no vārdiem uz vērtībām (no String uz String).
  • Metode propertyNames atgriež uzskaitījumu - Enumeration ar visiem īpašību nosaukumiem
  • Metode getProperty atgriež String, kurš ir attiecīgās metodes vārds
  • Īpašību sarakstu var rakstīt/lasīt failā, izmantojot metodes load un store.

Sistēmas īpašības

1  import java.util.Properties;
2  import java.util.Enumeration;
3  
4  public class TestProperties {
5    public static void main(String[] args) {
6      Properties props = System.getProperties();
7      Enumeration prop_names = props.propertyNames();
8  
9      while ( prop_names.hasMoreElements() ) {
10        String prop_name = (String) prop_names.nextElement();
11        String property = props.getProperty(prop_name);
12        System.out.println("property '" + prop_name
13            + "' is '" + property + "'");
14      }
15    }
16  }
java -DmyProp=theValue TestProperties

Izvade izskatās apmēram šādi:

property 'java.runtime.name' is 'Java(TM) 2 Runtime Environment, Standard Edition'
property 'sun.boot.library.path' is 'c:\j2sdk1.4.0\jre\bin'
property 'java.vm.version' is '1.4.0-b92'
property 'java.vm.vendor' is 'Sun Microsystems Inc.'
property 'java.vendor.url' is 'http://java.sun.com/'
property 'path.separator' is ';'
property 'java.vm.name' is 'Java HotSpot(TM) Client VM'
property 'file.encoding.pkg' is 'sun.io'
property 'user.country' is 'US'
property 'sun.os.patch.level' is 'Service Pack 3'
property 'java.vm.specification.name' is 'Java Virtual Machine Specification'
property 'user.dir' is 'c:\javakursi\exercise31'
property 'java.runtime.version' is '1.4.0-b92'
property 'java.awt.graphicsenv' is 'sun.awt.Win32GraphicsEnvironment'
property 'java.endorsed.dirs' is 'c:\j2sdk1.4.0\jre\lib\endorsed'
property 'os.arch' is 'x86'
property 'java.io.tmpdir' is 'C:\DOCUME~1\kalvis\LOCALS~1\Temp\'
property 'line.separator' is '
'
property 'java.vm.specification.vendor' is 'Sun Microsystems Inc.'
property 'user.variant' is ''
property 'os.name' is 'Windows 2000'
property 'sun.java2d.fontpath' is ''
property 'myProp' is 'val'
property 'java.library.path' is 'c:\j2sdk1.4.0\bin'
property 'java.specification.name' is 'Java Platform API Specification'
property 'java.class.version' is '48.0'
property 'java.util.prefs.PreferencesFactory' is 'java.util.prefs.WindowsPreferencesFactory'
property 'os.version' is '5.0'
property 'user.home' is 'C:\Documents and Settings\kalvis'
property 'user.timezone' is ''
property 'java.awt.printerjob' is 'sun.awt.windows.WPrinterJob'
property 'file.encoding' is 'Cp1252'
property 'java.specification.version' is '1.4'
property 'user.name' is 'kalvis'
property 'java.class.path' is '.'
property 'java.vm.specification.version' is '1.0'
property 'sun.arch.data.model' is '32'
property 'java.home' is 'c:\j2sdk1.4.0\jre'
property 'java.specification.vendor' is 'Sun Microsystems Inc.'
property 'user.language' is 'en'
property 'awt.toolkit' is 'sun.awt.windows.WToolkit'
property 'java.vm.info' is 'mixed mode'
property 'java.version' is '1.4.0'
property 'java.ext.dirs' is 'c:\j2sdk1.4.0\jre\lib\ext'
property 'sun.boot.class.path' is 'c:\j2sdk1.4.0\jre\lib\rt.jar;...'
property 'java.vendor' is 'Sun Microsystems Inc.'
property 'file.separator' is '\'
property 'java.vendor.url.bug' is 'http://java.sun.com/cgi-bin/bugreport.cgi'
property 'sun.cpu.endian' is 'little'
property 'sun.io.unicode.encoding' is 'UnicodeLittle'
property 'sun.cpu.isalist' is 'pentium i486 i386'

Metode System.exit(int)

Ja aplikācijai nodots nepareizs parametru skaits, mēdz lietot šādu konstrukciju:

    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Lietojums: java Fibonaci <n>"); 
            System.exit(0); 
        }
                ...
        }
  • Metode beidz ne vien konkrēto aplikāciju, bet visu Javas interpretatoru (Jāuzmanās, ja to lieto daudzpavedienu programmās)
  • Metodei var būt spēkā drošības ierobežojumi (nevar izsaukt apletos, utml.)
  • Šo metodi ir ļoti nevēlami lietot komponentēm, kuras darbojas lielākā ietvarā (piemēram, JBoss aplikāciju serverī). Jebkurā pavedienā izpildot šo komandu, JVM mašīna bez brīdinājuma apstājas, neatbrīvo resursus un var saglabāt pastāvīgo atmiņu nekonsistentā stāvoklī. JVM pasaulē tas ir līdzvērtīgi datora fiziskai izslēgšanai.

Metode System.currentTimeMillis()

  • Laiks "long" formātā, kas pagājis kopš 1970.g. janvāra 1. datuma plkst. 00:00:00.
  • Bieži lieto empīriskai ātrdarbības pārbaudei

Metode System.gc()

  • System.gc() programmētājs piedāvā JVM veikt drazu savākšanu - piemēram, pirms liela aprēķina uzsākšanas vai arī tad, ja sagaidāma sistēmas dīkstāve.
  • Drazu savākšanas noklusētais mehānisms parasti ir pietiekami labs tipiskās situācijās (piemēram, ir paredzēts, ka liela daļa nelielu objektu ir ar ļoti īsu dzīves ilgumu). Sk. http://java.sun.com/docs/hotspot/gc/ - "Tuning Garbage Collection".
  • Ja drazu objektiem ir metodes "finalize", tad tās arī var izsaukt pēc programmētāja iniciatīvas ar System.runFinalization().

Klase Runtime

Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac Hello.java");
InputStream stderr = proc.getErrorStream();
...
int exitVal = proc.waitFor();

Metode Runtime.exec(String) ļauj darbināt konkrētās platformas komandas. Jāievēro vairākas lietas:

  • Runtime.exec() izsaukums ir asinhrons - JVM negaida, kamēr sistēmas komanda izpildīsies. Lai to panāktu, jālieto Process.waitFor() metode, kura atgriež izejas vērtību
  • Runtime.exec() nav ekvivalenta komandrindai - daudzas "shell"-ā interpretējamas komandas ("dir", "copy" utml.), kurām neatbilst nekas izpildāms, ir atklāti jādarbina kopā ar interpretatoru "cmd.exe" vai "command.com"
  • Lietotājs ir atbildīgs par plūsmu apstrādi - dažreiz jānolasa gan Process.getErrorStream(), gan Process.getOutputStream()
  • Ārējā procesa izvades plūsma ir iegūstama ar metodi Process.getInputStream() - tā ir truba no ārējā procesa izvades plūsmas uz mūsu programmas ievades plūsmu

Sk. http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

Novecošana (deprecation)

  • Novecošana deklarē klases, atribūtus, metodes, konstruktorus, utml. par novecojušiem (tie gan turpina normāli funkcionēt, bet rada kompilācijas brīdinājumus).
  • Novecojušās deklarācijas tiek aizstātas ar metodēm, kuras standarta veidotāji rekomendē.
  • Kad notiek koda migrācija, kompilējiet to ar -deprecation karodziņu
javac -deprecation MyFile.java

Novecošanas piemērs

JDK 1.1 programma izskatās sekojoši:

1  package myutilities;
2  
3  import java.util.*;
4  import java.text.*;
5  
6  public final class DateConverter {
7    private static final String DAY_OF_THE_WEEK [] =
8      {"Sunday", "Monday", "Tuesday", "Wednesday",
9      "Thursday", "Friday", "Saturday"};
10  
11    public static String getDayOfWeek (String theDate) {
12      int month, day, year;
13  
14      StringTokenizer st = new StringTokenizer (theDate, "/");
15  
16      month = Integer.parseInt(st.nextToken ());
17      day = Integer.parseInt(st.nextToken());
18      year = Integer.parseInt(st.nextToken());
19      Date d = new Date (year, month, day);
20  
21      return (DAY_OF_THE_WEEK[d.getDay()]);
22    }
23  }

Kompilējot iepriekšējo kodu ar -deprecation karodziņu, iegūstam:

javac -deprecation DateConverter.java
DateConverter.java:19: warning: Date(int,int,int) in java.util.Date has been deprecated
Date d = new Date (year, month, day);
^
DateConverter.java:21: warning: getDay() in java.util.Date has been deprecated
return (DAY_OF_THE_WEEK[d.getDay()]);
^
2 warnings

Uzlabots piemērs

Java 2 versijā šis pats kods izskatās šādi:

1  package myutilities;
2  
3  import java.util.*;
4  import java.text.*;
5  
6  public final class DateConverter {
7    private static String day_Of_The_Week[] =
8        {"Sunday", "Monday", "Tuesday", "Wednesday",
9          "Thursday", "Friday", "Saturday"};
10  
11    public static String getDayOfWeek (String theDate) {
12      Date d = null;
13      SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy");
14  
15      try {
16        d = sdf.parse (theDate);
17      } catch (ParseException e) {
18        System.out.println (e);
19        e.printStackTrace();
20      }
21  
22      // Create a GregorianCalendar object
23      Calendar c =
24          new GregorianCalendar(
25              TimeZone.getTimeZone("EST"),Locale.US);
26      c.setTime (d);
27  
28      return(
29          day_Of_The_Week[(c.get(Calendar.DAY_OF_WEEK)-1)]);
30    }
31  }

Jautājumi paškontrolei

  • Uzrakstīt programmu, kura izmanto komandrindas argumentus un sistēmas īpašības
  • Identificēt nožēlotas klases un izskaidrot, kā migrēt no JDK1.0 vai JDK1.1. uz Java 2 SDK.