0% found this document useful (0 votes)
0 views

Oop Java Bloch

Uploaded by

mcknucklecuck
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views

Oop Java Bloch

Uploaded by

mcknucklecuck
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 44

Principles of Software Construction:

Objects, Design, and Concurrency

Object-Oriented Programming in Java

Josh Bloch Charlie Garrod

17-214 1
Administrivia
• Homework 1 due Thursday 11:59 p.m., EDT
– Everyone must read and sign our collaboration policy
• First reading assignment due Today
– Effective Java Items 15 and 16

17-214 2
Key concepts from Thursday
• Bipartite type system – primitives & object refs
• Single implementation inheritance
• Multiple interface inheritance
• Easiest output – println , printf
• Easiest input – Command line args, Scanner

17-214 3
Outline
I. A brief introduction to collections
II. More object-oriented programming
III. Information hiding (AKA encapsulation)
IV. Enums (if time)

17-214 4
Primary collection interfaces

Collection Map

Set List Queue

Deque

17-214 5
“Primary” collection implementations

Interface Implementation
Set HashSet
List ArrayList
Queue ArrayDeque
Deque ArrayDeque
(stack) ArrayDeque
Map HashMap

17-214 6
Other noteworthy collection implementations

Interface Implementation(s)
Set LinkedHashSet
TreeSet
EnumSet
Queue PriorityQueue
Map LinkedHashMap
TreeMap
EnumMap

17-214 7
Collections usage example 1
Squeezes duplicate words out of command line

$ java Squeeze I came I saw I conquered


[I, came, saw, conquered]

public class Squeeze {


public static void main(String[] args) {
Set<String> s = new LinkedHashSet<>();
for (String word : args)
s.add(word);
System.out.println(s);
}
}

17-214 8
Collections usage example 2
Prints unique words in alphabetical order

$ java Lexicon I came I saw I conquered


[I, came, conquered, saw]

public class Lexicon {


public static void main(String[] args) {
Set<String> s = new TreeSet<>(); // Sole change!
for (String word : args)
s.add(word);
System.out.println(s);
}
}

17-214 9
Collections usage example 2a
Prints unique words in case-independent alphabetical order

$ java Lexicon I came I saw I conquered


[came, conquered, I, saw]

public class Lexicon {


public static void main(String[] args) {
Set<String> s =
new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
for (String word : args)
s.add(word);
System.out.println(s);
}
}

17-214 10
Collections usage example 3
Prints the index of the first occurrence of each word

$ java Index if it is to be it is up to me to do it
{be=4, do=11, if=0, is=2, it=1, me=9, to=3, up=7}

class Index {
public static void main(String[] args) {
Map<String, Integer> index = new TreeMap<>();

// Iterate backwards so first occurrence wins


for (int i = args.length - 1; i >= 0; i--) {
index.put(args[i], i);
}
System.out.println(index);
}
}

17-214 11
More information on collections
• For much more information on collections,
see the annotated outline:

https://docs.oracle.com/javase/11/docs/technotes
/guides/collections/reference.html

• For more info on any library class, see javadoc


– Search web for <fully qualified class name> 11
– e.g., java.util.scanner 11

17-214 12
What about arrays?
• Arrays aren’t a part of the collections framework
• But there is an adapter: Arrays.asList
• Arrays and collections don’t mix well
• If you try to mix them and get compiler
warnings, take them seriously
• Generally speaking, prefer collections to arrays
– But arrays of primitives (e.g., int[]) are preferable
to lists of boxed primitives (e.g., List<Integer>)
• See Effective Java Item 28 for details
17-214 13
To learn Java quickly

17-214 14
Outline
I. A brief introduction to collections
II. More object-oriented programming
III. Information hiding (AKA encapsulation)
IV. Enums

17-214 15
Objects – review
• An object is a bundle of state and behavior
• State – the data contained in the object
– Stored in the fields of the object
• Behavior – the actions supported by the object
– Provided by methods
• Method is just OO-speak for function
• Invoke a method = call a function

17-214 16
Classes – review
• Every object has a class
– A class defines methods and fields
– Methods and fields collectively known as members
• Class defines both type and implementation
– Type ≈ what the object is and where it can be used
– Implementation ≈ how the object does things
• Loosely speaking, the methods of a class are its
Application Programming Interface (API)
– Defines how users interact with instances

17-214 17
Class example – complex numbers
class Complex {
final double re; // Real Part
final double im; // Imaginary Part

public Complex(double re, double im) {


this.re = re;
this.im = im;
}

public double realPart() { return re; }


public double imaginaryPart() { return im; }
public double r() { return Math.sqrt(re * re + im * im); }
public double theta() { return Math.atan(im / re); }

public Complex add(Complex c) {


return new Complex(re + c.re, im + c.im);
}
public Complex subtract(Complex c) { ... }
public Complex multiply(Complex c) { ... }
public Complex divide(Complex c) { ... }
}
17-214 18
Class usage example
public class ComplexUser {
public static void main(String args[]) {
Complex c = new Complex(-1, 0);
Complex d = new Complex( 0, 1);

Complex e = c.plus(d);
System.out.printf("Sum: %d + %di%n",
e.realPart(), e.imaginaryPart());
e = c.times(d);
System.out.printf("Product: %d + %di%n",
e.realPart(), e.imaginaryPart());
}
}

When you run this program, it prints


Sum: -1.0 + 1.0i
Product: -0.0 + -1.0i

17-214 19
Interfaces and implementations
• Multiple implementations of an API can coexist
– Multiple classes can implement the same API
• In Java, an API is specified by class or interface
– Class provides an API and an implementation
– Interface provides only an API
– A class can implement multiple interfaces
• Remember diagram: ElectricGuitar implements
StringedInstrument, ElectricInstrument

17-214 20
An interface to go with our class
public interface Complex {
// No constructors, fields, or implementations!

double realPart();
double imaginaryPart();
double r();
double theta();

Complex plus(Complex c);


Complex minus(Complex c);
Complex times(Complex c);
Complex dividedBy(Complex c);
}

An interface defines but does not implement API

17-214 21
Modifying class to use interface
class OrdinaryComplex implements Complex {
final double re; // Real Part
final double im; // Imaginary Part

public OrdinaryComplex(double re, double im) {


this.re = re;
this.im = im;
}

public double realPart() { return re; }


public double imaginaryPart() { return im; }
public double r() { return Math.sqrt(re * re + im * im); }
public double theta() { return Math.atan(im / re); }

public Complex add(Complex c) {


return new OrdinaryComplex(re + c.realPart(), im + c.imaginaryPart());
}
public Complex subtract(Complex c) { ... }
public Complex multiply(Complex c) { ... }
public Complex divide(Complex c) { ... }
}
17-214 22
Modifying client to use interface
public class ComplexUser {
public static void main(String args[]) {
Complex c = new OrdinaryComplex(-1, 0);
Complex d = new OrdinaryComplex(0, 1);

Complex e = c.plus(d);
System.out.printf("Sum: %d + %di%n",
e.realPart(), e.imaginaryPart());
e = c.times(d);
System.out.printf("Product: %d + %di%n",
e.realPart(), e.imaginaryPart());
}
}

When you run this program, it still prints


Sum: -1.0 + 1.0i
Product: -0.0 + -1.0i

17-214 23
Interface enables multiple implementations
class PolarComplex implements Complex {
final double r; // Different representation!
final double theta;

public PolarComplex(double r, double theta) {


this.r = r;
this.theta = theta;
}

public double realPart() { return r * Math.cos(theta) ; }


public double imaginaryPart() { return r * Math.sin(theta) ; }
public double r() { return r; }
public double theta() { return theta; }

public Complex plus(Complex c) { ... } // Different implementation!


public Complex minus(Complex c) { ... }
public Complex times(Complex c) {
return new PolarComplex(r * c.r(), theta + c.theta());
}
public Complex dividedBy(Complex c) { ... }
}
17-214 24
Interface decouples client from implementation
public class ComplexUser {
public static void main(String args[]) {
Complex c = new PolarComplex(1, Math.PI); // -1
Complex d = new PolarComplex(1, Math.PI/2); // i

Complex e = c.plus(d);
System.out.printf("Sum: %d + %di%n",
e.realPart(), e.imaginaryPart());
e = c.times(d);
System.out.printf("Product: %d + %di%n",
e.realPart(), e.imaginaryPart());
}
}

When you run this program, it still prints


Sum: -1.0 + 1.0i
Product: -0.0 + -1.0i

17-214 25
Why multiple implementations?
• Different performance
– Choose implementation that works best for your use
• Different behavior
– Choose implementation that does what you want
– Behavior must comply with interface spec (“contract”)
• Often performance and behavior both vary
– Provides a functionality – performance tradeoff
– Example: HashSet, LinkedHashSet, TreeSet

17-214 26
Prefer interfaces to classes as types
…but don’t overdo it
• Use interface types for parameters and variables
unless a single implementation will suffice
– Supports change of implementation
– Prevents dependence on implementation details
• But sometimes a single implementation will suffice
– In which cases write a class and be done with it

Set<Criminal> senate = new HashSet<>(); // Do this…


HashSet<Criminal> senate = new HashSet<>(); // Not this

17-214 27
Check your understanding
interface Animal {
void vocalize();
}
class Dog implements Animal {
public void vocalize() { System.out.println("Woof!"); }
}
class Cow implements Animal {
public void vocalize() { moo(); }
public void moo() { System.out.println("Moo!"); }
}

What Happens?
1. Animal a = new Animal(); a.vocalize();
2. Dog b = new Dog(); b.vocalize();
3. Animal c = new Cow(); c.vocalize();
4. Animal d = new Cow(); d.moo();

17-214 28
Outline
I. A brief introduction to collections
II. More object-oriented programming
III. Information hiding (AKA encapsulation)
IV. Enums (if time)

17-214 29
Information hiding (AKA encapsulation)
• Single most important factor that distinguishes a
well-designed module from a bad one is the
degree to which it hides internal data and other
implementation details from other modules
• Well-designed code hides all implementation details
– Cleanly separates API from implementation
– Modules communicate only through APIs
– They are oblivious to each others’ inner workings
• Fundamental tenet of software design

17-214 30
Benefits of information hiding
• Decouples the classes that comprise a system
– Allows them to be developed, tested, optimized,
used, understood, and modified in isolation
• Speeds up system development
– Classes can be developed in parallel
• Eases burden of maintenance
– Classes can be understood more quickly and debugged
with little fear of harming other modules
• Enables effective performance tuning
– “Hot” classes can be optimized in isolation
• Increases software reuse
– Loosely-coupled classes often prove useful in other contexts

17-214 31
Information hiding with interfaces
• Declare variables using interface types
• Client can use only interface methods
• Fields and implementation-specific methods not
accessible from client code
• But this takes us only so far
– Client can access non-interface members directly
– In essence, it’s voluntary information hiding

17-214 32
Mandatory Information hiding
Vsibility modifiers for members

• private – Accessible only from declaring class


• package-private – Accessible from any class in
the package where it is declared
– Technically known as default access
– You get this if no access modifier is specified
• protected – Accessible from subclasses of
declaring class (and within package)
• public – Accessible from any class

17-214 33
Hiding internal state in OrdinaryComplex
class OrdinaryComplex implements Complex {
private double re; // Real Part
private double im; // Imaginary Part

public OrdinaryComplex(double re, double im) {


this.re = re;
this.im = im;
}

public double realPart() { return re; }


public double imaginaryPart() { return im; }
public double r() { return Math.sqrt(re * re + im * im); }
public double theta() { return Math.atan(im / re); }

public Complex add(Complex c) {


return new OrdinaryComplex(re + c.realPart(), im + c.imaginaryPart());
}
public Complex subtract(Complex c) { ... }
public Complex multiply(Complex c) { ... }
public Complex divide(Complex c) { ... }
}
17-214 34
Best practices for information hiding
• Carefully design your API
• Provide only functionality required by clients
– All other members should be private
• Use the most restrictive access modifier possible
• You can always make a private member public
later without breaking clients but not vice-versa!

17-214 35
Outline
I. A brief introduction to collections
II. More object-oriented programming
III. Information hiding (AKA encapsulation)
IV. Enums (if time)

17-214 36
Enums – review
• Java has object-oriented enums
• In simple form, they look just like C enums:
public enum Planet { MERCURY, VENUS, EARTH, MARS,
JUPITER, SATURN, URANUS, NEPTUNE }

• But they have many advantages


– Compile-time type safety
– Multiple enum types can share value names
– Can add or reorder without breaking constants
– High-quality Object methods
– Screaming fast collections (EnumSet, EnumMap)
– Can easily iterate over all constants of an enum

17-214 37
You can add data to enums
public enum Planet {
MERCURY(3.302e+23, 2.439e6), VENUS (4.869e+24, 6.052e6),
EARTH(5.975e+24, 6.378e6), MARS(6.419e+23, 3.393e6);
private final double mass; // In kg.
private final double radius; // In m.
private static final double G = 6.67300e-11; // N m2/kg2
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
public double mass() { return mass; }
public double radius() { return radius; }
public double surfaceGravity() {
return G * mass / (radius * radius);
}
}

17-214 38
You can add behavior too
public enum Planet {
... // As on previous slide

public double surfaceWeight(double mass) {


return mass * surfaceGravity; // F = ma
}
}

17-214 39
Watch it go!
public static void main(String[] args) {
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight / EARTH.surfaceGravity();

for (Planet p : Planet.values()) {


System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
}

$ java WeightOnPlanet 180


Your weight on MERCURY is 68.023205
Your weight on VENUS is 162.909181
Your weight on EARTH is 180.000000
Your weight on MARS is 68.328719

17-214 40
You can even add value-specific behavior
public enum Operation {
PLUS ("+", (x, y) -> x + y),
MINUS ("-", (x, y) -> x - y),
TIMES ("*", (x, y) -> x * y),
DIVIDE("/", (x, y) -> x / y);
private final String symbol;
private final DoubleBinaryOperator op;
Operation(String symbol, DoubleBinaryOperator op) {
this.symbol = symbol;
this.op = op;
}
@Override public String toString() { return symbol; }
public double apply(double x, double y) {
return op.applyAsDouble(x, y);
}
}

17-214 41
Watch it go!
public static void main(String[] args) {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
for (Operation op : Operation.values())
System.out.printf("%f %s %f = %f%n",
x, op, y, op.apply(x, y));
}

$ java TestOperation 4 2
4.000000 + 2.000000 = 6.000000
4.000000 - 2.000000 = 2.000000
4.000000 * 2.000000 = 8.000000
4.000000 / 2.000000 = 2.000000

17-214 42
Enums are your friend
• Use them whenever you have a type with a fixed
number of values known at compile time
• You may find them useful on Homework 2
• See Effective Java Items 34, 42

17-214 43
Summary
• Collections are your friend
• interface types provide flexibility
• Information hiding is crucial to good design
• Enums are also your friend

17-214 44

You might also like