3.2 Creating Data Types
In this section, we introduce the Java mechanism that enables us
to create user-defined data types.
We consider a range of examples, from charged particles and complex
numbers to turtle graphics and stock accounts.
Basic elements of a data type.
To illustrate the process, we define in Charge.java a data type for charged particles. Coulomb’s law tells us that the electric potential at a point \((x, y)\) due to a given charged particle is \(V = kq /r\), where \(q\) is the charge value, \(r\) is the distance from the point \((x, y)\) to the charge, and \(k = 8.99 \times 10^9\) is the electrostatic constant.- API.
The application programming interface is the contract with all clients and,
therefore, the starting point for any implementation.
- Class. In Java, you implement a data type in a class. As usual, we put the code for a data type in a file with the same name as the class, followed by the .java extension.
- Access modifiers. We designate every instance variable and method within a class as either public (this entity is accessible by clients) or private (this entity is not accessible by clients). The final modifier indicates that the value of the variable will not change once it is initialized—its access is read-only.
- Instance variables.
We declare instance variables to represent the data-type values in the same
way as we declare local variables,
except that these declarations appear as the first statements in the class,
not inside main() or any other method.
For Charge,
we use three double variables—two to describe the charge’s position
and one to describe the amount of charge.
- Constructors.
A constructor is a special method that creates an object and provides
a reference to that object.
Java automatically invokes a constructor when a client program uses the keyword new.
Each time that a client invokes a constructor, Java automatically
- Allocates memory for the object
- Invokes the constructor code to initialize the instance variables
- Returns a reference to the newly created object
The constructor in Charge is typical: it initializes the instance variables with the values provided by the client as arguments.
- Instance methods.
To implement instance methods, we write code that
is precisely like code for implementing static methods.
The one critical distinction is that instance methods
can perform operations on instance variables.
- Variables within methods.
The Java code we write to implement instance methods uses three kinds of variables.
Parameter variables and local variables are familiar.
Instance variables are completely different: they hold data-type
values for objects in a class.
- Test client. Each class can define its own main() method, which we reserve for unit testing. At a minimum, the test client should call every constructor and instance method in the class.
Stopwatch.
Stopwatch.java implements the following API:
It is a stripped-down version of an old-fashioned stopwatch. When you create one, it starts running, and you can ask it how long it has been running by invoking the method elapsedTime().
Histogram.
Histogram.java is a data type to visualize data using a familiar plot known as a histogram. For simplicity, we assume that the data consists of a sequence of integer values between 0 and n−1. A histogram counts the number of times each value appears and plots a bar for each value (with height proportional to its frequency). The following API describes the operations:
Turtle graphics.
Turtle.java is a mutable type for turtle graphics, in which we command a turtle to move a specified distance in a straight line, or rotate (counterclockwise) a specified number of degrees.Here are a few example clients:
- Regular n-gons. Ngon.java takes a command-line argument n and draws a regular n-gon using turtle graphics. By taking n to a sufficiently large value, we obtain a good approximation to a circle.
- Recursive graphics.
Koch.java takes a command-line argument
n and draws a
Koch curve of
order n.
A Koch curve of order order 0 is a line segment.
To form a Koch curve of order n:
- Draw a Koch curve of order n−1
- Rotate 60° counterclockwise
- Draw a Koch curve of order n−1
- Rotate 120° clockwise
- Draw a Koch curve of order n−1
- Rotate 60° counterclockwise
- Draw a Koch curve of order n−1
Below are the Koch curves of order 0, 1, 2, and 3.
- Spira mirabilis.
Spiral.java
takes an integer n and a decay factor as command-line arguments,
and instructs the turtle to alternately step and turn until it has wound around itself 10 times.
This produces a geometric shape known as a
logarithmic spiral,
which arise frequently in nature.
Three examples are depicted below: the chambers of a nautilus shell,
the arms of a spiral galaxy, and the cloud formation in a tropical storm.
This Wikipedia image is from user Chris 73,
and is available via the CC by-SA 3.0 license.Photo: NASA and ESA
Photo: NASA
- Brownian motion. DrunkenTurtle.java plots the path followed by a disoriented turtle, who alternates between moving forward and turning in a random direction. This process is known as Brownian motion. DrunkenTurtles.java plots many such turtles, all of whom wander around.
Complex numbers.
A complex number is a number of the form x + iy, where x and y are real numbers and i is the square root of −1. The basic operations on complex numbers are to add and multiply them, as follows:- Addition: \((x_0+iy_0) + (x_1+iy_1) = (x_0+x_1) + i\,(y_0+y_1)\)
- Multiplication: \((x_0 + iy_0) \cdot (x_1 + iy_1) = (x_0x_1 - y_0y_1) + i\,(y_0x_1 + x_0y_1)\)
- Magnitude: \(\left | x + iy \right | = \sqrt{x^2 + y^2}\)
- Real part: \(\operatorname{Re}(x + iy) = x\)
- Imaginary part: \( \operatorname{Im}(x + iy) = y\)
This data type introduces a few new features.
- Accessing values of other objects of the same type. The instance methods plus() and times() each need to access values in two objects: the object passed as an argument and the object used to invoke the method. If we call the method with a.plus(b), we can access the instance variables of a using the names re and im, as usual. However, to access the instance variables of b, we use the code b.re and b.im.
- Creating and returning new objects. Observe the manner in which plus() and times() provide return values to clients: they need to return a Complex value, so they each compute the requisite real and imaginary parts, use them to create a new object, and then return a reference to that object.
- Chaining method calls. Observe the manner in which main() chains two method calls into one compact expression z.times(z).plus(z0), which corresponds to the mathematical expression z2 + z0.
- Final instance variables. The two instance variables in Complex are final, meaning that their values are set for each Complex object when it is created and do not change during the lifetime of that object.
Mandelbrot set.
The Mandelbrot set is a specific set of complex numbers with many fascinating properties. The algorithm for determining whether or not a complex number \(z_0\) is in the Mandelbrot set is simple: Consider the sequence of complex numbers \(z_0, z_1, z_2, \ldots, z_t, \ldots,\) where \(z_{i+1} = z_i^2 + z_0\). For example, the following table shows the first few entries in the sequence corresponding to \(z_0 = 1 + i\):
Now, if the sequence \( | z_i |\) diverges to infinity, then \(z_0\) is not in the Mandelbrot set; if the sequence is bounded, then \(z_0\) is in the Mandelbrot set. For many points, the test is simple; for many other points, the test requires more computation, as indicated by the examples in the following table:
To visualize the Mandelbrot set, we define an evenly spaced n-by-n pixel grid within a specified square and draw a black pixel if the corresponding point is in the Mandelbrot set and a white pixel if it is not.
But how do we determine whether a complex number is in the Mandelbrot set? For each complex number, Mandelbrot.java computes up to 255 terms in its sequence. If the magnitude ever exceeds 2, then we can conclude that the complex number is not in the set (because it is known that the sequence will surely diverge). Otherwise, we conclude that the complex number is in the set (knowing that our conclusion might be wrong on occasion).
Commercial data processing.
StockAccount.java implements a data type that might be used by a financial institution to keep track of customer information.
Exercises
- Develop an implementation Rectangle.java of your Rectangle API from Exercise 3.2.1 that that represents rectangles with the x- and y-coordinates of their lower-left and upper-right corners. Do not change the API.
-
Implement a data type Rational.java
numbers that supports addition, subtraction, multiplication,
and division.
-
Write a data type Interval.java
that implements the following API:
-
Write a data type Point.java
that implements the following API:
- Modify the toString() method in Complex.java so that it complex numbers in the traditional format. For example, it should print the value \(3-i\) as 3 - i instead of 3.0 + -1.0i, the value 3 as 3 instead of 3.0 + 0.0i and the value \3i\) as 3i instead of 0.0 + 3.0i.
- Write a Complex client RootsOfUnity.java that takes two double values a and b and an integer n from the command line and prints the nth root of \(a + bi\).
-
Implement the following additions to Complex.java:
Write a test client that exercises all of your methods.
-
Suppose you want to add a constructor to Complex.java
that takes a double value as its argument and creates a
Complex number with that value as the real part (and no imaginary part).
You write the following code:
public void Complex(double real) { re = real; im = 0.0; }
Solution: Constructors do not have return types, not even void. This code defines method named Complex(), not a constructor. Remove the keyword void.
Creative Exercises
-
Electric potential visualization.
Write a program Potential.java
that creates an array of charged particles from values given
on standard input (each charged particle is specified by its
x-coordinate, y-coordinate, and charge value) and
produces a visualization of the electric potential in the unit square.
To do so, sample points in the unit square. For each sampled point,
compute the electric potential at that point (by summing the
electric potentials due to each charged particle) and plot the
corresponding point in a shade of gray proportional to the
electric potential.
-
Quaternions.
In 1843, Sir William Hamilton discovered an extension to complex
numbers called
quaternions.
Quaternions extend the concept of rotation in three dimensions to
four dimensions. They are used in computer graphics, control theory,
signal processing, and orbital mechanics, e.g., command for
spacecraft attitude control systems.
are related to Pauli spin matrices in physics.
Create a date type Quaternion.java
to represent quaternions.
Include operations for adding, multiplying, inverting, conjugating,
and taking the norm of quaternions.
A quaternion can be represented by a 4-tuple of real numbers \((a_0, a_1, a_2, a_3)\), which represents \(a_0 + a_1 i + a_2 j + a_3 k\). The fundamental identity is \(i^2 = j^2 = k^2 = ijk = -1\).
- Magnitude: \( \left \| a \right \| = \sqrt{a_0^2 + a_1^2 + a_2^2 + a_3^2} \)
- Conjugate: \( a^* = (a_0, -a_1, -a_2, -a_3)\)
- Inverse: \( a^{-1} = (a_0\,/\, \left \| a \right \|^2, -a_1\,/\, \left \| a \right \|^2, -a_2\,/\, \left \| a \right \|^2, -a_3\,/\, \left \| a \right \|^2)\)
- Sum: \( a + b = (a_0+b_0, a_1+b_1, a_2+b_2, a_3+b_3)\)
- Hamilton product: $$ \begin{align} a \times b \; = \; (& a_0b_0 - a_1b_1 - a_2b_2 - a_3b_3, \\ & a_0b_1 + a_1b_0 + a_2b_3 - a_3b_2, \\ & a_0b_2 - a_1b_3 + a_2b_0 + a_3b_1, \\ & a_0b_3 + a_1b_2 - a_2b_1 + a_3b_0) \end{align} $$
- Quotient: \( a\,/\,b = a^{-1} \times b \)
-
Dragon curve.
Write a program Dragon.java that
reads in a command-line parameter N and plots the order N dragon
curve using turtle graphics. The dragon curve was first discovered
by three NASA physicists (John E. Heighway, Bruce A.
Banks, and William G. Harter) and later popularized by Martin Gardner in Scientific
American (March and April 1967) and Michael Crichton in Jurassic Park.
This is a sophisticated program that uses two mutually recursive functions.
Program SequentialDragon.java is an iterative version of the dragon curve. It is a hacker's paradise.
- Hilbert curves.
A space-filling
curve is a continuous curve in the unit square that passes through every point.
Write a recursive Turtle client
Hilbert.java
(or SingleHilbert.java)
that produces these recursive patterns, which approach a space-filling curve
that was defined by the mathematician David Hilbert at the end of the 19th century.
-
Gosper island.
Write a recursive Turtle client
GosperIsland.java
that produces these recursive patterns.
-
Chaos with Newton's method.
The polynomial \(f(z) = z^4 - 1\) has 4 roots at 1, −1, i,
and −i.
We can find the roots using Newton's method in the complex
plane: \(z_{k+1} = z_k - f(z_k) \,/ \, f'(z_k)\).
Here \(f(z) = z^4 - 1\) and \(f'(z) = 4z^3\).
The method converges to one of the 4 roots depending on the starting
point \(z_0\).
Write a
program NewtonChaos.java
that takes a command-line argument n and creates an
n-by-n image corresponding to the square of
size 2 centered at the origin. Color each pixel white, red,
green, or blue according to which of the four roots the corresponding
complex number converges (black if no convergence after
100 iterations).
-
Color Mandelbrot plot.
Create a file of 256 integer triples
that represent interesting Color values,
and then use those colors instead of grayscale values to plot each pixel
in ColorMandelbrot.java
Read the values to create an array of 256 Color values,
then index into that array with the return value of mand().
By experimenting with various color choices at various places in the set,
you can produce astonishing images. See
mandel.txt for an example.
-1.5 -1.0 2.0 2.0 0.10259 -0.641 0.0086 0.0086 -
Julia sets.
The Julia set for a given complex number c
is a set of points related to the Mandelbrot function.
Instead of fixing z and varying c, we fix c and vary z.
Those points z for which the modified Mandelbrot function stays bounded
are in the Julia set; those for which the sequence diverges to infinity are not in the set.
All points z of interest lie in the 4-by-4 box centered at the origin.
The Julia set for c is connected if and only if c is in the Mandelbrot set!
Write a program ColorJulia.java
that takes two command-line arguments a and b,
and plots a color version of the Julia set for c = a + bi,
using the color-table method described in the previous exercise.
-1.25 0.00 -0.75 0.10
Web Exercises
- IP addresses. Create a data type for IPv4 (Internet Protocol, version 4) addresses. An IP address is a 32-bit integer.
- Dates. Create a data type Date that represents a date. You should be able to create a new Date by specifying the month, day, and year. It should supports methods to compute the number of days between two dates, return the day of the week that a day falls on, etc.
- Time bombs. UNIX represents the date with a signed integer measuring the number of seconds since January 1, 1970. Write a client program to calculate when this date will occur. Add a static method add(Date d, int days) to your date data type that returns a new date which is the specified number of days after the date d. Note that there are 86,400 seconds in a day.
- Qubits. In quantum computing, a qubit plays the role of a bit. It is a complex number a + bi such that |a + bi| = 1. Once we measure a qubit, it "decides" to be a 1 with probability a2 and a 0 with probability b2. Any subsequent observations will always yield the same value. Implement a data type Qubit that has a constructor Qubit(a, b) and a boolean method observe that returns true or false with the proscribed probabilities.
- Biorhythms. A biorhythm is a pseudo-scientific profile of the three natural cycles of your body: physical (23 days), emotional (28 days), and intellectual (31 days). Write a program that takes six command line inputs M, D, Y, m, d, and y where (M, D, Y) is the month (1-12), day (1-31), and year (1900-2100) of your birthday and (m, d, y) is today's month, day, and year. It should then print out your biorhythm on a scale of -1.0 to 1.0 according to the formula: sin (2 π age / cycle length). Use the date data type created in the previous exercise.
- Particle. Create a data type for elementary or composite particles (electron, proton, quark, photon, atom, molecule). Each particle should have an instance variable to store its name, its mass, its charge, and its spin (multiple of 1/2).
- Quark. Quarks are the smallest known building blocks of matter. Create a data type for quarks. Include a field for its type (up, down, charm, strange, top, or bottom) and its color (red, green, or blue). The charges are +2/3, -1/3, +2/3, -1/3, +2/3, -1/3, respectively. All have spin 1/2.
- Biorhythms. Plot your biorhythm in turtle graphics over a 6 week interval. Identify critical days when your rhythm goes from positive to negative - according to biorhythm theory, this is when you are most prone to accident, instability, and error.
- Vector3. Include normal vector operations for 3-vectors, including cross product. The cross product of two vectors is another vector. a cross b = ||a|| ||b|| sin(theta) n, where theta is angle between a and b, and n is unit normal vector perpendicular to both a and b. (a1, a2, a3) cross (b1, b2, b3) = (a2 b3 - a3 b2, a3 b1 - a1 b3, a1 b2 - a2 b1). Note that |a cross b| = area of the parallelogram with sides a and b. Cross product arises in definition of torque, angular momentum and vector operator curl.
- Four-vector. Create a data type for four-vectors. A four-vector is a four-dimensional vector (t, x, y, z) subject to Lorentz transformations. Useful in special relativity.
- Euclidean points. Create a data type EuclideanPoint.java that represents a d-dimensional point. Include a method so that p.distanceTo(q) returns the Euclidean distance between points p and q.
- Vector field. A vector field associates a vector with every point in a Euclidean space. Widely used in physics to model speed and direction of a moving object or or strength and direction of a Newtonian force.
- Soda machine. Create a data type SodaMachine that has methods insertCoin(), getChange(), buy(), etc.
- Months.
Write a data type Month that represents one of
the twelve months of the year. It should have fields for
the name of the month, the number of days in the month,
and the birthstone.
MONTH DAYS BIRTHSTONE January 31 Garnet February 28 Amethyst March 31 Aquamarine April 30 Diamond May 31 Emerald June 30 Alexandrite July 31 Ruby August 31 Peridot September 30 Sapphires October 31 Opal November 30 Topaz December 31 Blue Zircon
- Gauss multiplication. Implement complex multiplication using only 3 floating point multiplications (instead of 4). You may use as many as 5 floating point additions. Answer: Gauss gave the following method to multiply (a + bi)(c + di). Set x1 = (a + b)(c + d), x2 = ac, x3 = bd. Then the product is given by x + yi where x = x2 - x3, y = x1 - x2 - x3.
- Tensors. Create a data type for tensors.
- UN Countries. Create a data type Country for UN countries. Include fields for 3 digit UN Code, 3 letter ISO abbreviation, country name, and capital. Write a program Country.java that reads in a list of countries and stores them in an array of type Country. Use the method String.split to help parse the input file.
- Area codes. Create a data type for telephone area codes in North America. Include fields for the area code, the city, and state, and the two letter state abbreviation. Or for international phone codes. Include a field for zone, code, and country.
- Congressional districts. Create a data type for places, counties, and congressional districts. Include fields for place name, county name, county code, zip code, congressional district, etc. Use the data sets from the 1998 FIPS55-DC3 Index: Pennsylvania (2MB) or all 50 states plus DC and 9 outlying areas (30MB).
- Latitudes and longitudes. For USA latitudes and longitudes, use the TIGER database or www.bcca.org or gazetteer. For the rest of the world, use earth-info.
- Astronomy. Data for asteroids, meteors, and comets.
- Fortune 1000 companies. Create a data type the for Fortune 1000. Include fields for company name and sales revenue in millions of dollars. Data taken from April 15, 2002 issue of Fortune. Note: currently need to parse data.
- Molecular weight. Write a program so that the user enters a molecule H2 O and the program calculates its molecular weight.
- Some potentially useful datafiles: aroma therapies, nutritional information, meteorological glossary, psychiatric disorders, words translated in 15 languages, dictionary of emoticons, meanings of common names, World Almanac facts about countries.
- Student records. Create a data type Student.java to represent students in an introductory computer science course. Each student record object should represent a first name, last name, email address, and section number. Include a toString() method that returns a string representation of a student and a less() method that compares two students by section number.
- Impedance.
Impedance is the generalization of resistance from DC circuits
to AC circuits.
In an AC circuit, the impedance of a component
measures its opposition to the flow of electrons at a given
frequency ω. The impedance has two components: the resistance
and the reactance.
The resistance R of a circuit component measures its
opposition to the movement of electrons (friction against
motion of electrons) when a given voltage is applied.
The reactance X of a circuit component measures its
ability to store and release energy as the current and voltage
fluctuate (inertia against motion of electrons).
In circuits with resistors only, the current is directly proportional to the voltage. However, with capacitors and inductors, there is a +- 90 degree "phase shift" between the current and voltage. This means that when the voltage wave is at its maximum, the current is 0, and when the current is at its maximum the voltage is 0. To unify the treatment of resistors (R), inductors (L), and capacitors (C) it is convenient to treat the impedance as the complex quantity Z = R + iX. the impedance of an inductor is iwL and the impedance of a capacitor is 1/iwC. To determine the impedance of a sequence of circuit elements in series, we simply add up their individual impedances. Two important quantities in electrical engineering are themagnitude of the impedance and the phase angle. The magnitude is the ratio of the RMS voltage to the RMS current - it equals the magnitude of the complex impedance. The phase angle is the amount by which the voltage leads or lags the current - it is the phase of the complex impedance. Program CircuitRLC.java does a computation involving complex numbers and impedance of circuits with resistors, inductors, and capacitors in series.
Exercise: RLC circuit in parallel. 1/Z = 1/Z1 + 1/Z2 + ... 1/Zn.
Exercise (for objects): repeat series-parallel network for RLC circuits with impedances instead of resistance
- Diffusion of particles in a fluid. Simulate diffusion of particles in a fluid. See BrownianParticle.java in Section 9.8.
- Electric field lines.
Michael Faraday introduced an abstraction called electric field lines
to visualize the electric field.
By Coulombs law, the electric field at a point induced by a point
charge qi is given by Ei = k qi / r2,
and the direction points to qi if qi is negative and
away from qi it is positive.
If there are a group of n point charges, the electric field at a point is
the vector sum of the electric fields induced by the n individual
point charges. We can compute it by summing up the components in the x- and y-
directions. The figure below illustrates the field lines for two equal
positive point charges (left) and two point charges of opposite signs (right).
The second configuration is called an electric dipole:
the charges cancel each other out, and the electric field weakens very
quickly as you move away from the charges. Examples of dipoles can be found
in molecules where charge is not evenly distributed. Oscillating dipoles
can be used to produce electromagnetic waves to transmit radio and television signals.
Program FieldLines.java draws 10 electric field lines coming out of each charge. (We take some liberties since traditionally the number of field lines per unit area should be proportional to the magnitude of the field strength.) Each line starts on a 1-pixel circle around the charge, at twelve equally spaced angles. The electric field at a point (x, y) from a point charge qi is given by Ei = k qi / r2, where qi is the magnitude of the charge i and r is the radial distance from it. The field due to several charges is the vector sum of the field due to each, and can be found by adding the x- and y-components. After calculating the electric field strength, we move in the direction of the vector field and draws a spot. We repeat this process until we reach the boundary of the region or another point charge. The figures below illustrate the electric potential and field lines for several random charges of equal magnitude.
- Koch snowflake with rainbow of colors.
The Koch snowflake of order n consists of three copies of the Koch curve of over n. We draw the three Koch curves one after the other, but rotate 120° clockwise in between. Below are the Koch snowflakes of order 0, 1, 2, and 3. Write a program KochRainbow.java that plots the Koch snowflake in a continuous spectrum of colors from red, to orange, yellow, green, blue, and indigo, and violet.
- Anti-Koch snowflakes.
The anti-Koch snowflake is generated exactly like
the Koch snowflake, except that clockwise and counterclockwise
are interchanged. Write a program AntiKoch.java that
takes a command line parameter N and plots the anti-Koch snowflake
of order N using Turtle graphics.
- Randomized Koch snowflakes. A randomized Koch snowflake is generated exactly like the Koch snowflake, except that we flip a coin to generate the clockwise and counterclockwise direction at each step.
- Turtle graphics.
- Minkowski sausage. (Sausage.java)
-
Cesaro broken square.
- Minkowski sausage. (Sausage.java)
- More turtle graphics.
Write a program to produce each of the following recursive patterns.
- Levy tapestry. (Levy.java)
- Fudgeflake.
- Levy tapestry. (Levy.java)
-
Turtle graphics (hard).
Write a program to produce each of the following recursive patterns
without lifting the pen or tracing over the same line segment more
than once.
-
Sierpinski arrowhead.
-
Sierpinski curve.
-
Sierpinski arrowhead.
- Mandelbrot trajectory. Write an interactive program Trajectory.java that plots the sequence of points in the Mandelbrot iteration in the complex plane. If the user clicks on (x, y), plot the sequence of iterates for z = x + iy.
- Faster Mandelbrot. Speed up Mandelbrot by performing the computation directly instead of using Complex. Compare. Incorporate periodicity checking or boundary tracing for further improvements. Use divide-and-conquer: choose 4 corners of a rectangle and a few random points inside; if they're all the same color, color the whole rectangle that color; otherwise divide into 4 rectangles and recur.
- Random walker. Write a data type RandomWalker that simulates the motion of a random walker in the plane that starts at the origin and makes a random step (left, right, up, or down) at each step. Include a method step() that moves the random walker one step and a method distance() that returns the distance the random walker is from the origin. Use this data type to formulate a hypothesis as to how far (as a function of N) the random walker is from the origin after N steps. (See also Exercise 1.x.)
- Big rational numbers. Create a data type BigRational.java for positive rational numbers, where the numerators and denominators can be arbitrarily large. Hint: use java.math.BigInteger
- Deluxe turtle graphics. Extend Turtle in various ways. Make DeluxeTurtle that adds color, etc. Add a version that supports error checking. For example, throw a TurtleOutOfBounds exception if turtle goes outside designated boundary.
- Write a program FourChargeClient.java that takes a double command-line argument r, creates four Charge objects that are each distance r from the center of the screen (0.5, 0.5), and prints the potential at location (0.25, 0.5) due to the combined four charges. All four charges should have the same unit charge.
-
Why does program Bug1.java create a
java.lang.NullPointerException when executed?
public class Bug1 { private String s; public void Bug1() { s = "hello"; } public String toString() { return s.toUpperCase(); } public static void main(String[] args) { Bug1 x = new Bug1(); StdOut.println(x); } }
Answer: the programmer probably intended to make the no argument constructor set the string to hello. However, it has a return type (void) so it is an ordinary instance method instead of a constructor. It just happens to have the same name as the class.
- Why does program Bug2.java create a java.lang.NullPointerException when executed?
- Implement a data type Die for rolling a fair die, say with 6 sides. Include a mutator method roll() and an accessor method value.
- Implement a mutable data type LFSR for a linear feedback shift register.
- Implement a mutable data type Odometer.
- Complex trigonometric functions.
Add methods to Complex.java
support trigonometric and exponential functions on complex numbers.
- \(\exp(a + ib) = e^a \cos(b) + i \, e^a \sin(b)\)
- \(\sin(a + ib) = \sin(a) \cosh(b) + i \cos(a) \sinh(b)\)
- \(\cos(a + ib) = \cos(a) \cosh(b) - i \sin(a) \sinh(b)\)
- \(\tan(a + ib) = \sin(a + ib) \;/\; \cos(a + ib)\)
- Implement a data type VotingMachine for tabulating votes. Include mutator methods voteRepublican(), voteDemocrat(), and voteIndependent(). Include an accessor method getCount() to retrieve the total number of votes.
-
What happens when you try to compile and execute the following code fragment?
Student x; StdOut.println(x);
Answer: it complains that x may not be initialized, and does not compile.
-
What happens when you try to compile and execute the following code fragment?
Student[] students = new Student[10]; StdOut.println(students[5]);
Answer: it compiles and prints out null.
-
What is wrong with the following code fragment?
int n = 17; Dog[] dogs = new Dog[n]; for (int i = 0; i < n; i++) { dogs[i].bark(); dogs[i].eat(); }
Answer: it produces a NullPointerException because we forgot use new to create each individual Dog object. To correct, add the following loop after the array initialization statement.
for (int i = 0; i < n; i++) dogs[i] = new Dog();
-
What does the following code fragment print?
Complex c = new Complex(2.0, 0.0); StdOut.println(c); StdOut.println(c.mul(c).mul(c).mul(c)); StdOut.println(c);
-
What's wrong with the following code fragment that swaps
the Student objects x and y?
Student swap = new Student(); swap = x; x = y; y = swap;
Answer: First, the data type Student does not have a no-argument constructor. If it did, then it would technically be correct, but the new Student() line is unnecessary and wasteful. It allocates memory for a new student object, sets swap equal to that memory address, then immediately sets swap equal to the memory address of x. The allocated memory is no longer accessible. The following version is correct.
Student swap = x; x = y; y = swap;
- Find inputs to the Mandelbrot update formula that make it converge (z0 = 1/2 + 0i), cycle with a period of 1 (z0 = -2 + 0i), cycle with a period of 2 (z0 = -1 + 0i), or stay bounded without converging (z0 = -3/2 + 0i).
- Point3D. Create a data type for points in 3 dimensional space. Include a constructor that takes three real coordinates x, y, and z. Include methods distance, distanceSquared, and distanceL1 for the Euclidean distance, Euclidean distance squared, and the L1-distance.
- Create a data type PhoneNumber.java that represents a US phone number. The constructor should take three string arguments, the area code (3 decimal digits), the exchange (3 decimal digits) and the extension (4 decimal digits). Include a toString method that prints out phone numbers of the form (800) 867-5309. Include a method so that p.equals(q) returns true if the phone numbers p and q are the same, and false otherwise.
- Redo PhoneNumber.java
but implement it using three integer fields. Make the
constructor take three integer arguments. Comment on the advantages
and disadvantages of this approach over the string representation.
Answer: more efficient with time and memory. More hassle to handle leading 0s correct in constructor and toString method.
- Write a program to draw the field lines for a uniform field. Arrange N evenly-spaced particles with charge e in a vertical column, and arrange N particles with charge -e in a vertical column so that each charge on one side is lined up with a corresponding charge on the other side. This simulates the field inside a plane capacitor. What can you say about the resulting electric field? A. Almost uniform.
- Equipotential surfaces.
An equipotential surface is the set of all
points that have the same electric potential V. Given a group of N
point charges, it is useful to visualize the electric potential
by plotting equipotential surfaces (aka contour plots).
Program Equipotential.java
draws a line every 5V by computing the potential at each
gridpoint and checking whether the potential is within 1 pixel of a multiple of
5V. Since the electric field E measures how much the potential changes,
E * eps is the range that the potential changes in a distance of 1 pixel.
It relies on the helper program
DeluxeCharge.java.
It is also interesting to plot the field lines and the equipotential lines simultaneously. The field lines are always perpendicular the the equipotential lines.
- Color palettes.
Create Mandelbrot and Julia sets using different color palettes.
For example, this scheme was proposed by Hubert Grassmann
Color[] colors = new Color[ITERS]; for (int t = 0; t < ITERS; t++) { // or some other primes int r = 13*(256-t) % 256; int g = 7*(256-t) % 256; int b = 11*(256-t) % 256; colors[t] = new Color(r, g, b); }