03-object-oriented programming in java

Post on 29-Dec-2021

5 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

117-214

PrinciplesofSoftwareConstruction:Objects,Design,andConcurrency

Object-OrientedProgramminginJava

JoshBlochCharlieGarrod DaryaMelicher

217-214

Administrivia

• Homework1dueThursday11:59p.m.– Everyonemustreadandsignourcollaborationpolicy

• FirstreadingassignmentdueTuesday– EffectiveJavaItems15and16

317-214

KeyconceptsfromThursday

• Bipartitetypesystem– primitives&objectrefs– Singleimplementationinheritance–Multipleinterfaceinheritance

• Easiestoutput– println ,printf• Easiestinput– Commandlineargs,Scanner• Collectionsframeworkispowerful&easytouse

417-214

Outline

I. Object-orientedprogrammingbasicsII. InformationhidingIII. Exceptions

517-214

Objects

• Anobject isabundleofstateandbehavior• State– thedatacontainedintheobject– InJava,thesearethefields oftheobject

• Behavior– theactionssupportedbytheobject– InJava,thesearecalledmethods–MethodisjustOO-speakforfunction– Invokeamethod=callafunction

617-214

Classes

• Everyobjecthasaclass– Aclassdefinesmethodsandfields–Methodsandfieldscollectivelyknownasmembers

• Classdefinesbothtypeandimplementation– Type≈wheretheobjectcanbeused– Implementation≈howtheobjectdoesthings

• Looselyspeaking,themethodsofaclassareitsApplicationProgrammingInterface(API)– Defineshowusersinteractwithinstances

717-214

Classexample– complexnumbersclass Complex {private final double re; // Real Partprivate 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) { ... }

}

817-214

Classusageexamplepublic 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.println(e.realPart() + " + "

+ e.imaginaryPart() + "i");e = c.times(d);System.out.println(e.realPart() + " + "

+ e.imaginaryPart() + "i");}

}

Whenyourunthisprogram,itprints-1.0 + 1.0i-0.0 + -1.0i

917-214

Interfacesandimplementations

• MultipleimplementationsofAPIcancoexist–MultipleclassescanimplementthesameAPI– Theycandifferinperformanceandbehavior

• InJava,anAPIisspecifiedbyinterfaceorclass– InterfaceprovidesonlyanAPI– ClassprovidesanAPIandanimplementation– Aclasscanimplementmultipleinterfaces

1017-214

Aninterfacetogowithourclasspublic 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);

}

AninterfacedefinesbutdoesnotimplementAPI

1117-214

Modifyingclasstouseinterface

class OrdinaryComplex implements Complex {final double re; // Real Partfinal 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) { ... }

}

1217-214

Modifyingclienttouseinterfacepublic 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.println(e.realPart() + " + "

+ e.imaginaryPart() + "i");e = c.times(d);System.out.println(e.realPart() + " + "

+ e.imaginaryPart() + "i");}

}

Whenyourunthisprogram,itstillprints-1.0 + 1.0i-0.0 + -1.0i

1317-214

Interfacepermitsmultipleimplementations

class PolarComplex implements Complex {final double r;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) { ... } // Completely different implspublic Complex minus(Complex c) { ... }public Complex times(Complex c) { ... }public Complex dividedBy(Complex c) { ... }

}

1417-214

Interfacedecouplesclientfromimplementationpublic class ComplexUser {

public static void main(String args[]) {Complex c = new PolarComplex(Math.PI, 1); // -1Complex d = new PolarComplex(Math.PI/2, 1); // i

Complex e = c.plus(d);System.out.println(e.realPart() + " + "

+ e.imaginaryPart() + "i");e = c.times(d);System.out.println(e.realPart() + " + "

+ e.imaginaryPart() + "i");}

}

Whenyourunthisprogram,itSTILL prints-1.0 + 1.0i-0.0 + -1.0i

1517-214

Whymultipleimplementations?

• Differentperformance– Chooseimplementationthatworksbestforyouruse

• Differentbehavior– Chooseimplementationthatdoeswhatyouwant– Behaviormust complywithinterfacespec(“contract”)

• Oftenperformanceandbehaviorboth vary– Providesafunctionality– performancetradeoff– Example:HashSet,TreeSet

1617-214

Javainterfacesandclasses

• Atypedefinesafamilyofobjects– Eachtypeoffersaspecificsetofoperations– Objectsareotherwiseopaque

• Interfacesvs.classes– Interface:specifiesexpectations– Class:deliversonexpectations(theimplementation)

1717-214

Classesastypes

• Classesdo definetypes– Publicclassmethodsusablelikeinterfacemethods– Publicfieldsdirectlyaccessiblefromotherclasses

• Butgenerallyprefertheuseofinterfaces– Useinterfacetypesforvariablesandparametersunlessyouknowasingleimplementationwillsuffice• Supportschangeofimplementation• Preventsdependenceonimplementationdetails

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

1817-214

Checkyourunderstandinginterface 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!"); }

}

WhatHappens?1. Animal a = new Animal();

a. vocalize();2. Dog d = new Dog();

d.vocalize();3. Animal b = new Cow();

b.vocalize();4. b.moo();

1917-214

Historicalnote:simulationandtheoriginsofOOprogramming• Simula 67wasthefirst object-orientedlanguage

• DevelopedbyKristinNygaard andOle-JohanDahlattheNorwegianComputingCenter

• Developedtosupportdiscrete-eventsimulation– Application:operationsresearch,e.g.trafficanalysis– Extensibilitywasakeyqualityattributeforthem– Codereusewasanother

2017-214

Outline

I. Object-orientedprogrammingbasicsII. InformationhidingIII. Exceptions

2117-214

Informationhiding

• Singlemostimportantfactorthatdistinguishesawell-designedmodulefromabadoneisthedegreetowhichithidesinternaldataandotherimplementationdetailsfromothermodules

• Well-designedcodehidesall implementationdetails– CleanlyseparatesAPIfromimplementation–Modulescommunicateonly throughAPIs– Theyareoblivioustoeachothers’innerworkings

• Knownasinformationhidingorencapsulation• Fundamentaltenetofsoftwaredesign[Parnas,‘72]

2217-214

Benefitsofinformationhiding

• Decouples theclassesthatcompriseasystem– Allowsthemtobedeveloped,tested,optimized,used,understood,andmodifiedinisolation

• Speedsupsystemdevelopment– Classescanbedevelopedinparallel

• Easesburdenofmaintenance– Classescanbeunderstoodmorequicklyanddebuggedwithlittlefearofharmingothermodules

• Enableseffectiveperformancetuning– “Hot”classescanbeoptimizedinisolation

• Increasessoftwarereuse– Loosely-coupledclassesoftenproveusefulinothercontexts

2317-214

Informationhidingwithinterfaces

• Declarevariablesusinginterfacetypes• Clientcanuseonlyinterfacemethods• Fieldsnotaccessiblefromclientcode• Butthisonlytakesussofar– Clientcanaccessnon-interfacemembersdirectly– Inessence,it’svoluntaryinformationhiding

2417-214

MandatoryInformationhidingvisibilitymodifiers formembers• private – Accessibleonly fromdeclaringclass• package-private – Accessiblefromanyclassinthepackagewhereitisdeclared– Technicallyknownasdefaultaccess– Yougetthisifnoaccessmodifierisspecified

• protected – Accessiblefromsubclassesofdeclaringclass(andwithinpackage)

• public – Accessiblefromanywhere

2517-214

HidinginteriorstateinOrdinaryComplex

class OrdinaryComplex implements Complex {private double re; // Real Partprivate 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) { ... }

}

2617-214

Discussion

• Youknowthebenefitsofprivatefields• Whatarethebenefitsofprivatemethods?

2717-214

Bestpracticesforinformationhiding

• CarefullydesignyourAPI• Provideonly functionalityrequiredbyclients– All othermembersshouldbeprivate

• Youcanalwaysmakeaprivatememberpubliclaterwithoutbreakingclients– Butnotvice-versa!

2817-214

Outline

I. Object-orientedprogrammingbasicsII. InformationhidingIII. Exceptions

2917-214

Whatdoesthiscodedo?FileInputStream fIn = new FileInputStream(fileName);if (fIn == null) {switch (errno) {case _ENOFILE:

System.err.println(“File not found: “ + …);return -1;

default:System.err.println(“Something else bad happened: “ + …);return -1;

}}DataInput dataInput = new DataInputStream(fIn);if (dataInput == null) {System.err.println(“Unknown internal error.”);return -1; // errno > 0 set by new DataInputStream

}int i = dataInput.readInt();if (errno > 0) {System.err.println(“Error reading binary data from file”);return -1;

} // The Slide lacks space to close the file. Oh well.return i;

3017-214

Whatdoesthiscodedo?FileInputStream fIn = new FileInputStream(fileName);if (fIn == null) {switch (errno) {case _ENOFILE:

System.err.println(“File not found: “ + …);return -1;

default:System.err.println(“Something else bad happened: “ + …);return -1;

}}DataInput dataInput = new DataInputStream(fIn);if (dataInput == null) {System.err.println(“Unknown internal error.”);return -1; // errno > 0 set by new DataInputStream

}int i = dataInput.readInt();if (errno > 0) {System.err.println(“Error reading binary data from file”);return -1;

} // The Slide lacks space to close the file. Oh well.return i;

3117-214

Compareto:

FileInputStream fileInput = null; try {

fileInput = new FileInputStream(fileName);DataInput dataInput = new DataInputStream(fileInput);return dataInput.readInt();

} catch (FileNotFoundException e) {System.out.println("Could not open file " + fileName);

} catch (IOException e) {System.out.println("Couldn’t read file: " + e);

} finally {if (fileInput != null)

fileInput.close();}

3217-214

Exceptions

• Notifythecallerofanexceptionalconditionbyautomatictransferofcontrol

• Semantics:– Propagatesupstackuntilmainmethodisreached(terminatesprogram),orexceptioniscaught

• Sources:– Program– e.g.,IllegalArgumentException– JVM– e.g.,StackOverflowError

3317-214

Control-flowofexceptions

public static void main(String[] args) {try {

test();} catch (IndexOutOfBoundsException e) {

System.out.println"("Caught index out of bounds");}

}

public static void test() {try {

System.out.println("Top");int[] a = new int[10];a[42] = 42;System.out.println("Bottom");

} catch (NegativeArraySizeException e) {System.out.println("Caught negative array size");

}}

3417-214

Checkedvs.uncheckedexceptions

• Checkedexception–Mustbecaughtorpropagated,orprogramwon’tcompile

• Uncheckedexception– Noactionisrequiredforprogramtocompile– Butuncaughtexceptionwillcauseprogramtofail!

3517-214

TheexceptionhierarchyinJava

Throwable

Exception

RuntimeException IOException

EOFException

FileNotFoundException

NullPointerException

IndexOutOfBoundsException

ClassNotFoundException… …

. . .

Object

Error

3617-214

Designchoice:checkedanduncheckedexceptionsandreturnvalues

• Uncheckedexception– Programmingerror,otherunrecoverablefailure

• Checkedexception– Anerrorthateverycallershouldbeawareofandhandle

• Specialreturnvalue(e.g.,null fromMap.get)– Commonbutatypicalresult

• DoNOTusereturncodes• NEVERreturnnull toindicateazero-lengthresult– Useazero-lengthlistorarrayinstead

3717-214

Onemorealternative– returnOptional<T>

• Optional<T> isasingleTinstanceornothing– Avalueissaidtopresent,ortheoptionalisempty– Canthinkofitasasubsingleton collection

• Similarinspirittocheckedexceptions– Force callertoconfrontpossibilityofnovalue

• Butoptionalsdemandlessboilerplateinclient• Canbetrickytodecidewhichalternativetouse• SeeEffectiveJavaItem55formoreinformation

3817-214

AsampleuseofOptional<T>

// Returns maximum value in collection as an Optional<E>public static <E extends Comparable<E>>

Optional<E> max(Collection<E> c) {if (c.isEmpty())

return Optional.empty();

E result = null;for (E e : c)

if (result == null || e.compareTo(result) > 0)result = Objects.requireNonNull(e);

return Optional.of(result);}

3917-214

Creatingandthrowingyourownexceptions

public class SpanishInquisitionException extends RuntimeException {public SpanishInquisitionException() {}

}

public class HolyGrail {public void seek() {

...if (heresyByWord() || heresyByDeed())

throw new SpanishInquisitionException();...

}}

4017-214

Benefitsofexceptions

• Youcan’tforgettohandlecommonfailuremodes– Compare:usingaflagorspecialreturnvalue

• Providehigh-levelsummaryoferror,andstacktrace– Compare:coredumpinC

• Improvecodestructure– Separatenormalcodepathfromexceptional– Easetaskofrecoveringfromfailure

• Easetaskofwritingrobust,maintainablecode

4117-214

Guidelinesforusingexceptions(1)

• Avoidunnecessarycheckedexceptions(EJItem71)• Favorstandardexceptions(EJItem72)– IllegalArgumentException – invalidparametervalue– IllegalStateException – invalidobjectstate– NullPointerException – nullparamwhereprohibited– IndexOutOfBoundsException – invalidindexparam

• Throwexceptionsappropriatetoabstraction(EJItem73)

4217-214

Guidelinesforusingexceptions(2)

• Documentallexceptionsthrownbyeachmethod– Checkedandunchecked(EJItem74)– Butdon’tdeclare uncheckedexceptions!

• Includefailure-captureinfoindetailmessage(Item75)– throw new IlegalArgumentException(

"Modulus must be prime: " + modulus);

• Don’tignoreexceptions(EJItem77)// Empty catch block IGNORES exception – Bad smell in code!try {

...} catch (SomeException e) { }

4317-214

Rememberthisslide?Youcandomuchbetter!

FileInputStream fileInput = null; try {

FileInputStream fileInput = new FileInputStream(fileName);DataInput dataInput = new DataInputStream(fileInput);return dataInput.readInt();

} catch (FileNotFoundException e) {System.out.println("Could not open file " + fileName);

} catch (IOException e) {System.out.println("Couldn’t read file: " + e);

} finally {if (fileInput != null) fileInput.close();

}

4417-214

Manualresourceterminationisuglyanderrorprone• Evengoodprogrammersusuallygetitwrong– Sun’sGuidetoPersistentConnectionsgotitwrongincodethatclaimedtobeexemplary

– Solutiononpage88ofBlochandGafter’s JavaPuzzlersisbadlybroken;noonenoticedforyears

• 70%oftheusesoftheclosemethodintheJDKitselfwerewrongin2008(!)

• Even“correct”idiomsformanualresourcemanagementaredeficient

4517-214

Thesolution:try-with-resources(TWR)Automaticallyclosesresources

try (DataInput dataInput = new DataInputStream(new FileInputStream(fileName))) {

return dataInput.readInt();} catch (FileNotFoundException e) {

System.out.println("Could not open file " + fileName);} catch (IOException e) {

System.out.println("Couldn’t read file: " + e);}

4617-214

FilecopywithoutTWRstatic void copy(String src, String dest) throws IOException {

InputStream in = new FileInputStream(src);try {

OutputStream out = new FileOutputStream(dest);try {

byte[] buf = new byte[8 * 1024];int n;while ((n = in.read(buf)) >= 0)

out.write(buf, 0, n);} finally {

out.close();}

} finally {in.close();

}}

}

4717-214

FilecopywithTWRstatic void copy(String src, String dest) throws IOException {

try (InputStream in = new FileInputStream(src);OutputStream out = new FileOutputStream(dest)) {byte[] buf = new byte[8 * 1024];int n;while ((n = in.read(buf)) >= 0)

out.write(buf, 0, n);}

}

4817-214

Summary

• Interface-baseddesignshandlechangewell• Informationhidingiscrucialtogooddesign• Exceptionsarefarbetterthanerrorcodes• Theneedforcheckedexceptionsisrare• try-with-resources(TWR)isabigwin

top related