Java Article 17 - Passing Values and Data Validation

In Article 16 we looked at naming swing components. Today I will show one way to use component names coupled with reference passing to save yourself some typing and make your program a bit more elegant. I am also going to touch a bit on data validation.

In computer science, data validation is the process of checking that data used by a program meets the specific requirements of that program (e.g. data type, minimum or maximum character lengths, or the presence or absence of certain characters).

A simple example would be a program that accepts a person's name, like in a contact list, or in a program that manages a company's customer information. One way the company can improve the accuracy and quality of their customer database would be to ensure that every customer entered into their database has a contact name included in the data input into the system. Also you would want to alert the user with an error message if they forgot to enter the customer name. This is one simple and classic example of validation.

We are going to simulate this situation with a swing interface class called PassReference which will pass a reference to one of its textfields to another class called CheckReference. CheckReference will then check (validate) that there is text present in this field before accepting the name. CheckReference will also display a message stating weather the data was accepted or not.

From an engineering standpoint this is a form of poka yoke, also referred to as mistake proofing, or the less politically correct term idiot proofing. If you were the sales manager responsible for this customer database you would not want entries in your system without customer names. Put another way, you want to ensure the people using the program are forced to include a name in the customer record.

We accomplish our data validation here by passing a reference to an object (our textfield) as an argument. In a method call passing a reference has the same syntax as passing a value:

This calls a method that receives the number 8 as a parameter and does something with it.

int myInt = 8;
doSomethingWithThisInt(myInt);

public void doSomethingWithThisInt(int myInt)
{
	newNumber = myInt * 20;
}

Passing an object is done similarly:

JTextField textfield = new JTextField();
doSomethingWithThisObject(textfield);

public void doSomethingWithThisObject (JTextField textfield) 
{
	System.out.print(textfield.getClass())
	textfield.setText("Hello!");
}

In Java "textfield" is a value that represtes a location in memory, so you are not passing the actual object nor are you making a copy of the object. You are passing instructions on where the data contained in the object can be found - its memory address. The address may resemble something like "24de7d." People with a background in C and Objective-C call this "passing a reference." Once a method has a value representing a reference to the location in memory where textfield is, it can then modify textfield's public properties, like its text or background color. This is a very powerful feature.

The term "passing by reference" can mean different things to people with experience in older languages like C and C++, becasue the definition of the word "reference" is different. According to the Java Specification, Java is officially a "pass by value" language. When you pass an object in Java, like a JTextField, you are not passing the actual object. You are also not passing a copy of the object. You are passing a value that represents a location in memory where the object is stored. In C and Objective-C this is called a "pointer" and is considered "passing by reference." This is also referred to as a shallow copy vs a deep copy.

In C++ there are both references and pointers, and they are two different things. The difference in terminolgy between languages casues a lot of confusion. People can be reluctant to abandon the terminology they are familiar with becasue it took considersaable brain power to understand the concept to begin with and they don't want to disrupt the delicate equasion in thier heads. For me it is really hard not to use the words "reference" and "pointer" here.

So in Java, when working with programmers with differnt backgrounds, it may be safer to say "passing a value representing a location in memory." Some people like to call this "calling by object" or "calling by object sharing" but these terms are not universally used.

Passing object values is a powerful tool. This concept requires some effort to understand. Don't expect to read a couple of paragraphs about them and have a firm grasp of how they work and what they can be used for. You need to dive in and experiment with them.

Here is a simple example on how pass by value works with a primitive type like an int:

public class PassValue 
{
	static int myInt = 8;
	
	
	public static void main(String[] args)
	{
		doSomethingWithThisInt(myInt);
		System.out.println("Notice that after the call to doSomethingWithThisInt, myInt has not changed: "
				+ myInt);
		System.out.println("This is because doSomethingWithThisInt() is only working with a value, and not the data contained within the memory location named myInt");
		
		 // The value for myInt is not changed in the method below.
		 
	
	}
	

	static public void doSomethingWithThisInt(int incommingInt)
	{
		System.out.println("Received value: " + incommingInt);
		incommingInt = 0; // we reassign incommingInt
		System.out.println("Reassigned value: " + incommingInt);
	}

}

Similar to primitive types, when you pass an object in Java, like a JTextField, you are not passing the actual object. You are also not passing a copy of the object. You are passing a value (remember Java is a pass by value language) that represents a location in memory where the object is stored. In other languages this is called a pointer, because it points to a location in memory. Put another way it is like an address to a house, not the actual house.

Passing an object can be seen in action along with data validation in today's main example:

Here is the Main class that is the interface:


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class PassValueLocation extends JFrame implements ActionListener 
{
		JPanel panel = new JPanel();
		JTextArea labelOne = new JTextArea("Customer name:");
		JButton button1 = new JButton("Validate");
		static JTextField textField1 =  new JTextField(10);
		
		//Constructor
		public PassValueLocation()
		{
			panel.add(labelOne);
			panel.add(textField1);
			panel.add(button1);
		
			button1.setActionCommand("button1Click");
			button1.addActionListener(this);
			//We name the textfield for use later
			textField1.setName("The Customer Name");
			
			add(panel);
		}

		public void actionPerformed(ActionEvent e)
		{
			
			String cmd = e.getActionCommand();	
			
			if (cmd == "button1Click")
			{
				CheckReference checkReference = new CheckReference();
				//here we pass a reference to textField1
				checkReference.checkTextField(textField1);
			}
		}
		
		public static void main(String[] args)
		{
			PassValueLocation passValueLocation = new PassValueLocation();
			passValueLocation.setSize(250, 100);
			
			//this centers our window
			Dimension dimensions = Toolkit.getDefaultToolkit().getScreenSize();
			int w = passValueLocation.getSize().width;
		    int h = passValueLocation.getSize().height;
		    int x = (dimensions.width-w)/2;
		    int y = (dimensions.height-h)/2;
		    passValueLocation.setLocation(x,y);
		    
			passValueLocation.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			passValueLocation.setVisible(true);
			
			//This puts the cursor in the textfield
			textField1.requestFocus();
		}
}

Here is the second class (sometimes called a helper class in java) that does the data validation:


import java.awt.Color;
import javax.swing.*;

public class CheckReference 
{
	//We use allcaps to denote a constant
	final static int STRING_LENGTH = 0;
	
//	  A constant is a variable that we don't intend to change
//	  The keyword final prevents STRING_LENGTH from being changed
//	  Elsewhere in our program.
	 
	
	public void checkTextField(JTextField incommingTextFieldAdressValue)
	{
		
		
		 // Now that we have a value that represents a location in memory of our JTextField object
		//we can get all kinds of information about it.
		//(This is called a reference or pointer in C and Objective-C)
		
		System.out.println(incommingTextFieldAdressValue);
		System.out.println(incommingTextFieldAdressValue.getClass());
		
		//Here we get the current text length from the textfield
		if (incommingTextFieldAdressValue.getText().length() 
				== STRING_LENGTH)
		{	
			
			 // here we use a JOptionPane to show a pop-up message
			 
			JOptionPane.showMessageDialog(null, 
					incommingTextFieldAdressValue.getName() 
					+  " must be > " + STRING_LENGTH 
					+ " characters.","Data Entry Error"
					,JOptionPane.WARNING_MESSAGE);
			
			// Now that we have an address to the location in memory where textField1 is we can 
			// change its properties
			 
			incommingTextFieldAdressValue.setBackground(Color.red);
			incommingTextFieldAdressValue.requestFocus();
		}

		else
		{
			
			 // You can do some fancy stuff with your message 
			 // dialogs using the reference to textfield1
			
			JOptionPane.showMessageDialog(null, 
					incommingTextFieldAdressValue.getName()
					+": \""
					+ incommingTextFieldAdressValue.getText()
					+ "\""
					+ " is validated and accepted",
					"Validation Complete"
					,JOptionPane.INFORMATION_MESSAGE);
			
			incommingTextFieldAdressValue.setBackground(Color.white);
		}
		
	}
}

When you launch this application try leaving the text field blank and see what happens. Next add some text to the textfield and see how it is accepted by the checkReference object.