Lecture 15, Encapsulation, packages and inner classes.

Reading

JP chap 9.4, 9.7, 9.11, 9.12, 17, 18.

Slide handouts 3.

Study Guide

There are one major topic for this lecture, which is the management of classes in Java. As an aside, we will refresh the notion of scope rules, in particular access modifiers.

There are three main class structuring mechanisms in Java: Packages, Files, and Inner classes. We shall examine them all in quite some detail.

Most programming languages depend on the underlying file system to store both source files, and compiled code (in Java that is .java and .class files). Thus there is a need for the compiler to know where such files are found, as well as it is necessary for the virtual machine to know where to find the class files. In most java systems, this is what the classpath variable is used for. The value of the classpath variable in a DOS prompt window can be changed using "set classpath=xxx". To see the current value of the classpath variable, use "set classpath", that is without an equals sign.

Inner classes are typically used for specifying how a program should react to user input when writing user interfaces using the class libraries awt or swing. The exercise below, also uses this as an example. However, inner classes are not defined to be used specifically for this. Rather it is the awt and swing libraries which has been designed specifically to utilize inner classes. Inner classes are described in JP 9.11 and 9.12. An inner class is really very much like a normal class, the only trick is that there are more than one this. The this of the Inner class, and the this of the enclosing class. If one has three classes nested inside each other, there will be tree this references. 

It is possible to write more than one class in a file. Both as top level an as inner classes. The rules are in sec. 17, first paragraph. Exercise 2.2 below is about this. 

Encapsulation is the technical term for hiding the internals of a class from the clients of a class. There are two types of clients. Those that use the class, and those that specialize it (extends it). To control the access to members (fields, methods, and inner classes) there are four modifiers, private, protected, default and public (see section 9.7). The top level classes (those that are not inner), can be declared as either public or default (see section 9.4).

Exercises

Exercise 1

Consider the following three classes, two of which has the same name and must be placed in different directories as shown.

file: .\GreetingTest.java
class GreetingTest {

	public static void main(String[] args){
		String message = greet.Greetings.getGreeting();
		System.out.println(message);
	}
}
file: .\hellopath\greet\Greetings.java
package greet;

public class Greetings {
	public static String getGreeting(){
		return "Hello dear chap";
	}
}
file: .\yopath\greet\Greetings.java

 

package greet;

public class Greetings {
	public static String getGreeting(){
		return "Yo man";
	}
}
 

This exercise will require that you compile and execute from a DOS prompt, using javac and java commands. You need to make the directories hellopath and yopath, and each of these should have a directory named greet. Each of the questions below assume that your DOS prompt has current directory in the directory containing the GreetingTest.java.

  1. Place the above source files as shown in the file names above. Set the classpath variable to ".;.\hellopath". Compile the files. The two Greetings classes should be compiled first. Compiling the files as "javac .\hellopath\greet\Greetings.java" will work fine. (No answer to this is needed, just do it).
  2. Execute the GreetingsTest. What is written?
  3. Change the classpath to ".;.\yopath". Execute the GreetingsTest again. What is written?.
  4. Change the classpath to ".;.\yopath;.\hellopath". Execute the GreetingsTest again. What is written?.
  5. Try to compile all three files at the same time, as "javac GreetingTest.java helloPath\greet\Greetings.java yoPath\greet\Greetings.java". You get an error! why?
  6. The class GreetingsTest requires that one of the two Greetings classes have been compiled already (or is compiled at the same time). Why does it not matter which of them is used?

Exercise 2 (Hand-In)

This exercise is about inner classes. We take the outset in the class DotFrame listed below (it can also be found in the classes for lecture 3). When the program runs, a window appears on the screen, and a black dot is drawn under the mouse then the mouse is clicked. The program can be terminated by clicking in the close button on the window.

package dk.itu.oop.lecture3;

import javax.swing.JFrame;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class DotFrame extends JFrame {
	
	public static void main(String[] args){
		final DotFrame df = new DotFrame();
		df.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e){
				df.getGraphics().fillOval(e.getX()-5,e.getY()-5,10,10);
			}
		});
	}
		
		
	public DotFrame(){
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(400, 400);
		setTitle("DotFrame");
		setVisible(true);
	}
}

Notice, the exercises below requires some rewriting of the DotFrame itself, not only the inner class. It is part of the exercise to figure out which parts.

The idea of the exercise is to give you an understanding of what information is available to an inner class, and what is therefore necessary to provide explicitly if the class is not inner. First step is to make the class a named inner class, rather than an anonymous. Second step is to declare it outside the DotFrame class.

  1. Rewrite the class so that the anonymous inner class in the main method become a named inner class in the DotFrame. The name of the class should be MakeDotOnMouseClick. If you need, you can look in section 11.7 (last two lines) to see how one creates instances of inner classes.
  2. Rewrite the class so that the MakeDotOnMouseClick is not an inner class, but is non-public class in the same file as DotFrame.  A hint is that inner classes has an implicit reference to its enclosing object. When the class is mover out of DotFrame, you must make this reference explicit.
  3. In the file above (before it was rewritten) the df variable is declared final. 

Exercise 3 (voluntary).

If you are not 100% stable in the difference between static and non-static fields, this exercise might be something for you. Static is not really the topic of this lecture, but it seemed we lacked an exercise about this. The exercise starts out with the following program, which is in error.

public class Bike {
	private String serialNo; // of the form axb889<serialNo>
	private int size; // wheel size in inches
	private String color; 
	
	public String getSerialNo(){ return serialNo; }
	public int getSize(){ return size; }
	public String color() { return color; }
	
	public static void main(String[] args){
		serialNo = "axb88910001";
		size = 27; 
		color = "Red";
	}
}
  1. The compiler complains "Bike.java:13: non-static variable serialNo cannot be referenced from a static context"! why?
  2. Add a constructor to the class, and change the class so that the main method no longer gives an error. Create an object of type Bike in the main method, and print out the fields using the getter methods.
  3. Add a private static field to the class "int nextSerialNumber"!. Give it the value 10001 in the main method. Why can you access this field from main, when you could not access serialNo?
  4. What section in Java Precisely explains this?
  5. Use this field in the constructor so that each Bike created gets a unique serialNo.
  6. Create a new class BikeTest, which just contain the main method from Bike. At the same time, remove it from Bike. You can no longer set the nextSerialNumber from the main method, because it is private. Write a setter method void setNextSerialNumber(int n) which can be used from the main method.
  7. This method will work both if it is static and non-static. Why?