You are on page 1of 61

Weiss4thEditionSolutionstoExercises (USVersion)

Chapter1PrimitiveJava
1.1KeyConceptsandHowToTeachThem ThischapterintroducesprimitivefeaturesofJavafoundinalllanguagessuchasPascalandC: basiclexicalelements primitivetypes basicoperators controlflow functions(knownasmethodsinJava) StudentswhohavehadJavaalreadycanskipthischapter.Iteachthematerialintheorderpresented.Thereis littletrickymaterialhere(thisispartoftheappealofJava).AlthoughthetextdoesnotmentionCorC++,here aresomedifferences: 1. Primitivetypeshavepreciseranges.Thereisnounsignedtype.Acharis16bits. 2. Orderofevaluationisguaranteed(generallylefttoright).Inparticular,thesequencepointrulefrom C++isnotneeded.Thusnonsensesuchasx+++x++hasaprecisebehaviorinJava. 3. OnlytheCstyletypeconversionisallowed. 4. booleanisaprimitivetype,thusremovingmanyofthecommonerrorsinC++,suchasif(x=y).... 5. Thereisnocommaoperator,exceptinforloopexpressions. 6. Javaprovidesalabeledbreakstatement. 7. 7.Allfunctionsmustbeclassmethods. 1.2SolutionstoExercises INSHORT 1.1 Javasourcefilesendin.java.Compiledfiles(containingjcodeorbytecodes)endin.class. 1.2 1.3 1.4 //,whichextendstotheendofthelineand/*and/**,bothofwhichextendtoa*/.Commentsdo notnest. boolean,byte,short,char,int,long,float,anddouble. *multipliestwoprimitivevalues,returningtheresultandnotchangingitstwoarguments.*= changesthelefthandargumenttotheproductofthelefthandargumentandtherighthand argument.Therighthandargumentisunchanged. Boththeprefixandpostfixincrementoperatorsaddonetothetargetvariable.Theprefixoperator usesthenewvalueofthevariableinalargerexpression;thepostfixoperatorusesthepriorvalue. Thewhileloopisthemostgeneralloopandperformsatestatthetopoftheloop.Thebodyis executedzeroormoretimes.Thedoloopissimilar,butthetestisperformedatthebottomofthe loop;thusthebodyisexecutedatleastonce.Theforloopisusedprimarilyforcountinglike iterationandconsistsofaninitialization,test,andupdatealongwiththebody. breakisusedtoexitaloop.Alabeledbreakexitstheloopthatismarkedwithalabel.breakis alsousedtoexitaswitchstatement,ratherthansteppingthroughtothenextcase. Thecontinuestatementisusedtoadvancetothenextiterationoftheloop. Methodoverloadingallowsthereuseofamethodnameinthesamescopeaslongasthesignatures (parameterlisttypes)ofthemethodsdiffer.

1.5 1.6

1.7 1.8 1.9

Page1of1

1.10

Incallbyvalue,theactualargumentsarecopiedintothemethodsformalparameters.Thus,changes tothevaluesoftheformalparametersdonotaffectthevaluesoftheactualarguments.

INTHEORY 1.11 Afterline1,bis6,cis9,andais13.Afterline2,bis7,cis10,andais16.Afterline3,bis8,cis11, andais18.Afterline4,bis9,cis12,andais21. 1.12 1.13 1.14 Theresultistrue.Notethattheprecedencerulesimplythattheexpressionisevaluatedas(true && false) || true. Thebehaviorisdifferentifstatementscontainsacontinuestatement. Becauseofcallbyvalue,xmustbe0afterthecalltomethodf.Thustheonlypossibleoutputis0.

INPRACTICE 1.15 Anequivalentstatementis: while( true ) statement 1.16 ThisquestionisharderthanitlooksbecauseI/Ofacilitiesarelimited,makingitdifficulttoalign columns. public static void addition() { for( int i = 0; i < 10; i++ ) { for( int j = 0; j < 10; j++ ) { if( i + j < 10 ) System.out.print( " " ); System.out.print( i + j + " " ); } System.out.println( ); } } public static void multiplication() { for( int i = 1; i < 10; i++ ) { for( int j = 1; j < 10; j++ ) { if( i * j < 10 ) System.out.print( " " ); System.out.print( j * i + " " ); } System.out.println( ); } } 1.17 Themethodsareshownbelow(withoutasupportingclass);weassumethatthisisplacedinaclass thatalreadyprovidesthemaxmethodfortwoparameters. public static int max( int a, int b, int c ) Page2of2

{ return max( max( a, b ), c ); } public static int max( int a, int b, int c, int d ) { return max( max( a, b ), max( c, d ) ); } 1.18 Themethodisbelow: public static boolean isLeap( int year ) { boolean result = year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 ); return result; } 1.3ExamQuestions 1.1 Considerthefollowingstatements: int a = 4; int b = 7; b *= a;

Whataretheresultingvaluesofaandb? a. ais4,bis7 b. ais28,bis7 c. ais4,bis28 d. ais28,bis28 e. thestatementisillegal 1.2 Considerthefollowingstatements: int a = 4; int b = 7 int c = ++a + b; Whatistheresultingvalueofc? a. 10 b. 11 c. 12 d. 13 e. noneoftheabove 1.3 Considerthefollowingstatements: boolean a = false; boolean b = true; boolean c = false; boolean d; Inwhichofthefollowingisdevaluated? a. a && d b. b && d
Page3of3

c. d. e.

b || d c && d Alltheoperationsevaluated

1.4

Whichofthefollowingloopconstructsguaranteethatthebodyisexecutedatleastonce? a. doloop b. forloop c. whileloop d. twooftheconstructs e. allthreeoftheconstructs Inthemethodbelow,whichstatementaboutthepossibleoutputsismostcorrect? public static void what( ) { int x = 5; f( x ); System.out.println( x ); } a. b. c. d. e. 0isapossibleoutput 5istheonlypossibleoutput anypositiveintegercanbeoutput anyintegercanbeoutput noneoftheabovearetrue

1.5

1.6.

Iftwomethodsinthesameclasshavethesamename,whichistrue: a. Theymusthaveadifferentnumberofparameters b. Theymusthavedifferentreturntypes c. Theymusthavedifferentparametertypelists d. Thecompilermustgenerateanerrormessage e. noneoftheabove Consider the following statements: int a = 5; int b = 7; int c, d; c = (b - a)/2*a; d = b + 7/a; Whataretheresultingvaluesofc a. c is 0 and d is 2 b. c is 0 and d is 2.4 c. c is 5 and d is 8 d. c is 5 and d is 2 e. none of the above

1.7

1.8

Which of the following is true and d? a. A variable must be declared immediately before its first use. b. An identifier may start with any letter or any digit. c. _33a is a valid identifier. d. both (a) and (c) are true e. all of the above are true

Page4of4

AnswerstoExamQuestions 1. C 2. C 3. B 4. A 5. B 6. C 7. C 8. C

Page5of5

Chapter2ReferenceTypes
2.1KeyConceptsandHowToTeachThem Thischapterintroducesseveralconcepts: references strings arrays exceptions I/O Dependingonthestudentsbackground,someoreventhisentirechaptercouldbeskipped,butIrecommend atleastaquickreviewofthechapterinallcircumstances.StudentswhohavenothadJavashouldgothrough theentirechapterslowlybecausetherearefundamentaldifferencesbetweenJavaobjectsandobjectsin otherlanguages. 2.1.1References Explainthegeneralideaofareferenceinthecontextofapointer.Thisisimportanttodobecausepointersare fundamentalinmostotherlanguages.Thendiscussthebasicoperations.Mostimportantistoexplainthat objectsmustbecreatedvianew,what=and==meansforreferences,andparameterpassingforreference types.Studentsthathaveusedotherlanguagesmaybeconfusedwiththedistinctionbetweencallby referenceinalanguagesuchasPascal,C++,orAdaandcallbyvalueappliedtoreferencetypesinJava. Emphasizethatthestateofthereferencedobjectcanchange,buttheobjectbeingreferencedbytheactual argumentpriortothemethodcallwillstillbereferencedafterthemethodcall. 2.1.2Strings ExplainthebasicsoftheString;especiallythatitisnotanarrayofcharacters.Thetrickypartsaremixing up==andequals,andrememberingthatthesecondparametertosubStringisthefirstnonincluded position. 2.1.3Arrays Thetrickypartaboutarraysarethattypicallythearraymustbecreatedvianewandifthearrayisanarrayof Object,theneachObjectinthearraymustalsobecreatedbynew.Also,arraycopiesareshallow. 2.1.4DynamicExpansion Explainwhywedoubleinsteadofsimplyaddanextraposition.DiscussArrayListasatypethatmaintains thesizeaswellascapacityofanarrayandautomaticallyincreasescapacitywhenneeded. 2.1.5Exceptions DesigninginheritancehierarchiesisdeferredtoChapter4wheninheritanceisdiscussed.Thissectionsimply discussesthetry,catch,finallyblocks,thethrowclauseandthethrowslist.Studentsdonotseemto havedifficultywiththismaterial. 2.1.6InputandOutput ThissectiongivesabriefdescriptionofI/O(mostlyI),andtheStringTokenizer.TheI/OusesJava1.1 constructs.ThisaccountsforalmostalloftheupdatingfromJava1.0.TheStringTokenizerisextremely importantforsimplifyingtheparsingofinputlines.Withoutit,lifewillbedifficult. 2.2SolutionsToExercises INSHORT 2.1 Referencevalues(logically)storetheaddresswhereanobjectresides;aprimitivevaluestoresthe valueofaprimitivevariable.Asaresult,operationssuchas==haveseeminglydifferentmeanings forreferencetypesandprimitivetypes. 2.2 Thebasicoperationsthatcanbeappliedtoareferencetypeareassignmentvia=,comparisonvia== and!=,thedotoperator,typeconversion,andinstanceof. Page6of6

2.3 2.4

Anarrayhasitssizeassociatedwithit.AnArrayListhasacapacityinadditiontosize.Addingan elementtoanArrayListwillautomaticallyexpandthecapacityofthearrayifneeded. Exceptionsarethrownbyamethod.Theexceptionimmediatelypropagatesbackthroughthecalling sequenceuntilitishandledbyamatchingcatchclause,atwhichpointtheexceptionisconsidered handled. BasicstringoperationsincludeequalsandcompareTotocompare,=tocopy,+and+=toperform concatenation,length,charAt,andsubstring. ThenextmethodreturnsthenexttokenfromtheScannerobject,whilethehasNextmethod returnsatruevalueifthereexistsatokenavailabletobereadontheScannersstream.

2.5 2.6

INTHEORY 2.7 Thesecondstatementoutputs57,asexpected.Thefirstoutputs44,becauseitusedtheASCIIvalue of,whichis32. 2.8 ThesourcecodeinFigure2.21failstocompileasshown.Inthefoomethod,thecompilerdoesnot permitthemultiplereturnstatements(additionallythemethodisvoid).Ifyouexecuteacalltothe barmethod,ajava.lang.ArithmeticExceptionisthrown.

INPRACTICE 2.9 Onepossiblesolutiontoaccomplishthisis: import java.io.*; import java.util.*; public class Checksum { public static void main(String[] args) { int checksum = 0; System.out.print("Enter the name of the file: "); String filename = (new Scanner(System.in)).nextLine(); Scanner fileScanner = null; try { fileScanner = new Scanner(new File(filename)); } catch (IOException ioe) { System.err.println("IO Exception thrown."); } while (fileScanner.hasNextLine()) { String line = fileScanner.nextLine(); for (int i=0; i < line.length(); i++) checksum += line.charAt(i); } System.out.println("File checksum = " + checksum); } } 2.10 Onepossiblesolutiontodothisis: import java.util.Scanner; Page7of7

import java.io.FileReader; import java.io.IOException; public class ListFiles { public static void main( String [ ] args ) { Scanner scanIn = null; if( args.length != 0 ) { for( String fileName : args ) { System.out.println( "FILE: " + fileName ); try { scanIn = new Scanner (new FileReader ( fileName )); listFile( scanIn ); } catch( IOException e ) { System.out.println( e ); } finally { // Close the stream if( scanIn != null ) scanIn.close( ); } } } else { scanIn = new Scanner (System.in); listFile( scanIn ); // Close the stream if( scanIn != null ) scanIn.close( ); } } public static void listFile( Scanner fileIn ) { while( fileIn.hasNextLine( ) ) { String oneLine = fileIn.nextLine( ); System.out.println( oneLine ); } } } 2.11 Amethodtodothisisbelow: public static boolean isPrefix( String str1, String str2 ) { if( str1.length( ) > str2.length( ) ) return false;

Page8of8

for( int i = 0; i < str1.length( ) ; i++ ) if( str1.charAt( str1.length() ) != str2.charAt( str2.length() ) ) return false; return true; } 2.12 Amethodtodothisisbelow: public static int getTotalStrLength(String [] theStrings ) { int total = 0; for( String s : theStrings ) total += s.length( ); return total; } 2.13 2.14 Theelementsintheoriginalarrayarenotcopiedbeforeitisreinitialized. Methodstoaccomplishthisarebelow: public static double sum( double [ ] arr ) { double sum = 0.0d; for (int i = 0; i < arr.length; i++ ) sum += arr[i]; return sum; } public static double average( double [ ] arr ) { double sum = 0.0d; for (int i = 0; i < arr.length; i++ ) sum += arr[i]; return sum / arr.length; } public static double mode( double [ ] arr ) { java.util.Arrays.sort(arr); int modeCounter = 1; int maxMode = 1; double modeValue = arr[0]; for (int i = 0; i < arr.length-1; i++ ) { if (arr[i] == arr[i+1]) modeCounter++; if (modeCounter > maxMode) { maxMode = modeCounter; modeValue = arr[i+1]; Page9of9

modeCounter = 1; } } return modeValue; } 2.15 Methodstoaccomplishthisarebelow: public static double sum( double [ ][ ] arr ) { double sum = 0.0d; for (int row = 0; row < arr.length; row++ ) for (int col = 0; col < arr[row].length; col++ ) sum += arr[row][col]; return sum; } public static double average( double [ ][ ] arr ) { double sum = 0.0d; int row = 0, col = 0; for (row = 0; row < arr.length; row++ ) for (col = 0; col < arr[row].length; col++ ) sum += arr[row][col]; return sum / (row*col); } public static double mode( double [ ][] arr ) { double [] newArr = new double[arr.length * arr[0].length]; int counter = 0; for (int row = 0; row < arr.length; row++ ) for (int col = 0; col < arr[row].length; col++ ) newArr[counter++] = arr[row][col]; java.util.Arrays.sort(newArr); int modeCounter = 1; int maxMode = 1; double modeValue = newArr[0]; for (int i = 0; i < newArr.length-1; i++ ) { if (newArr[i] == newArr[i+1]) modeCounter++; if (modeCounter > maxMode) { maxMode = modeCounter; modeValue = newArr[i+1]; modeCounter = 1; } } return modeValue; } Page10of10

2.16

Methodstoaccomplishthisarebelow: public static void reverse( String [ ] arr ) { for (int i=0; i < arr.length / 2; i++) { String temp = arr[arr.length-i-1]; arr[arr.length-i-1] = arr[i]; arr[i] = temp; } }

public static void reverse( ArrayList<String> arr ) { for (int i=0; i < arr.size() / 2; i++) { String temp = arr.get(arr.size()-i-1); arr.set(arr.size()-i-1, arr.get(i)); arr.set(i, temp); } } 2.17 Methodstoaccomplishthisarebelow: public static int min( int [ ] arr ) { int currentMin = arr[0]; for (int value : arr) if (value < currentMin) currentMin = value; return currentMin; } public static int min( int [ ][ ] arr ) { int currentMin = arr[0][0]; for (int row = 0; row < arr.length; row++) for (int col = 0; col < arr[row].length; col++) if (arr[row][col] < currentMin) currentMin = arr[row][col]; return currentMin; }

public static String min( String [ ] arr ) { String currentMin = arr[0]; for (String value : arr) if (value.compareTo(currentMin) < 0) currentMin = value; return currentMin; } Page11of11

public static String min( ArrayList<String> arr ) { String currentMin = arr.get(0); for (String value : arr) if (value.compareTo(currentMin) < 0) currentMin = value; return currentMin; } 2.18 Amethodtodothisisbelow: public static int rowWithMostZeros( int [ ] [ ] arr ) { int result = 0, maxCount = 0; for (int row = 0; row < arr.length; row++) { int rowCounter = 0; for (int col = 0; col < arr[row].length; col++) if (arr[row][col] == 0) rowCounter++; if (rowCounter > maxCount) { maxCount = rowCounter; result = row; } } return result; } 2.19 Methodstoaccomplishthisarebelow: public static boolean hasDuplicates( int [ ] arr ) { boolean result = false; for (int i=0; i < arr.length-1; i++) for (int j=i+1; j < arr.length; j++) if (arr[i] == arr[j]) result = true; return result; } public static boolean hasDuplicates( int [ ][ ] arr ) { double [] newArr = new double[arr.length * arr[0].length]; int counter = 0; for (int row = 0; row < arr.length; row++ ) for (int col = 0; col < arr[row].length; col++ ) newArr[counter++] = arr[row][col]; java.util.Arrays.sort(newArr); boolean result = false; for (int i=0; i < newArr.length-1; i++) for (int j=i+1; j < newArr.length; j++) if (newArr[i] == newArr[j]) Page12of12

result = true; return result; } public static boolean hasDuplicates( String [ ] arr ) { boolean result = false; for (int i=0; i < arr.length-1; i++) for (int j=i+1; j < arr.length; j++) if (arr[i].compareTo(arr[j]) == 0) result = true; return result; } public static boolean hasDuplicates( ArrayList<String> arr ) { boolean result = false; for (int i=0; i < arr.size()-1; i++) for (int j=i+1; j < arr.size(); j++) if (arr.get(i).compareTo(arr.get(j)) == 0) result = true; return result; } 2.20 Methodstoaccomplishthisarebelow: public static int howMany( int [ ] arr, int val ) { int result = 0; for (int i = 0; i < arr.length; i++) if (arr[i] == val) result++; return result; } public static int howMany( int [ ][ ] arr, int val ) { int result = 0; for (int i = 0; i < arr.length; i++) for (int j = 0; j < arr.length; j++) if (arr[i][j] == val) result++; return result; } 2.21 Methodstoaccomplishthisarebelow: public static int countChars( String str, char ch ) { int counter = 0; for (int i = 0; i < str.length(); i++) if (str.charAt(i) == ch) counter++; Page13of13

return counter; } public static int countChars( String [ ] str, char ch ) { int counter = 0; for (int stringNum = 0; stringNum < str.length; stringNum++) for (int i = 0; i < str[stringNum].length(); i++) if (str[stringNum].charAt(i) == ch) counter++; return counter; } 2.22 Methodstoaccomplishthisinclude: public static String [ { String [] results = int index = 0; for (String value : results[index++] return results; } public static void makeLowerCase( String [ ] arr ) { int index = 0; for (String value : arr) arr[index++] = value.toLowerCase(); } public static ArrayList<String> getLowerCase( ArrayList<String> arr ) { ArrayList<String> results = new ArrayList<String>(); for (String value : arr) results.add(value.toLowerCase()); return results; } public static void makeLowerCase( ArrayList<String> arr ) { int index = 0; for (String value : arr) arr.set(index++, value.toLowerCase()); } 2.23 Onesolutionis: public static boolean isIncreasing( int [ ] [ ] arr ) { boolean increasing = true; for (int row = 0; row < arr.length; row++) Page14of14 ] getLowerCase( String [ ] arr ) new String[arr.length]; arr) = value.toLowerCase();

for (int col = 0; col < arr[row].length-1; col++) if (arr[row][col] > arr[row][col+1]) increasing = false; return increasing; } 2.24 Onepossiblesolutionis: public ArrayList<String> startsWith( String [ ] arr, char ch ) { ArrayList<String> results = new ArrayList<String>(); for (String value : arr) if (value.charAt(0) == ch) results.add(value); return results; } 2.25 Onepossiblesolutionis: public String [ ] split( String str ) { ArrayList<String> list = new ArrayList<String>(); Scanner scan = new Scanner(str); while (scan.hasNext()) list.add(scan.next()); return ((String []) list.toArray()); } 2.26 Onepossiblesolutionincludes: import java.util.Scanner; import java.util.NoSuchElementException; class MaxTestA { public static void main( String [ ] args ) { Scanner in = new Scanner( System.in ); int x, y; System.out.println( "Enter 2 ints: " ); String inputLine = in.nextLine(); String [] inputs = inputLine.split("\\s"); x = new Integer(inputs[0]).intValue(); y = new Integer(inputs[1]).intValue(); System.out.println( "Max: " + Math.max( x, y ) ); return; } } 2.27 Hereisonepossiblesolution.Forwhateverreason,readingdirectlyfromtheinputstream (System.in)andusingthespecifieddelimiterwouldnotwork(triedonmultipleplatforms).Was forcedtoreadtheinputlineasaStringandthenuseasecondscannerontheStringtobreakit intotokensusingthedelimiter. Page15of15

public static void MaxTestA( ) { Scanner in = new Scanner( System.in ); int x, y; System.out.println( "Enter 2 ints separated by a comma" ); String inputLine = in.nextLine(); Scanner scan = new Scanner(inputLine); scan.useDelimiter("[,]"); if (scan.hasNextInt()) { x = scan.nextInt(); if (scan.hasNextInt()) { y = scan.nextInt(); System.out.println( "Max: " + Math.max( x, y ) ); return; } } System.err.println("Error: need two ints separated by a comma" ); return; } 2.3ExamQuestions 2.1 Inthemethodbelow,whichstatementaboutthepossibleoutputsismostcorrect? public static void what( ) { Integer x = new Integer( 5 ); f( x ); System.out.println( x ); }

a. b. c. d. e. 2.2

0isapossibleoutput 5istheonlypossibleoutput anypositiveintegercanbeoutput anyintegercanbeoutput noneoftheabovearetrue

Inthemethodbelow,whichstatementaboutthepossibleoutputsismostcorrect? public static void what( ) { Integer x; f( x ); System.out.println( x ); } a. b. c. d. e. 0isapossibleoutput 5istheonlypossibleoutput anypositiveintegercanbeoutput anyintegercanbeoutput noneoftheabovearetrue

2.3

Whichclassisusedtoparsealineofinput? a. BufferedReader b. FileReader


Page16of16

c. InputStreamReader d. StringTokenizer e. noneoftheabove 2.4 WhichofthefollowingisnottrueaboutaString? a. Stringsarereferencetypes. b. Individualcharacterscanbeaccessed. c. Stringsmustbecreatedwithoutusingnew. d. ThecontentsofaStringcanbesafelycopiedvia=. e. ThelengthofaStringcanalwaysbedetermined. Whichofthefollowingisnottrueaboutarrays? a. Arraysarereferencetypes. b. Arrayindexingisboundschecked. c. Arrayssometimescanbecreatedwithoutusingnew. d. Theentirecontentsofanarraycanbecopiedvia=. e. Thecapacityofanarraycanalwaysbedetermined. Whichofthefollowingistrueaboutreferencetypes? a. Theyareinitializedto0bydefault. b. =canbeusedtocopythestatesoftwoobjects. c. ==canbeusedtotestifthereferencedobjectshaveidenticalstates. d. Theyarepassedusingcallbyreference. e. alloftheabovearefalse Whichof(a)(d)isfalse: a. Acatchblockforastandardruntimeexceptionisoptional. b. Anexceptionisanobject c. Athrowsclauseisusedtothrowanexception. d. Anexceptionhandlerisinsideacatchblock. e. alloftheabovearetrue WhichofthefollowingisfalseabouttypeArrayList: a. Theaddoperationalwaysincreasesizeby1. b. OnlyobjectscanbestoredinanArrayList c. Anaddoperationmayincreasethecapacitybymorethanone. d. ThecapacityofanArrayListcanbechangedusingthesetmethod. e. noneoftheaboveisfalse

2.5

2.6

2.7

2.8

AnswerstoExamQuestions 1. B 2. E 3. D 4. C 5. D 6. E 7. C 8. D

Page17of17

Chapter3ObjectsandClasses
3.1KeyConceptsandHowToTeachThem StudentswhohavenothadJava,withadescriptionofclassdesign,willneedtogothroughthischapter initsentirety.StudentswhohavehadJavawithclassdesignmaywanttoquicklyreviewthechapter. Thischapterintroducesthegeneralconceptofencapsulationandinformationhiding,butisgeared towardspracticaluseofJavawithemphasisondesigningclassesandsyntax.Youmaywanttohavethe studentsbringacopyofthecodetoclasssoyoucanavoidrewritingtheclasses.Thischapterisbyfar muchsimplerthanitsC++counterpart.

Topicsinclude: theclassconstruct publicandprivatesections specification(javadoc)vs.implementation constructors accessorsandmutators toString equals packages this instanceofoperator staticclassmembers
3.1.1TheclassConstruct Describehowtheclassachievesthegroupingofdatamembersandtheinformationhidingandencapsulation offunctionality.Thebasicmechanismforthelatteristoallowmethodstobeclassmembers.Youcan illustratethiswithMemoryCell.Addtheprivateandpublicvisibilitymodifiersafterdiscussingit. 3.1.2PublicandPrivateSections Thisseemstobearelativelyeasytopic.Explainthateverythingintheprivatesectionisinaccessibletonon classroutines.ContinuewiththeMemoryCellexample. 3.1.3Specificationvs.Implementation Explaintheimportanceofthespecification,andhowsomeofitcanbegeneratedautomaticallyviajavadoc. 3.1.4Constructors Explainthatinadditiontoparticularmemberfunctions,everyclasshasconstructors.Showhowaconstructor matchesadeclaration.Remarkaboutthedefaultbehavior:Ifnoconstructorisprovided,adefaultzero parameterconstructorisgenerated. 3.1.5AccessorsandMutators Javahasnoformalwaytospecifyanaccessororamutator.Howevertheconceptisimportanttoteach. 3.1.6toString Thisisasimpletopictocover. 3.1.7equals ThetrickypartisthattheparameterisalwaysoftypeObjectandmustbeconvertedtotheclasstype. Mentionthatifequalsisnotimplemented,thenittypicallydefaultstoreturningfalse(actuallyitis inheritedfromitssuperclass). 3.1.8Packages Mentionwhyweusepackagesandthespecialvisibilityrules.Alsodiscusstheimportdirectivebriefly.This isareasonabletimetodiscusscompilationissuesandtheCLASSPATHvariable.

Page18of18

3.1.9this thisisusedintwomainplaces:aliasingtests(inwhichitisimportanttohaveareferencetothecurrent object),andasashorthandforcallingotherconstructors.Bothusesareeasytodiscuss. 3.1.10instanceofOperator Thisisusedmostlyintheequalsmethod.Notethatthenullreferenceisnotaninstanceofanyclass. 3.1.11staticClassMembers Explainthatastaticfieldisuniquetoaclassanddoesnotbelongtoanyinstanceofthatclass.Theycanbe referencedviaclassnamesorobjectreferences. 3.1.12Designpatterns Justmentionthatdesignpatternsareusedtoencodecommonlyoccurringproblemsandtheirsolutions,and thatwewillbeidentifyingdesignpatternsinthecourse. 3.2SolutionsToExercises INSHORT 3.1 Informationhidingmakesimplementationdetails,includingcomponentsofanobject,inaccessible. Encapsulationisthegroupingofdataandtheoperationsthatapplytothemtoformanaggregate whilehidingtheimplementationoftheaggregate.Encapsulationandinformationhidingare achievedinJavathroughtheuseoftheclass. 3.2 3.3 3.4 3.5 3.6 3.7 Membersinthepublicsectionofaclassarevisibletononclassroutinesandcanbeaccessedviathe dotmemberoperator.Privatemembersarenotvisibleoutsideoftheclass. Theconstructoriscalledwhenanobjectiscreatedbyacalltonew. Thedefaultconstructorisamemberbymemberapplicationofadefaultconstructor,meaningthat primitivemembersareinitializedtozeroandreferencemembersareinitializedtonull. thisisareferencetothecurrentobject.Thisreferencetothecurrentobjectcanbeusedtocompare itwithotherobjectsortopassthecurrentobjecttosomeotherunit. Theconstructorwouldbeviewedasamethod,andwouldnotbetreatedasaconstructor. Packagesareusedtoorganizesimilarclasses.Memberswithnovisibilitymodifierarepackage visible:thatis,theyarevisibletootherclasseswithinthesamepackage(itisnotvisibleoutsidethe package).

3.8

Output is typically performed by providing a toString method that generates a String. This String can be passed to println. However, a nonstatic field, which is part of each instance of the class, can be accessed by a static class method only if a controlling object is provided.
Thetwoimportdirectivesarebelow: import weiss.nonstandard.*; import weiss.nonstandard.Exiting;

3.9

3.10 3.11

Aninstancefieldisassociatedwithaparticularinstance(orobject)ofaclass.Astaticfieldis associatedwiththeclassitselfandcanbeaccessedfromanyinstanceoftheclass. Astaticmethodcanbeinvokedwithoutanyinstance(andthereforeanyinstancedata)existing. Evenifseveralinstancesdidexist,there'dbenowayofknowingwhichobject'sinstancedatawas beingreferenced. Adesignpatterndescribesacommonlyoccurringprobleminmanycontextsandagenericsolution thatcanbeappliedinawidevarietyofthesecontexts. Page19of19

3.12

3.13

(a)Line17isillegalbecausepisanonstaticfieldandthereforeneedsanobjectreferenceinorderto bereferenceinthemainmethod(whichisastaticmethod).Line18islegalasqiscreatedwithinthe mainmethod.(b)Line20and23arelegalasNO_ SSNisapublicstaticfieldthatcanbeaccessedvia anobjectreferenceoraclassname.Line22islegalbecausebydefault,nameisvisible.Line21and 24areillegalbecauseSSNisprivate.Also,Person.SSNisillegalasSSNisnonstatic.

INTHEORY 3.14 BydefiningasingleprivateconstructorforaclassA,wecandisallowanyotherobjecttocreatean instanceofA.Forexample,wemayuseAtoholdonlystaticdata. 3.15 3.16 3.17 (a)Yes;mainworksanywhere.(b)Yes;ifmainwaspartofclassIntCell,thenstoredValue wouldnolongerbeconsideredprivatetomain. No,onlyonewildcardsymbol(*)canbeusedinanimportstatementandonlytospecifyallclasses withinaspecifiedpackage(i.e.java.util.*). Aruntimeerrorwilloccurstatingthatthezeroparameterconstructorcouldnotbefound. Exception in thread "main" java.lang.NoSuchMethodError: IntCell: method <init>()V not found at TestIntCell.main(TestIntCell.java:7) INPRACTICE 3.18 Onepossiblesolutionis: public class Combolock { private int num1; private int num2; private int num3; public Combolock ( int a, int b, int c) { num1 = a; num2 = b; num3 = c; } //returns true if the proper combination is given public boolean open ( int a, int b, int c) { return ( ( a == num1 ) && ( b == num2 ) && (c == num3 ) ); } public boolean changeCombo( int a, int b, int c, int newA, int newB, int newC ) { if ( open( a, b, c) ) { num1 = newA; num2 = newB; num3 = newC; return true; } return false; } Page20of20

3.19

The surprising result in part (d) is that the compiler will find the bytecodes for the local List class, even though you have recommented it. And thus, no ambiguity will be reported. Even with the import directive, the local List class will win out over java.awt.List.
ThemodificationtoTestIntCellresultsintheadditionoftheimportstatement: import weiss.nonstandard.IntCell; // Exercise the IntCell class public class TestIntCell { public static void main( String [ ] args ) { IntCell m = new IntCell( ); m.write( 5 ); System.out.println( "Cell contents: " + m.read( ) ); // The next line would be illegal if uncommented // m.storedValue = 0; } }

3.20

3.21

Implementationsareasfollows: public BigRational pow( int exp ) // exception if exp<0 { BigRational result = this; if (exp < 0) throw new ArithmeticException( "EXPONENT < 0" ); else { if (exp == 0) return BigRational.ONE; else if (exp == 1) return this; else for (int i = 2; i <= exp; i++) { result = result.multiply(this); } } return result; } public BigRational reciprocal( ) { BigRational newRational = new BigRational(den, num); newRational.fixSigns(); return newRational; } public BigInteger toBigInteger( ) // exception if denominator is not 1 { if (!den.equals( BigInteger.ONE )) throw new ArithmeticException( "DENOMINATOR IS NOT ONE" ); else return num; Page21of21

} public int toInteger( ) // exception if denominator is not 1 { if (!den.equals( BigInteger.ONE )) throw new ArithmeticException( "DENOMINATOR IS NOT ONE" ); else return num.intValue(); } 3.22 Theimplementationis: public BigRational( BigInteger n, BigInteger d ) { if( d.compareTo( BigInteger.ZERO ) < 0 ) throw new ArithmeticException( " DENOMINATOR < 0" ); if( num.equals( BigInteger.ZERO ) && den.equals( BigInteger.ZERO ) ) throw new IllegalArgumentException( "0/0" ); num = n; den = d; reduce( ); } 3.23 Apossiblesolutionis: package weiss.math; import java.math.BigInteger; public class BigRational2 { public static final BigRational2 ZERO = new BigRational2( ); public static final BigRational2 ONE = new BigRational2( "1" ); public BigRational2( String str ) { if( str.length( ) == 0 ) throw new IllegalArgumentException( "Zero-length string" ); // Check for "/" int slashIndex = str.indexOf( '/' ); if( slashIndex == -1 ) { // no denominator... use 1 den = BigInteger.ONE; num = new BigInteger( str.trim( ) ); } else { den = new BigInteger( str.substring( slashIndex + 1 ).trim( ) ); num = new BigInteger( str.substring( 0, slashIndex ).trim( ) ); fixSigns( ); reduce( );

Page22of22

} } // Ensure that the denominator is positive private void fixSigns( ) { if( den.compareTo( BigInteger.ZERO ) < 0 ) { num = num.negate( ); den = den.negate( ); } } // Divide num and den by their gcd private void reduce( ) { if (!den.equals(BigInteger.ZERO)) { BigInteger gcd = num.gcd( den ); num = num.divide( gcd ); den = den.divide( gcd ); } } public BigRational2( BigInteger n, BigInteger d ) { num = n; den = d; fixSigns( ); reduce( ); } public BigRational2( BigInteger n ) { this( n, BigInteger.ONE ); } public BigRational2( ) { this( BigInteger.ZERO ); } public BigRational2 abs( ) { return new BigRational2( num.abs( ), den ); } public BigRational2 negate( ) { return new BigRational2( num.negate( ), den ); } public BigRational2 add( BigRational2 other ) { BigInteger newNumerator = num.multiply( other.den ).add( other.num.multiply( den ) ); BigInteger newDenominator = Page23of23

den.multiply( other.den ); return new BigRational2( newNumerator, newDenominator ); } public BigRational2 subtract( BigRational2 other ) { return add( other.negate( ) ); } public BigRational2 multiply( BigRational2 other ) { BigInteger newNumer = num.multiply( other.num ); BigInteger newDenom = den.multiply( other.den ); return new BigRational2( newNumer, newDenom ); } public BigRational2 divide( BigRational2 other ) { if( other.num.equals( BigInteger.ZERO ) && num.equals( BigInteger.ZERO ) ) throw new ArithmeticException( "ZERO DIVIDE BY ZERO" ); BigInteger newNumer = num.multiply( other.den ); BigInteger newDenom = den.multiply( other.num ); return new BigRational2( newNumer, newDenom ); } public boolean equals( Object other ) { if( ! ( other instanceof BigRational2 ) ) return false; BigRational2 rhs = (BigRational2) other; return num.equals( rhs.num ) && den.equals( rhs.den ); } public String toString( ) { if( num.equals( BigInteger.ZERO ) && den.equals( BigInteger.ZERO ) ) return "Indeterminate"; if( den.equals( BigInteger.ZERO ) ) if( num.compareTo( BigInteger.ZERO ) < 0 ) return "-infinity"; else return "infinity"; if( den.equals( BigInteger.ONE ) ) return num.toString( ); else return num + "/" + den; } Page24of24

private BigInteger num; private BigInteger den; } 3.24 Onesolutionis: import import import import java.math.*; weiss.math.*; java.io.*; java.util.*;

// only this can be neg

public class RationalNumberTester { public static void main (String [] args) throws FileNotFoundException { ArrayList<BigRational> list = new ArrayList<BigRational>(); Scanner scan = new Scanner(new File ("rationalNumbers.txt")); while (scan.hasNextLine()) { String line = scan.nextLine(); BigRational br = new BigRational(line); if (!listContains(list, br)) list.add(br); } System.out.println("Sum: " + sum(list)); System.out.println("Mean: " + (sum(list).divide( new BigRational(list.size()+"/1")))); System.out.println("Recip. sum: " + reciprocalSum(list)); System.out.println("Harmonic Mean: " + (new BigRational(list.size() + "/1")).divide(reciprocalSum(list))); } private static BigRational sum(ArrayList<BigRational> list) { BigRational sum = list.get(0); for (int i = 1; i < list.size(); i++) sum = sum.add(list.get(i)); return sum; } private static BigRational reciprocalSum(ArrayList<BigRational> list) { BigRational sum = list.get(0).reciprocal(); for (int i = 1; i < list.size(); i++) sum = sum.add(list.get(i).reciprocal()); return sum; } private static void printList(ArrayList<BigRational> list) { for (BigRational value : list) System.out.print(value + " "); Page25of25

System.out.println(); } private static boolean listContains(ArrayList<BigRational> list, BigRational item) { boolean result = false; for (int i = 0; !result && i < list.size(); i++) if (list.get(i).equals(item)) result = true; return result; } } 3.25 Onepossiblesolutionis: public static void printArray(int [][] arr) { for (int row = 0; row < arr.length; row++) { for (int col = 0; col < arr[row].length; col++) System.out.print(String.format("%5d", arr[row][col])); System.out.println(); } } 3.26 (a)Yes,objectsoftheBigDecimalclassareimmutable.(b)WithcompareTo,two BigDecimalobjectsthatareequalinvaluebuthaveadifferentscale(like2.0and2.00)are consideredequal.Whenusingtheequalsmethod,twoBigDecimalobjectsareconsideredequal onlyiftheyareequalinvalueandscale.(c)bd1.equals(bd2)wouldbefalsewhenthevalueof bd2isalso0.(d)Bydefault,0.2wouldbetheresult.(e)Sincetheresultisanonterminatingdecimal expansion,anArithmeticExceptionisthrownwhenexecutingthedividemethod.(f)An objectwithaprecisionsettingmatchingtheIEEE754RDecimal128format,34digits,andarounding modeofHALF_EVEN,theIEEE754Rdefault.(g)Onepossiblesolutionis: package weiss.math; import java.math.*; public class BigRational3 { public static final BigRational3 ZERO = new BigRational3( ); public static final BigRational3 ONE = new BigRational3( "1" ); private MathContext mc = MathContext.UNLIMITED; public BigRational3( String str ) { if( str.length( ) == 0 ) throw new IllegalArgumentException( "Zero-length string" ); // Check for "/" int slashIndex = str.indexOf( '/' ); if( slashIndex == -1 ) { Page26of26

// no denominator... use 1 den = BigInteger.ONE; num = new BigInteger( str.trim( ) ); } else { den = new BigInteger( str.substring( slashIndex + 1 ).trim( ) ); num = new BigInteger( str.substring( 0, slashIndex ).trim( ) ); check00( ); fixSigns( ); reduce( ); } } private void check00( ) { if( num.equals( BigInteger.ZERO ) && den.equals( BigInteger.ZERO ) ) throw new IllegalArgumentException( "0/0" ); } // Ensure that the denominator is positive private void fixSigns( ) { if( den.compareTo( BigInteger.ZERO ) < 0 ) { num = num.negate( ); den = den.negate( ); } } // Divide num and den by their gcd private void reduce( ) { BigInteger gcd = num.gcd( den ); num = num.divide( gcd ); den = den.divide( gcd ); } public BigRational3( BigInteger n, BigInteger d ) { num = n; den = d; check00( ); fixSigns( ); reduce( ); } public BigRational3( BigInteger n ) { this( n, BigInteger.ONE ); } public BigRational3( ) { this( BigInteger.ZERO ); } public BigRational3 abs( ) Page27of27

{ return new BigRational3( num.abs( ), den ); } public BigRational3 negate( ) { return new BigRational3( num.negate( ), den ); } public BigRational3 add( BigRational3 other ) { BigInteger newNumerator = num.multiply( other.den ).add( other.num.multiply( den ) ); BigInteger newDenominator = den.multiply( other.den ); return new BigRational3( newNumerator, newDenominator ); } public BigRational3 subtract( BigRational3 other ) { return add( other.negate( ) ); } public BigRational3 multiply( BigRational3 other ) { BigInteger newNumer = num.multiply( other.num ); BigInteger newDenom = den.multiply( other.den ); return new BigRational3( newNumer, newDenom ); } public BigRational3 divide( BigRational3 other ) { if( other.num.equals( BigInteger.ZERO ) && num.equals( BigInteger.ZERO ) ) throw new ArithmeticException( "ZERO DIVIDE BY ZERO" ); BigInteger newNumer = num.multiply( other.den ); BigInteger newDenom = den.multiply( other.num ); return new BigRational3( newNumer, newDenom ); } public boolean equals( Object other ) { if( ! ( other instanceof BigRational3 ) ) return false; BigRational3 rhs = (BigRational3) other; return num.equals( rhs.num ) && den.equals( rhs.den ); } public String toString( ) { Page28of28

if( den.equals( BigInteger.ZERO ) ) if( num.compareTo( BigInteger.ZERO ) < 0 ) return "-infinity"; else return "infinity"; if( den.equals( BigInteger.ONE ) ) return num.toString( ); else return num + "/" + den; } public BigDecimal toBigDecimal() { BigDecimal decnum = new BigDecimal(num, mc); BigDecimal result = null; try { result = decnum.divide(new BigDecimal(den, mc), mc); } catch (ArithmeticException ae) { if (ae.getMessage().equals( "Non-terminating decimal expansion; " + "no exact representable decimal result.")) result = decnum.divide( new BigDecimal(den, mc), MathContext.DECIMAL128); } return result; } private BigInteger num; private BigInteger den; } 3.27 Onepossiblesolutionisbelow: public class Account { private float balance = 0.0f; public Account (float initAmt) throws Exception { if (initAmt < 0.0f) throw new Exception("Negative amounts are not possible."); balance = initAmt; } public float getBalance() { return balance; } public void deposit(float amt) { balance += amt; Page29of29 // only this can be neg

} public void withdraw(float amt) throws Exception { if (amt < 0.0) throw new Exception("Negative amounts are not possible."); if (amt > balance) throw new Exception("Your balance can not be < 0."); balance -= amt; } public String toString() { return balance + ""; } } 3.28 Onepossiblesolutionisasfollows: package weiss.misc; public class BinaryArray { private boolean [] arr = null; public BinaryArray(String init) { arr = new boolean[init.length()]; for (boolean value : arr) value = false; for (int ch = 0; ch < init.length(); ch++) { boolean val = false; if (init.charAt(ch) == 'T') val = true; arr[ch] = val; } } public int size() { return arr.length; } public String toString() { String result = ""; for (int i = 0; i < arr.length; i++) result += arr[i] + " "; return result; } public boolean get(int location) { return arr[location]; } Page30of30

public void set(int location, boolean value) { arr[location] = value; } } 3.3ExamQuestions 3.1 WhichofthefollowingisthemostdirectexampleofhowencapsulationissupportedinJava? a. constructors b. inheritance c. methods d. publicandprivatespecifiers e. theclassdeclaration

3.2 Java?

Whichofthefollowingisthemostdirectexampleofhowinformationhidingissupportedin a. b. c. d. e. constructors inheritance memberfunctions publicandprivatespecifiers theclassdeclaration

3.3

Whathappensifanonclassmethodattemptstoaccessaprivatemember? a. compiletimeerror b. compiletimewarning,butprogramcompiles c. theprogramcompilesbuttheresultsareundefined d. theprogramiscertaintocrash e. someoftheabove,buttheresultvariesfromsystemtosystem Whichconditionoccurswhenthesameobjectappearsasbothaninputandoutputparameter? a. aliasing b. copyconstruction c. operatoroverloading d. typeconversion e. noneoftheabove Whichof(a)to(c)isfalseaboutastaticclassmember? a. itmustbeamethod b. onememberisallocatedforeachdeclaredclassobject c. thestaticclassmemberisguaranteedtobeprivatetotheclass d. twooftheabovearefalse e. allof(a),(b),and(c)arefalse InwhichofthefollowingcasesisaclassmemberMinvisibletoamethodF? a. FisamethodinthesameclassandMisprivate b. FisapackagefriendlyfunctionandMisnotprivate c. FisamethodinanotherclassandMispublic d. FisamethodinanotherclassandMisprivate e. noneoftheabove Whichofthefollowingstatementsistrue? a. Anydocumentationproducedbyjavadocisguaranteedtobeimplementedbytheclass.
Page31of31

3.4

3.5

3.6

3.7

b. c. d. e. 3.8

Javaprovidesamechanismtodistinguishaccessorsandmutators. Eachclasscanprovideamaintoperformtesting. thisisavailableinallmethods,includingstaticmethods. EveryclassmustimplementtoStringandequals.

ForclassC,whicharetheparametertypesofequals? a. noparameters. b. oneparameter,typeC. c. oneparameter,typeObject. d. twoparameters,bothoftypeC. e. twoparameters,bothoftypeObject. Whichof(a)(d)isfalseforthemainmethod? a. Eachclasscanhaveitsownmainmethod. b. Theargumentspassedtoamainmethodfromacommandlinearestrings. c. Themainmethodmustbewrittenasthelastmethodintheclass. d. Themainmethodtypicallydoesnotreturnavalue e. alloftheabovearetrue Whichofthefollowingisfalseforconstructors? a. Theremaynotbeanyconstructordefinedinaclass. b. Aconstructormustbedeclaredpublic. c. Theremaybemultipleconstructorsinaclass. d. Aconstructortypicallyhasnoreturnvalue. e. Aconstructormusthavethesamenameastheclassname.

3.9

3.10

AnswerstoExamQuestions 1. E 2. D 3. A 4. A 5. E 6. D 7. C 8. C 9. C 10. B

Page32of32

Chapter4Inheritance
4.1KeyConceptsandHowToTeachThem InheritanceinJavaisafundamentalconcept.Thetextdoesnotdirectlydefinelargehierarchies,but repeatedlyusesinheritanceintwoplaces:theinterfaceandindesigninggenericalgorithms.My recommendationisthatotherusesofinheritanceshouldbeoccasional.Thebasicconceptsare: Theconceptofinheritanceandpolymorphism Extendingclasses Designinghierarchies Abstractandfinalmethodsandclasses;Staticvs.dynamicbinding Interfaces Genericcomponents Adaptersandwrappers 4.1.1TheConceptofInheritanceandPolymorphism Inheritanceisusedwhennewclassesareneededthathavebasicsimilaritytoexistingclasses.Several examplesareprovidedinthetext.UsethePersonexampletoexplaintheISArelation.Explainadvantages ofinheritancesuchascodereuse. 4.1.2ExtendingClasses Iliketoexplainthatthederivedclassisequaltothebaseclasswithpossibleadditions(newdatamembers, newmethods)andmodifications(redefinitionofbaseclassmembers).Explainthatthederivedclasshasallof thedatamembersofthebaseclass,plusitsown.Theinheritedmembersarenotdirectlyaccessibleifthey wereprivateinthebaseclass.Alsoexplainthatforthepurposesofconstruction,thedatamembersthat formthebaseclassareconsideredasanatomicobjectinthecalltosuper(andiftheyareprivate,thatis theonlywaytoinitializetheinheritedportionoftheclass).Useveryshortexamples,suchasUnderflow, initially.Public,private,andprotectedmustbeexplained.Thistendstonotbeadifficultconcept. 4.1.3Dynamicbindingandpolymorphism Areferencevariablethatispolymorphiccanreferenceobjectsofseveraldifferenttypes.Whenoperationsare appliedtothereference,theoperationthatisappropriatetotheactualreferencedobjectisautomatically selected(alsoreferredtoasdynamicbinding).Thisconceptisusefulwhenderivedclassesmayoverridebase classmethods.ExplaintheconceptusingtheShapeexample. 4.1.4Designinghierarchies UsingtheShapeexample,explaintheneedforabstractmethods,finalmethodsandstaticmethods. Similarly,explaintheuseofabstractclassesandfinalclasses.Abstractclassesareplaceholdersand cannotbeconstructed.Thederivedclassesmustprovideimplementationsfortheabstractclassmethods. Finalmethodsarethosethatcannotbeoverridden. 4.1.5Interfaces Interfacesaresimplyabstractclasseswithnoimplementation.Inotherwords,theyspecifyaprotocol.They aresyntacticallysimpleandstudentsdonotseemtohavetroublewiththeconcept. 4.1.6InheritanceinJava BrieflyexplaintheObjectclassandthatallotherclassisadirectorindirectsubclassofObject.The ExceptionandI/OhierarchiesintheJavalibrariesaregoodexamplestoillustrateinheritance.Withoutgoing intotoomuchdetail(assomeoftheseconceptsarecoveredinlaterchapters),explaintheexception hierarchyandI/OdecoratorpatternexampleforwrappingstreamsandreaderstoillustratetheI/O hierarchy. 4.1.7GenericComponents Agenericimplementationgivesthebasicfunctionalityinatypeindependentmanner.Themainideaistouse inheritanceandwritecomponentsintermsofthemostgeneraltypeofobjectthatwillbeused(this componentcanthenbereusedinallderivedclasses).Thiscanbeaccomplishedbyusinganappropriate Page33of33

superclasssuchasjava.lang.Object.UsetheMemoryCellexampletoillustrateagenericcellclass. Interfacetypesmaysometimesbeneededtodefinemorespecificoperationsthanthoseavailableinthe Objectclass.TheComparableinterfacecanbeusedtowriteagenericfindMaxmethod.Java1.5has simplifiedthetaskofwritinggenericcomponentswiththeintroductionoflanguagesupportforgeneric classesandmethods.ThegenericmechanisminJava1.5isdrivenentirelybythecompileressentially converting1.5genericcodeintoapre1.5inheritancebasedgenericimplementation.Forthisreason,itis essentialtounderstandinheritancebasedgenericcoding,evenwhenworkingwithJava1.5. 4.1.8WrappersandAdapters AWrapperstoresanobjectandaddsoperations,whereasanadaptersimplychangestheinterfacewithout changingthefunctionality.Java1.5introducednewautoboxingandunboxingfeaturesthatperformbehind thesceneswrapping/unwrappingofprimitivetypeswiththeircorrespondingclassbasedimplementations. 4.1.9Functor Afunctoristypicallyaclasswithasinglemethodthatisusedinagenericalgorithm.UsethefindMax exampletoillustratetheconcept.Notethatthealgorithmtypicallyspecifiesaninterfaceclassandthe actualfunctionobjectclassmustimplementthisinterface. 4.1.10Nested,anonymousandlocalclasses Anestedclassdeclarationisplacedinsideanotherclassdeclaration.Alocalclassisdeclaredinsideamethod. Finally,ananonymousclassisalsodeclaredinsideamethodbutisdeclaredimmediatelywhereitisused. GiveabriefexplanationusingthefindMaxexample.Studentswillgetcomfortablewiththemwhenthey actuallyusethemlaterinthecourse 4.2SolutionsToExercises INSHORT 4.1 Assumingpublicinheritance,onlypublicandprotectedmembersofthebaseclassarevisible inthederivedclassunlessthederivedclassisinthesamepackageofthebaseclass,inwhichcase packagefriendlymembersarealsovisible.Amongbaseclassmembers,onlypublicmembersofthe baseclassarevisibletousersofthederivedclass. 4.2 PrivateinheritanceisusedtoindicateaHASArelationshipwhileavoidingtheoverheadofalayer offunctioncalls.Compositionisabetteralternativeforthis.Incomposition,aclassiscomposedof objectsofotherclasses. Polymorphismistheabilityofareferencetypetoreferenceobjectsofseveraldifferenttypes.When operationsareappliedtothepolymorphictype,theoperationthatisappropriatetotheactual referencedobjectisautomaticallyselected. AutoboxingandunboxingarenewfeaturesintroducedinJava1.5.Theyperformautomatic conversionbetweenprimitivetypesandtheirobjectcounterparts(e.g.intand java.lang.Integer). Afinalmethodisamethodthatcannotberedefinedinaderiveclass. (a)Onlyb.bPublicandd.dPublicarelegal.(b)ifmainisinBase,thenonlyd.dPrivateis illegal.(c)IfmainisinDerived,thenb.bPrivateisillegal.(d)AssumingTesterisinthesame package,thenb.bProtectisvisibleinallcases.(e)placethestatementsbelowinthepublicsection oftheirrespectiveclasses;(f)and(g)bPrivateistheonlymembernotaccessibleinDerived. Base( int pub, int pri, int pro ) { bPublic = pub; bPrivate = pri; bProtect = pro; }

4.3

4.4

4.5 4.6

Page34of34

Derived( int bpub, int bpri, int bpro, int dpub, int dpri ) { super( bpub, bpri, bpro ); dPublic = dpub; dPrivate = dpri; } 4.7 4.8 Finalclassesmaynotbesubclassed(bytheuseofinheritance).Nonfinalclassescanbesubclassed. Finalclassesaregenerallyusedtoprovideanimplementationofaclassthatshouldnotbechanged. Anabstractmethodhasnomeaningfuldefinition.Asaresult,eachderivedclassmustredefineit toprovideadefinition.Abaseclassthatcontainsanabstractmethodisabstractandobjectsof theclasscannotbedefined. Aninterfaceisaclassthatcontainsaprotocolbutnoimplementation.Assuchitconsistsexclusively ofpublic abstractmethodsandpublic static finalfields.Thisisdifferentfrom abstractclasses,whichmayhavepartialimplementations. TheJavaI/Olibraryclassescanbedividedintotwogroups,inputandoutput.TheI/Oisdonevia inputandoutputstreams.ByteorientedreadingandwritingisprovidedviaInputStreamand OutputStreamclasseswhereascharacterorientedI/OisprovidedviaReaderandWriter classes.MostotherclassesforI/O(forfiles,pipes,socketsetc)arederivedfromthesefourclasses. Object FilterInputStream DataInputStream InflaterInputStream (java.util.zip) GZipInputStream (java.util.zip) FilterOutputStream DataOutputStream DeflaterOutputStream (java.util.zip) GZipOutputStream (java.util.zip) InputStream FileInputStream SocketInputStream (hidden) ObjectInputStream OutputStream FileOutputStream SocketOutputStream (hidden) ObjectOutputStream Reader BufferedReader InputStreamReader FileReader Writer Printwriter 4.11 GenericalgorithmsareimplementedbyusingObjectorsomeotherinterface(suchas Comparable)asparametersandreturntypes.Inotherwords,genericalgorithmsareimplemented byusinginheritance.Tostoreprimitivetypesinagenericcontainer,wrapperclassesmustbeused. Awrapperpatternisusedtostoreanexistingentity(e.g.,aclass)andaddoperationsthatthe originaltypedoesnotsupport.Anadapterpatternisusedtochangetheinterfaceofanexistingclass toconformtoanotherinterface.Unlikethewrapperpattern,theaimoftheadapterpatternisnotto changeoraddfunctionality. Page35of35

4.9

4.10

4.12

4.13

Onewaytoimplementanadaptorisviacompositionwhereinanewclassisdefinedthatcreatesan instanceoftheoriginalclassandredefinestheinterface.Theothermethodisviainheritance. Inheritanceaddsnewmethodsandmayleavetheoriginalmethodsintactwhereasviacomposition, wecreateaclassthatimplementsjustthenewinterface.Afunctionobjectisimplementedasaclass withnodataobjectandonemethod. Alocalclassisaclassthatisplacedinsideamethod.Thelocalclassisvisibleonlyinsidethemethod. Ananonymousclassisaclasswithnoname.Itisoftenusedtoimplementfunctionobjects(the syntaxallowswritingnew Interface()withtheimplementationofInterfaceimmediately followingit). Typeerasureistheprocessofconvertingagenericclasstoanongenericimplementation.Dueto typeerasure,generictypescannotbeprimitivetypes.Similarly,instanceoftestscannotbeused withgenerictypes,norcanagenerictypebeinstantiatedorreferencedinastaticcontext.Arraysof generictypescannotbecreated. InJava,arraysarecovariant,howevergenericcollectionsarenot.Wildcardsareusedtoexpress subclasses(orsuperclasses)ofparametertypesingenericcollections.Thetypeboundisspecified insidetheanglebrackets<>,anditspecifiespropertiesthattheparametertypesmusthave.

4.14

4.15

4.16

INTHEORY 4.17 a.falseb.truec.trued.truee.truef.trueg.falseh.truei.truej.true(see java.io.Serializable)k.truel.falsem.falsen.trueo.truep.falseq.truer.falses.truet. falseu.truev.true 4.18 ObjectsoftheFile,FileInputStream,andFileReaderareallacceptableparametersfora Scannerconstructor.Thelattertwo(FileInputStreamandFileReader)canusethe constructorsthataccepttheInputStreamandReadableparametersrespectively. Considerthecaseinwhichamethodfoo()containsalocalclassandreturnsanobjectoftype LocalClass.Inthiscase,ifthelocalclassaccessesx,thenitcontinuestobeavailableafterfoo terminates. Typetest foo () { final int x = 1; class LocalClass() implements Typetest { public int foo() { return x; } } return new localClass(); } 4.20 Theoutputis512andthesignatureisString getX().Afterchangingasgivenin(c),theoutputis 17andthesignatureisint getX().IfClass1ischangedasin(d),wegetanerrorasClass2is expectingamethodgetXreturninganinteger.Ifcodeinliningwereallowed,theresultwouldhave been17.

4.19

4.21

a) The last line throws a ClassCastException as the element in the array must be specifically cast, not the array itself. b) The last line contains an unnecessary cast. c) No errors. d) No errors.

INPRACTICE

4.22

One solution is as follows:

Page36of36

public static <AnyType> void copy( AnyType [ ] arr1, AnyType [ ] arr2 ) { for ( AnyType val : arr1 ) arr2[2] = val; }

4.23

The class below includes the generic method min and a test routine. max is similar.
public class Ex0420 { public static Comparable min( Comparable a, Comparable b ) { return a.lessThan( b ) ? a : b; } public static void main( String [ ] args ) { int x = 5, y = 7; System.out.println(min(new MyInteger( x ), new MyInteger( y ))); } }

4.24

One solution is a follows:


public static Comparable min( Comparable [] a ) { int minIndex = 0; for ( int i = 1; i < a.length; i++ ) if ( a[minIndex].compareTo(a[i]) > 0 ) minIndex = i; return a[minIndex]; }

4.25

One solution is as follows:


class MaxTwo { public static Comparable [] max2( Comparable [] a ) { Comparable [] obj1 = new Comparable [2]; int maxIndex0 = 0; int maxIndex1 = 0; if( a[0].compareTo(a[1]) > 0) maxIndex0 = 1; else maxIndex1 = 1; for( int i = 1; i < a.length; i++ ) { if( a[maxIndex0].compareTo(a[i]) > 0 ) { maxIndex1 = maxIndex0; maxIndex0 = i; } } obj1[0] = a[maxIndex0]; obj1[1] = a[maxIndex1]; Page37of37

return obj1; } public static void main( String [] args ) { String [] st1 = { B, C, A, F }; Comparable [] st2 = new Comparable[2]; st2 = max2(st1); System.out.println(st2[0] + + st2[1]); } }

4.26

One possible solution is:


class SortWithMin { public static int findmin( Comparable [] a, int start ) { int minIndex = start; for( int i = start; i < a.length; i++ ) if( a[minIndex].compareTo(a[i]) > 0 ) minIndex = i; return minIndex; } public static void sort (Comparable [] a) { int tempIndex; Comparable temp; for (int i = 0; i < a.length; i++) { tempIndex = findmin(a,i); temp = a[i]; a[i] = a[tempIndex]; a[tempIndex] = temp; } } public static void main (String [] args) { String [] st1 = { B, C, A, F }; sort(st1); for( int i = 0; i < st1.length; i++ ) System.out.println( st1[ i] ); Shape [] a = new Shape[ ] { new Circle( 2.0 ), new Circle( 1.0), new Circle( 3.0 ) }; sort(a); for( int i = 0; i < a.length; i++ ) System.out.println( a[ i]. area() ); } } ThisassumesthatShapeimplementsComparable.

4.27

One possible solution is:

Page38of38

public class Circle extends Shape { public Circle( double rad ) { if( rad >= 0 ) radius = rad; else throw new InvalidArgumentException(); } private double radius; } public class Rectangle extends Shape { public Rectangle( double len, double wid ) { if( (len >= 0) && (wid >= 0) ) { length = len; width = wid; } else throw new InvalidArgumentException(); } private double length; private double width; } public class Square extends Rectangle { public Square( double side ) { super( side, side ); } public String toString( ) { return Square: + getLength( ); } } public class InvalidArgumentException extends RuntimeException { }

4.28

One possible implementation is:


public class Ellipse extends Shape implements Stretchable { private double length; private double width; public Ellipse (double length, double width) { this.length = length; this.width = width; Page39of39

} public double area() { return Math.PI * length/2.0 * width/2.0; } public double { double asq double bsq return 2.0 } perimeter() = Math.pow(length/2.0, 2); = Math.pow(width/2.0, 2); * Math.PI * Math.sqrt((asq+bsq)/2.0);

public String toString() { return "Ellipse: " + length + " " + width; } public double getLength() { return length; } public double getWidth() { return width; } public void stretch(double factor) { if( factor <= 0 ) throw new IllegalArgumentException( ); if( length > width ) length *= factor; else width *= factor; } }

4.29

One possible solution follows. However note that since we are dealing with an underlying Object, we can only perform an equality comparison.
// MemoryCell class // Object read( ) --> // void write( Object x ) --> Returns the stored value x is stored

public class MemoryCell implements Comparable<MemoryCell> { // Public methods public Object read( ) { return storedValue; } public void write( Object x ) Page40of40

{ storedValue = x; } public int compareTo(MemoryCell obj) { if (this.storedValue.equals(obj.read())) return 0; else return -1; } // Private internal data representation private Object storedValue; }

4.30

Since Shape already implements Comparable<Shape>, we can use Shapes compareTo method for the comparison in Circle (and not change the code). If we do attempt to modify Circle class as follows, well obtain a compile time error message (as follows). If Shape does not implement Comparable<Shape>, then the Circle implementation below is valid.
public class Circle extends Shape implements Comparable<Circle> { public Circle( double rad ) { radius = rad; } public double area( ) { return Math.PI * radius * radius; } public double perimeter( ) { return 2 * Math.PI * radius; } public String toString( ) { return "Circle: " + radius; } public int compareTo(Circle other) { if (radius == other.radius) return 0; else if (radius > other.radius) return 1; else return -1; } private double radius; }

Page41of41

./Circle.java:1: java.lang.Comparable cannot be inherited with different arguments: <Circle> and <Shape> public class Circle extends Shape implements Comparable<Circle>

4.31

A possible solution is:


package weiss.math; import java.math.*; public class BigRational4 implements Comparable<BigRational4> { public static final BigRational4 ZERO = new BigRational4( ); public static final BigRational4 ONE = new BigRational4( "1" ); public BigRational4( String str ) { if( str.length( ) == 0 ) throw new IllegalArgumentException( "Zero-length string" ); // Check for "/" int slashIndex = str.indexOf( '/' ); if( slashIndex == -1 ) { // no denominator... use 1 den = BigInteger.ONE; num = new BigInteger( str.trim( ) ); } else { den = new BigInteger(str.substring(slashIndex + 1).trim()); num = new BigInteger(str.substring(0, slashIndex).trim()); check00( ); fixSigns( ); reduce( ); } } private void check00( ) { if( num.equals( BigInteger.ZERO ) && den.equals( BigInteger.ZERO ) ) throw new IllegalArgumentException( "0/0" ); } // Ensure that the denominator is positive private void fixSigns( ) { if( den.compareTo( BigInteger.ZERO ) < 0 ) { num = num.negate( ); den = den.negate( ); } } // Divide num and den by their gcd private void reduce( ) Page42of42

{ BigInteger gcd = num.gcd( den ); num = num.divide( gcd ); den = den.divide( gcd ); } public BigRational4( BigInteger n, BigInteger d ) { num = n; den = d; check00( ); fixSigns( ); reduce( ); } public BigRational4( BigInteger n ) { this( n, BigInteger.ONE ); } public BigRational4( ) { this( BigInteger.ZERO ); } public BigRational4 abs( ) { return new BigRational4( num.abs( ), den ); } public BigRational4 negate( ) { return new BigRational4( num.negate( ), den ); } public BigRational4 add( BigRational4 other ) { BigInteger newNumerator = num.multiply( other.den ).add( other.num.multiply( den ) ); BigInteger newDenominator = den.multiply( other.den ); return new BigRational4( newNumerator, newDenominator ); } public BigRational4 subtract( BigRational4 other ) { return add( other.negate( ) ); } public BigRational4 multiply( BigRational4 other ) { BigInteger newNumer = num.multiply( other.num ); BigInteger newDenom = den.multiply( other.den ); return new BigRational4( newNumer, newDenom ); }

Page43of43

public BigRational4 divide( BigRational4 other ) { if( other.num.equals( BigInteger.ZERO ) && num.equals( BigInteger.ZERO ) ) throw new ArithmeticException( "ZERO DIVIDE BY ZERO" ); BigInteger newNumer = num.multiply( other.den ); BigInteger newDenom = den.multiply( other.num ); return new BigRational4( newNumer, newDenom ); } public boolean equals( Object other ) { if( ! ( other instanceof BigRational4 ) ) return false; BigRational4 rhs = (BigRational4) other; return num.equals( rhs.num ) && den.equals( rhs.den ); } public String toString( ) { if( den.equals( BigInteger.ZERO ) ) if( num.compareTo( BigInteger.ZERO ) < 0 ) return "-infinity"; else return "infinity"; if( den.equals( BigInteger.ONE ) ) return num.toString( ); else return num + "/" + den; } private BigDecimal toBigDecimal() { BigDecimal decnum = new BigDecimal(num, MathContext.UNLIMITED); BigDecimal result = null; try { result = decnum.divide(new BigDecimal(den, MathContext.UNLIMITED), MathContext.UNLIMITED); } catch (ArithmeticException ae) { if (ae.getMessage().equals( "Non-terminating decimal expansion; " + "no exact representable decimal result.")) result = decnum.divide( new BigDecimal(den, MathContext.UNLIMITED), MathContext.DECIMAL128); } return result; } Page44of44

public int compareTo (BigRational4 other) { BigDecimal otherDec = other.toBigDecimal(); BigDecimal thisDec = this.toBigDecimal(); return thisDec.compareTo(otherDec); } private BigInteger num; private BigInteger den; } // only this can be neg

4.32

A possible solution is:


import java.util.*; public class Polynomial implements Comparable<Polynomial> { private int degree = -1; private int[] coeff; public Polynomial () { degree = 0; coeff = new int[1]; coeff[0] = 0; } public Polynomial (Polynomial poly) { this.degree = poly.degree; coeff = new int[poly.coeff.length]; for (int i=0; i<poly.coeff.length; i++) coeff[i] = poly.coeff[i]; } public Polynomial (String str) throws InvalidSpecificationException { // input format is pairs of ints (e.g 2,3) separated by a comma which // indicate the coefficient and the exponent (2x^3). Pairs are separated by // whitespace. For example: 2,3 4,2 -5,0 translates to 2x^3 + 4x^2 -5 // The largest exponent must appear in the first term (the degree). Other // terms can appear in any order, but if there are duplicates terms with // the same power, only the last term is used. Thus, it's not overly robust. Scanner poly = new Scanner(str); while (poly.hasNext()) { int cof = 0; int exponent = 0; String term = poly.next(); Scanner termScan = new Scanner(term); Page45of45

termScan.useDelimiter(","); // read each part of the term (coefficient,exponent) if (termScan.hasNextInt()) cof = termScan.nextInt(); else throw new InvalidSpecificationException("Invalid term: " + term); if (termScan.hasNextInt()) exponent = termScan.nextInt(); else throw new InvalidSpecificationException("Invalid term: " + term); // set data; degree of poly is largest exponent if (degree < exponent) degree = exponent; // create array and initialize if needed, then add new value to array if (coeff == null) { coeff = new int[degree+1]; for (int i = 0; i < coeff.length; i++) coeff[i] = 0; } coeff[exponent] = cof; } } // Duplicates the current polynomial and then negates each term. public Polynomial negate() { if (coeff == null) return null; Polynomial result = new Polynomial(this); for (int i = 0; i < result.coeff.length; i++) if (result.coeff[i] != 0) result.coeff[i] *= -1; return result; } // Adds the two polynomials together, modifying neither, and returing // a new resulting polynomial. public Polynomial add(Polynomial rhs) { // Determine which polynomial is larger, that's the one the result // will be based on, and at the end of the method, that's the one we // return. Polynomial result; Polynomial lhs; if (degree >= rhs.degree) Page46of46

{ result = new Polynomial(this); lhs = rhs; } else { result = new Polynomial(rhs); lhs = this; } for (int i = lhs.degree; i >= 0; i--) result.coeff[i] += lhs.coeff[i]; return result; } // Subtracts the rhs polynomial from the lhs polynomial, modifying neither, // and returning a new resulting polynomial. public Polynomial subtract(Polynomial rhs) { return this.add(rhs.negate()); } public Polynomial multiply(Polynomial rhs) { Polynomial result = new Polynomial(); result.degree = this.degree + rhs.degree; result.coeff = new int[result.degree+1]; for (int i = 0; i < rhs.coeff.length; i++) for (int j = 0; j < this.coeff.length; j++) result.coeff[i+j] += this.coeff[j] * rhs.coeff[i]; return result; } // Returns a true value if the lhs and rhs polynomials are equal in all // respects. public boolean equals(Object rhs) { Polynomial prhs = (Polynomial) rhs; boolean result = true; if (degree != prhs.degree) result = false; for (int i = 0; !result && i < degree; i++) if (coeff[i] != prhs.coeff[i]) result = false; return result; } // Returns a string representation of the current polynomial. public String toString() { String result = ""; for (int i = degree; i >= 0; i--) { if (i != degree && coeff[i] > 0) Page47of47

result += '+'; if (coeff[i] != 0) result += coeff[i]; if (i > 1 && coeff[i] != 0) result += "x^" + i + ' '; else if (i == 1 && coeff[i] != 0) result += "x" + ' '; } return result; } public int compareTo(Polynomial rhs) { if (degree < rhs.degree) return -1; else if (degree == rhs.degree) return 0; else return 1; } class InvalidSpecificationException extends IllegalArgumentException { public InvalidSpecificationException(String msg) { super (msg); } } }

4.33

Assuming the Shape class does not implement Comparable<Shape> (see problem 4.30), one solution would be:
public class Square extends Shape implements Comparable<Square> { public Square (double side) { this.side = side; } public double area( ) { return Math.pow(side, 2.0); } public double perimeter( ) { return side * 4.0; } public int compareTo(Square other) { if (side == other.side) return 0; else if (side < other.side) return -1; Page48of48

else return 1; } private double side; }

4.34

A possible solution (that assumes a right triangle) is:


public class Triangle extends Shape implements Stretchable { // Assumes a right triangle public Triangle (double base, double height) { this.base = base; this.height = height; } public double area( ) { return 0.5 * base * height; } public double perimeter( ) { return base + height + (base*base) + (height*height); } public void stretch (double factor) { base = base * factor; height = height * factor; } public String toString () { return "Triangle base: " + base + " } private double base; private double height; }

height: " + height;

4.35

A solution is:
public static void stretchAll( ArrayList<? extends Stretchable> arr, double factor ) { for( Stretchable s : arr ) s.stretch( factor ); }

4.36

A possible solution is:


class Person implements Comparable { public int compareTo(Object rhs) Page49of49

{ Person p2 = (Person) rhs; return (name.compareTo(p2.name)); } // Class is identical, with changes in bold. }

4.37

A solution is:
public class SingleBuffer <AnyType> { private AnyType theItem; private boolean isEmpty; public SingleBuffer( ) { theItem = null; isEmpty = true; } public SingleBuffer( AnyType item ) { theItem = item; if ( theItem != null ) isEmpty = false; else isEmpty = true; } public AnyType get( ) throws SingleBufferException { if ( isEmpty ) throw new SingleBufferException( "Buffer is empty!" );

isEmpty = true; AnyType item = theItem; theItem = null; return item;


} public void put( AnyType item ) throws SingleBufferException { if ( !isEmpty ) throw new SingleBufferException( "Buffer must be emptied by insertion!" ); theItem = item; isEmpty = false; } } public class SingleBufferException extends Exception { public SingleBufferException( String msg ) { super( msg ); } }

Page50of50

4.38

Here is an even fancier version that uses iterators, inner classes, nested classes, and comparators. Of course it has way too many forward references for use at this point in the course, but you can remove complications as needed.
import java.util.*; /** * A SortedArrayList stores objects in sorted order. * The SortedArrayList supports the add operation. * size is also provided, and so is a method * that returns an Iterator. * Of course a get routine could be provided too * as could numerous other routines.. * * This example illustrates both instance inner classes * and static inner classes. * An instance inner class is used in the typical iterator pattern. * A static inner class is used to define a default comparator. */ class SortedArrayList { // The list, in sorted order private ArrayList data = new ArrayList( ); // The comparator object private Comparator cmp; /** * Construct the SortedArrayList with specified Comparator. * @param compare The Comparator object. */ public SortedArrayList( Comparator compare ) { cmp = compare; } /** * Construct the SortedArrayList using natural ordering * If objects are not Comparable, an exception will be * thrown during an add operation. */ public SortedArrayList( ) { this( new DefaultComparator( ) ); } private static class DefaultComparator implements Comparator { public int compare( Object obj1, Object obj2 ) { return ((Comparable) obj1).compareTo( obj2 ); } } /** * Add a new value to this SortedArrayList, maintaining sorted * order. * @param x The Object to add. Page51of51

*/ public void add( Object x ) { data.add( x ); // add at the end for now int i = data.size( ) - 1; // Slide x over to correct position for( ; i > 0 && cmp.compare( data.get( i - 1 ), x ) > 0; i-- ) data.set( i, data.get( i - 1 ) ); data.set( i, x ); } /** * Return the number of items in this SortedArrayList. * @return the number of items in this SortedArrayList. */ public int size( ) { return data.size( ); } /** * Return an Iterator that can be used to traverse * this SortedArrayList. The remove operation is unimplemented. * @return An Iterator that can be used to traverse this * SortedArrayList. */ public Iterator iterator( ) { return new SortedIterator( ); } private class SortedIterator implements Iterator { private int current = 0; public boolean hasNext( ) { return current < size( ); } public Object next( ) { return data.get( current++ ); } public void remove( ) { throw new UnsupportedOperationException( ); } } } class TestSortedArrayList { public static String listToString( SortedArrayList list ) { Page52of52

Iterator itr = list.iterator( ); StringBuffer sb = new StringBuffer( ); for( int i = 0; itr.hasNext( ); i++ ) sb.append( [ + i + ] + itr.next( ) + ); return new String( sb ); } // Test by inserting 20 Strings public static void main( String[] args ) { SortedArrayList list = new SortedArrayList( ); for( int i = 0; i < 20; i++ ) list.add( + i ); System.out.println( Using iterator ); System.out.println( listToString( list ) ); } }

4.39

One solution is as follows:


import weiss.util.Comparator; public class StringComparator implements Comparator<String> { public int compare (String str1, String str2) { return str1.compareToIgnoreCase(str2); } }

4.40

Code solutions to all parts are as follows:


package weiss.util; /** * ContentsChecker function object interface. */ public interface ContentsChecker { /** * Returns a true value if data matches a criteria (prime, etc.) */ public boolean check(int [] data); }

// Accepts an array of ints and a ContentsChecker object. The array is // then searched to determine if there are any ints contained in the // array that match the criteria of the ContentsChecker. public static boolean contains (int [] input, ContentsChecker cmp) { return cmp.check(input); }

Page53of53

import weiss.util.ContentsChecker; public class Negative implements ContentsChecker // Checks to determine if any of the items of the data array are // negative. public boolean check (int [] data) { boolean negative = false; for (int index = 0; !negative && index < data.length; index++) { if (data[index] < 0) negative = true; } return negative; } } import weiss.util.ContentsChecker; public class Prime implements ContentsChecker { // Checks to determine if any of the items of the data array are // prime values. This algorithm uses the naive algorithm (see // http://en.wikipedia.org/wiki/Primality_test#Na.C3.AFve_methods) // to detect primality. public boolean check (int [] data) { boolean prime = false; for (int index = 0; index < data.length; index++) { int sqrtNum = (new Double(Math.sqrt(data[index]))).intValue(); boolean thisTest = true; for (int tester = 2; thisTest && tester <= sqrtNum; tester++) if (data[index] % tester == 0) thisTest = false; if (thisTest == true) prime = true; } return prime; } } import weiss.util.ContentsChecker; public class PerfectSquare implements ContentsChecker { // Checks to determine if any of the items of the data array are // perfect squares. public boolean check (int [] data) { boolean perfectSquare = false; for (int index = 0; !perfectSquare && index < data.length;

Page54of54

index++) { if (Math.pow(Math.rint(Math.sqrt(data[index])), 2.0) == data[index]) perfectSquare = true; } return perfectSquare; } }

4.41

Code solutions to all parts are as follows:


package weiss.util; /** * ArrayComputation function object interface. */ public interface ArrayTransformation { /** * Performs an operation on an array */ public void transform (double [] input, double[] transform); }

// Performs a specified transformation on an input array, placing the // output into the specified output array. An IllegalArgumentException // is thrown if the array lengths are not equal. public static void transform (double[] input, double[] output, ArrayTransformation trans) throws IllegalArgumentException { if (input.length != output.length) throw new IllegalArgumentException(); trans.transform(input, output); } import weiss.util.ArrayTransformation; public class ComputeSquare implements ArrayTransformation { /** * Computes the square of each member of the input array. * The results are returned in the new array. */ public void transform (double [] input, double [] output) { for (int index = 0; index < input.length; index++) output[index] = Math.pow(input[index], 2.0); } } import weiss.util.ArrayTransformation; Page55of55

public class ComputeAbsoluteValue implements ArrayTransformation { /** * Computes the absolute value of each member of the input array. * The results are returned in the new array. */ public void transform (double [] input, double [] output) { for (int index = 0; index < input.length; index++) output[index] = Math.abs(input[index]); } }

4.42

A solution is as follows:
package weiss.util; /** * ContentsChecker2 function object interface. */ public interface ContentsChecker2 { /** * Returns a true value if data matches a criteria (prime, etc.) */ public <AnyType> boolean check(AnyType[] data); }

// Accepts any array and a ContentsChecker2 object. The array is // then searched to determine if there are any items contained in // the array that match the criteria of the ContentsChecker2. public static <AnyType> boolean contains2 (AnyType[] input, ContentsChecker2 cmp) { return cmp.check(input); } import weiss.util.ContentsChecker2; public class Negative2 implements ContentsChecker2 { // Checks to determine if any of the items of the // data array are negative. public <AnyType> boolean check (AnyType[] data) { boolean negative = false; for (int index = 0; !negative && index < data.length; index++) { Integer zero = new Integer(0); if (zero.compareTo((Integer) data[index]) > 1) negative = true; } Page56of56

return negative; } } import weiss.util.ContentsChecker2; public class Prime2 implements ContentsChecker2 { // Checks to determine if any of the items of the // data array are prime values. This algorithm uses // the naive algorithm (see // http://en.wikipedia.org/wiki/Primality_test#Na.C3.AFve_methods) // to detect primality. public <AnyType> boolean check (AnyType[] data) { boolean prime = false; for (int index = 0; index < data.length; index++) { int sqrtNum = (new Double(Math.sqrt( (Integer) data[index]))).intValue(); boolean thisTest = true; for (int tester = 2; thisTest && tester <= sqrtNum; tester++) if ((Integer) data[index] % tester == 0) thisTest = false; if (thisTest == true) prime = true; } return prime; } } import weiss.util.ContentsChecker2; public class PerfectSquare2 implements ContentsChecker2 { // Checks to determine if any of the items of the data // array are perfect squares. public <AnyType> boolean check (AnyType[] data) { boolean perfectSquare = false; for (int index = 0; !perfectSquare && index < data.length; index++) { double valueSqrd = Math.pow(Math.rint(Math.sqrt( (Integer) data[index])), 2.0); if (valueSqrd == (Integer) data[index]) perfectSquare = true; } return perfectSquare; } }

4.43

A solution is as follows:
Page57of57

package weiss.util; /** * ArrayComputation function object interface. */ public interface ArrayTransformation2 { /** * Performs an operation on an array */ public <AnyType> void transform (AnyType[] input, AnyType[] transform); } // Performs a specified transformation on an input array, // placing the output into the specified output array. An // IllegalArgumentException is thrown if the array lengths // are not equal. public static <AnyType> void transform2 (AnyType[] input, AnyType[] output, ArrayTransformation2 trans) throws IllegalArgumentException { if (input.length != output.length) throw new IllegalArgumentException(); trans.transform(input, output); } import weiss.util.ArrayTransformation2; public class ComputeSquare2 implements ArrayTransformation2 { /** * Computes the square of each member of the input array. * The results are returned in the new array. */ public <AnyType> void transform (AnyType[] input, AnyType[] output) { for (int index = 0; index < input.length; index++) { Double newDbl = new Double((Math.pow( (Double) input[index], 2.0))); output[index] = (AnyType) newDbl; } } } import weiss.util.ArrayTransformation2; public class ComputeAbsoluteValue2 implements ArrayTransformation2 { /** * Computes the absolute value of each member of the input array. * The results are returned in the new array. */ Page58of58

public <AnyType> void transform (AnyType[] input, AnyType[] output) { for (int index = 0; index < input.length; index++) { Double newDbl = new Double(Math.abs((Double) input[index])); output[index] = (AnyType) newDbl; } } }

4.44

One solution is as follows:


public interface Matchable { boolean matches(int a); } class EqualsZero implements Matchable { public boolean matches(int a) { return a == 0; } } class CountTester { public static int countMatches( int [] a, Matchable func ) { int num = 0; for( int i = 0; i < a.length; i++ ) if( func.matches( a[i]) ) num++; return num; } public static void main (String [] args) { int [] a = { 4, 0, 5, 0, 0}; System.out.println(countMatches(a, new EqualsZero())); } }

4.45

One solution is as follows:


class EqualsK implements Matchable { private int k; public EqualsK( int initialk ) { k = initialk; } public EqualsK() { this( 0 ); } Page59of59

public boolean matches(int a) { return a == k; } } class Tester { public static void main (String [] args) { int [] a = { 4, 0, 5, 0, 0}; System.out.println( CountTester.countMatches(a, new EqualsK(5))); } } 4.3ExamQuestions 4.1 Whichtermdescribestheabilityofareferencetypetoreferenceobjectsofseveraldifferent types? a. composition b. encapsulation c. informationhiding d. polymorphism e. staticbinding

4.2

Inthederivedclass,whichdatamembersofthebaseclassarevisible? a. thoseinthepublicsectiononly b. thoseintheprotectedsectiononly c. thoseinthepublicorprotectedsections d. thoseinthepublicorprivatesections e. alldatamembersarevisible Forwhichmethodsisdynamicbindingused? a. allclassmethods b. allstaticmethods c. finalmethods d. nonstatic,nonfinalclassmethods e. noneoftheabove Whichofthefollowingistrueaboutanabstractbaseclass? a. noconstructorsshouldbeprovided b. atleastonememberfunctionshouldbeabstract c. noobjectsoftheclasscanbecreated d. exactlytwooftheabove e. allof(a),(b),and(c) Whenisamethodabstract? a. Whenitisconstantthroughouttheinheritancehierarchy b. Itsdefinitionchangesintheinheritancehierarchy,butthereisareasonabledefault c. Noreasonabledefaultcanbeprovided,anditmustbedefinedintheinheritancehierarchy d. Always e. noneoftheabove Whichofthefollowingarenotallowedinaninterface?
Page60of60

4.3

4.4

4.5

4.6

a. b. c. d. e. 4.7

publicmethods staticmethods finalmethods publicfields staticfields

HowisgenericprogrammingimplementedinJava1.5? a. byinheritance b. importdirective c. packagestatement d. privatemethods e. usingatemplate Whichclauseisusedtoderiveanewclass? a. extends b. implements c. import d. throw e. atleasttwooftheabove Whichofthefollowingisfalse? a. Anabstractclassmayimplementaninterface. b. Aclassthatcontainsanabstractmethodmustbedeclaredabstractitselforacompiler messagewillresult. c. Aclassmayimplementmultipleinterfaces. d. Aclassthatextendsanotherclassmayimplementonlyoneinterface. e. Aninterfacemayextendanotherinterface. Whichof(a)(c)isfalse? a. Anadapterclassisusedtochangetheinterfaceofanexistingclass. b. Awrapperclassstoresaprimitivetypesandaddoperationsthatprimitivetypedoesnot support. c. Anadapterisusedtoprovideasimplerinterfacewithfewermethods d. Both(a)and(c)arefalse e. alloftheabovearefalse Whichof(a)(d)isfalse? a. Anestedclassisamemberofitsouterclass. b. Anestedclassmustbedeclaredstatic. c. Methodsofalocalclasscanaccesslocalvariablesofitsouterclass. d. Alocalclassisvisibleonlyinsidethemethodinwhichitisdeclared. e. Both(b)and(c)arefalse

4.8

4.9

4.10

4.11

AnswerstoExamQuestions 1. D 2. C 3. D 4. D 5. C 6. C 7. A 8. E 9. D 10. B 11. C Page61of61

You might also like