Banner
Introduction to Java


Introduction to Java for ABM

Spring 2012

Psychology 120


Helpful Links

Introduction to Programming Using Java, Sixth Edition (online)

Introduction to Java by Jan Tobochnik and Harvey Gould (online)

A Quick, Painless Introduction to the Java Programming Language by Norman Matloff (online)

Oracle Java (Lots of technical stuff about Java)

Eclipse Documentation (online)

The Java Tutorials (online)


Problem Solving

During the 70s and 80s, software developers introduced a new style of programming, which was based in part on Herbert Simon’s idea that to solve a complex problem efficiently, it should be broken down into solvable subproblems and so on. Structured programming attempts to this: solve complex programming problems by breaking them down into subproblems. If these subproblems are still too abstract or complex, they are decomposed into sub-subproblems and so on until problems are reached that can be solved and verified. This approach to programming is top down: start with a general specification of a problem and continue to decompose it into subproblems until each is solvable. The combined components then solve the original complex problem.

Issues with Top-Down Solving

Top-down problem solving is a powerful method for solving problems. We use it all the time in experimental research. Once we have specified a theoretical hypothesis, then we have to do experiments that test it. We start by specifying what types of experiments could test the hypothesis and then we do the experiment by breaking it down into subproblems to be solved and implemented. Likewise, this approach to problem solving works for building computer programs as well, but it does run into several issues:

1. It focuses too much on the development of algorithms for solving programming problems and not enough on the data that the larger program will be using and manipulating. This is especially important for ABM where the exchange of information among agents (i.e., data) is crucial.

2. Structured programming doesn’t provide us with a systematic way to reuse code. Why keep building something again and again?

3. Especially for ABM, we want to model individuals in the world as agents that do things in an environment. It would be nice therefore to have a programming language that makes it natural to define objects and solve programing problems for active agents/objects.

4. It would really be nice if once we have defined an object, even abstractly, that we could some how build onto that object. For example, suppose we defined an object called person. It would save time and make logical sense if we could simply add to the definition of person (i.e., the class of objects that are persons) additional characteristics that define male and female.

Beginning in the mid to late 1980s, software engineers started to do just that: they created object-oriented versions of commonly used programming languages (e.g., to the programming language C, object-oriented extensions such C++ and Objective C were developed).

Java is an object-oriented programming language that is a relative of C programming languages, sharing many syntactical characteristics in common with C languages.

Object-Oriented Programming and Java

The central idea in object-oriented programming in Java is to define modules, which are objects that contain information (i.e., data) and have methods for interacting with other modules (i.e., objects). Java makes it relatively easy to define agents and various other objects (often referred to as tools) for creating agent-based simulations. Once we have defined an object then we can create one or more instances of it.

To illustrate these ideas, we are going to build our first agent (i.e., define an object in java). It will utter random phrases. We will name this agent class Talker and then make an instance of it.

Talker will be a class of agents, but to instantiate it, it must exist in an environment. To make a virtual talking agent, we will also need to create an Environment object for our talker to talk in.

Eclipse

Before we can get started, we need a programing environment in which we can define our objects and make them do things. We will use the open-source Java environment Eclipse. You can download Eclipse on your own computer if you like for free.

Step 1: We must start by making a new project in Eclipse. To do this, we need to go to the file menu and select “new project”. A dialog box will appear. We need to simply type in the name we want to give to our project, say “talkers”, select the separate source and object files option and finish.

Step 2: Now that we have a project, we need to create packages that hold the objects we define. A project can have many packages and we will talk more about packages later. For now let’s create a package called “talker”. To do so, click open the package “talkers”, highlight “src” (i.e., the folder that holds the packages of code), and choose “package” from the file menu.

Step 3: Next, we start to define our Talker and our Environment objects. In Java, to define an object, we make a class for it. Once defined, we can make as many instances of the class as we want. Let’s start by making the two classes and then filling out the details later. To do this, select the package “talker” in “talkers”. From the “file menu” again choose new, but this time choose “class”. In the dialog box, type in Talker (by convention, we define classes with the first letter capitalized), then finish. Repeat the procedure but this time type in the name Environment and click on the “main method” option.

For the Talker class we should have a file that looks like this:

package talker;

public class Talker {

}

For the Environment class we should have a file that looks like this:

package talker;

public class Environment {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
}

Step 4: Now, let’s define the Talker class. Our talker is not too bright, it just randomly says things. So, let’s give it some random things to say and a method for saying them randomly. What it can say is its data and its mechanism for saying it things is its method(s). Each of these are fields in the class we are defining.

The first thing we need to do is to specify a data structure that holds the phrases and words that talker can say. To do this, we are going to use the MASON project, which already has a number of classes that we can use to help us build ABMs. To do this, we need to connect our project with MASON.

From the file menu, look down until you see “properties” select it and a dialog box will appear. Choose “Java Build Path” and under the “source” tab choose “Add…”. Check MASON. Click “OK” and “OK” again and now our project “knows” about MASON.

Step 5: The data structure we will add is a class called Bag from MASON. So, let’s add Bag to our class. Our Talker class should now look like this:


package talker;

public class Talker {
	
	Bag phrases = new Bag();

}

Notice, however, that there are red marks, which indicate that there are errors. The problem is that Java does not know where the class Bag is in MASON. To correct this, we need to tell it where it is. If we click on the red marker, options will appear. Choose “import sim.util.Bag”. Our class should now look like this:

package talker;

import sim.util.Bag; //this tells our class where the class Bag can
                     //be found

public class Talker {
	
	Bag phrases = new Bag();

}

Step 6: Let’s give our talker something to say and let’s do so at the time it is instantiated. To do this, we will define a constructor method, which when a new instance is created, adds the phrases. For example, you might add the following phrases (or any phrases you like):

package talker;

import sim.util.Bag;

public class Talker {
	
	Bag phrases = new Bag();
	
	public Talker () {
		phrases.add("Hello World");
		phrases.add("Where am I?");
		phrases.add("What is your name?");
		phrases.add("My name is talker.");
		phrases.add("Where are you from?");
		phrases.add("What class is this?");
		phrases.add("It sure is a nice day today!");
		phrases.add("I'm hungry!");
		phrases.add("I live in a virtual world");
	}
}

Step 7: We also need to define a method for our talker to say something randomly. To do this, we will have to generate a random number and print out the selected phrase. Here, we will use predefined classes in Java called “Math” and “System.” They contain static methods that can be use without instantiating the classes. I’ll explain static methods and data later. This is a method that will do the trick:

package talker;

import sim.util.Bag;

public class Talker {
	
	Bag phrases = new Bag();
	
	public Talker () {
		phrases.add("Hello World");
		phrases.add("Where am I?");
		phrases.add("What is your name?");
		phrases.add("My name is talker.");
		phrases.add("Where are you from?");
		phrases.add("What class is this?");
		phrases.add("It sure is a nice day today!");
		phrases.add("I'm hungry!");
		phrases.add("I live in a virtual world");
	}
	
	public void saySomethingStupid(){
		int i = (int)(Math.random()*(double)phrases.numObjs);
		//Here we declared an integer i
		//Math.random() generates a pseudo random number in 
                //the range 0 to 1
		//phrases.numObjects is the number of phrases in phrases
		//Since Math.random() is a real number, we have to 
                //convert phrases.numObjs
		//to a real number by placing (double) before it.
		//We then multiply Math.random()*(double)phrases.numObjs
		//and finally convert the result back to an integer that
                //ranges from 0 to phrases.numObjs - 1. 
		
		System.out.println(phrases.get(i));
		//The class "System" contains an object "out" with the method "println", which 
		//prints the content of the bag.
	}
}

Step 8: Now, let’s create a Talker in the environment and have it say something.

package talker;

public class Environment {

	Talker t;  // This is a variable that will be an
	          // instantiation of a talker
	
	public void start(int steps){ //this is a method in the 
		//environment to start things happening
		t = new Talker();  
                //here is where we make our talker
		for(int i=0;i<steps;i++){  
                     //this is a "for loop", this will be
		     //explained later, but it repeats a 
		     //for a given number of steps
		t.saySomethingStupid(); 
                   //Here is where the waker says something stupid
		}
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) { 
         //this is the main method
		//Every Java program has to have at least one.
		Environment e = new Environment(); 
                 //Here it creates an environment
		e.start(10); 
               //the environment starts and runs for 10 steps
	}
}

Step 9: Let’s run it!

More on Classes

Variables and Their Types

As we just saw, we define the objects that will interact in our simulation by defining classes. Once a class is completely defined, then it can be instantiated many times. For example, we could define a class called “Person” and then make 1000 persons that interact in our simulation.

Classes have members that occupy fields in a class. A class can have indefinitely many fields and a field is either occupied by variables or methods. When defining classes, I prefer to place the variables first and methods second in a class, but Java does not care how they are ordered. Let’s look at some of the types of variables we can define in a class.

Suppose we define a class called “MyClass”:

public class MyClass {
	int n; //a declared integer
	int m = 1; //a declared integer with a value assigned to it
	double x; //declared a double variable, for storing real numbers
	double pi = Math.PI; //a double variable pi, with an approximation of
	                     //pi assigned to it, 3.141592654
	boolean b; //declaration of a boolean variable
	boolean xyz = true; //declaration of a boolean variable assigned the value true
	boolean there_is_a_Martian_in_this_room = false; 
	//it is often a good idea to make variable names that 
	//have meaning to you.
	String s; //declaration of a string variable
	String myName = "Jeff Schank"; //declaration of a string variable and
	//assignment of a string.
	
	//We can also define array variables that can contain values for the type of
	//array.
	
	int[] integerArray; //declaration of an integer array variable
	int[] myNumbers = new int[100]; //declaration of an integer array with
	//100 slots for integers.  But, no integers have been specified for the array
	int[] one_to_ten = {1,2,3,4,5,6,7,8,9,10}; // declaration of an integer array,
	//creation of an array with 10 slots, with values 1 to 10 assigned to the slots.
}

Access Modifiers

Variables (and methods) can have specifications how they are accessed. There are four types of access modifiers: no explicit modifier, public, private, and protected.

public modifier—the field is accessible from all classes.

private modifier—the field is accessible only within its own class.

protected modifier—the field is accessible within its own class, package, and subclass.

no explicit modifier—the field is accessible within its own class and package

Methods

Methods are the other general type of elements that can belong to classes in addition to variable. Methods are how objects interact with other object and, in general, do things internally and externally. Methods have at least five features:

1. Modifiers—such as public, private, and others listed above.

2. The return type—the data type of the value returned by the method, or void if the method does not return a value.

3. The method name—the rules for field names apply to method names as well, but the convention is a little different.

4. The parameter list in parenthesis—a comma-delimited list of input parameters, preceded by their data types, enclosed by parentheses, (). If there are no parameters, you must use empty parentheses.

5. The method body, enclosed between braces—the method’s code, including the declaration of local variables, goes here.

For example, consider a method for generating a pseudo random integer in the range 0 to n:

       protected int randomInteger(int range){
		int i = (int)(Math.random()*(double)range);
		return i;
	}

We can add this to our Talker agent above and add new method that uses it public void saySomethingStupid2():

package talker;

import sim.util.Bag;

public class Talker {
	
	Bag phrases = new Bag();
	
	public Talker () {
		phrases.add("Hello World");
		phrases.add("Where am I?");
		phrases.add("What is your name?");
		phrases.add("My name is talker.");
		phrases.add("Where are you from?");
		phrases.add("What class is this?");
		phrases.add("It sure is a nice day today!");
		phrases.add("I'm hungry!");
		phrases.add("I live in a virtual world");
	}
	
	public void saySomethingStupid(){
		int i = (int)(Math.random()*(double)phrases.numObjs);
		//Here we declared an integer i
		//Math.random() generates a pseudo random number in the range 0 to 1
		//phrases.numObjects  is the number of phrases in phrases
		//Since Math.random() is a real number, we have to convert phrases.numObjs
		//to a real number by placing (double) before it.
		//We then multiple Math.random()*(double)phrases.numObjs
		//And finally convert the result back to an integer that ranges from 0 to phrases.numObjs - 1 
		
		System.out.println(phrases.get(i));
		//The class "System" contains an object "out" with the method "println", which 
		//prints the content of the bag.
	}
	
	protected int randomInteger(int range){
		int i = (int)(Math.random()*(double)range);
		return i;
	}
	
	public void saySomethingStupid2(){
		int i = randomInteger(phrases.numObjs);
		//Here we declared an integer i
		//but now the method "randomInteger" does all the work
		
		System.out.println(phrases.get(i));
		//The class "System" contains an object "out" with the method "println", which 
		//prints the content of the bag.
	}
}