Come assegnare la dimensione di un array a run-time

Grazie al fatto che in Java un array non è altro che un oggetto, la sua dimensione è trattata come una proprietà dell’oggetto stesso e può dunque essere assegnata a run time. Questa caratteristica diviene di fondamentale importanza in tutti i casi in cui abbiamo bisogno di un array pe immagazzinare dei dati ma non possiamo conoscere la dimensione esatta prima di eseguire l’applicazione.

class TestArray {
  public static void main(String[] args) {

     int arraySize;
     try {
       if (args.length == 1)
         arraySize = Integer.parseInt(args[0]);
       else {
         System.err.println("Error: one argument expected");
         return;
       }
     } catch (NumberFormatException e) {
       // if user entered an invalid integer, exit the program.
       System.err.println("Error: Can't convert argument to integer");
       return;
     }
     // if arraySize is valid integer,
     // declare an array with size equals arraySize
     int intArray[] = new int[arraySize];

  }// end main()
}//end class TestArray

Come implementare una funzione di search&replace

Una classe semplice ed utile che consente di effettuare la classica funzione di “trova e sostituisci” all’interno di una stringa. Il metodo riportato sul CD accetta tre parametri: la stringa su cui effettuare la ricerca, la stringa di caratteri da cercare e la stringa di caratteri che andrà a sostituire quella originale.

private static String replace(String str, String pattern, String replace) {
int s = 0;
int e = 0;
StringBuffer result = new StringBuffer();
if(pattern == null || pattern.equals("")) return str;

while ((e = str.indexOf(pattern, s)) >= 0) {
result.append(str.substring(s, e));
result.append(replace);
s = e+pattern.length();}
result.append(str.substring(s));
return result.toString();
}

		
Come semplificare l’utilizzo degli switch

I programmatori C++ sono abituati ad analizzare gli argomenti passati dalla linea di comando attraverso i parametri “int argc” e “char *argv[]” della funzione main(). Un utilizzo del tutto simile dei parametri è possibile attuarlo in Java per impostare le opzioni di avvio di un’applicazione.
La classe presente sul CD rappresenta un utile framework su cui basare una propria implementazione delgi switch.

public class DemoSwitch {
	// Optional switch - default is false
	private boolean switch = false;

	// Execution starts here
	static public void main(String args[]) {
		int argc = args.length;		// Number of command line parameters
		int argv = 0;			// Index to first one
		String parameter;		// Expected parameter
	
		// Turn optional switch on if present in the command line    
		if (argc > 0 && (switch = args[argv].startsWith("-s"))) {
			// Skip for further processing
			--argc;
			++argv;
		}
    	
		// Continue processing command line parameters
		if (argc > 0) {
			parameter = args[argv];
		} else {
			System.err.println("Usage: java DemoSwitch [-s] ");
			return;
		}

	        // place useful code here...
    	}
}

Come caricare una classe da un file Jar

Una semplice, benchè completa, implementazione di un class loader per recuperare delle classi java da un file JAR durante l’esecuzione di un’applicazione. Il codice allegato, ampiamente commentato, non può essere facilmente personalizzato al fine di essere integrato nei nostri progetti. 

import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.util.jar.*;

public class JarClassLoader extends ClassLoader
{
  private Hashtable jarContents;

  /**
   * Creates a new JarClassLoader that will allow the loading
   * of classes stored in a jar file.
   *
   * @param jarFileName   the name of the jar file
   * @exception IOException   an error happened while reading
   * the contents of the jar file
   */
  public JarClassLoader(String jarFileName)
    throws IOException
  {
    // first get sizes of all files in the jar file
    Hashtable sizes = new Hashtable();

    ZipFile zf = new ZipFile(jarFileName);

    Enumeration e = zf.entries();
    while (e.hasMoreElements())
      {
	ZipEntry ze = (ZipEntry)e.nextElement();
	// make sure we have only slashes, we prefer unix, not windows
	sizes.put(ze.getName().replace('\\', '/'), 
		  new Integer((int)ze.getSize()));
      }

    zf.close();

    // second get contents of the jar file and place each
    // entry in a hashtable for later use
    jarContents = new Hashtable();

    JarInputStream jis = 
      new JarInputStream
	(new BufferedInputStream
	  (new FileInputStream(jarFileName)));

    JarEntry je;
    while ((je = jis.getNextJarEntry()) != null)
      {
	// make sure we have only slashes, we prefer unix, not windows
	String name = je.getName().replace('\\', '/');

	//System.err.println("JarClassLoader debug: loading " + name);

	// get entry size from the entry or from our hashtable
	int size;
	if ((size = (int)je.getSize()) < 0)
	  size = ((Integer)sizes.get(name)).intValue();

	// read the entry
	byte[] ba = new byte[size];
	int bytes_read = 0;
	while (bytes_read != size)
	  {
	    int r = jis.read(ba, bytes_read, size - bytes_read);
 	    if (r < 0)
	      break;
	    bytes_read += r;
	  }
	if (bytes_read != size)
	  throw new IOException("cannot read entry");
	
	jarContents.put(name, ba);
      }

    jis.close();
  }

  /**
   * Looks among the contents of the jar file (cached in memory)
   * and tries to find and define a class, given its name.
   *
   * @param className   the name of the class
   * @return   a Class object representing our class
   * @exception ClassNotFoundException   the jar file did not contain
   * a class named <code>className</code>
   */
  public Class findClass(String className)
    throws ClassNotFoundException
  {
    //System.err.println("JarClassLoader debug: finding " + className);

    // transform the name to a path
    String classPath = className.replace('.', '/') + ".class";

    byte[] classBytes = (byte[])jarContents.get(classPath);

    if (classBytes == null)
      throw new ClassNotFoundException();

    return defineClass(className, classBytes, 0, classBytes.length);
  }
}