You are on page 1of 36

I/O Streams and Files

// Example for File I/O

import java.lang.System;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;

public class FileIOApp {


public static void main ( String [] arg0 ) throws IOException {
FileOutputStream outStream =
new FileOutputStream ("test.txt");
String s = "This is a test.";
for ( int i =0; i <s.length(); ++i )
outStream.write ( s.charAt(i) );
outStream.close();

FileInputStream inStream =
new FileInputStream ("test.txt");
int inBytes = inStream.available();
System.out.println ( "The inStream has " + inBytes + " bytes
available.");
byte inBuf[]=new byte[inBytes];
int bytesRead = inStream.read ( inBuf, 0, inBytes);
System.out.println ( bytesRead + " bytes were read.");
System.out.println ("They are: " + new String (inBuf) );
inStream.close();
File f = new File ("test.txt");
f.delete();
}
}
In the above program:
The FileOutputStream constructor creates an output stream for the
file “test.txt”. The file is automatically created in the current working
directory. Then the program writes the string "This is a test." to the
output file stream. The output stream is closed to make sure that all
data are written to the file.
The file is then reopened as an input file by creating an object of
class FileInputStream. Method avaiable() is used to determine the
number of available bytes in the file and method read (-,-,-) is used to
read these bytes into a byte array. The input stream is closed and
then a File object is created to provide access to the file. The program
then uses the method delete( ) to delete the file.
The program's output is given by:
The inStream has 15 bytes available.
15 bytes were read.
They are: This is a test.

Chapter 11 Exception Handling


An exception is an event that occurs during the execution of a
program and makes program continuation impossible or undesirable.
Examples of exception are: integer division by zero, array reference
with index out of bounds, loading a file that cannot be found on disk,
printer out of paper in an attempt to print, and so on.
If any of the code in a method throws an exception of a type other
than the ones named in the catch clauses, Java exits this method
immediately. (Hopefully, one of its callers has already coded a catch
clause for that type). Any exception that occurred during the execution
of doFileProcessing() or displayResults() would be caught and
processed. If an exception occurred during doFileProcessing(),
displayResults() would never get called, and execution would proceed
directly to the catch block.
The finally statement can be used in conjunction with a try block.
Basically, it ensures that if
an exception occurs, any cleanup work that is necessary is taken care of.
code in a finally
statement is guaranteed to run no matter whether an exception occurs or
not.
Example:
Graphics g = image.getGraphics();
try
{
// section 1
code that might throw exceptions
// section 2
}
catch ( IOException e )
{
// section 3
show error dialog
// section 4
}
finally
{
// section 5
g.dispose();
}
// section 6
Scenarios:
1. The code throws no exceptions(Execution path: section 1, 2, 5, 6 )
2. The code throws an exception that is caught in a catch clause, in our
case, an IOException. In this scenario, execution passes through points
1, 3, 4, 5, and 6. If the catch clause throws an exception, then the
exception is thrown back to he caller of this method, and execution
passes through points 1, 3, and 5 only (no 6).
3. The code throws an exception that is not caught in any catch clause.
(Execution path: 1 and 5 only, no 6)
Exception (all checked, except for RuntimeException)
RuntimeException (unchecked) Other subclasses of
Exception, all checked.
ArithmeticException IOException (checked)
IndexOutOfBoundsException
FileNotFoundException
ArrayIndexOutOfBoundsException
MalformedURLException
IllegalArgumentException InterruptedException
(checked)
NumberFormatException

The argument to throw can be any expression that returns an


object of a subclass of Throwable. You usually use new and a
constructor to create the object. To throw an exception, we find an
appropriate exception class in the class library if there is one.
Otherwise, we define our own class by extending the Throwable class
or one of its subclasses. We then make an object of that class and
throw it.
Users of a method need to know the exceptions it might throw so
they can be prepared to handle them.Java requires that a method
definition includes a list of the checked exceptions the method throws
in the header.
import java.lang.*;
import java.io.*;
public class example2
{ public static void main(String[] args) throws IOException
{
System.out.println("Within main\n");
test1();
}
public static void test1() throws IOException
{
try {
System.out.println("Within test1\n");
test2();
}
catch( RuntimeException e ) {
System.out.println("Caught RuntimeException\n");
}
}
public static void test2() throws IOException
// it can throw spuerclass for checking but in test1 and main need to
check spuerclass {
try {
System.out.println("Within test2\n");
throw new IOException();
}
catch ( NumberFormatException e ){
System.out.println("Caught NumberFormatException\n");
}
}
}
Case 1: A checked exception
public void openFile()
try {
infile = new BufferedReader ( new
FileReader ("myFile.txt") );
}
catch ( FileNotFoundException e) {
errorField.setText ("Missing file, please try again!");
}
// The FileReader constructor throws a checked exception which we
must deal with. We can either use try-catch, or specify that the
method which contains the above statement can throw the exception.
The second approach is to pass the exception up to the invoking
method as follows:
public void openFile() throws IOException {
infile = new BufferedReader ( new
FileReader ( "myFile.txt") );
}
Case 2: An unchecked exception
Because NumberFormatException (a subclass of RuntimeException)
is unchecked, the compiler will not force us to check it. We can catch it
or ignore it (but there is no advantage to pass it upward).
Case 3: A RuntimeException
If we want the origin of the exception to be indicated so that it can
be tracked down and fixed, the easy way is to ignore the exception.
(It's ok, because the compiler does not check for this kind of
exception).
Programming pitfalls:
• Failing to acknowledge a checked exception will produce a
compilation error. You must either catch an exception locally, or
specify that your method throws it.
• Do not micromanage exceptions, i.e., do not put each line or small
section of code in a separate try-catch block.
• Do not squelch exceptions, i.e., if something goes wrong, do not
shut up that error by doing
try
{ doing something wrong … }
catch ( Throwable e ) {}
 Allowing an exception to be thrown from a method, when it can
sensibly be handled locally, dramatically slows down your code.

Chapter 9 User Interface Components with Swing


The flow layout manager is the default layout manager for a panel.
Flow layout manager: lines the components horizontally until there
is no more room and then starts a new row of components.
e.g.,
setLayout (new FlowLayout (FlowLayout.LEFT));
// align to the left; default = center alignment
(The method setLayout is defined in java.awt.Container.)
Border Layout (p.371) - using the border layout manager, you can
choose to place the component in the center, north, south, east, or
west of the container. It is the default layout manager of the content
pane of every JFrame.
e.g.,
//To change the layout manager of a
// JPanel object.
class MyPanel extends JPanel {
setLayout ( new BorderLayout() );
...
add ( yellowbutton, BorderLayout.SOUTH);
}
The Grid Layout Manager. All rows and columns have the same size.
public GridLayout(int rows, int cols)
public GridLayout(int rows, int cols, int hgap, int vgap) // hgap, vgap:
horizontal and vertical gap
panel.setLayout( new GridLayout(5,4) );
JLabel
JLabel’s are components that hold text. They do not react to user
input.
JLabel label = new JLabel( “User name: “, SwingConstants.RIGHT );
panel.add( label );

Text Input
JTextField (text fields): single line of text
JTextArea (text areas): multiple lines of text
Both inherit from the abstract class JTextComponent.
For text fields (p.378):
JPanel p = new JPanel ();
JTextField tf = new JTextField ("Default input", 20);
// Adds a text field and initializes its content;
sets the width equal to 20 columns.
p.add (tf);
tf.setText ( "HKBU");
//Changes the content of the text field.
tf.setColumn (10);
// Change the size of the text field.
p.validate();
// Recompute the size and layout of all components in a container.
String s = tf.getText().trim();
// Return the exact text and trim any extraneous spaces for the data in
the text field.
interface DocumentListener (3 methods)
insertUpdate(..)
character(s) inserted
removeUpdate(..)
character(s) deleted
changedUpdate(..)
changed in formatting, etc.

DocumentListener listener = new ClockFieldListener();


// add a panel with text fields
JPanel panel = new JPanel();

panel.add(new JLabel("Hours:"));
hourField = new JTextField("12", 3);
panel.add(hourField);
hourField.getDocument().addDocumentListener(listener);

panel.add(new JLabel("Minutes:"));
minuteField = new JTextField("00", 3);
panel.add(minuteField);
minuteField.getDocument().addDocumentListener(listener);

add(panel, BorderLayout.SOUTH);
// add the clock

clock = new ClockPanel();


add(clock, BorderLayout.CENTER);
pack();
}
/**
Set the clock to the values stored in the text fields.
*/
public void setClock()
{
try
{
int hours = Integer.parseInt(hourField.getText().trim());
int minutes = Integer.parseInt(minuteField.getText().trim());
clock.setTime(hours, minutes);
}
catch (NumberFormatException e) {}
// don't set the clock if the input can't be parsed
}
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 300;

private JTextField hourField;


private JTextField minuteField;
private ClockPanel clock;

private class ClockFieldListener implements DocumentListener


{
public void insertUpdate(DocumentEvent event) { setClock(); }
public void removeUpdate(DocumentEvent event) { setClock(); }
public void changedUpdate(DocumentEvent event) {}
}
}
Note: The model for all text components is described by the Document
interface. In the statement
minuteField.getDocument().addDocumentListener(listener);
the minuteField obtains the data model "document" through the metho
getDocument( ).

For text areas, the user can enter any number of lines of text, using
the ENTER key to separate them.
JTextArea textArea = new JTextArea (8, 40);
// 8 lines of 40 columns
frame.add (textArea);
Internally, each line ends with '\n'.
textArea.setLineWrap (true); // long lines are wrapped
visually; no '\n' characters are inserted into the text.
Automatic Scrolling
textArea = new JTextArea ( 8, 40 );
JScrollPane scrollPane = new JScrollPane( textArea );
frame.add( scrollPane, BorderLayout.CENTER );
JPasswordField
The characters that the user entered are not actually displayed, bu
represented by an echo character (typically ‘*’).
JPasswordField( String text, int columns)

// add button to append text into the text area

JButton insertButton = new JButton("Insert");


buttonPanel.add(insertButton);
insertButton.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
textArea.append("The quick brown fox jumps over the lazy
dog. ");
}
});
// add button to turn line wrapping on and off

wrapButton = new JButton("Wrap");


buttonPanel.add(wrapButton);
wrapButton.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
boolean wrap = !textArea.getLineWrap();
textArea.setLineWrap(wrap);
scrollPane.revalidate();
wrapButton.setText(wrap ? "No Wrap" : "Wrap");
}
});

Radio Buttons
ButtonGroup group = new ButtonGroup();
JRadioButton smallButton = newJRadioButton( “Small”, false );
group.add( smallButton );
JRadioButton mediumButton = newJRadioButton( “Medium”,
false );
group.add( mediumButton );
Sliders
JSlider slider = new JSlider(min, max, initialValue); // default: 0, 100, 5
JSlider slider = new JSlider(SwingConstants.VERTICAL, min, max,
initialValue);
ChangeEvent, addChangeListener(), stateChanged()
snap to ticks – move slider to closest tick
// common listener for all sliders
listener = new ChangeListener()
{
public void stateChanged(ChangeEvent event)
{
// update text field when the slider value changes
JSlider source = (JSlider) event.getSource();
textField.setText("" + source.getValue());
}
};

// add a plain slider slider.setPaintTicks(true);


JSlider slider = new JSlider(); slider.setMajorTickSpacing(20
addSlider(slider, "Plain"); );
// add a slider with major and slider.setMinorTickSpacing(5);
minor ticks addSlider(slider, "Ticks");
slider = new JSlider(); // add a slider that snaps to
ticks labels
slider = new JSlider(); slider = new JSlider();
slider.setPaintTicks(true); slider.setPaintLabels(true);
slider.setSnapToTicks(true); slider.setPaintTicks(true);
slider.setMajorTickSpacing(20 slider.setMajorTickSpacing(20
); );
slider.setMinorTickSpacing(5); slider.setMinorTickSpacing(5);
addSlider(slider, "Snap to Dictionary<Integer,
ticks"); Component> labelTable = new
// add a slider with no track Hashtable<Integer,
slider = new JSlider(); Component>();
slider.setPaintTicks(true); labelTable.put(0, new
slider.setMajorTickSpacing(20 JLabel("A"));
); labelTable.put(20, new
slider.setMinorTickSpacing(5); JLabel("B"));
slider.setPaintTrack(false); labelTable.put(40, new
addSlider(slider, "No track"); JLabel("C"));
// add an inverted slider labelTable.put(60, new
slider = new JSlider(); JLabel("D"));
slider.setPaintTicks(true); labelTable.put(80, new
slider.setMajorTickSpacing(20 JLabel("E"));
); labelTable.put(100, new
slider.setMinorTickSpacing(5); JLabel("F"));
slider.setInverted(true); slider.setLabelTable(labelTabl
addSlider(slider, "Inverted"); e);
// add a slider with numeric addSlider(slider, "Custom
labels labels");
slider = new JSlider(); // add a slider with icon labels
slider.setPaintTicks(true); slider = new JSlider();
slider.setPaintLabels(true); slider.setPaintTicks(true);
slider.setMajorTickSpacing(20 slider.setPaintLabels(true);
); slider.setSnapToTicks(true);
slider.setMinorTickSpacing(5); slider.setMajorTickSpacing(20
addSlider(slider, "Labels"); );
// add a slider with alphabetic
slider.setMinorTickSpacing(20);
labelTable = new Hashtable<Integer, Component>();
// add card images
labelTable.put(0, new JLabel(new ImageIcon("nine.gif")));
labelTable.put(20, new JLabel(new ImageIcon("ten.gif")));
labelTable.put(40, new JLabel(new ImageIcon("jack.gif")));
labelTable.put(60, new JLabel(new ImageIcon("queen.gif")));
labelTable.put(80, new JLabel(new ImageIcon("king.gif")));
labelTable.put(100, new JLabel(new ImageIcon("ace.gif")));
slider.setLabelTable(labelTable);
addSlider(slider, "Icon labels");
// add the text field that displays the slider value
textField = new JTextField();
add(sliderPanel, BorderLayout.CENTER);
add(textField, BorderLayout.SOUTH);
}
Chapter 8 Event Handling
What is an event?
An event is (in most cases) an action taken by the user. For example,
the user presses a key, clicks the mouse, etc

In Java, you completely control how an event is transmitted from the


event source (buttons, scrollbars, etc.) to the event listener (an object
that can carry out the response you want for the event). This Event
delegation model gives us much more flexibility than VB (in VB, the
listener is predetermined; in Java, you can designate any object to be
an event listener).
eventSourceObject.addEventListener ( eventListenerObject);
e.g.,
ActionListener listener = … ;
JButton b = new JButton ("OK");
b.addActionListener (listener);
// the method addActionListener is defined in class Button.
E.g.,
...
ActionListener listener = … ;
JButton b = new JButton ("OK");
b.addActionListener (listener);
...
class MyListener implements ActionListener
{...
public void actionPerformed ( ActionEvent evt )
{ // reaction to button click goes here
...
}
Listener Interfaces (See p.359 for a complete list.)
Name Methods Accessors Events
generated by
ActionListener actionPerformed getSource
JButton
isSelected CheckBox
getActionCommand MenuItem
(getSource) JComboBox
Abstractbutton
JTextField
Timer

TextListener textValueChanged getText


TextComponent

#DocumentListener getText
TextComponent
insertUpdate
removeUpdate
changedupdate

MouseListener mousePressed MouseEvent


Component
mouseReleased getClickCount
mouseEntered getX, getY
mouseExited getPoint
mouseClicked isPopupTrigger

WindowListener windowClosing getWindow Window


windowOpened
windowIconified
windowDeconified
windowClosed
windowActivated
windowDeativated

KeyListener keyPressed getKeyCode Component


keyReleased getKeyChar
keyTyped getKeyModifiersText

#ListSelectionListener
valueChanged getSource List

Adapter Classes
Implementing six methods that do nothing is a tedious work. To
simplify this work, each of the listener interfaces that has more than
one method comes with a companion adapter class that implements
all the methods in the interface but does nothing with them.
For example, the WindowAdapter class has seven do-nothing
methods. This means the adapter class automatically satisfies the
technical requirements of using interface.
These are adapters:
WindowAdapter, ComponentAdapter, ContainerAdapter,
FocusAdapter,
KeyAdapter, MouseAdapter, MouseMotionAdapter.

addWindowListener ( new WindowAdapter()


{ public void windowClosing (WindowEvent e) { System.exit
(0);}
}
);
Handling Keyboard Events
Pressed the SHIFT key (keyPressed for VK_SHIFT)
Pressed the "A" key (keyPressed for VK_A)
Typed "A" key (keyTyped for ‘A’)
Released the "A" key (keyReleased for VK_A)
Released the SHIFT key (keyReleased for VK_SHIFT)

The keyTyped event reports the characters that were typed (‘A’)
whereas the keyPressesd and keyReleased events report on the raw
keystrokes (representing by the virtual key codes).
When we override the method keyPressed and keyReleased, we use
the getKeyCode method to obtain the virtual key code:
void keyPressed ( keyEvent evt) {
int keyCode = evt.getKeyCode ();
}
When we override the keyTyped method, we use the getKeyChar
method to obtain the actual character typed:
char keyChar = evt.getKeyChar();

Mouse Events (p.349)


You do not need to handle mouse events explicitly if you just want
the user to be able to click on a button or menu.
These mouse operations are handled internally by the various
components in the GUI. If you want to draw with the mouse, you
need to trap mouse move, click, and drag events.
Methods of MouseListener interface:
mousePressed, mouseReleased, mouseClicked,
mouseEntered, mouseExited
Methods of MouseMotionListener interface:
mouseDragged, mouseMoved
Method of MouseWheelListener interface:
mouseWheelMoved
A useful method: MouseEvent.getClickCount()
To detect if the right (nonprimary) mouse button is down:
if ((event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK)
!= 0 ) {…}
// Note that MouseEvent extends InputEvent.
// the square containing the mouse cursor
private class MouseHandler extends MouseAdapter
{
public void mousePressed(MouseEvent event)
{
// add a new square if the cursor isn't inside a square
current = find(event.getPoint());
if (current == null) add(event.getPoint());
}
public void mouseClicked(MouseEvent event)
{
// remove the current square if double clicked
current = find(event.getPoint());
if (current != null && event.getClickCount() >= 2)
remove(current);
}
}
private class MouseMotionHandler implements MouseMotionListener
{
public void mouseMoved(MouseEvent event)
{
// set the mouse cursor to cross hairs if it is inside
// a rectangle

if (find(event.getPoint()) == null)
setCursor(Cursor.getDefaultCursor());
else

setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
public void mouseDragged(MouseEvent event)
{
if (current != null)
{
int x = event.getX();
int y = event.getY();
// drag the current rectangle to center it at (x, y)
current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2,
SIDELENGTH, SIDELENGTH);
repaint();
}
}
}

Actions
to separate the responsibilities of getting user input and executing
commands;
multiple ways to activate the same command: menu, keystroke,
button, etc.
one class object for each command;
one listener for multiple event sources
Mulicasting
One event source, many listeners
Simply add multiple listeners to an event source.
There is no guarantee about the order in which the events are
delivered to the listeners.

Chapter 7 Graphics Programming


Java Graphics libraries
AWT (Abstract Window Toolkit) - for basic GUI (Graphical User Interface)
programming
Swing - additional set of user interface components provided by Java 1.2
Frame - a top-level window (a window that is not contained inside
another window) with a title and a border is called a frame. Frame is a
subclass of class Container.
import javax.swing.*; JFrame
public class SimpleFrameTest {
{ public SimpleFrame()
public static void main(String[] {
args) setSize(DEFAULT_WIDTH,
{ DEFAULT_HEIGHT);
SimpleFrame frame = new }
SimpleFrame(); public static final int
frame.setDefaultCloseOperation( DEFAULT_WIDTH = 300;
JFrame.EXIT_ON_CLOSE); public static final int
frame.setVisible(true); DEFAULT_HEIGHT = 200;
} }
}
class SimpleFrame extends // get screen dimensions
kit.getScreenSize();
Toolkit kit = int screenHeight =
Toolkit.getDefaultToolkit(); screenSize.height;
Dimension screenSize = int screenWidth = screenSize.wid

2D Shapes
The Java 2D library organizes geometric shapes in an object-oriented
fashion. There are
abstract classes Line2D, Rectangle2D,
Ellipse2D, and etc. Each class contains two static inner classes Float a
Double, e.g.,
Rectangle2D.Float floatRect = new Rectangle2D.Float( 10.0F, 25.0F,
22.5F, 20.0F );
// left x, top y, width, height; float values
Rectangle2D.Double doubleRect = new Rectangle2D.Double( 10.0, 25
22.5, 20.0 );
// double values
//example
Rectangle2D rect = new Rectangle2D.Double(leftX, topY, width,
height);
g2.draw(rect);
// draw the enclosed ellipse
Ellipse2D ellipse = new Ellipse2D.Double();
ellipse.setFrame(rect);
g2.draw(ellipse);
// draw a diagonal line

g2.draw(new Line2D.Double(leftX, topY, leftX + width, topY +


height));
// draw a circle with the same center
double centerX = rect.getCenterX();
double centerY = rect.getCenterY();
double radius = 150;
Ellipse2D circle = new Ellipse2D.Double();
circle.setFrameFromCenter(centerX, centerY, centerX + radius,
centerY + radius);
g2.draw(circle);
Colors
g2.setPaint( Color.red ); // predefined red color
g2.drawString( “Warning!”, 100, 100 );
Predefined colors: red, blue, green, black, magenta, yellow, etc. (RED,
BLUE, etc. are also ok.)
Custom colors specification:
g2.setPaint( new Color( 0, 128, 128 ) ); // given RGB intensities
The intensity of each red, green, and blue color has a range from 0 -
255.
Useful methods:
Color c = new Color( r, g, b );
c.brighter().brighter().brighter();
// The return value of brighter() is a Color object.
MyComponent p = new MyComponent();
p.setBackground( SystemColor.window );
p.setForeground( SystemColor.textText );
frame.add( p );
Font
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
String message = "Hello, World!";
Font f = new Font("Serif", Font.BOLD, 36);
g2.setFont(f);
// measure the size of the message
FontRenderContext context = g2.getFontRenderContext();
Rectangle2D bounds = f.getStringBounds(message, context);
// set (x,y) = top left corner of text
double x = (getWidth() - bounds.getWidth()) / 2;
double y = (getHeight() - bounds.getHeight()) / 2;
// add ascent to y to reach the baseline
double ascent = -bounds.getY();
double baseY = y + ascent;
// draw the message
g2.drawString(message, (int) x, (int) baseY);
g2.setPaint(Color.LIGHT_GRAY);

// draw the baseline


g2.draw(new Line2D.Double(x, baseY, x + bounds.getWidth(),
baseY));
// draw the enclosing rectangle
Rectangle2D rect = new Rectangle2D.Double(x, y,
bounds.getWidth(), bounds.getHeight());
g2.draw(rect);
}
}
Images
class ImageComponent extends JComponent
{
public ImageComponent()
{
// acquire the image
try
{
image = ImageIO.read(new File("blue-ball.gif"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void paintComponent(Graphics g)
{
if (image == null) return;
int imageWidth = image.getWidth(this);
int imageHeight = image.getHeight(this);
// draw the image in the upper-left corner
g.drawImage(image, 0, 0, null);
// tile the image across the component
for (int i = 0; i * imageWidth <= getWidth(); i++)
for (int j = 0; j * imageHeight <= getHeight(); j++)
if (i + j > 0) g.copyArea(0, 0, imageWidth, imageHeight, i *
imageWidth, j * imageHeight);
}
private Image image;
}

Chapter 6 Interfaces and Inner Classes


A Java interface is similar to a class except that there are no instance fiel
and no
implementations of methods in the interface.
Interfaces are a way to declare a type consisting only of abstract method
(without
implementation details) and constants.
The methods are actually provided in those classes that implement the
interfaces.
Thus an interface is an expression of pure design.
All methods in an interface are implicitly abstract (with only declaration a
no implementation)
and are always public. Interfaces
cannot have any static method.
Any class can promise to implement the interface using the keyword
implements. Any class that implements an interface must
implement all its methods.
Differences between using interfaces and abstract classes:
If multiple inheritance is important, use interfaces, otherwise use
abstract classes. This is because an abstract class can provide some
or all of the methods that can be inherited easily.
Interfaces never have instance fields, and the methods are never
implemented in the
interfaces.
Arrays.sort(staff); //Library method calls compareTo().
class Employee implements Comparable<Employee>
{
public Employee(String n, double s)
{ }
public int compareTo(Employee other)
{
if (salary < other.salary) return -1; //to compare two string return
name.conmpareTo(other.name);
if (salary > other.salary) return 1; //to compare two hireday
return hireday.compareTo(other.hireday);
return 0;
}
}
x = new Comparable( … ); // error
Comparable y; // ok
y = new Employee( … ); // ok if Employee implements Comparable
if ( y instanceof Comparable ) { … } // ok
You can extend interfaces. You can also put constants in interfaces. The
fields are always
public static final.

Object Cloning
Employee original = new Employee(“John Public”, 50000);
Employee copy = original; // copying
copy.raiseSalary(10); // oops – also changed original
Using the clone() method in the Object class copies only the first level of
fields. If there are immutable subobjects in the
data fields (such as a String object), this library clone() method works fin
Employee copy = original.clone();
copy.raiseSalary(10); // OK – original unchanged.
Quite frequently, subobjects are mutable, and one must override the clon
method to make
a “deep” copy that clones the subobjects as well. The relevant class mus
also
implement the Cloneable interface.
class Employee implements Cloneable {
public Employee(String n, double s) { ... }
public Employee clone() { ... }
}
public Employee clone() throws CloneNotSupportedException
{
// call Object.clone()
Employee cloned = (Employee) super.clone();
// clone mutable fields
cloned.hireDay = (Date) hireDay.clone();
return cloned;
}
Inner classes
Inner classes are classes defined within another class.
Only inner classes can be private. Regular classes always have either package or
public visibility.
Advantages: ability to access instance fields of the outer classes; inner classes can be
private to ensure encapsulation
public void start()
{
// Creating an inner class object.
ActionListener listener = new TimePrinter();
Timer t = new Timer(interval, listener);
t.start();
}
Local inner classes
Define a class within a method. The class is usable only in that method (always private to
method). No access modifier is needed.
For example, in Example 6-4, the inner class TimePrinter is used only once.
public void start()
{
class TimePrinter implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
Date now = new Date();
System.out.println("At the tone, the time is ” + now);
if (beep) Toolkit.getDefaultToolkit().beep();
}
}

ActionListener listener = new TimePrinter();


Timer t = new Timer(1000, listener);
t.start();
}
Anonymous inner classes
// start() method of TalkingClock
public void start( int interval, final Boolean beep)
{
ActionListener listener = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
Date now = new Date();
System.out.println("At the tone, the time is ” + now);
if (beep) Toolkit.getDefaultToolkit().beep();
}
}
Timer t = new Timer(interval, listener);
/* calling the start() method of Timer, not the start() method of TalkingClock. */
t.start();
}
Meaning: create a new object of a class that implements the ActionListener
interface. This class has no name.
(a) If SuperType is an interface, the anonymous class implements that interf
(b) If SuperType is a class, the anonymous class extends that class.
(c) An anonymous class cannot have constructors because the class has
name.
(d) If SuperType is an interface, construction parameters should be empty.
(e) If SuperType is a class, the construction parameters are passed to the
constructor of
SuperType.
Chapter 5 Inheritance
Inheritance is a way to derive new classes from existing ones. You can reuse or change the members
of existing classes, as well as add new members in order to adapt them to new circumstances.
The relation between subclass and superclass is the "is - a" relationship (e.g., a pixel is a point, a
manager is an employee, a passenger-carrying vehicle is a vehicle). Any object of the subclass
must be usable in place of the superclass object.
When you extend a class to create a new class, the new class (subclass) inherits all the fields and
methods of the old class (superclass). However, objects of the superclass cannot use fields newly
defined in the subclass.
A subclass object cannot access the private fields of the superclass object.
Polymorphism
Another way of formulating the “is – a” rule is the substitution principle. You can use a
subclass object whenever the program expects a superclass object.
Employee e;
e = new Employee( … ); // Employee object expected
e = new Manager( … ); //OK, a Manager object can be used as well.

Object variables in Java are polymorphic, i.e., an object variable of a class can refer to an
object of this particular class or any of the subclasses.
Another form of polymorphism is discussed in the section about overriding (see below),
where one method name is being overloaded or overridden.
We can assign a subclass object to a superclass variable.
Manager boss = new Manager ( “John”, 70000, 1990, 1, 2 );
Employee em1 = new Employee ( “Lee”, 50000, 1992, 3, 1 );
Employee em2 = new Employee ( “Wong”, 55000, 1994, 9, 4 );
Employee em3 = new Employee (“Chan”, 60000, 1996, 3, 8 );
Employee EM = boss; // ok!
/* In this case, EM and boss refer to the same area of memory. The actual type of
EM is Manager, but the variable type of EM is Employee. */
Employee[] staff = new Employee[4];
staff [0] = boss;
/*Ok, although the type of staff[0] is Employee and the type of boss is Manager. */
staff [1] = em1;
staff [2] = em2;
staff [3] = em3;
However, the converse (assigning a superclass object to a subclass variable) is false in general.
superclass object cannot be used as a subclass object.
Overloading and overriding
The scenario that methods in different classes of an inheritance hierarchy have the same
signature (method name and parameter list) and same return type but different contents is
called overriding that method name (polymorphism). Notice that the return type is not
part of the signature.
Overloading a class provides more than one method with the same name, but with
different signatures.
Overriding a class hierarchy replaces the superclass's implementation of a method in
the subclass. Their signatures and return types must be identical. Note that only
non-static methods may be overridden. For example,
// in class Employee
public void raiseSalary( double byPercent ) {
salary *= ( 1. + byPercent / 100. );
}
// in class Manager
public void raiseSalary( double byPercent ) {
Date today = new Date();
//addition 0.5% for each year of service
double bonus_percent =
0.5* ( today.getYear() – getHireDay().getYear() );
super.raisesalary( byPercent + bonus_percent );
}
When you override a method, the subclass method must be at least as visible as the
superclass method. For example,
• If the superclass method is public, the subclass method must also be public.
• If the superclass method is private, the subclass method can be public. Also,
• in this case, if the method is named, say, func(), the subclass method cannot call
super.func().
When an object of a subclass calls a method name (this method may or may not have been
overridden in the inheritance hierarchy), which one will actually be invoked? The rules are:
(1) The subclass checks whether or not it has a method with that name and with exactly
the same parameters. If so, use it. If not,
(2) Java moves to the parent class and looks there for a method with that name and those
parameters. If so, it calls that method. If not,
(3) Java continues to move up the inheritance chain. The parent classes are checked
until the chain of inheritance stops (an error) or until Java finds a matching method
This is one of the fundamental inheritance rules: a method redefined in a subclass hides or over
the method of the ancestor class.
Dynamic binding
Dynamic binding occurs when a superclass and a subclass both have a method of the same sign
and return type.
If an object of a subclass is assigned to a superclass variable, and the variable calls an overridd
method, which one of the overridden methods in the inheritance hierarchy will be invoked?
The answer is - according to the actual type of the object itself, not the type of the variable.
Consider the code from Example 5-1:
for (int i = 0; i < staff.length; i++) {
Employee e = staff[i];
// staff[0] is of type boss; staff[1] and staff[2] are of type Employee
System.out.println( "name=" +
e.getName() + //static binding
", salary = " + e.getSalary()); // dynamic binding
}
The Java compiler produces the method tables for the Employee and Manager classes (in Exam
5-1):
Employee:
getName() → Employee.getName()
getSalary() → Employee.getSalary()
getHireDay() → Employee.getHireDay()
raiseSalary( double ) → Employee.raiseSalary( double )
Manager:
getName() → Employee.getName()
getSalary() → Manager.getSalary()
getHireDay() → Employee.getHireDay()
raiseSalary( double ) → Employee.raiseSalary( double )
setBonus( double ) → Manager.setBonus( double )
Constructors in inheritance hierarchy
Every constructor of a subclass must somehow call a constructor of the superclass (to set up
the data fields of the superclass).
(1) In a constructor of a subclass, we can explicitly use super with the appropriate
(2) parameters to invoke one of the superclass's constructors. This must be done in the
first statement of the subclass’s constructor.
(2) If the subclass constructor does not call a superclass constructor explicitly, the default
constructor of the superclass will be called automatically by the compiler.
By convention, if a class does not have any constructor, the Java compiler will
automatically generate a default constructor. However, if the class has one or more cons
that requires parameters (but no default constructor), the compiler will not
generate a default constructor. Thus
(i) if the superclass has no default constructor but does possess other constructors, we
explicitly use one of these constructors via super. Otherwise the compiler will repo
error;
(ii) if the superclass has no constructor at all and the subclass constructor does not use
the default constructor provided by the compiler will be called.

Existence of superclass’s constructors: When a constructor of a


subclass does not invoke
the superclass’s constructor
explicitly, the Java
compiler
existence of existence of
default (no- constructors
argument) requiring
constructor parameters
uses the default
Case 1:No No constructor provided by
the compiler
Yes reports an error
Case 2:No
Case 3: Yes No uses the default
constructor
Case 4: Yes Yes uses the default
constructor

Abstract Classes and Abstract Methods


When one moves up an inheritance hierarchy, the ancestor class may become so general that
we think of it more as a framework for other classes than as a class that we want to use. We
may use the keyword abstract to declare such general classes.
Abstract classes cannot be instantiated, meaning that if a class is declared as abstract, no
instance of that class can be created.
Abstract Method - in an abstract class, you can define (deferring implementation) only the
signatures of some of its methods, leaving extended classes to provide specific implemen
tation of these methods.
Each method that has not been implemented in the class is specifically marked abstract.
For added clarity, a class with one or more abstract methods must itself be declared abstract. Fo
example,
abstract class Person {
public Person(String n){
name = n;
}
public abstract String getDescription();
public String getName() {
return name;
}
private String name;
}
Abstract classes can have concrete data and methods. Also, a class can even be declared
as abstract even though it has no abstract methods.
All non-abstract subclasses of the abstract class must implement all the abstract methods of
the abstract class (overriding). So abstract methods act as placeholder methods that are
implemented in the subclasses.
final classes and methods
Marking a method in a superclass final means that no subclass can override the method and
change its behavior. In other words, this is the final version of that method.
Wrapper Classes
Occasionally, you need to convert a primitive type to an object. Java has defined correspond
ding wrapper classes for all primitive types. ( Integer, Long, Float, Double, Byte, Character,
Boolean).
E.g., declare an object named anInteger of class Integer and using the constructor of class
Integer to initialize it:
Chapter 4 (Part 2) Objects and Classes in Java
Instance fields are the internal data/variables of the objects of the class.
Instance methods operate on the instance fields of the class.

Methods
In Java, the terminology method is used instead of functions in C. All methods must
be defined inside a class.
public The member can be accessed by any class.
private The member can be accessed only by methods within the same class (to make sure
that no outside agency can access the members except through the methods
of our class).
protected The member can be accessed by subclasses of this class and classes in the same
package.
(none) Members declared with no access modifier are accessible only to classes in the same
package.
Overloading Methods
Each method has a signature - the name together with the number and types of its parameters
in the parameter list.
Two methods of a class can have the same name but different number or types of parameters.
This feature is called overloading - because the name of the method has been overloaded.
Constructors
Java offers a good way to initialize data fields of instances (especially for private fields)
through constructors.
Static Fields and methods
Static fields and methods (class fields and methods) are associated with a class as a whole,
not with a particular instance. They are declared static in the class definition.
The value of a static field (class field) does not change from one class instance to another.
There is exactly one copy of the variable, no matter how many object instances (even zero)
there are of the class. This single value is shared by all objects of the class. It represents a
piece of “class-wide” information.

Using a block for initialization - a class can also have static initialization blocks to set
up static fields or other necessary states.
public static double [] buffer = new double[BUFFER_SIZE];
static {
int i;
for ( i = 0 ; i < buffer.length ; i++ )
buffer[i] = java.lang.Math.random( );
}
Thus a static method cannot use the implicit parameter this.
Finalizers
Every class in Java can have a finalizer method that releases resources back to the operating
system. This method is called before the garbage collector sweeps away the object. A
class’s finalizer method always has the name finalize, receiving no parameters and returning no
value. (I.e., its return type is void.)

Chapter 4 (Part 1)Fundamental Concepts ofObject-oriented Approach


Quality Factors:
Correctness --- Correctness is the ability of software products to exactly perform their tasks,
as defined by the requirements and specification.
Robustness --- Robustness is the ability of software systems to function even in abnormal
conditions.
Extendibility --- Extendibility is the ease with which software products may be adapted to
changes of specification.
Reusability --- Reusability is the ability of software products to be reused, in whole or in part,
for new applications.
O-O Analysis
Tradition structured analysis focus upon the flow of data within a system; O-O analysis
emphasizes on the building of real-world models.
What is an object?
An object is an entity that contains both the attributes that describe the state of a real-world
object and the actions that are associated with the real-world object.
With an O-O language, an object would capture both the data (attributes) and methods
( actions) associated with the object.
What is a class?
Object-Oriented programs usually operate with hundreds or thousands of objects. Many objects
common properties ( same structure, same interface, same behavior ) --- they are
the same kind.
We define a class of objects to be one that has the same properties to describe objects in
this class, which messages they should accept, which methods they should execute in
response to these messages, and the attributes of them.
Polymorphism
Polymorphism represents a concept in type theory in which a single name
(e.g., the name of a method) may denote things of many different classes that are
related by some common superclass.
The identically named method may have different implementations in the subclasses

Chapter 3: Basics of Java


Data Type
All data types are classes, except several "primitive" types built-in to support integer, floating-
point, boolean, and character values.
Classes
Classes are user-defined data types. (There are lots of libraries classes.) We will study how to
write user-defined classes in chapter 4.
Constants
Java uses the keyword final to denote a constant (In C, use the keyword const.) The keyword
final indicates that you can assign to the variable only once.
Enumerated Types
enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE}

Size pizza = Size.MEDIUM;


Further discussion in Chapter 5.
• Strings (java.lang.String p.53)
The standard Java library contains a predefined class String to deal with sequences of character dat
provide shorthand to declare and initialize them.
labeled break (breaking out of one or nested loops)
int n;
read_data:
while ( … ) { // This loop statement is tagged with the label.

for ( … ) { // This inner loop is not labeled.
System.out.print(“Enter a number >= 0: ” );
n = in.nextInt( );
if ( n < 0 ) // should never happen – can’t go on
break read_data;
// break out of read_data loop
}
}
// This statement is executed immediately after the break.
if ( n < 0 ) { // check for bad situation
// deal with bad situation
}
else {
// carry out normal processing
}
// Second example
label:
{

if ( condition ) break label; //exits block

}
// jumps here when the break statement executes
MP1
import java.io.*;
import java.util.*;

public class MP1 {

public static void main(String[] args)throws IOException{


int i = 0, j = 0;
int ii, jj;
int maxpara = 1000;
int maxline = 1000;
String [][] contents = new String[maxpara]
[maxline];
if (args[0].substring(0,1).equals("-")){
if (args[0].substring(0,2).equals("-s")){
Scanner in = new Scanner(new File(args[1]));
while(in.hasNextLine()){
String temp =
in.nextLine();
if(temp.equals("")){
i++;
j=0;
}else{
contents[i][j] =
temp;
j++;
}
}

itemS(args[0], i, j, maxline,maxpara, contents);


in.close();
else{
Scanner in = new Scanner(new File(args[0]));
PrintWriter out = new PrintWriter(new
File(args[1]));
while(in.hasNextLine()){
String temp = in.nextLine();
if(temp.equals("")){
i++;
j=0;
}else{
contents[i][j] = temp;
j++;
}
}
for(ii = 0;ii <= i;ii++){
for(jj = 0;jj < maxline;jj++){
if(contents[ii][jj]!=null)out.println(contents[ii][jj]);
}out.println("");
}
in.close();
out.close();
}
public static void itemE (String args3, int i3,int j3, int maxline3, int
maxpara3, String [][] contents3) throws IOException{
int g = args3.indexOf(",", 0);
int h = args3.indexOf(",", (g+1));
int k = args3.length();
int a = Integer.parseInt(args3.substring(2,g), 10);
int b = Integer.parseInt(args3.substring((g+1),(h)), 10);
int c = Integer.parseInt(args3.substring((h+1),k), 10);
String [][] tmp3 = new String[maxpara3][maxline3];
int e = 0, f = 0;
int i, j;

tmp3[e][f] = contents3[a-1][b-1];
contents3[a-1][b-1] = contents3[a-1][c-1];
contents3[a-1][c-1] = tmp3[e][f];
for(i=0;i <= i3;i++){
for(j=0;j < maxline3;j++){
if(contents3[i][j]==null)break;
System.out.println(contents3[i][j]);
}System.out.println(""); }
}

MP2
import java.io.*;
import java.util.*;
public Blue_Card(String n, int an, Date cs, ArrayList<Trip> ml){
this.name = n;
this.acct_no = an;
this.customer_since = cs;
this.mileage_list = ml;
}
public Blue_Card(){}
public Blue_Card claim_ticket(int km){
Collections.sort(mileage_list);
return this;
}
class Trip implements Comparable<Trip>{
public int compareTo(Trip other){
return
date_granted.compareTo(other.date_granted);
}
}
public class MP2 {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
ArrayList<Trip> Ada_list = new ArrayList<Trip>();
Ada_list.add(new Trip(20000, new Date(2007-
1900,1-1,5)));
Ada_list.add(new Trip(15000, new Date(2008-
1900,8-1,8)));
System.out.print("Please enter mileage earned:");
int me = in.nextInt();
}
}
if(option == 6){
System.exit( 0 );
}
MP3
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
public class MP3 {
public static void main(String[] args){
KFrame frame = new KFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class KFrame extends JFrame{
public KFrame(){
setTitle("MP3");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
KPanel panel = new KPanel();
add(panel);
}
public static final int DEFAULT_WIDTH = 315;
public static final int DEFAULT_HEIGHT = 635;
}
class MyMouseAdapter extends MouseAdapter
{ public void mousePressed( MouseEvent e){
int x =e.getX();
int y = e.getY();
}
}
class MyKeyAdapter extends KeyAdapter
{
public void keyPressed(KeyEvent event)
{ int code = event.getKeyCode();
char code2 = event.getKeyChar();
}
}
MP4
public KFrame(){
setTitle("MP4");
main_panel = new JPanel();
main_panel.setLayout( new BorderLayout() );

left_panel = new FillPanel();


left_panel.setPreferredSize(new Dimension(400,
700));

main_panel.add(left_panel,BorderLayout.WEST);
right_panel = new RPanel();
right_panel.setLayout( new BorderLayout() );
right_panel.setPreferredSize(new Dimension(300,
700));
right_top = new RTPanel();
right_top.setPreferredSize(new Dimension(300,
250));
right_panel.add(right_top, BorderLayout.NORTH);
right_middle = new RMPanel();
right_middle.setLayout(new BorderLayout());
right_middle.setPreferredSize(new Dimension(300,
250));
JPanel right_middle_bottom = new JPanel();
right_middle_bottom.setPreferredSize(new
Dimension(300, 150));
right_middle_bottom.setLayout(new
GridLayout(8,1));
top_scores = new JLabel(" Top Scores");
name = new JLabel(" Name Scores");
first = new JLabel("1.");
second = new JLabel("2.");
third = new JLabel("3.");
fourth = new JLabel("4.");
fifth = new JLabel("5.");
JTextField tf = new JTextField (" ", 10);
right_middle_bottom.add(top_scores);
right_middle_bottom.add(name);
right_middle_bottom.add(first);
right_middle_bottom.add(second);
right_middle_bottom.add(third);
right_middle_bottom.add(fourth);
right_middle_bottom.add(fifth);
right_middle_bottom.add(tf);
right_middle.add(right_middle_bottom,
BorderLayout.SOUTH);
right_panel.add(right_middle,
BorderLayout.CENTER);
right_bottom = new RBPanel();
right_bottom.setPreferredSize(new Dimension(300,
200));
slider_panel = new SPanel();
slider_panel.setLayout( new BorderLayout() );
slider = new JSlider(1,100,50);
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent event)
{
JSlider source = (JSlider)event.getSource();
slider_value = source.getValue();
timer.setDelay(slider_value+1000);
slider.transferFocus();
s_r.transferFocus();
p_r.transferFocus();
//timer.start();
System.out.println(slider_value);
}
}
);
speed = new JLabel(" Speed");
slider_panel.add(speed,BorderLayout.NORTH);

slider_panel.add(slider,BorderLayout.CENTER);
right_bottom.add(slider_panel);
button_panel = new BPanel();
s_r = new JButton("Start");
p_r = new JButton("Pause");
button_panel.add(s_r);
button_panel.add(p_r);
right_bottom.add(button_panel);
right_panel.add(right_bottom,
BorderLayout.SOUTH);
main_panel.add(right_panel,BorderLayout.CENTER);
add(main_panel);
pack();
}
PT2
public KFrame(){
JLabel label = new JLabel("Select your next figue
here:");
JButton square = new JButton("Square");
JButton triangle = new JButton("Triangle");
JButton circle = new JButton("Circle");
square.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event){
figure = 1;
repaint();
}
}
);
top_left_down.add(square);
top_left_down.add(triangle);
top_left_down.add(circle);
top_left.setLayout(new GridLayout(2,1));
top_left.add(label);
top_left.add(top_left_down);

ButtonGroup group = new JLabel label5 = new


ButtonGroup(); JLabel("Status");
JRadioButton fill = new bottom_left.setLayout(new
JRadioButton("Filled figue", true); GridLayout(2,1));
JRadioButton outline = new JLabel label1 = new JLabel("Size
JRadioButton("Outline only", of square, triangle, or circles:");
false); JSlider slider = new
fill.addActionListener(new JSlider(5,300,50);
ActionListener() slider.setPaintTicks(true);
{ slider.setMajorTickSpacing(20);
public void slider.setMinorTickSpacing(5);
actionPerformed(ActionEvent bottom_left.add(label1);
event){ bottom_left.add(slider);
fill_out = true; bottom_right.setLayout(new
repaint(); GridLayout(2,3));
} JLabel label2 = new JLabel("Red
} intensity:");
); JLabel label3 = new JLabel("Green
top_right.setLayout(new intensity:");
GridLayout(2,1)); JLabel label4 = new JLabel("Blue
group.add(fill); intensity:");
group.add(outline); JTextField tf = new JTextField("",
top_right.add(fill); 5);
top_right.add(outline); JTextField tf1 = new JTextField("",
top_panel.add(top_left,BorderLay 5);
out.CENTER); JTextField tf2 = new JTextField("",
top_panel.add(top_right, 5);
BorderLayout.EAST); bottom_right.add(label2);
bottom_panel.setLayout(new bottom_right.add(label3);
BorderLayout()); bottom_right.add(label4);
bottom_left = new JPanel(); bottom_right.add(tf);
bottom_right = new JPanel(); bottom_right.add(tf1);
bottom_right.add(tf2); int w2 = w / 2;
bottom_panel.add(bottom_left,Bo if(figure == 2){
rderLayout.WEST); Polygon poly;
bottom_panel.add(bottom_right,B g2.setPaint( Color.green );
orderLayout.CENTER); poly = new Polygon();
bottom_panel.add(label5,BorderL poly.addPoint( w2 - s, h -
ayout.SOUTH); margin );
add(top_panel,BorderLayout.NOR poly.addPoint( w2 + s, h -
TH); margin );
add(middle_panel,BorderLayout.C poly.addPoint( w2, h - margin -
ENTER); s );
add(bottom_panel,BorderLayout.S active.add(poly);
OUTH); if(fill_out){
public void g2.fill( poly );
paintComponent(Graphics g){ }else{
super.paintComponent(g); g2.draw( poly );
Graphics2D g2 = (Graphics2D) g; }
int w = getWidth(), h = //poly.reset();
getHeight(); }
int margin = h/2;

You might also like