From d88c9042d8fb6b7fecad67ac0fd325ecacc08f73 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 19 Nov 2020 14:48:57 +0800 Subject: [PATCH 01/68] 1 --- code/.gitattributes | 17 + code/.gitignore | 111 +++++ code/.travisXX.yml | 8 + code/CI.txt | 5 + code/Copyright.txt | 72 +++ code/README.md | 43 ++ code/annotations/AUComposition.java | 30 ++ code/annotations/AUExternalTest.java | 29 ++ code/annotations/AtUnitExample1.java | 48 ++ code/annotations/AtUnitExample2.java | 57 +++ code/annotations/AtUnitExample3.java | 42 ++ code/annotations/AtUnitExample4.java | 83 ++++ code/annotations/AtUnitExample5.java | 63 +++ code/annotations/DemoProcessFiles.java | 43 ++ code/annotations/HashSetTest.java | 36 ++ code/annotations/PasswordUtils.java | 24 + code/annotations/SimulatingNull.java | 12 + code/annotations/StackL.java | 14 + code/annotations/StackLStringTst.java | 42 ++ code/annotations/Testable.java | 14 + code/annotations/UseCase.java | 12 + code/annotations/UseCaseTracker.java | 37 ++ code/annotations/database/Constraints.java | 14 + code/annotations/database/DBTable.java | 12 + code/annotations/database/Member.java | 22 + code/annotations/database/SQLInteger.java | 13 + code/annotations/database/SQLString.java | 14 + code/annotations/database/TableCreator.java | 106 +++++ code/annotations/database/Uniqueness.java | 11 + code/annotations/ifx/ExtractInterface.java | 13 + .../ifx/IfaceExtractorProcessor.java | 91 ++++ code/annotations/ifx/Multiplier.java | 34 ++ code/annotations/simplest/Simple.java | 20 + .../annotations/simplest/SimpleProcessor.java | 47 ++ code/annotations/simplest/SimpleTest.java | 32 ++ code/appveyorXX.yml | 4 + code/arrays/AlphabeticSearch.java | 29 ++ code/arrays/ArrayCopying.java | 81 ++++ code/arrays/ArrayOfGenericType.java | 16 + code/arrays/ArrayOfGenerics.java | 33 ++ code/arrays/ArrayOptions.java | 79 ++++ code/arrays/ArraySearching.java | 33 ++ .../AssemblingMultidimensionalArrays.java | 22 + code/arrays/AutoboxingArrays.java | 22 + code/arrays/CollectionComparison.java | 53 +++ code/arrays/CompType.java | 56 +++ code/arrays/ComparatorTest.java | 39 ++ code/arrays/ComparingArrays.java | 62 +++ code/arrays/CountUpward.java | 24 + code/arrays/FillingArrays.java | 55 +++ code/arrays/IceCreamFlavors.java | 45 ++ code/arrays/ModifyExisting.java | 22 + code/arrays/MultiDimWrapperArray.java | 38 ++ code/arrays/MultidimensionalObjectArrays.java | 25 ++ .../MultidimensionalPrimitiveArray.java | 18 + code/arrays/ParallelPrefix1.java | 27 ++ code/arrays/ParallelPrefix2.java | 20 + code/arrays/ParallelPrefix3.java | 23 + code/arrays/ParallelSetAll.java | 24 + code/arrays/ParameterizedArrayType.java | 25 ++ code/arrays/PythonLists.py | 36 ++ code/arrays/RaggedArray.java | 26 ++ code/arrays/Reverse.java | 32 ++ code/arrays/SimpleSetAll.java | 56 +++ code/arrays/StreamFromArray.java | 51 +++ code/arrays/StringSorting.java | 39 ++ code/arrays/TestConvertTo.java | 87 ++++ code/arrays/TestCount.java | 167 +++++++ code/arrays/TestRand.java | 192 ++++++++ code/arrays/ThreeDWithNew.java | 17 + code/arrays/jmh/ParallelSort.java | 25 ++ code/build.gradle | 23 + code/checkstyle.xml | 179 ++++++++ code/chkstyle.bat | 2 + code/collections/AdapterMethodIdiom.java | 48 ++ code/collections/AddingGroups.java | 24 + .../ApplesAndOrangesWithGenerics.java | 23 + .../ApplesAndOrangesWithoutGenerics.java | 38 ++ code/collections/ArrayIsNotIterable.java | 23 + code/collections/AsListInference.java | 34 ++ code/collections/CollectionDifferences.java | 71 +++ code/collections/CollectionSequence.java | 40 ++ .../collections/CrossCollectionIteration.java | 36 ++ .../CrossCollectionIteration2.java | 37 ++ code/collections/EnvironmentVariables.java | 15 + code/collections/ForInCollections.java | 19 + code/collections/GenericsAndUpcasting.java | 28 ++ code/collections/InterfaceVsIterator.java | 55 +++ code/collections/IterableClass.java | 35 ++ code/collections/LinkedListFeatures.java | 54 +++ code/collections/ListFeatures.java | 93 ++++ code/collections/ListIteration.java | 37 ++ code/collections/MapOfList.java | 65 +++ code/collections/ModifyingArraysAsList.java | 32 ++ code/collections/MultiIterableClass.java | 53 +++ code/collections/NonCollectionSequence.java | 37 ++ code/collections/PetMap.java | 27 ++ code/collections/PrintingCollections.java | 44 ++ code/collections/PriorityQueueDemo.java | 53 +++ code/collections/QueueDemo.java | 29 ++ code/collections/SetOfInteger.java | 19 + code/collections/SetOfString.java | 25 ++ code/collections/SetOperations.java | 40 ++ code/collections/SimpleCollection.java | 18 + code/collections/SimpleIteration.java | 36 ++ code/collections/SortedSetOfString.java | 25 ++ code/collections/StackCollision.java | 25 ++ code/collections/StackTest.java | 18 + code/collections/StackTest2.java | 18 + code/collections/Statistics.java | 25 ++ code/collections/UniqueWords.java | 29 ++ code/collections/UniqueWordsAlphabetic.java | 30 ++ code/collectiontopics/AssociativeArray.java | 64 +++ code/collectiontopics/Bits.java | 79 ++++ code/collectiontopics/CanonicalMapping.java | 56 +++ code/collectiontopics/CollectionMethods.java | 135 ++++++ code/collectiontopics/Enumerations.java | 24 + code/collectiontopics/FailFast.java | 22 + code/collectiontopics/FillMapTest.java | 32 ++ code/collectiontopics/FillingLists.java | 35 ++ code/collectiontopics/FunctionalMap.java | 38 ++ code/collectiontopics/HTMLColorTest.java | 103 +++++ code/collectiontopics/LinkedHashMapDemo.java | 31 ++ code/collectiontopics/ListOps.java | 167 +++++++ code/collectiontopics/ListSortSearch.java | 57 +++ code/collectiontopics/MapOps.java | 76 ++++ code/collectiontopics/NavMap.java | 96 ++++ code/collectiontopics/QueueBehavior.java | 50 +++ code/collectiontopics/ReadOnly.java | 56 +++ code/collectiontopics/References.java | 92 ++++ code/collectiontopics/SetOrder.java | 92 ++++ code/collectiontopics/SimpleDeques.java | 70 +++ code/collectiontopics/SortedMapDemo.java | 42 ++ code/collectiontopics/SortedSetDemo.java | 42 ++ code/collectiontopics/Stacks.java | 61 +++ code/collectiontopics/StreamFillMaps.java | 55 +++ .../SuppliersCollectionTest.java | 67 +++ code/collectiontopics/Synchronization.java | 24 + code/collectiontopics/ToDoList.java | 56 +++ code/collectiontopics/TypesForSets.java | 93 ++++ code/collectiontopics/Unsupported.java | 60 +++ code/collectiontopics/Utilities.java | 88 ++++ code/com/mindviewinc/simple/List.java | 12 + code/com/mindviewinc/simple/Vector.java | 12 + code/compression/GZIPcompress.java | 45 ++ code/compression/ZipCompress.java | 83 ++++ code/concurrent/Baked.java | 31 ++ code/concurrent/Batter.java | 34 ++ code/concurrent/Breakable.java | 29 ++ code/concurrent/CachedThreadPool.java | 29 ++ code/concurrent/CachedThreadPool2.java | 29 ++ code/concurrent/CachedThreadPool3.java | 47 ++ .../CatchCompletableExceptions.java | 81 ++++ code/concurrent/CollectionIntoStream.java | 36 ++ code/concurrent/CompletableApply.java | 27 ++ code/concurrent/CompletableApplyAsync.java | 31 ++ code/concurrent/CompletableApplyChained.java | 27 ++ code/concurrent/CompletableExceptions.java | 75 ++++ code/concurrent/CompletableOperations.java | 74 ++++ code/concurrent/CompletablePizza.java | 87 ++++ code/concurrent/CompletableUtilities.java | 27 ++ code/concurrent/CompletedMachina.java | 19 + code/concurrent/CountingStream.java | 32 ++ code/concurrent/CountingTask.java | 19 + code/concurrent/DiningPhilosophers.java | 33 ++ .../concurrent/DualCompletableOperations.java | 115 +++++ code/concurrent/FrostedCake.java | 32 ++ code/concurrent/Futures.java | 23 + code/concurrent/GuardedIDField.java | 18 + code/concurrent/HasID.java | 8 + code/concurrent/IDChecker.java | 41 ++ code/concurrent/InterferingTask.java | 17 + .../LambdasAndMethodReferences.java | 40 ++ code/concurrent/Machina.java | 31 ++ code/concurrent/MoreTasksAfterShutdown.java | 27 ++ code/concurrent/NapTask.java | 20 + code/concurrent/OnePizza.java | 26 ++ code/concurrent/ParallelPrime.java | 35 ++ code/concurrent/ParallelStreamPuzzle.java | 28 ++ code/concurrent/ParallelStreamPuzzle2.java | 38 ++ code/concurrent/ParallelStreamPuzzle3.java | 33 ++ code/concurrent/Philosopher.java | 30 ++ code/concurrent/Pizza.java | 49 +++ code/concurrent/PizzaParallelSteps.java | 69 +++ code/concurrent/PizzaStreams.java | 60 +++ code/concurrent/QuittableTask.java | 20 + code/concurrent/QuittingCompletable.java | 35 ++ code/concurrent/QuittingTasks.java | 35 ++ .../concurrent/SharedConstructorArgument.java | 44 ++ code/concurrent/SingleThreadExecutor.java | 49 +++ code/concurrent/SingleThreadExecutor2.java | 30 ++ code/concurrent/SingleThreadExecutor3.java | 30 ++ code/concurrent/StaticIDField.java | 10 + code/concurrent/StickHolder.java | 27 ++ code/concurrent/StreamExceptions.java | 40 ++ code/concurrent/Summing.java | 47 ++ code/concurrent/Summing2.java | 44 ++ code/concurrent/Summing3.java | 42 ++ code/concurrent/Summing4.java | 23 + code/concurrent/SynchronizedConstructor.java | 29 ++ code/concurrent/SynchronizedFactory.java | 29 ++ code/concurrent/TestStaticIDField.java | 13 + code/concurrent/ThrowsChecked.java | 42 ++ code/concurrent/Workable.java | 32 ++ code/control/BreakAndContinue.java | 38 ++ code/control/CommaOperator.java | 18 + code/control/ForInFloat.java | 28 ++ code/control/ForInInt.java | 28 ++ code/control/ForInString.java | 14 + code/control/IfElse.java | 29 ++ code/control/LabeledFor.java | 65 +++ code/control/LabeledWhile.java | 51 +++ code/control/ListCharacters.java | 27 ++ code/control/RandomBounds.java | 30 ++ code/control/StringSwitch.java | 44 ++ code/control/TestWithReturn.java | 24 + code/control/TrueFalse.java | 15 + code/control/VowelsAndConsonants.java | 44 ++ code/control/WhileTest.java | 31 ++ code/enums/AlarmPoints.java | 9 + code/enums/BigEnumSet.java | 29 ++ code/enums/Burrito2.java | 28 ++ code/enums/CarWash.java | 88 ++++ code/enums/Competitor.java | 10 + code/enums/ConstantSpecificMethod.java | 41 ++ code/enums/EnumClass.java | 51 +++ code/enums/EnumMaps.java | 37 ++ code/enums/EnumSets.java | 39 ++ code/enums/Input.java | 33 ++ code/enums/NonEnum.java | 19 + code/enums/NotClasses.java | 50 +++ code/enums/Outcome.java | 6 + code/enums/OverrideConstantSpecific.java | 28 ++ code/enums/OzWitch.java | 32 ++ code/enums/PostOffice.java | 197 +++++++++ code/enums/RandomTest.java | 21 + code/enums/Reflection.java | 71 +++ code/enums/RoShamBo.java | 21 + code/enums/RoShamBo1.java | 104 +++++ code/enums/RoShamBo2.java | 55 +++ code/enums/RoShamBo3.java | 71 +++ code/enums/RoShamBo4.java | 57 +++ code/enums/RoShamBo5.java | 59 +++ code/enums/RoShamBo6.java | 46 ++ code/enums/SecurityCategory.java | 46 ++ code/enums/SpaceShip.java | 28 ++ code/enums/SpicinessEnum.java | 9 + code/enums/TrafficLight.java | 44 ++ code/enums/UpcastEnum.java | 21 + code/enums/VendingMachine.java | 183 ++++++++ code/enums/VendingMachineInput.txt | 8 + code/enums/cartoons/EnumImplementation.java | 37 ++ code/enums/menu/Course.java | 20 + code/enums/menu/Food.java | 24 + code/enums/menu/Meal.java | 45 ++ code/enums/menu/Meal2.java | 74 ++++ code/enums/menu/TypeOfFood.java | 16 + code/equalshashcode/ComposedEquality.java | 66 +++ code/equalshashcode/CountedString.java | 72 +++ code/equalshashcode/DefaultComparison.java | 24 + code/equalshashcode/Equality.java | 77 ++++ code/equalshashcode/EqualityFactory.java | 9 + code/equalshashcode/Groundhog.java | 14 + code/equalshashcode/Groundhog2.java | 19 + code/equalshashcode/IndividualTest.java | 31 ++ code/equalshashcode/MapEntry.java | 42 ++ code/equalshashcode/Prediction.java | 15 + code/equalshashcode/SimpleHashMap.java | 90 ++++ code/equalshashcode/SlowMap.java | 64 +++ code/equalshashcode/SpringDetector.java | 62 +++ code/equalshashcode/SpringDetector2.java | 25 ++ code/equalshashcode/StringHashCode.java | 16 + code/equalshashcode/SubtypeEquality.java | 60 +++ code/equalshashcode/SubtypeEquality2.java | 40 ++ code/equalshashcode/SuccinctEquality.java | 46 ++ code/exceptions/AlwaysFinally.java | 33 ++ code/exceptions/AutoCloseableDetails.java | 33 ++ code/exceptions/BodyException.java | 32 ++ code/exceptions/Cleanup.java | 30 ++ code/exceptions/CleanupIdiom.java | 72 +++ code/exceptions/CloseExceptions.java | 48 ++ code/exceptions/ConstructorException.java | 33 ++ code/exceptions/DynamicFields.java | 130 ++++++ code/exceptions/ExceptionMethods.java | 32 ++ code/exceptions/ExceptionSilencer.java | 16 + code/exceptions/ExtraFeatures.java | 72 +++ code/exceptions/FinallyWorks.java | 32 ++ code/exceptions/FullConstructors.java | 44 ++ code/exceptions/Human.java | 31 ++ code/exceptions/InheritingExceptions.java | 28 ++ code/exceptions/InputFile.java | 47 ++ code/exceptions/InputFile2.java | 28 ++ code/exceptions/LoggingExceptions.java | 48 ++ code/exceptions/LoggingExceptions2.java | 32 ++ code/exceptions/LostMessage.java | 44 ++ code/exceptions/MainException.java | 17 + code/exceptions/MessyExceptions.java | 27 ++ code/exceptions/MultiCatch.java | 16 + code/exceptions/MultiCatch2.java | 19 + code/exceptions/MultipleReturns.java | 47 ++ code/exceptions/NeverCaught.java | 26 ++ code/exceptions/OnOffException1.java | 5 + code/exceptions/OnOffException2.java | 5 + code/exceptions/OnOffSwitch.java | 29 ++ code/exceptions/PreciseRethrow.java | 17 + code/exceptions/RethrowNew.java | 47 ++ code/exceptions/Rethrowing.java | 70 +++ code/exceptions/SameHandler.java | 31 ++ code/exceptions/StormyInning.java | 83 ++++ code/exceptions/StreamsAreAutoCloseable.java | 24 + code/exceptions/Switch.java | 21 + code/exceptions/TryAnything.java | 16 + code/exceptions/TryWithResources.java | 19 + code/exceptions/TurnOffChecking.java | 64 +++ code/exceptions/WhoCalled.java | 39 ++ code/exceptions/WithFinally.java | 26 ++ code/files/AddAndSubtractPaths.java | 87 ++++ code/files/Directories.java | 94 ++++ code/files/FileSystemDemo.java | 41 ++ code/files/Find.java | 60 +++ code/files/ListOfLines.java | 26 ++ code/files/PartsOfPaths.java | 45 ++ code/files/PathAnalysis.java | 56 +++ code/files/PathInfo.java | 102 +++++ code/files/PathWatcher.java | 61 +++ code/files/ReadLineStream.java | 18 + code/files/StreamInAndOut.java | 24 + code/files/TreeWatcher.java | 51 +++ code/files/Writing.java | 31 ++ code/functional/AnonymousClosure.java | 17 + code/functional/BiConsumerPermutations.java | 24 + code/functional/ClassFunctionals.java | 45 ++ code/functional/Closure1.java | 12 + code/functional/Closure2.java | 12 + code/functional/Closure3.java | 14 + code/functional/Closure4.java | 12 + code/functional/Closure5.java | 15 + code/functional/Closure6.java | 16 + code/functional/Closure7.java | 14 + code/functional/Closure8.java | 32 ++ code/functional/Closure9.java | 15 + code/functional/ConsumeFunction.java | 17 + code/functional/CtorReference.java | 36 ++ code/functional/CurriedIntAdd.java | 17 + code/functional/Curry3Args.java | 23 + code/functional/CurryingAndPartials.java | 35 ++ code/functional/FunctionComposition.java | 24 + code/functional/FunctionVariants.java | 65 +++ code/functional/FunctionWithWrapped.java | 12 + code/functional/FunctionalAnnotation.java | 40 ++ code/functional/IntCall.java | 8 + code/functional/LambdaExpressions.java | 48 ++ code/functional/MethodConversion.java | 31 ++ code/functional/MethodReferences.java | 53 +++ code/functional/MultiUnbound.java | 36 ++ code/functional/PredicateComposition.java | 23 + code/functional/ProduceFunction.java | 21 + code/functional/RecursiveFactorial.java | 26 ++ code/functional/RecursiveFibonacci.java | 32 ++ code/functional/RunnableMethodReference.java | 33 ++ code/functional/SharedStorage.java | 22 + code/functional/Strategize.java | 58 +++ code/functional/TransformFunction.java | 35 ++ code/functional/TriFunction.java | 9 + code/functional/TriFunctionTest.java | 13 + code/functional/UnboundMethodReference.java | 31 ++ code/generics/Amphibian.java | 5 + code/generics/Apply.java | 21 + code/generics/ApplyFunctional.java | 49 +++ code/generics/ApplyTest.java | 65 +++ code/generics/ArrayMaker.java | 24 + code/generics/ArrayOfGeneric.java | 28 ++ code/generics/ArrayOfGenericReference.java | 10 + code/generics/BankTeller.java | 71 +++ code/generics/BasicBounds.java | 63 +++ code/generics/BasicHolder.java | 14 + code/generics/BasicSupplierDemo.java | 22 + code/generics/ByteSet.java | 14 + code/generics/CRGWithBasicHolder.java | 20 + code/generics/CaptureConversion.java | 62 +++ code/generics/CheckedList.java | 35 ++ code/generics/ClassCasting.java | 18 + code/generics/ClassTypeCapture.java | 33 ++ code/generics/ComparablePet.java | 12 + code/generics/CompilerIntelligence.java | 15 + code/generics/CountedObject.java | 14 + code/generics/CovariantArrays.java | 30 ++ code/generics/CovariantReturnTypes.java | 23 + code/generics/CreatorGeneric.java | 31 ++ code/generics/CuriouslyRecurringGeneric.java | 9 + code/generics/Diamond.java | 13 + .../DogsAndRobotMethodReferences.java | 45 ++ code/generics/DogsAndRobots.cpp | 38 ++ code/generics/DogsAndRobots.java | 41 ++ code/generics/DogsAndRobots.py | 36 ++ code/generics/DynamicProxyMixin.java | 66 +++ code/generics/EpicBattle.java | 74 ++++ code/generics/Erased.java | 24 + code/generics/ErasedTypeEquivalence.java | 16 + code/generics/ErasureAndInheritance.java | 28 ++ code/generics/FactoryConstraint.java | 62 +++ code/generics/Fibonacci.java | 27 ++ code/generics/FilledList.java | 28 ++ code/generics/GenericArray.java | 32 ++ code/generics/GenericArray2.java | 39 ++ code/generics/GenericArrayWithTypeToken.java | 27 ++ code/generics/GenericCast.java | 47 ++ code/generics/GenericHolder.java | 19 + code/generics/GenericHolder2.java | 16 + code/generics/GenericMethods.java | 27 ++ code/generics/GenericReading.java | 46 ++ code/generics/GenericVarargs.java | 30 ++ code/generics/GenericsAndCovariance.java | 19 + code/generics/GenericsAndReturnTypes.java | 17 + code/generics/HasF.java | 10 + code/generics/HijackedInterface.java | 16 + code/generics/Holder.java | 42 ++ code/generics/Holder1.java | 12 + code/generics/InheritBounds.java | 40 ++ code/generics/InstantiateGenericType.cpp | 20 + code/generics/InstantiateGenericType.java | 46 ++ code/generics/IterableFibonacci.java | 36 ++ code/generics/LatentReflection.java | 65 +++ code/generics/LinkedStack.java | 43 ++ code/generics/ListMaker.java | 13 + code/generics/ListOfGenerics.java | 11 + code/generics/ListOfInt.java | 20 + code/generics/LostInformation.java | 33 ++ code/generics/Manipulation.java | 21 + code/generics/Manipulator2.java | 10 + code/generics/Manipulator3.java | 10 + code/generics/Mixins.cpp | 47 ++ code/generics/Mixins.java | 71 +++ code/generics/MultipleInterfaceVariants.java | 13 + code/generics/NeedCasting.java | 15 + code/generics/NonCovariantGenerics.java | 11 + code/generics/NotSelfBounded.java | 24 + code/generics/ObjectHolder.java | 20 + code/generics/OrdinaryArguments.java | 31 ++ code/generics/Performs.java | 9 + code/generics/PlainGenericInheritance.java | 30 ++ code/generics/PrimitiveGenericTest.java | 42 ++ code/generics/RandomList.java | 26 ++ code/generics/RestrictedComparablePets.java | 19 + code/generics/ReturnGenericType.java | 10 + code/generics/SelfBounding.java | 40 ++ .../SelfBoundingAndCovariantArguments.java | 31 ++ code/generics/SelfBoundingMethods.java | 13 + code/generics/Shape.java | 19 + code/generics/SimpleDogsAndRobots.java | 25 ++ code/generics/SimpleHolder.java | 15 + code/generics/SimpleQueue.java | 16 + code/generics/Square.java | 5 + code/generics/Store.java | 90 ++++ code/generics/SuperTypeWildcards.java | 13 + code/generics/Templates.cpp | 27 ++ code/generics/ThrowGenericException.java | 82 ++++ code/generics/TupleList.java | 23 + code/generics/TupleTest.java | 42 ++ code/generics/TupleTest2.java | 42 ++ code/generics/UnboundedWildcards1.java | 58 +++ code/generics/UnboundedWildcards2.java | 35 ++ code/generics/Unconstrained.java | 20 + code/generics/UseList.java | 11 + code/generics/UseList2.java | 10 + code/generics/Vehicle.java | 5 + code/generics/WatercolorSets.java | 54 +++ code/generics/Wildcards.java | 285 ++++++++++++ code/generics/coffee/Americano.java | 6 + code/generics/coffee/Breve.java | 6 + code/generics/coffee/Cappuccino.java | 6 + code/generics/coffee/Coffee.java | 14 + code/generics/coffee/CoffeeSupplier.java | 72 +++ code/generics/coffee/Latte.java | 6 + code/generics/coffee/Mocha.java | 6 + code/generics/decorator/Decoration.java | 51 +++ code/generics/dogsandrobots.go | 32 ++ code/generics/watercolors/Watercolors.java | 15 + code/gradle.properties | 1 + code/gradle/checkstyle.gradle | 14 + code/gradle/findbugs.gradle | 15 + code/gradle/java.gradle | 39 ++ code/gradle/jmh.gradle | 17 + code/gradle/junit-jupiter.gradle | 72 +++ code/gradle/subprojects.gradle | 67 +++ code/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes code/gradle/wrapper/gradle-wrapper.properties | 5 + code/gradlew | 185 ++++++++ code/gradlew.bat | 89 ++++ code/hiding/Cake.java | 15 + code/hiding/ChocolateChip.java | 23 + code/hiding/ChocolateChip2.java | 21 + code/hiding/CreatePackageAccessObject.java | 12 + code/hiding/Dinner.java | 16 + code/hiding/FullQualification.java | 11 + code/hiding/IceCream.java | 19 + code/hiding/ImportedMyClass.java | 11 + code/hiding/LibTest.java | 17 + code/hiding/Lunch.java | 36 ++ code/hiding/OrganizedByAccess.java | 15 + code/hiding/Pie.java | 9 + code/hiding/QualifiedMyClass.java | 11 + code/hiding/SingleImport.java | 11 + code/hiding/cookie2/Cookie.java | 14 + code/hiding/dessert/Cookie.java | 13 + code/hiding/mypackage/MyClass.java | 9 + .../packageaccess/PublicConstructor.java | 9 + code/housekeeping/Apricot.java | 8 + code/housekeeping/ArrayClassObj.java | 22 + code/housekeeping/ArrayInit.java | 25 ++ code/housekeeping/ArrayNew.java | 20 + code/housekeeping/ArraysOfPrimitives.java | 23 + code/housekeeping/AutoboxingVarargs.java | 22 + code/housekeeping/BananaPeel.java | 15 + code/housekeeping/Burrito.java | 39 ++ code/housekeeping/Counter.java | 9 + code/housekeeping/DefaultConstructor.java | 12 + code/housekeeping/Demotion.java | 43 ++ code/housekeeping/DynamicArray.java | 21 + code/housekeeping/EnumOrder.java | 19 + code/housekeeping/ExplicitStatic.java | 41 ++ code/housekeeping/Flower.java | 46 ++ code/housekeeping/InitialValues.java | 44 ++ code/housekeeping/InitialValues2.java | 16 + code/housekeeping/Leaf.java | 23 + code/housekeeping/Measurement.java | 10 + code/housekeeping/MethodInit.java | 8 + code/housekeeping/MethodInit2.java | 10 + code/housekeeping/MethodInit3.java | 10 + code/housekeeping/Mugs.java | 47 ++ code/housekeeping/NewVarArgs.java | 30 ++ code/housekeeping/NoSynthesis.java | 17 + .../OptionalTrailingArguments.java | 23 + code/housekeeping/OrderOfInitialization.java | 40 ++ code/housekeeping/Overloading.java | 56 +++ code/housekeeping/OverloadingOrder.java | 22 + code/housekeeping/OverloadingVarargs.java | 37 ++ code/housekeeping/OverloadingVarargs2.java | 18 + code/housekeeping/OverloadingVarargs3.java | 21 + code/housekeeping/PassingThis.java | 31 ++ code/housekeeping/PrimitiveOverloading.java | 120 +++++ code/housekeeping/SimpleConstructor.java | 21 + code/housekeeping/SimpleConstructor2.java | 21 + code/housekeeping/SimpleEnumUse.java | 14 + code/housekeeping/Spiciness.java | 8 + code/housekeeping/Spoon.java | 10 + code/housekeeping/StaticInitialization.java | 73 ++++ code/housekeeping/TerminationCondition.java | 41 ++ code/housekeeping/VarArgs.java | 26 ++ code/housekeeping/VarargType.java | 30 ++ code/innerclasses/AnonymousConstructor.java | 34 ++ code/innerclasses/BigEgg.java | 33 ++ code/innerclasses/BigEgg2.java | 44 ++ code/innerclasses/Callbacks.java | 84 ++++ code/innerclasses/ClassInInterface.java | 21 + code/innerclasses/Contents.java | 7 + code/innerclasses/Destination.java | 7 + code/innerclasses/DotNew.java | 13 + code/innerclasses/DotThis.java | 24 + code/innerclasses/GreenhouseController.java | 54 +++ code/innerclasses/GreenhouseControls.java | 150 +++++++ code/innerclasses/InheritInner.java | 20 + code/innerclasses/LocalInnerClass.java | 67 +++ code/innerclasses/MultiImplementation.java | 25 ++ code/innerclasses/MultiNestingAccess.java | 28 ++ code/innerclasses/Parcel1.java | 33 ++ code/innerclasses/Parcel10.java | 31 ++ code/innerclasses/Parcel11.java | 40 ++ code/innerclasses/Parcel2.java | 41 ++ code/innerclasses/Parcel3.java | 25 ++ code/innerclasses/Parcel5.java | 23 + code/innerclasses/Parcel6.java | 28 ++ code/innerclasses/Parcel7.java | 19 + code/innerclasses/Parcel7b.java | 20 + code/innerclasses/Parcel8.java | 21 + code/innerclasses/Parcel9.java | 20 + code/innerclasses/Sequence.java | 48 ++ code/innerclasses/TestBed.java | 19 + code/innerclasses/TestParcel.java | 37 ++ code/innerclasses/Wrapping.java | 9 + code/innerclasses/controller/Controller.java | 24 + code/innerclasses/controller/Event.java | 23 + code/innerclasses/mui/MultiInterfaces.java | 32 ++ code/interfaces/AbstractAccess.java | 15 + code/interfaces/AbstractWithoutAbstracts.java | 14 + code/interfaces/AdaptedRandomDoubles.java | 35 ++ code/interfaces/Adventure.java | 41 ++ code/interfaces/AnImplementation.java | 22 + code/interfaces/AnInterface.java | 9 + code/interfaces/Applicator.java | 58 +++ code/interfaces/AttemptToUseBasic.java | 10 + code/interfaces/Basic.java | 8 + code/interfaces/Basic2.java | 10 + code/interfaces/Factories.java | 67 +++ code/interfaces/Games.java | 59 +++ code/interfaces/HorrorShow.java | 57 +++ code/interfaces/Implementation2.java | 26 ++ code/interfaces/ImplementingAnInterface.java | 14 + code/interfaces/Instantiable.java | 19 + code/interfaces/InterfaceCollision.java | 31 ++ code/interfaces/InterfaceWithDefault.java | 12 + code/interfaces/Jim.java | 28 ++ code/interfaces/MICollision.java | 60 +++ code/interfaces/Machine.java | 36 ++ code/interfaces/Months.java | 13 + code/interfaces/MultipleInheritance.java | 35 ++ code/interfaces/PureInterface.java | 11 + code/interfaces/RandVals.java | 15 + code/interfaces/RandomDoubles.java | 21 + code/interfaces/RandomStrings.java | 50 +++ code/interfaces/TestRandVals.java | 19 + code/interfaces/filters/BandPass.java | 17 + code/interfaces/filters/Filter.java | 14 + code/interfaces/filters/HighPass.java | 16 + code/interfaces/filters/LowPass.java | 16 + code/interfaces/filters/Waveform.java | 14 + .../interfaceprocessor/Applicator.java | 12 + .../interfaceprocessor/FilterProcessor.java | 40 ++ .../interfaceprocessor/Processor.java | 12 + .../interfaceprocessor/StringProcessor.java | 50 +++ code/interfaces/music4/Music4.java | 105 +++++ code/interfaces/music5/Music5.java | 74 ++++ .../interfaces/nesting/NestingInterfaces.java | 105 +++++ code/iostreams/BasicFileOutput.java | 26 ++ code/iostreams/BufferedInputFile.java | 23 + code/iostreams/FileOutputShortcut.java | 24 + code/iostreams/FormattedMemoryInput.java | 25 ++ code/iostreams/MemoryInput.java | 17 + code/iostreams/StoringAndRecoveringData.java | 42 ++ code/iostreams/TestEOF.java | 22 + code/iostreams/UsingRandomAccessFile.java | 65 +++ code/javadoc/Documentation1.java | 11 + code/javadoc/Documentation2.java | 9 + code/javadoc/Documentation3.java | 12 + code/javadoc/HelloDateDoc.java | 26 ++ code/lowlevel/AtomicEvenProducer.java | 21 + code/lowlevel/AtomicIntegerTest.java | 20 + code/lowlevel/AtomicSerialNumbers.java | 21 + code/lowlevel/Atomicity.java | 20 + code/lowlevel/AttemptLocking.java | 57 +++ code/lowlevel/CaptureUncaughtException.java | 56 +++ code/lowlevel/CircularSet.java | 29 ++ code/lowlevel/DelayQueueDemo.java | 99 +++++ code/lowlevel/EvenChecker.java | 41 ++ code/lowlevel/EvenProducer.java | 26 ++ code/lowlevel/ExceptionThread.java | 30 ++ code/lowlevel/IntGenerator.java | 15 + code/lowlevel/IntTestable.java | 15 + code/lowlevel/MutexEvenProducer.java | 30 ++ code/lowlevel/NaiveExceptionHandling.java | 32 ++ code/lowlevel/NotAtomic.java | 49 +++ code/lowlevel/NumberOfProcessors.java | 14 + code/lowlevel/PriorityBlockingQueueDemo.java | 139 ++++++ code/lowlevel/ReOrdering.java | 19 + code/lowlevel/SafeReturn.java | 20 + code/lowlevel/SerialNumberChecker.java | 32 ++ code/lowlevel/SerialNumberTest.java | 13 + code/lowlevel/SerialNumbers.java | 11 + code/lowlevel/SettingDefaultHandler.java | 19 + code/lowlevel/SwallowedException.java | 17 + code/lowlevel/SyncOnObject.java | 70 +++ code/lowlevel/SynchronizedComparison.java | 89 ++++ code/lowlevel/SynchronizedEvenProducer.java | 24 + code/lowlevel/SynchronizedSerialNumbers.java | 19 + code/lowlevel/TestAbort.java | 17 + code/lowlevel/ThreadSize.java | 31 ++ code/lowlevel/UnsafeReturn.java | 20 + code/lowlevel/WorkStealingPool.java | 41 ++ code/newio/AvailableCharSets.java | 43 ++ code/newio/BufferToText.java | 93 ++++ code/newio/ChannelCopy.java | 35 ++ code/newio/Endians.java | 28 ++ code/newio/FileLocking.java | 30 ++ code/newio/GetChannel.java | 53 +++ code/newio/GetData.java | 56 +++ code/newio/IntBufferDemo.java | 35 ++ code/newio/LargeMappedFiles.java | 31 ++ code/newio/LockingMappedFiles.java | 60 +++ code/newio/MappedIO.java | 145 ++++++ code/newio/TransferTo.java | 30 ++ code/newio/UsingBuffers.java | 35 ++ code/newio/ViewBuffers.java | 69 +++ code/objects/HelloDate.java | 12 + code/objects/ShowProperties.java | 39 ++ code/onjava/ArrayShow.java | 73 ++++ code/onjava/BasicSupplier.java | 31 ++ code/onjava/CollectionMethodDifferences.java | 117 +++++ code/onjava/ConvertTo.java | 105 +++++ code/onjava/Count.java | 220 ++++++++++ code/onjava/CountMap.java | 97 +++++ code/onjava/CountingIntegerList.java | 34 ++ code/onjava/Countries.java | 351 +++++++++++++++ code/onjava/Enums.java | 17 + code/onjava/FillMap.java | 38 ++ code/onjava/HTMLColors.java | 236 ++++++++++ code/onjava/MouseClick.java | 19 + code/onjava/Nap.java | 20 + code/onjava/Null.java | 6 + code/onjava/OSExecute.java | 37 ++ code/onjava/OSExecuteException.java | 12 + code/onjava/Operations.java | 17 + code/onjava/Pair.java | 19 + code/onjava/ProcessFiles.java | 48 ++ code/onjava/Rand.java | 248 +++++++++++ code/onjava/Range.java | 34 ++ code/onjava/Repeat.java | 12 + code/onjava/RmDir.java | 31 ++ code/onjava/Sets.java | 32 ++ code/onjava/Stack.java | 20 + code/onjava/Suppliers.java | 36 ++ code/onjava/TimedAbort.java | 30 ++ code/onjava/Timer.java | 19 + code/onjava/Tuple.java | 24 + code/onjava/Tuple2.java | 16 + code/onjava/Tuple3.java | 17 + code/onjava/Tuple4.java | 18 + code/onjava/Tuple5.java | 18 + code/onjava/TypeCounter.java | 41 ++ code/onjava/atunit/AtUnit.java | 177 ++++++++ code/onjava/atunit/ClassNameFinder.java | 180 ++++++++ code/onjava/atunit/Test.java | 11 + code/onjava/atunit/TestObjectCleanup.java | 11 + code/onjava/atunit/TestObjectCreate.java | 11 + code/onjava/atunit/TestProperty.java | 12 + code/operators/AllOps.java | 411 ++++++++++++++++++ code/operators/Assignment.java | 31 ++ code/operators/AutoInc.java | 27 ++ code/operators/BitManipulation.java | 98 +++++ code/operators/Bool.java | 42 ++ code/operators/Casting.java | 16 + code/operators/CastingNumbers.java | 23 + code/operators/EqualsMethod.java | 15 + code/operators/EqualsMethod2.java | 21 + code/operators/Equivalence.java | 17 + code/operators/Exponents.java | 21 + code/operators/Literals.java | 61 +++ code/operators/MathOps.java | 75 ++++ code/operators/Overflow.java | 18 + code/operators/PassObject.java | 27 ++ code/operators/Precedence.java | 18 + code/operators/RoundingNumbers.java | 26 ++ code/operators/ShortCircuit.java | 34 ++ code/operators/StringOperators.java | 24 + code/operators/TernaryIfElse.java | 28 ++ code/operators/URShift.java | 42 ++ code/operators/Underscores.java | 22 + code/patterns/BoxObserver.java | 94 ++++ code/patterns/CommandPattern.java | 19 + code/patterns/Facade.java | 24 + code/patterns/PaperScissorsRock.java | 135 ++++++ code/patterns/ProxyDemo.java | 51 +++ code/patterns/ShapeFactory1.java | 39 ++ code/patterns/ShapeFactory2.java | 54 +++ code/patterns/ShapeFactory3.java | 52 +++ code/patterns/SingletonPattern.java | 58 +++ code/patterns/StateDemo.java | 87 ++++ code/patterns/TemplateMethod.java | 44 ++ .../abstractfactory/GameEnvironment.java | 96 ++++ code/patterns/adapt/Adapter.java | 85 ++++ .../patterns/chain/ChainOfResponsibility.java | 90 ++++ code/patterns/doubledispatch/Aluminum.java | 18 + code/patterns/doubledispatch/Cardboard.java | 18 + .../doubledispatch/DoubleDispatch.java | 96 ++++ code/patterns/doubledispatch/Glass.java | 18 + code/patterns/doubledispatch/Paper.java | 18 + code/patterns/doubledispatch/TypedBin.java | 28 ++ .../doubledispatch/TypedBinMember.java | 14 + code/patterns/dynatrash/DynaTrash.java | 74 ++++ code/patterns/observer/ObservedFlower.java | 125 ++++++ code/patterns/recyclea/RecycleA.java | 127 ++++++ code/patterns/recycleb/RecycleB.java | 56 +++ code/patterns/recyclec/RecycleC.java | 84 ++++ code/patterns/shapes/BadShapeCreation.java | 12 + code/patterns/shapes/Circle.java | 7 + code/patterns/shapes/FactoryMethod.java | 9 + code/patterns/shapes/FactoryTest.java | 17 + code/patterns/shapes/Shape.java | 21 + code/patterns/shapes/Square.java | 7 + code/patterns/shapes/Triangle.java | 7 + code/patterns/state/StateMachineDemo.java | 80 ++++ code/patterns/strategy/StrategyPattern.java | 64 +++ code/patterns/strategy/StrategyPattern2.java | 43 ++ code/patterns/trash/Aluminum.java | 15 + code/patterns/trash/Cardboard.java | 15 + code/patterns/trash/Fillable.java | 10 + code/patterns/trash/FillableList.java | 17 + code/patterns/trash/Glass.java | 15 + code/patterns/trash/Paper.java | 15 + code/patterns/trash/ParseTrash.java | 91 ++++ code/patterns/trash/Trash.dat | 35 ++ code/patterns/trash/Trash.java | 92 ++++ code/patterns/trashvisitor/Aluminum.java | 16 + code/patterns/trashvisitor/Cardboard.java | 16 + code/patterns/trashvisitor/Glass.java | 16 + code/patterns/trashvisitor/Paper.java | 16 + code/patterns/trashvisitor/TrashVisitor.java | 127 ++++++ code/patterns/trashvisitor/Visitable.java | 12 + code/patterns/trashvisitor/Visitor.java | 14 + code/patterns/visitor/BeeAndFlowers.java | 122 ++++++ code/polymorphism/CovariantReturn.java | 38 ++ code/polymorphism/FieldAccess.java | 36 ++ code/polymorphism/Frog.java | 122 ++++++ code/polymorphism/PolyConstructors.java | 41 ++ code/polymorphism/PrivateOverride.java | 24 + code/polymorphism/PrivateOverride2.java | 22 + code/polymorphism/RTTI.java | 43 ++ code/polymorphism/ReferenceCounting.java | 71 +++ code/polymorphism/Sandwich.java | 54 +++ code/polymorphism/Shapes.java | 26 ++ code/polymorphism/StaticPolymorphism.java | 36 ++ code/polymorphism/Transmogrify.java | 43 ++ code/polymorphism/music/Instrument.java | 11 + code/polymorphism/music/Music.java | 21 + code/polymorphism/music/Music2.java | 46 ++ code/polymorphism/music/Note.java | 10 + code/polymorphism/music/Wind.java | 15 + code/polymorphism/music3/Music3.java | 108 +++++ code/polymorphism/shape/Circle.java | 16 + code/polymorphism/shape/RandomShapes.java | 26 ++ code/polymorphism/shape/Shape.java | 10 + code/polymorphism/shape/Square.java | 16 + code/polymorphism/shape/Triangle.java | 16 + code/references/AddingClone.java | 67 +++ code/references/Alias1.java | 27 ++ code/references/Alias2.java | 25 ++ code/references/CheckCloneable.java | 113 +++++ code/references/CloneArrayList.java | 38 ++ code/references/Compete.java | 89 ++++ code/references/CopyConstructor.java | 188 ++++++++ code/references/DepthReading.java | 29 ++ code/references/HorrorFlick.java | 35 ++ code/references/Immutable1.java | 34 ++ code/references/Immutable2.java | 71 +++ code/references/ImmutableInteger.java | 22 + code/references/ImmutableStrings.java | 25 ++ code/references/LocalCopy.java | 57 +++ code/references/MutableInteger.java | 34 ++ code/references/OceanReading.java | 48 ++ code/references/PassReferences.java | 19 + code/references/SimplerMutableInteger.java | 30 ++ code/references/Snake.java | 51 +++ code/references/Stringer.java | 22 + code/references/TemperatureReading.java | 33 ++ code/references/tests/DeepCopyTest.java | 28 ++ code/reuse/Bath.java | 61 +++ code/reuse/Beetle.java | 43 ++ code/reuse/BlankFinal.java | 29 ++ code/reuse/CADSystem.java | 116 +++++ code/reuse/Car.java | 43 ++ code/reuse/Cartoon.java | 31 ++ code/reuse/Chess.java | 33 ++ code/reuse/DerivedSpaceShip.java | 19 + code/reuse/Detergent.java | 48 ++ code/reuse/FinalArguments.java | 27 ++ code/reuse/FinalData.java | 57 +++ code/reuse/FinalOverridingIllusion.java | 56 +++ code/reuse/Hide.java | 41 ++ code/reuse/Jurassic.java | 26 ++ code/reuse/Lisa.java | 11 + code/reuse/Orc.java | 41 ++ code/reuse/PlaceSetting.java | 82 ++++ code/reuse/SpaceShipControls.java | 14 + code/reuse/SpaceShipDelegation.java | 40 ++ code/reuse/SprinklerSystem.java | 41 ++ code/reuse/Wind.java | 22 + code/serialization/APerson.java | 83 ++++ code/serialization/AStoreCADState.java | 120 +++++ code/serialization/Alien.java | 7 + code/serialization/Blip3.java | 75 ++++ code/serialization/Blips.java | 80 ++++ code/serialization/FreezeAlien.java | 19 + code/serialization/Logon.java | 62 +++ code/serialization/MyWorld.java | 100 +++++ code/serialization/People.java | 28 ++ code/serialization/RecoverCADState.java | 42 ++ code/serialization/SerialCtl.java | 60 +++ code/serialization/Worm.java | 102 +++++ code/serialization/xfiles/ThawAlien.java | 22 + code/settings.gradle | 13 + code/standardio/ChangeSystemOut.java | 17 + code/standardio/Echo.java | 20 + code/standardio/OSExecuteDemo.java | 16 + code/standardio/Redirecting.java | 31 ++ code/staticchecking/DogsAndRobots.cpp | 33 ++ code/staticchecking/DogsAndRobots.py | 26 ++ code/staticchecking/NoBasePetSpeak.py | 35 ++ code/staticchecking/PetSpeak.py | 28 ++ code/staticchecking/dogsandrobots.go | 27 ++ code/staticchecking/dr/DogsAndRobots.java | 42 ++ .../drc/DogAndRobotCollections.java | 58 +++ code/staticchecking/latent/Latent.java | 60 +++ code/staticchecking/petspeak.go | 51 +++ code/staticchecking/petspeak/PetSpeak.java | 36 ++ code/streams/ArrayStreams.java | 31 ++ code/streams/Bubble.java | 18 + code/streams/Bubbles.java | 20 + code/streams/Cheese.dat | 6 + code/streams/CollectionToStream.java | 39 ++ code/streams/CreatingOptionals.java | 37 ++ code/streams/Duplicator.java | 18 + code/streams/Fibonacci.java | 34 ++ code/streams/FileToWords.java | 17 + code/streams/FileToWordsBuilder.java | 31 ++ code/streams/FileToWordsRegexp.java | 39 ++ code/streams/FileToWordsTest.java | 23 + code/streams/FlatMap.java | 25 ++ code/streams/ForEach.java | 28 ++ code/streams/FunctionMap.java | 60 +++ code/streams/FunctionMap2.java | 32 ++ code/streams/FunctionMap3.java | 28 ++ code/streams/Generator.java | 25 ++ code/streams/ImperativeRandoms.java | 21 + code/streams/Informational.java | 27 ++ code/streams/LastElement.java | 24 + code/streams/Looping.java | 20 + code/streams/Machine2.java | 23 + code/streams/MapCollector.java | 48 ++ code/streams/Matching.java | 38 ++ code/streams/NumericStreamInfo.java | 24 + code/streams/OptionalBasics.java | 23 + code/streams/OptionalFilter.java | 72 +++ code/streams/OptionalFlatMap.java | 73 ++++ code/streams/OptionalMap.java | 74 ++++ code/streams/Optionals.java | 63 +++ code/streams/OptionalsFromEmptyStreams.java | 31 ++ code/streams/Peeking.java | 22 + code/streams/Prime.java | 31 ++ code/streams/RandInts.java | 15 + code/streams/RandomGenerators.java | 86 ++++ code/streams/RandomWords.java | 41 ++ code/streams/Randoms.java | 25 ++ code/streams/Ranges.java | 29 ++ code/streams/Reduce.java | 44 ++ code/streams/SelectElement.java | 24 + code/streams/Signal.java | 29 ++ code/streams/SortedComparator.java | 20 + code/streams/SpecialCollector.java | 24 + code/streams/StreamOf.java | 28 ++ code/streams/StreamOfOptionals.java | 37 ++ code/streams/StreamOfRandoms.java | 20 + code/streams/StreamOfStreams.java | 19 + code/streams/TreeSetOfWords.java | 31 ++ code/strings/ArrayListDisplay.java | 22 + code/strings/BetterRead.java | 37 ++ code/strings/Concatenation.java | 15 + code/strings/Conversion.java | 113 +++++ code/strings/DatabaseException.java | 22 + code/strings/Finding.java | 27 ++ code/strings/Groups.java | 40 ++ code/strings/Hex.java | 44 ++ code/strings/Immutable.java | 22 + code/strings/InfiniteRecursion.java | 22 + code/strings/IntegerMatch.java | 19 + code/strings/JGrep.java | 36 ++ code/strings/ReFlags.java | 23 + code/strings/ReceiptBuilder.java | 48 ++ code/strings/Replacing.java | 21 + code/strings/ReplacingStringTokenizer.java | 26 ++ code/strings/Resetting.java | 23 + code/strings/Rudolph.java | 21 + code/strings/ScannerDelimiter.java | 21 + code/strings/SimpleFormat.java | 22 + code/strings/SimpleRead.java | 43 ++ code/strings/SplitDemo.java | 22 + code/strings/Splitting.java | 32 ++ code/strings/StartEnd.java | 82 ++++ code/strings/TestRegularExpression.java | 44 ++ code/strings/TheReplacements.java | 57 +++ code/strings/ThreatAnalyzer.java | 36 ++ code/strings/Turtle.java | 40 ++ code/strings/UsingStringBuilder.java | 37 ++ code/strings/WhitherStringBuilder.java | 21 + code/typeinfo/AnonymousImplementation.java | 50 +++ code/typeinfo/BoundedClassReferences.java | 13 + code/typeinfo/ClassCasts.java | 16 + code/typeinfo/ClassInitialization.java | 57 +++ code/typeinfo/DynamicSupplier.java | 42 ++ code/typeinfo/FamilyVsExactType.java | 62 +++ code/typeinfo/GenericClassReferences.java | 14 + code/typeinfo/HiddenImplementation.java | 44 ++ code/typeinfo/InnerImplementation.java | 49 +++ code/typeinfo/InterfaceViolation.java | 27 ++ code/typeinfo/ModifyingPrivateFields.java | 49 +++ code/typeinfo/NullRobot.java | 63 +++ code/typeinfo/Operation.java | 15 + code/typeinfo/Person.java | 49 +++ code/typeinfo/PetCount.java | 65 +++ code/typeinfo/PetCount2.java | 18 + code/typeinfo/PetCount3.java | 53 +++ code/typeinfo/PetCount4.java | 26 ++ code/typeinfo/Position.java | 51 +++ code/typeinfo/RegisteredFactories.java | 95 ++++ code/typeinfo/Robot.java | 22 + code/typeinfo/SelectingMethods.java | 69 +++ code/typeinfo/Shapes.java | 39 ++ code/typeinfo/ShowMethods.java | 71 +++ code/typeinfo/SimpleDynamicProxy.java | 53 +++ code/typeinfo/SimpleProxyDemo.java | 57 +++ code/typeinfo/SnowRemovalRobot.java | 42 ++ code/typeinfo/Staff.java | 63 +++ code/typeinfo/SweetShop.java | 42 ++ code/typeinfo/WildcardClassReferences.java | 11 + code/typeinfo/interfacea/A.java | 9 + code/typeinfo/packageaccess/HiddenC.java | 29 ++ code/typeinfo/pets/Cat.java | 10 + code/typeinfo/pets/Cymric.java | 10 + code/typeinfo/pets/Dog.java | 10 + code/typeinfo/pets/EgyptianMau.java | 10 + code/typeinfo/pets/ForNameCreator.java | 37 ++ code/typeinfo/pets/Hamster.java | 10 + code/typeinfo/pets/Individual.java | 46 ++ code/typeinfo/pets/LiteralPetCreator.java | 39 ++ code/typeinfo/pets/Manx.java | 10 + code/typeinfo/pets/Mouse.java | 10 + code/typeinfo/pets/Mutt.java | 10 + code/typeinfo/pets/Person.java | 9 + code/typeinfo/pets/Pet.java | 10 + code/typeinfo/pets/PetCreator.java | 28 ++ code/typeinfo/pets/Pets.java | 30 ++ code/typeinfo/pets/Pug.java | 10 + code/typeinfo/pets/Rat.java | 10 + code/typeinfo/pets/Rodent.java | 10 + code/typeinfo/toys/GenericToyTest.java | 23 + code/typeinfo/toys/ToyTest.java | 78 ++++ code/validating/Assert1.java | 19 + code/validating/Assert2.java | 20 + code/validating/BadMicroBenchmark.java | 29 ++ code/validating/BadMicroBenchmark2.java | 35 ++ code/validating/CircularQueue.java | 91 ++++ code/validating/CircularQueueException.java | 12 + code/validating/CountedList.java | 16 + code/validating/GuavaAssertions.java | 49 +++ code/validating/GuavaPreconditions.java | 125 ++++++ code/validating/Inverter1.java | 9 + code/validating/Inverter2.java | 19 + code/validating/Inverter3.java | 21 + code/validating/Inverter4.java | 26 ++ code/validating/LoaderAssertions.java | 28 ++ code/validating/NonNullConstruction.java | 18 + code/validating/SLF4JLevels.java | 29 ++ code/validating/SLF4JLogging.java | 17 + code/validating/SimpleDebugging.java | 40 ++ code/validating/StringInverter.java | 9 + code/validating/jmh/JMH1.java | 31 ++ code/validating/jmh/JMH2.java | 44 ++ code/validating/jmh/JMH3.java | 48 ++ code/validating/logback.xml | 15 + code/validating/tests/CircularQueueTest.java | 150 +++++++ code/validating/tests/CountedListTest.java | 101 +++++ .../tests/DynamicStringInverterTests.java | 122 ++++++ .../validating/tests/StringInverterTests.java | 65 +++ 1051 files changed, 40784 insertions(+) create mode 100644 code/.gitattributes create mode 100644 code/.gitignore create mode 100644 code/.travisXX.yml create mode 100644 code/CI.txt create mode 100644 code/Copyright.txt create mode 100644 code/README.md create mode 100644 code/annotations/AUComposition.java create mode 100644 code/annotations/AUExternalTest.java create mode 100644 code/annotations/AtUnitExample1.java create mode 100644 code/annotations/AtUnitExample2.java create mode 100644 code/annotations/AtUnitExample3.java create mode 100644 code/annotations/AtUnitExample4.java create mode 100644 code/annotations/AtUnitExample5.java create mode 100644 code/annotations/DemoProcessFiles.java create mode 100644 code/annotations/HashSetTest.java create mode 100644 code/annotations/PasswordUtils.java create mode 100644 code/annotations/SimulatingNull.java create mode 100644 code/annotations/StackL.java create mode 100644 code/annotations/StackLStringTst.java create mode 100644 code/annotations/Testable.java create mode 100644 code/annotations/UseCase.java create mode 100644 code/annotations/UseCaseTracker.java create mode 100644 code/annotations/database/Constraints.java create mode 100644 code/annotations/database/DBTable.java create mode 100644 code/annotations/database/Member.java create mode 100644 code/annotations/database/SQLInteger.java create mode 100644 code/annotations/database/SQLString.java create mode 100644 code/annotations/database/TableCreator.java create mode 100644 code/annotations/database/Uniqueness.java create mode 100644 code/annotations/ifx/ExtractInterface.java create mode 100644 code/annotations/ifx/IfaceExtractorProcessor.java create mode 100644 code/annotations/ifx/Multiplier.java create mode 100644 code/annotations/simplest/Simple.java create mode 100644 code/annotations/simplest/SimpleProcessor.java create mode 100644 code/annotations/simplest/SimpleTest.java create mode 100644 code/appveyorXX.yml create mode 100644 code/arrays/AlphabeticSearch.java create mode 100644 code/arrays/ArrayCopying.java create mode 100644 code/arrays/ArrayOfGenericType.java create mode 100644 code/arrays/ArrayOfGenerics.java create mode 100644 code/arrays/ArrayOptions.java create mode 100644 code/arrays/ArraySearching.java create mode 100644 code/arrays/AssemblingMultidimensionalArrays.java create mode 100644 code/arrays/AutoboxingArrays.java create mode 100644 code/arrays/CollectionComparison.java create mode 100644 code/arrays/CompType.java create mode 100644 code/arrays/ComparatorTest.java create mode 100644 code/arrays/ComparingArrays.java create mode 100644 code/arrays/CountUpward.java create mode 100644 code/arrays/FillingArrays.java create mode 100644 code/arrays/IceCreamFlavors.java create mode 100644 code/arrays/ModifyExisting.java create mode 100644 code/arrays/MultiDimWrapperArray.java create mode 100644 code/arrays/MultidimensionalObjectArrays.java create mode 100644 code/arrays/MultidimensionalPrimitiveArray.java create mode 100644 code/arrays/ParallelPrefix1.java create mode 100644 code/arrays/ParallelPrefix2.java create mode 100644 code/arrays/ParallelPrefix3.java create mode 100644 code/arrays/ParallelSetAll.java create mode 100644 code/arrays/ParameterizedArrayType.java create mode 100644 code/arrays/PythonLists.py create mode 100644 code/arrays/RaggedArray.java create mode 100644 code/arrays/Reverse.java create mode 100644 code/arrays/SimpleSetAll.java create mode 100644 code/arrays/StreamFromArray.java create mode 100644 code/arrays/StringSorting.java create mode 100644 code/arrays/TestConvertTo.java create mode 100644 code/arrays/TestCount.java create mode 100644 code/arrays/TestRand.java create mode 100644 code/arrays/ThreeDWithNew.java create mode 100644 code/arrays/jmh/ParallelSort.java create mode 100644 code/build.gradle create mode 100644 code/checkstyle.xml create mode 100644 code/chkstyle.bat create mode 100644 code/collections/AdapterMethodIdiom.java create mode 100644 code/collections/AddingGroups.java create mode 100644 code/collections/ApplesAndOrangesWithGenerics.java create mode 100644 code/collections/ApplesAndOrangesWithoutGenerics.java create mode 100644 code/collections/ArrayIsNotIterable.java create mode 100644 code/collections/AsListInference.java create mode 100644 code/collections/CollectionDifferences.java create mode 100644 code/collections/CollectionSequence.java create mode 100644 code/collections/CrossCollectionIteration.java create mode 100644 code/collections/CrossCollectionIteration2.java create mode 100644 code/collections/EnvironmentVariables.java create mode 100644 code/collections/ForInCollections.java create mode 100644 code/collections/GenericsAndUpcasting.java create mode 100644 code/collections/InterfaceVsIterator.java create mode 100644 code/collections/IterableClass.java create mode 100644 code/collections/LinkedListFeatures.java create mode 100644 code/collections/ListFeatures.java create mode 100644 code/collections/ListIteration.java create mode 100644 code/collections/MapOfList.java create mode 100644 code/collections/ModifyingArraysAsList.java create mode 100644 code/collections/MultiIterableClass.java create mode 100644 code/collections/NonCollectionSequence.java create mode 100644 code/collections/PetMap.java create mode 100644 code/collections/PrintingCollections.java create mode 100644 code/collections/PriorityQueueDemo.java create mode 100644 code/collections/QueueDemo.java create mode 100644 code/collections/SetOfInteger.java create mode 100644 code/collections/SetOfString.java create mode 100644 code/collections/SetOperations.java create mode 100644 code/collections/SimpleCollection.java create mode 100644 code/collections/SimpleIteration.java create mode 100644 code/collections/SortedSetOfString.java create mode 100644 code/collections/StackCollision.java create mode 100644 code/collections/StackTest.java create mode 100644 code/collections/StackTest2.java create mode 100644 code/collections/Statistics.java create mode 100644 code/collections/UniqueWords.java create mode 100644 code/collections/UniqueWordsAlphabetic.java create mode 100644 code/collectiontopics/AssociativeArray.java create mode 100644 code/collectiontopics/Bits.java create mode 100644 code/collectiontopics/CanonicalMapping.java create mode 100644 code/collectiontopics/CollectionMethods.java create mode 100644 code/collectiontopics/Enumerations.java create mode 100644 code/collectiontopics/FailFast.java create mode 100644 code/collectiontopics/FillMapTest.java create mode 100644 code/collectiontopics/FillingLists.java create mode 100644 code/collectiontopics/FunctionalMap.java create mode 100644 code/collectiontopics/HTMLColorTest.java create mode 100644 code/collectiontopics/LinkedHashMapDemo.java create mode 100644 code/collectiontopics/ListOps.java create mode 100644 code/collectiontopics/ListSortSearch.java create mode 100644 code/collectiontopics/MapOps.java create mode 100644 code/collectiontopics/NavMap.java create mode 100644 code/collectiontopics/QueueBehavior.java create mode 100644 code/collectiontopics/ReadOnly.java create mode 100644 code/collectiontopics/References.java create mode 100644 code/collectiontopics/SetOrder.java create mode 100644 code/collectiontopics/SimpleDeques.java create mode 100644 code/collectiontopics/SortedMapDemo.java create mode 100644 code/collectiontopics/SortedSetDemo.java create mode 100644 code/collectiontopics/Stacks.java create mode 100644 code/collectiontopics/StreamFillMaps.java create mode 100644 code/collectiontopics/SuppliersCollectionTest.java create mode 100644 code/collectiontopics/Synchronization.java create mode 100644 code/collectiontopics/ToDoList.java create mode 100644 code/collectiontopics/TypesForSets.java create mode 100644 code/collectiontopics/Unsupported.java create mode 100644 code/collectiontopics/Utilities.java create mode 100644 code/com/mindviewinc/simple/List.java create mode 100644 code/com/mindviewinc/simple/Vector.java create mode 100644 code/compression/GZIPcompress.java create mode 100644 code/compression/ZipCompress.java create mode 100644 code/concurrent/Baked.java create mode 100644 code/concurrent/Batter.java create mode 100644 code/concurrent/Breakable.java create mode 100644 code/concurrent/CachedThreadPool.java create mode 100644 code/concurrent/CachedThreadPool2.java create mode 100644 code/concurrent/CachedThreadPool3.java create mode 100644 code/concurrent/CatchCompletableExceptions.java create mode 100644 code/concurrent/CollectionIntoStream.java create mode 100644 code/concurrent/CompletableApply.java create mode 100644 code/concurrent/CompletableApplyAsync.java create mode 100644 code/concurrent/CompletableApplyChained.java create mode 100644 code/concurrent/CompletableExceptions.java create mode 100644 code/concurrent/CompletableOperations.java create mode 100644 code/concurrent/CompletablePizza.java create mode 100644 code/concurrent/CompletableUtilities.java create mode 100644 code/concurrent/CompletedMachina.java create mode 100644 code/concurrent/CountingStream.java create mode 100644 code/concurrent/CountingTask.java create mode 100644 code/concurrent/DiningPhilosophers.java create mode 100644 code/concurrent/DualCompletableOperations.java create mode 100644 code/concurrent/FrostedCake.java create mode 100644 code/concurrent/Futures.java create mode 100644 code/concurrent/GuardedIDField.java create mode 100644 code/concurrent/HasID.java create mode 100644 code/concurrent/IDChecker.java create mode 100644 code/concurrent/InterferingTask.java create mode 100644 code/concurrent/LambdasAndMethodReferences.java create mode 100644 code/concurrent/Machina.java create mode 100644 code/concurrent/MoreTasksAfterShutdown.java create mode 100644 code/concurrent/NapTask.java create mode 100644 code/concurrent/OnePizza.java create mode 100644 code/concurrent/ParallelPrime.java create mode 100644 code/concurrent/ParallelStreamPuzzle.java create mode 100644 code/concurrent/ParallelStreamPuzzle2.java create mode 100644 code/concurrent/ParallelStreamPuzzle3.java create mode 100644 code/concurrent/Philosopher.java create mode 100644 code/concurrent/Pizza.java create mode 100644 code/concurrent/PizzaParallelSteps.java create mode 100644 code/concurrent/PizzaStreams.java create mode 100644 code/concurrent/QuittableTask.java create mode 100644 code/concurrent/QuittingCompletable.java create mode 100644 code/concurrent/QuittingTasks.java create mode 100644 code/concurrent/SharedConstructorArgument.java create mode 100644 code/concurrent/SingleThreadExecutor.java create mode 100644 code/concurrent/SingleThreadExecutor2.java create mode 100644 code/concurrent/SingleThreadExecutor3.java create mode 100644 code/concurrent/StaticIDField.java create mode 100644 code/concurrent/StickHolder.java create mode 100644 code/concurrent/StreamExceptions.java create mode 100644 code/concurrent/Summing.java create mode 100644 code/concurrent/Summing2.java create mode 100644 code/concurrent/Summing3.java create mode 100644 code/concurrent/Summing4.java create mode 100644 code/concurrent/SynchronizedConstructor.java create mode 100644 code/concurrent/SynchronizedFactory.java create mode 100644 code/concurrent/TestStaticIDField.java create mode 100644 code/concurrent/ThrowsChecked.java create mode 100644 code/concurrent/Workable.java create mode 100644 code/control/BreakAndContinue.java create mode 100644 code/control/CommaOperator.java create mode 100644 code/control/ForInFloat.java create mode 100644 code/control/ForInInt.java create mode 100644 code/control/ForInString.java create mode 100644 code/control/IfElse.java create mode 100644 code/control/LabeledFor.java create mode 100644 code/control/LabeledWhile.java create mode 100644 code/control/ListCharacters.java create mode 100644 code/control/RandomBounds.java create mode 100644 code/control/StringSwitch.java create mode 100644 code/control/TestWithReturn.java create mode 100644 code/control/TrueFalse.java create mode 100644 code/control/VowelsAndConsonants.java create mode 100644 code/control/WhileTest.java create mode 100644 code/enums/AlarmPoints.java create mode 100644 code/enums/BigEnumSet.java create mode 100644 code/enums/Burrito2.java create mode 100644 code/enums/CarWash.java create mode 100644 code/enums/Competitor.java create mode 100644 code/enums/ConstantSpecificMethod.java create mode 100644 code/enums/EnumClass.java create mode 100644 code/enums/EnumMaps.java create mode 100644 code/enums/EnumSets.java create mode 100644 code/enums/Input.java create mode 100644 code/enums/NonEnum.java create mode 100644 code/enums/NotClasses.java create mode 100644 code/enums/Outcome.java create mode 100644 code/enums/OverrideConstantSpecific.java create mode 100644 code/enums/OzWitch.java create mode 100644 code/enums/PostOffice.java create mode 100644 code/enums/RandomTest.java create mode 100644 code/enums/Reflection.java create mode 100644 code/enums/RoShamBo.java create mode 100644 code/enums/RoShamBo1.java create mode 100644 code/enums/RoShamBo2.java create mode 100644 code/enums/RoShamBo3.java create mode 100644 code/enums/RoShamBo4.java create mode 100644 code/enums/RoShamBo5.java create mode 100644 code/enums/RoShamBo6.java create mode 100644 code/enums/SecurityCategory.java create mode 100644 code/enums/SpaceShip.java create mode 100644 code/enums/SpicinessEnum.java create mode 100644 code/enums/TrafficLight.java create mode 100644 code/enums/UpcastEnum.java create mode 100644 code/enums/VendingMachine.java create mode 100644 code/enums/VendingMachineInput.txt create mode 100644 code/enums/cartoons/EnumImplementation.java create mode 100644 code/enums/menu/Course.java create mode 100644 code/enums/menu/Food.java create mode 100644 code/enums/menu/Meal.java create mode 100644 code/enums/menu/Meal2.java create mode 100644 code/enums/menu/TypeOfFood.java create mode 100644 code/equalshashcode/ComposedEquality.java create mode 100644 code/equalshashcode/CountedString.java create mode 100644 code/equalshashcode/DefaultComparison.java create mode 100644 code/equalshashcode/Equality.java create mode 100644 code/equalshashcode/EqualityFactory.java create mode 100644 code/equalshashcode/Groundhog.java create mode 100644 code/equalshashcode/Groundhog2.java create mode 100644 code/equalshashcode/IndividualTest.java create mode 100644 code/equalshashcode/MapEntry.java create mode 100644 code/equalshashcode/Prediction.java create mode 100644 code/equalshashcode/SimpleHashMap.java create mode 100644 code/equalshashcode/SlowMap.java create mode 100644 code/equalshashcode/SpringDetector.java create mode 100644 code/equalshashcode/SpringDetector2.java create mode 100644 code/equalshashcode/StringHashCode.java create mode 100644 code/equalshashcode/SubtypeEquality.java create mode 100644 code/equalshashcode/SubtypeEquality2.java create mode 100644 code/equalshashcode/SuccinctEquality.java create mode 100644 code/exceptions/AlwaysFinally.java create mode 100644 code/exceptions/AutoCloseableDetails.java create mode 100644 code/exceptions/BodyException.java create mode 100644 code/exceptions/Cleanup.java create mode 100644 code/exceptions/CleanupIdiom.java create mode 100644 code/exceptions/CloseExceptions.java create mode 100644 code/exceptions/ConstructorException.java create mode 100644 code/exceptions/DynamicFields.java create mode 100644 code/exceptions/ExceptionMethods.java create mode 100644 code/exceptions/ExceptionSilencer.java create mode 100644 code/exceptions/ExtraFeatures.java create mode 100644 code/exceptions/FinallyWorks.java create mode 100644 code/exceptions/FullConstructors.java create mode 100644 code/exceptions/Human.java create mode 100644 code/exceptions/InheritingExceptions.java create mode 100644 code/exceptions/InputFile.java create mode 100644 code/exceptions/InputFile2.java create mode 100644 code/exceptions/LoggingExceptions.java create mode 100644 code/exceptions/LoggingExceptions2.java create mode 100644 code/exceptions/LostMessage.java create mode 100644 code/exceptions/MainException.java create mode 100644 code/exceptions/MessyExceptions.java create mode 100644 code/exceptions/MultiCatch.java create mode 100644 code/exceptions/MultiCatch2.java create mode 100644 code/exceptions/MultipleReturns.java create mode 100644 code/exceptions/NeverCaught.java create mode 100644 code/exceptions/OnOffException1.java create mode 100644 code/exceptions/OnOffException2.java create mode 100644 code/exceptions/OnOffSwitch.java create mode 100644 code/exceptions/PreciseRethrow.java create mode 100644 code/exceptions/RethrowNew.java create mode 100644 code/exceptions/Rethrowing.java create mode 100644 code/exceptions/SameHandler.java create mode 100644 code/exceptions/StormyInning.java create mode 100644 code/exceptions/StreamsAreAutoCloseable.java create mode 100644 code/exceptions/Switch.java create mode 100644 code/exceptions/TryAnything.java create mode 100644 code/exceptions/TryWithResources.java create mode 100644 code/exceptions/TurnOffChecking.java create mode 100644 code/exceptions/WhoCalled.java create mode 100644 code/exceptions/WithFinally.java create mode 100644 code/files/AddAndSubtractPaths.java create mode 100644 code/files/Directories.java create mode 100644 code/files/FileSystemDemo.java create mode 100644 code/files/Find.java create mode 100644 code/files/ListOfLines.java create mode 100644 code/files/PartsOfPaths.java create mode 100644 code/files/PathAnalysis.java create mode 100644 code/files/PathInfo.java create mode 100644 code/files/PathWatcher.java create mode 100644 code/files/ReadLineStream.java create mode 100644 code/files/StreamInAndOut.java create mode 100644 code/files/TreeWatcher.java create mode 100644 code/files/Writing.java create mode 100644 code/functional/AnonymousClosure.java create mode 100644 code/functional/BiConsumerPermutations.java create mode 100644 code/functional/ClassFunctionals.java create mode 100644 code/functional/Closure1.java create mode 100644 code/functional/Closure2.java create mode 100644 code/functional/Closure3.java create mode 100644 code/functional/Closure4.java create mode 100644 code/functional/Closure5.java create mode 100644 code/functional/Closure6.java create mode 100644 code/functional/Closure7.java create mode 100644 code/functional/Closure8.java create mode 100644 code/functional/Closure9.java create mode 100644 code/functional/ConsumeFunction.java create mode 100644 code/functional/CtorReference.java create mode 100644 code/functional/CurriedIntAdd.java create mode 100644 code/functional/Curry3Args.java create mode 100644 code/functional/CurryingAndPartials.java create mode 100644 code/functional/FunctionComposition.java create mode 100644 code/functional/FunctionVariants.java create mode 100644 code/functional/FunctionWithWrapped.java create mode 100644 code/functional/FunctionalAnnotation.java create mode 100644 code/functional/IntCall.java create mode 100644 code/functional/LambdaExpressions.java create mode 100644 code/functional/MethodConversion.java create mode 100644 code/functional/MethodReferences.java create mode 100644 code/functional/MultiUnbound.java create mode 100644 code/functional/PredicateComposition.java create mode 100644 code/functional/ProduceFunction.java create mode 100644 code/functional/RecursiveFactorial.java create mode 100644 code/functional/RecursiveFibonacci.java create mode 100644 code/functional/RunnableMethodReference.java create mode 100644 code/functional/SharedStorage.java create mode 100644 code/functional/Strategize.java create mode 100644 code/functional/TransformFunction.java create mode 100644 code/functional/TriFunction.java create mode 100644 code/functional/TriFunctionTest.java create mode 100644 code/functional/UnboundMethodReference.java create mode 100644 code/generics/Amphibian.java create mode 100644 code/generics/Apply.java create mode 100644 code/generics/ApplyFunctional.java create mode 100644 code/generics/ApplyTest.java create mode 100644 code/generics/ArrayMaker.java create mode 100644 code/generics/ArrayOfGeneric.java create mode 100644 code/generics/ArrayOfGenericReference.java create mode 100644 code/generics/BankTeller.java create mode 100644 code/generics/BasicBounds.java create mode 100644 code/generics/BasicHolder.java create mode 100644 code/generics/BasicSupplierDemo.java create mode 100644 code/generics/ByteSet.java create mode 100644 code/generics/CRGWithBasicHolder.java create mode 100644 code/generics/CaptureConversion.java create mode 100644 code/generics/CheckedList.java create mode 100644 code/generics/ClassCasting.java create mode 100644 code/generics/ClassTypeCapture.java create mode 100644 code/generics/ComparablePet.java create mode 100644 code/generics/CompilerIntelligence.java create mode 100644 code/generics/CountedObject.java create mode 100644 code/generics/CovariantArrays.java create mode 100644 code/generics/CovariantReturnTypes.java create mode 100644 code/generics/CreatorGeneric.java create mode 100644 code/generics/CuriouslyRecurringGeneric.java create mode 100644 code/generics/Diamond.java create mode 100644 code/generics/DogsAndRobotMethodReferences.java create mode 100644 code/generics/DogsAndRobots.cpp create mode 100644 code/generics/DogsAndRobots.java create mode 100644 code/generics/DogsAndRobots.py create mode 100644 code/generics/DynamicProxyMixin.java create mode 100644 code/generics/EpicBattle.java create mode 100644 code/generics/Erased.java create mode 100644 code/generics/ErasedTypeEquivalence.java create mode 100644 code/generics/ErasureAndInheritance.java create mode 100644 code/generics/FactoryConstraint.java create mode 100644 code/generics/Fibonacci.java create mode 100644 code/generics/FilledList.java create mode 100644 code/generics/GenericArray.java create mode 100644 code/generics/GenericArray2.java create mode 100644 code/generics/GenericArrayWithTypeToken.java create mode 100644 code/generics/GenericCast.java create mode 100644 code/generics/GenericHolder.java create mode 100644 code/generics/GenericHolder2.java create mode 100644 code/generics/GenericMethods.java create mode 100644 code/generics/GenericReading.java create mode 100644 code/generics/GenericVarargs.java create mode 100644 code/generics/GenericsAndCovariance.java create mode 100644 code/generics/GenericsAndReturnTypes.java create mode 100644 code/generics/HasF.java create mode 100644 code/generics/HijackedInterface.java create mode 100644 code/generics/Holder.java create mode 100644 code/generics/Holder1.java create mode 100644 code/generics/InheritBounds.java create mode 100644 code/generics/InstantiateGenericType.cpp create mode 100644 code/generics/InstantiateGenericType.java create mode 100644 code/generics/IterableFibonacci.java create mode 100644 code/generics/LatentReflection.java create mode 100644 code/generics/LinkedStack.java create mode 100644 code/generics/ListMaker.java create mode 100644 code/generics/ListOfGenerics.java create mode 100644 code/generics/ListOfInt.java create mode 100644 code/generics/LostInformation.java create mode 100644 code/generics/Manipulation.java create mode 100644 code/generics/Manipulator2.java create mode 100644 code/generics/Manipulator3.java create mode 100644 code/generics/Mixins.cpp create mode 100644 code/generics/Mixins.java create mode 100644 code/generics/MultipleInterfaceVariants.java create mode 100644 code/generics/NeedCasting.java create mode 100644 code/generics/NonCovariantGenerics.java create mode 100644 code/generics/NotSelfBounded.java create mode 100644 code/generics/ObjectHolder.java create mode 100644 code/generics/OrdinaryArguments.java create mode 100644 code/generics/Performs.java create mode 100644 code/generics/PlainGenericInheritance.java create mode 100644 code/generics/PrimitiveGenericTest.java create mode 100644 code/generics/RandomList.java create mode 100644 code/generics/RestrictedComparablePets.java create mode 100644 code/generics/ReturnGenericType.java create mode 100644 code/generics/SelfBounding.java create mode 100644 code/generics/SelfBoundingAndCovariantArguments.java create mode 100644 code/generics/SelfBoundingMethods.java create mode 100644 code/generics/Shape.java create mode 100644 code/generics/SimpleDogsAndRobots.java create mode 100644 code/generics/SimpleHolder.java create mode 100644 code/generics/SimpleQueue.java create mode 100644 code/generics/Square.java create mode 100644 code/generics/Store.java create mode 100644 code/generics/SuperTypeWildcards.java create mode 100644 code/generics/Templates.cpp create mode 100644 code/generics/ThrowGenericException.java create mode 100644 code/generics/TupleList.java create mode 100644 code/generics/TupleTest.java create mode 100644 code/generics/TupleTest2.java create mode 100644 code/generics/UnboundedWildcards1.java create mode 100644 code/generics/UnboundedWildcards2.java create mode 100644 code/generics/Unconstrained.java create mode 100644 code/generics/UseList.java create mode 100644 code/generics/UseList2.java create mode 100644 code/generics/Vehicle.java create mode 100644 code/generics/WatercolorSets.java create mode 100644 code/generics/Wildcards.java create mode 100644 code/generics/coffee/Americano.java create mode 100644 code/generics/coffee/Breve.java create mode 100644 code/generics/coffee/Cappuccino.java create mode 100644 code/generics/coffee/Coffee.java create mode 100644 code/generics/coffee/CoffeeSupplier.java create mode 100644 code/generics/coffee/Latte.java create mode 100644 code/generics/coffee/Mocha.java create mode 100644 code/generics/decorator/Decoration.java create mode 100644 code/generics/dogsandrobots.go create mode 100644 code/generics/watercolors/Watercolors.java create mode 100644 code/gradle.properties create mode 100644 code/gradle/checkstyle.gradle create mode 100644 code/gradle/findbugs.gradle create mode 100644 code/gradle/java.gradle create mode 100644 code/gradle/jmh.gradle create mode 100644 code/gradle/junit-jupiter.gradle create mode 100644 code/gradle/subprojects.gradle create mode 100644 code/gradle/wrapper/gradle-wrapper.jar create mode 100644 code/gradle/wrapper/gradle-wrapper.properties create mode 100644 code/gradlew create mode 100644 code/gradlew.bat create mode 100644 code/hiding/Cake.java create mode 100644 code/hiding/ChocolateChip.java create mode 100644 code/hiding/ChocolateChip2.java create mode 100644 code/hiding/CreatePackageAccessObject.java create mode 100644 code/hiding/Dinner.java create mode 100644 code/hiding/FullQualification.java create mode 100644 code/hiding/IceCream.java create mode 100644 code/hiding/ImportedMyClass.java create mode 100644 code/hiding/LibTest.java create mode 100644 code/hiding/Lunch.java create mode 100644 code/hiding/OrganizedByAccess.java create mode 100644 code/hiding/Pie.java create mode 100644 code/hiding/QualifiedMyClass.java create mode 100644 code/hiding/SingleImport.java create mode 100644 code/hiding/cookie2/Cookie.java create mode 100644 code/hiding/dessert/Cookie.java create mode 100644 code/hiding/mypackage/MyClass.java create mode 100644 code/hiding/packageaccess/PublicConstructor.java create mode 100644 code/housekeeping/Apricot.java create mode 100644 code/housekeeping/ArrayClassObj.java create mode 100644 code/housekeeping/ArrayInit.java create mode 100644 code/housekeeping/ArrayNew.java create mode 100644 code/housekeeping/ArraysOfPrimitives.java create mode 100644 code/housekeeping/AutoboxingVarargs.java create mode 100644 code/housekeeping/BananaPeel.java create mode 100644 code/housekeeping/Burrito.java create mode 100644 code/housekeeping/Counter.java create mode 100644 code/housekeeping/DefaultConstructor.java create mode 100644 code/housekeeping/Demotion.java create mode 100644 code/housekeeping/DynamicArray.java create mode 100644 code/housekeeping/EnumOrder.java create mode 100644 code/housekeeping/ExplicitStatic.java create mode 100644 code/housekeeping/Flower.java create mode 100644 code/housekeeping/InitialValues.java create mode 100644 code/housekeeping/InitialValues2.java create mode 100644 code/housekeeping/Leaf.java create mode 100644 code/housekeeping/Measurement.java create mode 100644 code/housekeeping/MethodInit.java create mode 100644 code/housekeeping/MethodInit2.java create mode 100644 code/housekeeping/MethodInit3.java create mode 100644 code/housekeeping/Mugs.java create mode 100644 code/housekeeping/NewVarArgs.java create mode 100644 code/housekeeping/NoSynthesis.java create mode 100644 code/housekeeping/OptionalTrailingArguments.java create mode 100644 code/housekeeping/OrderOfInitialization.java create mode 100644 code/housekeeping/Overloading.java create mode 100644 code/housekeeping/OverloadingOrder.java create mode 100644 code/housekeeping/OverloadingVarargs.java create mode 100644 code/housekeeping/OverloadingVarargs2.java create mode 100644 code/housekeeping/OverloadingVarargs3.java create mode 100644 code/housekeeping/PassingThis.java create mode 100644 code/housekeeping/PrimitiveOverloading.java create mode 100644 code/housekeeping/SimpleConstructor.java create mode 100644 code/housekeeping/SimpleConstructor2.java create mode 100644 code/housekeeping/SimpleEnumUse.java create mode 100644 code/housekeeping/Spiciness.java create mode 100644 code/housekeeping/Spoon.java create mode 100644 code/housekeeping/StaticInitialization.java create mode 100644 code/housekeeping/TerminationCondition.java create mode 100644 code/housekeeping/VarArgs.java create mode 100644 code/housekeeping/VarargType.java create mode 100644 code/innerclasses/AnonymousConstructor.java create mode 100644 code/innerclasses/BigEgg.java create mode 100644 code/innerclasses/BigEgg2.java create mode 100644 code/innerclasses/Callbacks.java create mode 100644 code/innerclasses/ClassInInterface.java create mode 100644 code/innerclasses/Contents.java create mode 100644 code/innerclasses/Destination.java create mode 100644 code/innerclasses/DotNew.java create mode 100644 code/innerclasses/DotThis.java create mode 100644 code/innerclasses/GreenhouseController.java create mode 100644 code/innerclasses/GreenhouseControls.java create mode 100644 code/innerclasses/InheritInner.java create mode 100644 code/innerclasses/LocalInnerClass.java create mode 100644 code/innerclasses/MultiImplementation.java create mode 100644 code/innerclasses/MultiNestingAccess.java create mode 100644 code/innerclasses/Parcel1.java create mode 100644 code/innerclasses/Parcel10.java create mode 100644 code/innerclasses/Parcel11.java create mode 100644 code/innerclasses/Parcel2.java create mode 100644 code/innerclasses/Parcel3.java create mode 100644 code/innerclasses/Parcel5.java create mode 100644 code/innerclasses/Parcel6.java create mode 100644 code/innerclasses/Parcel7.java create mode 100644 code/innerclasses/Parcel7b.java create mode 100644 code/innerclasses/Parcel8.java create mode 100644 code/innerclasses/Parcel9.java create mode 100644 code/innerclasses/Sequence.java create mode 100644 code/innerclasses/TestBed.java create mode 100644 code/innerclasses/TestParcel.java create mode 100644 code/innerclasses/Wrapping.java create mode 100644 code/innerclasses/controller/Controller.java create mode 100644 code/innerclasses/controller/Event.java create mode 100644 code/innerclasses/mui/MultiInterfaces.java create mode 100644 code/interfaces/AbstractAccess.java create mode 100644 code/interfaces/AbstractWithoutAbstracts.java create mode 100644 code/interfaces/AdaptedRandomDoubles.java create mode 100644 code/interfaces/Adventure.java create mode 100644 code/interfaces/AnImplementation.java create mode 100644 code/interfaces/AnInterface.java create mode 100644 code/interfaces/Applicator.java create mode 100644 code/interfaces/AttemptToUseBasic.java create mode 100644 code/interfaces/Basic.java create mode 100644 code/interfaces/Basic2.java create mode 100644 code/interfaces/Factories.java create mode 100644 code/interfaces/Games.java create mode 100644 code/interfaces/HorrorShow.java create mode 100644 code/interfaces/Implementation2.java create mode 100644 code/interfaces/ImplementingAnInterface.java create mode 100644 code/interfaces/Instantiable.java create mode 100644 code/interfaces/InterfaceCollision.java create mode 100644 code/interfaces/InterfaceWithDefault.java create mode 100644 code/interfaces/Jim.java create mode 100644 code/interfaces/MICollision.java create mode 100644 code/interfaces/Machine.java create mode 100644 code/interfaces/Months.java create mode 100644 code/interfaces/MultipleInheritance.java create mode 100644 code/interfaces/PureInterface.java create mode 100644 code/interfaces/RandVals.java create mode 100644 code/interfaces/RandomDoubles.java create mode 100644 code/interfaces/RandomStrings.java create mode 100644 code/interfaces/TestRandVals.java create mode 100644 code/interfaces/filters/BandPass.java create mode 100644 code/interfaces/filters/Filter.java create mode 100644 code/interfaces/filters/HighPass.java create mode 100644 code/interfaces/filters/LowPass.java create mode 100644 code/interfaces/filters/Waveform.java create mode 100644 code/interfaces/interfaceprocessor/Applicator.java create mode 100644 code/interfaces/interfaceprocessor/FilterProcessor.java create mode 100644 code/interfaces/interfaceprocessor/Processor.java create mode 100644 code/interfaces/interfaceprocessor/StringProcessor.java create mode 100644 code/interfaces/music4/Music4.java create mode 100644 code/interfaces/music5/Music5.java create mode 100644 code/interfaces/nesting/NestingInterfaces.java create mode 100644 code/iostreams/BasicFileOutput.java create mode 100644 code/iostreams/BufferedInputFile.java create mode 100644 code/iostreams/FileOutputShortcut.java create mode 100644 code/iostreams/FormattedMemoryInput.java create mode 100644 code/iostreams/MemoryInput.java create mode 100644 code/iostreams/StoringAndRecoveringData.java create mode 100644 code/iostreams/TestEOF.java create mode 100644 code/iostreams/UsingRandomAccessFile.java create mode 100644 code/javadoc/Documentation1.java create mode 100644 code/javadoc/Documentation2.java create mode 100644 code/javadoc/Documentation3.java create mode 100644 code/javadoc/HelloDateDoc.java create mode 100644 code/lowlevel/AtomicEvenProducer.java create mode 100644 code/lowlevel/AtomicIntegerTest.java create mode 100644 code/lowlevel/AtomicSerialNumbers.java create mode 100644 code/lowlevel/Atomicity.java create mode 100644 code/lowlevel/AttemptLocking.java create mode 100644 code/lowlevel/CaptureUncaughtException.java create mode 100644 code/lowlevel/CircularSet.java create mode 100644 code/lowlevel/DelayQueueDemo.java create mode 100644 code/lowlevel/EvenChecker.java create mode 100644 code/lowlevel/EvenProducer.java create mode 100644 code/lowlevel/ExceptionThread.java create mode 100644 code/lowlevel/IntGenerator.java create mode 100644 code/lowlevel/IntTestable.java create mode 100644 code/lowlevel/MutexEvenProducer.java create mode 100644 code/lowlevel/NaiveExceptionHandling.java create mode 100644 code/lowlevel/NotAtomic.java create mode 100644 code/lowlevel/NumberOfProcessors.java create mode 100644 code/lowlevel/PriorityBlockingQueueDemo.java create mode 100644 code/lowlevel/ReOrdering.java create mode 100644 code/lowlevel/SafeReturn.java create mode 100644 code/lowlevel/SerialNumberChecker.java create mode 100644 code/lowlevel/SerialNumberTest.java create mode 100644 code/lowlevel/SerialNumbers.java create mode 100644 code/lowlevel/SettingDefaultHandler.java create mode 100644 code/lowlevel/SwallowedException.java create mode 100644 code/lowlevel/SyncOnObject.java create mode 100644 code/lowlevel/SynchronizedComparison.java create mode 100644 code/lowlevel/SynchronizedEvenProducer.java create mode 100644 code/lowlevel/SynchronizedSerialNumbers.java create mode 100644 code/lowlevel/TestAbort.java create mode 100644 code/lowlevel/ThreadSize.java create mode 100644 code/lowlevel/UnsafeReturn.java create mode 100644 code/lowlevel/WorkStealingPool.java create mode 100644 code/newio/AvailableCharSets.java create mode 100644 code/newio/BufferToText.java create mode 100644 code/newio/ChannelCopy.java create mode 100644 code/newio/Endians.java create mode 100644 code/newio/FileLocking.java create mode 100644 code/newio/GetChannel.java create mode 100644 code/newio/GetData.java create mode 100644 code/newio/IntBufferDemo.java create mode 100644 code/newio/LargeMappedFiles.java create mode 100644 code/newio/LockingMappedFiles.java create mode 100644 code/newio/MappedIO.java create mode 100644 code/newio/TransferTo.java create mode 100644 code/newio/UsingBuffers.java create mode 100644 code/newio/ViewBuffers.java create mode 100644 code/objects/HelloDate.java create mode 100644 code/objects/ShowProperties.java create mode 100644 code/onjava/ArrayShow.java create mode 100644 code/onjava/BasicSupplier.java create mode 100644 code/onjava/CollectionMethodDifferences.java create mode 100644 code/onjava/ConvertTo.java create mode 100644 code/onjava/Count.java create mode 100644 code/onjava/CountMap.java create mode 100644 code/onjava/CountingIntegerList.java create mode 100644 code/onjava/Countries.java create mode 100644 code/onjava/Enums.java create mode 100644 code/onjava/FillMap.java create mode 100644 code/onjava/HTMLColors.java create mode 100644 code/onjava/MouseClick.java create mode 100644 code/onjava/Nap.java create mode 100644 code/onjava/Null.java create mode 100644 code/onjava/OSExecute.java create mode 100644 code/onjava/OSExecuteException.java create mode 100644 code/onjava/Operations.java create mode 100644 code/onjava/Pair.java create mode 100644 code/onjava/ProcessFiles.java create mode 100644 code/onjava/Rand.java create mode 100644 code/onjava/Range.java create mode 100644 code/onjava/Repeat.java create mode 100644 code/onjava/RmDir.java create mode 100644 code/onjava/Sets.java create mode 100644 code/onjava/Stack.java create mode 100644 code/onjava/Suppliers.java create mode 100644 code/onjava/TimedAbort.java create mode 100644 code/onjava/Timer.java create mode 100644 code/onjava/Tuple.java create mode 100644 code/onjava/Tuple2.java create mode 100644 code/onjava/Tuple3.java create mode 100644 code/onjava/Tuple4.java create mode 100644 code/onjava/Tuple5.java create mode 100644 code/onjava/TypeCounter.java create mode 100644 code/onjava/atunit/AtUnit.java create mode 100644 code/onjava/atunit/ClassNameFinder.java create mode 100644 code/onjava/atunit/Test.java create mode 100644 code/onjava/atunit/TestObjectCleanup.java create mode 100644 code/onjava/atunit/TestObjectCreate.java create mode 100644 code/onjava/atunit/TestProperty.java create mode 100644 code/operators/AllOps.java create mode 100644 code/operators/Assignment.java create mode 100644 code/operators/AutoInc.java create mode 100644 code/operators/BitManipulation.java create mode 100644 code/operators/Bool.java create mode 100644 code/operators/Casting.java create mode 100644 code/operators/CastingNumbers.java create mode 100644 code/operators/EqualsMethod.java create mode 100644 code/operators/EqualsMethod2.java create mode 100644 code/operators/Equivalence.java create mode 100644 code/operators/Exponents.java create mode 100644 code/operators/Literals.java create mode 100644 code/operators/MathOps.java create mode 100644 code/operators/Overflow.java create mode 100644 code/operators/PassObject.java create mode 100644 code/operators/Precedence.java create mode 100644 code/operators/RoundingNumbers.java create mode 100644 code/operators/ShortCircuit.java create mode 100644 code/operators/StringOperators.java create mode 100644 code/operators/TernaryIfElse.java create mode 100644 code/operators/URShift.java create mode 100644 code/operators/Underscores.java create mode 100644 code/patterns/BoxObserver.java create mode 100644 code/patterns/CommandPattern.java create mode 100644 code/patterns/Facade.java create mode 100644 code/patterns/PaperScissorsRock.java create mode 100644 code/patterns/ProxyDemo.java create mode 100644 code/patterns/ShapeFactory1.java create mode 100644 code/patterns/ShapeFactory2.java create mode 100644 code/patterns/ShapeFactory3.java create mode 100644 code/patterns/SingletonPattern.java create mode 100644 code/patterns/StateDemo.java create mode 100644 code/patterns/TemplateMethod.java create mode 100644 code/patterns/abstractfactory/GameEnvironment.java create mode 100644 code/patterns/adapt/Adapter.java create mode 100644 code/patterns/chain/ChainOfResponsibility.java create mode 100644 code/patterns/doubledispatch/Aluminum.java create mode 100644 code/patterns/doubledispatch/Cardboard.java create mode 100644 code/patterns/doubledispatch/DoubleDispatch.java create mode 100644 code/patterns/doubledispatch/Glass.java create mode 100644 code/patterns/doubledispatch/Paper.java create mode 100644 code/patterns/doubledispatch/TypedBin.java create mode 100644 code/patterns/doubledispatch/TypedBinMember.java create mode 100644 code/patterns/dynatrash/DynaTrash.java create mode 100644 code/patterns/observer/ObservedFlower.java create mode 100644 code/patterns/recyclea/RecycleA.java create mode 100644 code/patterns/recycleb/RecycleB.java create mode 100644 code/patterns/recyclec/RecycleC.java create mode 100644 code/patterns/shapes/BadShapeCreation.java create mode 100644 code/patterns/shapes/Circle.java create mode 100644 code/patterns/shapes/FactoryMethod.java create mode 100644 code/patterns/shapes/FactoryTest.java create mode 100644 code/patterns/shapes/Shape.java create mode 100644 code/patterns/shapes/Square.java create mode 100644 code/patterns/shapes/Triangle.java create mode 100644 code/patterns/state/StateMachineDemo.java create mode 100644 code/patterns/strategy/StrategyPattern.java create mode 100644 code/patterns/strategy/StrategyPattern2.java create mode 100644 code/patterns/trash/Aluminum.java create mode 100644 code/patterns/trash/Cardboard.java create mode 100644 code/patterns/trash/Fillable.java create mode 100644 code/patterns/trash/FillableList.java create mode 100644 code/patterns/trash/Glass.java create mode 100644 code/patterns/trash/Paper.java create mode 100644 code/patterns/trash/ParseTrash.java create mode 100644 code/patterns/trash/Trash.dat create mode 100644 code/patterns/trash/Trash.java create mode 100644 code/patterns/trashvisitor/Aluminum.java create mode 100644 code/patterns/trashvisitor/Cardboard.java create mode 100644 code/patterns/trashvisitor/Glass.java create mode 100644 code/patterns/trashvisitor/Paper.java create mode 100644 code/patterns/trashvisitor/TrashVisitor.java create mode 100644 code/patterns/trashvisitor/Visitable.java create mode 100644 code/patterns/trashvisitor/Visitor.java create mode 100644 code/patterns/visitor/BeeAndFlowers.java create mode 100644 code/polymorphism/CovariantReturn.java create mode 100644 code/polymorphism/FieldAccess.java create mode 100644 code/polymorphism/Frog.java create mode 100644 code/polymorphism/PolyConstructors.java create mode 100644 code/polymorphism/PrivateOverride.java create mode 100644 code/polymorphism/PrivateOverride2.java create mode 100644 code/polymorphism/RTTI.java create mode 100644 code/polymorphism/ReferenceCounting.java create mode 100644 code/polymorphism/Sandwich.java create mode 100644 code/polymorphism/Shapes.java create mode 100644 code/polymorphism/StaticPolymorphism.java create mode 100644 code/polymorphism/Transmogrify.java create mode 100644 code/polymorphism/music/Instrument.java create mode 100644 code/polymorphism/music/Music.java create mode 100644 code/polymorphism/music/Music2.java create mode 100644 code/polymorphism/music/Note.java create mode 100644 code/polymorphism/music/Wind.java create mode 100644 code/polymorphism/music3/Music3.java create mode 100644 code/polymorphism/shape/Circle.java create mode 100644 code/polymorphism/shape/RandomShapes.java create mode 100644 code/polymorphism/shape/Shape.java create mode 100644 code/polymorphism/shape/Square.java create mode 100644 code/polymorphism/shape/Triangle.java create mode 100644 code/references/AddingClone.java create mode 100644 code/references/Alias1.java create mode 100644 code/references/Alias2.java create mode 100644 code/references/CheckCloneable.java create mode 100644 code/references/CloneArrayList.java create mode 100644 code/references/Compete.java create mode 100644 code/references/CopyConstructor.java create mode 100644 code/references/DepthReading.java create mode 100644 code/references/HorrorFlick.java create mode 100644 code/references/Immutable1.java create mode 100644 code/references/Immutable2.java create mode 100644 code/references/ImmutableInteger.java create mode 100644 code/references/ImmutableStrings.java create mode 100644 code/references/LocalCopy.java create mode 100644 code/references/MutableInteger.java create mode 100644 code/references/OceanReading.java create mode 100644 code/references/PassReferences.java create mode 100644 code/references/SimplerMutableInteger.java create mode 100644 code/references/Snake.java create mode 100644 code/references/Stringer.java create mode 100644 code/references/TemperatureReading.java create mode 100644 code/references/tests/DeepCopyTest.java create mode 100644 code/reuse/Bath.java create mode 100644 code/reuse/Beetle.java create mode 100644 code/reuse/BlankFinal.java create mode 100644 code/reuse/CADSystem.java create mode 100644 code/reuse/Car.java create mode 100644 code/reuse/Cartoon.java create mode 100644 code/reuse/Chess.java create mode 100644 code/reuse/DerivedSpaceShip.java create mode 100644 code/reuse/Detergent.java create mode 100644 code/reuse/FinalArguments.java create mode 100644 code/reuse/FinalData.java create mode 100644 code/reuse/FinalOverridingIllusion.java create mode 100644 code/reuse/Hide.java create mode 100644 code/reuse/Jurassic.java create mode 100644 code/reuse/Lisa.java create mode 100644 code/reuse/Orc.java create mode 100644 code/reuse/PlaceSetting.java create mode 100644 code/reuse/SpaceShipControls.java create mode 100644 code/reuse/SpaceShipDelegation.java create mode 100644 code/reuse/SprinklerSystem.java create mode 100644 code/reuse/Wind.java create mode 100644 code/serialization/APerson.java create mode 100644 code/serialization/AStoreCADState.java create mode 100644 code/serialization/Alien.java create mode 100644 code/serialization/Blip3.java create mode 100644 code/serialization/Blips.java create mode 100644 code/serialization/FreezeAlien.java create mode 100644 code/serialization/Logon.java create mode 100644 code/serialization/MyWorld.java create mode 100644 code/serialization/People.java create mode 100644 code/serialization/RecoverCADState.java create mode 100644 code/serialization/SerialCtl.java create mode 100644 code/serialization/Worm.java create mode 100644 code/serialization/xfiles/ThawAlien.java create mode 100644 code/settings.gradle create mode 100644 code/standardio/ChangeSystemOut.java create mode 100644 code/standardio/Echo.java create mode 100644 code/standardio/OSExecuteDemo.java create mode 100644 code/standardio/Redirecting.java create mode 100644 code/staticchecking/DogsAndRobots.cpp create mode 100644 code/staticchecking/DogsAndRobots.py create mode 100644 code/staticchecking/NoBasePetSpeak.py create mode 100644 code/staticchecking/PetSpeak.py create mode 100644 code/staticchecking/dogsandrobots.go create mode 100644 code/staticchecking/dr/DogsAndRobots.java create mode 100644 code/staticchecking/drc/DogAndRobotCollections.java create mode 100644 code/staticchecking/latent/Latent.java create mode 100644 code/staticchecking/petspeak.go create mode 100644 code/staticchecking/petspeak/PetSpeak.java create mode 100644 code/streams/ArrayStreams.java create mode 100644 code/streams/Bubble.java create mode 100644 code/streams/Bubbles.java create mode 100644 code/streams/Cheese.dat create mode 100644 code/streams/CollectionToStream.java create mode 100644 code/streams/CreatingOptionals.java create mode 100644 code/streams/Duplicator.java create mode 100644 code/streams/Fibonacci.java create mode 100644 code/streams/FileToWords.java create mode 100644 code/streams/FileToWordsBuilder.java create mode 100644 code/streams/FileToWordsRegexp.java create mode 100644 code/streams/FileToWordsTest.java create mode 100644 code/streams/FlatMap.java create mode 100644 code/streams/ForEach.java create mode 100644 code/streams/FunctionMap.java create mode 100644 code/streams/FunctionMap2.java create mode 100644 code/streams/FunctionMap3.java create mode 100644 code/streams/Generator.java create mode 100644 code/streams/ImperativeRandoms.java create mode 100644 code/streams/Informational.java create mode 100644 code/streams/LastElement.java create mode 100644 code/streams/Looping.java create mode 100644 code/streams/Machine2.java create mode 100644 code/streams/MapCollector.java create mode 100644 code/streams/Matching.java create mode 100644 code/streams/NumericStreamInfo.java create mode 100644 code/streams/OptionalBasics.java create mode 100644 code/streams/OptionalFilter.java create mode 100644 code/streams/OptionalFlatMap.java create mode 100644 code/streams/OptionalMap.java create mode 100644 code/streams/Optionals.java create mode 100644 code/streams/OptionalsFromEmptyStreams.java create mode 100644 code/streams/Peeking.java create mode 100644 code/streams/Prime.java create mode 100644 code/streams/RandInts.java create mode 100644 code/streams/RandomGenerators.java create mode 100644 code/streams/RandomWords.java create mode 100644 code/streams/Randoms.java create mode 100644 code/streams/Ranges.java create mode 100644 code/streams/Reduce.java create mode 100644 code/streams/SelectElement.java create mode 100644 code/streams/Signal.java create mode 100644 code/streams/SortedComparator.java create mode 100644 code/streams/SpecialCollector.java create mode 100644 code/streams/StreamOf.java create mode 100644 code/streams/StreamOfOptionals.java create mode 100644 code/streams/StreamOfRandoms.java create mode 100644 code/streams/StreamOfStreams.java create mode 100644 code/streams/TreeSetOfWords.java create mode 100644 code/strings/ArrayListDisplay.java create mode 100644 code/strings/BetterRead.java create mode 100644 code/strings/Concatenation.java create mode 100644 code/strings/Conversion.java create mode 100644 code/strings/DatabaseException.java create mode 100644 code/strings/Finding.java create mode 100644 code/strings/Groups.java create mode 100644 code/strings/Hex.java create mode 100644 code/strings/Immutable.java create mode 100644 code/strings/InfiniteRecursion.java create mode 100644 code/strings/IntegerMatch.java create mode 100644 code/strings/JGrep.java create mode 100644 code/strings/ReFlags.java create mode 100644 code/strings/ReceiptBuilder.java create mode 100644 code/strings/Replacing.java create mode 100644 code/strings/ReplacingStringTokenizer.java create mode 100644 code/strings/Resetting.java create mode 100644 code/strings/Rudolph.java create mode 100644 code/strings/ScannerDelimiter.java create mode 100644 code/strings/SimpleFormat.java create mode 100644 code/strings/SimpleRead.java create mode 100644 code/strings/SplitDemo.java create mode 100644 code/strings/Splitting.java create mode 100644 code/strings/StartEnd.java create mode 100644 code/strings/TestRegularExpression.java create mode 100644 code/strings/TheReplacements.java create mode 100644 code/strings/ThreatAnalyzer.java create mode 100644 code/strings/Turtle.java create mode 100644 code/strings/UsingStringBuilder.java create mode 100644 code/strings/WhitherStringBuilder.java create mode 100644 code/typeinfo/AnonymousImplementation.java create mode 100644 code/typeinfo/BoundedClassReferences.java create mode 100644 code/typeinfo/ClassCasts.java create mode 100644 code/typeinfo/ClassInitialization.java create mode 100644 code/typeinfo/DynamicSupplier.java create mode 100644 code/typeinfo/FamilyVsExactType.java create mode 100644 code/typeinfo/GenericClassReferences.java create mode 100644 code/typeinfo/HiddenImplementation.java create mode 100644 code/typeinfo/InnerImplementation.java create mode 100644 code/typeinfo/InterfaceViolation.java create mode 100644 code/typeinfo/ModifyingPrivateFields.java create mode 100644 code/typeinfo/NullRobot.java create mode 100644 code/typeinfo/Operation.java create mode 100644 code/typeinfo/Person.java create mode 100644 code/typeinfo/PetCount.java create mode 100644 code/typeinfo/PetCount2.java create mode 100644 code/typeinfo/PetCount3.java create mode 100644 code/typeinfo/PetCount4.java create mode 100644 code/typeinfo/Position.java create mode 100644 code/typeinfo/RegisteredFactories.java create mode 100644 code/typeinfo/Robot.java create mode 100644 code/typeinfo/SelectingMethods.java create mode 100644 code/typeinfo/Shapes.java create mode 100644 code/typeinfo/ShowMethods.java create mode 100644 code/typeinfo/SimpleDynamicProxy.java create mode 100644 code/typeinfo/SimpleProxyDemo.java create mode 100644 code/typeinfo/SnowRemovalRobot.java create mode 100644 code/typeinfo/Staff.java create mode 100644 code/typeinfo/SweetShop.java create mode 100644 code/typeinfo/WildcardClassReferences.java create mode 100644 code/typeinfo/interfacea/A.java create mode 100644 code/typeinfo/packageaccess/HiddenC.java create mode 100644 code/typeinfo/pets/Cat.java create mode 100644 code/typeinfo/pets/Cymric.java create mode 100644 code/typeinfo/pets/Dog.java create mode 100644 code/typeinfo/pets/EgyptianMau.java create mode 100644 code/typeinfo/pets/ForNameCreator.java create mode 100644 code/typeinfo/pets/Hamster.java create mode 100644 code/typeinfo/pets/Individual.java create mode 100644 code/typeinfo/pets/LiteralPetCreator.java create mode 100644 code/typeinfo/pets/Manx.java create mode 100644 code/typeinfo/pets/Mouse.java create mode 100644 code/typeinfo/pets/Mutt.java create mode 100644 code/typeinfo/pets/Person.java create mode 100644 code/typeinfo/pets/Pet.java create mode 100644 code/typeinfo/pets/PetCreator.java create mode 100644 code/typeinfo/pets/Pets.java create mode 100644 code/typeinfo/pets/Pug.java create mode 100644 code/typeinfo/pets/Rat.java create mode 100644 code/typeinfo/pets/Rodent.java create mode 100644 code/typeinfo/toys/GenericToyTest.java create mode 100644 code/typeinfo/toys/ToyTest.java create mode 100644 code/validating/Assert1.java create mode 100644 code/validating/Assert2.java create mode 100644 code/validating/BadMicroBenchmark.java create mode 100644 code/validating/BadMicroBenchmark2.java create mode 100644 code/validating/CircularQueue.java create mode 100644 code/validating/CircularQueueException.java create mode 100644 code/validating/CountedList.java create mode 100644 code/validating/GuavaAssertions.java create mode 100644 code/validating/GuavaPreconditions.java create mode 100644 code/validating/Inverter1.java create mode 100644 code/validating/Inverter2.java create mode 100644 code/validating/Inverter3.java create mode 100644 code/validating/Inverter4.java create mode 100644 code/validating/LoaderAssertions.java create mode 100644 code/validating/NonNullConstruction.java create mode 100644 code/validating/SLF4JLevels.java create mode 100644 code/validating/SLF4JLogging.java create mode 100644 code/validating/SimpleDebugging.java create mode 100644 code/validating/StringInverter.java create mode 100644 code/validating/jmh/JMH1.java create mode 100644 code/validating/jmh/JMH2.java create mode 100644 code/validating/jmh/JMH3.java create mode 100644 code/validating/logback.xml create mode 100644 code/validating/tests/CircularQueueTest.java create mode 100644 code/validating/tests/CountedListTest.java create mode 100644 code/validating/tests/DynamicStringInverterTests.java create mode 100644 code/validating/tests/StringInverterTests.java diff --git a/code/.gitattributes b/code/.gitattributes new file mode 100644 index 00000000..bdb0cabc --- /dev/null +++ b/code/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/code/.gitignore b/code/.gitignore new file mode 100644 index 00000000..48292956 --- /dev/null +++ b/code/.gitignore @@ -0,0 +1,111 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +*.class +*output.txt +Generated.txt +*-control.txt +*-results.txt +*-out.txt +OutputErrors.txt +report.txt +failures +People.xml +annotations/Test0.txt +annotations/Test1.txt +annotations/Test2.txt +io/*.out +io/*.txt +io/*.dat +io/*.tmp +io/test.zip +io/test.gz +io/X.file +*.pyc + +*.out +*.err +/files/bytes.dat +/files/test/ +/exceptions/Results.txt +/files/Cheese.txt +/files/StreamInAndOut.txt + +.gradle +/*.iml +/.idea/ + +/serialization/Blip3.serialized +/serialization/Blips.serialized + +build/ +buildSrc/ + +/compression/test.gz +/compression/test.zip +/iostreams/BasicFileOutput.dat +/iostreams/Data.txt +/iostreams/FileOutputShortcut.dat +/iostreams/rtest.dat +/logging/LogToFile.xml +/logging/LogToFile2.txt +/logging/MultipleHandlers.xml +/logging/MultipleHandlers2.xml +/logging/java0.log +/logging/java1.log +/logging/java2.log +/newio/TransferTo.txt +/newio/data2.txt +/newio/file.txt +/newio/test.dat +/newio/test.txt +/serialization/CADState.dat +/serialization/worm.dat +/serialization/Logon.dat +/serialization/X.file +/standardio/Redirecting.txt +/threads/PSP2.txt +/threads/primes.txt +_* +config.py diff --git a/code/.travisXX.yml b/code/.travisXX.yml new file mode 100644 index 00000000..54fee659 --- /dev/null +++ b/code/.travisXX.yml @@ -0,0 +1,8 @@ +language: java +jdk: + - oraclejdk11 +install: true +script: + - ./gradlew --no-daemon --stacktrace run +# - ./gradlew --parallel --stacktrace run +# - ./gradlew --parallel --stacktrace :validating:jmh diff --git a/code/CI.txt b/code/CI.txt new file mode 100644 index 00000000..524ee206 --- /dev/null +++ b/code/CI.txt @@ -0,0 +1,5 @@ +Links formerly in the README. Both of these mysteriously started breaking. + +[![](https://travis-ci.org/BruceEckel/OnJava8-Examples.svg?branch=master)](https://travis-ci.org/BruceEckel/OnJava8-Examples) + +[![](https://ci.appveyor.com/api/projects/status/github/BruceEckel/OnJava8-Examples)](https://ci.appveyor.com/project/BruceEckel/onjava-examples) diff --git a/code/Copyright.txt b/code/Copyright.txt new file mode 100644 index 00000000..f0d35035 --- /dev/null +++ b/code/Copyright.txt @@ -0,0 +1,72 @@ +// Copyright.txt +This computer source code is Copyright 2020 MindView LLC. +All Rights Reserved. + +Permission to use, copy, modify, and distribute this +computer source code (Source Code) and its documentation +without fee and without a written agreement for the +purposes set forth below is hereby granted, provided that +the above copyright notice, this paragraph and the +following five numbered paragraphs appear in all copies. + +1. Permission is granted to compile the Source Code and to +include the compiled code, in executable format only, in +personal and commercial software programs. + +2. Permission is granted to use the Source Code without +modification in classroom situations, including in +presentation materials, provided that the book "On +Java 8" is cited as the origin. + +3. Permission to incorporate the Source Code into printed +media may be obtained by contacting: + +MindView LLC, PO Box 969, Crested Butte, CO 81224 +MindViewInc@gmail.com + +4. The Source Code and documentation are copyrighted by +MindView LLC. The Source code is provided without express +or implied warranty of any kind, including any implied +warranty of merchantability, fitness for a particular +purpose or non-infringement. MindView LLC does not +warrant that the operation of any program that includes the +Source Code will be uninterrupted or error-free. MindView +LLC makes no representation about the suitability of the +Source Code or of any software that includes the Source +Code for any purpose. The entire risk as to the quality +and performance of any program that includes the Source +Code is with the user of the Source Code. The user +understands that the Source Code was developed for research +and instructional purposes and is advised not to rely +exclusively for any reason on the Source Code or any +program that includes the Source Code. Should the Source +Code or any resulting software prove defective, the user +assumes the cost of all necessary servicing, repair, or +correction. + +5. IN NO EVENT SHALL MINDVIEW LLC, OR ITS PUBLISHER BE +LIABLE TO ANY PARTY UNDER ANY LEGAL THEORY FOR DIRECT, +INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +INCLUDING LOST PROFITS, BUSINESS INTERRUPTION, LOSS OF +BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS, OR FOR +PERSONAL INJURIES, ARISING OUT OF THE USE OF THIS SOURCE +CODE AND ITS DOCUMENTATION, OR ARISING OUT OF THE INABILITY +TO USE ANY RESULTING PROGRAM, EVEN IF MINDVIEW LLC, OR +ITS PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. MINDVIEW LLC SPECIFICALLY DISCLAIMS ANY +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOURCE CODE AND DOCUMENTATION PROVIDED +HEREUNDER IS ON AN "AS IS" BASIS, WITHOUT ANY ACCOMPANYING +SERVICES FROM MINDVIEW LLC, AND MINDVIEW LLC HAS NO +OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, +ENHANCEMENTS, OR MODIFICATIONS. + +Please note that MindView LLC maintains a Web site which +is the sole distribution point for electronic copies of the +Source Code, https://github.com/BruceEckel/OnJava8-examples, +where it is freely available under the terms stated above. + +If you think you've found an error in the Source Code, +please submit a correction at: +https://github.com/BruceEckel/OnJava8-examples/issues diff --git a/code/README.md b/code/README.md new file mode 100644 index 00000000..985dbbe4 --- /dev/null +++ b/code/README.md @@ -0,0 +1,43 @@ +# Example Source Code for the Book "On Java 8" by Bruce Eckel + +Download release from [here](https://github.com/BruceEckel/OnJava8-Examples/releases/tag/v1.0). + +To compile and run these programs, you only need JDK 8 installed. +Invoking `gradlew` will automatically download and install Gradle. +Gradle will also install all additional libraries necessary to compile +and run the Java examples in the book. + +To compile and run everything, the command is: + +`gradlew run` + +If you are on a Unix/Linux based system, you must select the local directory for all commands, for example: + +`./gradlew run` + +To only compile everything, the command is: + +`gradlew compileJava` + +To compile only a single chapter (including dependencies), use for example: + +`gradlew :strings:compileJava` + +To run only a single chapter, say: + +`gradlew :strings:run` + +Gradle can also be used to run a single program. Here, we run the **ReplacingStringTokenizer.java** +program in the **strings** chapter subdirectory: + +`gradlew :strings:ReplacingStringTokenizer` + +However, if the file name is unique throughout the book (the majority are), you can just give the +program name, like this: + +`gradlew ReplacingStringTokenizer` + +Note that all commands are run from the base directory where the example code is installed, and where you find the +`gradlew` script. + +You can learn about other options by just typing `gradlew` with no arguments. diff --git a/code/annotations/AUComposition.java b/code/annotations/AUComposition.java new file mode 100644 index 00000000..ee43e88d --- /dev/null +++ b/code/annotations/AUComposition.java @@ -0,0 +1,30 @@ +// annotations/AUComposition.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating non-embedded tests +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/AUComposition.class} +package annotations; +import onjava.atunit.*; +import onjava.*; + +public class AUComposition { + AtUnitExample1 testObject = new AtUnitExample1(); + @Test + boolean tMethodOne() { + return testObject.methodOne() + .equals("This is methodOne"); + } + @Test + boolean tMethodTwo() { + return testObject.methodTwo() == 2; + } +} +/* Output: +annotations.AUComposition + . tMethodTwo This is methodTwo + + . tMethodOne +OK (2 tests) +*/ diff --git a/code/annotations/AUExternalTest.java b/code/annotations/AUExternalTest.java new file mode 100644 index 00000000..cce5c429 --- /dev/null +++ b/code/annotations/AUExternalTest.java @@ -0,0 +1,29 @@ +// annotations/AUExternalTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating non-embedded tests +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/AUExternalTest.class} +package annotations; +import onjava.atunit.*; +import onjava.*; + +public class +AUExternalTest extends AtUnitExample1 { + @Test + boolean tMethodOne() { + return methodOne().equals("This is methodOne"); + } + @Test + boolean tMethodTwo() { + return methodTwo() == 2; + } +} +/* Output: +annotations.AUExternalTest + . tMethodOne + . tMethodTwo This is methodTwo + +OK (2 tests) +*/ diff --git a/code/annotations/AtUnitExample1.java b/code/annotations/AtUnitExample1.java new file mode 100644 index 00000000..3b1f6fec --- /dev/null +++ b/code/annotations/AtUnitExample1.java @@ -0,0 +1,48 @@ +// annotations/AtUnitExample1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/AtUnitExample1.class} +package annotations; +import onjava.atunit.*; +import onjava.*; + +public class AtUnitExample1 { + public String methodOne() { + return "This is methodOne"; + } + public int methodTwo() { + System.out.println("This is methodTwo"); + return 2; + } + @Test + boolean methodOneTest() { + return methodOne().equals("This is methodOne"); + } + @Test + boolean m2() { return methodTwo() == 2; } + @Test + private boolean m3() { return true; } + // Shows output for failure: + @Test + boolean failureTest() { return false; } + @Test + boolean anotherDisappointment() { + return false; + } +} +/* Output: +annotations.AtUnitExample1 + . m3 + . methodOneTest + . m2 This is methodTwo + + . failureTest (failed) + . anotherDisappointment (failed) +(5 tests) + +>>> 2 FAILURES <<< + annotations.AtUnitExample1: failureTest + annotations.AtUnitExample1: anotherDisappointment +*/ diff --git a/code/annotations/AtUnitExample2.java b/code/annotations/AtUnitExample2.java new file mode 100644 index 00000000..bf3f1d5c --- /dev/null +++ b/code/annotations/AtUnitExample2.java @@ -0,0 +1,57 @@ +// annotations/AtUnitExample2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Assertions and exceptions can be used in @Tests +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/AtUnitExample2.class} +package annotations; +import java.io.*; +import onjava.atunit.*; +import onjava.*; + +public class AtUnitExample2 { + public String methodOne() { + return "This is methodOne"; + } + public int methodTwo() { + System.out.println("This is methodTwo"); + return 2; + } + @Test + void assertExample() { + assert methodOne().equals("This is methodOne"); + } + @Test + void assertFailureExample() { + assert 1 == 2: "What a surprise!"; + } + @Test + void exceptionExample() throws IOException { + try(FileInputStream fis = + new FileInputStream("nofile.txt")) {} // Throws + } + @Test + boolean assertAndReturn() { + // Assertion with message: + assert methodTwo() == 2: "methodTwo must equal 2"; + return methodOne().equals("This is methodOne"); + } +} +/* Output: +annotations.AtUnitExample2 + . exceptionExample java.io.FileNotFoundException: +nofile.txt (The system cannot find the file specified) +(failed) + . assertExample + . assertAndReturn This is methodTwo + + . assertFailureExample java.lang.AssertionError: What +a surprise! +(failed) +(4 tests) + +>>> 2 FAILURES <<< + annotations.AtUnitExample2: exceptionExample + annotations.AtUnitExample2: assertFailureExample +*/ diff --git a/code/annotations/AtUnitExample3.java b/code/annotations/AtUnitExample3.java new file mode 100644 index 00000000..02092591 --- /dev/null +++ b/code/annotations/AtUnitExample3.java @@ -0,0 +1,42 @@ +// annotations/AtUnitExample3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/AtUnitExample3.class} +package annotations; +import onjava.atunit.*; +import onjava.*; + +public class AtUnitExample3 { + private int n; + public AtUnitExample3(int n) { this.n = n; } + public int getN() { return n; } + public String methodOne() { + return "This is methodOne"; + } + public int methodTwo() { + System.out.println("This is methodTwo"); + return 2; + } + @TestObjectCreate + static AtUnitExample3 create() { + return new AtUnitExample3(47); + } + @Test + boolean initialization() { return n == 47; } + @Test + boolean methodOneTest() { + return methodOne().equals("This is methodOne"); + } + @Test + boolean m2() { return methodTwo() == 2; } +} +/* Output: +annotations.AtUnitExample3 + . initialization + . m2 This is methodTwo + + . methodOneTest +OK (3 tests) +*/ diff --git a/code/annotations/AtUnitExample4.java b/code/annotations/AtUnitExample4.java new file mode 100644 index 00000000..6b644b17 --- /dev/null +++ b/code/annotations/AtUnitExample4.java @@ -0,0 +1,83 @@ +// annotations/AtUnitExample4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/AtUnitExample4.class} +// {VisuallyInspectOutput} +package annotations; +import java.util.*; +import onjava.atunit.*; +import onjava.*; + +public class AtUnitExample4 { + static String theory = "All brontosauruses " + + "are thin at one end, much MUCH thicker in the " + + "middle, and then thin again at the far end."; + private String word; + private Random rand = new Random(); // Time-based seed + public AtUnitExample4(String word) { + this.word = word; + } + public String getWord() { return word; } + public String scrambleWord() { + List chars = Arrays.asList( + ConvertTo.boxed(word.toCharArray())); + Collections.shuffle(chars, rand); + StringBuilder result = new StringBuilder(); + for(char ch : chars) + result.append(ch); + return result.toString(); + } + @TestProperty + static List input = + Arrays.asList(theory.split(" ")); + @TestProperty + static Iterator words = input.iterator(); + @TestObjectCreate + static AtUnitExample4 create() { + if(words.hasNext()) + return new AtUnitExample4(words.next()); + else + return null; + } + @Test + boolean words() { + System.out.println("'" + getWord() + "'"); + return getWord().equals("are"); + } + @Test + boolean scramble1() { + // Use specific seed to get verifiable results: + rand = new Random(47); + System.out.println("'" + getWord() + "'"); + String scrambled = scrambleWord(); + System.out.println(scrambled); + return scrambled.equals("lAl"); + } + @Test + boolean scramble2() { + rand = new Random(74); + System.out.println("'" + getWord() + "'"); + String scrambled = scrambleWord(); + System.out.println(scrambled); + return scrambled.equals("tsaeborornussu"); + } +} +/* Output: +annotations.AtUnitExample4 + . words 'All' +(failed) + . scramble1 'brontosauruses' +ntsaueorosurbs +(failed) + . scramble2 'are' +are +(failed) +(3 tests) + +>>> 3 FAILURES <<< + annotations.AtUnitExample4: words + annotations.AtUnitExample4: scramble1 + annotations.AtUnitExample4: scramble2 +*/ diff --git a/code/annotations/AtUnitExample5.java b/code/annotations/AtUnitExample5.java new file mode 100644 index 00000000..d7cf95df --- /dev/null +++ b/code/annotations/AtUnitExample5.java @@ -0,0 +1,63 @@ +// annotations/AtUnitExample5.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/AtUnitExample5.class} +package annotations; +import java.io.*; +import onjava.atunit.*; +import onjava.*; + +public class AtUnitExample5 { + private String text; + public AtUnitExample5(String text) { + this.text = text; + } + @Override + public String toString() { return text; } + @TestProperty + static PrintWriter output; + @TestProperty + static int counter; + @TestObjectCreate + static AtUnitExample5 create() { + String id = Integer.toString(counter++); + try { + output = new PrintWriter("Test" + id + ".txt"); + } catch(IOException e) { + throw new RuntimeException(e); + } + return new AtUnitExample5(id); + } + @TestObjectCleanup + static void cleanup(AtUnitExample5 tobj) { + System.out.println("Running cleanup"); + output.close(); + } + @Test + boolean test1() { + output.print("test1"); + return true; + } + @Test + boolean test2() { + output.print("test2"); + return true; + } + @Test + boolean test3() { + output.print("test3"); + return true; + } +} +/* Output: +annotations.AtUnitExample5 + . test1 +Running cleanup + . test3 +Running cleanup + . test2 +Running cleanup +OK (3 tests) +*/ diff --git a/code/annotations/DemoProcessFiles.java b/code/annotations/DemoProcessFiles.java new file mode 100644 index 00000000..6e250537 --- /dev/null +++ b/code/annotations/DemoProcessFiles.java @@ -0,0 +1,43 @@ +// annotations/DemoProcessFiles.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.ProcessFiles; + +public class DemoProcessFiles { + public static void main(String[] args) { + new ProcessFiles(file -> System.out.println(file), + "java").start(args); + } +} +/* Output: +.\AtUnitExample1.java +.\AtUnitExample2.java +.\AtUnitExample3.java +.\AtUnitExample4.java +.\AtUnitExample5.java +.\AUComposition.java +.\AUExternalTest.java +.\database\Constraints.java +.\database\DBTable.java +.\database\Member.java +.\database\SQLInteger.java +.\database\SQLString.java +.\database\TableCreator.java +.\database\Uniqueness.java +.\DemoProcessFiles.java +.\HashSetTest.java +.\ifx\ExtractInterface.java +.\ifx\IfaceExtractorProcessor.java +.\ifx\Multiplier.java +.\PasswordUtils.java +.\simplest\Simple.java +.\simplest\SimpleProcessor.java +.\simplest\SimpleTest.java +.\SimulatingNull.java +.\StackL.java +.\StackLStringTst.java +.\Testable.java +.\UseCase.java +.\UseCaseTracker.java +*/ diff --git a/code/annotations/HashSetTest.java b/code/annotations/HashSetTest.java new file mode 100644 index 00000000..8dfa8a9c --- /dev/null +++ b/code/annotations/HashSetTest.java @@ -0,0 +1,36 @@ +// annotations/HashSetTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/HashSetTest.class} +package annotations; +import java.util.*; +import onjava.atunit.*; +import onjava.*; + +public class HashSetTest { + HashSet testObject = new HashSet<>(); + @Test + void initialization() { + assert testObject.isEmpty(); + } + @Test + void tContains() { + testObject.add("one"); + assert testObject.contains("one"); + } + @Test + void tRemove() { + testObject.add("one"); + testObject.remove("one"); + assert testObject.isEmpty(); + } +} +/* Output: +annotations.HashSetTest + . initialization + . tRemove + . tContains +OK (3 tests) +*/ diff --git a/code/annotations/PasswordUtils.java b/code/annotations/PasswordUtils.java new file mode 100644 index 00000000..74a6df78 --- /dev/null +++ b/code/annotations/PasswordUtils.java @@ -0,0 +1,24 @@ +// annotations/PasswordUtils.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class PasswordUtils { + @UseCase(id = 47, description = + "Passwords must contain at least one numeric") + public boolean validatePassword(String passwd) { + return (passwd.matches("\\w*\\d\\w*")); + } + @UseCase(id = 48) + public String encryptPassword(String passwd) { + return new StringBuilder(passwd) + .reverse().toString(); + } + @UseCase(id = 49, description = + "New passwords can't equal previously used ones") + public boolean checkForNewPassword( + List prevPasswords, String passwd) { + return !prevPasswords.contains(passwd); + } +} diff --git a/code/annotations/SimulatingNull.java b/code/annotations/SimulatingNull.java new file mode 100644 index 00000000..8166802b --- /dev/null +++ b/code/annotations/SimulatingNull.java @@ -0,0 +1,12 @@ +// annotations/SimulatingNull.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SimulatingNull { + int id() default -1; + String description() default ""; +} diff --git a/code/annotations/StackL.java b/code/annotations/StackL.java new file mode 100644 index 00000000..6ff806af --- /dev/null +++ b/code/annotations/StackL.java @@ -0,0 +1,14 @@ +// annotations/StackL.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A stack built on a LinkedList +package annotations; +import java.util.*; + +public class StackL { + private LinkedList list = new LinkedList<>(); + public void push(T v) { list.addFirst(v); } + public T top() { return list.getFirst(); } + public T pop() { return list.removeFirst(); } +} diff --git a/code/annotations/StackLStringTst.java b/code/annotations/StackLStringTst.java new file mode 100644 index 00000000..49aef9b7 --- /dev/null +++ b/code/annotations/StackLStringTst.java @@ -0,0 +1,42 @@ +// annotations/StackLStringTst.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Applying @Unit to generics +// {java onjava.atunit.AtUnit +// build/classes/java/main/annotations/StackLStringTst.class} +package annotations; +import onjava.atunit.*; +import onjava.*; + +public class +StackLStringTst extends StackL { + @Test + void tPush() { + push("one"); + assert top().equals("one"); + push("two"); + assert top().equals("two"); + } + @Test + void tPop() { + push("one"); + push("two"); + assert pop().equals("two"); + assert pop().equals("one"); + } + @Test + void tTop() { + push("A"); + push("B"); + assert top().equals("B"); + assert top().equals("B"); + } +} +/* Output: +annotations.StackLStringTst + . tTop + . tPush + . tPop +OK (3 tests) +*/ diff --git a/code/annotations/Testable.java b/code/annotations/Testable.java new file mode 100644 index 00000000..bc48f416 --- /dev/null +++ b/code/annotations/Testable.java @@ -0,0 +1,14 @@ +// annotations/Testable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package annotations; +import onjava.atunit.*; + +public class Testable { + public void execute() { + System.out.println("Executing.."); + } + @Test + void testExecute() { execute(); } +} diff --git a/code/annotations/UseCase.java b/code/annotations/UseCase.java new file mode 100644 index 00000000..dfce3149 --- /dev/null +++ b/code/annotations/UseCase.java @@ -0,0 +1,12 @@ +// annotations/UseCase.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface UseCase { + int id(); + String description() default "no description"; +} diff --git a/code/annotations/UseCaseTracker.java b/code/annotations/UseCaseTracker.java new file mode 100644 index 00000000..5489b762 --- /dev/null +++ b/code/annotations/UseCaseTracker.java @@ -0,0 +1,37 @@ +// annotations/UseCaseTracker.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.lang.reflect.*; + +public class UseCaseTracker { + public static void + trackUseCases(List useCases, Class cl) { + for(Method m : cl.getDeclaredMethods()) { + UseCase uc = m.getAnnotation(UseCase.class); + if(uc != null) { + System.out.println("Found Use Case " + + uc.id() + "\n " + uc.description()); + useCases.remove(Integer.valueOf(uc.id())); + } + } + useCases.forEach(i -> + System.out.println("Missing use case " + i)); + } + public static void main(String[] args) { + List useCases = IntStream.range(47, 51) + .boxed().collect(Collectors.toList()); + trackUseCases(useCases, PasswordUtils.class); + } +} +/* Output: +Found Use Case 48 + no description +Found Use Case 47 + Passwords must contain at least one numeric +Found Use Case 49 + New passwords can't equal previously used ones +Missing use case 50 +*/ diff --git a/code/annotations/database/Constraints.java b/code/annotations/database/Constraints.java new file mode 100644 index 00000000..4e4e40fc --- /dev/null +++ b/code/annotations/database/Constraints.java @@ -0,0 +1,14 @@ +// annotations/database/Constraints.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package annotations.database; +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Constraints { + boolean primaryKey() default false; + boolean allowNull() default true; + boolean unique() default false; +} diff --git a/code/annotations/database/DBTable.java b/code/annotations/database/DBTable.java new file mode 100644 index 00000000..9aa5562f --- /dev/null +++ b/code/annotations/database/DBTable.java @@ -0,0 +1,12 @@ +// annotations/database/DBTable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package annotations.database; +import java.lang.annotation.*; + +@Target(ElementType.TYPE) // Applies to classes only +@Retention(RetentionPolicy.RUNTIME) +public @interface DBTable { + String name() default ""; +} diff --git a/code/annotations/database/Member.java b/code/annotations/database/Member.java new file mode 100644 index 00000000..d722a3b1 --- /dev/null +++ b/code/annotations/database/Member.java @@ -0,0 +1,22 @@ +// annotations/database/Member.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package annotations.database; + +@DBTable(name = "MEMBER") +public class Member { + @SQLString(30) String firstName; + @SQLString(50) String lastName; + @SQLInteger Integer age; + @SQLString(value = 30, + constraints = @Constraints(primaryKey = true)) + String reference; + static int memberCount; + public String getReference() { return reference; } + public String getFirstName() { return firstName; } + public String getLastName() { return lastName; } + @Override + public String toString() { return reference; } + public Integer getAge() { return age; } +} diff --git a/code/annotations/database/SQLInteger.java b/code/annotations/database/SQLInteger.java new file mode 100644 index 00000000..635a907c --- /dev/null +++ b/code/annotations/database/SQLInteger.java @@ -0,0 +1,13 @@ +// annotations/database/SQLInteger.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package annotations.database; +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SQLInteger { + String name() default ""; + Constraints constraints() default @Constraints; +} diff --git a/code/annotations/database/SQLString.java b/code/annotations/database/SQLString.java new file mode 100644 index 00000000..dac9919f --- /dev/null +++ b/code/annotations/database/SQLString.java @@ -0,0 +1,14 @@ +// annotations/database/SQLString.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package annotations.database; +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SQLString { + int value() default 0; + String name() default ""; + Constraints constraints() default @Constraints; +} diff --git a/code/annotations/database/TableCreator.java b/code/annotations/database/TableCreator.java new file mode 100644 index 00000000..53322fc7 --- /dev/null +++ b/code/annotations/database/TableCreator.java @@ -0,0 +1,106 @@ +// annotations/database/TableCreator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Reflection-based annotation processor +// {java annotations.database.TableCreator +// annotations.database.Member} +package annotations.database; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; + +public class TableCreator { + public static void + main(String[] args) throws Exception { + if(args.length < 1) { + System.out.println( + "arguments: annotated classes"); + System.exit(0); + } + for(String className : args) { + Class cl = Class.forName(className); + DBTable dbTable = cl.getAnnotation(DBTable.class); + if(dbTable == null) { + System.out.println( + "No DBTable annotations in class " + + className); + continue; + } + String tableName = dbTable.name(); + // If the name is empty, use the Class name: + if(tableName.length() < 1) + tableName = cl.getName().toUpperCase(); + List columnDefs = new ArrayList<>(); + for(Field field : cl.getDeclaredFields()) { + String columnName = null; + Annotation[] anns = + field.getDeclaredAnnotations(); + if(anns.length < 1) + continue; // Not a db table column + if(anns[0] instanceof SQLInteger) { + SQLInteger sInt = (SQLInteger) anns[0]; + // Use field name if name not specified + if(sInt.name().length() < 1) + columnName = field.getName().toUpperCase(); + else + columnName = sInt.name(); + columnDefs.add(columnName + " INT" + + getConstraints(sInt.constraints())); + } + if(anns[0] instanceof SQLString) { + SQLString sString = (SQLString) anns[0]; + // Use field name if name not specified. + if(sString.name().length() < 1) + columnName = field.getName().toUpperCase(); + else + columnName = sString.name(); + columnDefs.add(columnName + " VARCHAR(" + + sString.value() + ")" + + getConstraints(sString.constraints())); + } + StringBuilder createCommand = new StringBuilder( + "CREATE TABLE " + tableName + "("); + for(String columnDef : columnDefs) + createCommand.append( + "\n " + columnDef + ","); + // Remove trailing comma + String tableCreate = createCommand.substring( + 0, createCommand.length() - 1) + ");"; + System.out.println("Table Creation SQL for " + + className + " is:\n" + tableCreate); + } + } + } + private static + String getConstraints(Constraints con) { + String constraints = ""; + if(!con.allowNull()) + constraints += " NOT NULL"; + if(con.primaryKey()) + constraints += " PRIMARY KEY"; + if(con.unique()) + constraints += " UNIQUE"; + return constraints; + } +} +/* Output: +Table Creation SQL for annotations.database.Member is: +CREATE TABLE MEMBER( + FIRSTNAME VARCHAR(30)); +Table Creation SQL for annotations.database.Member is: +CREATE TABLE MEMBER( + FIRSTNAME VARCHAR(30), + LASTNAME VARCHAR(50)); +Table Creation SQL for annotations.database.Member is: +CREATE TABLE MEMBER( + FIRSTNAME VARCHAR(30), + LASTNAME VARCHAR(50), + AGE INT); +Table Creation SQL for annotations.database.Member is: +CREATE TABLE MEMBER( + FIRSTNAME VARCHAR(30), + LASTNAME VARCHAR(50), + AGE INT, + REFERENCE VARCHAR(30) PRIMARY KEY); +*/ diff --git a/code/annotations/database/Uniqueness.java b/code/annotations/database/Uniqueness.java new file mode 100644 index 00000000..1aa1a36c --- /dev/null +++ b/code/annotations/database/Uniqueness.java @@ -0,0 +1,11 @@ +// annotations/database/Uniqueness.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Sample of nested annotations +package annotations.database; + +public @interface Uniqueness { + Constraints constraints() + default @Constraints(unique = true); +} diff --git a/code/annotations/ifx/ExtractInterface.java b/code/annotations/ifx/ExtractInterface.java new file mode 100644 index 00000000..70a94bf5 --- /dev/null +++ b/code/annotations/ifx/ExtractInterface.java @@ -0,0 +1,13 @@ +// annotations/ifx/ExtractInterface.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// javac-based annotation processing +package annotations.ifx; +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.SOURCE) +public @interface ExtractInterface { + String interfaceName() default "-!!-"; +} diff --git a/code/annotations/ifx/IfaceExtractorProcessor.java b/code/annotations/ifx/IfaceExtractorProcessor.java new file mode 100644 index 00000000..d17156f8 --- /dev/null +++ b/code/annotations/ifx/IfaceExtractorProcessor.java @@ -0,0 +1,91 @@ +// annotations/ifx/IfaceExtractorProcessor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// javac-based annotation processing +package annotations.ifx; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import java.util.*; +import java.util.stream.*; +import java.io.*; + +@SupportedAnnotationTypes( + "annotations.ifx.ExtractInterface") +@SupportedSourceVersion(SourceVersion.RELEASE_8) +public class IfaceExtractorProcessor +extends AbstractProcessor { + private ArrayList + interfaceMethods = new ArrayList<>(); + Elements elementUtils; + private ProcessingEnvironment processingEnv; + @Override + public void init( + ProcessingEnvironment processingEnv) { + this.processingEnv = processingEnv; + elementUtils = processingEnv.getElementUtils(); + } + @Override + public boolean process( + Set annotations, + RoundEnvironment env) { + for(Element elem:env.getElementsAnnotatedWith( + ExtractInterface.class)) { + String interfaceName = elem.getAnnotation( + ExtractInterface.class).interfaceName(); + for(Element enclosed : + elem.getEnclosedElements()) { + if(enclosed.getKind() + .equals(ElementKind.METHOD) && + enclosed.getModifiers() + .contains(Modifier.PUBLIC) && + !enclosed.getModifiers() + .contains(Modifier.STATIC)) { + interfaceMethods.add(enclosed); + } + } + if(interfaceMethods.size() > 0) + writeInterfaceFile(interfaceName); + } + return false; + } + private void + writeInterfaceFile(String interfaceName) { + try( + Writer writer = processingEnv.getFiler() + .createSourceFile(interfaceName) + .openWriter() + ) { + String packageName = elementUtils + .getPackageOf(interfaceMethods + .get(0)).toString(); + writer.write( + "package " + packageName + ";\n"); + writer.write("public interface " + + interfaceName + " {\n"); + for(Element elem : interfaceMethods) { + ExecutableElement method = + (ExecutableElement)elem; + String signature = " public "; + signature += method.getReturnType() + " "; + signature += method.getSimpleName(); + signature += createArgList( + method.getParameters()); + System.out.println(signature); + writer.write(signature + ";\n"); + } + writer.write("}"); + } catch(Exception e) { + throw new RuntimeException(e); + } + } + private String createArgList( + List parameters) { + String args = parameters.stream() + .map(p -> p.asType() + " " + p.getSimpleName()) + .collect(Collectors.joining(", ")); + return "(" + args + ")"; + } +} diff --git a/code/annotations/ifx/Multiplier.java b/code/annotations/ifx/Multiplier.java new file mode 100644 index 00000000..b5b99a1b --- /dev/null +++ b/code/annotations/ifx/Multiplier.java @@ -0,0 +1,34 @@ +// annotations/ifx/Multiplier.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// javac-based annotation processing +// {java annotations.ifx.Multiplier} +package annotations.ifx; + +@ExtractInterface(interfaceName="IMultiplier") +public class Multiplier { + public boolean flag = false; + private int n = 0; + public int multiply(int x, int y) { + int total = 0; + for(int i = 0; i < x; i++) + total = add(total, y); + return total; + } + public int fortySeven() { return 47; } + private int add(int x, int y) { + return x + y; + } + public double timesTen(double arg) { + return arg * 10; + } + public static void main(String[] args) { + Multiplier m = new Multiplier(); + System.out.println( + "11 * 16 = " + m.multiply(11, 16)); + } +} +/* Output: +11 * 16 = 176 +*/ diff --git a/code/annotations/simplest/Simple.java b/code/annotations/simplest/Simple.java new file mode 100644 index 00000000..0dc555ce --- /dev/null +++ b/code/annotations/simplest/Simple.java @@ -0,0 +1,20 @@ +// annotations/simplest/Simple.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A bare-bones annotation +package annotations.simplest; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE, ElementType.METHOD, + ElementType.CONSTRUCTOR, + ElementType.ANNOTATION_TYPE, + ElementType.PACKAGE, ElementType.FIELD, + ElementType.LOCAL_VARIABLE}) +public @interface Simple { + String value() default "-default-"; +} diff --git a/code/annotations/simplest/SimpleProcessor.java b/code/annotations/simplest/SimpleProcessor.java new file mode 100644 index 00000000..a85d8987 --- /dev/null +++ b/code/annotations/simplest/SimpleProcessor.java @@ -0,0 +1,47 @@ +// annotations/simplest/SimpleProcessor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A bare-bones annotation processor +package annotations.simplest; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import java.util.*; + +@SupportedAnnotationTypes( + "annotations.simplest.Simple") +@SupportedSourceVersion(SourceVersion.RELEASE_8) +public class SimpleProcessor +extends AbstractProcessor { + @Override + public boolean process( + Set annotations, + RoundEnvironment env) { + for(TypeElement t : annotations) + System.out.println(t); + for(Element el : + env.getElementsAnnotatedWith(Simple.class)) + display(el); + return false; + } + private void display(Element el) { + System.out.println("==== " + el + " ===="); + System.out.println(el.getKind() + + " : " + el.getModifiers() + + " : " + el.getSimpleName() + + " : " + el.asType()); + if(el.getKind().equals(ElementKind.CLASS)) { + TypeElement te = (TypeElement)el; + System.out.println(te.getQualifiedName()); + System.out.println(te.getSuperclass()); + System.out.println(te.getEnclosedElements()); + } + if(el.getKind().equals(ElementKind.METHOD)) { + ExecutableElement ex = (ExecutableElement)el; + System.out.print(ex.getReturnType() + " "); + System.out.print(ex.getSimpleName() + "("); + System.out.println(ex.getParameters() + ")"); + } + } +} diff --git a/code/annotations/simplest/SimpleTest.java b/code/annotations/simplest/SimpleTest.java new file mode 100644 index 00000000..689d12fd --- /dev/null +++ b/code/annotations/simplest/SimpleTest.java @@ -0,0 +1,32 @@ +// annotations/simplest/SimpleTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Test the "Simple" annotation +// {java annotations.simplest.SimpleTest} +package annotations.simplest; + +@Simple +public class SimpleTest { + @Simple + int i; + @Simple + public SimpleTest() {} + @Simple + public void foo() { + System.out.println("SimpleTest.foo()"); + } + @Simple + public void bar(String s, int i, float f) { + System.out.println("SimpleTest.bar()"); + } + @Simple + public static void main(String[] args) { + @Simple + SimpleTest st = new SimpleTest(); + st.foo(); + } +} +/* Output: +SimpleTest.foo() +*/ diff --git a/code/appveyorXX.yml b/code/appveyorXX.yml new file mode 100644 index 00000000..5e586b07 --- /dev/null +++ b/code/appveyorXX.yml @@ -0,0 +1,4 @@ +build_script: + - gradlew.bat --no-daemon --stacktrace run + +test: off diff --git a/code/arrays/AlphabeticSearch.java b/code/arrays/AlphabeticSearch.java new file mode 100644 index 00000000..70adc8ff --- /dev/null +++ b/code/arrays/AlphabeticSearch.java @@ -0,0 +1,29 @@ +// arrays/AlphabeticSearch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Searching with a Comparator import +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class AlphabeticSearch { + public static void main(String[] args) { + String[] sa = new Rand.String().array(30); + Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER); + show(sa); + int index = Arrays.binarySearch(sa, + sa[10], String.CASE_INSENSITIVE_ORDER); + System.out.println( + "Index: "+ index + "\n"+ sa[index]); + } +} +/* Output: +[anmkkyh, bhmupju, btpenpc, cjwzmmr, cuxszgv, eloztdv, +ewcippc, ezdeklu, fcjpthl, fqmlgsh, gmeinne, hyoubzl, +jbvlgwc, jlxpqds, ljlbynx, mvducuj, qgekgly, skddcat, +taprwxz, uybypgp, vjsszkn, vniyapk, vqqakbm, vwodhcf, +ydpulcq, ygpoalk, yskvett, zehpfmm, zofmmvm, zrxmclh] +Index: 10 +gmeinne +*/ diff --git a/code/arrays/ArrayCopying.java b/code/arrays/ArrayCopying.java new file mode 100644 index 00000000..c68c2a0d --- /dev/null +++ b/code/arrays/ArrayCopying.java @@ -0,0 +1,81 @@ +// arrays/ArrayCopying.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrate Arrays.copy() and Arrays.copyOf() +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +class Sup { // Superclass + private int id; + Sup(int n) { id = n; } + @Override + public String toString() { + return getClass().getSimpleName() + id; + } +} + +class Sub extends Sup { // Subclass + Sub(int n) { super(n); } +} + +public class ArrayCopying { + public static final int SZ = 15; + public static void main(String[] args) { + int[] a1 = new int[SZ]; + Arrays.setAll(a1, new Count.Integer()::get); + show("a1", a1); + int[] a2 = Arrays.copyOf(a1, a1.length); // [1] + // Prove they are distinct arrays: + Arrays.fill(a1, 1); + show("a1", a1); + show("a2", a2); + + // Create a shorter result: + a2 = Arrays.copyOf(a2, a2.length/2); // [2] + show("a2", a2); + // Allocate more space: + a2 = Arrays.copyOf(a2, a2.length + 5); + show("a2", a2); + + // Also copies wrapped arrays: + Integer[] a3 = new Integer[SZ]; // [3] + Arrays.setAll(a3, new Count.Integer()::get); + Integer[] a4 = Arrays.copyOfRange(a3, 4, 12); + show("a4", a4); + + Sub[] d = new Sub[SZ/2]; + Arrays.setAll(d, Sub::new); + // Produce Sup[] from Sub[]: + Sup[] b = + Arrays.copyOf(d, d.length, Sup[].class); // [4] + show(b); + + // This "downcast" works fine: + Sub[] d2 = + Arrays.copyOf(b, b.length, Sub[].class); // [5] + show(d2); + + // Bad "downcast" compiles but throws exception: + Sup[] b2 = new Sup[SZ/2]; + Arrays.setAll(b2, Sup::new); + try { + Sub[] d3 = Arrays.copyOf( + b2, b2.length, Sub[].class); // [6] + } catch(Exception e) { + System.out.println(e); + } + } +} +/* Output: +a1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] +a1: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +a2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] +a2: [0, 1, 2, 3, 4, 5, 6] +a2: [0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0] +a4: [4, 5, 6, 7, 8, 9, 10, 11] +[Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6] +[Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6] +java.lang.ArrayStoreException +*/ diff --git a/code/arrays/ArrayOfGenericType.java b/code/arrays/ArrayOfGenericType.java new file mode 100644 index 00000000..68f9e8de --- /dev/null +++ b/code/arrays/ArrayOfGenericType.java @@ -0,0 +1,16 @@ +// arrays/ArrayOfGenericType.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ArrayOfGenericType { + T[] array; // OK + @SuppressWarnings("unchecked") + public ArrayOfGenericType(int size) { + // error: generic array creation: + //- array = new T[size]; + array = (T[])new Object[size]; // unchecked cast + } + // error: generic array creation: + //- public U[] makeArray() { return new U[10]; } +} diff --git a/code/arrays/ArrayOfGenerics.java b/code/arrays/ArrayOfGenerics.java new file mode 100644 index 00000000..79971d7a --- /dev/null +++ b/code/arrays/ArrayOfGenerics.java @@ -0,0 +1,33 @@ +// arrays/ArrayOfGenerics.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ArrayOfGenerics { + @SuppressWarnings("unchecked") + public static void main(String[] args) { + List[] ls; + List[] la = new List[10]; + ls = (List[])la; // Unchecked cast + ls[0] = new ArrayList<>(); + + //- ls[1] = new ArrayList(); + // error: incompatible types: ArrayList + // cannot be converted to List + // ls[1] = new ArrayList(); + // ^ + + // The problem: List is a subtype of Object + Object[] objects = ls; // So assignment is OK + // Compiles and runs without complaint: + objects[1] = new ArrayList<>(); + + // However, if your needs are straightforward it is + // possible to create an array of generics, albeit + // with an "unchecked cast" warning: + List[] spheres = + (List[])new List[10]; + Arrays.setAll(spheres, n -> new ArrayList<>()); + } +} diff --git a/code/arrays/ArrayOptions.java b/code/arrays/ArrayOptions.java new file mode 100644 index 00000000..bb6cbfbb --- /dev/null +++ b/code/arrays/ArrayOptions.java @@ -0,0 +1,79 @@ +// arrays/ArrayOptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Initialization & re-assignment of arrays +import java.util.*; +import static onjava.ArrayShow.*; + +public class ArrayOptions { + public static void main(String[] args) { + // Arrays of objects: + BerylliumSphere[] a; // Uninitialized local + BerylliumSphere[] b = new BerylliumSphere[5]; + + // The references inside the array are + // automatically initialized to null: + show("b", b); + BerylliumSphere[] c = new BerylliumSphere[4]; + for(int i = 0; i < c.length; i++) + if(c[i] == null) // Can test for null reference + c[i] = new BerylliumSphere(); + + // Aggregate initialization: + BerylliumSphere[] d = { + new BerylliumSphere(), + new BerylliumSphere(), + new BerylliumSphere() + }; + + // Dynamic aggregate initialization: + a = new BerylliumSphere[]{ + new BerylliumSphere(), new BerylliumSphere(), + }; + // (Trailing comma is optional) + + System.out.println("a.length = " + a.length); + System.out.println("b.length = " + b.length); + System.out.println("c.length = " + c.length); + System.out.println("d.length = " + d.length); + a = d; + System.out.println("a.length = " + a.length); + + // Arrays of primitives: + int[] e; // Null reference + int[] f = new int[5]; + + // The primitives inside the array are + // automatically initialized to zero: + show("f", f); + int[] g = new int[4]; + for(int i = 0; i < g.length; i++) + g[i] = i*i; + int[] h = { 11, 47, 93 }; + + // Compile error: variable e not initialized: + //- System.out.println("e.length = " + e.length); + System.out.println("f.length = " + f.length); + System.out.println("g.length = " + g.length); + System.out.println("h.length = " + h.length); + e = h; + System.out.println("e.length = " + e.length); + e = new int[]{ 1, 2 }; + System.out.println("e.length = " + e.length); + } +} +/* Output: +b: [null, null, null, null, null] +a.length = 2 +b.length = 5 +c.length = 4 +d.length = 3 +a.length = 3 +f: [0, 0, 0, 0, 0] +f.length = 5 +g.length = 4 +h.length = 3 +e.length = 3 +e.length = 2 +*/ diff --git a/code/arrays/ArraySearching.java b/code/arrays/ArraySearching.java new file mode 100644 index 00000000..fb4085e9 --- /dev/null +++ b/code/arrays/ArraySearching.java @@ -0,0 +1,33 @@ +// arrays/ArraySearching.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using Arrays.binarySearch() +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class ArraySearching { + public static void main(String[] args) { + Rand.Pint rand = new Rand.Pint(); + int[] a = new Rand.Pint().array(25); + Arrays.sort(a); + show("Sorted array", a); + while(true) { + int r = rand.getAsInt(); + int location = Arrays.binarySearch(a, r); + if(location >= 0) { + System.out.println( + "Location of " + r + " is " + location + + ", a[" + location + "] is " + a[location]); + break; // Out of while loop + } + } + } +} +/* Output: +Sorted array: [125, 267, 635, 650, 1131, 1506, 1634, +2400, 2766, 3063, 3768, 3941, 4720, 4762, 4948, 5070, +5682, 5807, 6177, 6193, 6656, 7021, 8479, 8737, 9954] +Location of 635 is 2, a[2] is 635 +*/ diff --git a/code/arrays/AssemblingMultidimensionalArrays.java b/code/arrays/AssemblingMultidimensionalArrays.java new file mode 100644 index 00000000..e79302b3 --- /dev/null +++ b/code/arrays/AssemblingMultidimensionalArrays.java @@ -0,0 +1,22 @@ +// arrays/AssemblingMultidimensionalArrays.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating multidimensional arrays +import java.util.*; + +public class AssemblingMultidimensionalArrays { + public static void main(String[] args) { + Integer[][] a; + a = new Integer[3][]; + for(int i = 0; i < a.length; i++) { + a[i] = new Integer[3]; + for(int j = 0; j < a[i].length; j++) + a[i][j] = i * j; // Autoboxing + } + System.out.println(Arrays.deepToString(a)); + } +} +/* Output: +[[0, 0, 0], [0, 1, 2], [0, 2, 4]] +*/ diff --git a/code/arrays/AutoboxingArrays.java b/code/arrays/AutoboxingArrays.java new file mode 100644 index 00000000..25b3a0e8 --- /dev/null +++ b/code/arrays/AutoboxingArrays.java @@ -0,0 +1,22 @@ +// arrays/AutoboxingArrays.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class AutoboxingArrays { + public static void main(String[] args) { + Integer[][] a = { // Autoboxing: + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, + { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }, + { 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 }, + { 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 }, + }; + System.out.println(Arrays.deepToString(a)); + } +} +/* Output: +[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [21, 22, 23, 24, 25, +26, 27, 28, 29, 30], [51, 52, 53, 54, 55, 56, 57, 58, +59, 60], [71, 72, 73, 74, 75, 76, 77, 78, 79, 80]] +*/ diff --git a/code/arrays/CollectionComparison.java b/code/arrays/CollectionComparison.java new file mode 100644 index 00000000..fc703c0a --- /dev/null +++ b/code/arrays/CollectionComparison.java @@ -0,0 +1,53 @@ +// arrays/CollectionComparison.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +class BerylliumSphere { + private static long counter; + private final long id = counter++; + @Override + public String toString() { + return "Sphere " + id; + } +} + +public class CollectionComparison { + public static void main(String[] args) { + BerylliumSphere[] spheres = + new BerylliumSphere[10]; + for(int i = 0; i < 5; i++) + spheres[i] = new BerylliumSphere(); + show(spheres); + System.out.println(spheres[4]); + + List sphereList = Suppliers.create( + ArrayList::new, BerylliumSphere::new, 5); + System.out.println(sphereList); + System.out.println(sphereList.get(4)); + + int[] integers = { 0, 1, 2, 3, 4, 5 }; + show(integers); + System.out.println(integers[4]); + + List intList = new ArrayList<>( + Arrays.asList(0, 1, 2, 3, 4, 5)); + intList.add(97); + System.out.println(intList); + System.out.println(intList.get(4)); + } +} +/* Output: +[Sphere 0, Sphere 1, Sphere 2, Sphere 3, Sphere 4, +null, null, null, null, null] +Sphere 4 +[Sphere 5, Sphere 6, Sphere 7, Sphere 8, Sphere 9] +Sphere 9 +[0, 1, 2, 3, 4, 5] +4 +[0, 1, 2, 3, 4, 5, 97] +4 +*/ diff --git a/code/arrays/CompType.java b/code/arrays/CompType.java new file mode 100644 index 00000000..621b33d1 --- /dev/null +++ b/code/arrays/CompType.java @@ -0,0 +1,56 @@ +// arrays/CompType.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Implementing Comparable in a class +import java.util.*; +import java.util.function.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class CompType implements Comparable { + int i; + int j; + private static int count = 1; + public CompType(int n1, int n2) { + i = n1; + j = n2; + } + @Override + public String toString() { + String result = "[i = " + i + ", j = " + j + "]"; + if(count++ % 3 == 0) + result += "\n"; + return result; + } + @Override + public int compareTo(CompType rv) { + return (i < rv.i ? -1 : (i == rv.i ? 0 : 1)); + } + private static SplittableRandom r = + new SplittableRandom(47); + public static CompType get() { + return new CompType(r.nextInt(100), r.nextInt(100)); + } + public static void main(String[] args) { + CompType[] a = new CompType[12]; + Arrays.setAll(a, n -> get()); + show("Before sorting", a); + Arrays.sort(a); + show("After sorting", a); + } +} +/* Output: +Before sorting: [[i = 35, j = 37], [i = 41, j = 20], [i += 77, j = 79] +, [i = 56, j = 68], [i = 48, j = 93], [i = 70, j = 7] +, [i = 0, j = 25], [i = 62, j = 34], [i = 50, j = 82] +, [i = 31, j = 67], [i = 66, j = 54], [i = 21, j = 6] +] +After sorting: [[i = 0, j = 25], [i = 21, j = 6], [i = +31, j = 67] +, [i = 35, j = 37], [i = 41, j = 20], [i = 48, j = 93] +, [i = 50, j = 82], [i = 56, j = 68], [i = 62, j = 34] +, [i = 66, j = 54], [i = 70, j = 7], [i = 77, j = 79] +] +*/ diff --git a/code/arrays/ComparatorTest.java b/code/arrays/ComparatorTest.java new file mode 100644 index 00000000..68f7e380 --- /dev/null +++ b/code/arrays/ComparatorTest.java @@ -0,0 +1,39 @@ +// arrays/ComparatorTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Implementing a Comparator for a class +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +class CompTypeComparator +implements Comparator { + public int compare(CompType o1, CompType o2) { + return (o1.j < o2.j ? -1 : (o1.j == o2.j ? 0 : 1)); + } +} + +public class ComparatorTest { + public static void main(String[] args) { + CompType[] a = new CompType[12]; + Arrays.setAll(a, n -> CompType.get()); + show("Before sorting", a); + Arrays.sort(a, new CompTypeComparator()); + show("After sorting", a); + } +} +/* Output: +Before sorting: [[i = 35, j = 37], [i = 41, j = 20], [i += 77, j = 79] +, [i = 56, j = 68], [i = 48, j = 93], [i = 70, j = 7] +, [i = 0, j = 25], [i = 62, j = 34], [i = 50, j = 82] +, [i = 31, j = 67], [i = 66, j = 54], [i = 21, j = 6] +] +After sorting: [[i = 21, j = 6], [i = 70, j = 7], [i = +41, j = 20] +, [i = 0, j = 25], [i = 62, j = 34], [i = 35, j = 37] +, [i = 66, j = 54], [i = 31, j = 67], [i = 56, j = 68] +, [i = 77, j = 79], [i = 50, j = 82], [i = 48, j = 93] +] +*/ diff --git a/code/arrays/ComparingArrays.java b/code/arrays/ComparingArrays.java new file mode 100644 index 00000000..9ddad69d --- /dev/null +++ b/code/arrays/ComparingArrays.java @@ -0,0 +1,62 @@ +// arrays/ComparingArrays.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using Arrays.equals() +import java.util.*; +import onjava.*; + +public class ComparingArrays { + public static final int SZ = 15; + static String[][] twoDArray() { + String[][] md = new String[5][]; + Arrays.setAll(md, n -> new String[n]); + for(int i = 0; i < md.length; i++) + Arrays.setAll(md[i], new Rand.String()::get); + return md; + } + public static void main(String[] args) { + int[] a1 = new int[SZ], a2 = new int[SZ]; + Arrays.setAll(a1, new Count.Integer()::get); + Arrays.setAll(a2, new Count.Integer()::get); + System.out.println( + "a1 == a2: " + Arrays.equals(a1, a2)); + a2[3] = 11; + System.out.println( + "a1 == a2: " + Arrays.equals(a1, a2)); + + Integer[] a1w = new Integer[SZ], + a2w = new Integer[SZ]; + Arrays.setAll(a1w, new Count.Integer()::get); + Arrays.setAll(a2w, new Count.Integer()::get); + System.out.println( + "a1w == a2w: " + Arrays.equals(a1w, a2w)); + a2w[3] = 11; + System.out.println( + "a1w == a2w: " + Arrays.equals(a1w, a2w)); + + String[][] md1 = twoDArray(), md2 = twoDArray(); + System.out.println(Arrays.deepToString(md1)); + System.out.println("deepEquals(md1, md2): " + + Arrays.deepEquals(md1, md2)); + System.out.println( + "md1 == md2: " + Arrays.equals(md1, md2)); + md1[4][1] = "#$#$#$#"; + System.out.println(Arrays.deepToString(md1)); + System.out.println("deepEquals(md1, md2): " + + Arrays.deepEquals(md1, md2)); + } +} +/* Output: +a1 == a2: true +a1 == a2: false +a1w == a2w: true +a1w == a2w: false +[[], [btpenpc], [btpenpc, cuxszgv], [btpenpc, cuxszgv, +gmeinne], [btpenpc, cuxszgv, gmeinne, eloztdv]] +deepEquals(md1, md2): true +md1 == md2: false +[[], [btpenpc], [btpenpc, cuxszgv], [btpenpc, cuxszgv, +gmeinne], [btpenpc, #$#$#$#, gmeinne, eloztdv]] +deepEquals(md1, md2): false +*/ diff --git a/code/arrays/CountUpward.java b/code/arrays/CountUpward.java new file mode 100644 index 00000000..bbeb02ba --- /dev/null +++ b/code/arrays/CountUpward.java @@ -0,0 +1,24 @@ +// arrays/CountUpward.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import static onjava.ArrayShow.*; + +public class CountUpward { + static long[] fillCounted(int size) { + return LongStream.iterate(0, i -> i + 1) + .limit(size).toArray(); + } + public static void main(String[] args) { + long[] l1 = fillCounted(20); // No problem + show(l1); + // On my machine, this runs out of heap space: + //- long[] l2 = fillCounted(10_000_000); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19] +*/ diff --git a/code/arrays/FillingArrays.java b/code/arrays/FillingArrays.java new file mode 100644 index 00000000..df54e62f --- /dev/null +++ b/code/arrays/FillingArrays.java @@ -0,0 +1,55 @@ +// arrays/FillingArrays.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using Arrays.fill() +import java.util.*; +import static onjava.ArrayShow.*; + +public class FillingArrays { + public static void main(String[] args) { + int size = 6; + boolean[] a1 = new boolean[size]; + byte[] a2 = new byte[size]; + char[] a3 = new char[size]; + short[] a4 = new short[size]; + int[] a5 = new int[size]; + long[] a6 = new long[size]; + float[] a7 = new float[size]; + double[] a8 = new double[size]; + String[] a9 = new String[size]; + Arrays.fill(a1, true); + show("a1", a1); + Arrays.fill(a2, (byte)11); + show("a2", a2); + Arrays.fill(a3, 'x'); + show("a3", a3); + Arrays.fill(a4, (short)17); + show("a4", a4); + Arrays.fill(a5, 19); + show("a5", a5); + Arrays.fill(a6, 23); + show("a6", a6); + Arrays.fill(a7, 29); + show("a7", a7); + Arrays.fill(a8, 47); + show("a8", a8); + Arrays.fill(a9, "Hello"); + show("a9", a9); + // Manipulating ranges: + Arrays.fill(a9, 3, 5, "World"); + show("a9", a9); + } +} +/* Output: +a1: [true, true, true, true, true, true] +a2: [11, 11, 11, 11, 11, 11] +a3: [x, x, x, x, x, x] +a4: [17, 17, 17, 17, 17, 17] +a5: [19, 19, 19, 19, 19, 19] +a6: [23, 23, 23, 23, 23, 23] +a7: [29.0, 29.0, 29.0, 29.0, 29.0, 29.0] +a8: [47.0, 47.0, 47.0, 47.0, 47.0, 47.0] +a9: [Hello, Hello, Hello, Hello, Hello, Hello] +a9: [Hello, Hello, Hello, World, World, Hello] +*/ diff --git a/code/arrays/IceCreamFlavors.java b/code/arrays/IceCreamFlavors.java new file mode 100644 index 00000000..5e9d2b61 --- /dev/null +++ b/code/arrays/IceCreamFlavors.java @@ -0,0 +1,45 @@ +// arrays/IceCreamFlavors.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Returning arrays from methods +import java.util.*; +import static onjava.ArrayShow.*; + +public class IceCreamFlavors { + private static SplittableRandom rand = + new SplittableRandom(47); + static final String[] FLAVORS = { + "Chocolate", "Strawberry", "Vanilla Fudge Swirl", + "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", + "Praline Cream", "Mud Pie" + }; + public static String[] flavorSet(int n) { + if(n > FLAVORS.length) + throw new IllegalArgumentException("Set too big"); + String[] results = new String[n]; + boolean[] picked = new boolean[FLAVORS.length]; + for(int i = 0; i < n; i++) { + int t; + do + t = rand.nextInt(FLAVORS.length); + while(picked[t]); + results[i] = FLAVORS[t]; + picked[t] = true; + } + return results; + } + public static void main(String[] args) { + for(int i = 0; i < 7; i++) + show(flavorSet(3)); + } +} +/* Output: +[Praline Cream, Mint Chip, Vanilla Fudge Swirl] +[Strawberry, Vanilla Fudge Swirl, Mud Pie] +[Chocolate, Strawberry, Vanilla Fudge Swirl] +[Rum Raisin, Praline Cream, Chocolate] +[Mint Chip, Rum Raisin, Mocha Almond Fudge] +[Mocha Almond Fudge, Mud Pie, Vanilla Fudge Swirl] +[Mocha Almond Fudge, Mud Pie, Mint Chip] +*/ diff --git a/code/arrays/ModifyExisting.java b/code/arrays/ModifyExisting.java new file mode 100644 index 00000000..d74df78e --- /dev/null +++ b/code/arrays/ModifyExisting.java @@ -0,0 +1,22 @@ +// arrays/ModifyExisting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class ModifyExisting { + public static void main(String[] args) { + double[] da = new double[7]; + Arrays.setAll(da, new Rand.Double()::get); + show(da); + Arrays.setAll(da, n -> da[n] / 100); // [1] + show(da); + } +} +/* Output: +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99] +[0.0483, 0.028900000000000002, 0.028999999999999998, +0.0197, 0.0301, 0.0018, 0.009899999999999999] +*/ diff --git a/code/arrays/MultiDimWrapperArray.java b/code/arrays/MultiDimWrapperArray.java new file mode 100644 index 00000000..1185d0f9 --- /dev/null +++ b/code/arrays/MultiDimWrapperArray.java @@ -0,0 +1,38 @@ +// arrays/MultiDimWrapperArray.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Multidimensional arrays of "wrapper" objects +import java.util.*; + +public class MultiDimWrapperArray { + public static void main(String[] args) { + Integer[][] a1 = { // Autoboxing + { 1, 2, 3, }, + { 4, 5, 6, }, + }; + Double[][][] a2 = { // Autoboxing + { { 1.1, 2.2 }, { 3.3, 4.4 } }, + { { 5.5, 6.6 }, { 7.7, 8.8 } }, + { { 9.9, 1.2 }, { 2.3, 3.4 } }, + }; + String[][] a3 = { + { "The", "Quick", "Sly", "Fox" }, + { "Jumped", "Over" }, + { "The", "Lazy", "Brown", "Dog", "&", "friend" }, + }; + System.out.println( + "a1: " + Arrays.deepToString(a1)); + System.out.println( + "a2: " + Arrays.deepToString(a2)); + System.out.println( + "a3: " + Arrays.deepToString(a3)); + } +} +/* Output: +a1: [[1, 2, 3], [4, 5, 6]] +a2: [[[1.1, 2.2], [3.3, 4.4]], [[5.5, 6.6], [7.7, +8.8]], [[9.9, 1.2], [2.3, 3.4]]] +a3: [[The, Quick, Sly, Fox], [Jumped, Over], [The, +Lazy, Brown, Dog, &, friend]] +*/ diff --git a/code/arrays/MultidimensionalObjectArrays.java b/code/arrays/MultidimensionalObjectArrays.java new file mode 100644 index 00000000..998e7c99 --- /dev/null +++ b/code/arrays/MultidimensionalObjectArrays.java @@ -0,0 +1,25 @@ +// arrays/MultidimensionalObjectArrays.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class MultidimensionalObjectArrays { + public static void main(String[] args) { + BerylliumSphere[][] spheres = { + { new BerylliumSphere(), new BerylliumSphere() }, + { new BerylliumSphere(), new BerylliumSphere(), + new BerylliumSphere(), new BerylliumSphere() }, + { new BerylliumSphere(), new BerylliumSphere(), + new BerylliumSphere(), new BerylliumSphere(), + new BerylliumSphere(), new BerylliumSphere(), + new BerylliumSphere(), new BerylliumSphere() }, + }; + System.out.println(Arrays.deepToString(spheres)); + } +} +/* Output: +[[Sphere 0, Sphere 1], [Sphere 2, Sphere 3, Sphere 4, +Sphere 5], [Sphere 6, Sphere 7, Sphere 8, Sphere 9, +Sphere 10, Sphere 11, Sphere 12, Sphere 13]] +*/ diff --git a/code/arrays/MultidimensionalPrimitiveArray.java b/code/arrays/MultidimensionalPrimitiveArray.java new file mode 100644 index 00000000..8ed5884f --- /dev/null +++ b/code/arrays/MultidimensionalPrimitiveArray.java @@ -0,0 +1,18 @@ +// arrays/MultidimensionalPrimitiveArray.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class MultidimensionalPrimitiveArray { + public static void main(String[] args) { + int[][] a = { + { 1, 2, 3, }, + { 4, 5, 6, }, + }; + System.out.println(Arrays.deepToString(a)); + } +} +/* Output: +[[1, 2, 3], [4, 5, 6]] +*/ diff --git a/code/arrays/ParallelPrefix1.java b/code/arrays/ParallelPrefix1.java new file mode 100644 index 00000000..e180d019 --- /dev/null +++ b/code/arrays/ParallelPrefix1.java @@ -0,0 +1,27 @@ +// arrays/ParallelPrefix1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class ParallelPrefix1 { + public static void main(String[] args) { + int[] nums = new Count.Pint().array(10); + show(nums); + System.out.println(Arrays.stream(nums) + .reduce(Integer::sum).getAsInt()); + Arrays.parallelPrefix(nums, Integer::sum); + show(nums); + System.out.println(Arrays.stream( + new Count.Pint().array(6)) + .reduce(Integer::sum).getAsInt()); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +45 +[0, 1, 3, 6, 10, 15, 21, 28, 36, 45] +15 +*/ diff --git a/code/arrays/ParallelPrefix2.java b/code/arrays/ParallelPrefix2.java new file mode 100644 index 00000000..5288d3ce --- /dev/null +++ b/code/arrays/ParallelPrefix2.java @@ -0,0 +1,20 @@ +// arrays/ParallelPrefix2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class ParallelPrefix2 { + public static void main(String[] args) { + String[] strings = new Rand.String(1).array(8); + show(strings); + Arrays.parallelPrefix(strings, (a, b) -> a + b); + show(strings); + } +} +/* Output: +[b, t, p, e, n, p, c, c] +[b, bt, btp, btpe, btpen, btpenp, btpenpc, btpenpcc] +*/ diff --git a/code/arrays/ParallelPrefix3.java b/code/arrays/ParallelPrefix3.java new file mode 100644 index 00000000..ed2751dc --- /dev/null +++ b/code/arrays/ParallelPrefix3.java @@ -0,0 +1,23 @@ +// arrays/ParallelPrefix3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromTravisCI} +import java.util.*; + +public class ParallelPrefix3 { + static final int SIZE = 10_000_000; + public static void main(String[] args) { + long[] nums = new long[SIZE]; + Arrays.setAll(nums, n -> n); + Arrays.parallelPrefix(nums, Long::sum); + System.out.println("First 20: " + nums[19]); + System.out.println("First 200: " + nums[199]); + System.out.println("All: " + nums[nums.length-1]); + } +} +/* Output: +First 20: 190 +First 200: 19900 +All: 49999995000000 +*/ diff --git a/code/arrays/ParallelSetAll.java b/code/arrays/ParallelSetAll.java new file mode 100644 index 00000000..f6c47ff5 --- /dev/null +++ b/code/arrays/ParallelSetAll.java @@ -0,0 +1,24 @@ +// arrays/ParallelSetAll.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.*; + +public class ParallelSetAll { + static final int SIZE = 10_000_000; + static void intArray() { + int[] ia = new int[SIZE]; + Arrays.setAll(ia, new Rand.Pint()::get); + Arrays.parallelSetAll(ia, new Rand.Pint()::get); + } + static void longArray() { + long[] la = new long[SIZE]; + Arrays.setAll(la, new Rand.Plong()::get); + Arrays.parallelSetAll(la, new Rand.Plong()::get); + } + public static void main(String[] args) { + intArray(); + longArray(); + } +} diff --git a/code/arrays/ParameterizedArrayType.java b/code/arrays/ParameterizedArrayType.java new file mode 100644 index 00000000..06c1021c --- /dev/null +++ b/code/arrays/ParameterizedArrayType.java @@ -0,0 +1,25 @@ +// arrays/ParameterizedArrayType.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class ClassParameter { + public T[] f(T[] arg) { return arg; } +} + +class MethodParameter { + public static T[] f(T[] arg) { return arg; } +} + +public class ParameterizedArrayType { + public static void main(String[] args) { + Integer[] ints = { 1, 2, 3, 4, 5 }; + Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 }; + Integer[] ints2 = + new ClassParameter().f(ints); + Double[] doubles2 = + new ClassParameter().f(doubles); + ints2 = MethodParameter.f(ints); + doubles2 = MethodParameter.f(doubles); + } +} diff --git a/code/arrays/PythonLists.py b/code/arrays/PythonLists.py new file mode 100644 index 00000000..910daf18 --- /dev/null +++ b/code/arrays/PythonLists.py @@ -0,0 +1,36 @@ +# arrays/PythonLists.py +# (c)2020 MindView LLC: see Copyright.txt +# We make no guarantees that this code is fit for any purpose. +# Visit http://OnJava8.com for more book information. + +aList = [1, 2, 3, 4, 5] +print(type(aList)) # +print(aList) # [1, 2, 3, 4, 5] +print(aList[4]) # 5 Basic list indexing +aList.append(6) # lists can be resized +aList += [7, 8] # Add a list to a list +print(aList) # [1, 2, 3, 4, 5, 6, 7, 8] +aSlice = aList[2:4] +print(aSlice) # [3, 4] + +class MyList(list): # Inherit from list + # Define a method; 'this' pointer is explicit: + def getReversed(self): + reversed = self[:] # Copy list using slices + reversed.reverse() # Built-in list method + return reversed + +# No 'new' necessary for object creation: +list2 = MyList(aList) +print(type(list2)) # +print(list2.getReversed()) # [8, 7, 6, 5, 4, 3, 2, 1] + +output = """ + +[1, 2, 3, 4, 5] +5 +[1, 2, 3, 4, 5, 6, 7, 8] +[3, 4] + +[8, 7, 6, 5, 4, 3, 2, 1] +""" diff --git a/code/arrays/RaggedArray.java b/code/arrays/RaggedArray.java new file mode 100644 index 00000000..bd7d625b --- /dev/null +++ b/code/arrays/RaggedArray.java @@ -0,0 +1,26 @@ +// arrays/RaggedArray.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class RaggedArray { + static int val = 1; + public static void main(String[] args) { + SplittableRandom rand = new SplittableRandom(47); + // 3-D array with varied-length vectors: + int[][][] a = new int[rand.nextInt(7)][][]; + for(int i = 0; i < a.length; i++) { + a[i] = new int[rand.nextInt(5)][]; + for(int j = 0; j < a[i].length; j++) { + a[i][j] = new int[rand.nextInt(5)]; + Arrays.setAll(a[i][j], n -> val++); // [1] + } + } + System.out.println(Arrays.deepToString(a)); + } +} +/* Output: +[[[1], []], [[2, 3, 4, 5], [6]], [[7, 8, 9], [10, 11, +12], []]] +*/ diff --git a/code/arrays/Reverse.java b/code/arrays/Reverse.java new file mode 100644 index 00000000..9a7de678 --- /dev/null +++ b/code/arrays/Reverse.java @@ -0,0 +1,32 @@ +// arrays/Reverse.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The Collections.reverseOrder() Comparator +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class Reverse { + public static void main(String[] args) { + CompType[] a = new CompType[12]; + Arrays.setAll(a, n -> CompType.get()); + show("Before sorting", a); + Arrays.sort(a, Collections.reverseOrder()); + show("After sorting", a); + } +} +/* Output: +Before sorting: [[i = 35, j = 37], [i = 41, j = 20], [i += 77, j = 79] +, [i = 56, j = 68], [i = 48, j = 93], [i = 70, j = 7] +, [i = 0, j = 25], [i = 62, j = 34], [i = 50, j = 82] +, [i = 31, j = 67], [i = 66, j = 54], [i = 21, j = 6] +] +After sorting: [[i = 77, j = 79], [i = 70, j = 7], [i = +66, j = 54] +, [i = 62, j = 34], [i = 56, j = 68], [i = 50, j = 82] +, [i = 48, j = 93], [i = 41, j = 20], [i = 35, j = 37] +, [i = 31, j = 67], [i = 21, j = 6], [i = 0, j = 25] +] +*/ diff --git a/code/arrays/SimpleSetAll.java b/code/arrays/SimpleSetAll.java new file mode 100644 index 00000000..70336e79 --- /dev/null +++ b/code/arrays/SimpleSetAll.java @@ -0,0 +1,56 @@ +// arrays/SimpleSetAll.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import static onjava.ArrayShow.*; + +class Bob { + final int id; + Bob(int n) { id = n; } + @Override + public String toString() { return "Bob" + id; } +} + +public class SimpleSetAll { + public static final int SZ = 8; + static int val = 1; + static char[] chars = "abcdefghijklmnopqrstuvwxyz" + .toCharArray(); + static char getChar(int n) { return chars[n]; } + public static void main(String[] args) { + int[] ia = new int[SZ]; + long[] la = new long[SZ]; + double[] da = new double[SZ]; + Arrays.setAll(ia, n -> n); // [1] + Arrays.setAll(la, n -> n); + Arrays.setAll(da, n -> n); + show(ia); + show(la); + show(da); + Arrays.setAll(ia, n -> val++); // [2] + Arrays.setAll(la, n -> val++); + Arrays.setAll(da, n -> val++); + show(ia); + show(la); + show(da); + + Bob[] ba = new Bob[SZ]; + Arrays.setAll(ba, Bob::new); // [3] + show(ba); + + Character[] ca = new Character[SZ]; + Arrays.setAll(ca, SimpleSetAll::getChar); // [4] + show(ca); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7] +[0, 1, 2, 3, 4, 5, 6, 7] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] +[1, 2, 3, 4, 5, 6, 7, 8] +[9, 10, 11, 12, 13, 14, 15, 16] +[17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0] +[Bob0, Bob1, Bob2, Bob3, Bob4, Bob5, Bob6, Bob7] +[a, b, c, d, e, f, g, h] +*/ diff --git a/code/arrays/StreamFromArray.java b/code/arrays/StreamFromArray.java new file mode 100644 index 00000000..69628703 --- /dev/null +++ b/code/arrays/StreamFromArray.java @@ -0,0 +1,51 @@ +// arrays/StreamFromArray.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.*; + +public class StreamFromArray { + public static void main(String[] args) { + String[] s = new Rand.String().array(10); + Arrays.stream(s) + .skip(3) + .limit(5) + .map(ss -> ss + "!") + .forEach(System.out::println); + + int[] ia = new Rand.Pint().array(10); + Arrays.stream(ia) + .skip(3) + .limit(5) + .map(i -> i * 10) + .forEach(System.out::println); + + Arrays.stream(new long[10]); + Arrays.stream(new double[10]); + + // Only int, long and double work: + //- Arrays.stream(new boolean[10]); + //- Arrays.stream(new byte[10]); + //- Arrays.stream(new char[10]); + //- Arrays.stream(new short[10]); + //- Arrays.stream(new float[10]); + + // For the other types you must use wrapped arrays: + float[] fa = new Rand.Pfloat().array(10); + Arrays.stream(ConvertTo.boxed(fa)); + Arrays.stream(new Rand.Float().array(10)); + } +} +/* Output: +eloztdv! +ewcippc! +ygpoalk! +ljlbynx! +taprwxz! +47200 +61770 +84790 +66560 +37680 +*/ diff --git a/code/arrays/StringSorting.java b/code/arrays/StringSorting.java new file mode 100644 index 00000000..0da5c733 --- /dev/null +++ b/code/arrays/StringSorting.java @@ -0,0 +1,39 @@ +// arrays/StringSorting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Sorting an array of Strings +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class StringSorting { + public static void main(String[] args) { + String[] sa = new Rand.String().array(20); + show("Before sort", sa); + Arrays.sort(sa); + show("After sort", sa); + Arrays.sort(sa, Collections.reverseOrder()); + show("Reverse sort", sa); + Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER); + show("Case-insensitive sort", sa); + } +} +/* Output: +Before sort: [btpenpc, cuxszgv, gmeinne, eloztdv, +ewcippc, ygpoalk, ljlbynx, taprwxz, bhmupju, cjwzmmr, +anmkkyh, fcjpthl, skddcat, jbvlgwc, mvducuj, ydpulcq, +zehpfmm, zrxmclh, qgekgly, hyoubzl] +After sort: [anmkkyh, bhmupju, btpenpc, cjwzmmr, +cuxszgv, eloztdv, ewcippc, fcjpthl, gmeinne, hyoubzl, +jbvlgwc, ljlbynx, mvducuj, qgekgly, skddcat, taprwxz, +ydpulcq, ygpoalk, zehpfmm, zrxmclh] +Reverse sort: [zrxmclh, zehpfmm, ygpoalk, ydpulcq, +taprwxz, skddcat, qgekgly, mvducuj, ljlbynx, jbvlgwc, +hyoubzl, gmeinne, fcjpthl, ewcippc, eloztdv, cuxszgv, +cjwzmmr, btpenpc, bhmupju, anmkkyh] +Case-insensitive sort: [anmkkyh, bhmupju, btpenpc, +cjwzmmr, cuxszgv, eloztdv, ewcippc, fcjpthl, gmeinne, +hyoubzl, jbvlgwc, ljlbynx, mvducuj, qgekgly, skddcat, +taprwxz, ydpulcq, ygpoalk, zehpfmm, zrxmclh] +*/ diff --git a/code/arrays/TestConvertTo.java b/code/arrays/TestConvertTo.java new file mode 100644 index 00000000..8ecb72a6 --- /dev/null +++ b/code/arrays/TestConvertTo.java @@ -0,0 +1,87 @@ +// arrays/TestConvertTo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.*; +import static onjava.ArrayShow.*; +import static onjava.ConvertTo.*; + +public class TestConvertTo { + static final int SIZE = 6; + public static void main(String[] args) { + Boolean[] a1 = new Boolean[SIZE]; + Arrays.setAll(a1, new Rand.Boolean()::get); + boolean[] a1p = primitive(a1); + show("a1p", a1p); + Boolean[] a1b = boxed(a1p); + show("a1b", a1b); + + Byte[] a2 = new Byte[SIZE]; + Arrays.setAll(a2, new Rand.Byte()::get); + byte[] a2p = primitive(a2); + show("a2p", a2p); + Byte[] a2b = boxed(a2p); + show("a2b", a2b); + + Character[] a3 = new Character[SIZE]; + Arrays.setAll(a3, new Rand.Character()::get); + char[] a3p = primitive(a3); + show("a3p", a3p); + Character[] a3b = boxed(a3p); + show("a3b", a3b); + + Short[] a4 = new Short[SIZE]; + Arrays.setAll(a4, new Rand.Short()::get); + short[] a4p = primitive(a4); + show("a4p", a4p); + Short[] a4b = boxed(a4p); + show("a4b", a4b); + + Integer[] a5 = new Integer[SIZE]; + Arrays.setAll(a5, new Rand.Integer()::get); + int[] a5p = primitive(a5); + show("a5p", a5p); + Integer[] a5b = boxed(a5p); + show("a5b", a5b); + + Long[] a6 = new Long[SIZE]; + Arrays.setAll(a6, new Rand.Long()::get); + long[] a6p = primitive(a6); + show("a6p", a6p); + Long[] a6b = boxed(a6p); + show("a6b", a6b); + + Float[] a7 = new Float[SIZE]; + Arrays.setAll(a7, new Rand.Float()::get); + float[] a7p = primitive(a7); + show("a7p", a7p); + Float[] a7b = boxed(a7p); + show("a7b", a7b); + + Double[] a8 = new Double[SIZE]; + Arrays.setAll(a8, new Rand.Double()::get); + double[] a8p = primitive(a8); + show("a8p", a8p); + Double[] a8b = boxed(a8p); + show("a8b", a8b); + } +} +/* Output: +a1p: [true, false, true, true, true, false] +a1b: [true, false, true, true, true, false] +a2p: [123, 33, 101, 112, 33, 31] +a2b: [123, 33, 101, 112, 33, 31] +a3p: [b, t, p, e, n, p] +a3b: [b, t, p, e, n, p] +a4p: [635, 8737, 3941, 4720, 6177, 8479] +a4b: [635, 8737, 3941, 4720, 6177, 8479] +a5p: [635, 8737, 3941, 4720, 6177, 8479] +a5b: [635, 8737, 3941, 4720, 6177, 8479] +a6p: [6882, 3765, 692, 9575, 4439, 2638] +a6b: [6882, 3765, 692, 9575, 4439, 2638] +a7p: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] +a7b: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] +a8p: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] +a8b: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] +*/ diff --git a/code/arrays/TestCount.java b/code/arrays/TestCount.java new file mode 100644 index 00000000..a77e00f7 --- /dev/null +++ b/code/arrays/TestCount.java @@ -0,0 +1,167 @@ +// arrays/TestCount.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Test counting generators +import java.util.*; +import java.util.stream.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class TestCount { + static final int SZ = 5; + public static void main(String[] args) { + System.out.println("Boolean"); + Boolean[] a1 = new Boolean[SZ]; + Arrays.setAll(a1, new Count.Boolean()::get); + show(a1); + a1 = Stream.generate(new Count.Boolean()) + .limit(SZ + 1).toArray(Boolean[]::new); + show(a1); + a1 = new Count.Boolean().array(SZ + 2); + show(a1); + boolean[] a1b = + new Count.Pboolean().array(SZ + 3); + show(a1b); + + System.out.println("Byte"); + Byte[] a2 = new Byte[SZ]; + Arrays.setAll(a2, new Count.Byte()::get); + show(a2); + a2 = Stream.generate(new Count.Byte()) + .limit(SZ + 1).toArray(Byte[]::new); + show(a2); + a2 = new Count.Byte().array(SZ + 2); + show(a2); + byte[] a2b = new Count.Pbyte().array(SZ + 3); + show(a2b); + + System.out.println("Character"); + Character[] a3 = new Character[SZ]; + Arrays.setAll(a3, new Count.Character()::get); + show(a3); + a3 = Stream.generate(new Count.Character()) + .limit(SZ + 1).toArray(Character[]::new); + show(a3); + a3 = new Count.Character().array(SZ + 2); + show(a3); + char[] a3b = new Count.Pchar().array(SZ + 3); + show(a3b); + + System.out.println("Short"); + Short[] a4 = new Short[SZ]; + Arrays.setAll(a4, new Count.Short()::get); + show(a4); + a4 = Stream.generate(new Count.Short()) + .limit(SZ + 1).toArray(Short[]::new); + show(a4); + a4 = new Count.Short().array(SZ + 2); + show(a4); + short[] a4b = new Count.Pshort().array(SZ + 3); + show(a4b); + + System.out.println("Integer"); + int[] a5 = new int[SZ]; + Arrays.setAll(a5, new Count.Integer()::get); + show(a5); + Integer[] a5b = + Stream.generate(new Count.Integer()) + .limit(SZ + 1).toArray(Integer[]::new); + show(a5b); + a5b = new Count.Integer().array(SZ + 2); + show(a5b); + a5 = IntStream.generate(new Count.Pint()) + .limit(SZ + 1).toArray(); + show(a5); + a5 = new Count.Pint().array(SZ + 3); + show(a5); + + System.out.println("Long"); + long[] a6 = new long[SZ]; + Arrays.setAll(a6, new Count.Long()::get); + show(a6); + Long[] a6b = Stream.generate(new Count.Long()) + .limit(SZ + 1).toArray(Long[]::new); + show(a6b); + a6b = new Count.Long().array(SZ + 2); + show(a6b); + a6 = LongStream.generate(new Count.Plong()) + .limit(SZ + 1).toArray(); + show(a6); + a6 = new Count.Plong().array(SZ + 3); + show(a6); + + System.out.println("Float"); + Float[] a7 = new Float[SZ]; + Arrays.setAll(a7, new Count.Float()::get); + show(a7); + a7 = Stream.generate(new Count.Float()) + .limit(SZ + 1).toArray(Float[]::new); + show(a7); + a7 = new Count.Float().array(SZ + 2); + show(a7); + float[] a7b = new Count.Pfloat().array(SZ + 3); + show(a7b); + + System.out.println("Double"); + double[] a8 = new double[SZ]; + Arrays.setAll(a8, new Count.Double()::get); + show(a8); + Double[] a8b = + Stream.generate(new Count.Double()) + .limit(SZ + 1).toArray(Double[]::new); + show(a8b); + a8b = new Count.Double().array(SZ + 2); + show(a8b); + a8 = DoubleStream.generate(new Count.Pdouble()) + .limit(SZ + 1).toArray(); + show(a8); + a8 = new Count.Pdouble().array(SZ + 3); + show(a8); + } +} +/* Output: +Boolean +[false, true, false, true, false] +[false, true, false, true, false, true] +[false, true, false, true, false, true, false] +[false, true, false, true, false, true, false, true] +Byte +[0, 1, 2, 3, 4] +[0, 1, 2, 3, 4, 5] +[0, 1, 2, 3, 4, 5, 6] +[0, 1, 2, 3, 4, 5, 6, 7] +Character +[b, c, d, e, f] +[b, c, d, e, f, g] +[b, c, d, e, f, g, h] +[b, c, d, e, f, g, h, i] +Short +[0, 1, 2, 3, 4] +[0, 1, 2, 3, 4, 5] +[0, 1, 2, 3, 4, 5, 6] +[0, 1, 2, 3, 4, 5, 6, 7] +Integer +[0, 1, 2, 3, 4] +[0, 1, 2, 3, 4, 5] +[0, 1, 2, 3, 4, 5, 6] +[0, 1, 2, 3, 4, 5] +[0, 1, 2, 3, 4, 5, 6, 7] +Long +[0, 1, 2, 3, 4] +[0, 1, 2, 3, 4, 5] +[0, 1, 2, 3, 4, 5, 6] +[0, 1, 2, 3, 4, 5] +[0, 1, 2, 3, 4, 5, 6, 7] +Float +[0.0, 1.0, 2.0, 3.0, 4.0] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] +Double +[0.0, 1.0, 2.0, 3.0, 4.0] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0] +[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] +*/ diff --git a/code/arrays/TestRand.java b/code/arrays/TestRand.java new file mode 100644 index 00000000..17e0718f --- /dev/null +++ b/code/arrays/TestRand.java @@ -0,0 +1,192 @@ +// arrays/TestRand.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Test random generators +import java.util.*; +import java.util.stream.*; +import onjava.*; +import static onjava.ArrayShow.*; + +public class TestRand { + static final int SZ = 5; + public static void main(String[] args) { + System.out.println("Boolean"); + Boolean[] a1 = new Boolean[SZ]; + Arrays.setAll(a1, new Rand.Boolean()::get); + show(a1); + a1 = Stream.generate(new Rand.Boolean()) + .limit(SZ + 1).toArray(Boolean[]::new); + show(a1); + a1 = new Rand.Boolean().array(SZ + 2); + show(a1); + boolean[] a1b = + new Rand.Pboolean().array(SZ + 3); + show(a1b); + + System.out.println("Byte"); + Byte[] a2 = new Byte[SZ]; + Arrays.setAll(a2, new Rand.Byte()::get); + show(a2); + a2 = Stream.generate(new Rand.Byte()) + .limit(SZ + 1).toArray(Byte[]::new); + show(a2); + a2 = new Rand.Byte().array(SZ + 2); + show(a2); + byte[] a2b = new Rand.Pbyte().array(SZ + 3); + show(a2b); + + System.out.println("Character"); + Character[] a3 = new Character[SZ]; + Arrays.setAll(a3, new Rand.Character()::get); + show(a3); + a3 = Stream.generate(new Rand.Character()) + .limit(SZ + 1).toArray(Character[]::new); + show(a3); + a3 = new Rand.Character().array(SZ + 2); + show(a3); + char[] a3b = new Rand.Pchar().array(SZ + 3); + show(a3b); + + System.out.println("Short"); + Short[] a4 = new Short[SZ]; + Arrays.setAll(a4, new Rand.Short()::get); + show(a4); + a4 = Stream.generate(new Rand.Short()) + .limit(SZ + 1).toArray(Short[]::new); + show(a4); + a4 = new Rand.Short().array(SZ + 2); + show(a4); + short[] a4b = new Rand.Pshort().array(SZ + 3); + show(a4b); + + System.out.println("Integer"); + int[] a5 = new int[SZ]; + Arrays.setAll(a5, new Rand.Integer()::get); + show(a5); + Integer[] a5b = + Stream.generate(new Rand.Integer()) + .limit(SZ + 1).toArray(Integer[]::new); + show(a5b); + a5b = new Rand.Integer().array(SZ + 2); + show(a5b); + a5 = IntStream.generate(new Rand.Pint()) + .limit(SZ + 1).toArray(); + show(a5); + a5 = new Rand.Pint().array(SZ + 3); + show(a5); + + System.out.println("Long"); + long[] a6 = new long[SZ]; + Arrays.setAll(a6, new Rand.Long()::get); + show(a6); + Long[] a6b = Stream.generate(new Rand.Long()) + .limit(SZ + 1).toArray(Long[]::new); + show(a6b); + a6b = new Rand.Long().array(SZ + 2); + show(a6b); + a6 = LongStream.generate(new Rand.Plong()) + .limit(SZ + 1).toArray(); + show(a6); + a6 = new Rand.Plong().array(SZ + 3); + show(a6); + + System.out.println("Float"); + Float[] a7 = new Float[SZ]; + Arrays.setAll(a7, new Rand.Float()::get); + show(a7); + a7 = Stream.generate(new Rand.Float()) + .limit(SZ + 1).toArray(Float[]::new); + show(a7); + a7 = new Rand.Float().array(SZ + 2); + show(a7); + float[] a7b = new Rand.Pfloat().array(SZ + 3); + show(a7b); + + System.out.println("Double"); + double[] a8 = new double[SZ]; + Arrays.setAll(a8, new Rand.Double()::get); + show(a8); + Double[] a8b = + Stream.generate(new Rand.Double()) + .limit(SZ + 1).toArray(Double[]::new); + show(a8b); + a8b = new Rand.Double().array(SZ + 2); + show(a8b); + a8 = DoubleStream.generate(new Rand.Pdouble()) + .limit(SZ + 1).toArray(); + show(a8); + a8 = new Rand.Pdouble().array(SZ + 3); + show(a8); + + System.out.println("String"); + String[] s = new String[SZ - 1]; + Arrays.setAll(s, new Rand.String()::get); + show(s); + s = Stream.generate(new Rand.String()) + .limit(SZ).toArray(String[]::new); + show(s); + s = new Rand.String().array(SZ + 1); + show(s); + + Arrays.setAll(s, new Rand.String(4)::get); + show(s); + s = Stream.generate(new Rand.String(4)) + .limit(SZ).toArray(String[]::new); + show(s); + s = new Rand.String(4).array(SZ + 1); + show(s); + } +} +/* Output: +Boolean +[true, false, true, true, true] +[true, false, true, true, true, false] +[true, false, true, true, true, false, false] +[true, false, true, true, true, false, false, true] +Byte +[123, 33, 101, 112, 33] +[123, 33, 101, 112, 33, 31] +[123, 33, 101, 112, 33, 31, 0] +[123, 33, 101, 112, 33, 31, 0, -72] +Character +[b, t, p, e, n] +[b, t, p, e, n, p] +[b, t, p, e, n, p, c] +[b, t, p, e, n, p, c, c] +Short +[635, 8737, 3941, 4720, 6177] +[635, 8737, 3941, 4720, 6177, 8479] +[635, 8737, 3941, 4720, 6177, 8479, 6656] +[635, 8737, 3941, 4720, 6177, 8479, 6656, 3768] +Integer +[635, 8737, 3941, 4720, 6177] +[635, 8737, 3941, 4720, 6177, 8479] +[635, 8737, 3941, 4720, 6177, 8479, 6656] +[635, 8737, 3941, 4720, 6177, 8479] +[635, 8737, 3941, 4720, 6177, 8479, 6656, 3768] +Long +[6882, 3765, 692, 9575, 4439] +[6882, 3765, 692, 9575, 4439, 2638] +[6882, 3765, 692, 9575, 4439, 2638, 4011] +[6882, 3765, 692, 9575, 4439, 2638] +[6882, 3765, 692, 9575, 4439, 2638, 4011, 9610] +Float +[4.83, 2.89, 2.9, 1.97, 3.01] +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18] +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99] +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99, 8.28] +Double +[4.83, 2.89, 2.9, 1.97, 3.01] +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18] +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99] +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18] +[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99, 8.28] +String +[btpenpc, cuxszgv, gmeinne, eloztdv] +[btpenpc, cuxszgv, gmeinne, eloztdv, ewcippc] +[btpenpc, cuxszgv, gmeinne, eloztdv, ewcippc, ygpoalk] +[btpe, npcc, uxsz, gvgm, einn, eelo] +[btpe, npcc, uxsz, gvgm, einn] +[btpe, npcc, uxsz, gvgm, einn, eelo] +*/ diff --git a/code/arrays/ThreeDWithNew.java b/code/arrays/ThreeDWithNew.java new file mode 100644 index 00000000..7aaef069 --- /dev/null +++ b/code/arrays/ThreeDWithNew.java @@ -0,0 +1,17 @@ +// arrays/ThreeDWithNew.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ThreeDWithNew { + public static void main(String[] args) { + // 3-D array with fixed length: + int[][][] a = new int[2][2][4]; + System.out.println(Arrays.deepToString(a)); + } +} +/* Output: +[[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, +0]]] +*/ diff --git a/code/arrays/jmh/ParallelSort.java b/code/arrays/jmh/ParallelSort.java new file mode 100644 index 00000000..fe0b505b --- /dev/null +++ b/code/arrays/jmh/ParallelSort.java @@ -0,0 +1,25 @@ +// arrays/jmh/ParallelSort.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package arrays.jmh; +import java.util.*; +import onjava.*; +import org.openjdk.jmh.annotations.*; + +@State(Scope.Thread) +public class ParallelSort { + private long[] la; + @Setup + public void setup() { + la = new Rand.Plong().array(100_000); + } + @Benchmark + public void sort() { + Arrays.sort(la); + } + @Benchmark + public void parallelSort() { + Arrays.parallelSort(la); + } +} diff --git a/code/build.gradle b/code/build.gradle new file mode 100644 index 00000000..b4feb13d --- /dev/null +++ b/code/build.gradle @@ -0,0 +1,23 @@ +buildscript { + repositories { + maven { + url 'https://plugins.gradle.org/m2/' + } + } + dependencies { + classpath 'me.champeau.gradle:jmh-gradle-plugin:0.5.2' + } +} + +apply plugin: 'com.mindviewinc.example-output-verification' + +subprojects { + apply from: "$rootProject.projectDir/gradle/java.gradle" + apply from: "$rootProject.projectDir/gradle/junit-jupiter.gradle" + apply from: "$rootProject.projectDir/gradle/jmh.gradle" + // apply from: "$rootProject.projectDir/gradle/checkstyle.gradle" + apply from: "$rootProject.projectDir/gradle/findbugs.gradle" + apply plugin: 'com.mindviewinc.tagging' +} + +apply from: 'gradle/subprojects.gradle' diff --git a/code/checkstyle.xml b/code/checkstyle.xml new file mode 100644 index 00000000..aabea2c4 --- /dev/null +++ b/code/checkstyle.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/chkstyle.bat b/code/chkstyle.bat new file mode 100644 index 00000000..24838fc0 --- /dev/null +++ b/code/chkstyle.bat @@ -0,0 +1,2 @@ +@echo run gradlew clean first! +gradlew checkstyleMain 1> checkstyleout.txt 2>&1 diff --git a/code/collections/AdapterMethodIdiom.java b/code/collections/AdapterMethodIdiom.java new file mode 100644 index 00000000..a97abb41 --- /dev/null +++ b/code/collections/AdapterMethodIdiom.java @@ -0,0 +1,48 @@ +// collections/AdapterMethodIdiom.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The "Adapter Method" idiom uses for-in +// with additional kinds of Iterables +import java.util.*; + +class ReversibleArrayList extends ArrayList { + ReversibleArrayList(Collection c) { + super(c); + } + public Iterable reversed() { + return new Iterable() { + public Iterator iterator() { + return new Iterator() { + int current = size() - 1; + public boolean hasNext() { + return current > -1; + } + public T next() { return get(current--); } + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + }; + } + }; + } +} + +public class AdapterMethodIdiom { + public static void main(String[] args) { + ReversibleArrayList ral = + new ReversibleArrayList( + Arrays.asList("To be or not to be".split(" "))); + // Grabs the ordinary iterator via iterator(): + for(String s : ral) + System.out.print(s + " "); + System.out.println(); + // Hand it the Iterable of your choice + for(String s : ral.reversed()) + System.out.print(s + " "); + } +} +/* Output: +To be or not to be +be to not or be To +*/ diff --git a/code/collections/AddingGroups.java b/code/collections/AddingGroups.java new file mode 100644 index 00000000..ecfc8a5a --- /dev/null +++ b/code/collections/AddingGroups.java @@ -0,0 +1,24 @@ +// collections/AddingGroups.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Adding groups of elements to Collection objects +import java.util.*; + +public class AddingGroups { + public static void main(String[] args) { + Collection collection = + new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); + Integer[] moreInts = { 6, 7, 8, 9, 10 }; + collection.addAll(Arrays.asList(moreInts)); + // Runs significantly faster, but you can't + // construct a Collection this way: + Collections.addAll(collection, 11, 12, 13, 14, 15); + Collections.addAll(collection, moreInts); + // Produces a list "backed by" an array: + List list = Arrays.asList(16,17,18,19,20); + list.set(1, 99); // OK -- modify an element + // list.add(21); // Runtime error; the underlying + // array cannot be resized. + } +} diff --git a/code/collections/ApplesAndOrangesWithGenerics.java b/code/collections/ApplesAndOrangesWithGenerics.java new file mode 100644 index 00000000..c251672c --- /dev/null +++ b/code/collections/ApplesAndOrangesWithGenerics.java @@ -0,0 +1,23 @@ +// collections/ApplesAndOrangesWithGenerics.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ApplesAndOrangesWithGenerics { + public static void main(String[] args) { + ArrayList apples = new ArrayList<>(); + for(int i = 0; i < 3; i++) + apples.add(new Apple()); + // Compile-time error: + // apples.add(new Orange()); + for(Apple apple : apples) { + System.out.println(apple.id()); + } + } +} +/* Output: +0 +1 +2 +*/ diff --git a/code/collections/ApplesAndOrangesWithoutGenerics.java b/code/collections/ApplesAndOrangesWithoutGenerics.java new file mode 100644 index 00000000..6afacd12 --- /dev/null +++ b/code/collections/ApplesAndOrangesWithoutGenerics.java @@ -0,0 +1,38 @@ +// collections/ApplesAndOrangesWithoutGenerics.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple collection use (suppressing compiler warnings) +// {ThrowsException} +import java.util.*; + +class Apple { + private static long counter; + private final long id = counter++; + public long id() { return id; } +} + +class Orange {} + +public class ApplesAndOrangesWithoutGenerics { + @SuppressWarnings("unchecked") + public static void main(String[] args) { + ArrayList apples = new ArrayList(); + for(int i = 0; i < 3; i++) + apples.add(new Apple()); + // No problem adding an Orange to apples: + apples.add(new Orange()); + for(Object apple : apples) { + ((Apple) apple).id(); + // Orange is detected only at run time + } + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "main" +java.lang.ClassCastException: Orange cannot be cast to +Apple + at ApplesAndOrangesWithoutGenerics.main(ApplesA +ndOrangesWithoutGenerics.java:23) +*/ diff --git a/code/collections/ArrayIsNotIterable.java b/code/collections/ArrayIsNotIterable.java new file mode 100644 index 00000000..d496feb1 --- /dev/null +++ b/code/collections/ArrayIsNotIterable.java @@ -0,0 +1,23 @@ +// collections/ArrayIsNotIterable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ArrayIsNotIterable { + static void test(Iterable ib) { + for(T t : ib) + System.out.print(t + " "); + } + public static void main(String[] args) { + test(Arrays.asList(1, 2, 3)); + String[] strings = { "A", "B", "C" }; + // An array works in for-in, but it's not Iterable: + //- test(strings); + // You must explicitly convert it to an Iterable: + test(Arrays.asList(strings)); + } +} +/* Output: +1 2 3 A B C +*/ diff --git a/code/collections/AsListInference.java b/code/collections/AsListInference.java new file mode 100644 index 00000000..ef813708 --- /dev/null +++ b/code/collections/AsListInference.java @@ -0,0 +1,34 @@ +// collections/AsListInference.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class Snow {} +class Powder extends Snow {} +class Light extends Powder {} +class Heavy extends Powder {} +class Crusty extends Snow {} +class Slush extends Snow {} + +public class AsListInference { + public static void main(String[] args) { + List snow1 = Arrays.asList( + new Crusty(), new Slush(), new Powder()); + //- snow1.add(new Heavy()); // Exception + + List snow2 = Arrays.asList( + new Light(), new Heavy()); + //- snow2.add(new Slush()); // Exception + + List snow3 = new ArrayList<>(); + Collections.addAll(snow3, + new Light(), new Heavy(), new Powder()); + snow3.add(new Crusty()); + + // Hint with explicit type argument specification: + List snow4 = Arrays.asList( + new Light(), new Heavy(), new Slush()); + //- snow4.add(new Powder()); // Exception + } +} diff --git a/code/collections/CollectionDifferences.java b/code/collections/CollectionDifferences.java new file mode 100644 index 00000000..711f7bd7 --- /dev/null +++ b/code/collections/CollectionDifferences.java @@ -0,0 +1,71 @@ +// collections/CollectionDifferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; + +public class CollectionDifferences { + public static void main(String[] args) { + CollectionMethodDifferences.main(args); + } +} +/* Output: +Collection: [add, addAll, clear, contains, containsAll, +equals, forEach, hashCode, isEmpty, iterator, +parallelStream, remove, removeAll, removeIf, retainAll, +size, spliterator, stream, toArray] +Interfaces in Collection: [Iterable] +Set extends Collection, adds: [] +Interfaces in Set: [Collection] +HashSet extends Set, adds: [] +Interfaces in HashSet: [Set, Cloneable, Serializable] +LinkedHashSet extends HashSet, adds: [] +Interfaces in LinkedHashSet: [Set, Cloneable, +Serializable] +TreeSet extends Set, adds: [headSet, +descendingIterator, descendingSet, pollLast, subSet, +floor, tailSet, ceiling, last, lower, comparator, +pollFirst, first, higher] +Interfaces in TreeSet: [NavigableSet, Cloneable, +Serializable] +List extends Collection, adds: [replaceAll, get, +indexOf, subList, set, sort, lastIndexOf, listIterator] +Interfaces in List: [Collection] +ArrayList extends List, adds: [trimToSize, +ensureCapacity] +Interfaces in ArrayList: [List, RandomAccess, +Cloneable, Serializable] +LinkedList extends List, adds: [offerFirst, poll, +getLast, offer, getFirst, removeFirst, element, +removeLastOccurrence, peekFirst, peekLast, push, +pollFirst, removeFirstOccurrence, descendingIterator, +pollLast, removeLast, pop, addLast, peek, offerLast, +addFirst] +Interfaces in LinkedList: [List, Deque, Cloneable, +Serializable] +Queue extends Collection, adds: [poll, peek, offer, +element] +Interfaces in Queue: [Collection] +PriorityQueue extends Queue, adds: [comparator] +Interfaces in PriorityQueue: [Serializable] +Map: [clear, compute, computeIfAbsent, +computeIfPresent, containsKey, containsValue, entrySet, +equals, forEach, get, getOrDefault, hashCode, isEmpty, +keySet, merge, put, putAll, putIfAbsent, remove, +replace, replaceAll, size, values] +HashMap extends Map, adds: [] +Interfaces in HashMap: [Map, Cloneable, Serializable] +LinkedHashMap extends HashMap, adds: [] +Interfaces in LinkedHashMap: [Map] +SortedMap extends Map, adds: [lastKey, subMap, +comparator, firstKey, headMap, tailMap] +Interfaces in SortedMap: [Map] +TreeMap extends Map, adds: [descendingKeySet, +navigableKeySet, higherEntry, higherKey, floorKey, +subMap, ceilingKey, pollLastEntry, firstKey, lowerKey, +headMap, tailMap, lowerEntry, ceilingEntry, +descendingMap, pollFirstEntry, lastKey, firstEntry, +floorEntry, comparator, lastEntry] +Interfaces in TreeMap: [NavigableMap, Cloneable, +Serializable] +*/ diff --git a/code/collections/CollectionSequence.java b/code/collections/CollectionSequence.java new file mode 100644 index 00000000..6a12ed69 --- /dev/null +++ b/code/collections/CollectionSequence.java @@ -0,0 +1,40 @@ +// collections/CollectionSequence.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class CollectionSequence +extends AbstractCollection { + private Pet[] pets = Pets.array(8); + @Override + public int size() { return pets.length; } + @Override + public Iterator iterator() { + return new Iterator() { // [1] + private int index = 0; + @Override + public boolean hasNext() { + return index < pets.length; + } + @Override + public Pet next() { return pets[index++]; } + @Override + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + }; + } + public static void main(String[] args) { + CollectionSequence c = new CollectionSequence(); + InterfaceVsIterator.display(c); + InterfaceVsIterator.display(c.iterator()); + } +} +/* Output: +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +*/ diff --git a/code/collections/CrossCollectionIteration.java b/code/collections/CrossCollectionIteration.java new file mode 100644 index 00000000..99769fe2 --- /dev/null +++ b/code/collections/CrossCollectionIteration.java @@ -0,0 +1,36 @@ +// collections/CrossCollectionIteration.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class CrossCollectionIteration { + public static void display(Iterator it) { + while(it.hasNext()) { + Pet p = it.next(); + System.out.print(p.id() + ":" + p + " "); + } + System.out.println(); + } + public static void main(String[] args) { + List pets = Pets.list(8); + LinkedList petsLL = new LinkedList<>(pets); + HashSet petsHS = new HashSet<>(pets); + TreeSet petsTS = new TreeSet<>(pets); + display(pets.iterator()); + display(petsLL.iterator()); + display(petsHS.iterator()); + display(petsTS.iterator()); + } +} +/* Output: +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug +0:Rat +*/ diff --git a/code/collections/CrossCollectionIteration2.java b/code/collections/CrossCollectionIteration2.java new file mode 100644 index 00000000..c7da143f --- /dev/null +++ b/code/collections/CrossCollectionIteration2.java @@ -0,0 +1,37 @@ +// collections/CrossCollectionIteration2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class CrossCollectionIteration2 { + public static void display(Iterable ip) { + Iterator it = ip.iterator(); + while(it.hasNext()) { + Pet p = it.next(); + System.out.print(p.id() + ":" + p + " "); + } + System.out.println(); + } + public static void main(String[] args) { + List pets = Pets.list(8); + LinkedList petsLL = new LinkedList<>(pets); + HashSet petsHS = new HashSet<>(pets); + TreeSet petsTS = new TreeSet<>(pets); + display(pets); + display(petsLL); + display(petsHS); + display(petsTS); + } +} +/* Output: +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug +0:Rat +*/ diff --git a/code/collections/EnvironmentVariables.java b/code/collections/EnvironmentVariables.java new file mode 100644 index 00000000..af89e5a2 --- /dev/null +++ b/code/collections/EnvironmentVariables.java @@ -0,0 +1,15 @@ +// collections/EnvironmentVariables.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.util.*; + +public class EnvironmentVariables { + public static void main(String[] args) { + for(Map.Entry entry: System.getenv().entrySet()) { + System.out.println(entry.getKey() + ": " + + entry.getValue()); + } + } +} diff --git a/code/collections/ForInCollections.java b/code/collections/ForInCollections.java new file mode 100644 index 00000000..a8ddd792 --- /dev/null +++ b/code/collections/ForInCollections.java @@ -0,0 +1,19 @@ +// collections/ForInCollections.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// All collections work with for-in +import java.util.*; + +public class ForInCollections { + public static void main(String[] args) { + Collection cs = new LinkedList<>(); + Collections.addAll(cs, + "Take the long way home".split(" ")); + for(String s : cs) + System.out.print("'" + s + "' "); + } +} +/* Output: +'Take' 'the' 'long' 'way' 'home' +*/ diff --git a/code/collections/GenericsAndUpcasting.java b/code/collections/GenericsAndUpcasting.java new file mode 100644 index 00000000..ed8d3f55 --- /dev/null +++ b/code/collections/GenericsAndUpcasting.java @@ -0,0 +1,28 @@ +// collections/GenericsAndUpcasting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class GrannySmith extends Apple {} +class Gala extends Apple {} +class Fuji extends Apple {} +class Braeburn extends Apple {} + +public class GenericsAndUpcasting { + public static void main(String[] args) { + ArrayList apples = new ArrayList<>(); + apples.add(new GrannySmith()); + apples.add(new Gala()); + apples.add(new Fuji()); + apples.add(new Braeburn()); + for(Apple apple : apples) + System.out.println(apple); + } +} +/* Output: +GrannySmith@15db9742 +Gala@6d06d69c +Fuji@7852e922 +Braeburn@4e25154f +*/ diff --git a/code/collections/InterfaceVsIterator.java b/code/collections/InterfaceVsIterator.java new file mode 100644 index 00000000..b5a8663d --- /dev/null +++ b/code/collections/InterfaceVsIterator.java @@ -0,0 +1,55 @@ +// collections/InterfaceVsIterator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class InterfaceVsIterator { + public static void display(Iterator it) { + while(it.hasNext()) { + Pet p = it.next(); + System.out.print(p.id() + ":" + p + " "); + } + System.out.println(); + } + public static void display(Collection pets) { + for(Pet p : pets) + System.out.print(p.id() + ":" + p + " "); + System.out.println(); + } + public static void main(String[] args) { + List petList = Pets.list(8); + Set petSet = new HashSet<>(petList); + Map petMap = new LinkedHashMap<>(); + String[] names = ("Ralph, Eric, Robin, Lacey, " + + "Britney, Sam, Spot, Fluffy").split(", "); + for(int i = 0; i < names.length; i++) + petMap.put(names[i], petList.get(i)); + display(petList); + display(petSet); + display(petList.iterator()); + display(petSet.iterator()); + System.out.println(petMap); + System.out.println(petMap.keySet()); + display(petMap.values()); + display(petMap.values().iterator()); + } +} +/* Output: +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +{Ralph=Rat, Eric=Manx, Robin=Cymric, Lacey=Mutt, +Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx} +[Ralph, Eric, Robin, Lacey, Britney, Sam, Spot, Fluffy] +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +*/ diff --git a/code/collections/IterableClass.java b/code/collections/IterableClass.java new file mode 100644 index 00000000..260edc7d --- /dev/null +++ b/code/collections/IterableClass.java @@ -0,0 +1,35 @@ +// collections/IterableClass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Anything Iterable works with for-in +import java.util.*; + +public class IterableClass implements Iterable { + protected String[] words = ("And that is how " + + "we know the Earth to be banana-shaped." + ).split(" "); + @Override + public Iterator iterator() { + return new Iterator() { + private int index = 0; + @Override + public boolean hasNext() { + return index < words.length; + } + @Override + public String next() { return words[index++]; } + @Override + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + }; + } + public static void main(String[] args) { + for(String s : new IterableClass()) + System.out.print(s + " "); + } +} +/* Output: +And that is how we know the Earth to be banana-shaped. +*/ diff --git a/code/collections/LinkedListFeatures.java b/code/collections/LinkedListFeatures.java new file mode 100644 index 00000000..3c10ff4e --- /dev/null +++ b/code/collections/LinkedListFeatures.java @@ -0,0 +1,54 @@ +// collections/LinkedListFeatures.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class LinkedListFeatures { + public static void main(String[] args) { + LinkedList pets = + new LinkedList<>(Pets.list(5)); + System.out.println(pets); + // Identical: + System.out.println( + "pets.getFirst(): " + pets.getFirst()); + System.out.println( + "pets.element(): " + pets.element()); + // Only differs in empty-list behavior: + System.out.println("pets.peek(): " + pets.peek()); + // Identical; remove and return the first element: + System.out.println( + "pets.remove(): " + pets.remove()); + System.out.println( + "pets.removeFirst(): " + pets.removeFirst()); + // Only differs in empty-list behavior: + System.out.println("pets.poll(): " + pets.poll()); + System.out.println(pets); + pets.addFirst(new Rat()); + System.out.println("After addFirst(): " + pets); + pets.offer(Pets.get()); + System.out.println("After offer(): " + pets); + pets.add(Pets.get()); + System.out.println("After add(): " + pets); + pets.addLast(new Hamster()); + System.out.println("After addLast(): " + pets); + System.out.println( + "pets.removeLast(): " + pets.removeLast()); + } +} +/* Output: +[Rat, Manx, Cymric, Mutt, Pug] +pets.getFirst(): Rat +pets.element(): Rat +pets.peek(): Rat +pets.remove(): Rat +pets.removeFirst(): Manx +pets.poll(): Cymric +[Mutt, Pug] +After addFirst(): [Rat, Mutt, Pug] +After offer(): [Rat, Mutt, Pug, Cymric] +After add(): [Rat, Mutt, Pug, Cymric, Pug] +After addLast(): [Rat, Mutt, Pug, Cymric, Pug, Hamster] +pets.removeLast(): Hamster +*/ diff --git a/code/collections/ListFeatures.java b/code/collections/ListFeatures.java new file mode 100644 index 00000000..b4ee16ab --- /dev/null +++ b/code/collections/ListFeatures.java @@ -0,0 +1,93 @@ +// collections/ListFeatures.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class ListFeatures { + public static void main(String[] args) { + Random rand = new Random(47); + List pets = Pets.list(7); + System.out.println("1: " + pets); + Hamster h = new Hamster(); + pets.add(h); // Automatically resizes + System.out.println("2: " + pets); + System.out.println("3: " + pets.contains(h)); + pets.remove(h); // Remove by object + Pet p = pets.get(2); + System.out.println( + "4: " + p + " " + pets.indexOf(p)); + Pet cymric = new Cymric(); + System.out.println("5: " + pets.indexOf(cymric)); + System.out.println("6: " + pets.remove(cymric)); + // Must be the exact object: + System.out.println("7: " + pets.remove(p)); + System.out.println("8: " + pets); + pets.add(3, new Mouse()); // Insert at an index + System.out.println("9: " + pets); + List sub = pets.subList(1, 4); + System.out.println("subList: " + sub); + System.out.println("10: " + pets.containsAll(sub)); + Collections.sort(sub); // In-place sort + System.out.println("sorted subList: " + sub); + // Order is not important in containsAll(): + System.out.println("11: " + pets.containsAll(sub)); + Collections.shuffle(sub, rand); // Mix it up + System.out.println("shuffled subList: " + sub); + System.out.println("12: " + pets.containsAll(sub)); + List copy = new ArrayList<>(pets); + sub = Arrays.asList(pets.get(1), pets.get(4)); + System.out.println("sub: " + sub); + copy.retainAll(sub); + System.out.println("13: " + copy); + copy = new ArrayList<>(pets); // Get a fresh copy + copy.remove(2); // Remove by index + System.out.println("14: " + copy); + copy.removeAll(sub); // Only removes exact objects + System.out.println("15: " + copy); + copy.set(1, new Mouse()); // Replace an element + System.out.println("16: " + copy); + copy.addAll(2, sub); // Insert a list in the middle + System.out.println("17: " + copy); + System.out.println("18: " + pets.isEmpty()); + pets.clear(); // Remove all elements + System.out.println("19: " + pets); + System.out.println("20: " + pets.isEmpty()); + pets.addAll(Pets.list(4)); + System.out.println("21: " + pets); + Object[] o = pets.toArray(); + System.out.println("22: " + o[3]); + Pet[] pa = pets.toArray(new Pet[0]); + System.out.println("23: " + pa[3].id()); + } +} +/* Output: +1: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug] +2: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Hamster] +3: true +4: Cymric 2 +5: -1 +6: false +7: true +8: [Rat, Manx, Mutt, Pug, Cymric, Pug] +9: [Rat, Manx, Mutt, Mouse, Pug, Cymric, Pug] +subList: [Manx, Mutt, Mouse] +10: true +sorted subList: [Manx, Mouse, Mutt] +11: true +shuffled subList: [Mouse, Manx, Mutt] +12: true +sub: [Mouse, Pug] +13: [Mouse, Pug] +14: [Rat, Mouse, Mutt, Pug, Cymric, Pug] +15: [Rat, Mutt, Cymric, Pug] +16: [Rat, Mouse, Cymric, Pug] +17: [Rat, Mouse, Mouse, Pug, Cymric, Pug] +18: false +19: [] +20: true +21: [Manx, Cymric, Rat, EgyptianMau] +22: EgyptianMau +23: 14 +*/ diff --git a/code/collections/ListIteration.java b/code/collections/ListIteration.java new file mode 100644 index 00000000..95d2786c --- /dev/null +++ b/code/collections/ListIteration.java @@ -0,0 +1,37 @@ +// collections/ListIteration.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class ListIteration { + public static void main(String[] args) { + List pets = Pets.list(8); + ListIterator it = pets.listIterator(); + while(it.hasNext()) + System.out.print(it.next() + + ", " + it.nextIndex() + + ", " + it.previousIndex() + "; "); + System.out.println(); + // Backwards: + while(it.hasPrevious()) + System.out.print(it.previous().id() + " "); + System.out.println(); + System.out.println(pets); + it = pets.listIterator(3); + while(it.hasNext()) { + it.next(); + it.set(Pets.get()); + } + System.out.println(pets); + } +} +/* Output: +Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug, +5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7; +7 6 5 4 3 2 1 0 +[Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Manx] +[Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster, +EgyptianMau] +*/ diff --git a/code/collections/MapOfList.java b/code/collections/MapOfList.java new file mode 100644 index 00000000..3a985dd9 --- /dev/null +++ b/code/collections/MapOfList.java @@ -0,0 +1,65 @@ +// collections/MapOfList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java collections.MapOfList} +package collections; +import typeinfo.pets.*; +import java.util.*; + +public class MapOfList { + public static final Map> + petPeople = new HashMap<>(); + static { + petPeople.put(new Person("Dawn"), + Arrays.asList( + new Cymric("Molly"), + new Mutt("Spot"))); + petPeople.put(new Person("Kate"), + Arrays.asList(new Cat("Shackleton"), + new Cat("Elsie May"), new Dog("Margrett"))); + petPeople.put(new Person("Marilyn"), + Arrays.asList( + new Pug("Louie aka Louis Snorkelstein Dupree"), + new Cat("Stanford"), + new Cat("Pinkola"))); + petPeople.put(new Person("Luke"), + Arrays.asList( + new Rat("Fuzzy"), new Rat("Fizzy"))); + petPeople.put(new Person("Isaac"), + Arrays.asList(new Rat("Freckly"))); + } + public static void main(String[] args) { + System.out.println("People: " + petPeople.keySet()); + System.out.println("Pets: " + petPeople.values()); + for(Person person : petPeople.keySet()) { + System.out.println(person + " has:"); + for(Pet pet : petPeople.get(person)) + System.out.println(" " + pet); + } + } +} +/* Output: +People: [Person Dawn, Person Kate, Person Isaac, Person +Marilyn, Person Luke] +Pets: [[Cymric Molly, Mutt Spot], [Cat Shackleton, Cat +Elsie May, Dog Margrett], [Rat Freckly], [Pug Louie aka +Louis Snorkelstein Dupree, Cat Stanford, Cat Pinkola], +[Rat Fuzzy, Rat Fizzy]] +Person Dawn has: + Cymric Molly + Mutt Spot +Person Kate has: + Cat Shackleton + Cat Elsie May + Dog Margrett +Person Isaac has: + Rat Freckly +Person Marilyn has: + Pug Louie aka Louis Snorkelstein Dupree + Cat Stanford + Cat Pinkola +Person Luke has: + Rat Fuzzy + Rat Fizzy +*/ diff --git a/code/collections/ModifyingArraysAsList.java b/code/collections/ModifyingArraysAsList.java new file mode 100644 index 00000000..fea3da42 --- /dev/null +++ b/code/collections/ModifyingArraysAsList.java @@ -0,0 +1,32 @@ +// collections/ModifyingArraysAsList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ModifyingArraysAsList { + public static void main(String[] args) { + Random rand = new Random(47); + Integer[] ia = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + List list1 = + new ArrayList<>(Arrays.asList(ia)); + System.out.println("Before shuffling: " + list1); + Collections.shuffle(list1, rand); + System.out.println("After shuffling: " + list1); + System.out.println("array: " + Arrays.toString(ia)); + + List list2 = Arrays.asList(ia); + System.out.println("Before shuffling: " + list2); + Collections.shuffle(list2, rand); + System.out.println("After shuffling: " + list2); + System.out.println("array: " + Arrays.toString(ia)); + } +} +/* Output: +Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +After shuffling: [4, 6, 3, 1, 8, 7, 2, 5, 10, 9] +array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +After shuffling: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8] +array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8] +*/ diff --git a/code/collections/MultiIterableClass.java b/code/collections/MultiIterableClass.java new file mode 100644 index 00000000..1d7376e5 --- /dev/null +++ b/code/collections/MultiIterableClass.java @@ -0,0 +1,53 @@ +// collections/MultiIterableClass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Adding several Adapter Methods +import java.util.*; + +public class MultiIterableClass extends IterableClass { + public Iterable reversed() { + return new Iterable() { + public Iterator iterator() { + return new Iterator() { + int current = words.length - 1; + public boolean hasNext() { + return current > -1; + } + public String next() { + return words[current--]; + } + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + }; + } + }; + } + public Iterable randomized() { + return new Iterable() { + public Iterator iterator() { + List shuffled = + new ArrayList(Arrays.asList(words)); + Collections.shuffle(shuffled, new Random(47)); + return shuffled.iterator(); + } + }; + } + public static void main(String[] args) { + MultiIterableClass mic = new MultiIterableClass(); + for(String s : mic.reversed()) + System.out.print(s + " "); + System.out.println(); + for(String s : mic.randomized()) + System.out.print(s + " "); + System.out.println(); + for(String s : mic) + System.out.print(s + " "); + } +} +/* Output: +banana-shaped. be to Earth the know we how is that And +is banana-shaped. Earth that how the be And we know to +And that is how we know the Earth to be banana-shaped. +*/ diff --git a/code/collections/NonCollectionSequence.java b/code/collections/NonCollectionSequence.java new file mode 100644 index 00000000..ed1ae6f6 --- /dev/null +++ b/code/collections/NonCollectionSequence.java @@ -0,0 +1,37 @@ +// collections/NonCollectionSequence.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +class PetSequence { + protected Pet[] pets = Pets.array(8); +} + +public class NonCollectionSequence extends PetSequence { + public Iterator iterator() { + return new Iterator() { + private int index = 0; + @Override + public boolean hasNext() { + return index < pets.length; + } + @Override + public Pet next() { return pets[index++]; } + @Override + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + }; + } + public static void main(String[] args) { + NonCollectionSequence nc = + new NonCollectionSequence(); + InterfaceVsIterator.display(nc.iterator()); + } +} +/* Output: +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx +*/ diff --git a/code/collections/PetMap.java b/code/collections/PetMap.java new file mode 100644 index 00000000..18d02ef0 --- /dev/null +++ b/code/collections/PetMap.java @@ -0,0 +1,27 @@ +// collections/PetMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class PetMap { + public static void main(String[] args) { + Map petMap = new HashMap<>(); + petMap.put("My Cat", new Cat("Molly")); + petMap.put("My Dog", new Dog("Ginger")); + petMap.put("My Hamster", new Hamster("Bosco")); + System.out.println(petMap); + Pet dog = petMap.get("My Dog"); + System.out.println(dog); + System.out.println(petMap.containsKey("My Dog")); + System.out.println(petMap.containsValue(dog)); + } +} +/* Output: +{My Dog=Dog Ginger, My Cat=Cat Molly, My +Hamster=Hamster Bosco} +Dog Ginger +true +true +*/ diff --git a/code/collections/PrintingCollections.java b/code/collections/PrintingCollections.java new file mode 100644 index 00000000..c5746fc3 --- /dev/null +++ b/code/collections/PrintingCollections.java @@ -0,0 +1,44 @@ +// collections/PrintingCollections.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Collections print themselves automatically +import java.util.*; + +public class PrintingCollections { + static Collection + fill(Collection collection) { + collection.add("rat"); + collection.add("cat"); + collection.add("dog"); + collection.add("dog"); + return collection; + } + static Map fill(Map map) { + map.put("rat", "Fuzzy"); + map.put("cat", "Rags"); + map.put("dog", "Bosco"); + map.put("dog", "Spot"); + return map; + } + public static void main(String[] args) { + System.out.println(fill(new ArrayList<>())); + System.out.println(fill(new LinkedList<>())); + System.out.println(fill(new HashSet<>())); + System.out.println(fill(new TreeSet<>())); + System.out.println(fill(new LinkedHashSet<>())); + System.out.println(fill(new HashMap<>())); + System.out.println(fill(new TreeMap<>())); + System.out.println(fill(new LinkedHashMap<>())); + } +} +/* Output: +[rat, cat, dog, dog] +[rat, cat, dog, dog] +[rat, cat, dog] +[cat, dog, rat] +[rat, cat, dog] +{rat=Fuzzy, cat=Rags, dog=Spot} +{cat=Rags, dog=Spot, rat=Fuzzy} +{rat=Fuzzy, cat=Rags, dog=Spot} +*/ diff --git a/code/collections/PriorityQueueDemo.java b/code/collections/PriorityQueueDemo.java new file mode 100644 index 00000000..4f71ab0e --- /dev/null +++ b/code/collections/PriorityQueueDemo.java @@ -0,0 +1,53 @@ +// collections/PriorityQueueDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class PriorityQueueDemo { + public static void main(String[] args) { + PriorityQueue priorityQueue = + new PriorityQueue<>(); + Random rand = new Random(47); + for(int i = 0; i < 10; i++) + priorityQueue.offer(rand.nextInt(i + 10)); + QueueDemo.printQ(priorityQueue); + + List ints = Arrays.asList(25, 22, 20, + 18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25); + priorityQueue = new PriorityQueue<>(ints); + QueueDemo.printQ(priorityQueue); + priorityQueue = new PriorityQueue<>( + ints.size(), Collections.reverseOrder()); + priorityQueue.addAll(ints); + QueueDemo.printQ(priorityQueue); + + String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION"; + List strings = + Arrays.asList(fact.split("")); + PriorityQueue stringPQ = + new PriorityQueue<>(strings); + QueueDemo.printQ(stringPQ); + stringPQ = new PriorityQueue<>( + strings.size(), Collections.reverseOrder()); + stringPQ.addAll(strings); + QueueDemo.printQ(stringPQ); + + Set charSet = new HashSet<>(); + for(char c : fact.toCharArray()) + charSet.add(c); // Autoboxing + PriorityQueue characterPQ = + new PriorityQueue<>(charSet); + QueueDemo.printQ(characterPQ); + } +} +/* Output: +0 1 1 1 1 1 3 5 8 14 +1 1 2 3 3 9 9 14 14 18 18 20 21 22 23 25 25 +25 25 23 22 21 20 18 18 14 14 9 9 3 3 2 1 1 + A A B C C C D D E E E F H H I I L N N O O O O S S +S T T U U U W +W U U U T T S S S O O O O N N L I I H H F E E E D D C C +C B A A + A B C D E F H I L N O S T U W +*/ diff --git a/code/collections/QueueDemo.java b/code/collections/QueueDemo.java new file mode 100644 index 00000000..f807e89a --- /dev/null +++ b/code/collections/QueueDemo.java @@ -0,0 +1,29 @@ +// collections/QueueDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Upcasting to a Queue from a LinkedList +import java.util.*; + +public class QueueDemo { + public static void printQ(Queue queue) { + while(queue.peek() != null) + System.out.print(queue.remove() + " "); + System.out.println(); + } + public static void main(String[] args) { + Queue queue = new LinkedList<>(); + Random rand = new Random(47); + for(int i = 0; i < 10; i++) + queue.offer(rand.nextInt(i + 10)); + printQ(queue); + Queue qc = new LinkedList<>(); + for(char c : "Brontosaurus".toCharArray()) + qc.offer(c); + printQ(qc); + } +} +/* Output: +8 1 1 1 5 14 3 1 0 1 +B r o n t o s a u r u s +*/ diff --git a/code/collections/SetOfInteger.java b/code/collections/SetOfInteger.java new file mode 100644 index 00000000..78157d5c --- /dev/null +++ b/code/collections/SetOfInteger.java @@ -0,0 +1,19 @@ +// collections/SetOfInteger.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SetOfInteger { + public static void main(String[] args) { + Random rand = new Random(47); + Set intset = new HashSet<>(); + for(int i = 0; i < 10000; i++) + intset.add(rand.nextInt(30)); + System.out.println(intset); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] +*/ diff --git a/code/collections/SetOfString.java b/code/collections/SetOfString.java new file mode 100644 index 00000000..01d9455e --- /dev/null +++ b/code/collections/SetOfString.java @@ -0,0 +1,25 @@ +// collections/SetOfString.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SetOfString { + public static void main(String[] args) { + Set colors = new HashSet<>(); + for(int i = 0; i < 100; i++) { + colors.add("Yellow"); + colors.add("Blue"); + colors.add("Red"); + colors.add("Red"); + colors.add("Orange"); + colors.add("Yellow"); + colors.add("Blue"); + colors.add("Purple"); + } + System.out.println(colors); + } +} +/* Output: +[Red, Yellow, Blue, Purple, Orange] +*/ diff --git a/code/collections/SetOperations.java b/code/collections/SetOperations.java new file mode 100644 index 00000000..f716f965 --- /dev/null +++ b/code/collections/SetOperations.java @@ -0,0 +1,40 @@ +// collections/SetOperations.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SetOperations { + public static void main(String[] args) { + Set set1 = new HashSet<>(); + Collections.addAll(set1, + "A B C D E F G H I J K L".split(" ")); + set1.add("M"); + System.out.println("H: " + set1.contains("H")); + System.out.println("N: " + set1.contains("N")); + Set set2 = new HashSet<>(); + Collections.addAll(set2, "H I J K L".split(" ")); + System.out.println( + "set2 in set1: " + set1.containsAll(set2)); + set1.remove("H"); + System.out.println("set1: " + set1); + System.out.println( + "set2 in set1: " + set1.containsAll(set2)); + set1.removeAll(set2); + System.out.println( + "set2 removed from set1: " + set1); + Collections.addAll(set1, "X Y Z".split(" ")); + System.out.println( + "'X Y Z' added to set1: " + set1); + } +} +/* Output: +H: true +N: false +set2 in set1: true +set1: [A, B, C, D, E, F, G, I, J, K, L, M] +set2 in set1: false +set2 removed from set1: [A, B, C, D, E, F, G, M] +'X Y Z' added to set1: [A, B, C, D, E, F, G, M, X, Y, +Z] +*/ diff --git a/code/collections/SimpleCollection.java b/code/collections/SimpleCollection.java new file mode 100644 index 00000000..8915e259 --- /dev/null +++ b/code/collections/SimpleCollection.java @@ -0,0 +1,18 @@ +// collections/SimpleCollection.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SimpleCollection { + public static void main(String[] args) { + Collection c = new ArrayList<>(); + for(int i = 0; i < 10; i++) + c.add(i); // Autoboxing + for(Integer i : c) + System.out.print(i + ", "); + } +} +/* Output: +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +*/ diff --git a/code/collections/SimpleIteration.java b/code/collections/SimpleIteration.java new file mode 100644 index 00000000..a65a2a71 --- /dev/null +++ b/code/collections/SimpleIteration.java @@ -0,0 +1,36 @@ +// collections/SimpleIteration.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import java.util.*; + +public class SimpleIteration { + public static void main(String[] args) { + List pets = Pets.list(12); + Iterator it = pets.iterator(); + while(it.hasNext()) { + Pet p = it.next(); + System.out.print(p.id() + ":" + p + " "); + } + System.out.println(); + // A simpler approach, when possible: + for(Pet p : pets) + System.out.print(p.id() + ":" + p + " "); + System.out.println(); + // An Iterator can also remove elements: + it = pets.iterator(); + for(int i = 0; i < 6; i++) { + it.next(); + it.remove(); + } + System.out.println(pets); + } +} +/* Output: +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster +0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug +7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster +[Pug, Manx, Cymric, Rat, EgyptianMau, Hamster] +*/ diff --git a/code/collections/SortedSetOfString.java b/code/collections/SortedSetOfString.java new file mode 100644 index 00000000..a043b791 --- /dev/null +++ b/code/collections/SortedSetOfString.java @@ -0,0 +1,25 @@ +// collections/SortedSetOfString.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SortedSetOfString { + public static void main(String[] args) { + Set colors = new TreeSet<>(); + for(int i = 0; i < 100; i++) { + colors.add("Yellow"); + colors.add("Blue"); + colors.add("Red"); + colors.add("Red"); + colors.add("Orange"); + colors.add("Yellow"); + colors.add("Blue"); + colors.add("Purple"); + } + System.out.println(colors); + } +} +/* Output: +[Blue, Orange, Purple, Red, Yellow] +*/ diff --git a/code/collections/StackCollision.java b/code/collections/StackCollision.java new file mode 100644 index 00000000..67ee4d90 --- /dev/null +++ b/code/collections/StackCollision.java @@ -0,0 +1,25 @@ +// collections/StackCollision.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class StackCollision { + public static void main(String[] args) { + onjava.Stack stack = new onjava.Stack<>(); + for(String s : "My dog has fleas".split(" ")) + stack.push(s); + while(!stack.isEmpty()) + System.out.print(stack.pop() + " "); + System.out.println(); + java.util.Stack stack2 = + new java.util.Stack<>(); + for(String s : "My dog has fleas".split(" ")) + stack2.push(s); + while(!stack2.empty()) + System.out.print(stack2.pop() + " "); + } +} +/* Output: +fleas has dog My +fleas has dog My +*/ diff --git a/code/collections/StackTest.java b/code/collections/StackTest.java new file mode 100644 index 00000000..dc1663cc --- /dev/null +++ b/code/collections/StackTest.java @@ -0,0 +1,18 @@ +// collections/StackTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class StackTest { + public static void main(String[] args) { + Deque stack = new ArrayDeque<>(); + for(String s : "My dog has fleas".split(" ")) + stack.push(s); + while(!stack.isEmpty()) + System.out.print(stack.pop() + " "); + } +} +/* Output: +fleas has dog My +*/ diff --git a/code/collections/StackTest2.java b/code/collections/StackTest2.java new file mode 100644 index 00000000..2464d7a9 --- /dev/null +++ b/code/collections/StackTest2.java @@ -0,0 +1,18 @@ +// collections/StackTest2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; + +public class StackTest2 { + public static void main(String[] args) { + Stack stack = new Stack<>(); + for(String s : "My dog has fleas".split(" ")) + stack.push(s); + while(!stack.isEmpty()) + System.out.print(stack.pop() + " "); + } +} +/* Output: +fleas has dog My +*/ diff --git a/code/collections/Statistics.java b/code/collections/Statistics.java new file mode 100644 index 00000000..f888db58 --- /dev/null +++ b/code/collections/Statistics.java @@ -0,0 +1,25 @@ +// collections/Statistics.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple demonstration of HashMap +import java.util.*; + +public class Statistics { + public static void main(String[] args) { + Random rand = new Random(47); + Map m = new HashMap<>(); + for(int i = 0; i < 10000; i++) { + // Produce a number between 0 and 20: + int r = rand.nextInt(20); + Integer freq = m.get(r); // [1] + m.put(r, freq == null ? 1 : freq + 1); + } + System.out.println(m); + } +} +/* Output: +{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, +7=471, 8=468, 9=549, 10=513, 11=531, 12=521, 13=506, +14=477, 15=497, 16=533, 17=509, 18=478, 19=464} +*/ diff --git a/code/collections/UniqueWords.java b/code/collections/UniqueWords.java new file mode 100644 index 00000000..c6c3681d --- /dev/null +++ b/code/collections/UniqueWords.java @@ -0,0 +1,29 @@ +// collections/UniqueWords.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.nio.file.*; + +public class UniqueWords { + public static void + main(String[] args) throws Exception { + List lines = Files.readAllLines( + Paths.get("SetOperations.java")); + Set words = new TreeSet<>(); + for(String line : lines) + for(String word : line.split("\\W+")) + if(word.trim().length() > 0) + words.add(word); + System.out.println(words); + } +} +/* Output: +[A, B, C, Collections, D, E, F, G, H, HashSet, I, J, K, +L, M, N, Output, Set, SetOperations, String, System, X, +Y, Z, add, addAll, added, args, class, collections, +contains, containsAll, false, from, import, in, java, +main, new, out, println, public, remove, removeAll, +removed, set1, set2, split, static, to, true, util, +void] +*/ diff --git a/code/collections/UniqueWordsAlphabetic.java b/code/collections/UniqueWordsAlphabetic.java new file mode 100644 index 00000000..66a7fecf --- /dev/null +++ b/code/collections/UniqueWordsAlphabetic.java @@ -0,0 +1,30 @@ +// collections/UniqueWordsAlphabetic.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Producing an alphabetic listing +import java.util.*; +import java.nio.file.*; + +public class UniqueWordsAlphabetic { + public static void + main(String[] args) throws Exception { + List lines = Files.readAllLines( + Paths.get("SetOperations.java")); + Set words = + new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + for(String line : lines) + for(String word : line.split("\\W+")) + if(word.trim().length() > 0) + words.add(word); + System.out.println(words); + } +} +/* Output: +[A, add, addAll, added, args, B, C, class, collections, +contains, containsAll, D, E, F, false, from, G, H, +HashSet, I, import, in, J, java, K, L, M, main, N, new, +out, Output, println, public, remove, removeAll, +removed, Set, set1, set2, SetOperations, split, static, +String, System, to, true, util, void, X, Y, Z] +*/ diff --git a/code/collectiontopics/AssociativeArray.java b/code/collectiontopics/AssociativeArray.java new file mode 100644 index 00000000..e7488489 --- /dev/null +++ b/code/collectiontopics/AssociativeArray.java @@ -0,0 +1,64 @@ +// collectiontopics/AssociativeArray.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Associates keys with values + +public class AssociativeArray { + private Object[][] pairs; + private int index; + public AssociativeArray(int length) { + pairs = new Object[length][2]; + } + public void put(K key, V value) { + if(index >= pairs.length) + throw new ArrayIndexOutOfBoundsException(); + pairs[index++] = new Object[]{ key, value }; + } + @SuppressWarnings("unchecked") + public V get(K key) { + for(int i = 0; i < index; i++) + if(key.equals(pairs[i][0])) + return (V)pairs[i][1]; + return null; // Did not find key + } + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for(int i = 0; i < index; i++) { + result.append(pairs[i][0].toString()); + result.append(" : "); + result.append(pairs[i][1].toString()); + if(i < index - 1) + result.append("\n"); + } + return result.toString(); + } + public static void main(String[] args) { + AssociativeArray map = + new AssociativeArray<>(6); + map.put("sky", "blue"); + map.put("grass", "green"); + map.put("ocean", "dancing"); + map.put("tree", "tall"); + map.put("earth", "brown"); + map.put("sun", "warm"); + try { + map.put("extra", "object"); // Past the end + } catch(ArrayIndexOutOfBoundsException e) { + System.out.println("Too many objects!"); + } + System.out.println(map); + System.out.println(map.get("ocean")); + } +} +/* Output: +Too many objects! +sky : blue +grass : green +ocean : dancing +tree : tall +earth : brown +sun : warm +dancing +*/ diff --git a/code/collectiontopics/Bits.java b/code/collectiontopics/Bits.java new file mode 100644 index 00000000..16afb361 --- /dev/null +++ b/code/collectiontopics/Bits.java @@ -0,0 +1,79 @@ +// collectiontopics/Bits.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of BitSet +import java.util.*; + +public class Bits { + public static void printBitSet(BitSet b) { + System.out.println("bits: " + b); + StringBuilder bbits = new StringBuilder(); + for(int j = 0; j < b.size() ; j++) + bbits.append(b.get(j) ? "1" : "0"); + System.out.println("bit pattern: " + bbits); + } + public static void main(String[] args) { + Random rand = new Random(47); + // Take the LSB of nextInt(): + byte bt = (byte)rand.nextInt(); + BitSet bb = new BitSet(); + for(int i = 7; i >= 0; i--) + if(((1 << i) & bt) != 0) + bb.set(i); + else + bb.clear(i); + System.out.println("byte value: " + bt); + printBitSet(bb); + + short st = (short)rand.nextInt(); + BitSet bs = new BitSet(); + for(int i = 15; i >= 0; i--) + if(((1 << i) & st) != 0) + bs.set(i); + else + bs.clear(i); + System.out.println("short value: " + st); + printBitSet(bs); + + int it = rand.nextInt(); + BitSet bi = new BitSet(); + for(int i = 31; i >= 0; i--) + if(((1 << i) & it) != 0) + bi.set(i); + else + bi.clear(i); + System.out.println("int value: " + it); + printBitSet(bi); + + // Test bitsets >= 64 bits: + BitSet b127 = new BitSet(); + b127.set(127); + System.out.println("set bit 127: " + b127); + BitSet b255 = new BitSet(65); + b255.set(255); + System.out.println("set bit 255: " + b255); + BitSet b1023 = new BitSet(512); + b1023.set(1023); + b1023.set(1024); + System.out.println("set bit 1023: " + b1023); + } +} +/* Output: +byte value: -107 +bits: {0, 2, 4, 7} +bit pattern: 101010010000000000000000000000000000000000 +0000000000000000000000 +short value: 1302 +bits: {1, 2, 4, 8, 10} +bit pattern: 011010001010000000000000000000000000000000 +0000000000000000000000 +int value: -2014573909 +bits: {0, 1, 3, 5, 7, 9, 11, 18, 19, 21, 22, 23, 24, +25, 26, 31} +bit pattern: 110101010101000000110111111000010000000000 +0000000000000000000000 +set bit 127: {127} +set bit 255: {255} +set bit 1023: {1023, 1024} +*/ diff --git a/code/collectiontopics/CanonicalMapping.java b/code/collectiontopics/CanonicalMapping.java new file mode 100644 index 00000000..c02f9132 --- /dev/null +++ b/code/collectiontopics/CanonicalMapping.java @@ -0,0 +1,56 @@ +// collectiontopics/CanonicalMapping.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates WeakHashMap +import java.util.*; + +class Element { + private String ident; + Element(String id) { ident = id; } + @Override + public String toString() { return ident; } + @Override + public int hashCode() { + return Objects.hashCode(ident); + } + @Override + public boolean equals(Object r) { + return r instanceof Element && + Objects.equals(ident, ((Element)r).ident); + } + @SuppressWarnings("deprecation") + @Override + protected void finalize() { + System.out.println("Finalizing " + + getClass().getSimpleName() + " " + ident); + } +} + +class Key extends Element { + Key(String id) { super(id); } +} + +class Value extends Element { + Value(String id) { super(id); } +} + +public class CanonicalMapping { + public static void main(String[] args) { + int size = 1000; + // Or, choose size via the command line: + if(args.length > 0) + size = Integer.valueOf(args[0]); + Key[] keys = new Key[size]; + WeakHashMap map = + new WeakHashMap<>(); + for(int i = 0; i < size; i++) { + Key k = new Key(Integer.toString(i)); + Value v = new Value(Integer.toString(i)); + if(i % 3 == 0) + keys[i] = k; // Save as "real" references + map.put(k, v); + } + System.gc(); + } +} diff --git a/code/collectiontopics/CollectionMethods.java b/code/collectiontopics/CollectionMethods.java new file mode 100644 index 00000000..e32e5982 --- /dev/null +++ b/code/collectiontopics/CollectionMethods.java @@ -0,0 +1,135 @@ +// collectiontopics/CollectionMethods.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Things you can do with all Collections +import java.util.*; +import static onjava.HTMLColors.*; + +public class CollectionMethods { + public static void main(String[] args) { + Collection c = + new ArrayList<>(LIST.subList(0, 4)); + c.add("ten"); + c.add("eleven"); + show(c); + border(); + // Make an array from the List: + Object[] array = c.toArray(); + // Make a String array from the List: + String[] str = c.toArray(new String[0]); + // Find max and min elements; this means + // different things depending on the way + // the Comparable interface is implemented: + System.out.println( + "Collections.max(c) = " + Collections.max(c)); + System.out.println( + "Collections.min(c) = " + Collections.min(c)); + border(); + // Add a Collection to another Collection + Collection c2 = + new ArrayList<>(LIST.subList(10, 14)); + c.addAll(c2); + show(c); + border(); + c.remove(LIST.get(0)); + show(c); + border(); + // Remove all components that are + // in the argument collection: + c.removeAll(c2); + show(c); + border(); + c.addAll(c2); + show(c); + border(); + // Is an element in this Collection? + String val = LIST.get(3); + System.out.println( + "c.contains(" + val + ") = " + c.contains(val)); + // Is a Collection in this Collection? + System.out.println( + "c.containsAll(c2) = " + c.containsAll(c2)); + Collection c3 = + ((List)c).subList(3, 5); + // Keep all the elements that are in both + // c2 and c3 (an intersection of sets): + c2.retainAll(c3); + show(c2); + // Throw away all the elements + // in c2 that also appear in c3: + c2.removeAll(c3); + System.out.println( + "c2.isEmpty() = " + c2.isEmpty()); + border(); + // Functional operation: + c = new ArrayList<>(LIST); + c.removeIf(s -> !s.startsWith("P")); + c.removeIf(s -> s.startsWith("Pale")); + // Stream operation: + c.stream().forEach(System.out::println); + c.clear(); // Remove all elements + System.out.println("after c.clear():" + c); + } +} +/* Output: +AliceBlue +AntiqueWhite +Aquamarine +Azure +ten +eleven +****************************** +Collections.max(c) = ten +Collections.min(c) = AliceBlue +****************************** +AliceBlue +AntiqueWhite +Aquamarine +Azure +ten +eleven +Brown +BurlyWood +CadetBlue +Chartreuse +****************************** +AntiqueWhite +Aquamarine +Azure +ten +eleven +Brown +BurlyWood +CadetBlue +Chartreuse +****************************** +AntiqueWhite +Aquamarine +Azure +ten +eleven +****************************** +AntiqueWhite +Aquamarine +Azure +ten +eleven +Brown +BurlyWood +CadetBlue +Chartreuse +****************************** +c.contains(Azure) = true +c.containsAll(c2) = true +c2.isEmpty() = true +****************************** +PapayaWhip +PeachPuff +Peru +Pink +Plum +PowderBlue +Purple +after c.clear():[] +*/ diff --git a/code/collectiontopics/Enumerations.java b/code/collectiontopics/Enumerations.java new file mode 100644 index 00000000..22b83e52 --- /dev/null +++ b/code/collectiontopics/Enumerations.java @@ -0,0 +1,24 @@ +// collectiontopics/Enumerations.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Java 1.0/1.1 Vector and Enumeration +import java.util.*; +import onjava.*; + +public class Enumerations { + public static void main(String[] args) { + Vector v = + new Vector<>(Countries.names(10)); + Enumeration e = v.elements(); + while(e.hasMoreElements()) + System.out.print(e.nextElement() + ", "); + // Produce an Enumeration from a Collection: + e = Collections.enumeration(new ArrayList<>()); + } +} +/* Output: +ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, +BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN +REPUBLIC, CHAD, +*/ diff --git a/code/collectiontopics/FailFast.java b/code/collectiontopics/FailFast.java new file mode 100644 index 00000000..0b0ce253 --- /dev/null +++ b/code/collectiontopics/FailFast.java @@ -0,0 +1,22 @@ +// collectiontopics/FailFast.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates the "fail-fast" behavior +import java.util.*; + +public class FailFast { + public static void main(String[] args) { + Collection c = new ArrayList<>(); + Iterator it = c.iterator(); + c.add("An object"); + try { + String s = it.next(); + } catch(ConcurrentModificationException e) { + System.out.println(e); + } + } +} +/* Output: +java.util.ConcurrentModificationException +*/ diff --git a/code/collectiontopics/FillMapTest.java b/code/collectiontopics/FillMapTest.java new file mode 100644 index 00000000..5cfd612b --- /dev/null +++ b/code/collectiontopics/FillMapTest.java @@ -0,0 +1,32 @@ +// collectiontopics/FillMapTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import onjava.*; + +public class FillMapTest { + public static void main(String[] args) { + Map mcs = FillMap.basic( + new Rand.String(4), new Count.Integer(), 7); + System.out.println(mcs); + HashMap hashm = + FillMap.create(new Rand.String(4), + new Count.Integer(), HashMap::new, 7); + System.out.println(hashm); + LinkedHashMap linkm = + FillMap.create(new Rand.String(4), + new Count.Integer(), LinkedHashMap::new, 7); + System.out.println(linkm); + } +} +/* Output: +{npcc=1, ztdv=6, gvgm=3, btpe=0, einn=4, eelo=5, +uxsz=2} +{npcc=1, ztdv=6, gvgm=3, btpe=0, einn=4, eelo=5, +uxsz=2} +{btpe=0, npcc=1, uxsz=2, gvgm=3, einn=4, eelo=5, +ztdv=6} +*/ diff --git a/code/collectiontopics/FillingLists.java b/code/collectiontopics/FillingLists.java new file mode 100644 index 00000000..32bdb8ef --- /dev/null +++ b/code/collectiontopics/FillingLists.java @@ -0,0 +1,35 @@ +// collectiontopics/FillingLists.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Collections.fill() & Collections.nCopies() +import java.util.*; + +class StringAddress { + private String s; + StringAddress(String s) { this.s = s; } + @Override + public String toString() { + return super.toString() + " " + s; + } +} + +public class FillingLists { + public static void main(String[] args) { + List list = new ArrayList<>( + Collections.nCopies(4, + new StringAddress("Hello"))); + System.out.println(list); + Collections.fill(list, + new StringAddress("World!")); + System.out.println(list); + } +} +/* Output: +[StringAddress@15db9742 Hello, StringAddress@15db9742 +Hello, StringAddress@15db9742 Hello, +StringAddress@15db9742 Hello] +[StringAddress@6d06d69c World!, StringAddress@6d06d69c +World!, StringAddress@6d06d69c World!, +StringAddress@6d06d69c World!] +*/ diff --git a/code/collectiontopics/FunctionalMap.java b/code/collectiontopics/FunctionalMap.java new file mode 100644 index 00000000..404a1a64 --- /dev/null +++ b/code/collectiontopics/FunctionalMap.java @@ -0,0 +1,38 @@ +// collectiontopics/FunctionalMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Functional operations on a Map +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import static onjava.HTMLColors.*; + +public class FunctionalMap { + public static void main(String[] args) { + MAP.entrySet().stream() + .map(Map.Entry::getValue) + .filter(v -> v.startsWith("Dark")) + .map(v -> v.replaceFirst("Dark", "Hot")) + .forEach(System.out::println); + } +} +/* Output: +HotBlue +HotCyan +HotGoldenRod +HotGray +HotGreen +HotKhaki +HotMagenta +HotOliveGreen +HotOrange +HotOrchid +HotRed +HotSalmon +HotSeaGreen +HotSlateBlue +HotSlateGray +HotTurquoise +HotViolet +*/ diff --git a/code/collectiontopics/HTMLColorTest.java b/code/collectiontopics/HTMLColorTest.java new file mode 100644 index 00000000..99037ced --- /dev/null +++ b/code/collectiontopics/HTMLColorTest.java @@ -0,0 +1,103 @@ +// collectiontopics/HTMLColorTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import static onjava.HTMLColors.*; + +public class HTMLColorTest { + static final int DISPLAY_SIZE = 20; + public static void main(String[] args) { + show(MAP, DISPLAY_SIZE); + border(); + showInv(INVMAP, DISPLAY_SIZE); + border(); + show(LIST, DISPLAY_SIZE); + border(); + showrgb(RGBLIST, DISPLAY_SIZE); + } +} +/* Output: +0xF0F8FF: AliceBlue +0xFAEBD7: AntiqueWhite +0x7FFFD4: Aquamarine +0xF0FFFF: Azure +0xF5F5DC: Beige +0xFFE4C4: Bisque +0x000000: Black +0xFFEBCD: BlanchedAlmond +0x0000FF: Blue +0x8A2BE2: BlueViolet +0xA52A2A: Brown +0xDEB887: BurlyWood +0x5F9EA0: CadetBlue +0x7FFF00: Chartreuse +0xD2691E: Chocolate +0xFF7F50: Coral +0x6495ED: CornflowerBlue +0xFFF8DC: Cornsilk +0xDC143C: Crimson +0x00FFFF: Cyan +****************************** +AliceBlue 0xF0F8FF +AntiqueWhite 0xFAEBD7 +Aquamarine 0x7FFFD4 +Azure 0xF0FFFF +Beige 0xF5F5DC +Bisque 0xFFE4C4 +Black 0x000000 +BlanchedAlmond 0xFFEBCD +Blue 0x0000FF +BlueViolet 0x8A2BE2 +Brown 0xA52A2A +BurlyWood 0xDEB887 +CadetBlue 0x5F9EA0 +Chartreuse 0x7FFF00 +Chocolate 0xD2691E +Coral 0xFF7F50 +CornflowerBlue 0x6495ED +Cornsilk 0xFFF8DC +Crimson 0xDC143C +Cyan 0x00FFFF +****************************** +AliceBlue +AntiqueWhite +Aquamarine +Azure +Beige +Bisque +Black +BlanchedAlmond +Blue +BlueViolet +Brown +BurlyWood +CadetBlue +Chartreuse +Chocolate +Coral +CornflowerBlue +Cornsilk +Crimson +Cyan +****************************** +0xF0F8FF +0xFAEBD7 +0x7FFFD4 +0xF0FFFF +0xF5F5DC +0xFFE4C4 +0x000000 +0xFFEBCD +0x0000FF +0x8A2BE2 +0xA52A2A +0xDEB887 +0x5F9EA0 +0x7FFF00 +0xD2691E +0xFF7F50 +0x6495ED +0xFFF8DC +0xDC143C +0x00FFFF +*/ diff --git a/code/collectiontopics/LinkedHashMapDemo.java b/code/collectiontopics/LinkedHashMapDemo.java new file mode 100644 index 00000000..d0b93393 --- /dev/null +++ b/code/collectiontopics/LinkedHashMapDemo.java @@ -0,0 +1,31 @@ +// collectiontopics/LinkedHashMapDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// What you can do with a LinkedHashMap +import java.util.*; +import onjava.*; + +public class LinkedHashMapDemo { + public static void main(String[] args) { + LinkedHashMap linkedMap = + new LinkedHashMap<>(new CountMap(9)); + System.out.println(linkedMap); + // Least-recently-used order: + linkedMap = + new LinkedHashMap<>(16, 0.75f, true); + linkedMap.putAll(new CountMap(9)); + System.out.println(linkedMap); + for(int i = 0; i < 6; i++) + linkedMap.get(i); + System.out.println(linkedMap); + linkedMap.get(0); + System.out.println(linkedMap); + } +} +/* Output: +{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0} +{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0} +{6=G0, 7=H0, 8=I0, 0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0} +{6=G0, 7=H0, 8=I0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 0=A0} +*/ diff --git a/code/collectiontopics/ListOps.java b/code/collectiontopics/ListOps.java new file mode 100644 index 00000000..824ffba9 --- /dev/null +++ b/code/collectiontopics/ListOps.java @@ -0,0 +1,167 @@ +// collectiontopics/ListOps.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Things you can do with Lists +import java.util.*; +import onjava.HTMLColors; + +public class ListOps { + // Create a short list for testing: + static final List LIST = + HTMLColors.LIST.subList(0, 10); + private static boolean b; + private static String s; + private static int i; + private static Iterator it; + private static ListIterator lit; + public static void basicTest(List a) { + a.add(1, "x"); // Add at location 1 + a.add("x"); // Add at end + // Add a collection: + a.addAll(LIST); + // Add a collection starting at location 3: + a.addAll(3, LIST); + b = a.contains("1"); // Is it in there? + // Is the entire collection in there? + b = a.containsAll(LIST); + // Lists allow random access, which is cheap + // for ArrayList, expensive for LinkedList: + s = a.get(1); // Get (typed) object at location 1 + i = a.indexOf("1"); // Tell index of object + b = a.isEmpty(); // Any elements inside? + it = a.iterator(); // Ordinary Iterator + lit = a.listIterator(); // ListIterator + lit = a.listIterator(3); // Start at location 3 + i = a.lastIndexOf("1"); // Last match + a.remove(1); // Remove location 1 + a.remove("3"); // Remove this object + a.set(1, "y"); // Set location 1 to "y" + // Keep everything that's in the argument + // (the intersection of the two sets): + a.retainAll(LIST); + // Remove everything that's in the argument: + a.removeAll(LIST); + i = a.size(); // How big is it? + a.clear(); // Remove all elements + } + public static void iterMotion(List a) { + ListIterator it = a.listIterator(); + b = it.hasNext(); + b = it.hasPrevious(); + s = it.next(); + i = it.nextIndex(); + s = it.previous(); + i = it.previousIndex(); + } + public static void iterManipulation(List a) { + ListIterator it = a.listIterator(); + it.add("47"); + // Must move to an element after add(): + it.next(); + // Remove the element after the new one: + it.remove(); + // Must move to an element after remove(): + it.next(); + // Change the element after the deleted one: + it.set("47"); + } + public static void testVisual(List a) { + System.out.println(a); + List b = LIST; + System.out.println("b = " + b); + a.addAll(b); + a.addAll(b); + System.out.println(a); + // Insert, remove, and replace elements + // using a ListIterator: + ListIterator x = + a.listIterator(a.size()/2); + x.add("one"); + System.out.println(a); + System.out.println(x.next()); + x.remove(); + System.out.println(x.next()); + x.set("47"); + System.out.println(a); + // Traverse the list backwards: + x = a.listIterator(a.size()); + while(x.hasPrevious()) + System.out.print(x.previous() + " "); + System.out.println(); + System.out.println("testVisual finished"); + } + // There are some things that only LinkedLists can do: + public static void testLinkedList() { + LinkedList ll = new LinkedList<>(); + ll.addAll(LIST); + System.out.println(ll); + // Treat it like a stack, pushing: + ll.addFirst("one"); + ll.addFirst("two"); + System.out.println(ll); + // Like "peeking" at the top of a stack: + System.out.println(ll.getFirst()); + // Like popping a stack: + System.out.println(ll.removeFirst()); + System.out.println(ll.removeFirst()); + // Treat it like a queue, pulling elements + // off the tail end: + System.out.println(ll.removeLast()); + System.out.println(ll); + } + public static void main(String[] args) { + // Make and fill a new list each time: + basicTest(new LinkedList<>(LIST)); + basicTest(new ArrayList<>(LIST)); + iterMotion(new LinkedList<>(LIST)); + iterMotion(new ArrayList<>(LIST)); + iterManipulation(new LinkedList<>(LIST)); + iterManipulation(new ArrayList<>(LIST)); + testVisual(new LinkedList<>(LIST)); + testLinkedList(); + } +} +/* Output: +[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet] +b = [AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet] +[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet, +AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet, +AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet] +[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet, +AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, one, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet, +AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet] +Bisque +Black +[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet, +AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, one, +47, BlanchedAlmond, Blue, BlueViolet, AliceBlue, +AntiqueWhite, Aquamarine, Azure, Beige, Bisque, Black, +BlanchedAlmond, Blue, BlueViolet] +BlueViolet Blue BlanchedAlmond Black Bisque Beige Azure +Aquamarine AntiqueWhite AliceBlue BlueViolet Blue +BlanchedAlmond 47 one Beige Azure Aquamarine +AntiqueWhite AliceBlue BlueViolet Blue BlanchedAlmond +Black Bisque Beige Azure Aquamarine AntiqueWhite +AliceBlue +testVisual finished +[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue, BlueViolet] +[two, one, AliceBlue, AntiqueWhite, Aquamarine, Azure, +Beige, Bisque, Black, BlanchedAlmond, Blue, BlueViolet] +two +two +one +BlueViolet +[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, +Bisque, Black, BlanchedAlmond, Blue] +*/ diff --git a/code/collectiontopics/ListSortSearch.java b/code/collectiontopics/ListSortSearch.java new file mode 100644 index 00000000..4d1fbcf8 --- /dev/null +++ b/code/collectiontopics/ListSortSearch.java @@ -0,0 +1,57 @@ +// collectiontopics/ListSortSearch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Sorting/searching Lists with Collections utilities +import java.util.*; + +public class ListSortSearch { + public static void main(String[] args) { + List list = + new ArrayList<>(Utilities.list); + list.addAll(Utilities.list); + System.out.println(list); + Collections.shuffle(list, new Random(47)); + System.out.println("Shuffled: " + list); + // Use ListIterator to trim off last elements: + ListIterator it = list.listIterator(10); + while(it.hasNext()) { + it.next(); + it.remove(); + } + System.out.println("Trimmed: " + list); + Collections.sort(list); + System.out.println("Sorted: " + list); + String key = list.get(7); + int index = Collections.binarySearch(list, key); + System.out.println( + "Location of " + key + " is " + index + + ", list.get(" + index + ") = " + + list.get(index)); + Collections.sort(list, + String.CASE_INSENSITIVE_ORDER); + System.out.println( + "Case-insensitive sorted: " + list); + key = list.get(7); + index = Collections.binarySearch(list, key, + String.CASE_INSENSITIVE_ORDER); + System.out.println( + "Location of " + key + " is " + index + + ", list.get(" + index + ") = " + + list.get(index)); + } +} +/* Output: +[one, Two, three, Four, five, six, one, one, Two, +three, Four, five, six, one] +Shuffled: [Four, five, one, one, Two, six, six, three, +three, five, Four, Two, one, one] +Trimmed: [Four, five, one, one, Two, six, six, three, +three, five] +Sorted: [Four, Two, five, five, one, one, six, six, +three, three] +Location of six is 7, list.get(7) = six +Case-insensitive sorted: [five, five, Four, one, one, +six, six, three, three, Two] +Location of three is 7, list.get(7) = three +*/ diff --git a/code/collectiontopics/MapOps.java b/code/collectiontopics/MapOps.java new file mode 100644 index 00000000..b214fa2d --- /dev/null +++ b/code/collectiontopics/MapOps.java @@ -0,0 +1,76 @@ +// collectiontopics/MapOps.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Things you can do with Maps +import java.util.concurrent.*; +import java.util.*; +import onjava.*; + +public class MapOps { + public static + void printKeys(Map map) { + System.out.print("Size = " + map.size() + ", "); + System.out.print("Keys: "); + // Produce a Set of the keys: + System.out.println(map.keySet()); + } + public static + void test(Map map) { + System.out.println( + map.getClass().getSimpleName()); + map.putAll(new CountMap(25)); + // Map has 'Set' behavior for keys: + map.putAll(new CountMap(25)); + printKeys(map); + // Producing a Collection of the values: + System.out.print("Values: "); + System.out.println(map.values()); + System.out.println(map); + System.out.println("map.containsKey(11): " + + map.containsKey(11)); + System.out.println( + "map.get(11): " + map.get(11)); + System.out.println("map.containsValue(\"F0\"): " + + map.containsValue("F0")); + Integer key = map.keySet().iterator().next(); + System.out.println("First key in map: " + key); + map.remove(key); + printKeys(map); + map.clear(); + System.out.println( + "map.isEmpty(): " + map.isEmpty()); + map.putAll(new CountMap(25)); + // Operations on the Set change the Map: + map.keySet().removeAll(map.keySet()); + System.out.println( + "map.isEmpty(): " + map.isEmpty()); + } + public static void main(String[] args) { + test(new HashMap<>()); + test(new TreeMap<>()); + test(new LinkedHashMap<>()); + test(new IdentityHashMap<>()); + test(new ConcurrentHashMap<>()); + test(new WeakHashMap<>()); + } +} +/* Output: (First 11 Lines) +HashMap +Size = 25, Keys: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] +Values: [A0, B0, C0, D0, E0, F0, G0, H0, I0, J0, K0, +L0, M0, N0, O0, P0, Q0, R0, S0, T0, U0, V0, W0, X0, Y0] +{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, +9=J0, 10=K0, 11=L0, 12=M0, 13=N0, 14=O0, 15=P0, 16=Q0, +17=R0, 18=S0, 19=T0, 20=U0, 21=V0, 22=W0, 23=X0, 24=Y0} +map.containsKey(11): true +map.get(11): L0 +map.containsValue("F0"): true +First key in map: 0 +Size = 24, Keys: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] +map.isEmpty(): true +map.isEmpty(): true + ... +*/ diff --git a/code/collectiontopics/NavMap.java b/code/collectiontopics/NavMap.java new file mode 100644 index 00000000..076ae841 --- /dev/null +++ b/code/collectiontopics/NavMap.java @@ -0,0 +1,96 @@ +// collectiontopics/NavMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// NavigableMap produces pieces of a Map +import java.util.*; +import java.util.concurrent.*; +import static onjava.HTMLColors.*; + +public class NavMap { + public static final + NavigableMap COLORS = + new ConcurrentSkipListMap<>(MAP); + public static void main(String[] args) { + show(COLORS.firstEntry()); + border(); + show(COLORS.lastEntry()); + border(); + NavigableMap toLime = + COLORS.headMap(rgb("Lime"), true); + show(toLime); + border(); + show(COLORS.ceilingEntry(rgb("DeepSkyBlue") - 1)); + border(); + show(COLORS.floorEntry(rgb("DeepSkyBlue") - 1)); + border(); + show(toLime.descendingMap()); + border(); + show(COLORS.tailMap(rgb("MistyRose"), true)); + border(); + show(COLORS.subMap( + rgb("Orchid"), true, + rgb("DarkSalmon"), false)); + } +} +/* Output: +0x000000: Black +****************************** +0xFFFFFF: White +****************************** +0x000000: Black +0x000080: Navy +0x00008B: DarkBlue +0x0000CD: MediumBlue +0x0000FF: Blue +0x006400: DarkGreen +0x008000: Green +0x008080: Teal +0x008B8B: DarkCyan +0x00BFFF: DeepSkyBlue +0x00CED1: DarkTurquoise +0x00FA9A: MediumSpringGreen +0x00FF00: Lime +****************************** +0x00BFFF: DeepSkyBlue +****************************** +0x008B8B: DarkCyan +****************************** +0x00FF00: Lime +0x00FA9A: MediumSpringGreen +0x00CED1: DarkTurquoise +0x00BFFF: DeepSkyBlue +0x008B8B: DarkCyan +0x008080: Teal +0x008000: Green +0x006400: DarkGreen +0x0000FF: Blue +0x0000CD: MediumBlue +0x00008B: DarkBlue +0x000080: Navy +0x000000: Black +****************************** +0xFFE4E1: MistyRose +0xFFEBCD: BlanchedAlmond +0xFFEFD5: PapayaWhip +0xFFF0F5: LavenderBlush +0xFFF5EE: SeaShell +0xFFF8DC: Cornsilk +0xFFFACD: LemonChiffon +0xFFFAF0: FloralWhite +0xFFFAFA: Snow +0xFFFF00: Yellow +0xFFFFE0: LightYellow +0xFFFFF0: Ivory +0xFFFFFF: White +****************************** +0xDA70D6: Orchid +0xDAA520: GoldenRod +0xDB7093: PaleVioletRed +0xDC143C: Crimson +0xDCDCDC: Gainsboro +0xDDA0DD: Plum +0xDEB887: BurlyWood +0xE0FFFF: LightCyan +0xE6E6FA: Lavender +*/ diff --git a/code/collectiontopics/QueueBehavior.java b/code/collectiontopics/QueueBehavior.java new file mode 100644 index 00000000..136fbaf8 --- /dev/null +++ b/code/collectiontopics/QueueBehavior.java @@ -0,0 +1,50 @@ +// collectiontopics/QueueBehavior.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Compares basic behavior +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; + +public class QueueBehavior { + static Stream strings() { + return Arrays.stream( + ("one two three four five six seven " + + "eight nine ten").split(" ")); + } + static void test(int id, Queue queue) { + System.out.print(id + ": "); + strings().map(queue::offer).count(); + while(queue.peek() != null) + System.out.print(queue.remove() + " "); + System.out.println(); + } + public static void main(String[] args) { + int count = 10; + test(1, new LinkedList<>()); + test(2, new PriorityQueue<>()); + test(3, new ArrayBlockingQueue<>(count)); + test(4, new ConcurrentLinkedQueue<>()); + test(5, new LinkedBlockingQueue<>()); + test(6, new PriorityBlockingQueue<>()); + test(7, new ArrayDeque<>()); + test(8, new ConcurrentLinkedDeque<>()); + test(9, new LinkedBlockingDeque<>()); + test(10, new LinkedTransferQueue<>()); + test(11, new SynchronousQueue<>()); + } +} +/* Output: +1: one two three four five six seven eight nine ten +2: eight five four nine one seven six ten three two +3: one two three four five six seven eight nine ten +4: one two three four five six seven eight nine ten +5: one two three four five six seven eight nine ten +6: eight five four nine one seven six ten three two +7: one two three four five six seven eight nine ten +8: one two three four five six seven eight nine ten +9: one two three four five six seven eight nine ten +10: one two three four five six seven eight nine ten +11: +*/ diff --git a/code/collectiontopics/ReadOnly.java b/code/collectiontopics/ReadOnly.java new file mode 100644 index 00000000..93c336c4 --- /dev/null +++ b/code/collectiontopics/ReadOnly.java @@ -0,0 +1,56 @@ +// collectiontopics/ReadOnly.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using the Collections.unmodifiable methods +import java.util.*; +import onjava.*; + +public class ReadOnly { + static Collection data = + new ArrayList<>(Countries.names(6)); + public static void main(String[] args) { + Collection c = + Collections.unmodifiableCollection( + new ArrayList<>(data)); + System.out.println(c); // Reading is OK + //- c.add("one"); // Can't change it + + List a = Collections.unmodifiableList( + new ArrayList<>(data)); + ListIterator lit = a.listIterator(); + System.out.println(lit.next()); // Reading is OK + //- lit.add("one"); // Can't change it + + Set s = Collections.unmodifiableSet( + new HashSet<>(data)); + System.out.println(s); // Reading is OK + //- s.add("one"); // Can't change it + + // For a SortedSet: + Set ss = + Collections.unmodifiableSortedSet( + new TreeSet<>(data)); + + Map m = + Collections.unmodifiableMap( + new HashMap<>(Countries.capitals(6))); + System.out.println(m); // Reading is OK + //- m.put("Ralph", "Howdy!"); + + // For a SortedMap: + Map sm = + Collections.unmodifiableSortedMap( + new TreeMap<>(Countries.capitals(6))); + } +} +/* Output: +[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, +BURUNDI] +ALGERIA +[BENIN, BOTSWANA, ANGOLA, BURKINA FASO, ALGERIA, +BURUNDI] +{BENIN=Porto-Novo, BOTSWANA=Gaberone, ANGOLA=Luanda, +BURKINA FASO=Ouagadougou, ALGERIA=Algiers, +BURUNDI=Bujumbura} +*/ diff --git a/code/collectiontopics/References.java b/code/collectiontopics/References.java new file mode 100644 index 00000000..5fcca940 --- /dev/null +++ b/code/collectiontopics/References.java @@ -0,0 +1,92 @@ +// collectiontopics/References.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates Reference objects +import java.lang.ref.*; +import java.util.*; + +class VeryBig { + private static final int SIZE = 10000; + private long[] la = new long[SIZE]; + private String ident; + VeryBig(String id) { ident = id; } + @Override + public String toString() { return ident; } + @SuppressWarnings("deprecation") + @Override + protected void finalize() { + System.out.println("Finalizing " + ident); + } +} + +public class References { + private static ReferenceQueue rq = + new ReferenceQueue<>(); + public static void checkQueue() { + Reference inq = rq.poll(); + if(inq != null) + System.out.println("In queue: " + inq.get()); + } + public static void main(String[] args) { + int size = 10; + // Or, choose size via the command line: + if(args.length > 0) + size = Integer.valueOf(args[0]); + LinkedList> sa = + new LinkedList<>(); + for(int i = 0; i < size; i++) { + sa.add(new SoftReference<>( + new VeryBig("Soft " + i), rq)); + System.out.println( + "Just created: " + sa.getLast()); + checkQueue(); + } + LinkedList> wa = + new LinkedList<>(); + for(int i = 0; i < size; i++) { + wa.add(new WeakReference<>( + new VeryBig("Weak " + i), rq)); + System.out.println( + "Just created: " + wa.getLast()); + checkQueue(); + } + SoftReference s = + new SoftReference<>(new VeryBig("Soft")); + WeakReference w = + new WeakReference<>(new VeryBig("Weak")); + System.gc(); + LinkedList> pa = + new LinkedList<>(); + for(int i = 0; i < size; i++) { + pa.add(new PhantomReference<>( + new VeryBig("Phantom " + i), rq)); + System.out.println( + "Just created: " + pa.getLast()); + checkQueue(); + } + } +} +/* Output: (First and Last 10 Lines) +Just created: java.lang.ref.SoftReference@15db9742 +Just created: java.lang.ref.SoftReference@6d06d69c +Just created: java.lang.ref.SoftReference@7852e922 +Just created: java.lang.ref.SoftReference@4e25154f +Just created: java.lang.ref.SoftReference@70dea4e +Just created: java.lang.ref.SoftReference@5c647e05 +Just created: java.lang.ref.SoftReference@33909752 +Just created: java.lang.ref.SoftReference@55f96302 +Just created: java.lang.ref.SoftReference@3d4eac69 +Just created: java.lang.ref.SoftReference@42a57993 +...________...________...________...________... +Just created: java.lang.ref.PhantomReference@45ee12a7 +In queue: null +Just created: java.lang.ref.PhantomReference@330bedb4 +In queue: null +Just created: java.lang.ref.PhantomReference@2503dbd3 +In queue: null +Just created: java.lang.ref.PhantomReference@4b67cf4d +In queue: null +Just created: java.lang.ref.PhantomReference@7ea987ac +In queue: null +*/ diff --git a/code/collectiontopics/SetOrder.java b/code/collectiontopics/SetOrder.java new file mode 100644 index 00000000..1c25be23 --- /dev/null +++ b/code/collectiontopics/SetOrder.java @@ -0,0 +1,92 @@ +// collectiontopics/SetOrder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.HTMLColors; + +public class SetOrder { + static String[] sets = { + "java.util.HashSet", + "java.util.TreeSet", + "java.util.concurrent.ConcurrentSkipListSet", + "java.util.LinkedHashSet", + "java.util.concurrent.CopyOnWriteArraySet", + }; + static final List RLIST = + new ArrayList<>(HTMLColors.LIST); + static { + Collections.reverse(RLIST); + } + public static void + main(String[] args) throws Exception { + for(String type: sets) { + System.out.format("[-> %s <-]%n", + type.substring(type.lastIndexOf('.') + 1)); + @SuppressWarnings({"unchecked", "deprecation"}) + Set set = (Set) + Class.forName(type).newInstance(); + set.addAll(RLIST); + set.stream() + .limit(10) + .forEach(System.out::println); + } + } +} +/* Output: +[-> HashSet <-] +MediumOrchid +PaleGoldenRod +Sienna +LightSlateGray +DarkSeaGreen +Black +Gainsboro +Orange +LightCoral +DodgerBlue +[-> TreeSet <-] +AliceBlue +AntiqueWhite +Aquamarine +Azure +Beige +Bisque +Black +BlanchedAlmond +Blue +BlueViolet +[-> ConcurrentSkipListSet <-] +AliceBlue +AntiqueWhite +Aquamarine +Azure +Beige +Bisque +Black +BlanchedAlmond +Blue +BlueViolet +[-> LinkedHashSet <-] +YellowGreen +Yellow +WhiteSmoke +White +Wheat +Violet +Turquoise +Tomato +Thistle +Teal +[-> CopyOnWriteArraySet <-] +YellowGreen +Yellow +WhiteSmoke +White +Wheat +Violet +Turquoise +Tomato +Thistle +Teal +*/ diff --git a/code/collectiontopics/SimpleDeques.java b/code/collectiontopics/SimpleDeques.java new file mode 100644 index 00000000..fbb4a5ff --- /dev/null +++ b/code/collectiontopics/SimpleDeques.java @@ -0,0 +1,70 @@ +// collectiontopics/SimpleDeques.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Very basic test of Deques +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; + +class CountString implements Supplier { + private int n = 0; + CountString() {} + CountString(int start) { n = start; } + @Override + public String get() { + return Integer.toString(n++); + } +} + +public class SimpleDeques { + static void test(Deque deque) { + CountString s1 = new CountString(), + s2 = new CountString(20); + for(int n = 0; n < 8; n++) { + deque.offerFirst(s1.get()); + deque.offerLast(s2.get()); // Same as offer() + } + System.out.println(deque); + String result = ""; + while(deque.size() > 0) { + System.out.print(deque.peekFirst() + " "); + result += deque.pollFirst() + " "; + System.out.print(deque.peekLast() + " "); + result += deque.pollLast() + " "; + } + System.out.println("\n" + result); + } + public static void main(String[] args) { + int count = 10; + System.out.println("LinkedList"); + test(new LinkedList<>()); + System.out.println("ArrayDeque"); + test(new ArrayDeque<>()); + System.out.println("LinkedBlockingDeque"); + test(new LinkedBlockingDeque<>(count)); + System.out.println("ConcurrentLinkedDeque"); + test(new ConcurrentLinkedDeque<>()); + } +} +/* Output: +LinkedList +[7, 6, 5, 4, 3, 2, 1, 0, 20, 21, 22, 23, 24, 25, 26, +27] +7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 +7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 +ArrayDeque +[7, 6, 5, 4, 3, 2, 1, 0, 20, 21, 22, 23, 24, 25, 26, +27] +7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 +7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 +LinkedBlockingDeque +[4, 3, 2, 1, 0, 20, 21, 22, 23, 24] +4 24 3 23 2 22 1 21 0 20 +4 24 3 23 2 22 1 21 0 20 +ConcurrentLinkedDeque +[7, 6, 5, 4, 3, 2, 1, 0, 20, 21, 22, 23, 24, 25, 26, +27] +7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 +7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 +*/ diff --git a/code/collectiontopics/SortedMapDemo.java b/code/collectiontopics/SortedMapDemo.java new file mode 100644 index 00000000..4d57d34a --- /dev/null +++ b/code/collectiontopics/SortedMapDemo.java @@ -0,0 +1,42 @@ +// collectiontopics/SortedMapDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// What you can do with a TreeMap +import java.util.*; +import onjava.*; + +public class SortedMapDemo { + public static void main(String[] args) { + TreeMap sortedMap = + new TreeMap<>(new CountMap(10)); + System.out.println(sortedMap); + Integer low = sortedMap.firstKey(); + Integer high = sortedMap.lastKey(); + System.out.println(low); + System.out.println(high); + Iterator it = + sortedMap.keySet().iterator(); + for(int i = 0; i <= 6; i++) { + if(i == 3) low = it.next(); + if(i == 6) high = it.next(); + else it.next(); + } + System.out.println(low); + System.out.println(high); + System.out.println(sortedMap.subMap(low, high)); + System.out.println(sortedMap.headMap(high)); + System.out.println(sortedMap.tailMap(low)); + } +} +/* Output: +{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, +9=J0} +0 +9 +3 +7 +{3=D0, 4=E0, 5=F0, 6=G0} +{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0} +{3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, 9=J0} +*/ diff --git a/code/collectiontopics/SortedSetDemo.java b/code/collectiontopics/SortedSetDemo.java new file mode 100644 index 00000000..6ed81fb1 --- /dev/null +++ b/code/collectiontopics/SortedSetDemo.java @@ -0,0 +1,42 @@ +// collectiontopics/SortedSetDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import static java.util.stream.Collectors.*; + +public class SortedSetDemo { + public static void main(String[] args) { + SortedSet sortedSet = + Arrays.stream( + "one two three four five six seven eight" + .split(" ")) + .collect(toCollection(TreeSet::new)); + System.out.println(sortedSet); + String low = sortedSet.first(); + String high = sortedSet.last(); + System.out.println(low); + System.out.println(high); + Iterator it = sortedSet.iterator(); + for(int i = 0; i <= 6; i++) { + if(i == 3) low = it.next(); + if(i == 6) high = it.next(); + else it.next(); + } + System.out.println(low); + System.out.println(high); + System.out.println(sortedSet.subSet(low, high)); + System.out.println(sortedSet.headSet(high)); + System.out.println(sortedSet.tailSet(low)); + } +} +/* Output: +[eight, five, four, one, seven, six, three, two] +eight +two +one +two +[one, seven, six, three] +[eight, five, four, one, seven, six, three] +[one, seven, six, three, two] +*/ diff --git a/code/collectiontopics/Stacks.java b/code/collectiontopics/Stacks.java new file mode 100644 index 00000000..79a684cb --- /dev/null +++ b/code/collectiontopics/Stacks.java @@ -0,0 +1,61 @@ +// collectiontopics/Stacks.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of Stack Class +import java.util.*; + +enum Month { JANUARY, FEBRUARY, MARCH, APRIL, + MAY, JUNE, JULY, AUGUST, SEPTEMBER, + OCTOBER, NOVEMBER } + +public class Stacks { + public static void main(String[] args) { + Stack stack = new Stack<>(); + for(Month m : Month.values()) + stack.push(m.toString()); + System.out.println("stack = " + stack); + // Treating a stack as a Vector: + stack.addElement("The last line"); + System.out.println( + "element 5 = " + stack.elementAt(5)); + System.out.println("popping elements:"); + while(!stack.empty()) + System.out.print(stack.pop() + " "); + + // Using a LinkedList as a Stack: + LinkedList lstack = new LinkedList<>(); + for(Month m : Month.values()) + lstack.addFirst(m.toString()); + System.out.println("lstack = " + lstack); + while(!lstack.isEmpty()) + System.out.print(lstack.removeFirst() + " "); + + // Using the Stack class from + // the Collections Chapter: + onjava.Stack stack2 = + new onjava.Stack<>(); + for(Month m : Month.values()) + stack2.push(m.toString()); + System.out.println("stack2 = " + stack2); + while(!stack2.isEmpty()) + System.out.print(stack2.pop() + " "); + + } +} +/* Output: +stack = [JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, +JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER] +element 5 = JUNE +popping elements: +The last line NOVEMBER OCTOBER SEPTEMBER AUGUST JULY +JUNE MAY APRIL MARCH FEBRUARY JANUARY lstack = +[NOVEMBER, OCTOBER, SEPTEMBER, AUGUST, JULY, JUNE, MAY, +APRIL, MARCH, FEBRUARY, JANUARY] +NOVEMBER OCTOBER SEPTEMBER AUGUST JULY JUNE MAY APRIL +MARCH FEBRUARY JANUARY stack2 = [NOVEMBER, OCTOBER, +SEPTEMBER, AUGUST, JULY, JUNE, MAY, APRIL, MARCH, +FEBRUARY, JANUARY] +NOVEMBER OCTOBER SEPTEMBER AUGUST JULY JUNE MAY APRIL +MARCH FEBRUARY JANUARY +*/ diff --git a/code/collectiontopics/StreamFillMaps.java b/code/collectiontopics/StreamFillMaps.java new file mode 100644 index 00000000..816a74b3 --- /dev/null +++ b/code/collectiontopics/StreamFillMaps.java @@ -0,0 +1,55 @@ +// collectiontopics/StreamFillMaps.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import onjava.*; + +class Letters +implements Supplier> { + private int number = 1; + private char letter = 'A'; + @Override + public Pair get() { + return new Pair<>(number++, "" + letter++); + } +} + +public class StreamFillMaps { + public static void main(String[] args) { + Map m = + Stream.generate(new Letters()) + .limit(11) + .collect(Collectors + .toMap(Pair::key, Pair::value)); + System.out.println(m); + + // Two separate Suppliers: + Rand.String rs = new Rand.String(3); + Count.Character cc = new Count.Character(); + Map mcs = Stream.generate( + () -> Pair.make(cc.get(), rs.get())) + .limit(8) + .collect(Collectors + .toMap(Pair::key, Pair::value)); + System.out.println(mcs); + + // A key Supplier and a single value: + Map mcs2 = Stream.generate( + () -> Pair.make(cc.get(), "Val")) + .limit(8) + .collect(Collectors + .toMap(Pair::key, Pair::value)); + System.out.println(mcs2); + } +} +/* Output: +{1=A, 2=B, 3=C, 4=D, 5=E, 6=F, 7=G, 8=H, 9=I, 10=J, +11=K} +{b=btp, c=enp, d=ccu, e=xsz, f=gvg, g=mei, h=nne, +i=elo} +{p=Val, q=Val, j=Val, k=Val, l=Val, m=Val, n=Val, +o=Val} +*/ diff --git a/code/collectiontopics/SuppliersCollectionTest.java b/code/collectiontopics/SuppliersCollectionTest.java new file mode 100644 index 00000000..b30f1490 --- /dev/null +++ b/code/collectiontopics/SuppliersCollectionTest.java @@ -0,0 +1,67 @@ +// collectiontopics/SuppliersCollectionTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import onjava.*; + +class Government implements Supplier { + static String[] foundation = ( + "strange women lying in ponds " + + "distributing swords is no basis " + + "for a system of government").split(" "); + private int index; + @Override + public String get() { + return foundation[index++]; + } +} + +public class SuppliersCollectionTest { + public static void main(String[] args) { + // Suppliers class from the Generics chapter: + Set set = Suppliers.create( + LinkedHashSet::new, new Government(), 15); + System.out.println(set); + List list = Suppliers.create( + LinkedList::new, new Government(), 15); + System.out.println(list); + list = new ArrayList<>(); + Suppliers.fill(list, new Government(), 15); + System.out.println(list); + + // Or we can use Streams: + set = Arrays.stream(Government.foundation) + .collect(Collectors.toSet()); + System.out.println(set); + list = Arrays.stream(Government.foundation) + .collect(Collectors.toList()); + System.out.println(list); + list = Arrays.stream(Government.foundation) + .collect(Collectors + .toCollection(LinkedList::new)); + System.out.println(list); + set = Arrays.stream(Government.foundation) + .collect(Collectors + .toCollection(LinkedHashSet::new)); + System.out.println(set); + } +} +/* Output: +[strange, women, lying, in, ponds, distributing, +swords, is, no, basis, for, a, system, of, government] +[strange, women, lying, in, ponds, distributing, +swords, is, no, basis, for, a, system, of, government] +[strange, women, lying, in, ponds, distributing, +swords, is, no, basis, for, a, system, of, government] +[ponds, no, a, in, swords, for, is, basis, strange, +system, government, distributing, of, women, lying] +[strange, women, lying, in, ponds, distributing, +swords, is, no, basis, for, a, system, of, government] +[strange, women, lying, in, ponds, distributing, +swords, is, no, basis, for, a, system, of, government] +[strange, women, lying, in, ponds, distributing, +swords, is, no, basis, for, a, system, of, government] +*/ diff --git a/code/collectiontopics/Synchronization.java b/code/collectiontopics/Synchronization.java new file mode 100644 index 00000000..c7d3b732 --- /dev/null +++ b/code/collectiontopics/Synchronization.java @@ -0,0 +1,24 @@ +// collectiontopics/Synchronization.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using the Collections.synchronized methods +import java.util.*; + +public class Synchronization { + public static void main(String[] args) { + Collection c = + Collections.synchronizedCollection( + new ArrayList<>()); + List list = Collections + .synchronizedList(new ArrayList<>()); + Set s = Collections + .synchronizedSet(new HashSet<>()); + Set ss = Collections + .synchronizedSortedSet(new TreeSet<>()); + Map m = Collections + .synchronizedMap(new HashMap<>()); + Map sm = Collections + .synchronizedSortedMap(new TreeMap<>()); + } +} diff --git a/code/collectiontopics/ToDoList.java b/code/collectiontopics/ToDoList.java new file mode 100644 index 00000000..b288e8e1 --- /dev/null +++ b/code/collectiontopics/ToDoList.java @@ -0,0 +1,56 @@ +// collectiontopics/ToDoList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A more complex use of PriorityQueue +import java.util.*; + +class ToDoItem implements Comparable { + private char primary; + private int secondary; + private String item; + ToDoItem(String td, char pri, int sec) { + primary = pri; + secondary = sec; + item = td; + } + @Override + public int compareTo(ToDoItem arg) { + if(primary > arg.primary) + return +1; + if(primary == arg.primary) + if(secondary > arg.secondary) + return +1; + else if(secondary == arg.secondary) + return 0; + return -1; + } + @Override + public String toString() { + return Character.toString(primary) + + secondary + ": " + item; + } +} + +class ToDoList { + public static void main(String[] args) { + PriorityQueue toDo = + new PriorityQueue<>(); + toDo.add(new ToDoItem("Empty trash", 'C', 4)); + toDo.add(new ToDoItem("Feed dog", 'A', 2)); + toDo.add(new ToDoItem("Feed bird", 'B', 7)); + toDo.add(new ToDoItem("Mow lawn", 'C', 3)); + toDo.add(new ToDoItem("Water lawn", 'A', 1)); + toDo.add(new ToDoItem("Feed cat", 'B', 1)); + while(!toDo.isEmpty()) + System.out.println(toDo.remove()); + } +} +/* Output: +A1: Water lawn +A2: Feed dog +B1: Feed cat +B7: Feed bird +C3: Mow lawn +C4: Empty trash +*/ diff --git a/code/collectiontopics/TypesForSets.java b/code/collectiontopics/TypesForSets.java new file mode 100644 index 00000000..9950b003 --- /dev/null +++ b/code/collectiontopics/TypesForSets.java @@ -0,0 +1,93 @@ +// collectiontopics/TypesForSets.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Methods necessary to put your own type in a Set +import java.util.*; +import java.util.function.*; +import java.util.Objects; + +class SetType { + protected int i; + SetType(int n) { i = n; } + @Override + public boolean equals(Object o) { + return o instanceof SetType && + Objects.equals(i, ((SetType)o).i); + } + @Override + public String toString() { + return Integer.toString(i); + } +} + +class HashType extends SetType { + HashType(int n) { super(n); } + @Override + public int hashCode() { + return Objects.hashCode(i); + } +} + +class TreeType extends SetType +implements Comparable { + TreeType(int n) { super(n); } + @Override + public int compareTo(TreeType arg) { + return Integer.compare(arg.i, i); + // Equivalent to: + // return arg.i < i ? -1 : (arg.i == i ? 0 : 1); + } +} + +public class TypesForSets { + static void + fill(Set set, Function type) { + for(int i = 10; i >= 5; i--) // Descending + set.add(type.apply(i)); + for(int i = 0; i < 5; i++) // Ascending + set.add(type.apply(i)); + } + static void + test(Set set, Function type) { + fill(set, type); + fill(set, type); // Try to add duplicates + fill(set, type); + System.out.println(set); + } + public static void main(String[] args) { + test(new HashSet<>(), HashType::new); + test(new LinkedHashSet<>(), HashType::new); + test(new TreeSet<>(), TreeType::new); + // Things that don't work: + test(new HashSet<>(), SetType::new); + test(new HashSet<>(), TreeType::new); + test(new LinkedHashSet<>(), SetType::new); + test(new LinkedHashSet<>(), TreeType::new); + try { + test(new TreeSet<>(), SetType::new); + } catch(Exception e) { + System.out.println(e.getMessage()); + } + try { + test(new TreeSet<>(), HashType::new); + } catch(Exception e) { + System.out.println(e.getMessage()); + } + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +[10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4] +[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] +[1, 6, 8, 6, 2, 7, 8, 9, 4, 10, 7, 5, 1, 3, 4, 9, 9, +10, 5, 3, 2, 0, 4, 1, 2, 0, 8, 3, 0, 10, 6, 5, 7] +[3, 1, 4, 8, 7, 6, 9, 5, 3, 0, 10, 5, 5, 10, 7, 8, 8, +9, 1, 4, 10, 2, 6, 9, 1, 6, 0, 3, 2, 0, 7, 2, 4] +[10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, +0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4] +[10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, +0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4] +SetType cannot be cast to java.lang.Comparable +HashType cannot be cast to java.lang.Comparable +*/ diff --git a/code/collectiontopics/Unsupported.java b/code/collectiontopics/Unsupported.java new file mode 100644 index 00000000..a66b1cfd --- /dev/null +++ b/code/collectiontopics/Unsupported.java @@ -0,0 +1,60 @@ +// collectiontopics/Unsupported.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Unsupported operations in Java collections +import java.util.*; + +public class Unsupported { + static void + check(String description, Runnable tst) { + try { + tst.run(); + } catch(Exception e) { + System.out.println(description + "(): " + e); + } + } + static void test(String msg, List list) { + System.out.println("--- " + msg + " ---"); + Collection c = list; + Collection subList = list.subList(1,8); + // Copy of the sublist: + Collection c2 = new ArrayList<>(subList); + check("retainAll", () -> c.retainAll(c2)); + check("removeAll", () -> c.removeAll(c2)); + check("clear", () -> c.clear()); + check("add", () -> c.add("X")); + check("addAll", () -> c.addAll(c2)); + check("remove", () -> c.remove("C")); + // The List.set() method modifies the value but + // doesn't change the size of the data structure: + check("List.set", () -> list.set(0, "X")); + } + public static void main(String[] args) { + List list = Arrays.asList( + "A B C D E F G H I J K L".split(" ")); + test("Modifiable Copy", new ArrayList<>(list)); + test("Arrays.asList()", list); + test("unmodifiableList()", + Collections.unmodifiableList( + new ArrayList<>(list))); + } +} +/* Output: +--- Modifiable Copy --- +--- Arrays.asList() --- +retainAll(): java.lang.UnsupportedOperationException +removeAll(): java.lang.UnsupportedOperationException +clear(): java.lang.UnsupportedOperationException +add(): java.lang.UnsupportedOperationException +addAll(): java.lang.UnsupportedOperationException +remove(): java.lang.UnsupportedOperationException +--- unmodifiableList() --- +retainAll(): java.lang.UnsupportedOperationException +removeAll(): java.lang.UnsupportedOperationException +clear(): java.lang.UnsupportedOperationException +add(): java.lang.UnsupportedOperationException +addAll(): java.lang.UnsupportedOperationException +remove(): java.lang.UnsupportedOperationException +List.set(): java.lang.UnsupportedOperationException +*/ diff --git a/code/collectiontopics/Utilities.java b/code/collectiontopics/Utilities.java new file mode 100644 index 00000000..a2acc427 --- /dev/null +++ b/code/collectiontopics/Utilities.java @@ -0,0 +1,88 @@ +// collectiontopics/Utilities.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple demonstrations of the Collections utilities +import java.util.*; + +public class Utilities { + static List list = Arrays.asList( + "one Two three Four five six one".split(" ")); + public static void main(String[] args) { + System.out.println(list); + System.out.println("'list' disjoint (Four)?: " + + Collections.disjoint(list, + Collections.singletonList("Four"))); + System.out.println( + "max: " + Collections.max(list)); + System.out.println( + "min: " + Collections.min(list)); + System.out.println( + "max w/ comparator: " + Collections.max(list, + String.CASE_INSENSITIVE_ORDER)); + System.out.println( + "min w/ comparator: " + Collections.min(list, + String.CASE_INSENSITIVE_ORDER)); + List sublist = + Arrays.asList("Four five six".split(" ")); + System.out.println("indexOfSubList: " + + Collections.indexOfSubList(list, sublist)); + System.out.println("lastIndexOfSubList: " + + Collections.lastIndexOfSubList(list, sublist)); + Collections.replaceAll(list, "one", "Yo"); + System.out.println("replaceAll: " + list); + Collections.reverse(list); + System.out.println("reverse: " + list); + Collections.rotate(list, 3); + System.out.println("rotate: " + list); + List source = + Arrays.asList("in the matrix".split(" ")); + Collections.copy(list, source); + System.out.println("copy: " + list); + Collections.swap(list, 0, list.size() - 1); + System.out.println("swap: " + list); + Collections.shuffle(list, new Random(47)); + System.out.println("shuffled: " + list); + Collections.fill(list, "pop"); + System.out.println("fill: " + list); + System.out.println("frequency of 'pop': " + + Collections.frequency(list, "pop")); + List dups = + Collections.nCopies(3, "snap"); + System.out.println("dups: " + dups); + System.out.println("'list' disjoint 'dups'?: " + + Collections.disjoint(list, dups)); + // Getting an old-style Enumeration: + Enumeration e = + Collections.enumeration(dups); + Vector v = new Vector<>(); + while(e.hasMoreElements()) + v.addElement(e.nextElement()); + // Converting an old-style Vector + // to a List via an Enumeration: + ArrayList arrayList = + Collections.list(v.elements()); + System.out.println("arrayList: " + arrayList); + } +} +/* Output: +[one, Two, three, Four, five, six, one] +'list' disjoint (Four)?: false +max: three +min: Four +max w/ comparator: Two +min w/ comparator: five +indexOfSubList: 3 +lastIndexOfSubList: 3 +replaceAll: [Yo, Two, three, Four, five, six, Yo] +reverse: [Yo, six, five, Four, three, Two, Yo] +rotate: [three, Two, Yo, Yo, six, five, Four] +copy: [in, the, matrix, Yo, six, five, Four] +swap: [Four, the, matrix, Yo, six, five, in] +shuffled: [six, matrix, the, Four, Yo, five, in] +fill: [pop, pop, pop, pop, pop, pop, pop] +frequency of 'pop': 7 +dups: [snap, snap, snap] +'list' disjoint 'dups'?: true +arrayList: [snap, snap, snap] +*/ diff --git a/code/com/mindviewinc/simple/List.java b/code/com/mindviewinc/simple/List.java new file mode 100644 index 00000000..84b30315 --- /dev/null +++ b/code/com/mindviewinc/simple/List.java @@ -0,0 +1,12 @@ +// com/mindviewinc/simple/List.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating a package +package com.mindviewinc.simple; + +public class List { + public List() { + System.out.println("com.mindviewinc.simple.List"); + } +} diff --git a/code/com/mindviewinc/simple/Vector.java b/code/com/mindviewinc/simple/Vector.java new file mode 100644 index 00000000..19824cce --- /dev/null +++ b/code/com/mindviewinc/simple/Vector.java @@ -0,0 +1,12 @@ +// com/mindviewinc/simple/Vector.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating a package +package com.mindviewinc.simple; + +public class Vector { + public Vector() { + System.out.println("com.mindviewinc.simple.Vector"); + } +} diff --git a/code/compression/GZIPcompress.java b/code/compression/GZIPcompress.java new file mode 100644 index 00000000..c9022e78 --- /dev/null +++ b/code/compression/GZIPcompress.java @@ -0,0 +1,45 @@ +// compression/GZIPcompress.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java GZIPcompress GZIPcompress.java} +// {VisuallyInspectOutput} +import java.util.zip.*; +import java.io.*; + +public class GZIPcompress { + public static void main(String[] args) { + if(args.length == 0) { + System.out.println( + "Usage: \nGZIPcompress file\n" + + "\tUses GZIP compression to compress " + + "the file to test.gz"); + System.exit(1); + } + try( + InputStream in = new BufferedInputStream( + new FileInputStream(args[0])); + BufferedOutputStream out = + new BufferedOutputStream( + new GZIPOutputStream( + new FileOutputStream("test.gz"))) + ) { + System.out.println("Writing file"); + int c; + while((c = in.read()) != -1) + out.write(c); + } catch(IOException e) { + throw new RuntimeException(e); + } + System.out.println("Reading file"); + try( + BufferedReader in2 = new BufferedReader( + new InputStreamReader(new GZIPInputStream( + new FileInputStream("test.gz")))) + ) { + in2.lines().forEach(System.out::println); + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/compression/ZipCompress.java b/code/compression/ZipCompress.java new file mode 100644 index 00000000..f9ce7670 --- /dev/null +++ b/code/compression/ZipCompress.java @@ -0,0 +1,83 @@ +// compression/ZipCompress.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Uses Zip compression to compress any +// number of files given on the command line +// {java ZipCompress ZipCompress.java} +// {VisuallyInspectOutput} +import java.util.zip.*; +import java.io.*; +import java.util.*; + +public class ZipCompress { + public static void main(String[] args) { + try( + FileOutputStream f = + new FileOutputStream("test.zip"); + CheckedOutputStream csum = + new CheckedOutputStream(f, new Adler32()); + ZipOutputStream zos = new ZipOutputStream(csum); + BufferedOutputStream out = + new BufferedOutputStream(zos) + ) { + zos.setComment("A test of Java Zipping"); + // No corresponding getComment(), though. + for(String arg : args) { + System.out.println("Writing file " + arg); + try( + InputStream in = new BufferedInputStream( + new FileInputStream(arg)) + ) { + zos.putNextEntry(new ZipEntry(arg)); + int c; + while((c = in.read()) != -1) + out.write(c); + } + out.flush(); + } + // Checksum valid only after the file is closed! + System.out.println( + "Checksum: " + csum.getChecksum().getValue()); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Now extract the files: + System.out.println("Reading file"); + try( + FileInputStream fi = + new FileInputStream("test.zip"); + CheckedInputStream csumi = + new CheckedInputStream(fi, new Adler32()); + ZipInputStream in2 = new ZipInputStream(csumi); + BufferedInputStream bis = + new BufferedInputStream(in2) + ) { + ZipEntry ze; + while((ze = in2.getNextEntry()) != null) { + System.out.println("Reading file " + ze); + int x; + while((x = bis.read()) != -1) + System.out.write(x); + } + if(args.length == 1) + System.out.println( + "Checksum: "+csumi.getChecksum().getValue()); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Alternative way to open and read Zip files: + try( + ZipFile zf = new ZipFile("test.zip") + ) { + Enumeration e = zf.entries(); + while(e.hasMoreElements()) { + ZipEntry ze2 = (ZipEntry)e.nextElement(); + System.out.println("File: " + ze2); + // ... and extract the data as before + } + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/concurrent/Baked.java b/code/concurrent/Baked.java new file mode 100644 index 00000000..d616d94b --- /dev/null +++ b/code/concurrent/Baked.java @@ -0,0 +1,31 @@ +// concurrent/Baked.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; +import onjava.Nap; + +public class Baked { + static class Pan {} + static Pan pan(Batter b) { + new Nap(0.1); + return new Pan(); + } + static Baked heat(Pan p) { + new Nap(0.1); + return new Baked(); + } + static CompletableFuture + bake(CompletableFuture cfb) { + return cfb + .thenApplyAsync(Baked::pan) + .thenApplyAsync(Baked::heat); + } + public static + Stream> batch() { + CompletableFuture batter = Batter.mix(); + return Stream.of(bake(batter), bake(batter), + bake(batter), bake(batter)); + } +} diff --git a/code/concurrent/Batter.java b/code/concurrent/Batter.java new file mode 100644 index 00000000..9fe14c4f --- /dev/null +++ b/code/concurrent/Batter.java @@ -0,0 +1,34 @@ +// concurrent/Batter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import onjava.Nap; + +public class Batter { + static class Eggs {} + static class Milk {} + static class Sugar {} + static class Flour {} + static T prepare(T ingredient) { + new Nap(0.1); + return ingredient; + } + static CompletableFuture prep(T ingredient) { + return CompletableFuture + .completedFuture(ingredient) + .thenApplyAsync(Batter::prepare); + } + public static CompletableFuture mix() { + CompletableFuture eggs = prep(new Eggs()); + CompletableFuture milk = prep(new Milk()); + CompletableFuture sugar = prep(new Sugar()); + CompletableFuture flour = prep(new Flour()); + CompletableFuture + .allOf(eggs, milk, sugar, flour) + .join(); + new Nap(0.1); // Mixing time + return + CompletableFuture.completedFuture(new Batter()); + } +} diff --git a/code/concurrent/Breakable.java b/code/concurrent/Breakable.java new file mode 100644 index 00000000..facd7095 --- /dev/null +++ b/code/concurrent/Breakable.java @@ -0,0 +1,29 @@ +// concurrent/Breakable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class Breakable { + String id; + private int failcount; + public Breakable(String id, int failcount) { + this.id = id; + this.failcount = failcount; + } + @Override + public String toString() { + return "Breakable_" + id + + " [" + failcount + "]"; + } + public static Breakable work(Breakable b) { + if(--b.failcount == 0) { + System.out.println( + "Throwing Exception for " + b.id + ""); + throw new RuntimeException( + "Breakable_" + b.id + " failed"); + } + System.out.println(b); + return b; + } +} diff --git a/code/concurrent/CachedThreadPool.java b/code/concurrent/CachedThreadPool.java new file mode 100644 index 00000000..e0b825a2 --- /dev/null +++ b/code/concurrent/CachedThreadPool.java @@ -0,0 +1,29 @@ +// concurrent/CachedThreadPool.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; + +public class CachedThreadPool { + public static void main(String[] args) { + ExecutorService exec = + Executors.newCachedThreadPool(); + IntStream.range(0, 10) + .mapToObj(NapTask::new) + .forEach(exec::execute); + exec.shutdown(); + } +} +/* Output: +NapTask[7] pool-1-thread-8 +NapTask[4] pool-1-thread-5 +NapTask[1] pool-1-thread-2 +NapTask[3] pool-1-thread-4 +NapTask[0] pool-1-thread-1 +NapTask[8] pool-1-thread-9 +NapTask[2] pool-1-thread-3 +NapTask[9] pool-1-thread-10 +NapTask[6] pool-1-thread-7 +NapTask[5] pool-1-thread-6 +*/ diff --git a/code/concurrent/CachedThreadPool2.java b/code/concurrent/CachedThreadPool2.java new file mode 100644 index 00000000..9d763656 --- /dev/null +++ b/code/concurrent/CachedThreadPool2.java @@ -0,0 +1,29 @@ +// concurrent/CachedThreadPool2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; + +public class CachedThreadPool2 { + public static void main(String[] args) { + ExecutorService exec = + Executors.newCachedThreadPool(); + IntStream.range(0, 10) + .mapToObj(InterferingTask::new) + .forEach(exec::execute); + exec.shutdown(); + } +} +/* Output: +0 pool-1-thread-1 200 +1 pool-1-thread-2 200 +4 pool-1-thread-5 300 +5 pool-1-thread-6 400 +8 pool-1-thread-9 500 +9 pool-1-thread-10 600 +2 pool-1-thread-3 700 +7 pool-1-thread-8 800 +3 pool-1-thread-4 900 +6 pool-1-thread-7 1000 +*/ diff --git a/code/concurrent/CachedThreadPool3.java b/code/concurrent/CachedThreadPool3.java new file mode 100644 index 00000000..4b6e6d2e --- /dev/null +++ b/code/concurrent/CachedThreadPool3.java @@ -0,0 +1,47 @@ +// concurrent/CachedThreadPool3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.*; + +public class CachedThreadPool3 { + public static Integer + extractResult(Future f) { + try { + return f.get(); + } catch(Exception e) { + throw new RuntimeException(e); + } + } + public static void main(String[] args) + throws InterruptedException { + ExecutorService exec = + Executors.newCachedThreadPool(); + List tasks = + IntStream.range(0, 10) + .mapToObj(CountingTask::new) + .collect(Collectors.toList()); + List> futures = + exec.invokeAll(tasks); + Integer sum = futures.stream() + .map(CachedThreadPool3::extractResult) + .reduce(0, Integer::sum); + System.out.println("sum = " + sum); + exec.shutdown(); + } +} +/* Output: +1 pool-1-thread-2 100 +0 pool-1-thread-1 100 +4 pool-1-thread-5 100 +5 pool-1-thread-6 100 +8 pool-1-thread-9 100 +9 pool-1-thread-10 100 +2 pool-1-thread-3 100 +3 pool-1-thread-4 100 +6 pool-1-thread-7 100 +7 pool-1-thread-8 100 +sum = 1000 +*/ diff --git a/code/concurrent/CatchCompletableExceptions.java b/code/concurrent/CatchCompletableExceptions.java new file mode 100644 index 00000000..67451ed4 --- /dev/null +++ b/code/concurrent/CatchCompletableExceptions.java @@ -0,0 +1,81 @@ +// concurrent/CatchCompletableExceptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class CatchCompletableExceptions { + static void handleException(int failcount) { + // Call the Function only if there's an + // exception, must produce same type as came in: + CompletableExceptions + .test("exceptionally", failcount) + .exceptionally((ex) -> { // Function + if(ex == null) + System.out.println("I don't get it yet"); + return new Breakable(ex.getMessage(), 0); + }) + .thenAccept(str -> + System.out.println("result: " + str)); + + // Create a new result (recover): + CompletableExceptions + .test("handle", failcount) + .handle((result, fail) -> { // BiFunction + if(fail != null) + return "Failure recovery object"; + else + return result + " is good"; + }) + .thenAccept(str -> + System.out.println("result: " + str)); + + // Do something but pass the same result through: + CompletableExceptions + .test("whenComplete", failcount) + .whenComplete((result, fail) -> { // BiConsumer + if(fail != null) + System.out.println("It failed"); + else + System.out.println(result + " OK"); + }) + .thenAccept(r -> + System.out.println("result: " + r)); + } + public static void main(String[] args) { + System.out.println("**** Failure Mode ****"); + handleException(2); + System.out.println("**** Success Mode ****"); + handleException(0); + } +} +/* Output: +**** Failure Mode **** +Breakable_exceptionally [1] +Throwing Exception for exceptionally +result: Breakable_java.lang.RuntimeException: +Breakable_exceptionally failed [0] +Breakable_handle [1] +Throwing Exception for handle +result: Failure recovery object +Breakable_whenComplete [1] +Throwing Exception for whenComplete +It failed +**** Success Mode **** +Breakable_exceptionally [-1] +Breakable_exceptionally [-2] +Breakable_exceptionally [-3] +Breakable_exceptionally [-4] +result: Breakable_exceptionally [-4] +Breakable_handle [-1] +Breakable_handle [-2] +Breakable_handle [-3] +Breakable_handle [-4] +result: Breakable_handle [-4] is good +Breakable_whenComplete [-1] +Breakable_whenComplete [-2] +Breakable_whenComplete [-3] +Breakable_whenComplete [-4] +Breakable_whenComplete [-4] OK +result: Breakable_whenComplete [-4] +*/ diff --git a/code/concurrent/CollectionIntoStream.java b/code/concurrent/CollectionIntoStream.java new file mode 100644 index 00000000..2dc51a7e --- /dev/null +++ b/code/concurrent/CollectionIntoStream.java @@ -0,0 +1,36 @@ +// concurrent/CollectionIntoStream.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; +import java.util.*; +import java.util.stream.*; + +public class CollectionIntoStream { + public static void main(String[] args) { + List strings = + Stream.generate(new Rand.String(5)) + .limit(10) + .collect(Collectors.toList()); + strings.forEach(System.out::println); + // Convert to a Stream for many more options: + String result = strings.stream() + .map(String::toUpperCase) + .map(s -> s.substring(2)) + .reduce(":", (s1, s2) -> s1 + s2); + System.out.println(result); + } +} +/* Output: +btpen +pccux +szgvg +meinn +eeloz +tdvew +cippc +ygpoa +lkljl +bynxt +:PENCUXGVGINNLOZVEWPPCPOALJLNXT +*/ diff --git a/code/concurrent/CompletableApply.java b/code/concurrent/CompletableApply.java new file mode 100644 index 00000000..2f5bd9b4 --- /dev/null +++ b/code/concurrent/CompletableApply.java @@ -0,0 +1,27 @@ +// concurrent/CompletableApply.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class CompletableApply { + public static void main(String[] args) { + CompletableFuture cf = + CompletableFuture.completedFuture( + new Machina(0)); + CompletableFuture cf2 = + cf.thenApply(Machina::work); + CompletableFuture cf3 = + cf2.thenApply(Machina::work); + CompletableFuture cf4 = + cf3.thenApply(Machina::work); + CompletableFuture cf5 = + cf4.thenApply(Machina::work); + } +} +/* Output: +Machina0: ONE +Machina0: TWO +Machina0: THREE +Machina0: complete +*/ diff --git a/code/concurrent/CompletableApplyAsync.java b/code/concurrent/CompletableApplyAsync.java new file mode 100644 index 00000000..fa7c9271 --- /dev/null +++ b/code/concurrent/CompletableApplyAsync.java @@ -0,0 +1,31 @@ +// concurrent/CompletableApplyAsync.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import onjava.*; + +public class CompletableApplyAsync { + public static void main(String[] args) { + Timer timer = new Timer(); + CompletableFuture cf = + CompletableFuture.completedFuture( + new Machina(0)) + .thenApplyAsync(Machina::work) + .thenApplyAsync(Machina::work) + .thenApplyAsync(Machina::work) + .thenApplyAsync(Machina::work); + System.out.println(timer.duration()); + System.out.println(cf.join()); + System.out.println(timer.duration()); + } +} +/* Output: +116 +Machina0: ONE +Machina0: TWO +Machina0: THREE +Machina0: complete +Machina0: complete +552 +*/ diff --git a/code/concurrent/CompletableApplyChained.java b/code/concurrent/CompletableApplyChained.java new file mode 100644 index 00000000..aa6828d5 --- /dev/null +++ b/code/concurrent/CompletableApplyChained.java @@ -0,0 +1,27 @@ +// concurrent/CompletableApplyChained.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import onjava.Timer; + +public class CompletableApplyChained { + public static void main(String[] args) { + Timer timer = new Timer(); + CompletableFuture cf = + CompletableFuture.completedFuture( + new Machina(0)) + .thenApply(Machina::work) + .thenApply(Machina::work) + .thenApply(Machina::work) + .thenApply(Machina::work); + System.out.println(timer.duration()); + } +} +/* Output: +Machina0: ONE +Machina0: TWO +Machina0: THREE +Machina0: complete +514 +*/ diff --git a/code/concurrent/CompletableExceptions.java b/code/concurrent/CompletableExceptions.java new file mode 100644 index 00000000..624815d5 --- /dev/null +++ b/code/concurrent/CompletableExceptions.java @@ -0,0 +1,75 @@ +// concurrent/CompletableExceptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class CompletableExceptions { + static CompletableFuture + test(String id, int failcount) { + return + CompletableFuture.completedFuture( + new Breakable(id, failcount)) + .thenApply(Breakable::work) + .thenApply(Breakable::work) + .thenApply(Breakable::work) + .thenApply(Breakable::work); + } + public static void main(String[] args) { + // Exceptions don't appear ... + test("A", 1); + test("B", 2); + test("C", 3); + test("D", 4); + test("E", 5); + // ... until you try to fetch the value: + try { + test("F", 2).get(); // or join() + } catch(Exception e) { + System.out.println(e.getMessage()); + } + // Test for exceptions: + System.out.println( + test("G", 2).isCompletedExceptionally()); + // Counts as "done": + System.out.println(test("H", 2).isDone()); + // Force an exception: + CompletableFuture cfi = + new CompletableFuture<>(); + System.out.println("done? " + cfi.isDone()); + cfi.completeExceptionally( + new RuntimeException("forced")); + try { + cfi.get(); + } catch(Exception e) { + System.out.println(e.getMessage()); + } + } +} +/* Output: +Throwing Exception for A +Breakable_B [1] +Throwing Exception for B +Breakable_C [2] +Breakable_C [1] +Throwing Exception for C +Breakable_D [3] +Breakable_D [2] +Breakable_D [1] +Throwing Exception for D +Breakable_E [4] +Breakable_E [3] +Breakable_E [2] +Breakable_E [1] +Breakable_F [1] +Throwing Exception for F +java.lang.RuntimeException: Breakable_F failed +Breakable_G [1] +Throwing Exception for G +true +Breakable_H [1] +Throwing Exception for H +true +done? false +java.lang.RuntimeException: forced +*/ diff --git a/code/concurrent/CompletableOperations.java b/code/concurrent/CompletableOperations.java new file mode 100644 index 00000000..d03e8422 --- /dev/null +++ b/code/concurrent/CompletableOperations.java @@ -0,0 +1,74 @@ +// concurrent/CompletableOperations.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import static onjava.CompletableUtilities.*; + +public class CompletableOperations { + static CompletableFuture cfi(int i) { + return + CompletableFuture.completedFuture( + Integer.valueOf(i)); + } + public static void main(String[] args) { + showr(cfi(1)); // Basic test + voidr(cfi(2).runAsync(() -> + System.out.println("runAsync"))); + voidr(cfi(3).thenRunAsync(() -> + System.out.println("thenRunAsync"))); + voidr(CompletableFuture.runAsync(() -> + System.out.println("runAsync is static"))); + showr(CompletableFuture.supplyAsync(() -> 99)); + voidr(cfi(4).thenAcceptAsync(i -> + System.out.println("thenAcceptAsync: " + i))); + showr(cfi(5).thenApplyAsync(i -> i + 42)); + showr(cfi(6).thenComposeAsync(i -> cfi(i + 99))); + CompletableFuture c = cfi(7); + c.obtrudeValue(111); + showr(c); + showr(cfi(8).toCompletableFuture()); + c = new CompletableFuture<>(); + c.complete(9); + showr(c); + c = new CompletableFuture<>(); + c.cancel(true); + System.out.println("cancelled: " + + c.isCancelled()); + System.out.println("completed exceptionally: " + + c.isCompletedExceptionally()); + System.out.println("done: " + c.isDone()); + System.out.println(c); + c = new CompletableFuture<>(); + System.out.println(c.getNow(777)); + c = new CompletableFuture<>(); + c.thenApplyAsync(i -> i + 42) + .thenApplyAsync(i -> i * 12); + System.out.println("dependents: " + + c.getNumberOfDependents()); + c.thenApplyAsync(i -> i / 2); + System.out.println("dependents: " + + c.getNumberOfDependents()); + } +} +/* Output: +1 +runAsync +thenRunAsync +runAsync is static +99 +thenAcceptAsync: 4 +47 +105 +111 +8 +9 +cancelled: true +completed exceptionally: true +done: true +java.util.concurrent.CompletableFuture@6d311334[Complet +ed exceptionally] +777 +dependents: 1 +dependents: 2 +*/ diff --git a/code/concurrent/CompletablePizza.java b/code/concurrent/CompletablePizza.java new file mode 100644 index 00000000..97b68545 --- /dev/null +++ b/code/concurrent/CompletablePizza.java @@ -0,0 +1,87 @@ +// concurrent/CompletablePizza.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.*; +import onjava.Timer; + +public class CompletablePizza { + static final int QUANTITY = 5; + public static CompletableFuture + makeCF(Pizza za) { + return CompletableFuture + .completedFuture(za) + .thenApplyAsync(Pizza::roll) + .thenApplyAsync(Pizza::sauce) + .thenApplyAsync(Pizza::cheese) + .thenApplyAsync(Pizza::toppings) + .thenApplyAsync(Pizza::bake) + .thenApplyAsync(Pizza::slice) + .thenApplyAsync(Pizza::box); + } + public static void + show(CompletableFuture cf) { + try { + System.out.println(cf.get()); + } catch(Exception e) { + throw new RuntimeException(e); + } + } + public static void main(String[] args) { + Timer timer = new Timer(); + List> pizzas = + IntStream.range(0, QUANTITY) + .mapToObj(Pizza::new) + .map(CompletablePizza::makeCF) + .collect(Collectors.toList()); + System.out.println(timer.duration()); + pizzas.forEach(CompletablePizza::show); + System.out.println(timer.duration()); + } +} +/* Output: +169 +Pizza 0: ROLLED +Pizza 1: ROLLED +Pizza 2: ROLLED +Pizza 4: ROLLED +Pizza 3: ROLLED +Pizza 1: SAUCED +Pizza 0: SAUCED +Pizza 2: SAUCED +Pizza 4: SAUCED +Pizza 3: SAUCED +Pizza 0: CHEESED +Pizza 4: CHEESED +Pizza 1: CHEESED +Pizza 2: CHEESED +Pizza 3: CHEESED +Pizza 0: TOPPED +Pizza 4: TOPPED +Pizza 1: TOPPED +Pizza 2: TOPPED +Pizza 3: TOPPED +Pizza 0: BAKED +Pizza 4: BAKED +Pizza 1: BAKED +Pizza 3: BAKED +Pizza 2: BAKED +Pizza 0: SLICED +Pizza 4: SLICED +Pizza 1: SLICED +Pizza 3: SLICED +Pizza 2: SLICED +Pizza 4: BOXED +Pizza 0: BOXED +Pizza0: complete +Pizza 1: BOXED +Pizza1: complete +Pizza 3: BOXED +Pizza 2: BOXED +Pizza2: complete +Pizza3: complete +Pizza4: complete +1797 +*/ diff --git a/code/concurrent/CompletableUtilities.java b/code/concurrent/CompletableUtilities.java new file mode 100644 index 00000000..8f3a0e51 --- /dev/null +++ b/code/concurrent/CompletableUtilities.java @@ -0,0 +1,27 @@ +// concurrent/CompletableUtilities.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.util.concurrent.*; + +public class CompletableUtilities { + // Get and show value stored in a CF: + public static void showr(CompletableFuture c) { + try { + System.out.println(c.get()); + } catch(InterruptedException + | ExecutionException e) { + throw new RuntimeException(e); + } + } + // For CF operations that have no value: + public static void voidr(CompletableFuture c) { + try { + c.get(); // Returns void + } catch(InterruptedException + | ExecutionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/concurrent/CompletedMachina.java b/code/concurrent/CompletedMachina.java new file mode 100644 index 00000000..06a78710 --- /dev/null +++ b/code/concurrent/CompletedMachina.java @@ -0,0 +1,19 @@ +// concurrent/CompletedMachina.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class CompletedMachina { + public static void main(String[] args) { + CompletableFuture cf = + CompletableFuture.completedFuture( + new Machina(0)); + try { + Machina m = cf.get(); // Doesn't block + } catch(InterruptedException | + ExecutionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/concurrent/CountingStream.java b/code/concurrent/CountingStream.java new file mode 100644 index 00000000..4cebb24e --- /dev/null +++ b/code/concurrent/CountingStream.java @@ -0,0 +1,32 @@ +// concurrent/CountingStream.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.*; + +public class CountingStream { + public static void main(String[] args) { + System.out.println( + IntStream.range(0, 10) + .parallel() + .mapToObj(CountingTask::new) + .map(ct -> ct.call()) + .reduce(0, Integer::sum)); + } +} +/* Output: +1 ForkJoinPool.commonPool-worker-3 100 +8 ForkJoinPool.commonPool-worker-2 100 +0 ForkJoinPool.commonPool-worker-6 100 +2 ForkJoinPool.commonPool-worker-1 100 +4 ForkJoinPool.commonPool-worker-5 100 +9 ForkJoinPool.commonPool-worker-7 100 +6 main 100 +7 ForkJoinPool.commonPool-worker-4 100 +5 ForkJoinPool.commonPool-worker-2 100 +3 ForkJoinPool.commonPool-worker-3 100 +1000 +*/ diff --git a/code/concurrent/CountingTask.java b/code/concurrent/CountingTask.java new file mode 100644 index 00000000..b1fb7b89 --- /dev/null +++ b/code/concurrent/CountingTask.java @@ -0,0 +1,19 @@ +// concurrent/CountingTask.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class CountingTask implements Callable { + final int id; + public CountingTask(int id) { this.id = id; } + @Override + public Integer call() { + Integer val = 0; + for(int i = 0; i < 100; i++) + val++; + System.out.println(id + " " + + Thread.currentThread().getName() + " " + val); + return val; + } +} diff --git a/code/concurrent/DiningPhilosophers.java b/code/concurrent/DiningPhilosophers.java new file mode 100644 index 00000000..5c2b2f1b --- /dev/null +++ b/code/concurrent/DiningPhilosophers.java @@ -0,0 +1,33 @@ +// concurrent/DiningPhilosophers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Hidden deadlock +// {ExcludeFromGradle} Gradle has trouble +import java.util.*; +import java.util.concurrent.*; +import onjava.Nap; + +public class DiningPhilosophers { + private StickHolder[] sticks; + private Philosopher[] philosophers; + public DiningPhilosophers(int n) { + sticks = new StickHolder[n]; + Arrays.setAll(sticks, i -> new StickHolder()); + philosophers = new Philosopher[n]; + Arrays.setAll(philosophers, i -> + new Philosopher(i, + sticks[i], sticks[(i + 1) % n])); // [1] + // Fix by reversing stick order for this one: + // philosophers[1] = // [2] + // new Philosopher(0, sticks[0], sticks[1]); + Arrays.stream(philosophers) + .forEach(CompletableFuture::runAsync); // [3] + } + public static void main(String[] args) { + // Returns right away: + new DiningPhilosophers(5); // [4] + // Keeps main() from exiting: + new Nap(3, "Shutdown"); + } +} diff --git a/code/concurrent/DualCompletableOperations.java b/code/concurrent/DualCompletableOperations.java new file mode 100644 index 00000000..42052312 --- /dev/null +++ b/code/concurrent/DualCompletableOperations.java @@ -0,0 +1,115 @@ +// concurrent/DualCompletableOperations.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import static onjava.CompletableUtilities.*; + +public class DualCompletableOperations { + static CompletableFuture cfA, cfB; + static void init() { + cfA = Workable.make("A", 0.15); + cfB = Workable.make("B", 0.10); // Always wins + } + static void join() { + cfA.join(); + cfB.join(); + System.out.println("*****************"); + } + public static void main(String[] args) { + init(); + voidr(cfA.runAfterEitherAsync(cfB, () -> + System.out.println("runAfterEither"))); + join(); + + init(); + voidr(cfA.runAfterBothAsync(cfB, () -> + System.out.println("runAfterBoth"))); + join(); + + init(); + showr(cfA.applyToEitherAsync(cfB, w -> { + System.out.println("applyToEither: " + w); + return w; + })); + join(); + + init(); + voidr(cfA.acceptEitherAsync(cfB, w -> { + System.out.println("acceptEither: " + w); + })); + join(); + + init(); + voidr(cfA.thenAcceptBothAsync(cfB, (w1, w2) -> { + System.out.println("thenAcceptBoth: " + + w1 + ", " + w2); + })); + join(); + + init(); + showr(cfA.thenCombineAsync(cfB, (w1, w2) -> { + System.out.println("thenCombine: " + + w1 + ", " + w2); + return w1; + })); + join(); + + init(); + CompletableFuture + cfC = Workable.make("C", 0.08), + cfD = Workable.make("D", 0.09); + CompletableFuture.anyOf(cfA, cfB, cfC, cfD) + .thenRunAsync(() -> + System.out.println("anyOf")); + join(); + + init(); + cfC = Workable.make("C", 0.08); + cfD = Workable.make("D", 0.09); + CompletableFuture.allOf(cfA, cfB, cfC, cfD) + .thenRunAsync(() -> + System.out.println("allOf")); + join(); + } +} +/* Output: +Workable[BW] +runAfterEither +Workable[AW] +***************** +Workable[BW] +Workable[AW] +runAfterBoth +***************** +Workable[BW] +applyToEither: Workable[BW] +Workable[BW] +Workable[AW] +***************** +Workable[BW] +acceptEither: Workable[BW] +Workable[AW] +***************** +Workable[BW] +Workable[AW] +thenAcceptBoth: Workable[AW], Workable[BW] +***************** +Workable[BW] +Workable[AW] +thenCombine: Workable[AW], Workable[BW] +Workable[AW] +***************** +Workable[CW] +anyOf +Workable[DW] +Workable[BW] +Workable[AW] +***************** +Workable[CW] +Workable[DW] +Workable[BW] +Workable[AW] +***************** +allOf +*/ diff --git a/code/concurrent/FrostedCake.java b/code/concurrent/FrostedCake.java new file mode 100644 index 00000000..1be8b661 --- /dev/null +++ b/code/concurrent/FrostedCake.java @@ -0,0 +1,32 @@ +// concurrent/FrostedCake.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; +import onjava.Nap; + +final class Frosting { + private Frosting() {} + static CompletableFuture make() { + new Nap(0.1); + return CompletableFuture + .completedFuture(new Frosting()); + } +} + +public class FrostedCake { + public FrostedCake(Baked baked, Frosting frosting) { + new Nap(0.1); + } + @Override + public String toString() { return "FrostedCake"; } + public static void main(String[] args) { + Baked.batch().forEach(baked -> baked + .thenCombineAsync(Frosting.make(), + (cake, frosting) -> + new FrostedCake(cake, frosting)) + .thenAcceptAsync(System.out::println) + .join()); + } +} diff --git a/code/concurrent/Futures.java b/code/concurrent/Futures.java new file mode 100644 index 00000000..888e7f0d --- /dev/null +++ b/code/concurrent/Futures.java @@ -0,0 +1,23 @@ +// concurrent/Futures.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.*; + +public class Futures { + public static void main(String[] args) + throws InterruptedException, ExecutionException { + ExecutorService exec = + Executors.newSingleThreadExecutor(); + Future f = + exec.submit(new CountingTask(99)); + System.out.println(f.get()); // [1] + exec.shutdown(); + } +} +/* Output: +99 pool-1-thread-1 100 +100 +*/ diff --git a/code/concurrent/GuardedIDField.java b/code/concurrent/GuardedIDField.java new file mode 100644 index 00000000..e570a5d3 --- /dev/null +++ b/code/concurrent/GuardedIDField.java @@ -0,0 +1,18 @@ +// concurrent/GuardedIDField.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.atomic.*; + +public class GuardedIDField implements HasID { + private static AtomicInteger counter = + new AtomicInteger(); + private int id = counter.getAndIncrement(); + public int getID() { return id; } + public static void main(String[] args) { + IDChecker.test(GuardedIDField::new); + } +} +/* Output: +0 +*/ diff --git a/code/concurrent/HasID.java b/code/concurrent/HasID.java new file mode 100644 index 00000000..e5e13438 --- /dev/null +++ b/code/concurrent/HasID.java @@ -0,0 +1,8 @@ +// concurrent/HasID.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public interface HasID { + int getID(); +} diff --git a/code/concurrent/IDChecker.java b/code/concurrent/IDChecker.java new file mode 100644 index 00000000..845c9e6a --- /dev/null +++ b/code/concurrent/IDChecker.java @@ -0,0 +1,41 @@ +// concurrent/IDChecker.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import java.util.concurrent.*; +import com.google.common.collect.Sets; + +public class IDChecker { + public static final int SIZE = 100_000; + static class MakeObjects + implements Supplier> { + private Supplier gen; + MakeObjects(Supplier gen) { + this.gen = gen; + } + @Override + public List get() { + return + Stream.generate(gen) + .limit(SIZE) + .map(HasID::getID) + .collect(Collectors.toList()); + } + } + public static void test(Supplier gen) { + CompletableFuture> + groupA = CompletableFuture + .supplyAsync(new MakeObjects(gen)), + groupB = CompletableFuture + .supplyAsync(new MakeObjects(gen)); + groupA.thenAcceptBoth(groupB, (a, b) -> { + System.out.println( + Sets.intersection( + Sets.newHashSet(a), + Sets.newHashSet(b)).size()); + }).join(); + } +} diff --git a/code/concurrent/InterferingTask.java b/code/concurrent/InterferingTask.java new file mode 100644 index 00000000..da08f653 --- /dev/null +++ b/code/concurrent/InterferingTask.java @@ -0,0 +1,17 @@ +// concurrent/InterferingTask.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class InterferingTask implements Runnable { + final int id; + private static Integer val = 0; + public InterferingTask(int id) { this.id = id; } + @Override + public void run() { + for(int i = 0; i < 100; i++) + val++; + System.out.println(id + " " + + Thread.currentThread().getName() + " " + val); + } +} diff --git a/code/concurrent/LambdasAndMethodReferences.java b/code/concurrent/LambdasAndMethodReferences.java new file mode 100644 index 00000000..10552499 --- /dev/null +++ b/code/concurrent/LambdasAndMethodReferences.java @@ -0,0 +1,40 @@ +// concurrent/LambdasAndMethodReferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +class NotRunnable { + public void go() { + System.out.println("NotRunnable"); + } +} + +class NotCallable { + public Integer get() { + System.out.println("NotCallable"); + return 1; + } +} + +public class LambdasAndMethodReferences { + public static void main(String[] args) + throws InterruptedException { + ExecutorService exec = + Executors.newCachedThreadPool(); + exec.submit(() -> System.out.println("Lambda1")); + exec.submit(new NotRunnable()::go); + exec.submit(() -> { + System.out.println("Lambda2"); + return 1; + }); + exec.submit(new NotCallable()::get); + exec.shutdown(); + } +} +/* Output: +Lambda1 +NotCallable +NotRunnable +Lambda2 +*/ diff --git a/code/concurrent/Machina.java b/code/concurrent/Machina.java new file mode 100644 index 00000000..e70cd2b4 --- /dev/null +++ b/code/concurrent/Machina.java @@ -0,0 +1,31 @@ +// concurrent/Machina.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.Nap; + +public class Machina { + public enum State { + START, ONE, TWO, THREE, END; + State step() { + if(equals(END)) return END; + return values()[ordinal() + 1]; + } + } + private State state = State.START; + private final int id; + public Machina(int id) { this.id = id; } + public static Machina work(Machina m) { + if(!m.state.equals(State.END)){ + new Nap(0.1); + m.state = m.state.step(); + } + System.out.println(m); + return m; + } + @Override + public String toString() { + return "Machina" + id + ": " + + (state.equals(State.END)? "complete" : state); + } +} diff --git a/code/concurrent/MoreTasksAfterShutdown.java b/code/concurrent/MoreTasksAfterShutdown.java new file mode 100644 index 00000000..28b96af8 --- /dev/null +++ b/code/concurrent/MoreTasksAfterShutdown.java @@ -0,0 +1,27 @@ +// concurrent/MoreTasksAfterShutdown.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class MoreTasksAfterShutdown { + public static void main(String[] args) { + ExecutorService exec = + Executors.newSingleThreadExecutor(); + exec.execute(new NapTask(1)); + exec.shutdown(); + try { + exec.execute(new NapTask(99)); + } catch(RejectedExecutionException e) { + System.out.println(e); + } + } +} +/* Output: +java.util.concurrent.RejectedExecutionException: Task +NapTask[99] rejected from java.util.concurrent.ThreadPo +olExecutor@4e25154f[Shutting down, pool size = 1, +active threads = 1, queued tasks = 0, completed tasks = +0] +NapTask[1] pool-1-thread-1 +*/ diff --git a/code/concurrent/NapTask.java b/code/concurrent/NapTask.java new file mode 100644 index 00000000..92df6b60 --- /dev/null +++ b/code/concurrent/NapTask.java @@ -0,0 +1,20 @@ +// concurrent/NapTask.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.Nap; + +public class NapTask implements Runnable { + final int id; + public NapTask(int id) { this.id = id; } + @Override + public void run() { + new Nap(0.1); // Seconds + System.out.println(this + " " + + Thread.currentThread().getName()); + } + @Override + public String toString() { + return "NapTask[" + id + "]"; + } +} diff --git a/code/concurrent/OnePizza.java b/code/concurrent/OnePizza.java new file mode 100644 index 00000000..f4f27249 --- /dev/null +++ b/code/concurrent/OnePizza.java @@ -0,0 +1,26 @@ +// concurrent/OnePizza.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.Timer; + +public class OnePizza { + public static void main(String[] args) { + Pizza za = new Pizza(0); + System.out.println( + Timer.duration(() -> { + while(!za.complete()) + za.next(); + })); + } +} +/* Output: +Pizza 0: ROLLED +Pizza 0: SAUCED +Pizza 0: CHEESED +Pizza 0: TOPPED +Pizza 0: BAKED +Pizza 0: SLICED +Pizza 0: BOXED +1622 +*/ diff --git a/code/concurrent/ParallelPrime.java b/code/concurrent/ParallelPrime.java new file mode 100644 index 00000000..97c02575 --- /dev/null +++ b/code/concurrent/ParallelPrime.java @@ -0,0 +1,35 @@ +// concurrent/ParallelPrime.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import static java.util.stream.LongStream.*; +import java.io.*; +import java.nio.file.*; +import onjava.Timer; + +public class ParallelPrime { + static final int COUNT = 100_000; + public static boolean isPrime(long n) { + return rangeClosed(2, (long)Math.sqrt(n)) + .noneMatch(i -> n % i == 0); + } + public static void main(String[] args) + throws IOException { + Timer timer = new Timer(); + List primes = + iterate(2, i -> i + 1) + .parallel() // [1] + .filter(ParallelPrime::isPrime) + .limit(COUNT) + .mapToObj(Long::toString) + .collect(Collectors.toList()); + System.out.println(timer.duration()); + Files.write(Paths.get("primes.txt"), primes, + StandardOpenOption.CREATE); + } +} +/* Output: +1224 +*/ diff --git a/code/concurrent/ParallelStreamPuzzle.java b/code/concurrent/ParallelStreamPuzzle.java new file mode 100644 index 00000000..f57dec24 --- /dev/null +++ b/code/concurrent/ParallelStreamPuzzle.java @@ -0,0 +1,28 @@ +// concurrent/ParallelStreamPuzzle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public class ParallelStreamPuzzle { + static class IntGenerator + implements Supplier { + private int current = 0; + public Integer get() { + return current++; + } + } + public static void main(String[] args) { + List x = + Stream.generate(new IntGenerator()) + .limit(10) + .parallel() // [1] + .collect(Collectors.toList()); + System.out.println(x); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +*/ diff --git a/code/concurrent/ParallelStreamPuzzle2.java b/code/concurrent/ParallelStreamPuzzle2.java new file mode 100644 index 00000000..2fc11d48 --- /dev/null +++ b/code/concurrent/ParallelStreamPuzzle2.java @@ -0,0 +1,38 @@ +// concurrent/ParallelStreamPuzzle2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; +import java.nio.file.*; + +public class ParallelStreamPuzzle2 { + public static final Deque trace = + new ConcurrentLinkedDeque<>(); + static class + IntGenerator implements Supplier { + private AtomicInteger current = + new AtomicInteger(); + public Integer get() { + trace.add(current.get() + ": " + + Thread.currentThread().getName()); + return current.getAndIncrement(); + } + } + public static void + main(String[] args) throws Exception { + List x = + Stream.generate(new IntGenerator()) + .limit(10) + .parallel() + .collect(Collectors.toList()); + System.out.println(x); + Files.write(Paths.get("PSP2.txt"), trace); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +*/ diff --git a/code/concurrent/ParallelStreamPuzzle3.java b/code/concurrent/ParallelStreamPuzzle3.java new file mode 100644 index 00000000..757bddd5 --- /dev/null +++ b/code/concurrent/ParallelStreamPuzzle3.java @@ -0,0 +1,33 @@ +// concurrent/ParallelStreamPuzzle3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.util.*; +import java.util.stream.*; + +public class ParallelStreamPuzzle3 { + public static void main(String[] args) { + List x = IntStream.range(0, 30) + .peek(e -> System.out.println(e + ": " + + Thread.currentThread().getName())) + .limit(10) + .parallel() + .boxed() + .collect(Collectors.toList()); + System.out.println(x); + } +} +/* Output: +8: main +6: ForkJoinPool.commonPool-worker-5 +3: ForkJoinPool.commonPool-worker-7 +5: ForkJoinPool.commonPool-worker-5 +1: ForkJoinPool.commonPool-worker-3 +2: ForkJoinPool.commonPool-worker-6 +4: ForkJoinPool.commonPool-worker-1 +0: ForkJoinPool.commonPool-worker-4 +7: ForkJoinPool.commonPool-worker-1 +9: ForkJoinPool.commonPool-worker-2 +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +*/ diff --git a/code/concurrent/Philosopher.java b/code/concurrent/Philosopher.java new file mode 100644 index 00000000..48facb38 --- /dev/null +++ b/code/concurrent/Philosopher.java @@ -0,0 +1,30 @@ +// concurrent/Philosopher.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Philosopher implements Runnable { + private final int seat; + private final StickHolder left, right; + public Philosopher(int seat, + StickHolder left, StickHolder right) { + this.seat = seat; + this.left = left; + this.right = right; + } + @Override + public String toString() { + return "P" + seat; + } + @Override + public void run() { + while(true) { + // System.out.println("Thinking"); // [1] + right.pickUp(); + left.pickUp(); + System.out.println(this + " eating"); + right.putDown(); + left.putDown(); + } + } +} diff --git a/code/concurrent/Pizza.java b/code/concurrent/Pizza.java new file mode 100644 index 00000000..8cd5ff30 --- /dev/null +++ b/code/concurrent/Pizza.java @@ -0,0 +1,49 @@ +// concurrent/Pizza.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; +import onjava.Nap; + +public class Pizza { + public enum Step { + DOUGH(4), ROLLED(1), SAUCED(1), CHEESED(2), + TOPPED(5), BAKED(2), SLICED(1), BOXED(0); + int effort; // Needed to get to the next step + Step(int effort) { this.effort = effort; } + Step forward() { + if(equals(BOXED)) return BOXED; + new Nap(effort * 0.1); + return values()[ordinal() + 1]; + } + } + private Step step = Step.DOUGH; + private final int id; + public Pizza(int id) { this.id = id; } + public Pizza next() { + step = step.forward(); + System.out.println("Pizza " + id + ": " + step); + return this; + } + public Pizza next(Step previousStep) { + if(!step.equals(previousStep)) + throw new IllegalStateException("Expected " + + previousStep + " but found " + step); + return next(); + } + public Pizza roll() { return next(Step.DOUGH); } + public Pizza sauce() { return next(Step.ROLLED); } + public Pizza cheese() { return next(Step.SAUCED); } + public Pizza toppings() { return next(Step.CHEESED); } + public Pizza bake() { return next(Step.TOPPED); } + public Pizza slice() { return next(Step.BAKED); } + public Pizza box() { return next(Step.SLICED); } + public boolean complete() { + return step.equals(Step.BOXED); + } + @Override + public String toString() { + return "Pizza" + id + ": " + + (step.equals(Step.BOXED)? "complete" : step); + } +} diff --git a/code/concurrent/PizzaParallelSteps.java b/code/concurrent/PizzaParallelSteps.java new file mode 100644 index 00000000..605e9985 --- /dev/null +++ b/code/concurrent/PizzaParallelSteps.java @@ -0,0 +1,69 @@ +// concurrent/PizzaParallelSteps.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import onjava.Timer; + +public class PizzaParallelSteps { + static final int QUANTITY = 5; + public static void main(String[] args) { + Timer timer = new Timer(); + IntStream.range(0, QUANTITY) + .mapToObj(Pizza::new) + .parallel() + .map(Pizza::roll) + .map(Pizza::sauce) + .map(Pizza::cheese) + .map(Pizza::toppings) + .map(Pizza::bake) + .map(Pizza::slice) + .map(Pizza::box) + .forEach(za -> System.out.println(za)); + System.out.println(timer.duration()); + } +} +/* Output: +Pizza 2: ROLLED +Pizza 0: ROLLED +Pizza 1: ROLLED +Pizza 4: ROLLED +Pizza 3: ROLLED +Pizza 1: SAUCED +Pizza 0: SAUCED +Pizza 2: SAUCED +Pizza 3: SAUCED +Pizza 4: SAUCED +Pizza 1: CHEESED +Pizza 0: CHEESED +Pizza 2: CHEESED +Pizza 3: CHEESED +Pizza 4: CHEESED +Pizza 0: TOPPED +Pizza 2: TOPPED +Pizza 1: TOPPED +Pizza 3: TOPPED +Pizza 4: TOPPED +Pizza 1: BAKED +Pizza 2: BAKED +Pizza 0: BAKED +Pizza 4: BAKED +Pizza 3: BAKED +Pizza 0: SLICED +Pizza 2: SLICED +Pizza 1: SLICED +Pizza 3: SLICED +Pizza 4: SLICED +Pizza 1: BOXED +Pizza1: complete +Pizza 2: BOXED +Pizza 0: BOXED +Pizza2: complete +Pizza0: complete +Pizza 3: BOXED +Pizza 4: BOXED +Pizza4: complete +Pizza3: complete +1738 +*/ diff --git a/code/concurrent/PizzaStreams.java b/code/concurrent/PizzaStreams.java new file mode 100644 index 00000000..16be983a --- /dev/null +++ b/code/concurrent/PizzaStreams.java @@ -0,0 +1,60 @@ +// concurrent/PizzaStreams.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import onjava.Timer; + +public class PizzaStreams { + static final int QUANTITY = 5; + public static void main(String[] args) { + Timer timer = new Timer(); + IntStream.range(0, QUANTITY) + .mapToObj(Pizza::new) + .parallel() // [1] + .forEach(za -> { + while(!za.complete()) + za.next(); + }); + System.out.println(timer.duration()); + } +} +/* Output: +Pizza 2: ROLLED +Pizza 0: ROLLED +Pizza 1: ROLLED +Pizza 4: ROLLED +Pizza 3: ROLLED +Pizza 2: SAUCED +Pizza 1: SAUCED +Pizza 0: SAUCED +Pizza 4: SAUCED +Pizza 3: SAUCED +Pizza 2: CHEESED +Pizza 1: CHEESED +Pizza 0: CHEESED +Pizza 4: CHEESED +Pizza 3: CHEESED +Pizza 2: TOPPED +Pizza 1: TOPPED +Pizza 0: TOPPED +Pizza 4: TOPPED +Pizza 3: TOPPED +Pizza 2: BAKED +Pizza 1: BAKED +Pizza 0: BAKED +Pizza 4: BAKED +Pizza 3: BAKED +Pizza 2: SLICED +Pizza 1: SLICED +Pizza 0: SLICED +Pizza 4: SLICED +Pizza 3: SLICED +Pizza 2: BOXED +Pizza 1: BOXED +Pizza 0: BOXED +Pizza 4: BOXED +Pizza 3: BOXED +1739 +*/ diff --git a/code/concurrent/QuittableTask.java b/code/concurrent/QuittableTask.java new file mode 100644 index 00000000..3cf2a62e --- /dev/null +++ b/code/concurrent/QuittableTask.java @@ -0,0 +1,20 @@ +// concurrent/QuittableTask.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.atomic.AtomicBoolean; +import onjava.Nap; + +public class QuittableTask implements Runnable { + final int id; + public QuittableTask(int id) { this.id = id; } + private AtomicBoolean running = + new AtomicBoolean(true); + public void quit() { running.set(false); } + @Override + public void run() { + while(running.get()) // [1] + new Nap(0.1); + System.out.print(id + " "); // [2] + } +} diff --git a/code/concurrent/QuittingCompletable.java b/code/concurrent/QuittingCompletable.java new file mode 100644 index 00000000..e41e3899 --- /dev/null +++ b/code/concurrent/QuittingCompletable.java @@ -0,0 +1,35 @@ +// concurrent/QuittingCompletable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import onjava.Nap; + +public class QuittingCompletable { + public static void main(String[] args) { + List tasks = + IntStream.range(1, QuittingTasks.COUNT) + .mapToObj(QuittableTask::new) + .collect(Collectors.toList()); + List> cfutures = + tasks.stream() + .map(CompletableFuture::runAsync) + .collect(Collectors.toList()); + new Nap(1); + tasks.forEach(QuittableTask::quit); + cfutures.forEach(CompletableFuture::join); + } +} +/* Output: +7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 +26 27 28 29 30 31 32 33 34 6 35 4 38 39 40 41 42 43 44 +45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 +63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 +81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 +99 100 101 102 103 104 105 106 107 108 109 110 111 112 +1 113 114 116 117 118 119 120 121 122 123 124 125 126 +127 128 129 130 131 132 133 134 135 136 137 138 139 140 +141 142 143 144 145 146 147 148 149 5 115 37 36 2 3 +*/ diff --git a/code/concurrent/QuittingTasks.java b/code/concurrent/QuittingTasks.java new file mode 100644 index 00000000..326e24ce --- /dev/null +++ b/code/concurrent/QuittingTasks.java @@ -0,0 +1,35 @@ +// concurrent/QuittingTasks.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import onjava.Nap; + +public class QuittingTasks { + public static final int COUNT = 150; + public static void main(String[] args) { + ExecutorService es = + Executors.newCachedThreadPool(); + List tasks = + IntStream.range(1, COUNT) + .mapToObj(QuittableTask::new) + .peek(qt -> es.execute(qt)) + .collect(Collectors.toList()); + new Nap(1); + tasks.forEach(QuittableTask::quit); + es.shutdown(); + } +} +/* Output: +24 27 31 8 11 7 19 12 16 4 23 3 28 32 15 20 63 60 68 67 +64 39 47 52 51 55 40 43 48 59 44 56 36 35 71 72 83 103 +96 92 88 99 100 87 91 79 75 84 76 115 108 112 104 107 +111 95 80 147 120 127 119 123 144 143 116 132 124 128 +136 131 135 139 148 140 2 126 6 5 1 18 129 17 14 13 21 +22 9 10 30 33 58 37 125 26 34 133 145 78 137 141 138 62 +74 142 86 65 73 146 70 42 149 121 110 134 105 82 117 +106 113 122 45 114 118 38 50 29 90 101 89 57 53 94 41 +61 66 130 69 77 81 85 93 25 102 54 109 98 49 46 97 +*/ diff --git a/code/concurrent/SharedConstructorArgument.java b/code/concurrent/SharedConstructorArgument.java new file mode 100644 index 00000000..4b09cc26 --- /dev/null +++ b/code/concurrent/SharedConstructorArgument.java @@ -0,0 +1,44 @@ +// concurrent/SharedConstructorArgument.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.atomic.*; + +interface SharedArg { + int get(); +} + +class Unsafe implements SharedArg { + private int i = 0; + public int get() { return i++; } +} + +class Safe implements SharedArg { + private static AtomicInteger counter = + new AtomicInteger(); + public int get() { + return counter.getAndIncrement(); + } +} + +class SharedUser implements HasID { + private final int id; + SharedUser(SharedArg sa) { + id = sa.get(); + } + @Override + public int getID() { return id; } +} + +public class SharedConstructorArgument { + public static void main(String[] args) { + Unsafe unsafe = new Unsafe(); + IDChecker.test(() -> new SharedUser(unsafe)); + Safe safe = new Safe(); + IDChecker.test(() -> new SharedUser(safe)); + } +} +/* Output: +24838 +0 +*/ diff --git a/code/concurrent/SingleThreadExecutor.java b/code/concurrent/SingleThreadExecutor.java new file mode 100644 index 00000000..ef89e3a5 --- /dev/null +++ b/code/concurrent/SingleThreadExecutor.java @@ -0,0 +1,49 @@ +// concurrent/SingleThreadExecutor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; +import onjava.*; + +public class SingleThreadExecutor { + public static void main(String[] args) { + ExecutorService exec = + Executors.newSingleThreadExecutor(); + IntStream.range(0, 10) + .mapToObj(NapTask::new) + .forEach(exec::execute); + System.out.println("All tasks submitted"); + exec.shutdown(); + while(!exec.isTerminated()) { + System.out.println( + Thread.currentThread().getName() + + " awaiting termination"); + new Nap(0.1); + } + } +} +/* Output: +All tasks submitted +main awaiting termination +main awaiting termination +NapTask[0] pool-1-thread-1 +main awaiting termination +NapTask[1] pool-1-thread-1 +main awaiting termination +NapTask[2] pool-1-thread-1 +main awaiting termination +NapTask[3] pool-1-thread-1 +main awaiting termination +NapTask[4] pool-1-thread-1 +main awaiting termination +NapTask[5] pool-1-thread-1 +main awaiting termination +NapTask[6] pool-1-thread-1 +main awaiting termination +NapTask[7] pool-1-thread-1 +main awaiting termination +NapTask[8] pool-1-thread-1 +main awaiting termination +NapTask[9] pool-1-thread-1 +*/ diff --git a/code/concurrent/SingleThreadExecutor2.java b/code/concurrent/SingleThreadExecutor2.java new file mode 100644 index 00000000..08467df5 --- /dev/null +++ b/code/concurrent/SingleThreadExecutor2.java @@ -0,0 +1,30 @@ +// concurrent/SingleThreadExecutor2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; + +public class SingleThreadExecutor2 { + public static void main(String[] args) + throws InterruptedException { + ExecutorService exec = + Executors.newSingleThreadExecutor(); + IntStream.range(0, 10) + .mapToObj(NapTask::new) + .forEach(exec::execute); + exec.shutdown(); + } +} +/* Output: +NapTask[0] pool-1-thread-1 +NapTask[1] pool-1-thread-1 +NapTask[2] pool-1-thread-1 +NapTask[3] pool-1-thread-1 +NapTask[4] pool-1-thread-1 +NapTask[5] pool-1-thread-1 +NapTask[6] pool-1-thread-1 +NapTask[7] pool-1-thread-1 +NapTask[8] pool-1-thread-1 +NapTask[9] pool-1-thread-1 +*/ diff --git a/code/concurrent/SingleThreadExecutor3.java b/code/concurrent/SingleThreadExecutor3.java new file mode 100644 index 00000000..58149423 --- /dev/null +++ b/code/concurrent/SingleThreadExecutor3.java @@ -0,0 +1,30 @@ +// concurrent/SingleThreadExecutor3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; + +public class SingleThreadExecutor3 { + public static void main(String[] args) + throws InterruptedException { + ExecutorService exec = + Executors.newSingleThreadExecutor(); + IntStream.range(0, 10) + .mapToObj(InterferingTask::new) + .forEach(exec::execute); + exec.shutdown(); + } +} +/* Output: +0 pool-1-thread-1 100 +1 pool-1-thread-1 200 +2 pool-1-thread-1 300 +3 pool-1-thread-1 400 +4 pool-1-thread-1 500 +5 pool-1-thread-1 600 +6 pool-1-thread-1 700 +7 pool-1-thread-1 800 +8 pool-1-thread-1 900 +9 pool-1-thread-1 1000 +*/ diff --git a/code/concurrent/StaticIDField.java b/code/concurrent/StaticIDField.java new file mode 100644 index 00000000..22623faa --- /dev/null +++ b/code/concurrent/StaticIDField.java @@ -0,0 +1,10 @@ +// concurrent/StaticIDField.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class StaticIDField implements HasID { + private static int counter = 0; + private int id = counter++; + public int getID() { return id; } +} diff --git a/code/concurrent/StickHolder.java b/code/concurrent/StickHolder.java new file mode 100644 index 00000000..719a1c63 --- /dev/null +++ b/code/concurrent/StickHolder.java @@ -0,0 +1,27 @@ +// concurrent/StickHolder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class StickHolder { + private static class Chopstick {} + private Chopstick stick = new Chopstick(); + private BlockingQueue holder = + new ArrayBlockingQueue<>(1); + public StickHolder() { putDown(); } + public void pickUp() { + try { + holder.take(); // Blocks if unavailable + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + } + public void putDown() { + try { + holder.put(stick); + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/concurrent/StreamExceptions.java b/code/concurrent/StreamExceptions.java new file mode 100644 index 00000000..493daee1 --- /dev/null +++ b/code/concurrent/StreamExceptions.java @@ -0,0 +1,40 @@ +// concurrent/StreamExceptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.stream.*; + +public class StreamExceptions { + static Stream + test(String id, int failcount) { + return + Stream.of(new Breakable(id, failcount)) + .map(Breakable::work) + .map(Breakable::work) + .map(Breakable::work) + .map(Breakable::work); + } + public static void main(String[] args) { + // No operations are even applied ... + test("A", 1); + test("B", 2); + Stream c = test("C", 3); + test("D", 4); + test("E", 5); + // ... until there's a terminal operation: + System.out.println("Entering try"); + try { + c.forEach(System.out::println); // [1] + } catch(Exception e) { + System.out.println(e.getMessage()); + } + } +} +/* Output: +Entering try +Breakable_C [2] +Breakable_C [1] +Throwing Exception for C +Breakable_C failed +*/ diff --git a/code/concurrent/Summing.java b/code/concurrent/Summing.java new file mode 100644 index 00000000..321dcb57 --- /dev/null +++ b/code/concurrent/Summing.java @@ -0,0 +1,47 @@ +// concurrent/Summing.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; +import java.util.function.*; +import onjava.Timer; + +public class Summing { + static void timeTest(String id, long checkValue, + LongSupplier operation) { + System.out.print(id + ": "); + Timer timer = new Timer(); + long result = operation.getAsLong(); + if(result == checkValue) + System.out.println(timer.duration() + "ms"); + else + System.out.format("result: %d%ncheckValue: %d%n", + result, checkValue); + } + public static final int SZ = 100_000_000; + // This even works: + // public static final int SZ = 1_000_000_000; + public static final long CHECK = + (long)SZ * ((long)SZ + 1)/2; // Gauss's formula + public static void main(String[] args) { + System.out.println(CHECK); + timeTest("Sum Stream", CHECK, () -> + LongStream.rangeClosed(0, SZ).sum()); + timeTest("Sum Stream Parallel", CHECK, () -> + LongStream.rangeClosed(0, SZ).parallel().sum()); + timeTest("Sum Iterated", CHECK, () -> + LongStream.iterate(0, i -> i + 1) + .limit(SZ+1).sum()); + // Slower & runs out of memory above 1_000_000: + // timeTest("Sum Iterated Parallel", CHECK, () -> + // LongStream.iterate(0, i -> i + 1) + // .parallel() + // .limit(SZ+1).sum()); + } +} +/* Output: +5000000050000000 +Sum Stream: 167ms +Sum Stream Parallel: 46ms +Sum Iterated: 284ms +*/ diff --git a/code/concurrent/Summing2.java b/code/concurrent/Summing2.java new file mode 100644 index 00000000..c046721f --- /dev/null +++ b/code/concurrent/Summing2.java @@ -0,0 +1,44 @@ +// concurrent/Summing2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromTravisCI} +import java.util.*; + +public class Summing2 { + static long basicSum(long[] ia) { + long sum = 0; + int size = ia.length; + for(int i = 0; i < size; i++) + sum += ia[i]; + return sum; + } + // Approximate largest value of SZ before + // running out of memory on my machine: + public static final int SZ = 20_000_000; + public static final long CHECK = + (long)SZ * ((long)SZ + 1)/2; + public static void main(String[] args) { + System.out.println(CHECK); + long[] la = new long[SZ+1]; + Arrays.parallelSetAll(la, i -> i); + Summing.timeTest("Array Stream Sum", CHECK, () -> + Arrays.stream(la).sum()); + Summing.timeTest("Parallel", CHECK, () -> + Arrays.stream(la).parallel().sum()); + Summing.timeTest("Basic Sum", CHECK, () -> + basicSum(la)); + // Destructive summation: + Summing.timeTest("parallelPrefix", CHECK, () -> { + Arrays.parallelPrefix(la, Long::sum); + return la[la.length - 1]; + }); + } +} +/* Output: +200000010000000 +Array Stream Sum: 104ms +Parallel: 81ms +Basic Sum: 106ms +parallelPrefix: 265ms +*/ diff --git a/code/concurrent/Summing3.java b/code/concurrent/Summing3.java new file mode 100644 index 00000000..252e96f7 --- /dev/null +++ b/code/concurrent/Summing3.java @@ -0,0 +1,42 @@ +// concurrent/Summing3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromTravisCI} +import java.util.*; + +public class Summing3 { + static long basicSum(Long[] ia) { + long sum = 0; + int size = ia.length; + for(int i = 0; i < size; i++) + sum += ia[i]; + return sum; + } + // Approximate largest value of SZ before + // running out of memory on my machine: + public static final int SZ = 10_000_000; + public static final long CHECK = + (long)SZ * ((long)SZ + 1)/2; + public static void main(String[] args) { + System.out.println(CHECK); + Long[] aL = new Long[SZ+1]; + Arrays.parallelSetAll(aL, i -> (long)i); + Summing.timeTest("Long Array Stream Reduce", + CHECK, () -> + Arrays.stream(aL).reduce(0L, Long::sum)); + Summing.timeTest("Long Basic Sum", CHECK, () -> + basicSum(aL)); + // Destructive summation: + Summing.timeTest("Long parallelPrefix",CHECK, ()-> { + Arrays.parallelPrefix(aL, Long::sum); + return aL[aL.length - 1]; + }); + } +} +/* Output: +50000005000000 +Long Array Stream Reduce: 1038ms +Long Basic Sum: 21ms +Long parallelPrefix: 3616ms +*/ diff --git a/code/concurrent/Summing4.java b/code/concurrent/Summing4.java new file mode 100644 index 00000000..bb4fe2ea --- /dev/null +++ b/code/concurrent/Summing4.java @@ -0,0 +1,23 @@ +// concurrent/Summing4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromTravisCI} +import java.util.*; + +public class Summing4 { + public static void main(String[] args) { + System.out.println(Summing3.CHECK); + Long[] aL = new Long[Summing3.SZ+1]; + Arrays.parallelSetAll(aL, i -> (long)i); + Summing.timeTest("Long Parallel", + Summing3.CHECK, () -> + Arrays.stream(aL) + .parallel() + .reduce(0L,Long::sum)); + } +} +/* Output: +50000005000000 +Long Parallel: 1014ms +*/ diff --git a/code/concurrent/SynchronizedConstructor.java b/code/concurrent/SynchronizedConstructor.java new file mode 100644 index 00000000..95aa6a54 --- /dev/null +++ b/code/concurrent/SynchronizedConstructor.java @@ -0,0 +1,29 @@ +// concurrent/SynchronizedConstructor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.atomic.*; + +class SyncConstructor implements HasID { + private final int id; + private static Object + constructorLock = new Object(); + SyncConstructor(SharedArg sa) { + synchronized(constructorLock) { + id = sa.get(); + } + } + @Override + public int getID() { return id; } +} + +public class SynchronizedConstructor { + public static void main(String[] args) { + Unsafe unsafe = new Unsafe(); + IDChecker.test(() -> + new SyncConstructor(unsafe)); + } +} +/* Output: +0 +*/ diff --git a/code/concurrent/SynchronizedFactory.java b/code/concurrent/SynchronizedFactory.java new file mode 100644 index 00000000..669d4d76 --- /dev/null +++ b/code/concurrent/SynchronizedFactory.java @@ -0,0 +1,29 @@ +// concurrent/SynchronizedFactory.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.atomic.*; + +final class SyncFactory implements HasID { + private final int id; + private SyncFactory(SharedArg sa) { + id = sa.get(); + } + @Override + public int getID() { return id; } + public static synchronized + SyncFactory factory(SharedArg sa) { + return new SyncFactory(sa); + } +} + +public class SynchronizedFactory { + public static void main(String[] args) { + Unsafe unsafe = new Unsafe(); + IDChecker.test(() -> + SyncFactory.factory(unsafe)); + } +} +/* Output: +0 +*/ diff --git a/code/concurrent/TestStaticIDField.java b/code/concurrent/TestStaticIDField.java new file mode 100644 index 00000000..5df298b7 --- /dev/null +++ b/code/concurrent/TestStaticIDField.java @@ -0,0 +1,13 @@ +// concurrent/TestStaticIDField.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class TestStaticIDField { + public static void main(String[] args) { + IDChecker.test(StaticIDField::new); + } +} +/* Output: +13287 +*/ diff --git a/code/concurrent/ThrowsChecked.java b/code/concurrent/ThrowsChecked.java new file mode 100644 index 00000000..59177b35 --- /dev/null +++ b/code/concurrent/ThrowsChecked.java @@ -0,0 +1,42 @@ +// concurrent/ThrowsChecked.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; +import java.util.concurrent.*; + +public class ThrowsChecked { + class Checked extends Exception {} + static ThrowsChecked nochecked(ThrowsChecked tc) { + return tc; + } + static ThrowsChecked + withchecked(ThrowsChecked tc) throws Checked { + return tc; + } + static void testStream() { + Stream.of(new ThrowsChecked()) + .map(ThrowsChecked::nochecked) + // .map(ThrowsChecked::withchecked); // [1] + .map(tc -> { + try { + return withchecked(tc); + } catch(Checked e) { + throw new RuntimeException(e); + } + }); + } + static void testCompletableFuture() { + CompletableFuture + .completedFuture(new ThrowsChecked()) + .thenApply(ThrowsChecked::nochecked) + // .thenApply(ThrowsChecked::withchecked); // [2] + .thenApply(tc -> { + try { + return withchecked(tc); + } catch(Checked e) { + throw new RuntimeException(e); + } + }); + } +} diff --git a/code/concurrent/Workable.java b/code/concurrent/Workable.java new file mode 100644 index 00000000..fcdbbbf8 --- /dev/null +++ b/code/concurrent/Workable.java @@ -0,0 +1,32 @@ +// concurrent/Workable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import onjava.Nap; + +public class Workable { + String id; + final double duration; + public Workable(String id, double duration) { + this.id = id; + this.duration = duration; + } + @Override + public String toString() { + return "Workable[" + id + "]"; + } + public static Workable work(Workable tt) { + new Nap(tt.duration); // Seconds + tt.id = tt.id + "W"; + System.out.println(tt); + return tt; + } + public static CompletableFuture + make(String id, double duration) { + return + CompletableFuture.completedFuture( + new Workable(id, duration)) + .thenApplyAsync(Workable::work); + } +} diff --git a/code/control/BreakAndContinue.java b/code/control/BreakAndContinue.java new file mode 100644 index 00000000..1faaaa03 --- /dev/null +++ b/code/control/BreakAndContinue.java @@ -0,0 +1,38 @@ +// control/BreakAndContinue.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Break and continue keywords +import static onjava.Range.*; + +public class BreakAndContinue { + public static void main(String[] args) { + for(int i = 0; i < 100; i++) { // [1] + if(i == 74) break; // Out of for loop + if(i % 9 != 0) continue; // Next iteration + System.out.print(i + " "); + } + System.out.println(); + // Using for-in: + for(int i : range(100)) { // [2] + if(i == 74) break; // Out of for loop + if(i % 9 != 0) continue; // Next iteration + System.out.print(i + " "); + } + System.out.println(); + int i = 0; + // An "infinite loop": + while(true) { // [3] + i++; + int j = i * 27; + if(j == 1269) break; // Out of loop + if(i % 10 != 0) continue; // Top of loop + System.out.print(i + " "); + } + } +} +/* Output: +0 9 18 27 36 45 54 63 72 +0 9 18 27 36 45 54 63 72 +10 20 30 40 +*/ diff --git a/code/control/CommaOperator.java b/code/control/CommaOperator.java new file mode 100644 index 00000000..eae2df82 --- /dev/null +++ b/code/control/CommaOperator.java @@ -0,0 +1,18 @@ +// control/CommaOperator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class CommaOperator { + public static void main(String[] args) { + for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) { + System.out.println("i = " + i + " j = " + j); + } + } +} +/* Output: +i = 1 j = 11 +i = 2 j = 4 +i = 3 j = 6 +i = 4 j = 8 +*/ diff --git a/code/control/ForInFloat.java b/code/control/ForInFloat.java new file mode 100644 index 00000000..cee845b5 --- /dev/null +++ b/code/control/ForInFloat.java @@ -0,0 +1,28 @@ +// control/ForInFloat.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ForInFloat { + public static void main(String[] args) { + Random rand = new Random(47); + float[] f = new float[10]; + for(int i = 0; i < 10; i++) + f[i] = rand.nextFloat(); + for(float x : f) + System.out.println(x); + } +} +/* Output: +0.72711575 +0.39982635 +0.5309454 +0.0534122 +0.16020656 +0.57799757 +0.18847865 +0.4170137 +0.51660204 +0.73734957 +*/ diff --git a/code/control/ForInInt.java b/code/control/ForInInt.java new file mode 100644 index 00000000..f6b283a3 --- /dev/null +++ b/code/control/ForInInt.java @@ -0,0 +1,28 @@ +// control/ForInInt.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import static onjava.Range.*; + +public class ForInInt { + public static void main(String[] args) { + for(int i : range(10)) // 0..9 + System.out.print(i + " "); + System.out.println(); + for(int i : range(5, 10)) // 5..9 + System.out.print(i + " "); + System.out.println(); + for(int i : range(5, 20, 3)) // 5..20 step 3 + System.out.print(i + " "); + System.out.println(); + for(int i : range(20, 5, -3)) // Count down + System.out.print(i + " "); + System.out.println(); + } +} +/* Output: +0 1 2 3 4 5 6 7 8 9 +5 6 7 8 9 +5 8 11 14 17 +20 17 14 11 8 +*/ diff --git a/code/control/ForInString.java b/code/control/ForInString.java new file mode 100644 index 00000000..73e16538 --- /dev/null +++ b/code/control/ForInString.java @@ -0,0 +1,14 @@ +// control/ForInString.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ForInString { + public static void main(String[] args) { + for(char c : "An African Swallow".toCharArray()) + System.out.print(c + " "); + } +} +/* Output: +A n A f r i c a n S w a l l o w +*/ diff --git a/code/control/IfElse.java b/code/control/IfElse.java new file mode 100644 index 00000000..f40a07b7 --- /dev/null +++ b/code/control/IfElse.java @@ -0,0 +1,29 @@ +// control/IfElse.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class IfElse { + static int result = 0; + static void test(int testval, int target) { + if(testval > target) + result = +1; + else if(testval < target) // [1] + result = -1; + else + result = 0; // Match + } + public static void main(String[] args) { + test(10, 5); + System.out.println(result); + test(5, 10); + System.out.println(result); + test(5, 5); + System.out.println(result); + } +} +/* Output: +1 +-1 +0 +*/ diff --git a/code/control/LabeledFor.java b/code/control/LabeledFor.java new file mode 100644 index 00000000..2df79bad --- /dev/null +++ b/code/control/LabeledFor.java @@ -0,0 +1,65 @@ +// control/LabeledFor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// For loops with "labeled break"/"labeled continue." + +public class LabeledFor { + public static void main(String[] args) { + int i = 0; + outer: // Can't have statements here + for(; true ;) { // infinite loop + inner: // Can't have statements here + for(; i < 10; i++) { + System.out.println("i = " + i); + if(i == 2) { + System.out.println("continue"); + continue; + } + if(i == 3) { + System.out.println("break"); + i++; // Otherwise i never + // gets incremented. + break; + } + if(i == 7) { + System.out.println("continue outer"); + i++; // Otherwise i never + // gets incremented. + continue outer; + } + if(i == 8) { + System.out.println("break outer"); + break outer; + } + for(int k = 0; k < 5; k++) { + if(k == 3) { + System.out.println("continue inner"); + continue inner; + } + } + } + } + // Can't break or continue to labels here + } +} +/* Output: +i = 0 +continue inner +i = 1 +continue inner +i = 2 +continue +i = 3 +break +i = 4 +continue inner +i = 5 +continue inner +i = 6 +continue inner +i = 7 +continue outer +i = 8 +break outer +*/ diff --git a/code/control/LabeledWhile.java b/code/control/LabeledWhile.java new file mode 100644 index 00000000..961f5ff3 --- /dev/null +++ b/code/control/LabeledWhile.java @@ -0,0 +1,51 @@ +// control/LabeledWhile.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// "While" with "labeled break" and "labeled continue." + +public class LabeledWhile { + public static void main(String[] args) { + int i = 0; + outer: + while(true) { + System.out.println("Outer while loop"); + while(true) { + i++; + System.out.println("i = " + i); + if(i == 1) { + System.out.println("continue"); + continue; + } + if(i == 3) { + System.out.println("continue outer"); + continue outer; + } + if(i == 5) { + System.out.println("break"); + break; + } + if(i == 7) { + System.out.println("break outer"); + break outer; + } + } + } + } +} +/* Output: +Outer while loop +i = 1 +continue +i = 2 +i = 3 +continue outer +Outer while loop +i = 4 +i = 5 +break +Outer while loop +i = 6 +i = 7 +break outer +*/ diff --git a/code/control/ListCharacters.java b/code/control/ListCharacters.java new file mode 100644 index 00000000..43efce9f --- /dev/null +++ b/code/control/ListCharacters.java @@ -0,0 +1,27 @@ +// control/ListCharacters.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// List all the lowercase ASCII letters + +public class ListCharacters { + public static void main(String[] args) { + for(char c = 0; c < 128; c++) + if(Character.isLowerCase(c)) + System.out.println("value: " + (int)c + + " character: " + c); + } +} +/* Output: (First 10 Lines) +value: 97 character: a +value: 98 character: b +value: 99 character: c +value: 100 character: d +value: 101 character: e +value: 102 character: f +value: 103 character: g +value: 104 character: h +value: 105 character: i +value: 106 character: j + ... +*/ diff --git a/code/control/RandomBounds.java b/code/control/RandomBounds.java new file mode 100644 index 00000000..6befc6f4 --- /dev/null +++ b/code/control/RandomBounds.java @@ -0,0 +1,30 @@ +// control/RandomBounds.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Does Math.random() produce 0.0 and 1.0? +// {java RandomBounds lower} +import onjava.*; + +public class RandomBounds { + public static void main(String[] args) { + new TimedAbort(3); + switch(args.length == 0 ? "" : args[0]) { + case "lower": + while(Math.random() != 0.0) + ; // Keep trying + System.out.println("Produced 0.0!"); + break; + case "upper": + while(Math.random() != 1.0) + ; // Keep trying + System.out.println("Produced 1.0!"); + break; + default: + System.out.println("Usage:"); + System.out.println("\tRandomBounds lower"); + System.out.println("\tRandomBounds upper"); + System.exit(1); + } + } +} diff --git a/code/control/StringSwitch.java b/code/control/StringSwitch.java new file mode 100644 index 00000000..638cc427 --- /dev/null +++ b/code/control/StringSwitch.java @@ -0,0 +1,44 @@ +// control/StringSwitch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class StringSwitch { + public static void main(String[] args) { + String color = "red"; + // Old way: using if-then + if("red".equals(color)) { + System.out.println("RED"); + } else if("green".equals(color)) { + System.out.println("GREEN"); + } else if("blue".equals(color)) { + System.out.println("BLUE"); + } else if("yellow".equals(color)) { + System.out.println("YELLOW"); + } else { + System.out.println("Unknown"); + } + // New way: Strings in switch + switch(color) { + case "red": + System.out.println("RED"); + break; + case "green": + System.out.println("GREEN"); + break; + case "blue": + System.out.println("BLUE"); + break; + case "yellow": + System.out.println("YELLOW"); + break; + default: + System.out.println("Unknown"); + break; + } + } +} +/* Output: +RED +RED +*/ diff --git a/code/control/TestWithReturn.java b/code/control/TestWithReturn.java new file mode 100644 index 00000000..efe05c90 --- /dev/null +++ b/code/control/TestWithReturn.java @@ -0,0 +1,24 @@ +// control/TestWithReturn.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class TestWithReturn { + static int test(int testval, int target) { + if(testval > target) + return +1; + if(testval < target) + return -1; + return 0; // Match + } + public static void main(String[] args) { + System.out.println(test(10, 5)); + System.out.println(test(5, 10)); + System.out.println(test(5, 5)); + } +} +/* Output: +1 +-1 +0 +*/ diff --git a/code/control/TrueFalse.java b/code/control/TrueFalse.java new file mode 100644 index 00000000..e87dade4 --- /dev/null +++ b/code/control/TrueFalse.java @@ -0,0 +1,15 @@ +// control/TrueFalse.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class TrueFalse { + public static void main(String[] args) { + System.out.println(1 == 1); + System.out.println(1 == 2); + } +} +/* Output: +true +false +*/ diff --git a/code/control/VowelsAndConsonants.java b/code/control/VowelsAndConsonants.java new file mode 100644 index 00000000..d3a192d0 --- /dev/null +++ b/code/control/VowelsAndConsonants.java @@ -0,0 +1,44 @@ +// control/VowelsAndConsonants.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates the switch statement +import java.util.*; + +public class VowelsAndConsonants { + public static void main(String[] args) { + Random rand = new Random(47); + for(int i = 0; i < 100; i++) { + int c = rand.nextInt(26) + 'a'; + System.out.print((char)c + ", " + c + ": "); + switch(c) { + case 'a': + case 'e': + case 'i': + case 'o': + case 'u': System.out.println("vowel"); + break; + case 'y': + case 'w': System.out.println("Sometimes vowel"); + break; + default: System.out.println("consonant"); + } + } + } +} +/* Output: (First 13 Lines) +y, 121: Sometimes vowel +n, 110: consonant +z, 122: consonant +b, 98: consonant +r, 114: consonant +n, 110: consonant +y, 121: Sometimes vowel +g, 103: consonant +c, 99: consonant +f, 102: consonant +o, 111: vowel +w, 119: Sometimes vowel +z, 122: consonant + ... +*/ diff --git a/code/control/WhileTest.java b/code/control/WhileTest.java new file mode 100644 index 00000000..075068cf --- /dev/null +++ b/code/control/WhileTest.java @@ -0,0 +1,31 @@ +// control/WhileTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates the while loop + +public class WhileTest { + static boolean condition() { + boolean result = Math.random() < 0.99; + System.out.print(result + ", "); + return result; + } + public static void main(String[] args) { + while(condition()) + System.out.println("Inside 'while'"); + System.out.println("Exited 'while'"); + } +} +/* Output: (First and Last 5 Lines) +true, Inside 'while' +true, Inside 'while' +true, Inside 'while' +true, Inside 'while' +true, Inside 'while' +...________...________...________...________... +true, Inside 'while' +true, Inside 'while' +true, Inside 'while' +true, Inside 'while' +false, Exited 'while' +*/ diff --git a/code/enums/AlarmPoints.java b/code/enums/AlarmPoints.java new file mode 100644 index 00000000..a8731137 --- /dev/null +++ b/code/enums/AlarmPoints.java @@ -0,0 +1,9 @@ +// enums/AlarmPoints.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package enums; +public enum AlarmPoints { + STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3, + OFFICE4, BATHROOM, UTILITY, KITCHEN +} diff --git a/code/enums/BigEnumSet.java b/code/enums/BigEnumSet.java new file mode 100644 index 00000000..52ac3445 --- /dev/null +++ b/code/enums/BigEnumSet.java @@ -0,0 +1,29 @@ +// enums/BigEnumSet.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class BigEnumSet { + enum Big { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, + A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, + A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, + A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, + A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, + A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, + A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, + A70, A71, A72, A73, A74, A75 } + public static void main(String[] args) { + EnumSet bigEnumSet = EnumSet.allOf(Big.class); + System.out.println(bigEnumSet); + } +} +/* Output: +[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, +A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, +A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, +A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, +A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, +A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, +A68, A69, A70, A71, A72, A73, A74, A75] +*/ diff --git a/code/enums/Burrito2.java b/code/enums/Burrito2.java new file mode 100644 index 00000000..8b92ab0d --- /dev/null +++ b/code/enums/Burrito2.java @@ -0,0 +1,28 @@ +// enums/Burrito2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java enums.Burrito2} +package enums; +import static enums.SpicinessEnum.*; + +public class Burrito2 { + SpicinessEnum degree; + public Burrito2(SpicinessEnum degree) { + this.degree = degree; + } + @Override + public String toString() { + return "Burrito is "+ degree; + } + public static void main(String[] args) { + System.out.println(new Burrito2(NOT)); + System.out.println(new Burrito2(MEDIUM)); + System.out.println(new Burrito2(HOT)); + } +} +/* Output: +Burrito is NOT +Burrito is MEDIUM +Burrito is HOT +*/ diff --git a/code/enums/CarWash.java b/code/enums/CarWash.java new file mode 100644 index 00000000..95800e8f --- /dev/null +++ b/code/enums/CarWash.java @@ -0,0 +1,88 @@ +// enums/CarWash.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class CarWash { + public enum Cycle { + UNDERBODY { + @Override + void action() { + System.out.println("Spraying the underbody"); + } + }, + WHEELWASH { + @Override + void action() { + System.out.println("Washing the wheels"); + } + }, + PREWASH { + @Override + void action() { + System.out.println("Loosening the dirt"); + } + }, + BASIC { + @Override + void action() { + System.out.println("The basic wash"); + } + }, + HOTWAX { + @Override + void action() { + System.out.println("Applying hot wax"); + } + }, + RINSE { + @Override + void action() { + System.out.println("Rinsing"); + } + }, + BLOWDRY { + @Override + void action() { + System.out.println("Blowing dry"); + } + }; + abstract void action(); + } + EnumSet cycles = + EnumSet.of(Cycle.BASIC, Cycle.RINSE); + public void add(Cycle cycle) { + cycles.add(cycle); + } + public void washCar() { + for(Cycle c : cycles) + c.action(); + } + @Override + public String toString() { + return cycles.toString(); + } + public static void main(String[] args) { + CarWash wash = new CarWash(); + System.out.println(wash); + wash.washCar(); + // Order of addition is unimportant: + wash.add(Cycle.BLOWDRY); + wash.add(Cycle.BLOWDRY); // Duplicates ignored + wash.add(Cycle.RINSE); + wash.add(Cycle.HOTWAX); + System.out.println(wash); + wash.washCar(); + } +} +/* Output: +[BASIC, RINSE] +The basic wash +Rinsing +[BASIC, HOTWAX, RINSE, BLOWDRY] +The basic wash +Applying hot wax +Rinsing +Blowing dry +*/ diff --git a/code/enums/Competitor.java b/code/enums/Competitor.java new file mode 100644 index 00000000..09bf7141 --- /dev/null +++ b/code/enums/Competitor.java @@ -0,0 +1,10 @@ +// enums/Competitor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Switching one enum on another +package enums; + +public interface Competitor> { + Outcome compete(T competitor); +} diff --git a/code/enums/ConstantSpecificMethod.java b/code/enums/ConstantSpecificMethod.java new file mode 100644 index 00000000..913aa291 --- /dev/null +++ b/code/enums/ConstantSpecificMethod.java @@ -0,0 +1,41 @@ +// enums/ConstantSpecificMethod.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.text.*; + +public enum ConstantSpecificMethod { + DATE_TIME { + @Override + String getInfo() { + return + DateFormat.getDateInstance() + .format(new Date()); + } + }, + CLASSPATH { + @Override + String getInfo() { + return System.getenv("CLASSPATH"); + } + }, + VERSION { + @Override + String getInfo() { + return System.getProperty("java.version"); + } + }; + abstract String getInfo(); + public static void main(String[] args) { + for(ConstantSpecificMethod csm : values()) + System.out.println(csm.getInfo()); + } +} +/* Output: +May 9, 2017 +C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\\gradle\wrapper\gradle- +wrapper.jar +1.8.0_112 +*/ diff --git a/code/enums/EnumClass.java b/code/enums/EnumClass.java new file mode 100644 index 00000000..061f8abf --- /dev/null +++ b/code/enums/EnumClass.java @@ -0,0 +1,51 @@ +// enums/EnumClass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Capabilities of the Enum class + +enum Shrubbery { GROUND, CRAWLING, HANGING } + +public class EnumClass { + public static void main(String[] args) { + for(Shrubbery s : Shrubbery.values()) { + System.out.println( + s + " ordinal: " + s.ordinal()); + System.out.print( + s.compareTo(Shrubbery.CRAWLING) + " "); + System.out.print( + s.equals(Shrubbery.CRAWLING) + " "); + System.out.println(s == Shrubbery.CRAWLING); + System.out.println(s.getDeclaringClass()); + System.out.println(s.name()); + System.out.println("********************"); + } + // Produce an enum value from a String name: + for(String s : + "HANGING CRAWLING GROUND".split(" ")) { + Shrubbery shrub = + Enum.valueOf(Shrubbery.class, s); + System.out.println(shrub); + } + } +} +/* Output: +GROUND ordinal: 0 +-1 false false +class Shrubbery +GROUND +******************** +CRAWLING ordinal: 1 +0 true true +class Shrubbery +CRAWLING +******************** +HANGING ordinal: 2 +1 false false +class Shrubbery +HANGING +******************** +HANGING +CRAWLING +GROUND +*/ diff --git a/code/enums/EnumMaps.java b/code/enums/EnumMaps.java new file mode 100644 index 00000000..f75c5cd4 --- /dev/null +++ b/code/enums/EnumMaps.java @@ -0,0 +1,37 @@ +// enums/EnumMaps.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Basics of EnumMaps +// {java enums.EnumMaps} +package enums; +import java.util.*; +import static enums.AlarmPoints.*; + +interface Command { void action(); } + +public class EnumMaps { + public static void main(String[] args) { + EnumMap em = + new EnumMap<>(AlarmPoints.class); + em.put(KITCHEN, + () -> System.out.println("Kitchen fire!")); + em.put(BATHROOM, + () -> System.out.println("Bathroom alert!")); + for(Map.Entry e: + em.entrySet()) { + System.out.print(e.getKey() + ": "); + e.getValue().action(); + } + try { // If there's no value for a particular key: + em.get(UTILITY).action(); + } catch(Exception e) { + System.out.println("Expected: " + e); + } + } +} +/* Output: +BATHROOM: Bathroom alert! +KITCHEN: Kitchen fire! +Expected: java.lang.NullPointerException +*/ diff --git a/code/enums/EnumSets.java b/code/enums/EnumSets.java new file mode 100644 index 00000000..0e749cad --- /dev/null +++ b/code/enums/EnumSets.java @@ -0,0 +1,39 @@ +// enums/EnumSets.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Operations on EnumSets +// {java enums.EnumSets} +package enums; +import java.util.*; +import static enums.AlarmPoints.*; + +public class EnumSets { + public static void main(String[] args) { + EnumSet points = + EnumSet.noneOf(AlarmPoints.class); // Empty + points.add(BATHROOM); + System.out.println(points); + points.addAll( + EnumSet.of(STAIR1, STAIR2, KITCHEN)); + System.out.println(points); + points = EnumSet.allOf(AlarmPoints.class); + points.removeAll( + EnumSet.of(STAIR1, STAIR2, KITCHEN)); + System.out.println(points); + points.removeAll( + EnumSet.range(OFFICE1, OFFICE4)); + System.out.println(points); + points = EnumSet.complementOf(points); + System.out.println(points); + } +} +/* Output: +[BATHROOM] +[STAIR1, STAIR2, BATHROOM, KITCHEN] +[LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, +UTILITY] +[LOBBY, BATHROOM, UTILITY] +[STAIR1, STAIR2, OFFICE1, OFFICE2, OFFICE3, OFFICE4, +KITCHEN] +*/ diff --git a/code/enums/Input.java b/code/enums/Input.java new file mode 100644 index 00000000..3dc0ec44 --- /dev/null +++ b/code/enums/Input.java @@ -0,0 +1,33 @@ +// enums/Input.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public enum Input { + NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100), + TOOTHPASTE(200), CHIPS(75), SODA(100), SOAP(50), + ABORT_TRANSACTION { + @Override + public int amount() { // Disallow + throw new RuntimeException("ABORT.amount()"); + } + }, + STOP { // This must be the last instance. + @Override + public int amount() { // Disallow + throw new + RuntimeException("SHUT_DOWN.amount()"); + } + }; + int value; // In cents + Input(int value) { this.value = value; } + Input() {} + int amount() { return value; }; // In cents + static Random rand = new Random(47); + public static Input randomSelection() { + // Don't include STOP: + return + values()[rand.nextInt(values().length - 1)]; + } +} diff --git a/code/enums/NonEnum.java b/code/enums/NonEnum.java new file mode 100644 index 00000000..34440730 --- /dev/null +++ b/code/enums/NonEnum.java @@ -0,0 +1,19 @@ +// enums/NonEnum.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class NonEnum { + public static void main(String[] args) { + Class intClass = Integer.class; + try { + for(Object en : intClass.getEnumConstants()) + System.out.println(en); + } catch(Exception e) { + System.out.println("Expected: " + e); + } + } +} +/* Output: +Expected: java.lang.NullPointerException +*/ diff --git a/code/enums/NotClasses.java b/code/enums/NotClasses.java new file mode 100644 index 00000000..681e807d --- /dev/null +++ b/code/enums/NotClasses.java @@ -0,0 +1,50 @@ +// enums/NotClasses.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromGradle} +// javap -c LikeClasses + +enum LikeClasses { + WINKEN { + @Override + void behavior() { + System.out.println("Behavior1"); + } + }, + BLINKEN { + @Override + void behavior() { + System.out.println("Behavior2"); + } + }, + NOD { + @Override + void behavior() { + System.out.println("Behavior3"); + } + }; + abstract void behavior(); +} + +public class NotClasses { + // void f1(LikeClasses.WINKEN instance) {} // Nope +} +/* Output: (First 12 Lines) +Compiled from "NotClasses.java" +abstract class LikeClasses extends +java.lang.Enum { + public static final LikeClasses WINKEN; + + public static final LikeClasses BLINKEN; + + public static final LikeClasses NOD; + + public static LikeClasses[] values(); + Code: + 0: getstatic #2 // Field +$VALUES:[LLikeClasses; + 3: invokevirtual #3 // Method +"[LLikeClasses;".clone:()Ljava/lang/Object; + ... +*/ diff --git a/code/enums/Outcome.java b/code/enums/Outcome.java new file mode 100644 index 00000000..0e2a25d6 --- /dev/null +++ b/code/enums/Outcome.java @@ -0,0 +1,6 @@ +// enums/Outcome.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package enums; +public enum Outcome { WIN, LOSE, DRAW } diff --git a/code/enums/OverrideConstantSpecific.java b/code/enums/OverrideConstantSpecific.java new file mode 100644 index 00000000..28e3343b --- /dev/null +++ b/code/enums/OverrideConstantSpecific.java @@ -0,0 +1,28 @@ +// enums/OverrideConstantSpecific.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public enum OverrideConstantSpecific { + NUT, BOLT, + WASHER { + @Override + void f() { + System.out.println("Overridden method"); + } + }; + void f() { + System.out.println("default behavior"); + } + public static void main(String[] args) { + for(OverrideConstantSpecific ocs : values()) { + System.out.print(ocs + ": "); + ocs.f(); + } + } +} +/* Output: +NUT: default behavior +BOLT: default behavior +WASHER: Overridden method +*/ diff --git a/code/enums/OzWitch.java b/code/enums/OzWitch.java new file mode 100644 index 00000000..c9eedb4f --- /dev/null +++ b/code/enums/OzWitch.java @@ -0,0 +1,32 @@ +// enums/OzWitch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The witches in the land of Oz + +public enum OzWitch { + // Instances must be defined first, before methods: + WEST("Miss Gulch, aka the Wicked Witch of the West"), + NORTH("Glinda, the Good Witch of the North"), + EAST("Wicked Witch of the East, wearer of the Ruby " + + "Slippers, crushed by Dorothy's house"), + SOUTH("Good by inference, but missing"); + private String description; + // Constructor must be package or private access: + private OzWitch(String description) { + this.description = description; + } + public String getDescription() { return description; } + public static void main(String[] args) { + for(OzWitch witch : OzWitch.values()) + System.out.println( + witch + ": " + witch.getDescription()); + } +} +/* Output: +WEST: Miss Gulch, aka the Wicked Witch of the West +NORTH: Glinda, the Good Witch of the North +EAST: Wicked Witch of the East, wearer of the Ruby +Slippers, crushed by Dorothy's house +SOUTH: Good by inference, but missing +*/ diff --git a/code/enums/PostOffice.java b/code/enums/PostOffice.java new file mode 100644 index 00000000..05634820 --- /dev/null +++ b/code/enums/PostOffice.java @@ -0,0 +1,197 @@ +// enums/PostOffice.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Modeling a post office +import java.util.*; +import onjava.*; + +class Mail { + // The NO's reduce probability of random selection: + enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5} + enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4} + enum Readability {ILLEGIBLE,YES1,YES2,YES3,YES4} + enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6} + enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5} + GeneralDelivery generalDelivery; + Scannability scannability; + Readability readability; + Address address; + ReturnAddress returnAddress; + static long counter = 0; + long id = counter++; + @Override + public String toString() { return "Mail " + id; } + public String details() { + return toString() + + ", General Delivery: " + generalDelivery + + ", Address Scanability: " + scannability + + ", Address Readability: " + readability + + ", Address Address: " + address + + ", Return address: " + returnAddress; + } + // Generate test Mail: + public static Mail randomMail() { + Mail m = new Mail(); + m.generalDelivery = + Enums.random(GeneralDelivery.class); + m.scannability = + Enums.random(Scannability.class); + m.readability = + Enums.random(Readability.class); + m.address = Enums.random(Address.class); + m.returnAddress = + Enums.random(ReturnAddress.class); + return m; + } + public static + Iterable generator(final int count) { + return new Iterable() { + int n = count; + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + return n-- > 0; + } + @Override + public Mail next() { + return randomMail(); + } + @Override + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + }; + } + }; + } +} + +public class PostOffice { + enum MailHandler { + GENERAL_DELIVERY { + @Override + boolean handle(Mail m) { + switch(m.generalDelivery) { + case YES: + System.out.println( + "Using general delivery for " + m); + return true; + default: return false; + } + } + }, + MACHINE_SCAN { + @Override + boolean handle(Mail m) { + switch(m.scannability) { + case UNSCANNABLE: return false; + default: + switch(m.address) { + case INCORRECT: return false; + default: + System.out.println( + "Delivering "+ m + " automatically"); + return true; + } + } + } + }, + VISUAL_INSPECTION { + @Override + boolean handle(Mail m) { + switch(m.readability) { + case ILLEGIBLE: return false; + default: + switch(m.address) { + case INCORRECT: return false; + default: + System.out.println( + "Delivering " + m + " normally"); + return true; + } + } + } + }, + RETURN_TO_SENDER { + @Override + boolean handle(Mail m) { + switch(m.returnAddress) { + case MISSING: return false; + default: + System.out.println( + "Returning " + m + " to sender"); + return true; + } + } + }; + abstract boolean handle(Mail m); + } + static void handle(Mail m) { + for(MailHandler handler : MailHandler.values()) + if(handler.handle(m)) + return; + System.out.println(m + " is a dead letter"); + } + public static void main(String[] args) { + for(Mail mail : Mail.generator(10)) { + System.out.println(mail.details()); + handle(mail); + System.out.println("*****"); + } + } +} +/* Output: +Mail 0, General Delivery: NO2, Address Scanability: +UNSCANNABLE, Address Readability: YES3, Address +Address: OK1, Return address: OK1 +Delivering Mail 0 normally +***** +Mail 1, General Delivery: NO5, Address Scanability: +YES3, Address Readability: ILLEGIBLE, Address Address: +OK5, Return address: OK1 +Delivering Mail 1 automatically +***** +Mail 2, General Delivery: YES, Address Scanability: +YES3, Address Readability: YES1, Address Address: OK1, +Return address: OK5 +Using general delivery for Mail 2 +***** +Mail 3, General Delivery: NO4, Address Scanability: +YES3, Address Readability: YES1, Address Address: +INCORRECT, Return address: OK4 +Returning Mail 3 to sender +***** +Mail 4, General Delivery: NO4, Address Scanability: +UNSCANNABLE, Address Readability: YES1, Address +Address: INCORRECT, Return address: OK2 +Returning Mail 4 to sender +***** +Mail 5, General Delivery: NO3, Address Scanability: +YES1, Address Readability: ILLEGIBLE, Address Address: +OK4, Return address: OK2 +Delivering Mail 5 automatically +***** +Mail 6, General Delivery: YES, Address Scanability: +YES4, Address Readability: ILLEGIBLE, Address Address: +OK4, Return address: OK4 +Using general delivery for Mail 6 +***** +Mail 7, General Delivery: YES, Address Scanability: +YES3, Address Readability: YES4, Address Address: OK2, +Return address: MISSING +Using general delivery for Mail 7 +***** +Mail 8, General Delivery: NO3, Address Scanability: +YES1, Address Readability: YES3, Address Address: +INCORRECT, Return address: MISSING +Mail 8 is a dead letter +***** +Mail 9, General Delivery: NO1, Address Scanability: +UNSCANNABLE, Address Readability: YES2, Address +Address: OK1, Return address: OK4 +Delivering Mail 9 normally +***** +*/ diff --git a/code/enums/RandomTest.java b/code/enums/RandomTest.java new file mode 100644 index 00000000..92f2e481 --- /dev/null +++ b/code/enums/RandomTest.java @@ -0,0 +1,21 @@ +// enums/RandomTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; + +enum Activity { SITTING, LYING, STANDING, HOPPING, + RUNNING, DODGING, JUMPING, FALLING, FLYING } + +public class RandomTest { + public static void main(String[] args) { + for(int i = 0; i < 20; i++) + System.out.print( + Enums.random(Activity.class) + " "); + } +} +/* Output: +STANDING FLYING RUNNING STANDING RUNNING STANDING LYING +DODGING SITTING RUNNING HOPPING HOPPING HOPPING RUNNING +STANDING LYING FALLING RUNNING FLYING LYING +*/ diff --git a/code/enums/Reflection.java b/code/enums/Reflection.java new file mode 100644 index 00000000..822a134e --- /dev/null +++ b/code/enums/Reflection.java @@ -0,0 +1,71 @@ +// enums/Reflection.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Analyzing enums using reflection +import java.lang.reflect.*; +import java.util.*; +import onjava.*; + +enum Explore { HERE, THERE } + +public class Reflection { + public static + Set analyze(Class enumClass) { + System.out.println( + "_____ Analyzing " + enumClass + " _____"); + System.out.println("Interfaces:"); + for(Type t : enumClass.getGenericInterfaces()) + System.out.println(t); + System.out.println( + "Base: " + enumClass.getSuperclass()); + System.out.println("Methods: "); + Set methods = new TreeSet<>(); + for(Method m : enumClass.getMethods()) + methods.add(m.getName()); + System.out.println(methods); + return methods; + } + public static void main(String[] args) { + Set exploreMethods = + analyze(Explore.class); + Set enumMethods = analyze(Enum.class); + System.out.println( + "Explore.containsAll(Enum)? " + + exploreMethods.containsAll(enumMethods)); + System.out.print("Explore.removeAll(Enum): "); + exploreMethods.removeAll(enumMethods); + System.out.println(exploreMethods); + // Decompile the code for the enum: + OSExecute.command( + "javap -cp build/classes/java/main Explore"); + } +} +/* Output: +_____ Analyzing class Explore _____ +Interfaces: +Base: class java.lang.Enum +Methods: +[compareTo, equals, getClass, getDeclaringClass, +hashCode, name, notify, notifyAll, ordinal, toString, +valueOf, values, wait] +_____ Analyzing class java.lang.Enum _____ +Interfaces: +java.lang.Comparable +interface java.io.Serializable +Base: class java.lang.Object +Methods: +[compareTo, equals, getClass, getDeclaringClass, +hashCode, name, notify, notifyAll, ordinal, toString, +valueOf, wait] +Explore.containsAll(Enum)? true +Explore.removeAll(Enum): [values] +Compiled from "Reflection.java" +final class Explore extends java.lang.Enum { + public static final Explore HERE; + public static final Explore THERE; + public static Explore[] values(); + public static Explore valueOf(java.lang.String); + static {}; +} +*/ diff --git a/code/enums/RoShamBo.java b/code/enums/RoShamBo.java new file mode 100644 index 00000000..76b3d76f --- /dev/null +++ b/code/enums/RoShamBo.java @@ -0,0 +1,21 @@ +// enums/RoShamBo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Common tools for RoShamBo examples +package enums; +import onjava.*; + +public class RoShamBo { + public static > + void match(T a, T b) { + System.out.println( + a + " vs. " + b + ": " + a.compete(b)); + } + public static & Competitor> + void play(Class rsbClass, int size) { + for(int i = 0; i < size; i++) + match( + Enums.random(rsbClass),Enums.random(rsbClass)); + } +} diff --git a/code/enums/RoShamBo1.java b/code/enums/RoShamBo1.java new file mode 100644 index 00000000..abf52c9c --- /dev/null +++ b/code/enums/RoShamBo1.java @@ -0,0 +1,104 @@ +// enums/RoShamBo1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of multiple dispatching +// {java enums.RoShamBo1} +package enums; +import java.util.*; +import static enums.Outcome.*; + +interface Item { + Outcome compete(Item it); + Outcome eval(Paper p); + Outcome eval(Scissors s); + Outcome eval(Rock r); +} + +class Paper implements Item { + @Override + public Outcome compete(Item it) { + return it.eval(this); + } + @Override + public Outcome eval(Paper p) { return DRAW; } + @Override + public Outcome eval(Scissors s) { return WIN; } + @Override + public Outcome eval(Rock r) { return LOSE; } + @Override + public String toString() { return "Paper"; } +} + +class Scissors implements Item { + @Override + public Outcome compete(Item it) { + return it.eval(this); + } + @Override + public Outcome eval(Paper p) { return LOSE; } + @Override + public Outcome eval(Scissors s) { return DRAW; } + @Override + public Outcome eval(Rock r) { return WIN; } + @Override + public String toString() { return "Scissors"; } +} + +class Rock implements Item { + @Override + public Outcome compete(Item it) { + return it.eval(this); + } + @Override + public Outcome eval(Paper p) { return WIN; } + @Override + public Outcome eval(Scissors s) { return LOSE; } + @Override + public Outcome eval(Rock r) { return DRAW; } + @Override + public String toString() { return "Rock"; } +} + +public class RoShamBo1 { + static final int SIZE = 20; + private static Random rand = new Random(47); + public static Item newItem() { + switch(rand.nextInt(3)) { + default: + case 0: return new Scissors(); + case 1: return new Paper(); + case 2: return new Rock(); + } + } + public static void match(Item a, Item b) { + System.out.println( + a + " vs. " + b + ": " + a.compete(b)); + } + public static void main(String[] args) { + for(int i = 0; i < SIZE; i++) + match(newItem(), newItem()); + } +} +/* Output: +Rock vs. Rock: DRAW +Paper vs. Rock: WIN +Paper vs. Rock: WIN +Paper vs. Rock: WIN +Scissors vs. Paper: WIN +Scissors vs. Scissors: DRAW +Scissors vs. Paper: WIN +Rock vs. Paper: LOSE +Paper vs. Paper: DRAW +Rock vs. Paper: LOSE +Paper vs. Scissors: LOSE +Paper vs. Scissors: LOSE +Rock vs. Scissors: WIN +Rock vs. Paper: LOSE +Paper vs. Rock: WIN +Scissors vs. Paper: WIN +Paper vs. Scissors: LOSE +Paper vs. Scissors: LOSE +Paper vs. Scissors: LOSE +Paper vs. Scissors: LOSE +*/ diff --git a/code/enums/RoShamBo2.java b/code/enums/RoShamBo2.java new file mode 100644 index 00000000..ec8ab25b --- /dev/null +++ b/code/enums/RoShamBo2.java @@ -0,0 +1,55 @@ +// enums/RoShamBo2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Switching one enum on another +// {java enums.RoShamBo2} +package enums; +import static enums.Outcome.*; + +public enum RoShamBo2 implements Competitor { + PAPER(DRAW, LOSE, WIN), + SCISSORS(WIN, DRAW, LOSE), + ROCK(LOSE, WIN, DRAW); + private Outcome vPAPER, vSCISSORS, vROCK; + RoShamBo2(Outcome paper, + Outcome scissors, Outcome rock) { + this.vPAPER = paper; + this.vSCISSORS = scissors; + this.vROCK = rock; + } + @Override + public Outcome compete(RoShamBo2 it) { + switch(it) { + default: + case PAPER: return vPAPER; + case SCISSORS: return vSCISSORS; + case ROCK: return vROCK; + } + } + public static void main(String[] args) { + RoShamBo.play(RoShamBo2.class, 20); + } +} +/* Output: +ROCK vs. ROCK: DRAW +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +PAPER vs. PAPER: DRAW +PAPER vs. SCISSORS: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. SCISSORS: DRAW +ROCK vs. SCISSORS: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +ROCK vs. PAPER: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +*/ diff --git a/code/enums/RoShamBo3.java b/code/enums/RoShamBo3.java new file mode 100644 index 00000000..ffcd2cf1 --- /dev/null +++ b/code/enums/RoShamBo3.java @@ -0,0 +1,71 @@ +// enums/RoShamBo3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using constant-specific methods +// {java enums.RoShamBo3} +package enums; +import static enums.Outcome.*; + +public enum RoShamBo3 implements Competitor { + PAPER { + @Override + public Outcome compete(RoShamBo3 it) { + switch(it) { + default: // To placate the compiler + case PAPER: return DRAW; + case SCISSORS: return LOSE; + case ROCK: return WIN; + } + } + }, + SCISSORS { + @Override + public Outcome compete(RoShamBo3 it) { + switch(it) { + default: + case PAPER: return WIN; + case SCISSORS: return DRAW; + case ROCK: return LOSE; + } + } + }, + ROCK { + @Override + public Outcome compete(RoShamBo3 it) { + switch(it) { + default: + case PAPER: return LOSE; + case SCISSORS: return WIN; + case ROCK: return DRAW; + } + } + }; + @Override + public abstract Outcome compete(RoShamBo3 it); + public static void main(String[] args) { + RoShamBo.play(RoShamBo3.class, 20); + } +} +/* Output: +ROCK vs. ROCK: DRAW +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +PAPER vs. PAPER: DRAW +PAPER vs. SCISSORS: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. SCISSORS: DRAW +ROCK vs. SCISSORS: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +ROCK vs. PAPER: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +*/ diff --git a/code/enums/RoShamBo4.java b/code/enums/RoShamBo4.java new file mode 100644 index 00000000..f0b473ae --- /dev/null +++ b/code/enums/RoShamBo4.java @@ -0,0 +1,57 @@ +// enums/RoShamBo4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java enums.RoShamBo4} +package enums; + +public enum RoShamBo4 implements Competitor { + ROCK { + @Override + public Outcome compete(RoShamBo4 opponent) { + return compete(SCISSORS, opponent); + } + }, + SCISSORS { + @Override + public Outcome compete(RoShamBo4 opponent) { + return compete(PAPER, opponent); + } + }, + PAPER { + @Override + public Outcome compete(RoShamBo4 opponent) { + return compete(ROCK, opponent); + } + }; + Outcome compete(RoShamBo4 loser, RoShamBo4 opponent) { + return ((opponent == this) ? Outcome.DRAW + : ((opponent == loser) ? Outcome.WIN + : Outcome.LOSE)); + } + public static void main(String[] args) { + RoShamBo.play(RoShamBo4.class, 20); + } +} +/* Output: +PAPER vs. PAPER: DRAW +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +ROCK vs. SCISSORS: WIN +ROCK vs. ROCK: DRAW +ROCK vs. SCISSORS: WIN +PAPER vs. SCISSORS: LOSE +SCISSORS vs. SCISSORS: DRAW +PAPER vs. SCISSORS: LOSE +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +PAPER vs. ROCK: WIN +PAPER vs. SCISSORS: LOSE +SCISSORS vs. PAPER: WIN +ROCK vs. SCISSORS: WIN +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +*/ diff --git a/code/enums/RoShamBo5.java b/code/enums/RoShamBo5.java new file mode 100644 index 00000000..69885c01 --- /dev/null +++ b/code/enums/RoShamBo5.java @@ -0,0 +1,59 @@ +// enums/RoShamBo5.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Multiple dispatching using an EnumMap of EnumMaps +// {java enums.RoShamBo5} +package enums; +import java.util.*; +import static enums.Outcome.*; + +enum RoShamBo5 implements Competitor { + PAPER, SCISSORS, ROCK; + static EnumMap> + table = new EnumMap<>(RoShamBo5.class); + static { + for(RoShamBo5 it : RoShamBo5.values()) + table.put(it, new EnumMap<>(RoShamBo5.class)); + initRow(PAPER, DRAW, LOSE, WIN); + initRow(SCISSORS, WIN, DRAW, LOSE); + initRow(ROCK, LOSE, WIN, DRAW); + } + static void initRow(RoShamBo5 it, + Outcome vPAPER, Outcome vSCISSORS, Outcome vROCK) { + EnumMap row = + RoShamBo5.table.get(it); + row.put(RoShamBo5.PAPER, vPAPER); + row.put(RoShamBo5.SCISSORS, vSCISSORS); + row.put(RoShamBo5.ROCK, vROCK); + } + @Override + public Outcome compete(RoShamBo5 it) { + return table.get(this).get(it); + } + public static void main(String[] args) { + RoShamBo.play(RoShamBo5.class, 20); + } +} +/* Output: +ROCK vs. ROCK: DRAW +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +PAPER vs. PAPER: DRAW +PAPER vs. SCISSORS: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. SCISSORS: DRAW +ROCK vs. SCISSORS: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +ROCK vs. PAPER: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +*/ diff --git a/code/enums/RoShamBo6.java b/code/enums/RoShamBo6.java new file mode 100644 index 00000000..164911d5 --- /dev/null +++ b/code/enums/RoShamBo6.java @@ -0,0 +1,46 @@ +// enums/RoShamBo6.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Enums using "tables" instead of multiple dispatch +// {java enums.RoShamBo6} +package enums; +import static enums.Outcome.*; + +enum RoShamBo6 implements Competitor { + PAPER, SCISSORS, ROCK; + private static Outcome[][] table = { + { DRAW, LOSE, WIN }, // PAPER + { WIN, DRAW, LOSE }, // SCISSORS + { LOSE, WIN, DRAW }, // ROCK + }; + @Override + public Outcome compete(RoShamBo6 other) { + return table[this.ordinal()][other.ordinal()]; + } + public static void main(String[] args) { + RoShamBo.play(RoShamBo6.class, 20); + } +} +/* Output: +ROCK vs. ROCK: DRAW +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +PAPER vs. PAPER: DRAW +PAPER vs. SCISSORS: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. SCISSORS: DRAW +ROCK vs. SCISSORS: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +ROCK vs. PAPER: LOSE +ROCK vs. SCISSORS: WIN +SCISSORS vs. ROCK: LOSE +PAPER vs. SCISSORS: LOSE +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +SCISSORS vs. PAPER: WIN +*/ diff --git a/code/enums/SecurityCategory.java b/code/enums/SecurityCategory.java new file mode 100644 index 00000000..884cb56a --- /dev/null +++ b/code/enums/SecurityCategory.java @@ -0,0 +1,46 @@ +// enums/SecurityCategory.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// More succinct subcategorization of enums +import onjava.*; + +enum SecurityCategory { + STOCK(Security.Stock.class), + BOND(Security.Bond.class); + Security[] values; + SecurityCategory(Class kind) { + values = kind.getEnumConstants(); + } + interface Security { + enum Stock implements Security { + SHORT, LONG, MARGIN + } + enum Bond implements Security { + MUNICIPAL, JUNK + } + } + public Security randomSelection() { + return Enums.random(values); + } + public static void main(String[] args) { + for(int i = 0; i < 10; i++) { + SecurityCategory category = + Enums.random(SecurityCategory.class); + System.out.println(category + ": " + + category.randomSelection()); + } + } +} +/* Output: +BOND: MUNICIPAL +BOND: MUNICIPAL +STOCK: MARGIN +STOCK: MARGIN +BOND: JUNK +STOCK: SHORT +STOCK: LONG +STOCK: LONG +BOND: MUNICIPAL +BOND: JUNK +*/ diff --git a/code/enums/SpaceShip.java b/code/enums/SpaceShip.java new file mode 100644 index 00000000..3623389e --- /dev/null +++ b/code/enums/SpaceShip.java @@ -0,0 +1,28 @@ +// enums/SpaceShip.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public enum SpaceShip { + SCOUT, CARGO, TRANSPORT, + CRUISER, BATTLESHIP, MOTHERSHIP; + @Override + public String toString() { + String id = name(); + String lower = id.substring(1).toLowerCase(); + return id.charAt(0) + lower; + } + public static void main(String[] args) { + Stream.of(values()) + .forEach(System.out::println); + } +} +/* Output: +Scout +Cargo +Transport +Cruiser +Battleship +Mothership +*/ diff --git a/code/enums/SpicinessEnum.java b/code/enums/SpicinessEnum.java new file mode 100644 index 00000000..eef6f89a --- /dev/null +++ b/code/enums/SpicinessEnum.java @@ -0,0 +1,9 @@ +// enums/SpicinessEnum.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package enums; + +public enum SpicinessEnum { + NOT, MILD, MEDIUM, HOT, FLAMING +} diff --git a/code/enums/TrafficLight.java b/code/enums/TrafficLight.java new file mode 100644 index 00000000..b018e02c --- /dev/null +++ b/code/enums/TrafficLight.java @@ -0,0 +1,44 @@ +// enums/TrafficLight.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Enums in switch statements + +// Define an enum type: +enum Signal { GREEN, YELLOW, RED, } + +public class TrafficLight { + Signal color = Signal.RED; + public void change() { + switch(color) { + // Note you don't have to say Signal.RED + // in the case statement: + case RED: color = Signal.GREEN; + break; + case GREEN: color = Signal.YELLOW; + break; + case YELLOW: color = Signal.RED; + break; + } + } + @Override + public String toString() { + return "The traffic light is " + color; + } + public static void main(String[] args) { + TrafficLight t = new TrafficLight(); + for(int i = 0; i < 7; i++) { + System.out.println(t); + t.change(); + } + } +} +/* Output: +The traffic light is RED +The traffic light is GREEN +The traffic light is YELLOW +The traffic light is RED +The traffic light is GREEN +The traffic light is YELLOW +The traffic light is RED +*/ diff --git a/code/enums/UpcastEnum.java b/code/enums/UpcastEnum.java new file mode 100644 index 00000000..a5df2a86 --- /dev/null +++ b/code/enums/UpcastEnum.java @@ -0,0 +1,21 @@ +// enums/UpcastEnum.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// No values() method if you upcast an enum + +enum Search { HITHER, YON } + +public class UpcastEnum { + public static void main(String[] args) { + Search[] vals = Search.values(); + Enum e = Search.HITHER; // Upcast + // e.values(); // No values() in Enum + for(Enum en : e.getClass().getEnumConstants()) + System.out.println(en); + } +} +/* Output: +HITHER +YON +*/ diff --git a/code/enums/VendingMachine.java b/code/enums/VendingMachine.java new file mode 100644 index 00000000..bc7d7c19 --- /dev/null +++ b/code/enums/VendingMachine.java @@ -0,0 +1,183 @@ +// enums/VendingMachine.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java VendingMachine VendingMachineInput.txt} +import java.util.*; +import java.io.IOException; +import java.util.function.*; +import java.nio.file.*; +import java.util.stream.*; + +enum Category { + MONEY(Input.NICKEL, Input.DIME, + Input.QUARTER, Input.DOLLAR), + ITEM_SELECTION(Input.TOOTHPASTE, Input.CHIPS, + Input.SODA, Input.SOAP), + QUIT_TRANSACTION(Input.ABORT_TRANSACTION), + SHUT_DOWN(Input.STOP); + private Input[] values; + Category(Input... types) { values = types; } + private static EnumMap categories = + new EnumMap<>(Input.class); + static { + for(Category c : Category.class.getEnumConstants()) + for(Input type : c.values) + categories.put(type, c); + } + public static Category categorize(Input input) { + return categories.get(input); + } +} + +public class VendingMachine { + private static State state = State.RESTING; + private static int amount = 0; + private static Input selection = null; + enum StateDuration { TRANSIENT } // Tagging enum + enum State { + RESTING { + @Override + void next(Input input) { + switch(Category.categorize(input)) { + case MONEY: + amount += input.amount(); + state = ADDING_MONEY; + break; + case SHUT_DOWN: + state = TERMINAL; + default: + } + } + }, + ADDING_MONEY { + @Override + void next(Input input) { + switch(Category.categorize(input)) { + case MONEY: + amount += input.amount(); + break; + case ITEM_SELECTION: + selection = input; + if(amount < selection.amount()) + System.out.println( + "Insufficient money for " + selection); + else state = DISPENSING; + break; + case QUIT_TRANSACTION: + state = GIVING_CHANGE; + break; + case SHUT_DOWN: + state = TERMINAL; + default: + } + } + }, + DISPENSING(StateDuration.TRANSIENT) { + @Override + void next() { + System.out.println("here is your " + selection); + amount -= selection.amount(); + state = GIVING_CHANGE; + } + }, + GIVING_CHANGE(StateDuration.TRANSIENT) { + @Override + void next() { + if(amount > 0) { + System.out.println("Your change: " + amount); + amount = 0; + } + state = RESTING; + } + }, + TERMINAL {@Override + void output() { System.out.println("Halted"); } }; + private boolean isTransient = false; + State() {} + State(StateDuration trans) { isTransient = true; } + void next(Input input) { + throw new RuntimeException("Only call " + + "next(Input input) for non-transient states"); + } + void next() { + throw new RuntimeException( + "Only call next() for " + + "StateDuration.TRANSIENT states"); + } + void output() { System.out.println(amount); } + } + static void run(Supplier gen) { + while(state != State.TERMINAL) { + state.next(gen.get()); + while(state.isTransient) + state.next(); + state.output(); + } + } + public static void main(String[] args) { + Supplier gen = new RandomInputSupplier(); + if(args.length == 1) + gen = new FileInputSupplier(args[0]); + run(gen); + } +} + +// For a basic sanity check: +class RandomInputSupplier implements Supplier { + @Override + public Input get() { + return Input.randomSelection(); + } +} + +// Create Inputs from a file of ';'-separated strings: +class FileInputSupplier implements Supplier { + private Iterator input; + FileInputSupplier(String fileName) { + try { + input = Files.lines(Paths.get(fileName)) + .skip(1) // Skip the comment line + .flatMap(s -> Arrays.stream(s.split(";"))) + .map(String::trim) + .collect(Collectors.toList()) + .iterator(); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + @Override + public Input get() { + if(!input.hasNext()) + return null; + return Enum.valueOf( + Input.class, input.next().trim()); + } +} +/* Output: +25 +50 +75 +here is your CHIPS +0 +100 +200 +here is your TOOTHPASTE +0 +25 +35 +Your change: 35 +0 +25 +35 +Insufficient money for SODA +35 +60 +70 +75 +Insufficient money for SODA +75 +Your change: 75 +0 +Halted +*/ diff --git a/code/enums/VendingMachineInput.txt b/code/enums/VendingMachineInput.txt new file mode 100644 index 00000000..b39554f0 --- /dev/null +++ b/code/enums/VendingMachineInput.txt @@ -0,0 +1,8 @@ +// enums/VendingMachineInput.txt +QUARTER; QUARTER; QUARTER; CHIPS; +DOLLAR; DOLLAR; TOOTHPASTE; +QUARTER; DIME; ABORT_TRANSACTION; +QUARTER; DIME; SODA; +QUARTER; DIME; NICKEL; SODA; +ABORT_TRANSACTION; +STOP; diff --git a/code/enums/cartoons/EnumImplementation.java b/code/enums/cartoons/EnumImplementation.java new file mode 100644 index 00000000..58902e3f --- /dev/null +++ b/code/enums/cartoons/EnumImplementation.java @@ -0,0 +1,37 @@ +// enums/cartoons/EnumImplementation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An enum can implement an interface +// {java enums.cartoons.EnumImplementation} +package enums.cartoons; +import java.util.*; +import java.util.function.*; + +enum CartoonCharacter +implements Supplier { + SLAPPY, SPANKY, PUNCHY, + SILLY, BOUNCY, NUTTY, BOB; + private Random rand = + new Random(47); + @Override + public CartoonCharacter get() { + return values()[rand.nextInt(values().length)]; + } +} + +public class EnumImplementation { + public static void printNext(Supplier rg) { + System.out.print(rg.get() + ", "); + } + public static void main(String[] args) { + // Choose any instance: + CartoonCharacter cc = CartoonCharacter.BOB; + for(int i = 0; i < 10; i++) + printNext(cc); + } +} +/* Output: +BOB, PUNCHY, BOB, SPANKY, NUTTY, PUNCHY, SLAPPY, NUTTY, +NUTTY, SLAPPY, +*/ diff --git a/code/enums/menu/Course.java b/code/enums/menu/Course.java new file mode 100644 index 00000000..96481f1e --- /dev/null +++ b/code/enums/menu/Course.java @@ -0,0 +1,20 @@ +// enums/menu/Course.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package enums.menu; +import onjava.*; + +public enum Course { + APPETIZER(Food.Appetizer.class), + MAINCOURSE(Food.MainCourse.class), + DESSERT(Food.Dessert.class), + COFFEE(Food.Coffee.class); + private Food[] values; + private Course(Class kind) { + values = kind.getEnumConstants(); + } + public Food randomSelection() { + return Enums.random(values); + } +} diff --git a/code/enums/menu/Food.java b/code/enums/menu/Food.java new file mode 100644 index 00000000..4b97f69e --- /dev/null +++ b/code/enums/menu/Food.java @@ -0,0 +1,24 @@ +// enums/menu/Food.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Subcategorization of enums within interfaces +package enums.menu; + +public interface Food { + enum Appetizer implements Food { + SALAD, SOUP, SPRING_ROLLS; + } + enum MainCourse implements Food { + LASAGNE, BURRITO, PAD_THAI, + LENTILS, HUMMOUS, VINDALOO; + } + enum Dessert implements Food { + TIRAMISU, GELATO, BLACK_FOREST_CAKE, + FRUIT, CREME_CARAMEL; + } + enum Coffee implements Food { + BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, + LATTE, CAPPUCCINO, TEA, HERB_TEA; + } +} diff --git a/code/enums/menu/Meal.java b/code/enums/menu/Meal.java new file mode 100644 index 00000000..64bc496d --- /dev/null +++ b/code/enums/menu/Meal.java @@ -0,0 +1,45 @@ +// enums/menu/Meal.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java enums.menu.Meal} +package enums.menu; + +public class Meal { + public static void main(String[] args) { + for(int i = 0; i < 5; i++) { + for(Course course : Course.values()) { + Food food = course.randomSelection(); + System.out.println(food); + } + System.out.println("***"); + } + } +} +/* Output: +SPRING_ROLLS +VINDALOO +FRUIT +DECAF_COFFEE +*** +SOUP +VINDALOO +FRUIT +TEA +*** +SALAD +BURRITO +FRUIT +TEA +*** +SALAD +BURRITO +CREME_CARAMEL +LATTE +*** +SOUP +BURRITO +TIRAMISU +ESPRESSO +*** +*/ diff --git a/code/enums/menu/Meal2.java b/code/enums/menu/Meal2.java new file mode 100644 index 00000000..df1b90a5 --- /dev/null +++ b/code/enums/menu/Meal2.java @@ -0,0 +1,74 @@ +// enums/menu/Meal2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java enums.menu.Meal2} +package enums.menu; +import onjava.*; + +public enum Meal2 { + APPETIZER(Food.Appetizer.class), + MAINCOURSE(Food.MainCourse.class), + DESSERT(Food.Dessert.class), + COFFEE(Food.Coffee.class); + private Food[] values; + private Meal2(Class kind) { + values = kind.getEnumConstants(); + } + public interface Food { + enum Appetizer implements Food { + SALAD, SOUP, SPRING_ROLLS; + } + enum MainCourse implements Food { + LASAGNE, BURRITO, PAD_THAI, + LENTILS, HUMMOUS, VINDALOO; + } + enum Dessert implements Food { + TIRAMISU, GELATO, BLACK_FOREST_CAKE, + FRUIT, CREME_CARAMEL; + } + enum Coffee implements Food { + BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, + LATTE, CAPPUCCINO, TEA, HERB_TEA; + } + } + public Food randomSelection() { + return Enums.random(values); + } + public static void main(String[] args) { + for(int i = 0; i < 5; i++) { + for(Meal2 meal : Meal2.values()) { + Food food = meal.randomSelection(); + System.out.println(food); + } + System.out.println("***"); + } + } +} +/* Output: +SPRING_ROLLS +VINDALOO +FRUIT +DECAF_COFFEE +*** +SOUP +VINDALOO +FRUIT +TEA +*** +SALAD +BURRITO +FRUIT +TEA +*** +SALAD +BURRITO +CREME_CARAMEL +LATTE +*** +SOUP +BURRITO +TIRAMISU +ESPRESSO +*** +*/ diff --git a/code/enums/menu/TypeOfFood.java b/code/enums/menu/TypeOfFood.java new file mode 100644 index 00000000..5e59e78b --- /dev/null +++ b/code/enums/menu/TypeOfFood.java @@ -0,0 +1,16 @@ +// enums/menu/TypeOfFood.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java enums.menu.TypeOfFood} +package enums.menu; +import static enums.menu.Food.*; + +public class TypeOfFood { + public static void main(String[] args) { + Food food = Appetizer.SALAD; + food = MainCourse.LASAGNE; + food = Dessert.GELATO; + food = Coffee.CAPPUCCINO; + } +} diff --git a/code/equalshashcode/ComposedEquality.java b/code/equalshashcode/ComposedEquality.java new file mode 100644 index 00000000..c224231c --- /dev/null +++ b/code/equalshashcode/ComposedEquality.java @@ -0,0 +1,66 @@ +// equalshashcode/ComposedEquality.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class Part { + String ss; + double dd; + Part(String ss, double dd) { + this.ss = ss; + this.dd = dd; + } + @Override + public boolean equals(Object rval) { + return rval instanceof Part && + Objects.equals(ss, ((Part)rval).ss) && + Objects.equals(dd, ((Part)rval).dd); + } +} + +public class ComposedEquality extends SuccinctEquality { + Part part; + public ComposedEquality(int i, String s, double d) { + super(i, s, d); + part = new Part(s, d); + System.out.println("made 'ComposedEquality'"); + } + @Override + public boolean equals(Object rval) { + return rval instanceof ComposedEquality && + super.equals(rval) && + Objects.equals(part, + ((ComposedEquality)rval).part); + } + public static void main(String[] args) { + Equality.testAll( (i, s, d) -> + new ComposedEquality(i, s, d)); + } +} +/* Output: +made 'Equality' +made 'SuccinctEquality' +made 'ComposedEquality' +made 'Equality' +made 'SuccinctEquality' +made 'ComposedEquality' +made 'Equality' +made 'SuccinctEquality' +made 'ComposedEquality' +-- Testing null -- +null instanceof Equality: false +Expected false, got false +-- Testing same object -- +same object instanceof Equality: true +Expected true, got true +-- Testing different type -- +different type instanceof Equality: false +Expected false, got false +-- Testing same values -- +same values instanceof Equality: true +Expected true, got true +-- Testing different values -- +different values instanceof Equality: true +Expected false, got false +*/ diff --git a/code/equalshashcode/CountedString.java b/code/equalshashcode/CountedString.java new file mode 100644 index 00000000..5a6ec5fa --- /dev/null +++ b/code/equalshashcode/CountedString.java @@ -0,0 +1,72 @@ +// equalshashcode/CountedString.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating a good hashCode() +import java.util.*; + +public class CountedString { + private static List created = + new ArrayList<>(); + private String s; + private int id = 0; + public CountedString(String str) { + s = str; + created.add(s); + // id is the total number of instances + // of this String used by CountedString: + for(String s2 : created) + if(s2.equals(s)) + id++; + } + @Override + public String toString() { + return "String: " + s + " id: " + id + + " hashCode(): " + hashCode(); + } + @Override + public int hashCode() { + // The very simple approach: + // return s.hashCode() * id; + // Using Joshua Bloch's recipe: + int result = 17; + result = 37 * result + s.hashCode(); + result = 37 * result + id; + return result; + } + @Override + public boolean equals(Object o) { + return o instanceof CountedString && + Objects.equals(s, ((CountedString)o).s) && + Objects.equals(id, ((CountedString)o).id); + } + public static void main(String[] args) { + Map map = new HashMap<>(); + CountedString[] cs = new CountedString[5]; + for(int i = 0; i < cs.length; i++) { + cs[i] = new CountedString("hi"); + map.put(cs[i], i); // Autobox int to Integer + } + System.out.println(map); + for(CountedString cstring : cs) { + System.out.println("Looking up " + cstring); + System.out.println(map.get(cstring)); + } + } +} +/* Output: +{String: hi id: 4 hashCode(): 146450=3, String: hi id: +5 hashCode(): 146451=4, String: hi id: 2 hashCode(): +146448=1, String: hi id: 3 hashCode(): 146449=2, +String: hi id: 1 hashCode(): 146447=0} +Looking up String: hi id: 1 hashCode(): 146447 +0 +Looking up String: hi id: 2 hashCode(): 146448 +1 +Looking up String: hi id: 3 hashCode(): 146449 +2 +Looking up String: hi id: 4 hashCode(): 146450 +3 +Looking up String: hi id: 5 hashCode(): 146451 +4 +*/ diff --git a/code/equalshashcode/DefaultComparison.java b/code/equalshashcode/DefaultComparison.java new file mode 100644 index 00000000..d855de36 --- /dev/null +++ b/code/equalshashcode/DefaultComparison.java @@ -0,0 +1,24 @@ +// equalshashcode/DefaultComparison.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class DefaultComparison { + private int i, j, k; + DefaultComparison(int i, int j, int k) { + this.i = i; + this.j = j; + this.k = k; + } + public static void main(String[] args) { + DefaultComparison + a = new DefaultComparison(1, 2, 3), + b = new DefaultComparison(1, 2, 3); + System.out.println(a == a); + System.out.println(a == b); + } +} +/* Output: +true +false +*/ diff --git a/code/equalshashcode/Equality.java b/code/equalshashcode/Equality.java new file mode 100644 index 00000000..6ab13e5e --- /dev/null +++ b/code/equalshashcode/Equality.java @@ -0,0 +1,77 @@ +// equalshashcode/Equality.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class Equality { + protected int i; + protected String s; + protected double d; + public Equality(int i, String s, double d) { + this.i = i; + this.s = s; + this.d = d; + System.out.println("made 'Equality'"); + } + @Override + public boolean equals(Object rval) { + if(rval == null) + return false; + if(rval == this) + return true; + if(!(rval instanceof Equality)) + return false; + Equality other = (Equality)rval; + if(!Objects.equals(i, other.i)) + return false; + if(!Objects.equals(s, other.s)) + return false; + if(!Objects.equals(d, other.d)) + return false; + return true; + } + public void + test(String descr, String expected, Object rval) { + System.out.format("-- Testing %s --%n" + + "%s instanceof Equality: %s%n" + + "Expected %s, got %s%n", + descr, descr, rval instanceof Equality, + expected, equals(rval)); + } + public static void testAll(EqualityFactory eqf) { + Equality + e = eqf.make(1, "Monty", 3.14), + eq = eqf.make(1, "Monty", 3.14), + neq = eqf.make(99, "Bob", 1.618); + e.test("null", "false", null); + e.test("same object", "true", e); + e.test("different type", + "false", Integer.valueOf(99)); + e.test("same values", "true", eq); + e.test("different values", "false", neq); + } + public static void main(String[] args) { + testAll( (i, s, d) -> new Equality(i, s, d)); + } +} +/* Output: +made 'Equality' +made 'Equality' +made 'Equality' +-- Testing null -- +null instanceof Equality: false +Expected false, got false +-- Testing same object -- +same object instanceof Equality: true +Expected true, got true +-- Testing different type -- +different type instanceof Equality: false +Expected false, got false +-- Testing same values -- +same values instanceof Equality: true +Expected true, got true +-- Testing different values -- +different values instanceof Equality: true +Expected false, got false +*/ diff --git a/code/equalshashcode/EqualityFactory.java b/code/equalshashcode/EqualityFactory.java new file mode 100644 index 00000000..378b56b0 --- /dev/null +++ b/code/equalshashcode/EqualityFactory.java @@ -0,0 +1,9 @@ +// equalshashcode/EqualityFactory.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +interface EqualityFactory { + Equality make(int i, String s, double d); +} diff --git a/code/equalshashcode/Groundhog.java b/code/equalshashcode/Groundhog.java new file mode 100644 index 00000000..55c77563 --- /dev/null +++ b/code/equalshashcode/Groundhog.java @@ -0,0 +1,14 @@ +// equalshashcode/Groundhog.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Looks plausible, but doesn't work as a HashMap key + +public class Groundhog { + protected int number; + public Groundhog(int n) { number = n; } + @Override + public String toString() { + return "Groundhog #" + number; + } +} diff --git a/code/equalshashcode/Groundhog2.java b/code/equalshashcode/Groundhog2.java new file mode 100644 index 00000000..5348d1e5 --- /dev/null +++ b/code/equalshashcode/Groundhog2.java @@ -0,0 +1,19 @@ +// equalshashcode/Groundhog2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A class that's used as a key in a HashMap +// must override hashCode() and equals() +import java.util.*; + +public class Groundhog2 extends Groundhog { + public Groundhog2(int n) { super(n); } + @Override + public int hashCode() { return number; } + @Override + public boolean equals(Object o) { + return o instanceof Groundhog2 && + Objects.equals( + number, ((Groundhog2)o).number); + } +} diff --git a/code/equalshashcode/IndividualTest.java b/code/equalshashcode/IndividualTest.java new file mode 100644 index 00000000..d8f50974 --- /dev/null +++ b/code/equalshashcode/IndividualTest.java @@ -0,0 +1,31 @@ +// equalshashcode/IndividualTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import collections.MapOfList; +import typeinfo.pets.*; +import java.util.*; + +public class IndividualTest { + public static void main(String[] args) { + Set pets = new TreeSet<>(); + for(List lp : + MapOfList.petPeople.values()) + for(Pet p : lp) + pets.add(p); + pets.forEach(System.out::println); + } +} +/* Output: +Cat Elsie May +Cat Pinkola +Cat Shackleton +Cat Stanford +Cymric Molly +Dog Margrett +Mutt Spot +Pug Louie aka Louis Snorkelstein Dupree +Rat Fizzy +Rat Freckly +Rat Fuzzy +*/ diff --git a/code/equalshashcode/MapEntry.java b/code/equalshashcode/MapEntry.java new file mode 100644 index 00000000..c6e28bf4 --- /dev/null +++ b/code/equalshashcode/MapEntry.java @@ -0,0 +1,42 @@ +// equalshashcode/MapEntry.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A simple Map.Entry for sample Map implementations +import java.util.*; + +public class MapEntry implements Map.Entry { + private K key; + private V value; + public MapEntry(K key, V value) { + this.key = key; + this.value = value; + } + @Override + public K getKey() { return key; } + @Override + public V getValue() { return value; } + @Override + public V setValue(V v) { + V result = value; + value = v; + return result; + } + @Override + public int hashCode() { + return Objects.hash(key, value); + } + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object rval) { + return rval instanceof MapEntry && + Objects.equals(key, + ((MapEntry)rval).getKey()) && + Objects.equals(value, + ((MapEntry)rval).getValue()); + } + @Override + public String toString() { + return key + "=" + value; + } +} diff --git a/code/equalshashcode/Prediction.java b/code/equalshashcode/Prediction.java new file mode 100644 index 00000000..c8ff9777 --- /dev/null +++ b/code/equalshashcode/Prediction.java @@ -0,0 +1,15 @@ +// equalshashcode/Prediction.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Predicting the weather +import java.util.*; + +public class Prediction { + private static Random rand = new Random(47); + @Override + public String toString() { + return rand.nextBoolean() ? + "Six more weeks of Winter!" : "Early Spring!"; + } +} diff --git a/code/equalshashcode/SimpleHashMap.java b/code/equalshashcode/SimpleHashMap.java new file mode 100644 index 00000000..f82022a1 --- /dev/null +++ b/code/equalshashcode/SimpleHashMap.java @@ -0,0 +1,90 @@ +// equalshashcode/SimpleHashMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A demonstration hashed Map +import java.util.*; +import onjava.*; + +public +class SimpleHashMap extends AbstractMap { + // Choose a prime number for the hash table + // size, to achieve a uniform distribution: + static final int SIZE = 997; + // You can't have a physical array of generics, + // but you can upcast to one: + @SuppressWarnings("unchecked") + LinkedList>[] buckets = + new LinkedList[SIZE]; + @Override + public V put(K key, V value) { + V oldValue = null; + int index = Math.abs(key.hashCode()) % SIZE; + if(buckets[index] == null) + buckets[index] = new LinkedList<>(); + LinkedList> bucket = buckets[index]; + MapEntry pair = new MapEntry<>(key, value); + boolean found = false; + ListIterator> it = + bucket.listIterator(); + while(it.hasNext()) { + MapEntry iPair = it.next(); + if(iPair.getKey().equals(key)) { + oldValue = iPair.getValue(); + it.set(pair); // Replace old with new + found = true; + break; + } + } + if(!found) + buckets[index].add(pair); + return oldValue; + } + @Override + public V get(Object key) { + int index = Math.abs(key.hashCode()) % SIZE; + if(buckets[index] == null) return null; + for(MapEntry iPair : buckets[index]) + if(iPair.getKey().equals(key)) + return iPair.getValue(); + return null; + } + @Override + public Set> entrySet() { + Set> set= new HashSet<>(); + for(LinkedList> bucket : buckets) { + if(bucket == null) continue; + for(MapEntry mpair : bucket) + set.add(mpair); + } + return set; + } + public static void main(String[] args) { + SimpleHashMap m = + new SimpleHashMap<>(); + m.putAll(Countries.capitals(8)); + m.forEach((k, v) -> + System.out.println(k + "=" + v)); + System.out.println(m.get("BENIN")); + m.entrySet().forEach(System.out::println); + } +} +/* Output: +CAMEROON=Yaounde +ANGOLA=Luanda +BURKINA FASO=Ouagadougou +BURUNDI=Bujumbura +ALGERIA=Algiers +BENIN=Porto-Novo +CAPE VERDE=Praia +BOTSWANA=Gaberone +Porto-Novo +CAMEROON=Yaounde +ANGOLA=Luanda +BURKINA FASO=Ouagadougou +BURUNDI=Bujumbura +ALGERIA=Algiers +BENIN=Porto-Novo +CAPE VERDE=Praia +BOTSWANA=Gaberone +*/ diff --git a/code/equalshashcode/SlowMap.java b/code/equalshashcode/SlowMap.java new file mode 100644 index 00000000..63f17092 --- /dev/null +++ b/code/equalshashcode/SlowMap.java @@ -0,0 +1,64 @@ +// equalshashcode/SlowMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A Map implemented with ArrayLists +import java.util.*; +import onjava.*; + +public class SlowMap extends AbstractMap { + private List keys = new ArrayList<>(); + private List values = new ArrayList<>(); + @Override + public V put(K key, V value) { + V oldValue = get(key); // The old value or null + if(!keys.contains(key)) { + keys.add(key); + values.add(value); + } else + values.set(keys.indexOf(key), value); + return oldValue; + } + @Override + public V get(Object key) { // key: type Object, not K + if(!keys.contains(key)) + return null; + return values.get(keys.indexOf(key)); + } + @Override + public Set> entrySet() { + Set> set= new HashSet<>(); + Iterator ki = keys.iterator(); + Iterator vi = values.iterator(); + while(ki.hasNext()) + set.add(new MapEntry<>(ki.next(), vi.next())); + return set; + } + public static void main(String[] args) { + SlowMap m= new SlowMap<>(); + m.putAll(Countries.capitals(8)); + m.forEach((k, v) -> + System.out.println(k + "=" + v)); + System.out.println(m.get("BENIN")); + m.entrySet().forEach(System.out::println); + } +} +/* Output: +CAMEROON=Yaounde +ANGOLA=Luanda +BURKINA FASO=Ouagadougou +BURUNDI=Bujumbura +ALGERIA=Algiers +BENIN=Porto-Novo +CAPE VERDE=Praia +BOTSWANA=Gaberone +Porto-Novo +CAMEROON=Yaounde +ANGOLA=Luanda +BURKINA FASO=Ouagadougou +BURUNDI=Bujumbura +ALGERIA=Algiers +BENIN=Porto-Novo +CAPE VERDE=Praia +BOTSWANA=Gaberone +*/ diff --git a/code/equalshashcode/SpringDetector.java b/code/equalshashcode/SpringDetector.java new file mode 100644 index 00000000..9b41bd3e --- /dev/null +++ b/code/equalshashcode/SpringDetector.java @@ -0,0 +1,62 @@ +// equalshashcode/SpringDetector.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// What will the weather be? +import java.util.*; +import java.util.stream.*; +import java.util.function.*; +import java.lang.reflect.*; + +public class SpringDetector { + public static + void detectSpring(Class type) { + try { + Constructor ghog = + type.getConstructor(int.class); + Map map = + IntStream.range(0, 10) + .mapToObj(i -> { + try { + return ghog.newInstance(i); + } catch(Exception e) { + throw new RuntimeException(e); + } + }) + .collect(Collectors.toMap( + Function.identity(), + gh -> new Prediction())); + map.forEach((k, v) -> + System.out.println(k + ": " + v)); + Groundhog gh = ghog.newInstance(3); + System.out.println( + "Looking up prediction for " + gh); + if(map.containsKey(gh)) + System.out.println(map.get(gh)); + else + System.out.println("Key not found: " + gh); + } catch(NoSuchMethodException | + IllegalAccessException | + InvocationTargetException | + InstantiationException e) { + throw new RuntimeException(e); + } + } + public static void main(String[] args) { + detectSpring(Groundhog.class); + } +} +/* Output: +Groundhog #3: Six more weeks of Winter! +Groundhog #0: Early Spring! +Groundhog #8: Six more weeks of Winter! +Groundhog #6: Early Spring! +Groundhog #4: Early Spring! +Groundhog #2: Six more weeks of Winter! +Groundhog #1: Early Spring! +Groundhog #9: Early Spring! +Groundhog #5: Six more weeks of Winter! +Groundhog #7: Six more weeks of Winter! +Looking up prediction for Groundhog #3 +Key not found: Groundhog #3 +*/ diff --git a/code/equalshashcode/SpringDetector2.java b/code/equalshashcode/SpringDetector2.java new file mode 100644 index 00000000..1e136e47 --- /dev/null +++ b/code/equalshashcode/SpringDetector2.java @@ -0,0 +1,25 @@ +// equalshashcode/SpringDetector2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A working key + +public class SpringDetector2 { + public static void main(String[] args) { + SpringDetector.detectSpring(Groundhog2.class); + } +} +/* Output: +Groundhog #0: Six more weeks of Winter! +Groundhog #1: Early Spring! +Groundhog #2: Six more weeks of Winter! +Groundhog #3: Early Spring! +Groundhog #4: Early Spring! +Groundhog #5: Six more weeks of Winter! +Groundhog #6: Early Spring! +Groundhog #7: Early Spring! +Groundhog #8: Six more weeks of Winter! +Groundhog #9: Six more weeks of Winter! +Looking up prediction for Groundhog #3 +Early Spring! +*/ diff --git a/code/equalshashcode/StringHashCode.java b/code/equalshashcode/StringHashCode.java new file mode 100644 index 00000000..222fa612 --- /dev/null +++ b/code/equalshashcode/StringHashCode.java @@ -0,0 +1,16 @@ +// equalshashcode/StringHashCode.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class StringHashCode { + public static void main(String[] args) { + String[] hellos = "Hello Hello".split(" "); + System.out.println(hellos[0].hashCode()); + System.out.println(hellos[1].hashCode()); + } +} +/* Output: +69609650 +69609650 +*/ diff --git a/code/equalshashcode/SubtypeEquality.java b/code/equalshashcode/SubtypeEquality.java new file mode 100644 index 00000000..90320c88 --- /dev/null +++ b/code/equalshashcode/SubtypeEquality.java @@ -0,0 +1,60 @@ +// equalshashcode/SubtypeEquality.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +enum Size { SMALL, MEDIUM, LARGE } + +class Animal { + private static int counter = 0; + private final int id = counter++; + private final String name; + private final Size size; + Animal(String name, Size size) { + this.name = name; + this.size = size; + } + @Override + public boolean equals(Object rval) { + return rval instanceof Animal && + // Objects.equals(id, ((Animal)rval).id) && // [1] + Objects.equals(name, ((Animal)rval).name) && + Objects.equals(size, ((Animal)rval).size); + } + @Override + public int hashCode() { + return Objects.hash(name, size); + // return Objects.hash(name, size, id); // [2] + } + @Override + public String toString() { + return String.format("%s[%d]: %s %s %x", + getClass().getSimpleName(), id, + name, size, hashCode()); + } +} + +class Dog extends Animal { + Dog(String name, Size size) { + super(name, size); + } +} + +class Pig extends Animal { + Pig(String name, Size size) { + super(name, size); + } +} + +public class SubtypeEquality { + public static void main(String[] args) { + Set pets = new HashSet<>(); + pets.add(new Dog("Ralph", Size.MEDIUM)); + pets.add(new Pig("Ralph", Size.MEDIUM)); + pets.forEach(System.out::println); + } +} +/* Output: +Dog[0]: Ralph MEDIUM a752aeee +*/ diff --git a/code/equalshashcode/SubtypeEquality2.java b/code/equalshashcode/SubtypeEquality2.java new file mode 100644 index 00000000..c0ac5057 --- /dev/null +++ b/code/equalshashcode/SubtypeEquality2.java @@ -0,0 +1,40 @@ +// equalshashcode/SubtypeEquality2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class Dog2 extends Animal { + Dog2(String name, Size size) { + super(name, size); + } + @Override + public boolean equals(Object rval) { + return rval instanceof Dog2 && + super.equals(rval); + } +} + +class Pig2 extends Animal { + Pig2(String name, Size size) { + super(name, size); + } + @Override + public boolean equals(Object rval) { + return rval instanceof Pig2 && + super.equals(rval); + } +} + +public class SubtypeEquality2 { + public static void main(String[] args) { + Set pets = new HashSet<>(); + pets.add(new Dog2("Ralph", Size.MEDIUM)); + pets.add(new Pig2("Ralph", Size.MEDIUM)); + pets.forEach(System.out::println); + } +} +/* Output: +Dog2[0]: Ralph MEDIUM a752aeee +Pig2[1]: Ralph MEDIUM a752aeee +*/ diff --git a/code/equalshashcode/SuccinctEquality.java b/code/equalshashcode/SuccinctEquality.java new file mode 100644 index 00000000..55a0d8de --- /dev/null +++ b/code/equalshashcode/SuccinctEquality.java @@ -0,0 +1,46 @@ +// equalshashcode/SuccinctEquality.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SuccinctEquality extends Equality { + public SuccinctEquality(int i, String s, double d) { + super(i, s, d); + System.out.println("made 'SuccinctEquality'"); + } + @Override + public boolean equals(Object rval) { + return rval instanceof SuccinctEquality && + Objects.equals(i, ((SuccinctEquality)rval).i) && + Objects.equals(s, ((SuccinctEquality)rval).s) && + Objects.equals(d, ((SuccinctEquality)rval).d); + } + public static void main(String[] args) { + Equality.testAll( (i, s, d) -> + new SuccinctEquality(i, s, d)); + } +} +/* Output: +made 'Equality' +made 'SuccinctEquality' +made 'Equality' +made 'SuccinctEquality' +made 'Equality' +made 'SuccinctEquality' +-- Testing null -- +null instanceof Equality: false +Expected false, got false +-- Testing same object -- +same object instanceof Equality: true +Expected true, got true +-- Testing different type -- +different type instanceof Equality: false +Expected false, got false +-- Testing same values -- +same values instanceof Equality: true +Expected true, got true +-- Testing different values -- +different values instanceof Equality: true +Expected false, got false +*/ diff --git a/code/exceptions/AlwaysFinally.java b/code/exceptions/AlwaysFinally.java new file mode 100644 index 00000000..bb2270f7 --- /dev/null +++ b/code/exceptions/AlwaysFinally.java @@ -0,0 +1,33 @@ +// exceptions/AlwaysFinally.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Finally is always executed + +class FourException extends Exception {} + +public class AlwaysFinally { + public static void main(String[] args) { + System.out.println("Entering first try block"); + try { + System.out.println("Entering second try block"); + try { + throw new FourException(); + } finally { + System.out.println("finally in 2nd try block"); + } + } catch(FourException e) { + System.out.println( + "Caught FourException in 1st try block"); + } finally { + System.out.println("finally in 1st try block"); + } + } +} +/* Output: +Entering first try block +Entering second try block +finally in 2nd try block +Caught FourException in 1st try block +finally in 1st try block +*/ diff --git a/code/exceptions/AutoCloseableDetails.java b/code/exceptions/AutoCloseableDetails.java new file mode 100644 index 00000000..24a22e9d --- /dev/null +++ b/code/exceptions/AutoCloseableDetails.java @@ -0,0 +1,33 @@ +// exceptions/AutoCloseableDetails.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Reporter implements AutoCloseable { + String name = getClass().getSimpleName(); + Reporter() { + System.out.println("Creating " + name); + } + public void close() { + System.out.println("Closing " + name); + } +} + +class First extends Reporter {} +class Second extends Reporter {} + +public class AutoCloseableDetails { + public static void main(String[] args) { + try( + First f = new First(); + Second s = new Second() + ) { + } + } +} +/* Output: +Creating First +Creating Second +Closing Second +Closing First +*/ diff --git a/code/exceptions/BodyException.java b/code/exceptions/BodyException.java new file mode 100644 index 00000000..3e907f8a --- /dev/null +++ b/code/exceptions/BodyException.java @@ -0,0 +1,32 @@ +// exceptions/BodyException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Third extends Reporter {} + +public class BodyException { + public static void main(String[] args) { + try( + First f = new First(); + Second s2 = new Second() + ) { + System.out.println("In body"); + Third t = new Third(); + new SecondExcept(); + System.out.println("End of body"); + } catch(CE e) { + System.out.println("Caught: " + e); + } + } +} +/* Output: +Creating First +Creating Second +In body +Creating Third +Creating SecondExcept +Closing Second +Closing First +Caught: CE +*/ diff --git a/code/exceptions/Cleanup.java b/code/exceptions/Cleanup.java new file mode 100644 index 00000000..3d072304 --- /dev/null +++ b/code/exceptions/Cleanup.java @@ -0,0 +1,30 @@ +// exceptions/Cleanup.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Guaranteeing proper cleanup of a resource + +public class Cleanup { + public static void main(String[] args) { + try { + InputFile in = new InputFile("Cleanup.java"); + try { + String s; + int i = 1; + while((s = in.getLine()) != null) + ; // Perform line-by-line processing here... + } catch(Exception e) { + System.out.println("Caught Exception in main"); + e.printStackTrace(System.out); + } finally { + in.dispose(); + } + } catch(Exception e) { + System.out.println( + "InputFile construction failed"); + } + } +} +/* Output: +dispose() successful +*/ diff --git a/code/exceptions/CleanupIdiom.java b/code/exceptions/CleanupIdiom.java new file mode 100644 index 00000000..e8dd62c4 --- /dev/null +++ b/code/exceptions/CleanupIdiom.java @@ -0,0 +1,72 @@ +// exceptions/CleanupIdiom.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Disposable objects must be followed by a try-finally + +class NeedsCleanup { // Construction can't fail + private static long counter = 1; + private final long id = counter++; + public void dispose() { + System.out.println( + "NeedsCleanup " + id + " disposed"); + } +} + +class ConstructionException extends Exception {} + +class NeedsCleanup2 extends NeedsCleanup { + // Construction can fail: + NeedsCleanup2() throws ConstructionException {} +} + +public class CleanupIdiom { + public static void main(String[] args) { + // [1]: + NeedsCleanup nc1 = new NeedsCleanup(); + try { + // ... + } finally { + nc1.dispose(); + } + + // [2]: + // If construction cannot fail, + // you can group objects: + NeedsCleanup nc2 = new NeedsCleanup(); + NeedsCleanup nc3 = new NeedsCleanup(); + try { + // ... + } finally { + nc3.dispose(); // Reverse order of construction + nc2.dispose(); + } + + // [3]: + // If construction can fail you must guard each one: + try { + NeedsCleanup2 nc4 = new NeedsCleanup2(); + try { + NeedsCleanup2 nc5 = new NeedsCleanup2(); + try { + // ... + } finally { + nc5.dispose(); + } + } catch(ConstructionException e) { // nc5 const. + System.out.println(e); + } finally { + nc4.dispose(); + } + } catch(ConstructionException e) { // nc4 const. + System.out.println(e); + } + } +} +/* Output: +NeedsCleanup 1 disposed +NeedsCleanup 3 disposed +NeedsCleanup 2 disposed +NeedsCleanup 5 disposed +NeedsCleanup 4 disposed +*/ diff --git a/code/exceptions/CloseExceptions.java b/code/exceptions/CloseExceptions.java new file mode 100644 index 00000000..4309a888 --- /dev/null +++ b/code/exceptions/CloseExceptions.java @@ -0,0 +1,48 @@ +// exceptions/CloseExceptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class CloseException extends Exception {} + +class Reporter2 implements AutoCloseable { + String name = getClass().getSimpleName(); + Reporter2() { + System.out.println("Creating " + name); + } + public void close() throws CloseException { + System.out.println("Closing " + name); + } +} + +class Closer extends Reporter2 { + @Override + public void close() throws CloseException { + super.close(); + throw new CloseException(); + } +} + +public class CloseExceptions { + public static void main(String[] args) { + try( + First f = new First(); + Closer c = new Closer(); + Second s = new Second() + ) { + System.out.println("In body"); + } catch(CloseException e) { + System.out.println("Caught: " + e); + } + } +} +/* Output: +Creating First +Creating Closer +Creating Second +In body +Closing Second +Closing Closer +Closing First +Caught: CloseException +*/ diff --git a/code/exceptions/ConstructorException.java b/code/exceptions/ConstructorException.java new file mode 100644 index 00000000..54eaaba3 --- /dev/null +++ b/code/exceptions/ConstructorException.java @@ -0,0 +1,33 @@ +// exceptions/ConstructorException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class CE extends Exception {} + +class SecondExcept extends Reporter { + SecondExcept() throws CE { + super(); + throw new CE(); + } +} + +public class ConstructorException { + public static void main(String[] args) { + try( + First f = new First(); + SecondExcept s = new SecondExcept(); + Second s2 = new Second() + ) { + System.out.println("In body"); + } catch(CE e) { + System.out.println("Caught: " + e); + } + } +} +/* Output: +Creating First +Creating SecondExcept +Closing First +Caught: CE +*/ diff --git a/code/exceptions/DynamicFields.java b/code/exceptions/DynamicFields.java new file mode 100644 index 00000000..da3b9617 --- /dev/null +++ b/code/exceptions/DynamicFields.java @@ -0,0 +1,130 @@ +// exceptions/DynamicFields.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A Class that dynamically adds fields to itself to +// demonstrate exception chaining + +class DynamicFieldsException extends Exception {} + +public class DynamicFields { + private Object[][] fields; + public DynamicFields(int initialSize) { + fields = new Object[initialSize][2]; + for(int i = 0; i < initialSize; i++) + fields[i] = new Object[] { null, null }; + } + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for(Object[] obj : fields) { + result.append(obj[0]); + result.append(": "); + result.append(obj[1]); + result.append("\n"); + } + return result.toString(); + } + private int hasField(String id) { + for(int i = 0; i < fields.length; i++) + if(id.equals(fields[i][0])) + return i; + return -1; + } + private int getFieldNumber(String id) + throws NoSuchFieldException { + int fieldNum = hasField(id); + if(fieldNum == -1) + throw new NoSuchFieldException(); + return fieldNum; + } + private int makeField(String id) { + for(int i = 0; i < fields.length; i++) + if(fields[i][0] == null) { + fields[i][0] = id; + return i; + } + // No empty fields. Add one: + Object[][] tmp = new Object[fields.length + 1][2]; + for(int i = 0; i < fields.length; i++) + tmp[i] = fields[i]; + for(int i = fields.length; i < tmp.length; i++) + tmp[i] = new Object[] { null, null }; + fields = tmp; + // Recursive call with expanded fields: + return makeField(id); + } + public Object + getField(String id) throws NoSuchFieldException { + return fields[getFieldNumber(id)][1]; + } + public Object setField(String id, Object value) + throws DynamicFieldsException { + if(value == null) { + // Most exceptions don't have a "cause" + // constructor. In these cases you must use + // initCause(), available in all + // Throwable subclasses. + DynamicFieldsException dfe = + new DynamicFieldsException(); + dfe.initCause(new NullPointerException()); + throw dfe; + } + int fieldNumber = hasField(id); + if(fieldNumber == -1) + fieldNumber = makeField(id); + Object result = null; + try { + result = getField(id); // Get old value + } catch(NoSuchFieldException e) { + // Use constructor that takes "cause": + throw new RuntimeException(e); + } + fields[fieldNumber][1] = value; + return result; + } + public static void main(String[] args) { + DynamicFields df = new DynamicFields(3); + System.out.println(df); + try { + df.setField("d", "A value for d"); + df.setField("number", 47); + df.setField("number2", 48); + System.out.println(df); + df.setField("d", "A new value for d"); + df.setField("number3", 11); + System.out.println("df: " + df); + System.out.println("df.getField(\"d\") : " + + df.getField("d")); + Object field = + df.setField("d", null); // Exception + } catch(NoSuchFieldException | + DynamicFieldsException e) { + e.printStackTrace(System.out); + } + } +} +/* Output: +null: null +null: null +null: null + +d: A value for d +number: 47 +number2: 48 + +df: d: A new value for d +number: 47 +number2: 48 +number3: 11 + +df.getField("d") : A new value for d +DynamicFieldsException + at +DynamicFields.setField(DynamicFields.java:65) + at DynamicFields.main(DynamicFields.java:97) +Caused by: java.lang.NullPointerException + at +DynamicFields.setField(DynamicFields.java:67) + ... 1 more +*/ diff --git a/code/exceptions/ExceptionMethods.java b/code/exceptions/ExceptionMethods.java new file mode 100644 index 00000000..bd6e8259 --- /dev/null +++ b/code/exceptions/ExceptionMethods.java @@ -0,0 +1,32 @@ +// exceptions/ExceptionMethods.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrating the Exception Methods + +public class ExceptionMethods { + public static void main(String[] args) { + try { + throw new Exception("My Exception"); + } catch(Exception e) { + System.out.println("Caught Exception"); + System.out.println( + "getMessage():" + e.getMessage()); + System.out.println("getLocalizedMessage():" + + e.getLocalizedMessage()); + System.out.println("toString():" + e); + System.out.println("printStackTrace():"); + e.printStackTrace(System.out); + } + } +} +/* Output: +Caught Exception +getMessage():My Exception +getLocalizedMessage():My Exception +toString():java.lang.Exception: My Exception +printStackTrace(): +java.lang.Exception: My Exception + at +ExceptionMethods.main(ExceptionMethods.java:7) +*/ diff --git a/code/exceptions/ExceptionSilencer.java b/code/exceptions/ExceptionSilencer.java new file mode 100644 index 00000000..e418e9de --- /dev/null +++ b/code/exceptions/ExceptionSilencer.java @@ -0,0 +1,16 @@ +// exceptions/ExceptionSilencer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ExceptionSilencer { + public static void main(String[] args) { + try { + throw new RuntimeException(); + } finally { + // Using 'return' inside the finally block + // will silence any thrown exception. + return; + } + } +} diff --git a/code/exceptions/ExtraFeatures.java b/code/exceptions/ExtraFeatures.java new file mode 100644 index 00000000..8aa922af --- /dev/null +++ b/code/exceptions/ExtraFeatures.java @@ -0,0 +1,72 @@ +// exceptions/ExtraFeatures.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Further embellishment of exception classes + +class MyException2 extends Exception { + private int x; + MyException2() {} + MyException2(String msg) { super(msg); } + MyException2(String msg, int x) { + super(msg); + this.x = x; + } + public int val() { return x; } + @Override + public String getMessage() { + return "Detail Message: "+ x + + " "+ super.getMessage(); + } +} + +public class ExtraFeatures { + public static void f() throws MyException2 { + System.out.println( + "Throwing MyException2 from f()"); + throw new MyException2(); + } + public static void g() throws MyException2 { + System.out.println( + "Throwing MyException2 from g()"); + throw new MyException2("Originated in g()"); + } + public static void h() throws MyException2 { + System.out.println( + "Throwing MyException2 from h()"); + throw new MyException2("Originated in h()", 47); + } + public static void main(String[] args) { + try { + f(); + } catch(MyException2 e) { + e.printStackTrace(System.out); + } + try { + g(); + } catch(MyException2 e) { + e.printStackTrace(System.out); + } + try { + h(); + } catch(MyException2 e) { + e.printStackTrace(System.out); + System.out.println("e.val() = " + e.val()); + } + } +} +/* Output: +Throwing MyException2 from f() +MyException2: Detail Message: 0 null + at ExtraFeatures.f(ExtraFeatures.java:24) + at ExtraFeatures.main(ExtraFeatures.java:38) +Throwing MyException2 from g() +MyException2: Detail Message: 0 Originated in g() + at ExtraFeatures.g(ExtraFeatures.java:29) + at ExtraFeatures.main(ExtraFeatures.java:43) +Throwing MyException2 from h() +MyException2: Detail Message: 47 Originated in h() + at ExtraFeatures.h(ExtraFeatures.java:34) + at ExtraFeatures.main(ExtraFeatures.java:48) +e.val() = 47 +*/ diff --git a/code/exceptions/FinallyWorks.java b/code/exceptions/FinallyWorks.java new file mode 100644 index 00000000..fc4fec0a --- /dev/null +++ b/code/exceptions/FinallyWorks.java @@ -0,0 +1,32 @@ +// exceptions/FinallyWorks.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The finally clause is always executed + +class ThreeException extends Exception {} + +public class FinallyWorks { + static int count = 0; + public static void main(String[] args) { + while(true) { + try { + // Post-increment is zero first time: + if(count++ == 0) + throw new ThreeException(); + System.out.println("No exception"); + } catch(ThreeException e) { + System.out.println("ThreeException"); + } finally { + System.out.println("In finally clause"); + if(count == 2) break; // out of "while" + } + } + } +} +/* Output: +ThreeException +In finally clause +No exception +In finally clause +*/ diff --git a/code/exceptions/FullConstructors.java b/code/exceptions/FullConstructors.java new file mode 100644 index 00000000..f5b4c9ff --- /dev/null +++ b/code/exceptions/FullConstructors.java @@ -0,0 +1,44 @@ +// exceptions/FullConstructors.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class MyException extends Exception { + MyException() {} + MyException(String msg) { super(msg); } +} + +public class FullConstructors { + public static void f() throws MyException { + System.out.println("Throwing MyException from f()"); + throw new MyException(); + } + public static void g() throws MyException { + System.out.println("Throwing MyException from g()"); + throw new MyException("Originated in g()"); + } + public static void main(String[] args) { + try { + f(); + } catch(MyException e) { + e.printStackTrace(System.out); + } + try { + g(); + } catch(MyException e) { + e.printStackTrace(System.out); + } + } +} +/* Output: +Throwing MyException from f() +MyException + at FullConstructors.f(FullConstructors.java:11) + at +FullConstructors.main(FullConstructors.java:19) +Throwing MyException from g() +MyException: Originated in g() + at FullConstructors.g(FullConstructors.java:15) + at +FullConstructors.main(FullConstructors.java:24) +*/ diff --git a/code/exceptions/Human.java b/code/exceptions/Human.java new file mode 100644 index 00000000..7ee7dcaa --- /dev/null +++ b/code/exceptions/Human.java @@ -0,0 +1,31 @@ +// exceptions/Human.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Catching exception hierarchies + +class Annoyance extends Exception {} +class Sneeze extends Annoyance {} + +public class Human { + public static void main(String[] args) { + // Catch the exact type: + try { + throw new Sneeze(); + } catch(Sneeze s) { + System.out.println("Caught Sneeze"); + } catch(Annoyance a) { + System.out.println("Caught Annoyance"); + } + // Catch the base type: + try { + throw new Sneeze(); + } catch(Annoyance a) { + System.out.println("Caught Annoyance"); + } + } +} +/* Output: +Caught Sneeze +Caught Annoyance +*/ diff --git a/code/exceptions/InheritingExceptions.java b/code/exceptions/InheritingExceptions.java new file mode 100644 index 00000000..abb80c3b --- /dev/null +++ b/code/exceptions/InheritingExceptions.java @@ -0,0 +1,28 @@ +// exceptions/InheritingExceptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating your own exceptions + +class SimpleException extends Exception {} + +public class InheritingExceptions { + public void f() throws SimpleException { + System.out.println( + "Throw SimpleException from f()"); + throw new SimpleException(); + } + public static void main(String[] args) { + InheritingExceptions sed = + new InheritingExceptions(); + try { + sed.f(); + } catch(SimpleException e) { + System.out.println("Caught it!"); + } + } +} +/* Output: +Throw SimpleException from f() +Caught it! +*/ diff --git a/code/exceptions/InputFile.java b/code/exceptions/InputFile.java new file mode 100644 index 00000000..5c269851 --- /dev/null +++ b/code/exceptions/InputFile.java @@ -0,0 +1,47 @@ +// exceptions/InputFile.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Paying attention to exceptions in constructors +import java.io.*; + +public class InputFile { + private BufferedReader in; + public InputFile(String fname) throws Exception { + try { + in = new BufferedReader(new FileReader(fname)); + // Other code that might throw exceptions + } catch(FileNotFoundException e) { + System.out.println("Could not open " + fname); + // Wasn't open, so don't close it + throw e; + } catch(Exception e) { + // All other exceptions must close it + try { + in.close(); + } catch(IOException e2) { + System.out.println("in.close() unsuccessful"); + } + throw e; // Rethrow + } finally { + // Don't close it here!!! + } + } + public String getLine() { + String s; + try { + s = in.readLine(); + } catch(IOException e) { + throw new RuntimeException("readLine() failed"); + } + return s; + } + public void dispose() { + try { + in.close(); + System.out.println("dispose() successful"); + } catch(IOException e2) { + throw new RuntimeException("in.close() failed"); + } + } +} diff --git a/code/exceptions/InputFile2.java b/code/exceptions/InputFile2.java new file mode 100644 index 00000000..74a68c3f --- /dev/null +++ b/code/exceptions/InputFile2.java @@ -0,0 +1,28 @@ +// exceptions/InputFile2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.nio.file.*; +import java.util.stream.*; + +public class InputFile2 { + private String fname; + public InputFile2(String fname) { + this.fname = fname; + } + public + Stream getLines() throws IOException { + return Files.lines(Paths.get(fname)); + } + public static void + main(String[] args) throws IOException { + new InputFile2("InputFile2.java").getLines() + .skip(15) + .limit(1) + .forEach(System.out::println); + } +} +/* Output: + main(String[] args) throws IOException { +*/ diff --git a/code/exceptions/LoggingExceptions.java b/code/exceptions/LoggingExceptions.java new file mode 100644 index 00000000..0120ee17 --- /dev/null +++ b/code/exceptions/LoggingExceptions.java @@ -0,0 +1,48 @@ +// exceptions/LoggingExceptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An exception that reports through a Logger +// {ErrorOutputExpected} +import java.util.logging.*; +import java.io.*; + +class LoggingException extends Exception { + private static Logger logger = + Logger.getLogger("LoggingException"); + LoggingException() { + StringWriter trace = new StringWriter(); + printStackTrace(new PrintWriter(trace)); + logger.severe(trace.toString()); + } +} + +public class LoggingExceptions { + public static void main(String[] args) { + try { + throw new LoggingException(); + } catch(LoggingException e) { + System.err.println("Caught " + e); + } + try { + throw new LoggingException(); + } catch(LoggingException e) { + System.err.println("Caught " + e); + } + } +} +/* Output: +___[ Error Output ]___ +May 09, 2017 6:07:17 AM LoggingException +SEVERE: LoggingException + at +LoggingExceptions.main(LoggingExceptions.java:20) + +Caught LoggingException +May 09, 2017 6:07:17 AM LoggingException +SEVERE: LoggingException + at +LoggingExceptions.main(LoggingExceptions.java:25) + +Caught LoggingException +*/ diff --git a/code/exceptions/LoggingExceptions2.java b/code/exceptions/LoggingExceptions2.java new file mode 100644 index 00000000..21a92137 --- /dev/null +++ b/code/exceptions/LoggingExceptions2.java @@ -0,0 +1,32 @@ +// exceptions/LoggingExceptions2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Logging caught exceptions +// {ErrorOutputExpected} +import java.util.logging.*; +import java.io.*; + +public class LoggingExceptions2 { + private static Logger logger = + Logger.getLogger("LoggingExceptions2"); + static void logException(Exception e) { + StringWriter trace = new StringWriter(); + e.printStackTrace(new PrintWriter(trace)); + logger.severe(trace.toString()); + } + public static void main(String[] args) { + try { + throw new NullPointerException(); + } catch(NullPointerException e) { + logException(e); + } + } +} +/* Output: +___[ Error Output ]___ +May 09, 2017 6:07:17 AM LoggingExceptions2 logException +SEVERE: java.lang.NullPointerException + at +LoggingExceptions2.main(LoggingExceptions2.java:17) +*/ diff --git a/code/exceptions/LostMessage.java b/code/exceptions/LostMessage.java new file mode 100644 index 00000000..1446d903 --- /dev/null +++ b/code/exceptions/LostMessage.java @@ -0,0 +1,44 @@ +// exceptions/LostMessage.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// How an exception can be lost + +class VeryImportantException extends Exception { + @Override + public String toString() { + return "A very important exception!"; + } +} + +class HoHumException extends Exception { + @Override + public String toString() { + return "A trivial exception"; + } +} + +public class LostMessage { + void f() throws VeryImportantException { + throw new VeryImportantException(); + } + void dispose() throws HoHumException { + throw new HoHumException(); + } + public static void main(String[] args) { + try { + LostMessage lm = new LostMessage(); + try { + lm.f(); + } finally { + lm.dispose(); + } + } catch(VeryImportantException | + HoHumException e) { + System.out.println(e); + } + } +} +/* Output: +A trivial exception +*/ diff --git a/code/exceptions/MainException.java b/code/exceptions/MainException.java new file mode 100644 index 00000000..7a7e2638 --- /dev/null +++ b/code/exceptions/MainException.java @@ -0,0 +1,17 @@ +// exceptions/MainException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.nio.file.*; + +public class MainException { + // Pass exceptions to the console: + public static void + main(String[] args) throws Exception { + // Open the file: + List lines = Files.readAllLines( + Paths.get("MainException.java")); + // Use the file ... + } +} diff --git a/code/exceptions/MessyExceptions.java b/code/exceptions/MessyExceptions.java new file mode 100644 index 00000000..e8f7fc9d --- /dev/null +++ b/code/exceptions/MessyExceptions.java @@ -0,0 +1,27 @@ +// exceptions/MessyExceptions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; + +public class MessyExceptions { + public static void main(String[] args) { + InputStream in = null; + try { + in = new FileInputStream( + new File("MessyExceptions.java")); + int contents = in.read(); + // Process contents + } catch(IOException e) { + // Handle the error + } finally { + if(in != null) { + try { + in.close(); + } catch(IOException e) { + // Handle the close() error + } + } + } + } +} diff --git a/code/exceptions/MultiCatch.java b/code/exceptions/MultiCatch.java new file mode 100644 index 00000000..f97bde13 --- /dev/null +++ b/code/exceptions/MultiCatch.java @@ -0,0 +1,16 @@ +// exceptions/MultiCatch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class MultiCatch { + void x() throws Except1, Except2, Except3, Except4 {} + void process() {} + void f() { + try { + x(); + } catch(Except1 | Except2 | Except3 | Except4 e) { + process(); + } + } +} diff --git a/code/exceptions/MultiCatch2.java b/code/exceptions/MultiCatch2.java new file mode 100644 index 00000000..4629e93f --- /dev/null +++ b/code/exceptions/MultiCatch2.java @@ -0,0 +1,19 @@ +// exceptions/MultiCatch2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class MultiCatch2 { + void x() throws Except1, Except2, Except3, Except4 {} + void process1() {} + void process2() {} + void f() { + try { + x(); + } catch(Except1 | Except2 e) { + process1(); + } catch(Except3 | Except4 e) { + process2(); + } + } +} diff --git a/code/exceptions/MultipleReturns.java b/code/exceptions/MultipleReturns.java new file mode 100644 index 00000000..3f667b33 --- /dev/null +++ b/code/exceptions/MultipleReturns.java @@ -0,0 +1,47 @@ +// exceptions/MultipleReturns.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class MultipleReturns { + public static void f(int i) { + System.out.println( + "Initialization that requires cleanup"); + try { + System.out.println("Point 1"); + if(i == 1) return; + System.out.println("Point 2"); + if(i == 2) return; + System.out.println("Point 3"); + if(i == 3) return; + System.out.println("End"); + return; + } finally { + System.out.println("Performing cleanup"); + } + } + public static void main(String[] args) { + for(int i = 1; i <= 4; i++) + f(i); + } +} +/* Output: +Initialization that requires cleanup +Point 1 +Performing cleanup +Initialization that requires cleanup +Point 1 +Point 2 +Performing cleanup +Initialization that requires cleanup +Point 1 +Point 2 +Point 3 +Performing cleanup +Initialization that requires cleanup +Point 1 +Point 2 +Point 3 +End +Performing cleanup +*/ diff --git a/code/exceptions/NeverCaught.java b/code/exceptions/NeverCaught.java new file mode 100644 index 00000000..c8bb0a2f --- /dev/null +++ b/code/exceptions/NeverCaught.java @@ -0,0 +1,26 @@ +// exceptions/NeverCaught.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Ignoring RuntimeExceptions +// {ThrowsException} + +public class NeverCaught { + static void f() { + throw new RuntimeException("From f()"); + } + static void g() { + f(); + } + public static void main(String[] args) { + g(); + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "main" java.lang.RuntimeException: +From f() + at NeverCaught.f(NeverCaught.java:7) + at NeverCaught.g(NeverCaught.java:10) + at NeverCaught.main(NeverCaught.java:13) +*/ diff --git a/code/exceptions/OnOffException1.java b/code/exceptions/OnOffException1.java new file mode 100644 index 00000000..3333d815 --- /dev/null +++ b/code/exceptions/OnOffException1.java @@ -0,0 +1,5 @@ +// exceptions/OnOffException1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class OnOffException1 extends Exception {} diff --git a/code/exceptions/OnOffException2.java b/code/exceptions/OnOffException2.java new file mode 100644 index 00000000..0bb5e164 --- /dev/null +++ b/code/exceptions/OnOffException2.java @@ -0,0 +1,5 @@ +// exceptions/OnOffException2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class OnOffException2 extends Exception {} diff --git a/code/exceptions/OnOffSwitch.java b/code/exceptions/OnOffSwitch.java new file mode 100644 index 00000000..fe05fa35 --- /dev/null +++ b/code/exceptions/OnOffSwitch.java @@ -0,0 +1,29 @@ +// exceptions/OnOffSwitch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Why use finally? + +public class OnOffSwitch { + private static Switch sw = new Switch(); + public static void f() + throws OnOffException1, OnOffException2 {} + public static void main(String[] args) { + try { + sw.on(); + // Code that can throw exceptions... + f(); + sw.off(); + } catch(OnOffException1 e) { + System.out.println("OnOffException1"); + sw.off(); + } catch(OnOffException2 e) { + System.out.println("OnOffException2"); + sw.off(); + } + } +} +/* Output: +on +off +*/ diff --git a/code/exceptions/PreciseRethrow.java b/code/exceptions/PreciseRethrow.java new file mode 100644 index 00000000..f8849a3d --- /dev/null +++ b/code/exceptions/PreciseRethrow.java @@ -0,0 +1,17 @@ +// exceptions/PreciseRethrow.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class BaseException extends Exception {} +class DerivedException extends BaseException {} + +public class PreciseRethrow { + void catcher() throws DerivedException { + try { + throw new DerivedException(); + } catch(BaseException e) { + throw e; + } + } +} diff --git a/code/exceptions/RethrowNew.java b/code/exceptions/RethrowNew.java new file mode 100644 index 00000000..daa4ad41 --- /dev/null +++ b/code/exceptions/RethrowNew.java @@ -0,0 +1,47 @@ +// exceptions/RethrowNew.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Rethrow a different object from the one you caught + +class OneException extends Exception { + OneException(String s) { super(s); } +} + +class TwoException extends Exception { + TwoException(String s) { super(s); } +} + +public class RethrowNew { + public static void f() throws OneException { + System.out.println( + "originating the exception in f()"); + throw new OneException("thrown from f()"); + } + public static void main(String[] args) { + try { + try { + f(); + } catch(OneException e) { + System.out.println( + "Caught in inner try, e.printStackTrace()"); + e.printStackTrace(System.out); + throw new TwoException("from inner try"); + } + } catch(TwoException e) { + System.out.println( + "Caught in outer try, e.printStackTrace()"); + e.printStackTrace(System.out); + } + } +} +/* Output: +originating the exception in f() +Caught in inner try, e.printStackTrace() +OneException: thrown from f() + at RethrowNew.f(RethrowNew.java:16) + at RethrowNew.main(RethrowNew.java:21) +Caught in outer try, e.printStackTrace() +TwoException: from inner try + at RethrowNew.main(RethrowNew.java:26) +*/ diff --git a/code/exceptions/Rethrowing.java b/code/exceptions/Rethrowing.java new file mode 100644 index 00000000..5bf1a635 --- /dev/null +++ b/code/exceptions/Rethrowing.java @@ -0,0 +1,70 @@ +// exceptions/Rethrowing.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrating fillInStackTrace() + +public class Rethrowing { + public static void f() throws Exception { + System.out.println( + "originating the exception in f()"); + throw new Exception("thrown from f()"); + } + public static void g() throws Exception { + try { + f(); + } catch(Exception e) { + System.out.println( + "Inside g(), e.printStackTrace()"); + e.printStackTrace(System.out); + throw e; + } + } + public static void h() throws Exception { + try { + f(); + } catch(Exception e) { + System.out.println( + "Inside h(), e.printStackTrace()"); + e.printStackTrace(System.out); + throw (Exception)e.fillInStackTrace(); + } + } + public static void main(String[] args) { + try { + g(); + } catch(Exception e) { + System.out.println("main: printStackTrace()"); + e.printStackTrace(System.out); + } + try { + h(); + } catch(Exception e) { + System.out.println("main: printStackTrace()"); + e.printStackTrace(System.out); + } + } +} +/* Output: +originating the exception in f() +Inside g(), e.printStackTrace() +java.lang.Exception: thrown from f() + at Rethrowing.f(Rethrowing.java:8) + at Rethrowing.g(Rethrowing.java:12) + at Rethrowing.main(Rethrowing.java:32) +main: printStackTrace() +java.lang.Exception: thrown from f() + at Rethrowing.f(Rethrowing.java:8) + at Rethrowing.g(Rethrowing.java:12) + at Rethrowing.main(Rethrowing.java:32) +originating the exception in f() +Inside h(), e.printStackTrace() +java.lang.Exception: thrown from f() + at Rethrowing.f(Rethrowing.java:8) + at Rethrowing.h(Rethrowing.java:22) + at Rethrowing.main(Rethrowing.java:38) +main: printStackTrace() +java.lang.Exception: thrown from f() + at Rethrowing.h(Rethrowing.java:27) + at Rethrowing.main(Rethrowing.java:38) +*/ diff --git a/code/exceptions/SameHandler.java b/code/exceptions/SameHandler.java new file mode 100644 index 00000000..8c680567 --- /dev/null +++ b/code/exceptions/SameHandler.java @@ -0,0 +1,31 @@ +// exceptions/SameHandler.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class EBase1 extends Exception {} +class Except1 extends EBase1 {} +class EBase2 extends Exception {} +class Except2 extends EBase2 {} +class EBase3 extends Exception {} +class Except3 extends EBase3 {} +class EBase4 extends Exception {} +class Except4 extends EBase4 {} + +public class SameHandler { + void x() throws Except1, Except2, Except3, Except4 {} + void process() {} + void f() { + try { + x(); + } catch(Except1 e) { + process(); + } catch(Except2 e) { + process(); + } catch(Except3 e) { + process(); + } catch(Except4 e) { + process(); + } + } +} diff --git a/code/exceptions/StormyInning.java b/code/exceptions/StormyInning.java new file mode 100644 index 00000000..644c10ba --- /dev/null +++ b/code/exceptions/StormyInning.java @@ -0,0 +1,83 @@ +// exceptions/StormyInning.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Overridden methods can throw only the exceptions +// specified in their base-class versions, or exceptions +// derived from the base-class exceptions + +class BaseballException extends Exception {} +class Foul extends BaseballException {} +class Strike extends BaseballException {} + +abstract class Inning { + Inning() throws BaseballException {} + public void event() throws BaseballException { + // Doesn't actually have to throw anything + } + public abstract void atBat() throws Strike, Foul; + public void walk() {} // Throws no checked exceptions +} + +class StormException extends Exception {} +class RainedOut extends StormException {} +class PopFoul extends Foul {} + +interface Storm { + void event() throws RainedOut; + void rainHard() throws RainedOut; +} + +public +class StormyInning extends Inning implements Storm { + // OK to add new exceptions for constructors, but you + // must deal with the base constructor exceptions: + public StormyInning() + throws RainedOut, BaseballException {} + public StormyInning(String s) + throws BaseballException {} + // Regular methods must conform to base class: + //- void walk() throws PopFoul {} //Compile error + // Interface CANNOT add exceptions to existing + // methods from the base class: + //- public void event() throws RainedOut {} + // If the method doesn't already exist in the + // base class, the exception is OK: + @Override + public void rainHard() throws RainedOut {} + // You can choose to not throw any exceptions, + // even if the base version does: + @Override + public void event() {} + // Overridden methods can throw inherited exceptions: + @Override + public void atBat() throws PopFoul {} + public static void main(String[] args) { + try { + StormyInning si = new StormyInning(); + si.atBat(); + } catch(PopFoul e) { + System.out.println("Pop foul"); + } catch(RainedOut e) { + System.out.println("Rained out"); + } catch(BaseballException e) { + System.out.println("Generic baseball exception"); + } + // Strike not thrown in derived version. + try { + // What happens if you upcast? + Inning i = new StormyInning(); + i.atBat(); + // You must catch the exceptions from the + // base-class version of the method: + } catch(Strike e) { + System.out.println("Strike"); + } catch(Foul e) { + System.out.println("Foul"); + } catch(RainedOut e) { + System.out.println("Rained out"); + } catch(BaseballException e) { + System.out.println("Generic baseball exception"); + } + } +} diff --git a/code/exceptions/StreamsAreAutoCloseable.java b/code/exceptions/StreamsAreAutoCloseable.java new file mode 100644 index 00000000..c55bf417 --- /dev/null +++ b/code/exceptions/StreamsAreAutoCloseable.java @@ -0,0 +1,24 @@ +// exceptions/StreamsAreAutoCloseable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.nio.file.*; +import java.util.stream.*; + +public class StreamsAreAutoCloseable { + public static void + main(String[] args) throws IOException{ + try( + Stream in = Files.lines( + Paths.get("StreamsAreAutoCloseable.java")); + PrintWriter outfile = new PrintWriter( + "Results.txt"); // [1] + ) { + in.skip(5) + .limit(1) + .map(String::toLowerCase) + .forEachOrdered(outfile::println); + } // [2] + } +} diff --git a/code/exceptions/Switch.java b/code/exceptions/Switch.java new file mode 100644 index 00000000..7d491d00 --- /dev/null +++ b/code/exceptions/Switch.java @@ -0,0 +1,21 @@ +// exceptions/Switch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Switch { + private boolean state = false; + public boolean read() { return state; } + public void on() { + state = true; + System.out.println(this); + } + public void off() { + state = false; + System.out.println(this); + } + @Override + public String toString() { + return state ? "on" : "off"; + } +} diff --git a/code/exceptions/TryAnything.java b/code/exceptions/TryAnything.java new file mode 100644 index 00000000..9eeee07b --- /dev/null +++ b/code/exceptions/TryAnything.java @@ -0,0 +1,16 @@ +// exceptions/TryAnything.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} + +class Anything {} + +public class TryAnything { + public static void main(String[] args) { + try( + Anything a = new Anything() + ) { + } + } +} diff --git a/code/exceptions/TryWithResources.java b/code/exceptions/TryWithResources.java new file mode 100644 index 00000000..cdc83a5c --- /dev/null +++ b/code/exceptions/TryWithResources.java @@ -0,0 +1,19 @@ +// exceptions/TryWithResources.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; + +public class TryWithResources { + public static void main(String[] args) { + try( + InputStream in = new FileInputStream( + new File("TryWithResources.java")) + ) { + int contents = in.read(); + // Process contents + } catch(IOException e) { + // Handle the error + } + } +} diff --git a/code/exceptions/TurnOffChecking.java b/code/exceptions/TurnOffChecking.java new file mode 100644 index 00000000..898431b6 --- /dev/null +++ b/code/exceptions/TurnOffChecking.java @@ -0,0 +1,64 @@ +// exceptions/TurnOffChecking.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// "Turning off" Checked exceptions +import java.io.*; + +class WrapCheckedException { + void throwRuntimeException(int type) { + try { + switch(type) { + case 0: throw new FileNotFoundException(); + case 1: throw new IOException(); + case 2: throw new + RuntimeException("Where am I?"); + default: return; + } + } catch(IOException | RuntimeException e) { + // Adapt to unchecked: + throw new RuntimeException(e); + } + } +} + +class SomeOtherException extends Exception {} + +public class TurnOffChecking { + public static void main(String[] args) { + WrapCheckedException wce = + new WrapCheckedException(); + // You can call throwRuntimeException() without + // a try block, and let RuntimeExceptions + // leave the method: + wce.throwRuntimeException(3); + // Or you can choose to catch exceptions: + for(int i = 0; i < 4; i++) + try { + if(i < 3) + wce.throwRuntimeException(i); + else + throw new SomeOtherException(); + } catch(SomeOtherException e) { + System.out.println( + "SomeOtherException: " + e); + } catch(RuntimeException re) { + try { + throw re.getCause(); + } catch(FileNotFoundException e) { + System.out.println( + "FileNotFoundException: " + e); + } catch(IOException e) { + System.out.println("IOException: " + e); + } catch(Throwable e) { + System.out.println("Throwable: " + e); + } + } + } +} +/* Output: +FileNotFoundException: java.io.FileNotFoundException +IOException: java.io.IOException +Throwable: java.lang.RuntimeException: Where am I? +SomeOtherException: SomeOtherException +*/ diff --git a/code/exceptions/WhoCalled.java b/code/exceptions/WhoCalled.java new file mode 100644 index 00000000..4c4e0104 --- /dev/null +++ b/code/exceptions/WhoCalled.java @@ -0,0 +1,39 @@ +// exceptions/WhoCalled.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Programmatic access to stack trace information + +public class WhoCalled { + static void f() { + // Generate an exception to fill in the stack trace + try { + throw new Exception(); + } catch(Exception e) { + for(StackTraceElement ste : e.getStackTrace()) + System.out.println(ste.getMethodName()); + } + } + static void g() { f(); } + static void h() { g(); } + public static void main(String[] args) { + f(); + System.out.println("*******"); + g(); + System.out.println("*******"); + h(); + } +} +/* Output: +f +main +******* +f +g +main +******* +f +g +h +main +*/ diff --git a/code/exceptions/WithFinally.java b/code/exceptions/WithFinally.java new file mode 100644 index 00000000..9d3efc3a --- /dev/null +++ b/code/exceptions/WithFinally.java @@ -0,0 +1,26 @@ +// exceptions/WithFinally.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Finally Guarantees cleanup + +public class WithFinally { + static Switch sw = new Switch(); + public static void main(String[] args) { + try { + sw.on(); + // Code that can throw exceptions... + OnOffSwitch.f(); + } catch(OnOffException1 e) { + System.out.println("OnOffException1"); + } catch(OnOffException2 e) { + System.out.println("OnOffException2"); + } finally { + sw.off(); + } + } +} +/* Output: +on +off +*/ diff --git a/code/files/AddAndSubtractPaths.java b/code/files/AddAndSubtractPaths.java new file mode 100644 index 00000000..f3984d19 --- /dev/null +++ b/code/files/AddAndSubtractPaths.java @@ -0,0 +1,87 @@ +// files/AddAndSubtractPaths.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.file.*; +import java.io.IOException; + +public class AddAndSubtractPaths { + static Path base = Paths.get("..", "..", "..") + .toAbsolutePath() + .normalize(); + static void show(int id, Path result) { + if(result.isAbsolute()) + System.out.println("(" + id + ")r " + + base.relativize(result)); + else + System.out.println("(" + id + ") " + result); + try { + System.out.println("RealPath: " + + result.toRealPath()); + } catch(IOException e) { + System.out.println(e); + } + } + public static void main(String[] args) { + System.out.println(System.getProperty("os.name")); + System.out.println(base); + Path p = Paths.get("AddAndSubtractPaths.java") + .toAbsolutePath(); + show(1, p); + Path convoluted = p.getParent().getParent() + .resolve("strings") + .resolve("..") + .resolve(p.getParent().getFileName()); + show(2, convoluted); + show(3, convoluted.normalize()); + + Path p2 = Paths.get("..", ".."); + show(4, p2); + show(5, p2.normalize()); + show(6, p2.toAbsolutePath().normalize()); + + Path p3 = Paths.get(".").toAbsolutePath(); + Path p4 = p3.resolve(p2); + show(7, p4); + show(8, p4.normalize()); + + Path p5 = Paths.get("").toAbsolutePath(); + show(9, p5); + show(10, p5.resolveSibling("strings")); + show(11, Paths.get("nonexistent")); + } +} +/* Output: +Windows 10 +C:\Users\Bruce\Documents\GitHub +(1)r on- +java\ExtractedExamples\files\AddAndSubtractPaths.java +RealPath: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files\AddAndSubtractPaths.java +(2)r on-java\ExtractedExamples\strings\..\files +RealPath: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files +(3)r on-java\ExtractedExamples\files +RealPath: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files +(4) ..\.. +RealPath: C:\Users\Bruce\Documents\GitHub\on-java +(5) ..\.. +RealPath: C:\Users\Bruce\Documents\GitHub\on-java +(6)r on-java +RealPath: C:\Users\Bruce\Documents\GitHub\on-java +(7)r on-java\ExtractedExamples\files\.\..\.. +RealPath: C:\Users\Bruce\Documents\GitHub\on-java +(8)r on-java +RealPath: C:\Users\Bruce\Documents\GitHub\on-java +(9)r on-java\ExtractedExamples\files +RealPath: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files +(10)r on-java\ExtractedExamples\strings +RealPath: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\strings +(11) nonexistent +java.nio.file.NoSuchFileException: +C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files\nonexistent +*/ diff --git a/code/files/Directories.java b/code/files/Directories.java new file mode 100644 index 00000000..10ad9bee --- /dev/null +++ b/code/files/Directories.java @@ -0,0 +1,94 @@ +// files/Directories.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.nio.file.*; +import onjava.RmDir; + +public class Directories { + static Path test = Paths.get("test"); + static String sep = + FileSystems.getDefault().getSeparator(); + static List parts = + Arrays.asList("foo", "bar", "baz", "bag"); + static Path makeVariant() { + Collections.rotate(parts, 1); + return Paths.get("test", String.join(sep, parts)); + } + static void refreshTestDir() throws Exception { + if(Files.exists(test)) + RmDir.rmdir(test); + if(!Files.exists(test)) + Files.createDirectory(test); + } + public static void + main(String[] args) throws Exception { + refreshTestDir(); + Files.createFile(test.resolve("Hello.txt")); + Path variant = makeVariant(); + // Throws exception (too many levels): + try { + Files.createDirectory(variant); + } catch(Exception e) { + System.out.println("Nope, that doesn't work."); + } + populateTestDir(); + Path tempdir = + Files.createTempDirectory(test, "DIR_"); + Files.createTempFile(tempdir, "pre", ".non"); + Files.newDirectoryStream(test) + .forEach(System.out::println); + System.out.println("*********"); + Files.walk(test).forEach(System.out::println); + } + static void populateTestDir() throws Exception { + for(int i = 0; i < parts.size(); i++) { + Path variant = makeVariant(); + if(!Files.exists(variant)) { + Files.createDirectories(variant); + Files.copy(Paths.get("Directories.java"), + variant.resolve("File.txt")); + Files.createTempFile(variant, null, null); + } + } + } +} +/* Output: +Nope, that doesn't work. +test\bag +test\bar +test\baz +test\DIR_5142667942049986036 +test\foo +test\Hello.txt +********* +test +test\bag +test\bag\foo +test\bag\foo\bar +test\bag\foo\bar\baz +test\bag\foo\bar\baz\8279660869874696036.tmp +test\bag\foo\bar\baz\File.txt +test\bar +test\bar\baz +test\bar\baz\bag +test\bar\baz\bag\foo +test\bar\baz\bag\foo\1274043134240426261.tmp +test\bar\baz\bag\foo\File.txt +test\baz +test\baz\bag +test\baz\bag\foo +test\baz\bag\foo\bar +test\baz\bag\foo\bar\6130572530014544105.tmp +test\baz\bag\foo\bar\File.txt +test\DIR_5142667942049986036 +test\DIR_5142667942049986036\pre7704286843227113253.non +test\foo +test\foo\bar +test\foo\bar\baz +test\foo\bar\baz\bag +test\foo\bar\baz\bag\5412864507741775436.tmp +test\foo\bar\baz\bag\File.txt +test\Hello.txt +*/ diff --git a/code/files/FileSystemDemo.java b/code/files/FileSystemDemo.java new file mode 100644 index 00000000..3d9024ca --- /dev/null +++ b/code/files/FileSystemDemo.java @@ -0,0 +1,41 @@ +// files/FileSystemDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.file.*; + +public class FileSystemDemo { + static void show(String id, Object o) { + System.out.println(id + ": " + o); + } + public static void main(String[] args) { + System.out.println(System.getProperty("os.name")); + FileSystem fsys = FileSystems.getDefault(); + for(FileStore fs : fsys.getFileStores()) + show("File Store", fs); + for(Path rd : fsys.getRootDirectories()) + show("Root Directory", rd); + show("Separator", fsys.getSeparator()); + show("UserPrincipalLookupService", + fsys.getUserPrincipalLookupService()); + show("isOpen", fsys.isOpen()); + show("isReadOnly", fsys.isReadOnly()); + show("FileSystemProvider", fsys.provider()); + show("File Attribute Views", + fsys.supportedFileAttributeViews()); + } +} +/* Output: +Windows 10 +File Store: SSD (C:) +Root Directory: C:\ +Root Directory: D:\ +Separator: \ +UserPrincipalLookupService: +sun.nio.fs.WindowsFileSystem$LookupService$1@15db9742 +isOpen: true +isReadOnly: false +FileSystemProvider: +sun.nio.fs.WindowsFileSystemProvider@6d06d69c +File Attribute Views: [owner, dos, acl, basic, user] +*/ diff --git a/code/files/Find.java b/code/files/Find.java new file mode 100644 index 00000000..ac97ebdc --- /dev/null +++ b/code/files/Find.java @@ -0,0 +1,60 @@ +// files/Find.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromGradle} +import java.nio.file.*; + +public class Find { + public static void + main(String[] args) throws Exception { + Path test = Paths.get("test"); + Directories.refreshTestDir(); + Directories.populateTestDir(); + // Creating a *directory*, not a file: + Files.createDirectory(test.resolve("dir.tmp")); + + PathMatcher matcher = FileSystems.getDefault() + .getPathMatcher("glob:**/*.{tmp,txt}"); + Files.walk(test) + .filter(matcher::matches) + .forEach(System.out::println); + System.out.println("***************"); + + PathMatcher matcher2 = FileSystems.getDefault() + .getPathMatcher("glob:*.tmp"); + Files.walk(test) + .map(Path::getFileName) + .filter(matcher2::matches) + .forEach(System.out::println); + System.out.println("***************"); + + Files.walk(test) // Only look for files + .filter(Files::isRegularFile) + .map(Path::getFileName) + .filter(matcher2::matches) + .forEach(System.out::println); + } +} +/* Output: +test\bag\foo\bar\baz\5208762845883213974.tmp +test\bag\foo\bar\baz\File.txt +test\bar\baz\bag\foo\7918367201207778677.tmp +test\bar\baz\bag\foo\File.txt +test\baz\bag\foo\bar\8016595521026696632.tmp +test\baz\bag\foo\bar\File.txt +test\dir.tmp +test\foo\bar\baz\bag\5832319279813617280.tmp +test\foo\bar\baz\bag\File.txt +*************** +5208762845883213974.tmp +7918367201207778677.tmp +8016595521026696632.tmp +dir.tmp +5832319279813617280.tmp +*************** +5208762845883213974.tmp +7918367201207778677.tmp +8016595521026696632.tmp +5832319279813617280.tmp +*/ diff --git a/code/files/ListOfLines.java b/code/files/ListOfLines.java new file mode 100644 index 00000000..6f9ef467 --- /dev/null +++ b/code/files/ListOfLines.java @@ -0,0 +1,26 @@ +// files/ListOfLines.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.nio.file.*; + +public class ListOfLines { + public static void + main(String[] args) throws Exception { + Files.readAllLines( + Paths.get("../streams/Cheese.dat")) + .stream() + .filter(line -> !line.startsWith("//")) + .map(line -> + line.substring(0, line.length()/2)) + .forEach(System.out::println); + } +} +/* Output: +Not much of a cheese +Finest in the +And what leads you +Well, it's +It's certainly uncon +*/ diff --git a/code/files/PartsOfPaths.java b/code/files/PartsOfPaths.java new file mode 100644 index 00000000..1170fc68 --- /dev/null +++ b/code/files/PartsOfPaths.java @@ -0,0 +1,45 @@ +// files/PartsOfPaths.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.file.*; + +public class PartsOfPaths { + public static void main(String[] args) { + System.out.println(System.getProperty("os.name")); + Path p = + Paths.get("PartsOfPaths.java").toAbsolutePath(); + for(int i = 0; i < p.getNameCount(); i++) + System.out.println(p.getName(i)); + System.out.println("ends with '.java': " + + p.endsWith(".java")); + for(Path pp : p) { + System.out.print(pp + ": "); + System.out.print(p.startsWith(pp) + " : "); + System.out.println(p.endsWith(pp)); + } + System.out.println("Starts with " + p.getRoot() + + " " + p.startsWith(p.getRoot())); + } +} +/* Output: +Windows 10 +Users +Bruce +Documents +GitHub +on-java +ExtractedExamples +files +PartsOfPaths.java +ends with '.java': false +Users: false : false +Bruce: false : false +Documents: false : false +GitHub: false : false +on-java: false : false +ExtractedExamples: false : false +files: false : false +PartsOfPaths.java: false : true +Starts with C:\ true +*/ diff --git a/code/files/PathAnalysis.java b/code/files/PathAnalysis.java new file mode 100644 index 00000000..117119cd --- /dev/null +++ b/code/files/PathAnalysis.java @@ -0,0 +1,56 @@ +// files/PathAnalysis.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.file.*; +import java.io.IOException; + +public class PathAnalysis { + static void say(String id, Object result) { + System.out.print(id + ": "); + System.out.println(result); + } + public static void + main(String[] args) throws IOException { + System.out.println(System.getProperty("os.name")); + Path p = + Paths.get("PathAnalysis.java").toAbsolutePath(); + say("Exists", Files.exists(p)); + say("Directory", Files.isDirectory(p)); + say("Executable", Files.isExecutable(p)); + say("Readable", Files.isReadable(p)); + say("RegularFile", Files.isRegularFile(p)); + say("Writable", Files.isWritable(p)); + say("notExists", Files.notExists(p)); + say("Hidden", Files.isHidden(p)); + say("size", Files.size(p)); + say("FileStore", Files.getFileStore(p)); + say("LastModified: ", Files.getLastModifiedTime(p)); + say("Owner", Files.getOwner(p)); + say("ContentType", Files.probeContentType(p)); + say("SymbolicLink", Files.isSymbolicLink(p)); + if(Files.isSymbolicLink(p)) + say("SymbolicLink", Files.readSymbolicLink(p)); + if(FileSystems.getDefault() + .supportedFileAttributeViews().contains("posix")) + say("PosixFilePermissions", + Files.getPosixFilePermissions(p)); + } +} +/* Output: +Windows 10 +Exists: true +Directory: false +Executable: true +Readable: true +RegularFile: true +Writable: true +notExists: false +Hidden: false +size: 1631 +FileStore: SSD (C:) +LastModified: : 2017-05-09T12:07:00.428366Z +Owner: MINDVIEWTOSHIBA\Bruce (User) +ContentType: null +SymbolicLink: false +*/ diff --git a/code/files/PathInfo.java b/code/files/PathInfo.java new file mode 100644 index 00000000..96af9d93 --- /dev/null +++ b/code/files/PathInfo.java @@ -0,0 +1,102 @@ +// files/PathInfo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.file.*; +import java.net.URI; +import java.io.File; +import java.io.IOException; + +public class PathInfo { + static void show(String id, Object p) { + System.out.println(id + ": " + p); + } + static void info(Path p) { + show("toString", p); + show("Exists", Files.exists(p)); + show("RegularFile", Files.isRegularFile(p)); + show("Directory", Files.isDirectory(p)); + show("Absolute", p.isAbsolute()); + show("FileName", p.getFileName()); + show("Parent", p.getParent()); + show("Root", p.getRoot()); + System.out.println("******************"); + } + public static void main(String[] args) { + System.out.println(System.getProperty("os.name")); + info(Paths.get( + "C:", "path", "to", "nowhere", "NoFile.txt")); + Path p = Paths.get("PathInfo.java"); + info(p); + Path ap = p.toAbsolutePath(); + info(ap); + info(ap.getParent()); + try { + info(p.toRealPath()); + } catch(IOException e) { + System.out.println(e); + } + URI u = p.toUri(); + System.out.println("URI: " + u); + Path puri = Paths.get(u); + System.out.println(Files.exists(puri)); + File f = ap.toFile(); // Don't be fooled + } +} +/* Output: +Windows 10 +toString: C:\path\to\nowhere\NoFile.txt +Exists: false +RegularFile: false +Directory: false +Absolute: true +FileName: NoFile.txt +Parent: C:\path\to\nowhere +Root: C:\ +****************** +toString: PathInfo.java +Exists: true +RegularFile: true +Directory: false +Absolute: false +FileName: PathInfo.java +Parent: null +Root: null +****************** +toString: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files\PathInfo.java +Exists: true +RegularFile: true +Directory: false +Absolute: true +FileName: PathInfo.java +Parent: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files +Root: C:\ +****************** +toString: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files +Exists: true +RegularFile: false +Directory: true +Absolute: true +FileName: files +Parent: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples +Root: C:\ +****************** +toString: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files\PathInfo.java +Exists: true +RegularFile: true +Directory: false +Absolute: true +FileName: PathInfo.java +Parent: C:\Users\Bruce\Documents\GitHub\on- +java\ExtractedExamples\files +Root: C:\ +****************** +URI: file:///C:/Users/Bruce/Documents/GitHub/on- +java/ExtractedExamples/files/PathInfo.java +true +*/ diff --git a/code/files/PathWatcher.java b/code/files/PathWatcher.java new file mode 100644 index 00000000..162641d7 --- /dev/null +++ b/code/files/PathWatcher.java @@ -0,0 +1,61 @@ +// files/PathWatcher.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromGradle} +import java.io.IOException; +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKinds.*; +import java.util.concurrent.*; + +public class PathWatcher { + static Path test = Paths.get("test"); + static void delTxtFiles() { + try { + Files.walk(test) + .filter(f -> + f.toString().endsWith(".txt")) + .forEach(f -> { + try { + System.out.println("deleting " + f); + Files.delete(f); + } catch(IOException e) { + throw new RuntimeException(e); + } + }); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + public static void + main(String[] args) throws Exception { + Directories.refreshTestDir(); + Directories.populateTestDir(); + Files.createFile(test.resolve("Hello.txt")); + WatchService watcher = + FileSystems.getDefault().newWatchService(); + test.register(watcher, ENTRY_DELETE); + Executors.newSingleThreadScheduledExecutor() + .schedule( + PathWatcher::delTxtFiles, + 250, TimeUnit.MILLISECONDS); + WatchKey key = watcher.take(); + for(WatchEvent evt : key.pollEvents()) { + System.out.println( + "evt.context(): " + evt.context() + + "\nevt.count(): " + evt.count() + + "\nevt.kind(): " + evt.kind()); + System.exit(0); + } + } +} +/* Output: +deleting test\bag\foo\bar\baz\File.txt +deleting test\bar\baz\bag\foo\File.txt +deleting test\baz\bag\foo\bar\File.txt +deleting test\foo\bar\baz\bag\File.txt +deleting test\Hello.txt +evt.context(): Hello.txt +evt.count(): 1 +evt.kind(): ENTRY_DELETE +*/ diff --git a/code/files/ReadLineStream.java b/code/files/ReadLineStream.java new file mode 100644 index 00000000..64b0f562 --- /dev/null +++ b/code/files/ReadLineStream.java @@ -0,0 +1,18 @@ +// files/ReadLineStream.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.file.*; + +public class ReadLineStream { + public static void + main(String[] args) throws Exception { + Files.lines(Paths.get("PathInfo.java")) + .skip(13) + .findFirst() + .ifPresent(System.out::println); + } +} +/* Output: + show("RegularFile", Files.isRegularFile(p)); +*/ diff --git a/code/files/StreamInAndOut.java b/code/files/StreamInAndOut.java new file mode 100644 index 00000000..ec17c700 --- /dev/null +++ b/code/files/StreamInAndOut.java @@ -0,0 +1,24 @@ +// files/StreamInAndOut.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.nio.file.*; +import java.util.stream.*; + +public class StreamInAndOut { + public static void main(String[] args) { + try( + Stream input = + Files.lines(Paths.get("StreamInAndOut.java")); + PrintWriter output = + new PrintWriter("StreamInAndOut.txt") + ) { + input + .map(String::toUpperCase) + .forEachOrdered(output::println); + } catch(Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/files/TreeWatcher.java b/code/files/TreeWatcher.java new file mode 100644 index 00000000..f0660888 --- /dev/null +++ b/code/files/TreeWatcher.java @@ -0,0 +1,51 @@ +// files/TreeWatcher.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromGradle} +import java.io.IOException; +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKinds.*; +import java.util.concurrent.*; + +public class TreeWatcher { + static void watchDir(Path dir) { + try { + WatchService watcher = + FileSystems.getDefault().newWatchService(); + dir.register(watcher, ENTRY_DELETE); + Executors.newSingleThreadExecutor().submit(() -> { + try { + WatchKey key = watcher.take(); + for(WatchEvent evt : key.pollEvents()) { + System.out.println( + "evt.context(): " + evt.context() + + "\nevt.count(): " + evt.count() + + "\nevt.kind(): " + evt.kind()); + System.exit(0); + } + } catch(InterruptedException e) { + return; + } + }); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + public static void + main(String[] args) throws Exception { + Directories.refreshTestDir(); + Directories.populateTestDir(); + Files.walk(Paths.get("test")) + .filter(Files::isDirectory) + .forEach(TreeWatcher::watchDir); + PathWatcher.delTxtFiles(); + } +} +/* Output: +deleting test\bag\foo\bar\baz\File.txt +deleting test\bar\baz\bag\foo\File.txt +evt.context(): File.txt +evt.count(): 1 +evt.kind(): ENTRY_DELETE +*/ diff --git a/code/files/Writing.java b/code/files/Writing.java new file mode 100644 index 00000000..68a04fbc --- /dev/null +++ b/code/files/Writing.java @@ -0,0 +1,31 @@ +// files/Writing.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.nio.file.*; + +public class Writing { + static Random rand = new Random(47); + static final int SIZE = 1000; + public static void + main(String[] args) throws Exception { + // Write bytes to a file: + byte[] bytes = new byte[SIZE]; + rand.nextBytes(bytes); + Files.write(Paths.get("bytes.dat"), bytes); + System.out.println("bytes.dat: " + + Files.size(Paths.get("bytes.dat"))); + + // Write an iterable to a file: + List lines = Files.readAllLines( + Paths.get("../streams/Cheese.dat")); + Files.write(Paths.get("Cheese.txt"), lines); + System.out.println("Cheese.txt: " + + Files.size(Paths.get("Cheese.txt"))); + } +} +/* Output: +bytes.dat: 1000 +Cheese.txt: 199 +*/ diff --git a/code/functional/AnonymousClosure.java b/code/functional/AnonymousClosure.java new file mode 100644 index 00000000..497a1a52 --- /dev/null +++ b/code/functional/AnonymousClosure.java @@ -0,0 +1,17 @@ +// functional/AnonymousClosure.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class AnonymousClosure { + IntSupplier makeFun(int x) { + int i = 0; + // Same rules apply: + // i++; // Not "effectively final" + // x++; // Ditto + return new IntSupplier() { + public int getAsInt() { return x + i; } + }; + } +} diff --git a/code/functional/BiConsumerPermutations.java b/code/functional/BiConsumerPermutations.java new file mode 100644 index 00000000..75b7c32d --- /dev/null +++ b/code/functional/BiConsumerPermutations.java @@ -0,0 +1,24 @@ +// functional/BiConsumerPermutations.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class BiConsumerPermutations { + static BiConsumer bicid = (i, d) -> + System.out.format("%d, %f%n", i, d); + static BiConsumer bicdi = (d, i) -> + System.out.format("%d, %f%n", i, d); + static BiConsumer bicil = (i, l) -> + System.out.format("%d, %d%n", i, l); + public static void main(String[] args) { + bicid.accept(47, 11.34); + bicdi.accept(22.45, 92); + bicil.accept(1, 11L); + } +} +/* Output: +47, 11.340000 +92, 22.450000 +1, 11 +*/ diff --git a/code/functional/ClassFunctionals.java b/code/functional/ClassFunctionals.java new file mode 100644 index 00000000..e5101df4 --- /dev/null +++ b/code/functional/ClassFunctionals.java @@ -0,0 +1,45 @@ +// functional/ClassFunctionals.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; + +class AA {} +class BB {} +class CC {} + +public class ClassFunctionals { + static AA f1() { return new AA(); } + static int f2(AA aa1, AA aa2) { return 1; } + static void f3(AA aa) {} + static void f4(AA aa, BB bb) {} + static CC f5(AA aa) { return new CC(); } + static CC f6(AA aa, BB bb) { return new CC(); } + static boolean f7(AA aa) { return true; } + static boolean f8(AA aa, BB bb) { return true; } + static AA f9(AA aa) { return new AA(); } + static AA f10(AA aa1, AA aa2) { return new AA(); } + public static void main(String[] args) { + Supplier s = ClassFunctionals::f1; + s.get(); + Comparator c = ClassFunctionals::f2; + c.compare(new AA(), new AA()); + Consumer cons = ClassFunctionals::f3; + cons.accept(new AA()); + BiConsumer bicons = ClassFunctionals::f4; + bicons.accept(new AA(), new BB()); + Function f = ClassFunctionals::f5; + CC cc = f.apply(new AA()); + BiFunction bif = ClassFunctionals::f6; + cc = bif.apply(new AA(), new BB()); + Predicate p = ClassFunctionals::f7; + boolean result = p.test(new AA()); + BiPredicate bip = ClassFunctionals::f8; + result = bip.test(new AA(), new BB()); + UnaryOperator uo = ClassFunctionals::f9; + AA aa = uo.apply(new AA()); + BinaryOperator bo = ClassFunctionals::f10; + aa = bo.apply(new AA(), new AA()); + } +} diff --git a/code/functional/Closure1.java b/code/functional/Closure1.java new file mode 100644 index 00000000..2f504f42 --- /dev/null +++ b/code/functional/Closure1.java @@ -0,0 +1,12 @@ +// functional/Closure1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class Closure1 { + int i; + IntSupplier makeFun(int x) { + return () -> x + i++; + } +} diff --git a/code/functional/Closure2.java b/code/functional/Closure2.java new file mode 100644 index 00000000..825cf423 --- /dev/null +++ b/code/functional/Closure2.java @@ -0,0 +1,12 @@ +// functional/Closure2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class Closure2 { + IntSupplier makeFun(int x) { + int i = 0; + return () -> x + i; + } +} diff --git a/code/functional/Closure3.java b/code/functional/Closure3.java new file mode 100644 index 00000000..811179fb --- /dev/null +++ b/code/functional/Closure3.java @@ -0,0 +1,14 @@ +// functional/Closure3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +import java.util.function.*; + +public class Closure3 { + IntSupplier makeFun(int x) { + int i = 0; + // Neither x++ nor i++ will work: + return () -> x++ + i++; + } +} diff --git a/code/functional/Closure4.java b/code/functional/Closure4.java new file mode 100644 index 00000000..148aaf64 --- /dev/null +++ b/code/functional/Closure4.java @@ -0,0 +1,12 @@ +// functional/Closure4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class Closure4 { + IntSupplier makeFun(final int x) { + final int i = 0; + return () -> x + i; + } +} diff --git a/code/functional/Closure5.java b/code/functional/Closure5.java new file mode 100644 index 00000000..fb9aad77 --- /dev/null +++ b/code/functional/Closure5.java @@ -0,0 +1,15 @@ +// functional/Closure5.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +import java.util.function.*; + +public class Closure5 { + IntSupplier makeFun(int x) { + int i = 0; + i++; + x++; + return () -> x + i; + } +} diff --git a/code/functional/Closure6.java b/code/functional/Closure6.java new file mode 100644 index 00000000..178f9b4a --- /dev/null +++ b/code/functional/Closure6.java @@ -0,0 +1,16 @@ +// functional/Closure6.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class Closure6 { + IntSupplier makeFun(int x) { + int i = 0; + i++; + x++; + final int iFinal = i; + final int xFinal = x; + return () -> xFinal + iFinal; + } +} diff --git a/code/functional/Closure7.java b/code/functional/Closure7.java new file mode 100644 index 00000000..9facdc06 --- /dev/null +++ b/code/functional/Closure7.java @@ -0,0 +1,14 @@ +// functional/Closure7.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +import java.util.function.*; + +public class Closure7 { + IntSupplier makeFun(int x) { + Integer i = 0; + i = i + 1; + return () -> x + i; + } +} diff --git a/code/functional/Closure8.java b/code/functional/Closure8.java new file mode 100644 index 00000000..7ec059b2 --- /dev/null +++ b/code/functional/Closure8.java @@ -0,0 +1,32 @@ +// functional/Closure8.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; + +public class Closure8 { + Supplier> makeFun() { + final List ai = new ArrayList<>(); + ai.add(1); + return () -> ai; + } + public static void main(String[] args) { + Closure8 c7 = new Closure8(); + List + l1 = c7.makeFun().get(), + l2 = c7.makeFun().get(); + System.out.println(l1); + System.out.println(l2); + l1.add(42); + l2.add(96); + System.out.println(l1); + System.out.println(l2); + } +} +/* Output: +[1] +[1] +[1, 42] +[1, 96] +*/ diff --git a/code/functional/Closure9.java b/code/functional/Closure9.java new file mode 100644 index 00000000..4eddb47a --- /dev/null +++ b/code/functional/Closure9.java @@ -0,0 +1,15 @@ +// functional/Closure9.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +import java.util.*; +import java.util.function.*; + +public class Closure9 { + Supplier> makeFun() { + List ai = new ArrayList<>(); + ai = new ArrayList<>(); // Reassignment + return () -> ai; + } +} diff --git a/code/functional/ConsumeFunction.java b/code/functional/ConsumeFunction.java new file mode 100644 index 00000000..ea84a24a --- /dev/null +++ b/code/functional/ConsumeFunction.java @@ -0,0 +1,17 @@ +// functional/ConsumeFunction.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +class One {} +class Two {} + +public class ConsumeFunction { + static Two consume(Function onetwo) { + return onetwo.apply(new One()); + } + public static void main(String[] args) { + Two two = consume(one -> new Two()); + } +} diff --git a/code/functional/CtorReference.java b/code/functional/CtorReference.java new file mode 100644 index 00000000..4c22bdf1 --- /dev/null +++ b/code/functional/CtorReference.java @@ -0,0 +1,36 @@ +// functional/CtorReference.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Dog { + String name; + int age = -1; // For "unknown" + Dog() { name = "stray"; } + Dog(String nm) { name = nm; } + Dog(String nm, int yrs) { name = nm; age = yrs; } +} + +interface MakeNoArgs { + Dog make(); +} + +interface Make1Arg { + Dog make(String nm); +} + +interface Make2Args { + Dog make(String nm, int age); +} + +public class CtorReference { + public static void main(String[] args) { + MakeNoArgs mna = Dog::new; // [1] + Make1Arg m1a = Dog::new; // [2] + Make2Args m2a = Dog::new; // [3] + + Dog dn = mna.make(); + Dog d1 = m1a.make("Comet"); + Dog d2 = m2a.make("Ralph", 4); + } +} diff --git a/code/functional/CurriedIntAdd.java b/code/functional/CurriedIntAdd.java new file mode 100644 index 00000000..e89ac8e2 --- /dev/null +++ b/code/functional/CurriedIntAdd.java @@ -0,0 +1,17 @@ +// functional/CurriedIntAdd.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class CurriedIntAdd { + public static void main(String[] args) { + IntFunction + curriedIntAdd = a -> b -> a + b; + IntUnaryOperator add4 = curriedIntAdd.apply(4); + System.out.println(add4.applyAsInt(5)); + } +} +/* Output: +9 +*/ diff --git a/code/functional/Curry3Args.java b/code/functional/Curry3Args.java new file mode 100644 index 00000000..0fd376bc --- /dev/null +++ b/code/functional/Curry3Args.java @@ -0,0 +1,23 @@ +// functional/Curry3Args.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class Curry3Args { + public static void main(String[] args) { + Function>> sum = + a -> b -> c -> a + b + c; + Function> hi = + sum.apply("Hi "); + Function ho = + hi.apply("Ho "); + System.out.println(ho.apply("Hup")); + } +} +/* Output: +Hi Ho Hup +*/ diff --git a/code/functional/CurryingAndPartials.java b/code/functional/CurryingAndPartials.java new file mode 100644 index 00000000..0addb811 --- /dev/null +++ b/code/functional/CurryingAndPartials.java @@ -0,0 +1,35 @@ +// functional/CurryingAndPartials.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class CurryingAndPartials { + // Uncurried: + static String uncurried(String a, String b) { + return a + b; + } + public static void main(String[] args) { + // Curried function: + Function> sum = + a -> b -> a + b; // [1] + + System.out.println(uncurried("Hi ", "Ho")); + + Function + hi = sum.apply("Hi "); // [2] + System.out.println(hi.apply("Ho")); + + // Partial application: + Function sumHi = + sum.apply("Hup "); + System.out.println(sumHi.apply("Ho")); + System.out.println(sumHi.apply("Hey")); + } +} +/* Output: +Hi Ho +Hi Ho +Hup Ho +Hup Hey +*/ diff --git a/code/functional/FunctionComposition.java b/code/functional/FunctionComposition.java new file mode 100644 index 00000000..a183039d --- /dev/null +++ b/code/functional/FunctionComposition.java @@ -0,0 +1,24 @@ +// functional/FunctionComposition.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class FunctionComposition { + static Function + f1 = s -> { + System.out.println(s); + return s.replace('A', '_'); + }, + f2 = s -> s.substring(3), + f3 = s -> s.toLowerCase(), + f4 = f1.compose(f2).andThen(f3); + public static void main(String[] args) { + System.out.println( + f4.apply("GO AFTER ALL AMBULANCES")); + } +} +/* Output: +AFTER ALL AMBULANCES +_fter _ll _mbul_nces +*/ diff --git a/code/functional/FunctionVariants.java b/code/functional/FunctionVariants.java new file mode 100644 index 00000000..a6205462 --- /dev/null +++ b/code/functional/FunctionVariants.java @@ -0,0 +1,65 @@ +// functional/FunctionVariants.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +class Foo {} + +class Bar { + Foo f; + Bar(Foo f) { this.f = f; } +} + +class IBaz { + int i; + IBaz(int i) { + this.i = i; + } +} + +class LBaz { + long l; + LBaz(long l) { + this.l = l; + } +} + +class DBaz { + double d; + DBaz(double d) { + this.d = d; + } +} + +public class FunctionVariants { + static Function f1 = f -> new Bar(f); + static IntFunction f2 = i -> new IBaz(i); + static LongFunction f3 = l -> new LBaz(l); + static DoubleFunction f4 = d -> new DBaz(d); + static ToIntFunction f5 = ib -> ib.i; + static ToLongFunction f6 = lb -> lb.l; + static ToDoubleFunction f7 = db -> db.d; + static IntToLongFunction f8 = i -> i; + static IntToDoubleFunction f9 = i -> i; + static LongToIntFunction f10 = l -> (int)l; + static LongToDoubleFunction f11 = l -> l; + static DoubleToIntFunction f12 = d -> (int)d; + static DoubleToLongFunction f13 = d -> (long)d; + + public static void main(String[] args) { + Bar b = f1.apply(new Foo()); + IBaz ib = f2.apply(11); + LBaz lb = f3.apply(11); + DBaz db = f4.apply(11); + int i = f5.applyAsInt(ib); + long l = f6.applyAsLong(lb); + double d = f7.applyAsDouble(db); + l = f8.applyAsLong(12); + d = f9.applyAsDouble(12); + i = f10.applyAsInt(12); + d = f11.applyAsDouble(12); + i = f12.applyAsInt(13.0); + l = f13.applyAsLong(13.0); + } +} diff --git a/code/functional/FunctionWithWrapped.java b/code/functional/FunctionWithWrapped.java new file mode 100644 index 00000000..b654da65 --- /dev/null +++ b/code/functional/FunctionWithWrapped.java @@ -0,0 +1,12 @@ +// functional/FunctionWithWrapped.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class FunctionWithWrapped { + public static void main(String[] args) { + Function fid = i -> (double)i; + IntToDoubleFunction fid2 = i -> i; + } +} diff --git a/code/functional/FunctionalAnnotation.java b/code/functional/FunctionalAnnotation.java new file mode 100644 index 00000000..84cec649 --- /dev/null +++ b/code/functional/FunctionalAnnotation.java @@ -0,0 +1,40 @@ +// functional/FunctionalAnnotation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +@FunctionalInterface +interface Functional { + String goodbye(String arg); +} + +interface FunctionalNoAnn { + String goodbye(String arg); +} + +/* +@FunctionalInterface +interface NotFunctional { + String goodbye(String arg); + String hello(String arg); +} +Produces error message: +NotFunctional is not a functional interface +multiple non-overriding abstract methods +found in interface NotFunctional +*/ + +public class FunctionalAnnotation { + public String goodbye(String arg) { + return "Goodbye, " + arg; + } + public static void main(String[] args) { + FunctionalAnnotation fa = + new FunctionalAnnotation(); + Functional f = fa::goodbye; + FunctionalNoAnn fna = fa::goodbye; + // Functional fac = fa; // Incompatible + Functional fl = a -> "Goodbye, " + a; + FunctionalNoAnn fnal = a -> "Goodbye, " + a; + } +} diff --git a/code/functional/IntCall.java b/code/functional/IntCall.java new file mode 100644 index 00000000..a8256a00 --- /dev/null +++ b/code/functional/IntCall.java @@ -0,0 +1,8 @@ +// functional/IntCall.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface IntCall { + int call(int arg); +} diff --git a/code/functional/LambdaExpressions.java b/code/functional/LambdaExpressions.java new file mode 100644 index 00000000..fe7e3acb --- /dev/null +++ b/code/functional/LambdaExpressions.java @@ -0,0 +1,48 @@ +// functional/LambdaExpressions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface Description { + String brief(); +} + +interface Body { + String detailed(String head); +} + +interface Multi { + String twoArg(String head, Double d); +} + +public class LambdaExpressions { + + static Body bod = h -> h + " No Parens!"; // [1] + + static Body bod2 = (h) -> h + " More details"; // [2] + + static Description desc = () -> "Short info"; // [3] + + static Multi mult = (h, n) -> h + n; // [4] + + static Description moreLines = () -> { // [5] + System.out.println("moreLines()"); + return "from moreLines()"; + }; + + public static void main(String[] args) { + System.out.println(bod.detailed("Oh!")); + System.out.println(bod2.detailed("Hi!")); + System.out.println(desc.brief()); + System.out.println(mult.twoArg("Pi! ", 3.14159)); + System.out.println(moreLines.brief()); + } +} +/* Output: +Oh! No Parens! +Hi! More details +Short info +Pi! 3.14159 +moreLines() +from moreLines() +*/ diff --git a/code/functional/MethodConversion.java b/code/functional/MethodConversion.java new file mode 100644 index 00000000..008ecfc0 --- /dev/null +++ b/code/functional/MethodConversion.java @@ -0,0 +1,31 @@ +// functional/MethodConversion.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +class In1 {} +class In2 {} + +public class MethodConversion { + static void accept(In1 i1, In2 i2) { + System.out.println("accept()"); + } + static void someOtherName(In1 i1, In2 i2) { + System.out.println("someOtherName()"); + } + public static void main(String[] args) { + BiConsumer bic; + + bic = MethodConversion::accept; + bic.accept(new In1(), new In2()); + + bic = MethodConversion::someOtherName; + // bic.someOtherName(new In1(), new In2()); // Nope + bic.accept(new In1(), new In2()); + } +} +/* Output: +accept() +someOtherName() +*/ diff --git a/code/functional/MethodReferences.java b/code/functional/MethodReferences.java new file mode 100644 index 00000000..63bc365d --- /dev/null +++ b/code/functional/MethodReferences.java @@ -0,0 +1,53 @@ +// functional/MethodReferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +interface Callable { // [1] + void call(String s); +} + +class Describe { + void show(String msg) { // [2] + System.out.println(msg); + } +} + +public class MethodReferences { + static void hello(String name) { // [3] + System.out.println("Hello, " + name); + } + static class Description { + String about; + Description(String desc) { about = desc; } + void help(String msg) { // [4] + System.out.println(about + " " + msg); + } + } + static class Helper { + static void assist(String msg) { // [5] + System.out.println(msg); + } + } + public static void main(String[] args) { + Describe d = new Describe(); + Callable c = d::show; // [6] + c.call("call()"); // [7] + + c = MethodReferences::hello; // [8] + c.call("Bob"); + + c = new Description("valuable")::help; // [9] + c.call("information"); + + c = Helper::assist; // [10] + c.call("Help!"); + } +} +/* Output: +call() +Hello, Bob +valuable information +Help! +*/ diff --git a/code/functional/MultiUnbound.java b/code/functional/MultiUnbound.java new file mode 100644 index 00000000..4209fb04 --- /dev/null +++ b/code/functional/MultiUnbound.java @@ -0,0 +1,36 @@ +// functional/MultiUnbound.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Unbound methods with multiple arguments + +class This { + void two(int i, double d) {} + void three(int i, double d, String s) {} + void four(int i, double d, String s, char c) {} +} + +interface TwoArgs { + void call2(This athis, int i, double d); +} + +interface ThreeArgs { + void call3(This athis, int i, double d, String s); +} + +interface FourArgs { + void call4( + This athis, int i, double d, String s, char c); +} + +public class MultiUnbound { + public static void main(String[] args) { + TwoArgs twoargs = This::two; + ThreeArgs threeargs = This::three; + FourArgs fourargs = This::four; + This athis = new This(); + twoargs.call2(athis, 11, 3.14); + threeargs.call3(athis, 11, 3.14, "Three"); + fourargs.call4(athis, 11, 3.14, "Four", 'Z'); + } +} diff --git a/code/functional/PredicateComposition.java b/code/functional/PredicateComposition.java new file mode 100644 index 00000000..f95bbcbd --- /dev/null +++ b/code/functional/PredicateComposition.java @@ -0,0 +1,23 @@ +// functional/PredicateComposition.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; +import java.util.stream.*; + +public class PredicateComposition { + static Predicate + p1 = s -> s.contains("bar"), + p2 = s -> s.length() < 5, + p3 = s -> s.contains("foo"), + p4 = p1.negate().and(p2).or(p3); + public static void main(String[] args) { + Stream.of("bar", "foobar", "foobaz", "fongopuckey") + .filter(p4) + .forEach(System.out::println); + } +} +/* Output: +foobar +foobaz +*/ diff --git a/code/functional/ProduceFunction.java b/code/functional/ProduceFunction.java new file mode 100644 index 00000000..03471601 --- /dev/null +++ b/code/functional/ProduceFunction.java @@ -0,0 +1,21 @@ +// functional/ProduceFunction.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +interface +FuncSS extends Function {} // [1] + +public class ProduceFunction { + static FuncSS produce() { + return s -> s.toLowerCase(); // [2] + } + public static void main(String[] args) { + FuncSS f = produce(); + System.out.println(f.apply("YELLING")); + } +} +/* Output: +yelling +*/ diff --git a/code/functional/RecursiveFactorial.java b/code/functional/RecursiveFactorial.java new file mode 100644 index 00000000..2d610441 --- /dev/null +++ b/code/functional/RecursiveFactorial.java @@ -0,0 +1,26 @@ +// functional/RecursiveFactorial.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class RecursiveFactorial { + static IntCall fact; + public static void main(String[] args) { + fact = n -> n == 0 ? 1 : n * fact.call(n - 1); + for(int i = 0; i <= 10; i++) + System.out.println(fact.call(i)); + } +} +/* Output: +1 +1 +2 +6 +24 +120 +720 +5040 +40320 +362880 +3628800 +*/ diff --git a/code/functional/RecursiveFibonacci.java b/code/functional/RecursiveFibonacci.java new file mode 100644 index 00000000..9be43dc6 --- /dev/null +++ b/code/functional/RecursiveFibonacci.java @@ -0,0 +1,32 @@ +// functional/RecursiveFibonacci.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class RecursiveFibonacci { + IntCall fib; + RecursiveFibonacci() { + fib = n -> n == 0 ? 0 : + n == 1 ? 1 : + fib.call(n - 1) + fib.call(n - 2); + } + int fibonacci(int n) { return fib.call(n); } + public static void main(String[] args) { + RecursiveFibonacci rf = new RecursiveFibonacci(); + for(int i = 0; i <= 10; i++) + System.out.println(rf.fibonacci(i)); + } +} +/* Output: +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +*/ diff --git a/code/functional/RunnableMethodReference.java b/code/functional/RunnableMethodReference.java new file mode 100644 index 00000000..5fb8cd00 --- /dev/null +++ b/code/functional/RunnableMethodReference.java @@ -0,0 +1,33 @@ +// functional/RunnableMethodReference.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Method references with interface Runnable + +class Go { + static void go() { + System.out.println("Go::go()"); + } +} + +public class RunnableMethodReference { + public static void main(String[] args) { + + new Thread(new Runnable() { + public void run() { + System.out.println("Anonymous"); + } + }).start(); + + new Thread( + () -> System.out.println("lambda") + ).start(); + + new Thread(Go::go).start(); + } +} +/* Output: +Anonymous +lambda +Go::go() +*/ diff --git a/code/functional/SharedStorage.java b/code/functional/SharedStorage.java new file mode 100644 index 00000000..c2a41f66 --- /dev/null +++ b/code/functional/SharedStorage.java @@ -0,0 +1,22 @@ +// functional/SharedStorage.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class SharedStorage { + public static void main(String[] args) { + Closure1 c1 = new Closure1(); + IntSupplier f1 = c1.makeFun(0); + IntSupplier f2 = c1.makeFun(0); + IntSupplier f3 = c1.makeFun(0); + System.out.println(f1.getAsInt()); + System.out.println(f2.getAsInt()); + System.out.println(f3.getAsInt()); + } +} +/* Output: +0 +1 +2 +*/ diff --git a/code/functional/Strategize.java b/code/functional/Strategize.java new file mode 100644 index 00000000..e46c9143 --- /dev/null +++ b/code/functional/Strategize.java @@ -0,0 +1,58 @@ +// functional/Strategize.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface Strategy { + String approach(String msg); +} + +class Soft implements Strategy { + public String approach(String msg) { + return msg.toLowerCase() + "?"; + } +} + +class Unrelated { + static String twice(String msg) { + return msg + " " + msg; + } +} + +public class Strategize { + Strategy strategy; + String msg; + Strategize(String msg) { + strategy = new Soft(); // [1] + this.msg = msg; + } + void communicate() { + System.out.println(strategy.approach(msg)); + } + void changeStrategy(Strategy strategy) { + this.strategy = strategy; + } + public static void main(String[] args) { + Strategy[] strategies = { + new Strategy() { // [2] + public String approach(String msg) { + return msg.toUpperCase() + "!"; + } + }, + msg -> msg.substring(0, 5), // [3] + Unrelated::twice // [4] + }; + Strategize s = new Strategize("Hello there"); + s.communicate(); + for(Strategy newStrategy : strategies) { + s.changeStrategy(newStrategy); // [5] + s.communicate(); // [6] + } + } +} +/* Output: +hello there? +HELLO THERE! +Hello +Hello there Hello there +*/ diff --git a/code/functional/TransformFunction.java b/code/functional/TransformFunction.java new file mode 100644 index 00000000..1a046eb1 --- /dev/null +++ b/code/functional/TransformFunction.java @@ -0,0 +1,35 @@ +// functional/TransformFunction.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +class I { + @Override + public String toString() { return "I"; } +} + +class O { + @Override + public String toString() { return "O"; } +} + +public class TransformFunction { + static Function transform(Function in) { + return in.andThen(o -> { + System.out.println(o); + return o; + }); + } + public static void main(String[] args) { + Function f2 = transform(i -> { + System.out.println(i); + return new O(); + }); + O o = f2.apply(new I()); + } +} +/* Output: +I +O +*/ diff --git a/code/functional/TriFunction.java b/code/functional/TriFunction.java new file mode 100644 index 00000000..76049621 --- /dev/null +++ b/code/functional/TriFunction.java @@ -0,0 +1,9 @@ +// functional/TriFunction.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +@FunctionalInterface +public interface TriFunction { + R apply(T t, U u, V v); +} diff --git a/code/functional/TriFunctionTest.java b/code/functional/TriFunctionTest.java new file mode 100644 index 00000000..fccf8b9a --- /dev/null +++ b/code/functional/TriFunctionTest.java @@ -0,0 +1,13 @@ +// functional/TriFunctionTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class TriFunctionTest { + static int f(int i, long l, double d) { return 99; } + public static void main(String[] args) { + TriFunction tf = + TriFunctionTest::f; + tf = (i, l, d) -> 12; + } +} diff --git a/code/functional/UnboundMethodReference.java b/code/functional/UnboundMethodReference.java new file mode 100644 index 00000000..da2c7872 --- /dev/null +++ b/code/functional/UnboundMethodReference.java @@ -0,0 +1,31 @@ +// functional/UnboundMethodReference.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Method reference without an object + +class X { + String f() { return "X::f()"; } +} + +interface MakeString { + String make(); +} + +interface TransformX { + String transform(X x); +} + +public class UnboundMethodReference { + public static void main(String[] args) { + // MakeString ms = X::f; // [1] + TransformX sp = X::f; + X x = new X(); + System.out.println(sp.transform(x)); // [2] + System.out.println(x.f()); // Same effect + } +} +/* Output: +X::f() +X::f() +*/ diff --git a/code/generics/Amphibian.java b/code/generics/Amphibian.java new file mode 100644 index 00000000..5e76d8b1 --- /dev/null +++ b/code/generics/Amphibian.java @@ -0,0 +1,5 @@ +// generics/Amphibian.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class Amphibian {} diff --git a/code/generics/Apply.java b/code/generics/Apply.java new file mode 100644 index 00000000..c9378611 --- /dev/null +++ b/code/generics/Apply.java @@ -0,0 +1,21 @@ +// generics/Apply.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.reflect.*; +import java.util.*; + +public class Apply { + public static > + void apply(S seq, Method f, Object... args) { + try { + for(T t: seq) + f.invoke(t, args); + } catch(IllegalAccessException | + IllegalArgumentException | + InvocationTargetException e) { + // Failures are programmer errors + throw new RuntimeException(e); + } + } +} diff --git a/code/generics/ApplyFunctional.java b/code/generics/ApplyFunctional.java new file mode 100644 index 00000000..4cce156e --- /dev/null +++ b/code/generics/ApplyFunctional.java @@ -0,0 +1,49 @@ +// generics/ApplyFunctional.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; +import onjava.*; + +public class ApplyFunctional { + public static void main(String[] args) { + Stream.of( + Stream.generate(Shape::new).limit(2), + Stream.generate(Square::new).limit(2)) + .flatMap(c -> c) // flatten into one stream + .peek(Shape::rotate) + .forEach(s -> s.resize(7)); + + new FilledList<>(Shape::new, 2) + .forEach(Shape::rotate); + new FilledList<>(Square::new, 2) + .forEach(Shape::rotate); + + SimpleQueue shapeQ = Suppliers.fill( + new SimpleQueue<>(), SimpleQueue::add, + Shape::new, 2); + Suppliers.fill(shapeQ, SimpleQueue::add, + Square::new, 2); + shapeQ.forEach(Shape::rotate); + } +} +/* Output: +Shape 0 rotate +Shape 0 resize 7 +Shape 1 rotate +Shape 1 resize 7 +Square 2 rotate +Square 2 resize 7 +Square 3 rotate +Square 3 resize 7 +Shape 4 rotate +Shape 5 rotate +Square 6 rotate +Square 7 rotate +Shape 8 rotate +Shape 9 rotate +Square 10 rotate +Square 11 rotate +*/ diff --git a/code/generics/ApplyTest.java b/code/generics/ApplyTest.java new file mode 100644 index 00000000..62ef4eec --- /dev/null +++ b/code/generics/ApplyTest.java @@ -0,0 +1,65 @@ +// generics/ApplyTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import onjava.*; + +public class ApplyTest { + public static + void main(String[] args) throws Exception { + List shapes = + Suppliers.create(ArrayList::new, Shape::new, 3); + Apply.apply(shapes, + Shape.class.getMethod("rotate")); + Apply.apply(shapes, + Shape.class.getMethod("resize", int.class), 7); + + List squares = + Suppliers.create(ArrayList::new, Square::new, 3); + Apply.apply(squares, + Shape.class.getMethod("rotate")); + Apply.apply(squares, + Shape.class.getMethod("resize", int.class), 7); + + Apply.apply(new FilledList<>(Shape::new, 3), + Shape.class.getMethod("rotate")); + Apply.apply(new FilledList<>(Square::new, 3), + Shape.class.getMethod("rotate")); + + SimpleQueue shapeQ = Suppliers.fill( + new SimpleQueue<>(), SimpleQueue::add, + Shape::new, 3); + Suppliers.fill(shapeQ, SimpleQueue::add, + Square::new, 3); + Apply.apply(shapeQ, + Shape.class.getMethod("rotate")); + } +} +/* Output: +Shape 0 rotate +Shape 1 rotate +Shape 2 rotate +Shape 0 resize 7 +Shape 1 resize 7 +Shape 2 resize 7 +Square 3 rotate +Square 4 rotate +Square 5 rotate +Square 3 resize 7 +Square 4 resize 7 +Square 5 resize 7 +Shape 6 rotate +Shape 7 rotate +Shape 8 rotate +Square 9 rotate +Square 10 rotate +Square 11 rotate +Shape 12 rotate +Shape 13 rotate +Shape 14 rotate +Square 15 rotate +Square 16 rotate +Square 17 rotate +*/ diff --git a/code/generics/ArrayMaker.java b/code/generics/ArrayMaker.java new file mode 100644 index 00000000..f1bb6b9a --- /dev/null +++ b/code/generics/ArrayMaker.java @@ -0,0 +1,24 @@ +// generics/ArrayMaker.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.reflect.*; +import java.util.*; + +public class ArrayMaker { + private Class kind; + public ArrayMaker(Class kind) { this.kind = kind; } + @SuppressWarnings("unchecked") + T[] create(int size) { + return (T[])Array.newInstance(kind, size); + } + public static void main(String[] args) { + ArrayMaker stringMaker = + new ArrayMaker<>(String.class); + String[] stringArray = stringMaker.create(9); + System.out.println(Arrays.toString(stringArray)); + } +} +/* Output: +[null, null, null, null, null, null, null, null, null] +*/ diff --git a/code/generics/ArrayOfGeneric.java b/code/generics/ArrayOfGeneric.java new file mode 100644 index 00000000..67e6cb97 --- /dev/null +++ b/code/generics/ArrayOfGeneric.java @@ -0,0 +1,28 @@ +// generics/ArrayOfGeneric.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ArrayOfGeneric { + static final int SIZE = 100; + static Generic[] gia; + @SuppressWarnings("unchecked") + public static void main(String[] args) { + try { + gia = (Generic[])new Object[SIZE]; + } catch(ClassCastException e) { + System.out.println(e.getMessage()); + } + // Runtime type is the raw (erased) type: + gia = (Generic[])new Generic[SIZE]; + System.out.println(gia.getClass().getSimpleName()); + gia[0] = new Generic<>(); + //- gia[1] = new Object(); // Compile-time error + // Discovers type mismatch at compile time: + //- gia[2] = new Generic(); + } +} +/* Output: +[Ljava.lang.Object; cannot be cast to [LGeneric; +Generic[] +*/ diff --git a/code/generics/ArrayOfGenericReference.java b/code/generics/ArrayOfGenericReference.java new file mode 100644 index 00000000..1cb2f345 --- /dev/null +++ b/code/generics/ArrayOfGenericReference.java @@ -0,0 +1,10 @@ +// generics/ArrayOfGenericReference.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Generic {} + +public class ArrayOfGenericReference { + static Generic[] gia; +} diff --git a/code/generics/BankTeller.java b/code/generics/BankTeller.java new file mode 100644 index 00000000..68301996 --- /dev/null +++ b/code/generics/BankTeller.java @@ -0,0 +1,71 @@ +// generics/BankTeller.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A very simple bank teller simulation +import java.util.*; +import onjava.*; + +class Customer { + private static long counter = 1; + private final long id = counter++; + @Override + public String toString() { + return "Customer " + id; + } +} + +class Teller { + private static long counter = 1; + private final long id = counter++; + @Override + public String toString() { + return "Teller " + id; + } +} + +class Bank { + private List tellers = + new ArrayList<>(); + public void put(BankTeller bt) { + tellers.add(bt); + } +} + +public class BankTeller { + public static void serve(Teller t, Customer c) { + System.out.println(t + " serves " + c); + } + public static void main(String[] args) { + // Demonstrate create(): + RandomList tellers = + Suppliers.create( + RandomList::new, Teller::new, 4); + // Demonstrate fill(): + List customers = Suppliers.fill( + new ArrayList<>(), Customer::new, 12); + customers.forEach(c -> + serve(tellers.select(), c)); + // Demonstrate assisted latent typing: + Bank bank = Suppliers.fill( + new Bank(), Bank::put, BankTeller::new, 3); + // Can also use second version of fill(): + List customers2 = Suppliers.fill( + new ArrayList<>(), + List::add, Customer::new, 12); + } +} +/* Output: +Teller 3 serves Customer 1 +Teller 2 serves Customer 2 +Teller 3 serves Customer 3 +Teller 1 serves Customer 4 +Teller 1 serves Customer 5 +Teller 3 serves Customer 6 +Teller 1 serves Customer 7 +Teller 2 serves Customer 8 +Teller 3 serves Customer 9 +Teller 3 serves Customer 10 +Teller 2 serves Customer 11 +Teller 4 serves Customer 12 +*/ diff --git a/code/generics/BasicBounds.java b/code/generics/BasicBounds.java new file mode 100644 index 00000000..434d0fd8 --- /dev/null +++ b/code/generics/BasicBounds.java @@ -0,0 +1,63 @@ +// generics/BasicBounds.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface HasColor { java.awt.Color getColor(); } + +class WithColor { + T item; + WithColor(T item) { this.item = item; } + T getItem() { return item; } + // The bound allows you to call a method: + java.awt.Color color() { return item.getColor(); } +} + +class Coord { public int x, y, z; } + +// This fails. Class must be first, then interfaces: +// class WithColorCoord { + +// Multiple bounds: +class WithColorCoord { + T item; + WithColorCoord(T item) { this.item = item; } + T getItem() { return item; } + java.awt.Color color() { return item.getColor(); } + int getX() { return item.x; } + int getY() { return item.y; } + int getZ() { return item.z; } +} + +interface Weight { int weight(); } + +// As with inheritance, you can have only one +// concrete class but multiple interfaces: +class Solid { + T item; + Solid(T item) { this.item = item; } + T getItem() { return item; } + java.awt.Color color() { return item.getColor(); } + int getX() { return item.x; } + int getY() { return item.y; } + int getZ() { return item.z; } + int weight() { return item.weight(); } +} + +class Bounded +extends Coord implements HasColor, Weight { + @Override + public java.awt.Color getColor() { return null; } + @Override + public int weight() { return 0; } +} + +public class BasicBounds { + public static void main(String[] args) { + Solid solid = + new Solid<>(new Bounded()); + solid.color(); + solid.getY(); + solid.weight(); + } +} diff --git a/code/generics/BasicHolder.java b/code/generics/BasicHolder.java new file mode 100644 index 00000000..2b8b8a9b --- /dev/null +++ b/code/generics/BasicHolder.java @@ -0,0 +1,14 @@ +// generics/BasicHolder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class BasicHolder { + T element; + void set(T arg) { element = arg; } + T get() { return element; } + void f() { + System.out.println( + element.getClass().getSimpleName()); + } +} diff --git a/code/generics/BasicSupplierDemo.java b/code/generics/BasicSupplierDemo.java new file mode 100644 index 00000000..1ce95ca1 --- /dev/null +++ b/code/generics/BasicSupplierDemo.java @@ -0,0 +1,22 @@ +// generics/BasicSupplierDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; +import java.util.stream.*; + +public class BasicSupplierDemo { + public static void main(String[] args) { + Stream.generate( + BasicSupplier.create(CountedObject.class)) + .limit(5) + .forEach(System.out::println); + } +} +/* Output: +CountedObject 0 +CountedObject 1 +CountedObject 2 +CountedObject 3 +CountedObject 4 +*/ diff --git a/code/generics/ByteSet.java b/code/generics/ByteSet.java new file mode 100644 index 00000000..19b27091 --- /dev/null +++ b/code/generics/ByteSet.java @@ -0,0 +1,14 @@ +// generics/ByteSet.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ByteSet { + Byte[] possibles = { 1,2,3,4,5,6,7,8,9 }; + Set mySet = + new HashSet<>(Arrays.asList(possibles)); + // But you can't do this: + // Set mySet2 = new HashSet<>( + // Arrays.asList(1,2,3,4,5,6,7,8,9)); +} diff --git a/code/generics/CRGWithBasicHolder.java b/code/generics/CRGWithBasicHolder.java new file mode 100644 index 00000000..eb85868a --- /dev/null +++ b/code/generics/CRGWithBasicHolder.java @@ -0,0 +1,20 @@ +// generics/CRGWithBasicHolder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Subtype extends BasicHolder {} + +public class CRGWithBasicHolder { + public static void main(String[] args) { + Subtype + st1 = new Subtype(), + st2 = new Subtype(); + st1.set(st2); + Subtype st3 = st1.get(); + st1.f(); + } +} +/* Output: +Subtype +*/ diff --git a/code/generics/CaptureConversion.java b/code/generics/CaptureConversion.java new file mode 100644 index 00000000..16348468 --- /dev/null +++ b/code/generics/CaptureConversion.java @@ -0,0 +1,62 @@ +// generics/CaptureConversion.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class CaptureConversion { + static void f1(Holder holder) { + T t = holder.get(); + System.out.println(t.getClass().getSimpleName()); + } + static void f2(Holder holder) { + f1(holder); // Call with captured type + } + @SuppressWarnings("unchecked") + public static void main(String[] args) { + Holder raw = new Holder<>(1); + + f1(raw); + // warning: [unchecked] unchecked method invocation: + // method f1 in class CaptureConversion + // is applied to given types + // f1(raw); + // ^ + // required: Holder + // found: Holder + // where T is a type-variable: + // T extends Object declared in + // method f1(Holder) + // warning: [unchecked] unchecked conversion + // f1(raw); + // ^ + // required: Holder + // found: Holder + // where T is a type-variable: + // T extends Object declared in + // method f1(Holder) + // 2 warnings + + f2(raw); // No warnings + Holder rawBasic = new Holder(); + + rawBasic.set(new Object()); + // warning: [unchecked] unchecked call to set(T) + // as a member of the raw type Holder + // rawBasic.set(new Object()); + // ^ + // where T is a type-variable: + // T extends Object declared in class Holder + // 1 warning + + f2(rawBasic); // No warnings + // Upcast to Holder, still figures it out: + Holder wildcarded = new Holder<>(1.0); + f2(wildcarded); + } +} +/* Output: +Integer +Integer +Object +Double +*/ diff --git a/code/generics/CheckedList.java b/code/generics/CheckedList.java new file mode 100644 index 00000000..6e330cf6 --- /dev/null +++ b/code/generics/CheckedList.java @@ -0,0 +1,35 @@ +// generics/CheckedList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using Collection.checkedList() +import typeinfo.pets.*; +import java.util.*; + +public class CheckedList { + @SuppressWarnings("unchecked") + static void oldStyleMethod(List probablyDogs) { + probablyDogs.add(new Cat()); + } + public static void main(String[] args) { + List dogs1 = new ArrayList<>(); + oldStyleMethod(dogs1); // Quietly accepts a Cat + List dogs2 = Collections.checkedList( + new ArrayList<>(), Dog.class); + try { + oldStyleMethod(dogs2); // Throws an exception + } catch(Exception e) { + System.out.println("Expected: " + e); + } + // Derived types work fine: + List pets = Collections.checkedList( + new ArrayList<>(), Pet.class); + pets.add(new Dog()); + pets.add(new Cat()); + } +} +/* Output: +Expected: java.lang.ClassCastException: Attempt to +insert class typeinfo.pets.Cat element into collection +with element type class typeinfo.pets.Dog +*/ diff --git a/code/generics/ClassCasting.java b/code/generics/ClassCasting.java new file mode 100644 index 00000000..c6da592a --- /dev/null +++ b/code/generics/ClassCasting.java @@ -0,0 +1,18 @@ +// generics/ClassCasting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.util.*; + +public class ClassCasting { + @SuppressWarnings("unchecked") + public void f(String[] args) throws Exception { + ObjectInputStream in = new ObjectInputStream( + new FileInputStream(args[0])); + // Won't Compile: +// List lw1 = +// List<>.class.cast(in.readObject()); + List lw2 = List.class.cast(in.readObject()); + } +} diff --git a/code/generics/ClassTypeCapture.java b/code/generics/ClassTypeCapture.java new file mode 100644 index 00000000..ab193dfe --- /dev/null +++ b/code/generics/ClassTypeCapture.java @@ -0,0 +1,33 @@ +// generics/ClassTypeCapture.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Building {} +class House extends Building {} + +public class ClassTypeCapture { + Class kind; + public ClassTypeCapture(Class kind) { + this.kind = kind; + } + public boolean f(Object arg) { + return kind.isInstance(arg); + } + public static void main(String[] args) { + ClassTypeCapture ctt1 = + new ClassTypeCapture<>(Building.class); + System.out.println(ctt1.f(new Building())); + System.out.println(ctt1.f(new House())); + ClassTypeCapture ctt2 = + new ClassTypeCapture<>(House.class); + System.out.println(ctt2.f(new Building())); + System.out.println(ctt2.f(new House())); + } +} +/* Output: +true +true +false +true +*/ diff --git a/code/generics/ComparablePet.java b/code/generics/ComparablePet.java new file mode 100644 index 00000000..3646e66a --- /dev/null +++ b/code/generics/ComparablePet.java @@ -0,0 +1,12 @@ +// generics/ComparablePet.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ComparablePet +implements Comparable { + @Override + public int compareTo(ComparablePet arg) { + return 0; + } +} diff --git a/code/generics/CompilerIntelligence.java b/code/generics/CompilerIntelligence.java new file mode 100644 index 00000000..6e4cd0e8 --- /dev/null +++ b/code/generics/CompilerIntelligence.java @@ -0,0 +1,15 @@ +// generics/CompilerIntelligence.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class CompilerIntelligence { + public static void main(String[] args) { + List flist = + Arrays.asList(new Apple()); + Apple a = (Apple)flist.get(0); // No warning + flist.contains(new Apple()); // Argument is 'Object' + flist.indexOf(new Apple()); // Argument is 'Object' + } +} diff --git a/code/generics/CountedObject.java b/code/generics/CountedObject.java new file mode 100644 index 00000000..ab4caecd --- /dev/null +++ b/code/generics/CountedObject.java @@ -0,0 +1,14 @@ +// generics/CountedObject.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class CountedObject { + private static long counter = 0; + private final long id = counter++; + public long id() { return id; } + @Override + public String toString() { + return "CountedObject " + id; + } +} diff --git a/code/generics/CovariantArrays.java b/code/generics/CovariantArrays.java new file mode 100644 index 00000000..e202ca07 --- /dev/null +++ b/code/generics/CovariantArrays.java @@ -0,0 +1,30 @@ +// generics/CovariantArrays.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Fruit {} +class Apple extends Fruit {} +class Jonathan extends Apple {} +class Orange extends Fruit {} + +public class CovariantArrays { + public static void main(String[] args) { + Fruit[] fruit = new Apple[10]; + fruit[0] = new Apple(); // OK + fruit[1] = new Jonathan(); // OK + // Runtime type is Apple[], not Fruit[] or Orange[]: + try { + // Compiler allows you to add Fruit: + fruit[0] = new Fruit(); // ArrayStoreException + } catch(Exception e) { System.out.println(e); } + try { + // Compiler allows you to add Oranges: + fruit[0] = new Orange(); // ArrayStoreException + } catch(Exception e) { System.out.println(e); } + } +} +/* Output: +java.lang.ArrayStoreException: Fruit +java.lang.ArrayStoreException: Orange +*/ diff --git a/code/generics/CovariantReturnTypes.java b/code/generics/CovariantReturnTypes.java new file mode 100644 index 00000000..04178ad4 --- /dev/null +++ b/code/generics/CovariantReturnTypes.java @@ -0,0 +1,23 @@ +// generics/CovariantReturnTypes.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Base {} +class Derived extends Base {} + +interface OrdinaryGetter { + Base get(); +} + +interface DerivedGetter extends OrdinaryGetter { + // Overridden method return type can vary: + @Override + Derived get(); +} + +public class CovariantReturnTypes { + void test(DerivedGetter d) { + Derived d2 = d.get(); + } +} diff --git a/code/generics/CreatorGeneric.java b/code/generics/CreatorGeneric.java new file mode 100644 index 00000000..7fd90df4 --- /dev/null +++ b/code/generics/CreatorGeneric.java @@ -0,0 +1,31 @@ +// generics/CreatorGeneric.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +abstract class GenericWithCreate { + final T element; + GenericWithCreate() { element = create(); } + abstract T create(); +} + +class X {} + +class XCreator extends GenericWithCreate { + @Override + X create() { return new X(); } + void f() { + System.out.println( + element.getClass().getSimpleName()); + } +} + +public class CreatorGeneric { + public static void main(String[] args) { + XCreator xc = new XCreator(); + xc.f(); + } +} +/* Output: +X +*/ diff --git a/code/generics/CuriouslyRecurringGeneric.java b/code/generics/CuriouslyRecurringGeneric.java new file mode 100644 index 00000000..ee1f3a61 --- /dev/null +++ b/code/generics/CuriouslyRecurringGeneric.java @@ -0,0 +1,9 @@ +// generics/CuriouslyRecurringGeneric.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class GenericType {} + +public class CuriouslyRecurringGeneric + extends GenericType {} diff --git a/code/generics/Diamond.java b/code/generics/Diamond.java new file mode 100644 index 00000000..32c3ff1a --- /dev/null +++ b/code/generics/Diamond.java @@ -0,0 +1,13 @@ +// generics/Diamond.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Bob {} + +public class Diamond { + public static void main(String[] args) { + GenericHolder h3 = new GenericHolder<>(); + h3.set(new Bob()); + } +} diff --git a/code/generics/DogsAndRobotMethodReferences.java b/code/generics/DogsAndRobotMethodReferences.java new file mode 100644 index 00000000..7c3fa357 --- /dev/null +++ b/code/generics/DogsAndRobotMethodReferences.java @@ -0,0 +1,45 @@ +// generics/DogsAndRobotMethodReferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// "Assisted Latent Typing" +import typeinfo.pets.*; +import java.util.function.*; + +class PerformingDogA extends Dog { + public void speak() { System.out.println("Woof!"); } + public void sit() { System.out.println("Sitting"); } + public void reproduce() {} +} + +class RobotA { + public void speak() { System.out.println("Click!"); } + public void sit() { System.out.println("Clank!"); } + public void oilChange() {} +} + +class CommunicateA { + public static

void perform(P performer, + Consumer

action1, Consumer

action2) { + action1.accept(performer); + action2.accept(performer); + } +} + +public class DogsAndRobotMethodReferences { + public static void main(String[] args) { + CommunicateA.perform(new PerformingDogA(), + PerformingDogA::speak, PerformingDogA::sit); + CommunicateA.perform(new RobotA(), + RobotA::speak, RobotA::sit); + CommunicateA.perform(new Mime(), + Mime::walkAgainstTheWind, + Mime::pushInvisibleWalls); + } +} +/* Output: +Woof! +Sitting +Click! +Clank! +*/ diff --git a/code/generics/DogsAndRobots.cpp b/code/generics/DogsAndRobots.cpp new file mode 100644 index 00000000..81ced5d9 --- /dev/null +++ b/code/generics/DogsAndRobots.cpp @@ -0,0 +1,38 @@ +// generics/DogsAndRobots.cpp +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +#include +using namespace std; + +class Dog { +public: + void speak() { cout << "Arf!" << endl; } + void sit() { cout << "Sitting" << endl; } + void reproduce() {} +}; + +class Robot { +public: + void speak() { cout << "Click!" << endl; } + void sit() { cout << "Clank!" << endl; } + void oilChange() {} +}; + +template void perform(T anything) { + anything.speak(); + anything.sit(); +} + +int main() { + Dog d; + Robot r; + perform(d); + perform(r); +} +/* Output: +Arf! +Sitting +Click! +Clank! +*/ diff --git a/code/generics/DogsAndRobots.java b/code/generics/DogsAndRobots.java new file mode 100644 index 00000000..b6151122 --- /dev/null +++ b/code/generics/DogsAndRobots.java @@ -0,0 +1,41 @@ +// generics/DogsAndRobots.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// No (direct) latent typing in Java +import typeinfo.pets.*; + +class PerformingDog extends Dog implements Performs { + @Override + public void speak() { System.out.println("Woof!"); } + @Override + public void sit() { System.out.println("Sitting"); } + public void reproduce() {} +} + +class Robot implements Performs { + public void speak() { System.out.println("Click!"); } + public void sit() { System.out.println("Clank!"); } + public void oilChange() {} +} + +class Communicate { + public static + void perform(T performer) { + performer.speak(); + performer.sit(); + } +} + +public class DogsAndRobots { + public static void main(String[] args) { + Communicate.perform(new PerformingDog()); + Communicate.perform(new Robot()); + } +} +/* Output: +Woof! +Sitting +Click! +Clank! +*/ diff --git a/code/generics/DogsAndRobots.py b/code/generics/DogsAndRobots.py new file mode 100644 index 00000000..c9ca6fef --- /dev/null +++ b/code/generics/DogsAndRobots.py @@ -0,0 +1,36 @@ +# generics/DogsAndRobots.py +# (c)2020 MindView LLC: see Copyright.txt +# We make no guarantees that this code is fit for any purpose. +# Visit http://OnJava8.com for more book information. + +class Dog: + def speak(self): + print("Arf!") + def sit(self): + print("Sitting") + def reproduce(self): + pass + +class Robot: + def speak(self): + print("Click!") + def sit(self): + print("Clank!") + def oilChange(self): + pass + +def perform(anything): + anything.speak() + anything.sit() + +a = Dog() +b = Robot() +perform(a) +perform(b) + +output = """ +Arf! +Sitting +Click! +Clank! +""" diff --git a/code/generics/DynamicProxyMixin.java b/code/generics/DynamicProxyMixin.java new file mode 100644 index 00000000..38431e31 --- /dev/null +++ b/code/generics/DynamicProxyMixin.java @@ -0,0 +1,66 @@ +// generics/DynamicProxyMixin.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.reflect.*; +import java.util.*; +import onjava.*; +import static onjava.Tuple.*; + +class MixinProxy implements InvocationHandler { + Map delegatesByMethod; + @SuppressWarnings("unchecked") + MixinProxy(Tuple2>... pairs) { + delegatesByMethod = new HashMap<>(); + for(Tuple2> pair : pairs) { + for(Method method : pair.a2.getMethods()) { + String methodName = method.getName(); + // The first interface in the map + // implements the method. + if(!delegatesByMethod.containsKey(methodName)) + delegatesByMethod.put(methodName, pair.a1); + } + } + } + @Override + public Object invoke(Object proxy, Method method, + Object[] args) throws Throwable { + String methodName = method.getName(); + Object delegate = delegatesByMethod.get(methodName); + return method.invoke(delegate, args); + } + @SuppressWarnings("unchecked") + public static Object newInstance(Tuple2... pairs) { + Class[] interfaces = new Class[pairs.length]; + for(int i = 0; i < pairs.length; i++) { + interfaces[i] = (Class)pairs[i].a2; + } + ClassLoader cl = + pairs[0].a1.getClass().getClassLoader(); + return Proxy.newProxyInstance( + cl, interfaces, new MixinProxy(pairs)); + } +} + +public class DynamicProxyMixin { + public static void main(String[] args) { + @SuppressWarnings("unchecked") + Object mixin = MixinProxy.newInstance( + tuple(new BasicImp(), Basic.class), + tuple(new TimeStampedImp(), TimeStamped.class), + tuple(new SerialNumberedImp(), + SerialNumbered.class)); + Basic b = (Basic)mixin; + TimeStamped t = (TimeStamped)mixin; + SerialNumbered s = (SerialNumbered)mixin; + b.set("Hello"); + System.out.println(b.get()); + System.out.println(t.getStamp()); + System.out.println(s.getSerialNumber()); + } +} +/* Output: +Hello +1494331653339 +1 +*/ diff --git a/code/generics/EpicBattle.java b/code/generics/EpicBattle.java new file mode 100644 index 00000000..908a3343 --- /dev/null +++ b/code/generics/EpicBattle.java @@ -0,0 +1,74 @@ +// generics/EpicBattle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Bounds in Java generics +import java.util.*; + +interface SuperPower {} + +interface XRayVision extends SuperPower { + void seeThroughWalls(); +} + +interface SuperHearing extends SuperPower { + void hearSubtleNoises(); +} + +interface SuperSmell extends SuperPower { + void trackBySmell(); +} + +class SuperHero { + POWER power; + SuperHero(POWER power) { this.power = power; } + POWER getPower() { return power; } +} + +class SuperSleuth +extends SuperHero { + SuperSleuth(POWER power) { super(power); } + void see() { power.seeThroughWalls(); } +} + +class +CanineHero +extends SuperHero { + CanineHero(POWER power) { super(power); } + void hear() { power.hearSubtleNoises(); } + void smell() { power.trackBySmell(); } +} + +class SuperHearSmell +implements SuperHearing, SuperSmell { + @Override + public void hearSubtleNoises() {} + @Override + public void trackBySmell() {} +} + +class DogPerson extends CanineHero { + DogPerson() { super(new SuperHearSmell()); } +} + +public class EpicBattle { + // Bounds in generic methods: + static + void useSuperHearing(SuperHero hero) { + hero.getPower().hearSubtleNoises(); + } + static + void superFind(SuperHero hero) { + hero.getPower().hearSubtleNoises(); + hero.getPower().trackBySmell(); + } + public static void main(String[] args) { + DogPerson dogPerson = new DogPerson(); + useSuperHearing(dogPerson); + superFind(dogPerson); + // You can do this: + List audioPeople; + // But you can't do this: + // List dogPs; + } +} diff --git a/code/generics/Erased.java b/code/generics/Erased.java new file mode 100644 index 00000000..911839c3 --- /dev/null +++ b/code/generics/Erased.java @@ -0,0 +1,24 @@ +// generics/Erased.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} + +public class Erased { + private final int SIZE = 100; + public void f(Object arg) { + + // error: illegal generic type for instanceof + if(arg instanceof T) {} + + // error: unexpected type + T var = new T(); + + // error: generic array creation + T[] array = new T[SIZE]; + + // warning: [unchecked] unchecked cast + T[] array = (T[])new Object[SIZE]; + + } +} diff --git a/code/generics/ErasedTypeEquivalence.java b/code/generics/ErasedTypeEquivalence.java new file mode 100644 index 00000000..6034b304 --- /dev/null +++ b/code/generics/ErasedTypeEquivalence.java @@ -0,0 +1,16 @@ +// generics/ErasedTypeEquivalence.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ErasedTypeEquivalence { + public static void main(String[] args) { + Class c1 = new ArrayList().getClass(); + Class c2 = new ArrayList().getClass(); + System.out.println(c1 == c2); + } +} +/* Output: +true +*/ diff --git a/code/generics/ErasureAndInheritance.java b/code/generics/ErasureAndInheritance.java new file mode 100644 index 00000000..44a07b62 --- /dev/null +++ b/code/generics/ErasureAndInheritance.java @@ -0,0 +1,28 @@ +// generics/ErasureAndInheritance.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class GenericBase { + private T element; + public void set(T arg) { element = arg; } + public T get() { return element; } +} + +class Derived1 extends GenericBase {} + +class Derived2 extends GenericBase {} // No warning + +// class Derived3 extends GenericBase {} +// Strange error: +// unexpected type +// required: class or interface without bounds + +public class ErasureAndInheritance { + @SuppressWarnings("unchecked") + public static void main(String[] args) { + Derived2 d2 = new Derived2(); + Object obj = d2.get(); + d2.set(obj); // Warning here! + } +} diff --git a/code/generics/FactoryConstraint.java b/code/generics/FactoryConstraint.java new file mode 100644 index 00000000..f0651073 --- /dev/null +++ b/code/generics/FactoryConstraint.java @@ -0,0 +1,62 @@ +// generics/FactoryConstraint.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import onjava.*; + +class IntegerFactory implements Supplier { + private int i = 0; + @Override + public Integer get() { + return ++i; + } +} + +class Widget { + private int id; + Widget(int n) { id = n; } + @Override + public String toString() { + return "Widget " + id; + } + public static + class Factory implements Supplier { + private int i = 0; + @Override + public Widget get() { return new Widget(++i); } + } +} + +class Fudge { + private static int count = 1; + private int n = count++; + @Override + public String toString() { return "Fudge " + n; } +} + +class Foo2 { + private List x = new ArrayList<>(); + Foo2(Supplier factory) { + Suppliers.fill(x, factory, 5); + } + @Override + public String toString() { return x.toString(); } +} + +public class FactoryConstraint { + public static void main(String[] args) { + System.out.println( + new Foo2<>(new IntegerFactory())); + System.out.println( + new Foo2<>(new Widget.Factory())); + System.out.println( + new Foo2<>(Fudge::new)); + } +} +/* Output: +[1, 2, 3, 4, 5] +[Widget 1, Widget 2, Widget 3, Widget 4, Widget 5] +[Fudge 1, Fudge 2, Fudge 3, Fudge 4, Fudge 5] +*/ diff --git a/code/generics/Fibonacci.java b/code/generics/Fibonacci.java new file mode 100644 index 00000000..11540061 --- /dev/null +++ b/code/generics/Fibonacci.java @@ -0,0 +1,27 @@ +// generics/Fibonacci.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Generate a Fibonacci sequence +import java.util.function.*; +import java.util.stream.*; + +public class Fibonacci implements Supplier { + private int count = 0; + @Override + public Integer get() { return fib(count++); } + private int fib(int n) { + if(n < 2) return 1; + return fib(n-2) + fib(n-1); + } + public static void main(String[] args) { + Stream.generate(new Fibonacci()) + .limit(18) + .map(n -> n + " ") + .forEach(System.out::print); + } +} +/* Output: +1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 +2584 +*/ diff --git a/code/generics/FilledList.java b/code/generics/FilledList.java new file mode 100644 index 00000000..e24423ce --- /dev/null +++ b/code/generics/FilledList.java @@ -0,0 +1,28 @@ +// generics/FilledList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import onjava.*; + +public class FilledList extends ArrayList { + FilledList(Supplier gen, int size) { + Suppliers.fill(this, gen, size); + } + public FilledList(T t, int size) { + for(int i = 0; i < size; i++) + this.add(t); + } + public static void main(String[] args) { + List list = new FilledList<>("Hello", 4); + System.out.println(list); + // Supplier version: + List ilist = new FilledList<>(() -> 47, 4); + System.out.println(ilist); + } +} +/* Output: +[Hello, Hello, Hello, Hello] +[47, 47, 47, 47] +*/ diff --git a/code/generics/GenericArray.java b/code/generics/GenericArray.java new file mode 100644 index 00000000..f0ffba3d --- /dev/null +++ b/code/generics/GenericArray.java @@ -0,0 +1,32 @@ +// generics/GenericArray.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class GenericArray { + private T[] array; + @SuppressWarnings("unchecked") + public GenericArray(int sz) { + array = (T[])new Object[sz]; + } + public void put(int index, T item) { + array[index] = item; + } + public T get(int index) { return array[index]; } + // Method that exposes the underlying representation: + public T[] rep() { return array; } + public static void main(String[] args) { + GenericArray gai = new GenericArray<>(10); + try { + Integer[] ia = gai.rep(); + } catch(ClassCastException e) { + System.out.println(e.getMessage()); + } + // This is OK: + Object[] oa = gai.rep(); + } +} +/* Output: +[Ljava.lang.Object; cannot be cast to +[Ljava.lang.Integer; +*/ diff --git a/code/generics/GenericArray2.java b/code/generics/GenericArray2.java new file mode 100644 index 00000000..7ef4179e --- /dev/null +++ b/code/generics/GenericArray2.java @@ -0,0 +1,39 @@ +// generics/GenericArray2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class GenericArray2 { + private Object[] array; + public GenericArray2(int sz) { + array = new Object[sz]; + } + public void put(int index, T item) { + array[index] = item; + } + @SuppressWarnings("unchecked") + public T get(int index) { return (T)array[index]; } + @SuppressWarnings("unchecked") + public T[] rep() { + return (T[])array; // Unchecked cast + } + public static void main(String[] args) { + GenericArray2 gai = + new GenericArray2<>(10); + for(int i = 0; i < 10; i ++) + gai.put(i, i); + for(int i = 0; i < 10; i ++) + System.out.print(gai.get(i) + " "); + System.out.println(); + try { + Integer[] ia = gai.rep(); + } catch(Exception e) { + System.out.println(e); + } + } +} +/* Output: +0 1 2 3 4 5 6 7 8 9 +java.lang.ClassCastException: [Ljava.lang.Object; +cannot be cast to [Ljava.lang.Integer; +*/ diff --git a/code/generics/GenericArrayWithTypeToken.java b/code/generics/GenericArrayWithTypeToken.java new file mode 100644 index 00000000..6ea36a76 --- /dev/null +++ b/code/generics/GenericArrayWithTypeToken.java @@ -0,0 +1,27 @@ +// generics/GenericArrayWithTypeToken.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.reflect.*; + +public class GenericArrayWithTypeToken { + private T[] array; + @SuppressWarnings("unchecked") + public + GenericArrayWithTypeToken(Class type, int sz) { + array = (T[])Array.newInstance(type, sz); + } + public void put(int index, T item) { + array[index] = item; + } + public T get(int index) { return array[index]; } + // Expose the underlying representation: + public T[] rep() { return array; } + public static void main(String[] args) { + GenericArrayWithTypeToken gai = + new GenericArrayWithTypeToken<>( + Integer.class, 10); + // This now works: + Integer[] ia = gai.rep(); + } +} diff --git a/code/generics/GenericCast.java b/code/generics/GenericCast.java new file mode 100644 index 00000000..c3f82dac --- /dev/null +++ b/code/generics/GenericCast.java @@ -0,0 +1,47 @@ +// generics/GenericCast.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +class FixedSizeStack { + private final int size; + private Object[] storage; + private int index = 0; + FixedSizeStack(int size) { + this.size = size; + storage = new Object[size]; + } + public void push(T item) { + if(index < size) + storage[index++] = item; + } + @SuppressWarnings("unchecked") + public T pop() { + return index == 0 ? null : (T)storage[--index]; + } + @SuppressWarnings("unchecked") + Stream stream() { + return (Stream)Arrays.stream(storage); + } +} + +public class GenericCast { + static String[] letters = + "ABCDEFGHIJKLMNOPQRS".split(""); + public static void main(String[] args) { + FixedSizeStack strings = + new FixedSizeStack<>(letters.length); + Arrays.stream("ABCDEFGHIJKLMNOPQRS".split("")) + .forEach(strings::push); + System.out.println(strings.pop()); + strings.stream() + .map(s -> s + " ") + .forEach(System.out::print); + } +} +/* Output: +S +A B C D E F G H I J K L M N O P Q R S +*/ diff --git a/code/generics/GenericHolder.java b/code/generics/GenericHolder.java new file mode 100644 index 00000000..6d998a1c --- /dev/null +++ b/code/generics/GenericHolder.java @@ -0,0 +1,19 @@ +// generics/GenericHolder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class GenericHolder { + private T a; + public GenericHolder() {} + public void set(T a) { this.a = a; } + public T get() { return a; } + public static void main(String[] args) { + GenericHolder h3 = + new GenericHolder(); + h3.set(new Automobile()); // type checked + Automobile a = h3.get(); // No cast needed + //- h3.set("Not an Automobile"); // Error + //- h3.set(1); // Error + } +} diff --git a/code/generics/GenericHolder2.java b/code/generics/GenericHolder2.java new file mode 100644 index 00000000..9747f49b --- /dev/null +++ b/code/generics/GenericHolder2.java @@ -0,0 +1,16 @@ +// generics/GenericHolder2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class GenericHolder2 { + private T obj; + public void set(T obj) { this.obj = obj; } + public T get() { return obj; } + public static void main(String[] args) { + GenericHolder2 holder = + new GenericHolder2<>(); + holder.set("Item"); + String s = holder.get(); + } +} diff --git a/code/generics/GenericMethods.java b/code/generics/GenericMethods.java new file mode 100644 index 00000000..66f40e72 --- /dev/null +++ b/code/generics/GenericMethods.java @@ -0,0 +1,27 @@ +// generics/GenericMethods.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class GenericMethods { + public void f(T x) { + System.out.println(x.getClass().getName()); + } + public static void main(String[] args) { + GenericMethods gm = new GenericMethods(); + gm.f(""); + gm.f(1); + gm.f(1.0); + gm.f(1.0F); + gm.f('c'); + gm.f(gm); + } +} +/* Output: +java.lang.String +java.lang.Integer +java.lang.Double +java.lang.Float +java.lang.Character +GenericMethods +*/ diff --git a/code/generics/GenericReading.java b/code/generics/GenericReading.java new file mode 100644 index 00000000..5709c7a9 --- /dev/null +++ b/code/generics/GenericReading.java @@ -0,0 +1,46 @@ +// generics/GenericReading.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class GenericReading { + static List apples = + Arrays.asList(new Apple()); + static List fruit = Arrays.asList(new Fruit()); + static T readExact(List list) { + return list.get(0); + } + // A static method adapts to each call: + static void f1() { + Apple a = readExact(apples); + Fruit f = readExact(fruit); + f = readExact(apples); + } + // A class type is established + // when the class is instantiated: + static class Reader { + T readExact(List list) { return list.get(0); } + } + static void f2() { + Reader fruitReader = new Reader<>(); + Fruit f = fruitReader.readExact(fruit); + //- Fruit a = fruitReader.readExact(apples); + // error: incompatible types: List + // cannot be converted to List + } + static class CovariantReader { + T readCovariant(List list) { + return list.get(0); + } + } + static void f3() { + CovariantReader fruitReader = + new CovariantReader<>(); + Fruit f = fruitReader.readCovariant(fruit); + Fruit a = fruitReader.readCovariant(apples); + } + public static void main(String[] args) { + f1(); f2(); f3(); + } +} diff --git a/code/generics/GenericVarargs.java b/code/generics/GenericVarargs.java new file mode 100644 index 00000000..3a6e348c --- /dev/null +++ b/code/generics/GenericVarargs.java @@ -0,0 +1,30 @@ +// generics/GenericVarargs.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class GenericVarargs { + @SafeVarargs + public static List makeList(T... args) { + List result = new ArrayList<>(); + for(T item : args) + result.add(item); + return result; + } + public static void main(String[] args) { + List ls = makeList("A"); + System.out.println(ls); + ls = makeList("A", "B", "C"); + System.out.println(ls); + ls = makeList( + "ABCDEFFHIJKLMNOPQRSTUVWXYZ".split("")); + System.out.println(ls); + } +} +/* Output: +[A] +[A, B, C] +[A, B, C, D, E, F, F, H, I, J, K, L, M, N, O, P, Q, R, +S, T, U, V, W, X, Y, Z] +*/ diff --git a/code/generics/GenericsAndCovariance.java b/code/generics/GenericsAndCovariance.java new file mode 100644 index 00000000..f16b837b --- /dev/null +++ b/code/generics/GenericsAndCovariance.java @@ -0,0 +1,19 @@ +// generics/GenericsAndCovariance.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class GenericsAndCovariance { + public static void main(String[] args) { + // Wildcards allow covariance: + List flist = new ArrayList<>(); + // Compile Error: can't add any type of object: + // flist.add(new Apple()); + // flist.add(new Fruit()); + // flist.add(new Object()); + flist.add(null); // Legal but uninteresting + // We know it returns at least Fruit: + Fruit f = flist.get(0); + } +} diff --git a/code/generics/GenericsAndReturnTypes.java b/code/generics/GenericsAndReturnTypes.java new file mode 100644 index 00000000..de661864 --- /dev/null +++ b/code/generics/GenericsAndReturnTypes.java @@ -0,0 +1,17 @@ +// generics/GenericsAndReturnTypes.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface GenericGetter> { + T get(); +} + +interface Getter extends GenericGetter {} + +public class GenericsAndReturnTypes { + void test(Getter g) { + Getter result = g.get(); + GenericGetter gg = g.get(); // Also the base type + } +} diff --git a/code/generics/HasF.java b/code/generics/HasF.java new file mode 100644 index 00000000..f967386e --- /dev/null +++ b/code/generics/HasF.java @@ -0,0 +1,10 @@ +// generics/HasF.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class HasF { + public void f() { + System.out.println("HasF.f()"); + } +} diff --git a/code/generics/HijackedInterface.java b/code/generics/HijackedInterface.java new file mode 100644 index 00000000..868e1d46 --- /dev/null +++ b/code/generics/HijackedInterface.java @@ -0,0 +1,16 @@ +// generics/HijackedInterface.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} + +class Cat + extends ComparablePet implements Comparable{ + // error: Comparable cannot be inherited with + // different arguments: and + // class Cat + // ^ + // 1 error + + public int compareTo(Cat arg) { return 0; } +} diff --git a/code/generics/Holder.java b/code/generics/Holder.java new file mode 100644 index 00000000..e4301dc6 --- /dev/null +++ b/code/generics/Holder.java @@ -0,0 +1,42 @@ +// generics/Holder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.Objects; + +public class Holder { + private T value; + public Holder() {} + public Holder(T val) { value = val; } + public void set(T val) { value = val; } + public T get() { return value; } + @Override + public boolean equals(Object o) { + return o instanceof Holder && + Objects.equals(value, ((Holder)o).value); + } + @Override + public int hashCode() { + return Objects.hashCode(value); + } + public static void main(String[] args) { + Holder apple = new Holder<>(new Apple()); + Apple d = apple.get(); + apple.set(d); + // Holder Fruit = apple; // Cannot upcast + Holder fruit = apple; // OK + Fruit p = fruit.get(); + d = (Apple)fruit.get(); // Returns 'Object' + try { + Orange c = (Orange)fruit.get(); // No warning + } catch(Exception e) { System.out.println(e); } + // fruit.set(new Apple()); // Cannot call set() + // fruit.set(new Fruit()); // Cannot call set() + System.out.println(fruit.equals(d)); // OK + } +} +/* Output: +java.lang.ClassCastException: Apple cannot be cast to +Orange +false +*/ diff --git a/code/generics/Holder1.java b/code/generics/Holder1.java new file mode 100644 index 00000000..0c222cb5 --- /dev/null +++ b/code/generics/Holder1.java @@ -0,0 +1,12 @@ +// generics/Holder1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Automobile {} + +public class Holder1 { + private Automobile a; + public Holder1(Automobile a) { this.a = a; } + Automobile get() { return a; } +} diff --git a/code/generics/InheritBounds.java b/code/generics/InheritBounds.java new file mode 100644 index 00000000..fddd2543 --- /dev/null +++ b/code/generics/InheritBounds.java @@ -0,0 +1,40 @@ +// generics/InheritBounds.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class HoldItem { + T item; + HoldItem(T item) { this.item = item; } + T getItem() { return item; } +} + +class WithColor2 +extends HoldItem { + WithColor2(T item) { super(item); } + java.awt.Color color() { return item.getColor(); } +} + +class WithColorCoord2 +extends WithColor2 { + WithColorCoord2(T item) { super(item); } + int getX() { return item.x; } + int getY() { return item.y; } + int getZ() { return item.z; } +} + +class Solid2 +extends WithColorCoord2 { + Solid2(T item) { super(item); } + int weight() { return item.weight(); } +} + +public class InheritBounds { + public static void main(String[] args) { + Solid2 solid2 = + new Solid2<>(new Bounded()); + solid2.color(); + solid2.getY(); + solid2.weight(); + } +} diff --git a/code/generics/InstantiateGenericType.cpp b/code/generics/InstantiateGenericType.cpp new file mode 100644 index 00000000..1799d05b --- /dev/null +++ b/code/generics/InstantiateGenericType.cpp @@ -0,0 +1,20 @@ +// generics/InstantiateGenericType.cpp +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// C++, not Java! + +template class Foo { + T x; // Create a field of type T + T* y; // Pointer to T +public: + // Initialize the pointer: + Foo() { y = new T(); } +}; + +class Bar {}; + +int main() { + Foo fb; + Foo fi; // ... and it works with primitives +} diff --git a/code/generics/InstantiateGenericType.java b/code/generics/InstantiateGenericType.java new file mode 100644 index 00000000..9424c9a1 --- /dev/null +++ b/code/generics/InstantiateGenericType.java @@ -0,0 +1,46 @@ +// generics/InstantiateGenericType.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; +import java.lang.reflect.InvocationTargetException; + +class ClassAsFactory implements Supplier { + Class kind; + ClassAsFactory(Class kind) { + this.kind = kind; + } + @SuppressWarnings("deprecation") + @Override + public T get() { + try { + return kind.newInstance(); + } catch(Exception e) { + throw new RuntimeException(e); + } + } +} + +class Employee { + @Override + public String toString() { return "Employee"; } +} + +public class InstantiateGenericType { + public static void main(String[] args) { + ClassAsFactory fe = + new ClassAsFactory<>(Employee.class); + System.out.println(fe.get()); + ClassAsFactory fi = + new ClassAsFactory<>(Integer.class); + try { + System.out.println(fi.get()); + } catch(Exception e) { + System.out.println(e.getMessage()); + } + } +} +/* Output: +Employee +java.lang.InstantiationException: java.lang.Integer +*/ diff --git a/code/generics/IterableFibonacci.java b/code/generics/IterableFibonacci.java new file mode 100644 index 00000000..b5ccf285 --- /dev/null +++ b/code/generics/IterableFibonacci.java @@ -0,0 +1,36 @@ +// generics/IterableFibonacci.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Adapt the Fibonacci class to make it Iterable +import java.util.*; + +public class IterableFibonacci +extends Fibonacci implements Iterable { + private int n; + public IterableFibonacci(int count) { n = count; } + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { return n > 0; } + @Override + public Integer next() { + n--; + return IterableFibonacci.this.get(); + } + @Override + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + }; + } + public static void main(String[] args) { + for(int i : new IterableFibonacci(18)) + System.out.print(i + " "); + } +} +/* Output: +1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 +2584 +*/ diff --git a/code/generics/LatentReflection.java b/code/generics/LatentReflection.java new file mode 100644 index 00000000..0e9511a3 --- /dev/null +++ b/code/generics/LatentReflection.java @@ -0,0 +1,65 @@ +// generics/LatentReflection.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using reflection for latent typing +import java.lang.reflect.*; + +// Does not implement Performs: +class Mime { + public void walkAgainstTheWind() {} + public void sit() { + System.out.println("Pretending to sit"); + } + public void pushInvisibleWalls() {} + @Override + public String toString() { return "Mime"; } +} + +// Does not implement Performs: +class SmartDog { + public void speak() { System.out.println("Woof!"); } + public void sit() { System.out.println("Sitting"); } + public void reproduce() {} +} + +class CommunicateReflectively { + public static void perform(Object speaker) { + Class spkr = speaker.getClass(); + try { + try { + Method speak = spkr.getMethod("speak"); + speak.invoke(speaker); + } catch(NoSuchMethodException e) { + System.out.println(speaker + " cannot speak"); + } + try { + Method sit = spkr.getMethod("sit"); + sit.invoke(speaker); + } catch(NoSuchMethodException e) { + System.out.println(speaker + " cannot sit"); + } + } catch(SecurityException | + IllegalAccessException | + IllegalArgumentException | + InvocationTargetException e) { + throw new RuntimeException(speaker.toString(), e); + } + } +} + +public class LatentReflection { + public static void main(String[] args) { + CommunicateReflectively.perform(new SmartDog()); + CommunicateReflectively.perform(new Robot()); + CommunicateReflectively.perform(new Mime()); + } +} +/* Output: +Woof! +Sitting +Click! +Clank! +Mime cannot speak +Pretending to sit +*/ diff --git a/code/generics/LinkedStack.java b/code/generics/LinkedStack.java new file mode 100644 index 00000000..5142bcc7 --- /dev/null +++ b/code/generics/LinkedStack.java @@ -0,0 +1,43 @@ +// generics/LinkedStack.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A stack implemented with an internal linked structure + +public class LinkedStack { + private static class Node { + U item; + Node next; + Node() { item = null; next = null; } + Node(U item, Node next) { + this.item = item; + this.next = next; + } + boolean end() { + return item == null && next == null; + } + } + private Node top = new Node<>(); // End sentinel + public void push(T item) { + top = new Node<>(item, top); + } + public T pop() { + T result = top.item; + if(!top.end()) + top = top.next; + return result; + } + public static void main(String[] args) { + LinkedStack lss = new LinkedStack<>(); + for(String s : "Phasers on stun!".split(" ")) + lss.push(s); + String s; + while((s = lss.pop()) != null) + System.out.println(s); + } +} +/* Output: +stun! +on +Phasers +*/ diff --git a/code/generics/ListMaker.java b/code/generics/ListMaker.java new file mode 100644 index 00000000..582cbaea --- /dev/null +++ b/code/generics/ListMaker.java @@ -0,0 +1,13 @@ +// generics/ListMaker.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ListMaker { + List create() { return new ArrayList<>(); } + public static void main(String[] args) { + ListMaker stringMaker = new ListMaker<>(); + List stringList = stringMaker.create(); + } +} diff --git a/code/generics/ListOfGenerics.java b/code/generics/ListOfGenerics.java new file mode 100644 index 00000000..10a48031 --- /dev/null +++ b/code/generics/ListOfGenerics.java @@ -0,0 +1,11 @@ +// generics/ListOfGenerics.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ListOfGenerics { + private List array = new ArrayList<>(); + public void add(T item) { array.add(item); } + public T get(int index) { return array.get(index); } +} diff --git a/code/generics/ListOfInt.java b/code/generics/ListOfInt.java new file mode 100644 index 00000000..f8ac8e11 --- /dev/null +++ b/code/generics/ListOfInt.java @@ -0,0 +1,20 @@ +// generics/ListOfInt.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Autoboxing compensates for the inability +// to use primitives in generics +import java.util.*; +import java.util.stream.*; + +public class ListOfInt { + public static void main(String[] args) { + List li = IntStream.range(38, 48) + .boxed() // Converts ints to Integers + .collect(Collectors.toList()); + System.out.println(li); + } +} +/* Output: +[38, 39, 40, 41, 42, 43, 44, 45, 46, 47] +*/ diff --git a/code/generics/LostInformation.java b/code/generics/LostInformation.java new file mode 100644 index 00000000..e27430d2 --- /dev/null +++ b/code/generics/LostInformation.java @@ -0,0 +1,33 @@ +// generics/LostInformation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class Frob {} +class Fnorkle {} +class Quark {} +class Particle {} + +public class LostInformation { + public static void main(String[] args) { + List list = new ArrayList<>(); + Map map = new HashMap<>(); + Quark quark = new Quark<>(); + Particle p = new Particle<>(); + System.out.println(Arrays.toString( + list.getClass().getTypeParameters())); + System.out.println(Arrays.toString( + map.getClass().getTypeParameters())); + System.out.println(Arrays.toString( + quark.getClass().getTypeParameters())); + System.out.println(Arrays.toString( + p.getClass().getTypeParameters())); + } +} +/* Output: +[E] +[K, V] +[Q] +[POSITION, MOMENTUM] +*/ diff --git a/code/generics/Manipulation.java b/code/generics/Manipulation.java new file mode 100644 index 00000000..f365cf19 --- /dev/null +++ b/code/generics/Manipulation.java @@ -0,0 +1,21 @@ +// generics/Manipulation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} + +class Manipulator { + private T obj; + Manipulator(T x) { obj = x; } + // Error: cannot find symbol: method f(): + public void manipulate() { obj.f(); } +} + +public class Manipulation { + public static void main(String[] args) { + HasF hf = new HasF(); + Manipulator manipulator = + new Manipulator<>(hf); + manipulator.manipulate(); + } +} diff --git a/code/generics/Manipulator2.java b/code/generics/Manipulator2.java new file mode 100644 index 00000000..7c7c648b --- /dev/null +++ b/code/generics/Manipulator2.java @@ -0,0 +1,10 @@ +// generics/Manipulator2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Manipulator2 { + private T obj; + Manipulator2(T x) { obj = x; } + public void manipulate() { obj.f(); } +} diff --git a/code/generics/Manipulator3.java b/code/generics/Manipulator3.java new file mode 100644 index 00000000..2201d474 --- /dev/null +++ b/code/generics/Manipulator3.java @@ -0,0 +1,10 @@ +// generics/Manipulator3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Manipulator3 { + private HasF obj; + Manipulator3(HasF x) { obj = x; } + public void manipulate() { obj.f(); } +} diff --git a/code/generics/Mixins.cpp b/code/generics/Mixins.cpp new file mode 100644 index 00000000..89949d46 --- /dev/null +++ b/code/generics/Mixins.cpp @@ -0,0 +1,47 @@ +// generics/Mixins.cpp +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +#include +#include +#include +using namespace std; + +template class TimeStamped : public T { + long timeStamp; +public: + TimeStamped() { timeStamp = time(0); } + long getStamp() { return timeStamp; } +}; + +template class SerialNumbered : public T { + long serialNumber; + static long counter; +public: + SerialNumbered() { serialNumber = counter++; } + long getSerialNumber() { return serialNumber; } +}; + +// Define and initialize the static storage: +template long SerialNumbered::counter = 1; + +class Basic { + string value; +public: + void set(string val) { value = val; } + string get() { return value; } +}; + +int main() { + TimeStamped> mixin1, mixin2; + mixin1.set("test string 1"); + mixin2.set("test string 2"); + cout << mixin1.get() << " " << mixin1.getStamp() << + " " << mixin1.getSerialNumber() << endl; + cout << mixin2.get() << " " << mixin2.getStamp() << + " " << mixin2.getSerialNumber() << endl; +} +/* Output: +test string 1 1452987605 1 +test string 2 1452987605 2 +*/ diff --git a/code/generics/Mixins.java b/code/generics/Mixins.java new file mode 100644 index 00000000..af58b81e --- /dev/null +++ b/code/generics/Mixins.java @@ -0,0 +1,71 @@ +// generics/Mixins.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +interface TimeStamped { long getStamp(); } + +class TimeStampedImp implements TimeStamped { + private final long timeStamp; + TimeStampedImp() { + timeStamp = new Date().getTime(); + } + @Override + public long getStamp() { return timeStamp; } +} + +interface SerialNumbered { long getSerialNumber(); } + +class SerialNumberedImp implements SerialNumbered { + private static long counter = 1; + private final long serialNumber = counter++; + @Override + public long getSerialNumber() { return serialNumber; } +} + +interface Basic { + void set(String val); + String get(); +} + +class BasicImp implements Basic { + private String value; + @Override + public void set(String val) { value = val; } + @Override + public String get() { return value; } +} + +class Mixin extends BasicImp +implements TimeStamped, SerialNumbered { + private TimeStamped timeStamp = new TimeStampedImp(); + private SerialNumbered serialNumber = + new SerialNumberedImp(); + @Override + public long getStamp() { + return timeStamp.getStamp(); + } + @Override + public long getSerialNumber() { + return serialNumber.getSerialNumber(); + } +} + +public class Mixins { + public static void main(String[] args) { + Mixin mixin1 = new Mixin(), mixin2 = new Mixin(); + mixin1.set("test string 1"); + mixin2.set("test string 2"); + System.out.println(mixin1.get() + " " + + mixin1.getStamp() + " " + + mixin1.getSerialNumber()); + System.out.println(mixin2.get() + " " + + mixin2.getStamp() + " " + + mixin2.getSerialNumber()); + } +} +/* Output: +test string 1 1494331663026 1 +test string 2 1494331663027 2 +*/ diff --git a/code/generics/MultipleInterfaceVariants.java b/code/generics/MultipleInterfaceVariants.java new file mode 100644 index 00000000..70a535a2 --- /dev/null +++ b/code/generics/MultipleInterfaceVariants.java @@ -0,0 +1,13 @@ +// generics/MultipleInterfaceVariants.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +package generics; + +interface Payable {} + +class Employee implements Payable {} + +class Hourly extends Employee +implements Payable {} diff --git a/code/generics/NeedCasting.java b/code/generics/NeedCasting.java new file mode 100644 index 00000000..8801f5d8 --- /dev/null +++ b/code/generics/NeedCasting.java @@ -0,0 +1,15 @@ +// generics/NeedCasting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.util.*; + +public class NeedCasting { + @SuppressWarnings("unchecked") + public void f(String[] args) throws Exception { + ObjectInputStream in = new ObjectInputStream( + new FileInputStream(args[0])); + List shapes = (List)in.readObject(); + } +} diff --git a/code/generics/NonCovariantGenerics.java b/code/generics/NonCovariantGenerics.java new file mode 100644 index 00000000..c219a0d3 --- /dev/null +++ b/code/generics/NonCovariantGenerics.java @@ -0,0 +1,11 @@ +// generics/NonCovariantGenerics.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +import java.util.*; + +public class NonCovariantGenerics { + // Compile Error: incompatible types: + List flist = new ArrayList(); +} diff --git a/code/generics/NotSelfBounded.java b/code/generics/NotSelfBounded.java new file mode 100644 index 00000000..76aa593c --- /dev/null +++ b/code/generics/NotSelfBounded.java @@ -0,0 +1,24 @@ +// generics/NotSelfBounded.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class NotSelfBounded { + T element; + NotSelfBounded set(T arg) { + element = arg; + return this; + } + T get() { return element; } +} + +class A2 extends NotSelfBounded {} +class B2 extends NotSelfBounded {} + +class C2 extends NotSelfBounded { + C2 setAndGet(C2 arg) { set(arg); return get(); } +} + +class D2 {} +// Now this is OK: +class E2 extends NotSelfBounded {} diff --git a/code/generics/ObjectHolder.java b/code/generics/ObjectHolder.java new file mode 100644 index 00000000..f1dafd30 --- /dev/null +++ b/code/generics/ObjectHolder.java @@ -0,0 +1,20 @@ +// generics/ObjectHolder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ObjectHolder { + private Object a; + public ObjectHolder(Object a) { this.a = a; } + public void set(Object a) { this.a = a; } + public Object get() { return a; } + public static void main(String[] args) { + ObjectHolder h2 = + new ObjectHolder(new Automobile()); + Automobile a = (Automobile)h2.get(); + h2.set("Not an Automobile"); + String s = (String)h2.get(); + h2.set(1); // Autoboxes to Integer + Integer x = (Integer)h2.get(); + } +} diff --git a/code/generics/OrdinaryArguments.java b/code/generics/OrdinaryArguments.java new file mode 100644 index 00000000..6e50550d --- /dev/null +++ b/code/generics/OrdinaryArguments.java @@ -0,0 +1,31 @@ +// generics/OrdinaryArguments.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class OrdinarySetter { + void set(Base base) { + System.out.println("OrdinarySetter.set(Base)"); + } +} + +class DerivedSetter extends OrdinarySetter { + void set(Derived derived) { + System.out.println("DerivedSetter.set(Derived)"); + } +} + +public class OrdinaryArguments { + public static void main(String[] args) { + Base base = new Base(); + Derived derived = new Derived(); + DerivedSetter ds = new DerivedSetter(); + ds.set(derived); + // Compiles--overloaded, not overridden!: + ds.set(base); + } +} +/* Output: +DerivedSetter.set(Derived) +OrdinarySetter.set(Base) +*/ diff --git a/code/generics/Performs.java b/code/generics/Performs.java new file mode 100644 index 00000000..ace09523 --- /dev/null +++ b/code/generics/Performs.java @@ -0,0 +1,9 @@ +// generics/Performs.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public interface Performs { + void speak(); + void sit(); +} diff --git a/code/generics/PlainGenericInheritance.java b/code/generics/PlainGenericInheritance.java new file mode 100644 index 00000000..93eb61c6 --- /dev/null +++ b/code/generics/PlainGenericInheritance.java @@ -0,0 +1,30 @@ +// generics/PlainGenericInheritance.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class GenericSetter { // Not self-bounded + void set(T arg) { + System.out.println("GenericSetter.set(Base)"); + } +} + +class DerivedGS extends GenericSetter { + void set(Derived derived) { + System.out.println("DerivedGS.set(Derived)"); + } +} + +public class PlainGenericInheritance { + public static void main(String[] args) { + Base base = new Base(); + Derived derived = new Derived(); + DerivedGS dgs = new DerivedGS(); + dgs.set(derived); + dgs.set(base); // Overloaded, not overridden! + } +} +/* Output: +DerivedGS.set(Derived) +GenericSetter.set(Base) +*/ diff --git a/code/generics/PrimitiveGenericTest.java b/code/generics/PrimitiveGenericTest.java new file mode 100644 index 00000000..79356437 --- /dev/null +++ b/code/generics/PrimitiveGenericTest.java @@ -0,0 +1,42 @@ +// generics/PrimitiveGenericTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; +import java.util.*; +import java.util.function.*; + +// Fill an array using a generator: +interface FillArray { + static T[] fill(T[] a, Supplier gen) { + Arrays.setAll(a, n -> gen.get()); + return a; + } + static int[] fill(int[] a, IntSupplier gen) { + Arrays.setAll(a, n -> gen.getAsInt()); + return a; + } + static long[] fill(long[] a, LongSupplier gen) { + Arrays.setAll(a, n -> gen.getAsLong()); + return a; + } + static double[] fill(double[] a, DoubleSupplier gen) { + Arrays.setAll(a, n -> gen.getAsDouble()); + return a; + } +} + +public class PrimitiveGenericTest { + public static void main(String[] args) { + String[] strings = FillArray.fill( + new String[5], new Rand.String(9)); + System.out.println(Arrays.toString(strings)); + int[] integers = FillArray.fill( + new int[9], new Rand.Pint()); + System.out.println(Arrays.toString(integers)); + } +} +/* Output: +[btpenpccu, xszgvgmei, nneeloztd, vewcippcy, gpoalkljl] +[635, 8737, 3941, 4720, 6177, 8479, 6656, 3768, 4948] +*/ diff --git a/code/generics/RandomList.java b/code/generics/RandomList.java new file mode 100644 index 00000000..d4f198bc --- /dev/null +++ b/code/generics/RandomList.java @@ -0,0 +1,26 @@ +// generics/RandomList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class RandomList extends ArrayList { + private Random rand = new Random(47); + public T select() { + return get(rand.nextInt(size())); + } + public static void main(String[] args) { + RandomList rs = new RandomList<>(); + Arrays.stream( + ("The quick brown fox jumped over " + + "the lazy brown dog").split(" ")) + .forEach(rs::add); + IntStream.range(0, 11).forEach(i -> + System.out.print(rs.select() + " ")); + } +} +/* Output: +brown over fox quick quick dog brown The brown lazy +brown +*/ diff --git a/code/generics/RestrictedComparablePets.java b/code/generics/RestrictedComparablePets.java new file mode 100644 index 00000000..16146d7b --- /dev/null +++ b/code/generics/RestrictedComparablePets.java @@ -0,0 +1,19 @@ +// generics/RestrictedComparablePets.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Hamster extends ComparablePet +implements Comparable { + public int compareTo(ComparablePet arg) { + return 0; + } +} + +// Or just: + +class Gecko extends ComparablePet { + public int compareTo(ComparablePet arg) { + return 0; + } +} diff --git a/code/generics/ReturnGenericType.java b/code/generics/ReturnGenericType.java new file mode 100644 index 00000000..bf46ae15 --- /dev/null +++ b/code/generics/ReturnGenericType.java @@ -0,0 +1,10 @@ +// generics/ReturnGenericType.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class ReturnGenericType { + private T obj; + ReturnGenericType(T x) { obj = x; } + public T get() { return obj; } +} diff --git a/code/generics/SelfBounding.java b/code/generics/SelfBounding.java new file mode 100644 index 00000000..c8ecf0ff --- /dev/null +++ b/code/generics/SelfBounding.java @@ -0,0 +1,40 @@ +// generics/SelfBounding.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class SelfBounded> { + T element; + SelfBounded set(T arg) { + element = arg; + return this; + } + T get() { return element; } +} + +class A extends SelfBounded {} +class B extends SelfBounded {} // Also OK + +class C extends SelfBounded { + C setAndGet(C arg) { set(arg); return get(); } +} + +class D {} +// Can't do this: +// class E extends SelfBounded {} +// Compile error: +// Type parameter D is not within its bound + +// Alas, you can do this, so you cannot force the idiom: +class F extends SelfBounded {} + +public class SelfBounding { + public static void main(String[] args) { + A a = new A(); + a.set(new A()); + a = a.set(new A()).get(); + a = a.get(); + C c = new C(); + c = c.setAndGet(new C()); + } +} diff --git a/code/generics/SelfBoundingAndCovariantArguments.java b/code/generics/SelfBoundingAndCovariantArguments.java new file mode 100644 index 00000000..34262b0e --- /dev/null +++ b/code/generics/SelfBoundingAndCovariantArguments.java @@ -0,0 +1,31 @@ +// generics/SelfBoundingAndCovariantArguments.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface +SelfBoundSetter> { + void set(T arg); +} + +interface Setter extends SelfBoundSetter {} + +public class SelfBoundingAndCovariantArguments { + void + testA(Setter s1, Setter s2, SelfBoundSetter sbs) { + s1.set(s2); + //- s1.set(sbs); + // error: method set in interface SelfBoundSetter + // cannot be applied to given types; + // s1.set(sbs); + // ^ + // required: Setter + // found: SelfBoundSetter + // reason: argument mismatch; + // SelfBoundSetter cannot be converted to Setter + // where T is a type-variable: + // T extends SelfBoundSetter declared in + // interface SelfBoundSetter + // 1 error + } +} diff --git a/code/generics/SelfBoundingMethods.java b/code/generics/SelfBoundingMethods.java new file mode 100644 index 00000000..e6cb7949 --- /dev/null +++ b/code/generics/SelfBoundingMethods.java @@ -0,0 +1,13 @@ +// generics/SelfBoundingMethods.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SelfBoundingMethods { + static > T f(T arg) { + return arg.set(arg).get(); + } + public static void main(String[] args) { + A a = f(new A()); + } +} diff --git a/code/generics/Shape.java b/code/generics/Shape.java new file mode 100644 index 00000000..dd2458c2 --- /dev/null +++ b/code/generics/Shape.java @@ -0,0 +1,19 @@ +// generics/Shape.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Shape { + private static long counter = 0; + private final long id = counter++; + @Override + public String toString() { + return getClass().getSimpleName() + " " + id; + } + public void rotate() { + System.out.println(this + " rotate"); + } + public void resize(int newSize) { + System.out.println(this + " resize " + newSize); + } +} diff --git a/code/generics/SimpleDogsAndRobots.java b/code/generics/SimpleDogsAndRobots.java new file mode 100644 index 00000000..b9cee77b --- /dev/null +++ b/code/generics/SimpleDogsAndRobots.java @@ -0,0 +1,25 @@ +// generics/SimpleDogsAndRobots.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Removing the generic; code still works + +class CommunicateSimply { + static void perform(Performs performer) { + performer.speak(); + performer.sit(); + } +} + +public class SimpleDogsAndRobots { + public static void main(String[] args) { + CommunicateSimply.perform(new PerformingDog()); + CommunicateSimply.perform(new Robot()); + } +} +/* Output: +Woof! +Sitting +Click! +Clank! +*/ diff --git a/code/generics/SimpleHolder.java b/code/generics/SimpleHolder.java new file mode 100644 index 00000000..a73af0ab --- /dev/null +++ b/code/generics/SimpleHolder.java @@ -0,0 +1,15 @@ +// generics/SimpleHolder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SimpleHolder { + private Object obj; + public void set(Object obj) { this.obj = obj; } + public Object get() { return obj; } + public static void main(String[] args) { + SimpleHolder holder = new SimpleHolder(); + holder.set("Item"); + String s = (String)holder.get(); + } +} diff --git a/code/generics/SimpleQueue.java b/code/generics/SimpleQueue.java new file mode 100644 index 00000000..76fb4f3e --- /dev/null +++ b/code/generics/SimpleQueue.java @@ -0,0 +1,16 @@ +// generics/SimpleQueue.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A different kind of Iterable collection +import java.util.*; + +public class SimpleQueue implements Iterable { + private LinkedList storage = new LinkedList<>(); + public void add(T t) { storage.offer(t); } + public T get() { return storage.poll(); } + @Override + public Iterator iterator() { + return storage.iterator(); + } +} diff --git a/code/generics/Square.java b/code/generics/Square.java new file mode 100644 index 00000000..e3bcad93 --- /dev/null +++ b/code/generics/Square.java @@ -0,0 +1,5 @@ +// generics/Square.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class Square extends Shape {} diff --git a/code/generics/Store.java b/code/generics/Store.java new file mode 100644 index 00000000..c165926a --- /dev/null +++ b/code/generics/Store.java @@ -0,0 +1,90 @@ +// generics/Store.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Building a complex model using generic collections +import java.util.*; +import java.util.function.*; +import onjava.*; + +class Product { + private final int id; + private String description; + private double price; + Product(int idNumber, String descr, double price) { + id = idNumber; + description = descr; + this.price = price; + System.out.println(toString()); + } + @Override + public String toString() { + return id + ": " + description + + ", price: $" + price; + } + public void priceChange(double change) { + price += change; + } + public static Supplier generator = + new Supplier() { + private Random rand = new Random(47); + @Override + public Product get() { + return new Product(rand.nextInt(1000), "Test", + Math.round( + rand.nextDouble() * 1000.0) + 0.99); + } + }; +} + +class Shelf extends ArrayList { + Shelf(int nProducts) { + Suppliers.fill(this, Product.generator, nProducts); + } +} + +class Aisle extends ArrayList { + Aisle(int nShelves, int nProducts) { + for(int i = 0; i < nShelves; i++) + add(new Shelf(nProducts)); + } +} + +class CheckoutStand {} +class Office {} + +public class Store extends ArrayList { + private ArrayList checkouts = + new ArrayList<>(); + private Office office = new Office(); + public Store( + int nAisles, int nShelves, int nProducts) { + for(int i = 0; i < nAisles; i++) + add(new Aisle(nShelves, nProducts)); + } + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for(Aisle a : this) + for(Shelf s : a) + for(Product p : s) { + result.append(p); + result.append("\n"); + } + return result.toString(); + } + public static void main(String[] args) { + System.out.println(new Store(5, 4, 3)); + } +} +/* Output: (First 8 Lines) +258: Test, price: $400.99 +861: Test, price: $160.99 +868: Test, price: $417.99 +207: Test, price: $268.99 +551: Test, price: $114.99 +278: Test, price: $804.99 +520: Test, price: $554.99 +140: Test, price: $530.99 + ... +*/ diff --git a/code/generics/SuperTypeWildcards.java b/code/generics/SuperTypeWildcards.java new file mode 100644 index 00000000..f8672a4f --- /dev/null +++ b/code/generics/SuperTypeWildcards.java @@ -0,0 +1,13 @@ +// generics/SuperTypeWildcards.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SuperTypeWildcards { + static void writeTo(List apples) { + apples.add(new Apple()); + apples.add(new Jonathan()); + // apples.add(new Fruit()); // Error + } +} diff --git a/code/generics/Templates.cpp b/code/generics/Templates.cpp new file mode 100644 index 00000000..ab2a3b64 --- /dev/null +++ b/code/generics/Templates.cpp @@ -0,0 +1,27 @@ +// generics/Templates.cpp +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +#include +using namespace std; + +template class Manipulator { + T obj; +public: + Manipulator(T x) { obj = x; } + void manipulate() { obj.f(); } +}; + +class HasF { +public: + void f() { cout << "HasF::f()" << endl; } +}; + +int main() { + HasF hf; + Manipulator manipulator(hf); + manipulator.manipulate(); +} +/* Output: +HasF::f() +*/ diff --git a/code/generics/ThrowGenericException.java b/code/generics/ThrowGenericException.java new file mode 100644 index 00000000..994c7f88 --- /dev/null +++ b/code/generics/ThrowGenericException.java @@ -0,0 +1,82 @@ +// generics/ThrowGenericException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +interface Processor { + void process(List resultCollector) throws E; +} + +class ProcessRunner +extends ArrayList> { + List processAll() throws E { + List resultCollector = new ArrayList<>(); + for(Processor processor : this) + processor.process(resultCollector); + return resultCollector; + } +} + +class Failure1 extends Exception {} + +class Processor1 +implements Processor { + static int count = 3; + @Override + public void process(List resultCollector) + throws Failure1 { + if(count-- > 1) + resultCollector.add("Hep!"); + else + resultCollector.add("Ho!"); + if(count < 0) + throw new Failure1(); + } +} + +class Failure2 extends Exception {} + +class Processor2 +implements Processor { + static int count = 2; + @Override + public void process(List resultCollector) + throws Failure2 { + if(count-- == 0) + resultCollector.add(47); + else { + resultCollector.add(11); + } + if(count < 0) + throw new Failure2(); + } +} + +public class ThrowGenericException { + public static void main(String[] args) { + ProcessRunner runner = + new ProcessRunner<>(); + for(int i = 0; i < 3; i++) + runner.add(new Processor1()); + try { + System.out.println(runner.processAll()); + } catch(Failure1 e) { + System.out.println(e); + } + + ProcessRunner runner2 = + new ProcessRunner<>(); + for(int i = 0; i < 3; i++) + runner2.add(new Processor2()); + try { + System.out.println(runner2.processAll()); + } catch(Failure2 e) { + System.out.println(e); + } + } +} +/* Output: +[Hep!, Hep!, Ho!] +Failure2 +*/ diff --git a/code/generics/TupleList.java b/code/generics/TupleList.java new file mode 100644 index 00000000..fe93330b --- /dev/null +++ b/code/generics/TupleList.java @@ -0,0 +1,23 @@ +// generics/TupleList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Combining generic types to make complex generic types +import java.util.*; +import onjava.*; +import java.util.stream.*; + +public class TupleList +extends ArrayList> { + public static void main(String[] args) { + TupleList tl = + new TupleList<>(); + tl.add(TupleTest2.h()); + tl.add(TupleTest2.h()); + tl.forEach(System.out::println); + } +} +/* Output: +(Vehicle@7cca494b, Amphibian@7ba4f24f, hi, 47) +(Vehicle@3b9a45b3, Amphibian@7699a589, hi, 47) +*/ diff --git a/code/generics/TupleTest.java b/code/generics/TupleTest.java new file mode 100644 index 00000000..e207da40 --- /dev/null +++ b/code/generics/TupleTest.java @@ -0,0 +1,42 @@ +// generics/TupleTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; + +public class TupleTest { + static Tuple2 f() { + // Autoboxing converts the int to Integer: + return new Tuple2<>("hi", 47); + } + static Tuple3 g() { + return new Tuple3<>(new Amphibian(), "hi", 47); + } + static + Tuple4 h() { + return + new Tuple4<>( + new Vehicle(), new Amphibian(), "hi", 47); + } + static + Tuple5 k() { + return new + Tuple5<>( + new Vehicle(), new Amphibian(), "hi", 47, 11.1); + } + public static void main(String[] args) { + Tuple2 ttsi = f(); + System.out.println(ttsi); + // ttsi.a1 = "there"; // Compile error: final + System.out.println(g()); + System.out.println(h()); + System.out.println(k()); + } +} +/* Output: +(hi, 47) +(Amphibian@1540e19d, hi, 47) +(Vehicle@7f31245a, Amphibian@6d6f6e28, hi, 47) +(Vehicle@330bedb4, Amphibian@2503dbd3, hi, 47, 11.1) +*/ diff --git a/code/generics/TupleTest2.java b/code/generics/TupleTest2.java new file mode 100644 index 00000000..3a0c8d14 --- /dev/null +++ b/code/generics/TupleTest2.java @@ -0,0 +1,42 @@ +// generics/TupleTest2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; +import static onjava.Tuple.*; + +public class TupleTest2 { + static Tuple2 f() { + return tuple("hi", 47); + } + static Tuple2 f2() { return tuple("hi", 47); } + static Tuple3 g() { + return tuple(new Amphibian(), "hi", 47); + } + static + Tuple4 h() { + return tuple( + new Vehicle(), new Amphibian(), "hi", 47); + } + static + Tuple5 k() { + return tuple(new Vehicle(), new Amphibian(), + "hi", 47, 11.1); + } + public static void main(String[] args) { + Tuple2 ttsi = f(); + System.out.println(ttsi); + System.out.println(f2()); + System.out.println(g()); + System.out.println(h()); + System.out.println(k()); + } +} +/* Output: +(hi, 47) +(hi, 47) +(Amphibian@14ae5a5, hi, 47) +(Vehicle@135fbaa4, Amphibian@45ee12a7, hi, 47) +(Vehicle@4b67cf4d, Amphibian@7ea987ac, hi, 47, 11.1) +*/ diff --git a/code/generics/UnboundedWildcards1.java b/code/generics/UnboundedWildcards1.java new file mode 100644 index 00000000..6b163a4c --- /dev/null +++ b/code/generics/UnboundedWildcards1.java @@ -0,0 +1,58 @@ +// generics/UnboundedWildcards1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class UnboundedWildcards1 { + static List list1; + static List list2; + static List list3; + static void assign1(List list) { + list1 = list; + list2 = list; + //- list3 = list; + // warning: [unchecked] unchecked conversion + // list3 = list; + // ^ + // required: List + // found: List + } + static void assign2(List list) { + list1 = list; + list2 = list; + list3 = list; + } + static void assign3(List list) { + list1 = list; + list2 = list; + list3 = list; + } + public static void main(String[] args) { + assign1(new ArrayList()); + assign2(new ArrayList()); + //- assign3(new ArrayList()); + // warning: [unchecked] unchecked method invocation: + // method assign3 in class UnboundedWildcards1 + // is applied to given types + // assign3(new ArrayList()); + // ^ + // required: List + // found: ArrayList + // warning: [unchecked] unchecked conversion + // assign3(new ArrayList()); + // ^ + // required: List + // found: ArrayList + // 2 warnings + assign1(new ArrayList<>()); + assign2(new ArrayList<>()); + assign3(new ArrayList<>()); + // Both forms are acceptable as List: + List wildList = new ArrayList(); + wildList = new ArrayList<>(); + assign1(wildList); + assign2(wildList); + assign3(wildList); + } +} diff --git a/code/generics/UnboundedWildcards2.java b/code/generics/UnboundedWildcards2.java new file mode 100644 index 00000000..ee80d555 --- /dev/null +++ b/code/generics/UnboundedWildcards2.java @@ -0,0 +1,35 @@ +// generics/UnboundedWildcards2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class UnboundedWildcards2 { + static Map map1; + static Map map2; + static Map map3; + static void assign1(Map map) { map1 = map; } + static void assign2(Map map) { map2 = map; } + static void assign3(Map map) { map3 = map; } + public static void main(String[] args) { + assign1(new HashMap()); + assign2(new HashMap()); + //- assign3(new HashMap()); + // warning: [unchecked] unchecked method invocation: + // method assign3 in class UnboundedWildcards2 + // is applied to given types + // assign3(new HashMap()); + // ^ + // required: Map + // found: HashMap + // warning: [unchecked] unchecked conversion + // assign3(new HashMap()); + // ^ + // required: Map + // found: HashMap + // 2 warnings + assign1(new HashMap<>()); + assign2(new HashMap<>()); + assign3(new HashMap<>()); + } +} diff --git a/code/generics/Unconstrained.java b/code/generics/Unconstrained.java new file mode 100644 index 00000000..f683d53f --- /dev/null +++ b/code/generics/Unconstrained.java @@ -0,0 +1,20 @@ +// generics/Unconstrained.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Other {} +class BasicOther extends BasicHolder {} + +public class Unconstrained { + public static void main(String[] args) { + BasicOther b = new BasicOther(); + BasicOther b2 = new BasicOther(); + b.set(new Other()); + Other other = b.get(); + b.f(); + } +} +/* Output: +Other +*/ diff --git a/code/generics/UseList.java b/code/generics/UseList.java new file mode 100644 index 00000000..924d3b56 --- /dev/null +++ b/code/generics/UseList.java @@ -0,0 +1,11 @@ +// generics/UseList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +import java.util.*; + +public class UseList { + void f(List v) {} + void f(List v) {} +} diff --git a/code/generics/UseList2.java b/code/generics/UseList2.java new file mode 100644 index 00000000..83d3b5d3 --- /dev/null +++ b/code/generics/UseList2.java @@ -0,0 +1,10 @@ +// generics/UseList2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class UseList2 { + void f1(List v) {} + void f2(List v) {} +} diff --git a/code/generics/Vehicle.java b/code/generics/Vehicle.java new file mode 100644 index 00000000..301a84e4 --- /dev/null +++ b/code/generics/Vehicle.java @@ -0,0 +1,5 @@ +// generics/Vehicle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class Vehicle {} diff --git a/code/generics/WatercolorSets.java b/code/generics/WatercolorSets.java new file mode 100644 index 00000000..7956778d --- /dev/null +++ b/code/generics/WatercolorSets.java @@ -0,0 +1,54 @@ +// generics/WatercolorSets.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import generics.watercolors.*; +import java.util.*; +import static onjava.Sets.*; +import static generics.watercolors.Watercolors.*; + +public class WatercolorSets { + public static void main(String[] args) { + Set set1 = + EnumSet.range(BRILLIANT_RED, VIRIDIAN_HUE); + Set set2 = + EnumSet.range(CERULEAN_BLUE_HUE, BURNT_UMBER); + System.out.println("set1: " + set1); + System.out.println("set2: " + set2); + System.out.println( + "union(set1, set2): " + union(set1, set2)); + Set subset = intersection(set1, set2); + System.out.println( + "intersection(set1, set2): " + subset); + System.out.println("difference(set1, subset): " + + difference(set1, subset)); + System.out.println("difference(set2, subset): " + + difference(set2, subset)); + System.out.println("complement(set1, set2): " + + complement(set1, set2)); + } +} +/* Output: +set1: [BRILLIANT_RED, CRIMSON, MAGENTA, ROSE_MADDER, +VIOLET, CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, +COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE] +set2: [CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, +COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE, +SAP_GREEN, YELLOW_OCHRE, BURNT_SIENNA, RAW_UMBER, +BURNT_UMBER] +union(set1, set2): [BURNT_SIENNA, BRILLIANT_RED, +YELLOW_OCHRE, MAGENTA, SAP_GREEN, CERULEAN_BLUE_HUE, +ULTRAMARINE, VIRIDIAN_HUE, VIOLET, RAW_UMBER, +ROSE_MADDER, PERMANENT_GREEN, BURNT_UMBER, +PHTHALO_BLUE, CRIMSON, COBALT_BLUE_HUE] +intersection(set1, set2): [PERMANENT_GREEN, +CERULEAN_BLUE_HUE, ULTRAMARINE, VIRIDIAN_HUE, +PHTHALO_BLUE, COBALT_BLUE_HUE] +difference(set1, subset): [BRILLIANT_RED, MAGENTA, +VIOLET, CRIMSON, ROSE_MADDER] +difference(set2, subset): [BURNT_SIENNA, YELLOW_OCHRE, +BURNT_UMBER, SAP_GREEN, RAW_UMBER] +complement(set1, set2): [BURNT_SIENNA, BRILLIANT_RED, +YELLOW_OCHRE, MAGENTA, SAP_GREEN, VIOLET, RAW_UMBER, +ROSE_MADDER, BURNT_UMBER, CRIMSON] +*/ diff --git a/code/generics/Wildcards.java b/code/generics/Wildcards.java new file mode 100644 index 00000000..65348ecb --- /dev/null +++ b/code/generics/Wildcards.java @@ -0,0 +1,285 @@ +// generics/Wildcards.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Exploring the meaning of wildcards + +public class Wildcards { + // Raw argument: + static void rawArgs(Holder holder, Object arg) { + //- holder.set(arg); + // warning: [unchecked] unchecked call to set(T) + // as a member of the raw type Holder + // holder.set(arg); + // ^ + // where T is a type-variable: + // T extends Object declared in class Holder + // 1 warning + + // Can't do this; don't have any 'T': + // T t = holder.get(); + + // OK, but type information is lost: + Object obj = holder.get(); + } + // Like rawArgs(), but errors instead of warnings: + static void + unboundedArg(Holder holder, Object arg) { + //- holder.set(arg); + // error: method set in class Holder + // cannot be applied to given types; + // holder.set(arg); + // ^ + // required: CAP#1 + // found: Object + // reason: argument mismatch; + // Object cannot be converted to CAP#1 + // where T is a type-variable: + // T extends Object declared in class Holder + // where CAP#1 is a fresh type-variable: + // CAP#1 extends Object from capture of ? + // 1 error + + // Can't do this; don't have any 'T': + // T t = holder.get(); + + // OK, but type information is lost: + Object obj = holder.get(); + } + static T exact1(Holder holder) { + return holder.get(); + } + static T exact2(Holder holder, T arg) { + holder.set(arg); + return holder.get(); + } + static + T wildSubtype(Holder holder, T arg) { + //- holder.set(arg); + // error: method set in class Holder + // cannot be applied to given types; + // holder.set(arg); + // ^ + // required: CAP#1 + // found: T#1 + // reason: argument mismatch; + // T#1 cannot be converted to CAP#1 + // where T#1,T#2 are type-variables: + // T#1 extends Object declared in method + // wildSubtype(Holder,T#1) + // T#2 extends Object declared in class Holder + // where CAP#1 is a fresh type-variable: + // CAP#1 extends T#1 from + // capture of ? extends T#1 + // 1 error + + return holder.get(); + } + static + void wildSupertype(Holder holder, T arg) { + holder.set(arg); + //- T t = holder.get(); + // error: incompatible types: + // CAP#1 cannot be converted to T + // T t = holder.get(); + // ^ + // where T is a type-variable: + // T extends Object declared in method + // wildSupertype(Holder,T) + // where CAP#1 is a fresh type-variable: + // CAP#1 extends Object super: + // T from capture of ? super T + // 1 error + + // OK, but type information is lost: + Object obj = holder.get(); + } + public static void main(String[] args) { + Holder raw = new Holder<>(); + // Or: + raw = new Holder(); + Holder qualified = new Holder<>(); + Holder unbounded = new Holder<>(); + Holder bounded = new Holder<>(); + Long lng = 1L; + + rawArgs(raw, lng); + rawArgs(qualified, lng); + rawArgs(unbounded, lng); + rawArgs(bounded, lng); + + unboundedArg(raw, lng); + unboundedArg(qualified, lng); + unboundedArg(unbounded, lng); + unboundedArg(bounded, lng); + + //- Object r1 = exact1(raw); + // warning: [unchecked] unchecked method invocation: + // method exact1 in class Wildcards is applied + // to given types + // Object r1 = exact1(raw); + // ^ + // required: Holder + // found: Holder + // where T is a type-variable: + // T extends Object declared in + // method exact1(Holder) + // warning: [unchecked] unchecked conversion + // Object r1 = exact1(raw); + // ^ + // required: Holder + // found: Holder + // where T is a type-variable: + // T extends Object declared in + // method exact1(Holder) + // 2 warnings + + Long r2 = exact1(qualified); + Object r3 = exact1(unbounded); // Must return Object + Long r4 = exact1(bounded); + + //- Long r5 = exact2(raw, lng); + // warning: [unchecked] unchecked method invocation: + // method exact2 in class Wildcards is + // applied to given types + // Long r5 = exact2(raw, lng); + // ^ + // required: Holder,T + // found: Holder,Long + // where T is a type-variable: + // T extends Object declared in + // method exact2(Holder,T) + // warning: [unchecked] unchecked conversion + // Long r5 = exact2(raw, lng); + // ^ + // required: Holder + // found: Holder + // where T is a type-variable: + // T extends Object declared in + // method exact2(Holder,T) + // 2 warnings + + Long r6 = exact2(qualified, lng); + + //- Long r7 = exact2(unbounded, lng); + // error: method exact2 in class Wildcards + // cannot be applied to given types; + // Long r7 = exact2(unbounded, lng); + // ^ + // required: Holder,T + // found: Holder,Long + // reason: inference variable T has + // incompatible bounds + // equality constraints: CAP#1 + // lower bounds: Long + // where T is a type-variable: + // T extends Object declared in + // method exact2(Holder,T) + // where CAP#1 is a fresh type-variable: + // CAP#1 extends Object from capture of ? + // 1 error + + //- Long r8 = exact2(bounded, lng); + // error: method exact2 in class Wildcards + // cannot be applied to given types; + // Long r8 = exact2(bounded, lng); + // ^ + // required: Holder,T + // found: Holder,Long + // reason: inference variable T + // has incompatible bounds + // equality constraints: CAP#1 + // lower bounds: Long + // where T is a type-variable: + // T extends Object declared in + // method exact2(Holder,T) + // where CAP#1 is a fresh type-variable: + // CAP#1 extends Long from + // capture of ? extends Long + // 1 error + + //- Long r9 = wildSubtype(raw, lng); + // warning: [unchecked] unchecked method invocation: + // method wildSubtype in class Wildcards + // is applied to given types + // Long r9 = wildSubtype(raw, lng); + // ^ + // required: Holder,T + // found: Holder,Long + // where T is a type-variable: + // T extends Object declared in + // method wildSubtype(Holder,T) + // warning: [unchecked] unchecked conversion + // Long r9 = wildSubtype(raw, lng); + // ^ + // required: Holder + // found: Holder + // where T is a type-variable: + // T extends Object declared in + // method wildSubtype(Holder,T) + // 2 warnings + + Long r10 = wildSubtype(qualified, lng); + // OK, but can only return Object: + Object r11 = wildSubtype(unbounded, lng); + Long r12 = wildSubtype(bounded, lng); + + //- wildSupertype(raw, lng); + // warning: [unchecked] unchecked method invocation: + // method wildSupertype in class Wildcards + // is applied to given types + // wildSupertype(raw, lng); + // ^ + // required: Holder,T + // found: Holder,Long + // where T is a type-variable: + // T extends Object declared in + // method wildSupertype(Holder,T) + // warning: [unchecked] unchecked conversion + // wildSupertype(raw, lng); + // ^ + // required: Holder + // found: Holder + // where T is a type-variable: + // T extends Object declared in + // method wildSupertype(Holder,T) + // 2 warnings + + wildSupertype(qualified, lng); + + //- wildSupertype(unbounded, lng); + // error: method wildSupertype in class Wildcards + // cannot be applied to given types; + // wildSupertype(unbounded, lng); + // ^ + // required: Holder,T + // found: Holder,Long + // reason: cannot infer type-variable(s) T + // (argument mismatch; Holder + // cannot be converted to Holder) + // where T is a type-variable: + // T extends Object declared in + // method wildSupertype(Holder,T) + // where CAP#1 is a fresh type-variable: + // CAP#1 extends Object from capture of ? + // 1 error + + //- wildSupertype(bounded, lng); + // error: method wildSupertype in class Wildcards + // cannot be applied to given types; + // wildSupertype(bounded, lng); + // ^ + // required: Holder,T + // found: Holder,Long + // reason: cannot infer type-variable(s) T + // (argument mismatch; Holder + // cannot be converted to Holder) + // where T is a type-variable: + // T extends Object declared in + // method wildSupertype(Holder,T) + // where CAP#1 is a fresh type-variable: + // CAP#1 extends Long from capture of + // ? extends Long + // 1 error + } +} diff --git a/code/generics/coffee/Americano.java b/code/generics/coffee/Americano.java new file mode 100644 index 00000000..96cd4a1f --- /dev/null +++ b/code/generics/coffee/Americano.java @@ -0,0 +1,6 @@ +// generics/coffee/Americano.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package generics.coffee; +public class Americano extends Coffee {} diff --git a/code/generics/coffee/Breve.java b/code/generics/coffee/Breve.java new file mode 100644 index 00000000..329c406b --- /dev/null +++ b/code/generics/coffee/Breve.java @@ -0,0 +1,6 @@ +// generics/coffee/Breve.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package generics.coffee; +public class Breve extends Coffee {} diff --git a/code/generics/coffee/Cappuccino.java b/code/generics/coffee/Cappuccino.java new file mode 100644 index 00000000..3ce89b50 --- /dev/null +++ b/code/generics/coffee/Cappuccino.java @@ -0,0 +1,6 @@ +// generics/coffee/Cappuccino.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package generics.coffee; +public class Cappuccino extends Coffee {} diff --git a/code/generics/coffee/Coffee.java b/code/generics/coffee/Coffee.java new file mode 100644 index 00000000..c90d88c1 --- /dev/null +++ b/code/generics/coffee/Coffee.java @@ -0,0 +1,14 @@ +// generics/coffee/Coffee.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package generics.coffee; + +public class Coffee { + private static long counter = 0; + private final long id = counter++; + @Override + public String toString() { + return getClass().getSimpleName() + " " + id; + } +} diff --git a/code/generics/coffee/CoffeeSupplier.java b/code/generics/coffee/CoffeeSupplier.java new file mode 100644 index 00000000..fe5dced8 --- /dev/null +++ b/code/generics/coffee/CoffeeSupplier.java @@ -0,0 +1,72 @@ +// generics/coffee/CoffeeSupplier.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java generics.coffee.CoffeeSupplier} +package generics.coffee; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import java.lang.reflect.InvocationTargetException; + +public class CoffeeSupplier +implements Supplier, Iterable { + private Class[] types = { Latte.class, Mocha.class, + Cappuccino.class, Americano.class, Breve.class, }; + private static Random rand = new Random(47); + public CoffeeSupplier() {} + // For iteration: + private int size = 0; + public CoffeeSupplier(int sz) { size = sz; } + @Override + public Coffee get() { + try { + return (Coffee) + types[rand.nextInt(types.length)] + .getConstructor().newInstance(); + // Report programmer errors at run time: + } catch(InstantiationException | + NoSuchMethodException | + InvocationTargetException | + IllegalAccessException e) { + throw new RuntimeException(e); + } + } + class CoffeeIterator implements Iterator { + int count = size; + @Override + public boolean hasNext() { return count > 0; } + @Override + public Coffee next() { + count--; + return CoffeeSupplier.this.get(); + } + @Override + public void remove() { // Not implemented + throw new UnsupportedOperationException(); + } + } + @Override + public Iterator iterator() { + return new CoffeeIterator(); + } + public static void main(String[] args) { + Stream.generate(new CoffeeSupplier()) + .limit(5) + .forEach(System.out::println); + for(Coffee c : new CoffeeSupplier(5)) + System.out.println(c); + } +} +/* Output: +Americano 0 +Latte 1 +Americano 2 +Mocha 3 +Mocha 4 +Breve 5 +Americano 6 +Latte 7 +Cappuccino 8 +Cappuccino 9 +*/ diff --git a/code/generics/coffee/Latte.java b/code/generics/coffee/Latte.java new file mode 100644 index 00000000..d735cc87 --- /dev/null +++ b/code/generics/coffee/Latte.java @@ -0,0 +1,6 @@ +// generics/coffee/Latte.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package generics.coffee; +public class Latte extends Coffee {} diff --git a/code/generics/coffee/Mocha.java b/code/generics/coffee/Mocha.java new file mode 100644 index 00000000..cc567be1 --- /dev/null +++ b/code/generics/coffee/Mocha.java @@ -0,0 +1,6 @@ +// generics/coffee/Mocha.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package generics.coffee; +public class Mocha extends Coffee {} diff --git a/code/generics/decorator/Decoration.java b/code/generics/decorator/Decoration.java new file mode 100644 index 00000000..96611a75 --- /dev/null +++ b/code/generics/decorator/Decoration.java @@ -0,0 +1,51 @@ +// generics/decorator/Decoration.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java generics.decorator.Decoration} +package generics.decorator; +import java.util.*; + +class Basic { + private String value; + public void set(String val) { value = val; } + public String get() { return value; } +} + +class Decorator extends Basic { + protected Basic basic; + Decorator(Basic basic) { this.basic = basic; } + @Override + public void set(String val) { basic.set(val); } + @Override + public String get() { return basic.get(); } +} + +class TimeStamped extends Decorator { + private final long timeStamp; + TimeStamped(Basic basic) { + super(basic); + timeStamp = new Date().getTime(); + } + public long getStamp() { return timeStamp; } +} + +class SerialNumbered extends Decorator { + private static long counter = 1; + private final long serialNumber = counter++; + SerialNumbered(Basic basic) { super(basic); } + public long getSerialNumber() { return serialNumber; } +} + +public class Decoration { + public static void main(String[] args) { + TimeStamped t = new TimeStamped(new Basic()); + TimeStamped t2 = new TimeStamped( + new SerialNumbered(new Basic())); + //- t2.getSerialNumber(); // Not available + SerialNumbered s = new SerialNumbered(new Basic()); + SerialNumbered s2 = new SerialNumbered( + new TimeStamped(new Basic())); + //- s2.getStamp(); // Not available + } +} diff --git a/code/generics/dogsandrobots.go b/code/generics/dogsandrobots.go new file mode 100644 index 00000000..f65b9c18 --- /dev/null +++ b/code/generics/dogsandrobots.go @@ -0,0 +1,32 @@ +// generics/dogsandrobots.go +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package main +import "fmt" + +type Dog struct {} +func (this Dog) speak() { fmt.Printf("Arf!\n")} +func (this Dog) sit() { fmt.Printf("Sitting\n")} +func (this Dog) reproduce() {} + +type Robot struct {} +func (this Robot) speak() { fmt.Printf("Click!\n") } +func (this Robot) sit() { fmt.Printf("Clank!\n") } +func (this Robot) oilChange() {} + +func perform(speaker interface { speak(); sit() }) { + speaker.speak(); + speaker.sit(); +} + +func main() { + perform(Dog{}) + perform(Robot{}) +} +/* Output: +Arf! +Sitting +Click! +Clank! +*/ diff --git a/code/generics/watercolors/Watercolors.java b/code/generics/watercolors/Watercolors.java new file mode 100644 index 00000000..0625e532 --- /dev/null +++ b/code/generics/watercolors/Watercolors.java @@ -0,0 +1,15 @@ +// generics/watercolors/Watercolors.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package generics.watercolors; + +public enum Watercolors { + ZINC, LEMON_YELLOW, MEDIUM_YELLOW, DEEP_YELLOW, + ORANGE, BRILLIANT_RED, CRIMSON, MAGENTA, + ROSE_MADDER, VIOLET, CERULEAN_BLUE_HUE, + PHTHALO_BLUE, ULTRAMARINE, COBALT_BLUE_HUE, + PERMANENT_GREEN, VIRIDIAN_HUE, SAP_GREEN, + YELLOW_OCHRE, BURNT_SIENNA, RAW_UMBER, + BURNT_UMBER, PAYNES_GRAY, IVORY_BLACK +} diff --git a/code/gradle.properties b/code/gradle.properties new file mode 100644 index 00000000..f97ebb7d --- /dev/null +++ b/code/gradle.properties @@ -0,0 +1 @@ +org.gradle.parallel=true diff --git a/code/gradle/checkstyle.gradle b/code/gradle/checkstyle.gradle new file mode 100644 index 00000000..0f0e6086 --- /dev/null +++ b/code/gradle/checkstyle.gradle @@ -0,0 +1,14 @@ +apply plugin: 'checkstyle' + +checkstyle { + ignoreFailures = true + configFile = new File(rootProject.projectDir, 'checkstyle.xml') + sourceSets = [sourceSets.main] +} + +tasks.withType(Checkstyle) { + reports { + xml.enabled = false + html.enabled = true + } +} diff --git a/code/gradle/findbugs.gradle b/code/gradle/findbugs.gradle new file mode 100644 index 00000000..ac628cb2 --- /dev/null +++ b/code/gradle/findbugs.gradle @@ -0,0 +1,15 @@ +/* +apply plugin: 'findbugs' + +findbugs { + ignoreFailures = true + sourceSets = [sourceSets.main] +} + +tasks.withType(FindBugs) { + reports { + xml.enabled = false + html.enabled = true + } +} +*/ diff --git a/code/gradle/java.gradle b/code/gradle/java.gradle new file mode 100644 index 00000000..eadc4ef9 --- /dev/null +++ b/code/gradle/java.gradle @@ -0,0 +1,39 @@ +apply plugin: 'java' + +sourceCompatibility = '1.8' +targetCompatibility = '1.8' + +compileJava { + options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" +} + +sourceSets { + main { + java { + srcDir projectDir + exclude "tests/**" + } + resources { + srcDir projectDir + include '*.xml' + } + } + + test { + java { + srcDir file("tests") + } + } +} + +repositories { + jcenter() +} + +dependencies { + // Logging: + compile 'org.slf4j:slf4j-api:1.7.21' + compile 'ch.qos.logback:logback-classic:1.1.7' + // You can also use the JDK's built-in logging as the back end: + // compile group: 'org.slf4j:slf4j-jdk14:1.7.21' +} \ No newline at end of file diff --git a/code/gradle/jmh.gradle b/code/gradle/jmh.gradle new file mode 100644 index 00000000..ce61db4b --- /dev/null +++ b/code/gradle/jmh.gradle @@ -0,0 +1,17 @@ +apply plugin: 'me.champeau.gradle.jmh' + +sourceSets { + jmh { + java { + srcDir projectDir + } + } +} + +jmh { + jmhVersion = '1.17.4' + duplicateClassesStrategy = 'warn' + failOnError = true + // See https://github.com/melix/jmh-gradle-plugin + // for other options +} diff --git a/code/gradle/junit-jupiter.gradle b/code/gradle/junit-jupiter.gradle new file mode 100644 index 00000000..98a77843 --- /dev/null +++ b/code/gradle/junit-jupiter.gradle @@ -0,0 +1,72 @@ +import org.apache.tools.ant.util.TeeOutputStream + +dependencies { + testImplementation(platform('org.junit:junit-bom:5.7.0')) + testImplementation('org.junit.jupiter:junit-jupiter') +} + +test { + useJUnitPlatform() + testLogging { + events "passed", "skipped", "failed" + } +} + +/* NEW: (REQUIRES CODE REWRITES IN BOOK AND TEST CODE) +-> http://junit.org/junit5/docs/current/user-guide/ + +ext { + junitJupiterVersion = '5.0.0-M3' +} + +dependencies { + testCompile "org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}" + testRuntime "org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}" +} + + +junitPlatform { + platformVersion '1.0.0-M3' + + filters { + packages { + exclude 'collectiontopics.jmh' + } + includeClassNamePattern '.*' + } +} +*/ + +/* Store test output in $projectName/tests + JUnit 5's junitPlatformTest runs as a "javaExec" rather than a "test", + so we can't hook into the before/after test behavior. +*/ +tasks.findByPath(":$name:test").configure { + File testDir = file("tests") + if(testDir.exists()) { + File outFile = new File(testDir, 'report.txt') + + Writer taskOutput + + doFirst { + taskOutput = project.file(outFile).newWriter() + } + + testLogging.showStandardStreams = true + + onOutput { descriptor, event -> + taskOutput.append(event.message) + } + + doLast { + // WARNING: if the task fails, this won't be executed and the file remains open. + // The memory cache version doesn't have this problem. + taskOutput.close() + + if(outFile.size() == 0) + outFile.delete() + else if(outFile.text.contains("0 tests found")) + outFile.delete() + } + } +} diff --git a/code/gradle/subprojects.gradle b/code/gradle/subprojects.gradle new file mode 100644 index 00000000..e9d857d8 --- /dev/null +++ b/code/gradle/subprojects.gradle @@ -0,0 +1,67 @@ +project(':validating') { + jmh { + include = 'validating.jmh.*' + } +} + +project(':equalshashcode') { + dependencies { + compile project(':typeinfo') + compile project(':collections') + } +} + +project(':lowlevel') { + dependencies { + compile project(':enums') + } +} + +project(':strings') { + dependencies { + compile project(':generics') + } +} + +project(':serialization') { + configurations.all { + resolutionStrategy { + force 'xml-apis:xml-apis:1.0.b2' + } + } + dependencies { + compile 'com.io7m.xom:xom:1.2.10' + } +} + +project(':interfaces') { + dependencies { + compile project(':polymorphism') + } +} + +project(':hiding') { + dependencies { + compile project(':com') + } +} + +project(':generics') { + dependencies { + compile project(':typeinfo') + } +} + +project(':collections') { + dependencies { + compile project(':typeinfo') + } +} + +configure(subprojects - project(':onjava')) { + dependencies { + compile project(':onjava') + compile 'com.google.guava:guava:21.0' + compileOnly "org.openjdk.jmh:jmh-core:${jmh.jmhVersion}" + } +} diff --git a/code/gradle/wrapper/gradle-wrapper.jar b/code/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f GIT binary patch literal 59203 zcma&O1CT9Y(k9%tZQHhO+qUh#ZQHhO+qmuS+qP|E@9xZO?0h@l{(r>DQ>P;GjjD{w zH}lENr;dU&FbEU?00aa80D$0M0RRB{U*7-#kbjS|qAG&4l5%47zyJ#WrfA#1$1Ctx zf&Z_d{GW=lf^w2#qRJ|CvSJUi(^E3iv~=^Z(zH}F)3Z%V3`@+rNB7gTVU{Bb~90p|f+0(v;nz01EG7yDMX9@S~__vVgv%rS$+?IH+oZ03D5zYrv|^ zC1J)SruYHmCki$jLBlTaE5&dFG9-kq3!^i>^UQL`%gn6)jz54$WDmeYdsBE9;PqZ_ zoGd=P4+|(-u4U1dbAVQrFWoNgNd;0nrghPFbQrJctO>nwDdI`Q^i0XJDUYm|T|RWc zZ3^Qgo_Qk$%Fvjj-G}1NB#ZJqIkh;kX%V{THPqOyiq)d)0+(r9o(qKlSp*hmK#iIY zA^)Vr$-Hz<#SF=0@tL@;dCQsm`V9s1vYNq}K1B)!XSK?=I1)tX+bUV52$YQu*0%fnWEukW>mxkz+%3-S!oguE8u#MGzST8_Dy^#U?fA@S#K$S@9msUiX!gd_ow>08w5)nX{-KxqMOo7d?k2&?Vf z&diGDtZr(0cwPe9z9FAUSD9KC)7(n^lMWuayCfxzy8EZsns%OEblHFSzP=cL6}?J| z0U$H!4S_TVjj<`6dy^2j`V`)mC;cB%* z8{>_%E1^FH!*{>4a7*C1v>~1*@TMcLK{7nEQ!_igZC}ikJ$*<$yHy>7)oy79A~#xE zWavoJOIOC$5b6*q*F_qN1>2#MY)AXVyr$6x4b=$x^*aqF*L?vmj>Mgv+|ITnw_BoW zO?jwHvNy^prH{9$rrik1#fhyU^MpFqF2fYEt(;4`Q&XWOGDH8k6M=%@fics4ajI;st# zCU^r1CK&|jzUhRMv;+W~6N;u<;#DI6cCw-otsc@IsN3MoSD^O`eNflIoR~l4*&-%RBYk@gb^|-JXs&~KuSEmMxB}xSb z@K76cXD=Y|=I&SNC2E+>Zg?R6E%DGCH5J1nU!A|@eX9oS(WPaMm==k2s_ueCqdZw| z&hqHp)47`c{BgwgvY2{xz%OIkY1xDwkw!<0veB#yF4ZKJyabhyyVS`gZepcFIk%e2 zTcrmt2@-8`7i-@5Nz>oQWFuMC_KlroCl(PLSodswHqJ3fn<;gxg9=}~3x_L3P`9Sn zChIf}8vCHvTriz~T2~FamRi?rh?>3bX1j}%bLH+uFX+p&+^aXbOK7clZxdU~6Uxgy z8R=obwO4dL%pmVo*Ktf=lH6hnlz_5k3cG;m8lgaPp~?eD!Yn2kf)tU6PF{kLyn|oI@eQ`F z3IF7~Blqg8-uwUuWZScRKn%c2_}dXB6Dx_&xR*n9M9LXasJhtZdr$vBY!rP{c@=)& z#!?L$2UrkvClwQO>U*fSMs67oSj2mxiJ$t;E|>q%Kh_GzzWWO&3;ufU%2z%ucBU8H z3WIwr$n)cfCXR&>tyB7BcSInK>=ByZA%;cVEJhcg<#6N{aZC4>K41XF>ZgjG`z_u& zGY?;Ad?-sgiOnI`oppF1o1Gurqbi*;#x2>+SSV6|1^G@ooVy@fg?wyf@0Y!UZ4!}nGuLeC^l)6pwkh|oRY`s1Pm$>zZ3u-83T|9 zGaKJIV3_x+u1>cRibsaJpJqhcm%?0-L;2 zitBrdRxNmb0OO2J%Y&Ym(6*`_P3&&5Bw157{o7LFguvxC$4&zTy#U=W*l&(Q2MNO} zfaUwYm{XtILD$3864IA_nn34oVa_g^FRuHL5wdUd)+W-p-iWCKe8m_cMHk+=? zeKX)M?Dt(|{r5t7IenkAXo%&EXIb-i^w+0CX0D=xApC=|Xy(`xy+QG^UyFe z+#J6h_&T5i#sV)hj3D4WN%z;2+jJcZxcI3*CHXGmOF3^)JD5j&wfX)e?-|V0GPuA+ zQFot%aEqGNJJHn$!_}#PaAvQ^{3-Ye7b}rWwrUmX53(|~i0v{}G_sI9uDch_brX&6 zWl5Ndj-AYg(W9CGfQf<6!YmY>Ey)+uYd_JNXH=>|`OH-CDCmcH(0%iD_aLlNHKH z7bcW-^5+QV$jK?R*)wZ>r9t}loM@XN&M-Pw=F#xn(;u3!(3SXXY^@=aoj70;_=QE9 zGghsG3ekq#N||u{4We_25U=y#T*S{4I{++Ku)> zQ!DZW;pVcn>b;&g2;YE#+V`v*Bl&Y-i@X6D*OpNA{G@JAXho&aOk(_j^weW{#3X5Y z%$q_wpb07EYPdmyH(1^09i$ca{O<}7) zRWncXdSPgBE%BM#by!E>tdnc$8RwUJg1*x($6$}ae$e9Knj8gvVZe#bLi!<+&BkFj zg@nOpDneyc+hU9P-;jmOSMN|*H#>^Ez#?;%C3hg_65leSUm;iz)UkW)jX#p)e&S&M z1|a?wDzV5NVnlhRBCd_;F87wp>6c<&nkgvC+!@KGiIqWY4l}=&1w7|r6{oBN8xyzh zG$b#2=RJp_iq6)#t5%yLkKx(0@D=C3w+oiXtSuaQ%I1WIb-eiE$d~!)b@|4XLy!CZ z9p=t=%3ad@Ep+<9003D2KZ5VyP~_n$=;~r&YUg5UZ0KVD&tR1DHy9x)qWtKJp#Kq# zP*8p#W(8JJ_*h_3W}FlvRam?<4Z+-H77^$Lvi+#vmhL9J zJ<1SV45xi;SrO2f=-OB(7#iNA5)x1uNC-yNxUw|!00vcW2PufRm>e~toH;M0Q85MQLWd?3O{i8H+5VkR@l9Dg-ma ze2fZ%>G(u5(k9EHj2L6!;(KZ8%8|*-1V|B#EagbF(rc+5iL_5;Eu)L4Z-V;0HfK4d z*{utLse_rvHZeQ>V5H=f78M3Ntg1BPxFCVD{HbNA6?9*^YIq;B-DJd{Ca2L#)qWP? zvX^NhFmX?CTWw&Ns}lgs;r3i+Bq@y}Ul+U%pzOS0Fcv9~aB(0!>GT0)NO?p=25LjN z2bh>6RhgqD7bQj#k-KOm@JLgMa6>%-ok1WpOe)FS^XOU{c?d5shG(lIn3GiVBxmg`u%-j=)^v&pX1JecJics3&jvPI)mDut52? z3jEA)DM%}BYbxxKrizVYwq?(P&19EXlwD9^-6J+4!}9{ywR9Gk42jjAURAF&EO|~N z)?s>$Da@ikI4|^z0e{r`J8zIs>SpM~Vn^{3fArRu;?+43>lD+^XtUcY1HidJwnR6+ z!;oG2=B6Z_=M%*{z-RaHc(n|1RTKQdNjjV!Pn9lFt^4w|AeN06*j}ZyhqZ^!-=cyGP_ShV1rGxkx8t zB;8`h!S{LD%ot``700d0@Grql(DTt4Awgmi+Yr0@#jbe=2#UkK%rv=OLqF)9D7D1j z!~McAwMYkeaL$~kI~90)5vBhBzWYc3Cj1WI0RS`z000R8-@ET0dA~*r(gSiCJmQMN&4%1D zyVNf0?}sBH8zNbBLn>~(W{d3%@kL_eQ6jEcR{l>C|JK z(R-fA!z|TTRG40|zv}7E@PqCAXP3n`;%|SCQ|ZS%ym$I{`}t3KPL&^l5`3>yah4*6 zifO#{VNz3)?ZL$be;NEaAk9b#{tV?V7 zP|wf5YA*1;s<)9A4~l3BHzG&HH`1xNr#%){4xZ!jq%o=7nN*wMuXlFV{HaiQLJ`5G zBhDi#D(m`Q1pLh@Tq+L;OwuC52RdW7b8}~60WCOK5iYMUad9}7aWBuILb({5=z~YF zt?*Jr5NG+WadM{mDL>GyiByCuR)hd zA=HM?J6l1Xv0Dl+LW@w$OTcEoOda^nFCw*Sy^I@$sSuneMl{4ys)|RY#9&NxW4S)9 zq|%83IpslTLoz~&vTo!Ga@?rj_kw{|k{nv+w&Ku?fyk4Ki4I?);M|5Axm)t+BaE)D zm(`AQ#k^DWrjbuXoJf2{Aj^KT zFb1zMSqxq|vceV+Mf-)$oPflsO$@*A0n0Z!R{&(xh8s}=;t(lIy zv$S8x>m;vQNHuRzoaOo?eiWFe{0;$s`Bc+Osz~}Van${u;g(su`3lJ^TEfo~nERfP z)?aFzpDgnLYiERsKPu|0tq4l2wT)Atr6Qb%m-AUn6HnCue*yWICp7TjW$@sO zm5rm4aTcPQ(rfi7a`xP7cKCFrJD}*&_~xgLyr^-bmsL}y;A5P|al8J3WUoBSjqu%v zxC;mK!g(7r6RRJ852Z~feoC&sD3(6}^5-uLK8o)9{8L_%%rItZK9C){UxB|;G>JbP zsRRtS4-3B*5c+K2kvmgZK8472%l>3cntWUOVHxB|{Ay~aOg5RN;{PJgeVD*H%ac+y!h#wi%o2bF2Ca8IyMyH{>4#{E_8u^@+l-+n=V}Sq?$O z{091@v%Bd*3pk0^2UtiF9Z+(a@wy6 zUdw8J*ze$K#=$48IBi1U%;hmhO>lu!uU;+RS}p&6@rQila7WftH->*A4=5W|Fmtze z)7E}jh@cbmr9iup^i%*(uF%LG&!+Fyl@LFA-}Ca#bxRfDJAiR2dt6644TaYw1Ma79 zt8&DYj31j^5WPNf5P&{)J?WlCe@<3u^78wnd(Ja4^a>{^Tw}W>|Cjt^If|7l^l)^Q zbz|7~CF(k_9~n|h;ysZ+jHzkXf(*O*@5m zLzUmbHp=x!Q|!9NVXyipZ3)^GuIG$k;D)EK!a5=8MFLI_lpf`HPKl=-Ww%z8H_0$j ztJ||IfFG1lE9nmQ0+jPQy zCBdKkjArH@K7jVcMNz);Q(Q^R{d5G?-kk;Uu_IXSyWB)~KGIizZL(^&qF;|1PI7!E zTP`%l)gpX|OFn&)M%txpQ2F!hdA~hX1Cm5)IrdljqzRg!f{mN%G~H1&oqe`5eJCIF zHdD7O;AX-{XEV(a`gBFJ9ews#CVS2y!&>Cm_dm3C8*n3MA*e67(WC?uP@8TXuMroq z{#w$%z@CBIkRM7?}Xib+>hRjy?%G!fiw8! z8(gB+8J~KOU}yO7UGm&1g_MDJ$IXS!`+*b*QW2x)9>K~Y*E&bYMnjl6h!{17_8d!%&9D`a7r&LKZjC<&XOvTRaKJ1 zUY@hl5^R&kZl3lU3njk`3dPzxj$2foOL26r(9zsVF3n_F#v)s5vv3@dgs|lP#eylq62{<-vczqP!RpVBTgI>@O6&sU>W|do17+#OzQ7o5A$ICH z?GqwqnK^n2%LR;$^oZM;)+>$X3s2n}2jZ7CdWIW0lnGK-b#EG01)P@aU`pg}th&J-TrU`tIpb5t((0eu|!u zQz+3ZiOQ^?RxxK4;zs=l8q!-n7X{@jSwK(iqNFiRColuEOg}!7cyZi`iBX4g1pNBj zAPzL?P^Ljhn;1$r8?bc=#n|Ed7wB&oHcw()&*k#SS#h}jO?ZB246EGItsz*;^&tzp zu^YJ0=lwsi`eP_pU8}6JA7MS;9pfD;DsSsLo~ogzMNP70@@;Fm8f0^;>$Z>~}GWRw!W5J3tNX*^2+1f3hz{~rIzJo z6W%J(H!g-eI_J1>0juX$X4Cl6i+3wbc~k146UIX&G22}WE>0ga#WLsn9tY(&29zBvH1$`iWtTe zG2jYl@P!P)eb<5DsR72BdI7-zP&cZNI{7q3e@?N8IKc4DE#UVr->|-ryuJXk^u^>4 z$3wE~=q390;XuOQP~TNoDR?#|NSPJ%sTMInA6*rJ%go|=YjGe!B>z6u$IhgQSwoV* zjy3F2#I>uK{42{&IqP59)Y(1*Z>>#W8rCf4_eVsH)`v!P#^;BgzKDR`ARGEZzkNX+ zJUQu=*-ol=Xqqt5=`=pA@BIn@6a9G8C{c&`i^(i+BxQO9?YZ3iu%$$da&Kb?2kCCo zo7t$UpSFWqmydXf@l3bVJ=%K?SSw)|?srhJ-1ZdFu*5QhL$~-IQS!K1s@XzAtv6*Y zl8@(5BlWYLt1yAWy?rMD&bwze8bC3-GfNH=p zynNFCdxyX?K&G(ZZ)afguQ2|r;XoV^=^(;Cku#qYn4Lus`UeKt6rAlFo_rU`|Rq z&G?~iWMBio<78of-2X(ZYHx~=U0Vz4btyXkctMKdc9UM!vYr~B-(>)(Hc|D zMzkN4!PBg%tZoh+=Gba!0++d193gbMk2&krfDgcbx0jI92cq?FFESVg0D$>F+bil} zY~$)|>1HZsX=5sAZ2WgPB5P=8X#TI+NQ(M~GqyVB53c6IdX=k>Wu@A0Svf5#?uHaF zsYn|koIi3$(%GZ2+G+7Fv^lHTb#5b8sAHSTnL^qWZLM<(1|9|QFw9pnRU{svj}_Al zL)b9>fN{QiA($8peNEJyy`(a{&uh-T4_kdZFIVsKKVM(?05}76EEz?#W za^fiZOAd14IJ4zLX-n7Lq0qlQ^lW8Cvz4UKkV9~P}>sq0?xD3vg+$4vLm~C(+ zM{-3Z#qnZ09bJ>}j?6ry^h+@PfaD7*jZxBEY4)UG&daWb??6)TP+|3#Z&?GL?1i+280CFsE|vIXQbm| zM}Pk!U`U5NsNbyKzkrul-DzwB{X?n3E6?TUHr{M&+R*2%yOiXdW-_2Yd6?38M9Vy^ z*lE%gA{wwoSR~vN0=no}tP2Ul5Gk5M(Xq`$nw#ndFk`tcpd5A=Idue`XZ!FS>Q zG^0w#>P4pPG+*NC9gLP4x2m=cKP}YuS!l^?sHSFftZy{4CoQrb_ z^20(NnG`wAhMI=eq)SsIE~&Gp9Ne0nD4%Xiu|0Fj1UFk?6avDqjdXz{O1nKao*46y zT8~iA%Exu=G#{x=KD;_C&M+Zx4+n`sHT>^>=-1YM;H<72k>$py1?F3#T1*ef9mLZw z5naLQr?n7K;2l+{_uIw*_1nsTn~I|kkCgrn;|G~##hM;9l7Jy$yJfmk+&}W@JeKcF zx@@Woiz8qdi|D%aH3XTx5*wDlbs?dC1_nrFpm^QbG@wM=i2?Zg;$VK!c^Dp8<}BTI zyRhAq@#%2pGV49*Y5_mV4+OICP|%I(dQ7x=6Ob}>EjnB_-_18*xrY?b%-yEDT(wrO z9RY2QT0`_OpGfMObKHV;QLVnrK%mc?$WAdIT`kJQT^n%GuzE7|9@k3ci5fYOh(287 zuIbg!GB3xLg$YN=n)^pHGB0jH+_iIiC=nUcD;G6LuJsjn2VI1cyZx=a?ShCsF==QK z;q~*m&}L<-cb+mDDXzvvrRsybcgQ;Vg21P(uLv5I+eGc7o7tc6`;OA9{soHFOz zT~2?>Ts}gprIX$wRBb4yE>ot<8+*Bv`qbSDv*VtRi|cyWS>)Fjs>fkNOH-+PX&4(~ z&)T8Zam2L6puQl?;5zg9h<}k4#|yH9czHw;1jw-pwBM*O2hUR6yvHATrI%^mvs9q_ z&ccT0>f#eDG<^WG^q@oVqlJrhxH)dcq2cty@l3~|5#UDdExyXUmLQ}f4#;6fI{f^t zDCsgIJ~0`af%YR%Ma5VQq-p21k`vaBu6WE?66+5=XUd%Ay%D$irN>5LhluRWt7 zov-=f>QbMk*G##&DTQyou$s7UqjjW@k6=!I@!k+S{pP8R(2=e@io;N8E`EOB;OGoI zw6Q+{X1_I{OO0HPpBz!X!@`5YQ2)t{+!?M_iH25X(d~-Zx~cXnS9z>u?+If|iNJbx zyFU2d1!ITX64D|lE0Z{dLRqL1Ajj=CCMfC4lD3&mYR_R_VZ>_7_~|<^o*%_&jevU+ zQ4|qzci=0}Jydw|LXLCrOl1_P6Xf@c0$ieK2^7@A9UbF{@V_0p%lqW|L?5k>bVM8|p5v&2g;~r>B8uo<4N+`B zH{J)h;SYiIVx@#jI&p-v3dwL5QNV1oxPr8J%ooezTnLW>i*3Isb49%5i!&ac_dEXv zvXmVUck^QHmyrF8>CGXijC_R-y(Qr{3Zt~EmW)-nC!tiH`wlw5D*W7Pip;T?&j%kX z6DkZX4&}iw>hE(boLyjOoupf6JpvBG8}jIh!!VhnD0>}KSMMo{1#uU6kiFcA04~|7 zVO8eI&x1`g4CZ<2cYUI(n#wz2MtVFHx47yE5eL~8bot~>EHbevSt}LLMQX?odD{Ux zJMnam{d)W4da{l7&y-JrgiU~qY3$~}_F#G7|MxT)e;G{U`In&?`j<5D->}cb{}{T(4DF0BOk-=1195KB-E*o@c?`>y#4=dMtYtSY=&L{!TAjFVcq0y@AH`vH! z$41+u!Ld&}F^COPgL(EE{0X7LY&%D7-(?!kjFF7=qw<;`V{nwWBq<)1QiGJgUc^Vz ztMUlq1bZqKn17|6x6iAHbWc~l1HcmAxr%$Puv!znW)!JiukwIrqQ00|H$Z)OmGG@= zv%A8*4cq}(?qn4rN6o`$Y))(MyXr8R<2S^J+v(wmFmtac!%VOfN?&(8Nr!T@kV`N; z*Q33V3t`^rN&aBiHet)18wy{*wi1=W!B%B-Q6}SCrUl$~Hl{@!95ydml@FK8P=u4s z4e*7gV2s=YxEvskw2Ju!2%{8h01rx-3`NCPc(O zH&J0VH5etNB2KY6k4R@2Wvl^Ck$MoR3=)|SEclT2ccJ!RI9Nuter7u9@;sWf-%um;GfI!=eEIQ2l2p_YWUd{|6EG ze{yO6;lMc>;2tPrsNdi@&1K6(1;|$xe8vLgiouj%QD%gYk`4p{Ktv9|j+!OF-P?@p z;}SV|oIK)iwlBs+`ROXkhd&NK zzo__r!B>tOXpBJMDcv!Mq54P+n4(@dijL^EpO1wdg~q+!DT3lB<>9AANSe!T1XgC=J^)IP0XEZ()_vpu!!3HQyJhwh?r`Ae%Yr~b% zO*NY9t9#qWa@GCPYOF9aron7thfWT`eujS4`t2uG6)~JRTI;f(ZuoRQwjZjp5Pg34 z)rp$)Kr?R+KdJ;IO;pM{$6|2y=k_siqvp%)2||cHTe|b5Ht8&A{wazGNca zX$Ol?H)E_R@SDi~4{d-|8nGFhZPW;Cts1;08TwUvLLv&_2$O6Vt=M)X;g%HUr$&06 zISZb(6)Q3%?;3r~*3~USIg=HcJhFtHhIV(siOwV&QkQe#J%H9&E21!C*d@ln3E@J* zVqRO^<)V^ky-R|%{(9`l-(JXq9J)1r$`uQ8a}$vr9E^nNiI*thK8=&UZ0dsFN_eSl z(q~lnD?EymWLsNa3|1{CRPW60>DSkY9YQ;$4o3W7Ms&@&lv9eH!tk~N&dhqX&>K@} zi1g~GqglxkZ5pEFkllJ)Ta1I^c&Bt6#r(QLQ02yHTaJB~- zCcE=5tmi`UA>@P=1LBfBiqk)HB4t8D?02;9eXj~kVPwv?m{5&!&TFYhu>3=_ zsGmYZ^mo*-j69-42y&Jj0cBLLEulNRZ9vXE)8~mt9C#;tZs;=#M=1*hebkS;7(aGf zcs7zH(I8Eui9UU4L--))yy`&d&$In&VA2?DAEss4LAPCLd>-$i?lpXvn!gu^JJ$(DoUlc6wE98VLZ*z`QGQov5l4Fm_h?V-;mHLYDVOwKz7>e4+%AzeO>P6v}ndPW| zM>m#6Tnp7K?0mbK=>gV}=@k*0Mr_PVAgGMu$j+pWxzq4MAa&jpCDU&-5eH27Iz>m^ zax1?*HhG%pJ((tkR(V(O(L%7v7L%!_X->IjS3H5kuXQT2!ow(;%FDE>16&3r){!ex zhf==oJ!}YU89C9@mfDq!P3S4yx$aGB?rbtVH?sHpg?J5C->!_FHM%Hl3#D4eplxzQ zRA+<@LD%LKSkTk2NyWCg7u=$%F#;SIL44~S_OGR}JqX}X+=bc@swpiClB`Zbz|f!4 z7Ysah7OkR8liXfI`}IIwtEoL}(URrGe;IM8%{>b1SsqXh)~w}P>yiFRaE>}rEnNkT z!HXZUtxUp1NmFm)Dm@-{FI^aRQqpSkz}ZSyKR%Y}YHNzBk)ZIp} zMtS=aMvkgWKm9&oTcU0?S|L~CDqA+sHpOxwnswF-fEG)cXCzUR?ps@tZa$=O)=L+5 zf%m58cq8g_o}3?Bhh+c!w4(7AjxwQ3>WnVi<{{38g7yFboo>q|+7qs<$8CPXUFAN< zG&}BHbbyQ5n|qqSr?U~GY{@GJ{(Jny{bMaOG{|IkUj7tj^9pa9|FB_<+KHLxSxR;@ zHpS$4V)PP+tx}22fWx(Ku9y+}Ap;VZqD0AZW4gCDTPCG=zgJmF{|x;(rvdM|2|9a}cex6xrMkERnkE;}jvU-kmzd%_J50$M`lIPCKf+^*zL=@LW`1SaEc%=m zQ+lT06Gw+wVwvQ9fZ~#qd430v2HndFsBa9WjD0P}K(rZYdAt^5WQIvb%D^Q|pkVE^ zte$&#~zmULFACGfS#g=2OLOnIf2Of-k!(BIHjs77nr!5Q1*I9 z1%?=~#Oss!rV~?-6Gm~BWJiA4mJ5TY&iPm_$)H1_rTltuU1F3I(qTQ^U$S>%$l z)Wx1}R?ij0idp@8w-p!Oz{&*W;v*IA;JFHA9%nUvVDy7Q8woheC#|8QuDZb-L_5@R zOqHwrh|mVL9b=+$nJxM`3eE{O$sCt$UK^2@L$R(r^-_+z?lOo+me-VW=Zw z-Bn>$4ovfWd%SPY`ab-u9{INc*k2h+yH%toDHIyqQ zO68=u`N}RIIs7lsn1D){)~%>ByF<>i@qFb<-axvu(Z+6t7v<^z&gm9McRB~BIaDn$ z#xSGT!rzgad8o>~kyj#h1?7g96tOcCJniQ+*#=b7wPio>|6a1Z?_(TS{)KrPe}(8j z!#&A=k(&Pj^F;r)CI=Z{LVu>uj!_W1q4b`N1}E(i%;BWjbEcnD=mv$FL$l?zS6bW!{$7j1GR5ocn94P2u{ z70tAAcpqtQo<@cXw~@i-@6B23;317|l~S>CB?hR5qJ%J3EFgyBdJd^fHZu7AzHF(BQ!tyAz^L0`X z23S4Fe{2X$W0$zu9gm%rg~A>ijaE#GlYlrF9$ds^QtaszE#4M(OLVP2O-;XdT(XIC zatwzF*)1c+t~c{L=fMG8Z=k5lv>U0;C{caN1NItnuSMp)6G3mbahu>E#sj&oy94KC zpH}8oEw{G@N3pvHhp{^-YaZeH;K+T_1AUv;IKD<=mv^&Ueegrb!yf`4VlRl$M?wsl zZyFol(2|_QM`e_2lYSABpKR{{NlxlDSYQNkS;J66aT#MSiTx~;tUmvs-b*CrR4w=f z8+0;*th6kfZ3|5!Icx3RV11sp=?`0Jy3Fs0N4GZQMN=8HmT6%x9@{Dza)k}UwL6JT zHRDh;%!XwXr6yuuy`4;Xsn0zlR$k%r%9abS1;_v?`HX_hI|+EibVnlyE@3aL5vhQq zlIG?tN^w@0(v9M*&L+{_+RQZw=o|&BRPGB>e5=ys7H`nc8nx)|-g;s7mRc7hg{GJC zAe^vCIJhajmm7C6g! zL&!WAQ~5d_5)00?w_*|*H>3$loHrvFbitw#WvLB!JASO?#5Ig5$Ys10n>e4|3d;tS zELJ0|R4n3Az(Fl3-r^QiV_C;)lQ1_CW{5bKS15U|E9?ZgLec@%kXr84>5jV2a5v=w z?pB1GPdxD$IQL4)G||B_lI+A=08MUFFR4MxfGOu07vfIm+j=z9tp~5i_6jb`tR>qV z$#`=BQ*jpCjm$F0+F)L%xRlnS%#&gro6PiRfu^l!EVan|r3y}AHJQOORGx4~ z&<)3=K-tx518DZyp%|!EqpU!+X3Et7n2AaC5(AtrkW>_57i}$eqs$rupubg0a1+WO zGHZKLN2L0D;ab%{_S1Plm|hx8R?O14*w*f&2&bB050n!R2by zw!@XOQx$SqZ5I<(Qu$V6g>o#A!JVwErWv#(Pjx=KeS0@hxr4?13zj#oWwPS(7Ro|v z>Mp@Kmxo79q|}!5qtX2-O@U&&@6s~!I&)1WQIl?lTnh6UdKT_1R640S4~f=_xoN3- zI+O)$R@RjV$F=>Ti7BlnG1-cFKCC(t|Qjm{SalS~V-tX#+2ekRhwmN zZr`8{QF6y~Z!D|{=1*2D-JUa<(1Z=;!Ei!KiRNH?o{p5o3crFF=_pX9O-YyJchr$~ zRC`+G+8kx~fD2k*ZIiiIGR<8r&M@3H?%JVOfE>)})7ScOd&?OjgAGT@WVNSCZ8N(p zuQG~76GE3%(%h1*vUXg$vH{ua0b`sQ4f0*y=u~lgyb^!#CcPJa2mkSEHGLsnO^kb$ zru5_l#nu=Y{rSMWiYx?nO{8I!gH+?wEj~UM?IrG}E|bRIBUM>UlY<`T1EHpRr36vv zBi&dG8oxS|J$!zoaq{+JpJy+O^W(nt*|#g32bd&K^w-t>!Vu9N!k9eA8r!Xc{utY> zg9aZ(D2E0gL#W0MdjwES-7~Wa8iubPrd?8-$C4BP?*wok&O8+ykOx{P=Izx+G~hM8 z*9?BYz!T8~dzcZr#ux8kS7u7r@A#DogBH8km8Ry4slyie^n|GrTbO|cLhpqgMdsjX zJ_LdmM#I&4LqqsOUIXK8gW;V0B(7^$y#h3h>J0k^WJfAMeYek%Y-Dcb_+0zPJez!GM zAmJ1u;*rK=FNM0Nf}Y!!P9c4)HIkMnq^b;JFd!S3?_Qi2G#LIQ)TF|iHl~WKK6JmK zbv7rPE6VkYr_%_BT}CK8h=?%pk@3cz(UrZ{@h40%XgThP*-Oeo`T0eq9 zA8BnWZKzCy5e&&_GEsU4*;_k}(8l_&al5K-V*BFM=O~;MgRkYsOs%9eOY6s6AtE*<7GQAR2ulC3RAJrG_P1iQK5Z~&B z&f8X<>yJV6)oDGIlS$Y*D^Rj(cszTy5c81a5IwBr`BtnC6_e`ArI8CaTX_%rx7;cn zR-0?J_LFg*?(#n~G8cXut(1nVF0Oka$A$1FGcERU<^ggx;p@CZc?3UB41RY+wLS`LWFNSs~YP zuw1@DNN3lTd|jDL7gjBsd9}wIw}4xT2+8dBQzI00m<@?c2L%>}QLfK5%r!a-iII`p zX@`VEUH)uj^$;7jVUYdADQ2k*!1O3WdfgF?OMtUXNpQ1}QINamBTKDuv19^{$`8A1 zeq%q*O0mi@(%sZU>Xdb0Ru96CFqk9-L3pzLVsMQ`Xpa~N6CR{9Rm2)A|CI21L(%GW zh&)Y$BNHa=FD+=mBw3{qTgw)j0b!Eahs!rZnpu)z!!E$*eXE~##yaXz`KE5(nQM`s zD!$vW9XH)iMxu9R>r$VlLk9oIR%HxpUiW=BK@4U)|1WNQ=mz9a z^!KkO=>GaJ!GBXm{KJj^;kh-MkUlEQ%lza`-G&}C5y1>La1sR6hT=d*NeCnuK%_LV zOXt$}iP6(YJKc9j-Fxq~*ItVUqljQ8?oaysB-EYtFQp9oxZ|5m0^Hq(qV!S+hq#g( z?|i*H2MIr^Kxgz+3vIljQ*Feejy6S4v~jKEPTF~Qhq!(ms5>NGtRgO5vfPPc4Z^AM zTj!`5xEreIN)vaNxa|q6qWdg>+T`Ol0Uz)ckXBXEGvPNEL3R8hB3=C5`@=SYgAju1 z!)UBr{2~=~xa{b8>x2@C7weRAEuatC)3pkRhT#pMPTpSbA|tan%U7NGMvzmF?c!V8 z=pEWxbdXbTAGtWTyI?Fml%lEr-^AE}w#l(<7OIw;ctw}imYax&vR4UYNJZK6P7ZOd zP87XfhnUHxCUHhM@b*NbTi#(-8|wcv%3BGNs#zRCVV(W?1Qj6^PPQa<{yaBwZ`+<`w|;rqUY_C z&AeyKwwf*q#OW-F()lir=T^<^wjK65Lif$puuU5+tk$;e_EJ;Lu+pH>=-8=PDhkBg z8cWt%@$Sc#C6F$Vd+0507;{OOyT7Hs%nKS88q-W!$f~9*WGBpHGgNp}=C*7!RiZ5s zn1L_DbKF@B8kwhDiLKRB@lsXVVLK|ph=w%_`#owlf@s@V(pa`GY$8h%;-#h@TsO|Y8V=n@*!Rog7<7Cid%apR|x zOjhHCyfbIt%+*PCveTEcuiDi%Wx;O;+K=W?OFUV%)%~6;gl?<0%)?snDDqIvkHF{ zyI02)+lI9ov42^hL>ZRrh*HhjF9B$A@=H94iaBESBF=eC_KT$8A@uB^6$~o?3Wm5t1OIaqF^~><2?4e3c&)@wKn9bD? zoeCs;H>b8DL^F&>Xw-xjZEUFFTv>JD^O#1E#)CMBaG4DX9bD(Wtc8Rzq}9soQ8`jf zeSnHOL}<+WVSKp4kkq&?SbETjq6yr@4%SAqOG=9E(3YeLG9dtV+8vmzq+6PFPk{L; z(&d++iu=^F%b+ea$i2UeTC{R*0Isk;vFK!no<;L+(`y`3&H-~VTdKROkdyowo1iqR zbVW(3`+(PQ2>TKY>N!jGmGo7oeoB8O|P_!Ic@ zZ^;3dnuXo;WJ?S+)%P>{Hcg!Jz#2SI(s&dY4QAy_vRlmOh)QHvs_7c&zkJCmJGVvV zX;Mtb>QE+xp`KyciG$Cn*0?AK%-a|=o!+7x&&yzHQOS>8=B*R=niSnta^Pxp1`=md z#;$pS$4WCT?mbiCYU?FcHGZ#)kHVJTTBt^%XE(Q};aaO=Zik0UgLcc0I(tUpt(>|& zcxB_|fxCF7>&~5eJ=Dpn&5Aj{A^cV^^}(7w#p;HG&Q)EaN~~EqrE1qKrMAc&WXIE;>@<&)5;gD2?={Xf@Mvn@OJKw=8Mgn z!JUFMwD+s==JpjhroT&d{$kQAy%+d`a*XxDEVxy3`NHzmITrE`o!;5ClXNPb4t*8P zzAivdr{j_v!=9!^?T3y?gzmqDWX6mkzhIzJ-3S{T5bcCFMr&RPDryMcdwbBuZbsgN zGrp@^i?rcfN7v0NKGzDPGE#4yszxu=I_`MI%Z|10nFjU-UjQXXA?k8Pk|OE<(?ae) zE%vG#eZAlj*E7_3dx#Zz4kMLj>H^;}33UAankJiDy5ZvEhrjr`!9eMD8COp}U*hP+ zF}KIYx@pkccIgyxFm#LNw~G&`;o&5)2`5aogs`1~7cMZQ7zj!%L4E`2yzlQN6REX20&O<9 zKV6fyr)TScJPPzNTC2gL+0x#=u>(({{D7j)c-%tvqls3#Y?Z1m zV5WUE)zdJ{$p>yX;^P!UcXP?UD~YM;IRa#Rs5~l+*$&nO(;Ers`G=0D!twR(0GF@c zHl9E5DQI}Oz74n zfKP>&$q0($T4y$6w(p=ERAFh+>n%iaeRA%!T%<^+pg?M)@ucY<&59$x9M#n+V&>}=nO9wCV{O~lg&v#+jcUj(tQ z`0u1YH)-`U$15a{pBkGyPL0THv1P|4e@pf@3IBZS4dVJPo#H>pWq%Lr0YS-SeWash z8R7=jb28KPMI|_lo#GEO|5B?N_e``H*23{~a!AmUJ+fb4HX-%QI@lSEUxKlGV7z7Q zSKw@-TR>@1RL%w{x}dW#k1NgW+q4yt2Xf1J62Bx*O^WG8OJ|FqI4&@d3_o8Id@*)4 zYrk=>@!wv~mh7YWv*bZhxqSmFh2Xq)o=m;%n$I?GSz49l1$xRpPu_^N(vZ>*>Z<04 z2+rP70oM=NDysd!@fQdM2OcyT?3T^Eb@lIC-UG=Bw{BjQ&P`KCv$AcJ;?`vdZ4){d z&gkoUK{$!$$K`3*O-jyM1~p-7T*qb)Ys>Myt^;#1&a%O@x8A+E>! zY8=eD`ZG)LVagDLBeHg>=atOG?Kr%h4B%E6m@J^C+U|y)XX@f z8oyJDW|9g=<#f<{JRr{y#~euMnv)`7j=%cHWLc}ngjq~7k**6%4u>Px&W%4D94(r* z+akunK}O0DC2A%Xo9jyF;DobX?!1I(7%}@7F>i%&nk*LMO)bMGg2N+1iqtg+r(70q zF5{Msgsm5GS7DT`kBsjMvOrkx&|EU!{{~gL4d2MWrAT=KBQ-^zQCUq{5PD1orxlIL zq;CvlWx#f1NWvh`hg011I%?T_s!e38l*lWVt|~z-PO4~~1g)SrJ|>*tXh=QfXT)%( z+ex+inPvD&O4Ur;JGz>$sUOnWdpSLcm1X%aQDw4{dB!cnj`^muI$CJ2%p&-kULVCE z>$eMR36kN$wCPR+OFDM3-U(VOrp9k3)lI&YVFqd;Kpz~K)@Fa&FRw}L(SoD z9B4a+hQzZT-BnVltst&=kq6Y(f^S4hIGNKYBgMxGJ^;2yrO}P3;r)(-I-CZ)26Y6? z&rzHI_1GCvGkgy-t1E;r^3Le30|%$ebDRu2+gdLG)r=A~Qz`}~&L@aGJ{}vVs_GE* zVUjFnzHiXfKQbpv&bR&}l2bzIjAooB)=-XNcYmrGmBh(&iu@o!^hn0^#}m2yZZUK8 zufVm7Gq0y`Mj;9b>`c?&PZkU0j4>IL=UL&-Lp3j&47B5pAW4JceG{!XCA)kT<%2nqCxj<)uy6XR_uws~>_MEKPOpAQ!H zkn>FKh)<9DwwS*|Y(q?$^N!6(51O0 z^JM~Ax{AI1Oj$fs-S5d4T7Z_i1?{%0SsIuQ&r8#(JA=2iLcTN+?>wOL532%&dMYkT z*T5xepC+V6zxhS@vNbMoi|i)=rpli@R9~P!39tWbSSb904ekv7D#quKbgFEMTb48P zuq(VJ+&L8aWU(_FCD$3^uD!YM%O^K(dvy~Wm2hUuh6bD|#(I39Xt>N1Y{ZqXL`Fg6 zKQ?T2htHN!(Bx;tV2bfTtIj7e)liN-29s1kew>v(D^@)#v;}C4-G=7x#;-dM4yRWm zyY`cS21ulzMK{PoaQ6xChEZ}o_#}X-o}<&0)$1#3we?+QeLt;aVCjeA)hn!}UaKt< zat1fHEx13y-rXNMvpUUmCVzocPmN~-Y4(YJvQ#db)4|%B!rBsgAe+*yor~}FrNH08 z3V!97S}D7d$zbSD{$z;@IYMxM6aHdypIuS*pr_U6;#Y!_?0i|&yU*@16l z*dcMqDQgfNBf}?quiu4e>H)yTVfsp#f+Du0@=Kc41QockXkCkvu>FBd6Q+@FL!(Yx z2`YuX#eMEiLEDhp+9uFqME_E^faV&~9qjBHJkIp~%$x^bN=N)K@kvSVEMdDuzA0sn z88CBG?`RX1@#hQNd`o^V{37)!w|nA)QfiYBE^m=yQKv-fQF+UCMcuEe1d4BH7$?>b zJl-r9@0^Ie=)guO1vOd=i$_4sz>y3x^R7n4ED!5oXL3@5**h(xr%Hv)_gILarO46q+MaDOF%ChaymKoI6JU5Pg;7#2n9-18|S1;AK+ zgsn6;k6-%!QD>D?cFy}8F;r@z8H9xN1jsOBw2vQONVqBVEbkiNUqgw~*!^##ht>w0 zUOykwH=$LwX2j&nLy=@{hr)2O&-wm-NyjW7n~Zs9UlH;P7iP3 zI}S(r0YFVYacnKH(+{*)Tbw)@;6>%=&Th=+Z6NHo_tR|JCI8TJiXv2N7ei7M^Q+RM z?9o`meH$5Yi;@9XaNR#jIK^&{N|DYNNbtdb)XW1Lv2k{E>;?F`#Pq|&_;gm~&~Zc9 zf+6ZE%{x4|{YdtE?a^gKyzr}dA>OxQv+pq|@IXL%WS0CiX!V zm$fCePA%lU{%pTKD7|5NJHeXg=I0jL@$tOF@K*MI$)f?om)D63K*M|r`gb9edD1~Y zc|w7N)Y%do7=0{RC|AziW7#am$)9jciRJ?IWl9PE{G3U+$%FcyKs_0Cgq`=K3@ttV z9g;M!3z~f_?P%y3-ph%vBMeS@p7P&Ea8M@97+%XEj*(1E6vHj==d zjsoviB>j^$_^OI_DEPvFkVo(BGRo%cJeD){6Uckei=~1}>sp299|IRjhXe)%?uP0I zF5+>?0#Ye}T^Y$u_rc4=lPcq4K^D(TZG-w30-YiEM=dcK+4#o*>lJ8&JLi+3UcpZk z!^?95S^C0ja^jwP`|{<+3cBVog$(mRdQmadS+Vh~z zS@|P}=|z3P6uS+&@QsMp0no9Od&27O&14zHXGAOEy zh~OKpymK5C%;LLb467@KgIiVwYbYd6wFxI{0-~MOGfTq$nBTB!{SrWmL9Hs}C&l&l#m?s*{tA?BHS4mVKHAVMqm63H<|c5n0~k)-kbg zXidai&9ZUy0~WFYYKT;oe~rytRk?)r8bptITsWj(@HLI;@=v5|XUnSls7$uaxFRL+ zRVMGuL3w}NbV1`^=Pw*0?>bm8+xfeY(1PikW*PB>>Tq(FR`91N0c2&>lL2sZo5=VD zQY{>7dh_TX98L2)n{2OV=T10~*YzX27i2Q7W86M4$?gZIXZaBq#sA*{PH8){|GUi;oM>e?ua7eF4WFuFYZSG| zze?srg|5Ti8Og{O zeFxuw9!U+zhyk?@w zjsA6(oKD=Ka;A>Ca)oPORxK+kxH#O@zhC!!XS4@=swnuMk>t+JmLmFiE^1aX3f<)D@`%K0FGK^gg1a1j>zi z2KhV>sjU7AX3F$SEqrXSC}fRx64GDoc%!u2Yag68Lw@w9v;xOONf@o)Lc|Uh3<21ctTYu-mFZuHk*+R{GjXHIGq3p)tFtQp%TYqD=j1&y)>@zxoxUJ!G@ zgI0XKmP6MNzw>nRxK$-Gbzs}dyfFzt>#5;f6oR27ql!%+{tr+(`(>%51|k`ML} zY4eE)Lxq|JMas(;JibNQds1bUB&r}ydMQXBY4x(^&fY_&LlQC)3hylc$~8&~|06-D z#T+%66rYbHX%^KuqJED_wuGB+=h`nWA!>1n0)3wZrBG3%`b^Ozv6__dNa@%V14|!D zQ?o$z5u0^8`giv%qE!BzZ!3j;BlDlJDk)h@9{nSQeEk!z9RGW) z${RSF3phEM*ce*>Xdp}585vj$|40=&S{S-GTiE?Op*vY&Lvr9}BO$XWy80IF+6@%n z5*2ueT_g@ofP#u5pxb7n*fv^Xtt7&?SRc{*2Ka-*!BuOpf}neHGCiHy$@Ka1^Dint z;DkmIL$-e)rj4o2WQV%Gy;Xg(_Bh#qeOsTM2f@KEe~4kJ8kNLQ+;(!j^bgJMcNhvklP5Z6I+9Fq@c&D~8Fb-4rmDT!MB5QC{Dsb;BharP*O;SF4& zc$wj-7Oep7#$WZN!1nznc@Vb<_Dn%ga-O#J(l=OGB`dy=Sy&$(5-n3zzu%d7E#^8`T@}V+5B;PP8J14#4cCPw-SQTdGa2gWL0*zKM z#DfSXs_iWOMt)0*+Y>Lkd=LlyoHjublNLefhKBv@JoC>P7N1_#> zv=mLWe96%EY;!ZGSQDbZWb#;tzqAGgx~uk+-$+2_8U`!ypbwXl z^2E-FkM1?lY@yt8=J3%QK+xaZ6ok=-y%=KXCD^0r!5vUneW>95PzCkOPO*t}p$;-> ze5j-BLT_;)cZQzR2CEsm@rU7GZfFtdp*a|g4wDr%8?2QkIGasRfDWT-Dvy*U{?IHT z*}wGnzdlSptl#ZF^sf)KT|BJs&kLG91^A6ls{CzFprZ6-Y!V0Xysh%9p%iMd7HLsS zN+^Un$tDV)T@i!v?3o0Fsx2qI(AX_$dDkBzQ@fRM%n zRXk6hb9Py#JXUs+7)w@eo;g%QQ95Yq!K_d=z{0dGS+pToEI6=Bo8+{k$7&Z zo4>PH(`ce8E-Ps&uv`NQ;U$%t;w~|@E3WVOCi~R4oj5wP?%<*1C%}Jq%a^q~T7u>K zML5AKfQDv6>PuT`{SrKHRAF+^&edg6+5R_#H?Lz3iGoWo#PCEd0DS;)2U({{X#zU^ zw_xv{4x7|t!S)>44J;KfA|DC?;uQ($l+5Vp7oeqf7{GBF9356nx|&B~gs+@N^gSdd zvb*>&W)|u#F{Z_b`f#GVtQ`pYv3#||N{xj1NgB<#=Odt6{eB%#9RLt5v zIi|0u70`#ai}9fJjKv7dE!9ZrOIX!3{$z_K5FBd-Kp-&e4(J$LD-)NMTp^_pB`RT; zftVVlK2g@+1Ahv2$D){@Y#cL#dUj9*&%#6 zd2m9{1NYp>)6=oAvqdCn5#cx{AJ%S8skUgMglu2*IAtd+z1>B&`MuEAS(D(<6X#Lj z?f4CFx$)M&$=7*>9v1ER4b6!SIz-m0e{o0BfkySREchp?WdVPpQCh!q$t>?rL!&Jg zd#heM;&~A}VEm8Dvy&P|J*eAV&w!&Nx6HFV&B8jJFVTmgLaswn!cx$&%JbTsloz!3 zMEz1d`k==`Ueub_JAy_&`!ogbwx27^ZXgFNAbx=g_I~5nO^r)}&myw~+yY*cJl4$I znNJ32M&K=0(2Dj_>@39`3=FX!v3nZHno_@q^!y}%(yw0PqOo=);6Y@&ylVe>nMOZ~ zd>j#QQSBn3oaWd;qy$&5(5H$Ayi)0haAYO6TH>FR?rhqHmNOO+(})NB zLI@B@v0)eq!ug`>G<@htRlp3n!EpU|n+G+AvXFrWSUsLMBfL*ZB`CRsIVHNTR&b?K zxBgsN0BjfB>UVcJ|x%=-zb%OV7lmZc& zxiupadZVF7)6QuhoY;;FK2b*qL0J-Rn-8!X4ZY$-ZSUXV5DFd7`T41c(#lAeLMoeT z4%g655v@7AqT!i@)Edt5JMbN(=Q-6{=L4iG8RA%}w;&pKmtWvI4?G9pVRp|RTw`g0 zD5c12B&A2&P6Ng~8WM2eIW=wxd?r7A*N+&!Be7PX3s|7~z=APxm=A?5 zt>xB4WG|*Td@VX{Rs)PV0|yK`oI3^xn(4c_j&vgxk_Y3o(-`_5o`V zRTghg6%l@(qodXN;dB#+OKJEEvhfcnc#BeO2|E(5df-!fKDZ!%9!^BJ_4)9P+9Dq5 zK1=(v?KmIp34r?z{NEWnLB3Px{XYwy-akun4F7xTRr2^zeYW{gcK9)>aJDdU5;w5@ zak=<+-PLH-|04pelTb%ULpuuuJC7DgyT@D|p{!V!0v3KpDnRjANN12q6SUR3mb9<- z>2r~IApQGhstZ!3*?5V z8#)hJ0TdZg0M-BK#nGFP>$i=qk82DO z7h;Ft!D5E15OgW)&%lej*?^1~2=*Z5$2VX>V{x8SC+{i10BbtUk9@I#Vi&hX)q

Q!LwySI{Bnv%Sm)yh{^sSVJ8&h_D-BJ_YZe5eCaAWU9b$O2c z$T|{vWVRtOL!xC0DTc(Qbe`ItNtt5hr<)VijD0{U;T#bUEp381_y`%ZIav?kuYG{iyYdEBPW=*xNSc;Rlt6~F4M`5G+VtOjc z*0qGzCb@gME5udTjJA-9O<&TWd~}ysBd(eVT1-H82-doyH9RST)|+Pb{o*;$j9Tjs zhU!IlsPsj8=(x3bAKJTopW3^6AKROHR^7wZ185wJGVhA~hEc|LP;k7NEz-@4p5o}F z`AD6naG3(n=NF9HTH81=F+Q|JOz$7wm9I<+#BSmB@o_cLt2GkW9|?7mM;r!JZp89l zbo!Hp8=n!XH1{GwaDU+k)pGp`C|cXkCU5%vcH)+v@0eK>%7gWxmuMu9YLlChA|_D@ zi#5zovN_!a-0?~pUV-Rj*1P)KwdU-LguR>YM&*Nen+ln8Q$?WFCJg%DY%K}2!!1FE zDv-A%Cbwo^p(lzac&_TZ-l#9kq`mhLcY3h9ZTUVCM(Ad&=EriQY5{jJv<5K&g|*Lk zgV%ILnf1%8V2B0E&;Sp4sYbYOvvMebLwYwzkRQ#F8GpTQq#uv=J`uaSJ34OWITeSGo6+-8Xw znCk*n{kdDEi)Hi&u^)~cs@iyCkFWB2SWZU|Uc%^43ZIZQ-vWNExCCtDWjqHs;;tWf$v{}0{p0Rvxkq``)*>+Akq%|Na zA`@~-Vfe|+(AIlqru+7Ceh4nsVmO9p9jc8}HX^W&ViBDXT+uXbT#R#idPn&L>+#b6 zflC-4C5-X;kUnR~L>PSLh*gvL68}RBsu#2l`s_9KjUWRhiqF`j)`y`2`YU(>3bdBj z?>iyjEhe-~$^I5!nn%B6Wh+I`FvLNvauve~eX<+Ipl&04 zT}};W&1a3%W?dJ2=N#0t?e+aK+%t}5q%jSLvp3jZ%?&F}nOOWr>+{GFIa%wO_2`et z=JzoRR~}iKuuR+azPI8;Gf9)z3kyA4EIOSl!sRR$DlW}0>&?GbgPojmjmnln;cTqCt=ADbE zZ8GAnoM+S1(5$i8^O4t`ue;vO4i}z0wz-QEIVe5_u03;}-!G1NyY8;h^}y;tzY}i5 zqQr#Ur3Fy8sSa$Q0ys+f`!`+>9WbvU_I`Sj;$4{S>O3?#inLHCrtLy~!s#WXV=oVP zeE93*Nc`PBi4q@%Ao$x4lw9vLHM!6mn3-b_cebF|n-2vt-zYVF_&sDE--J-P;2WHo z+@n2areE0o$LjvjlV2X7ZU@j+`{*8zq`JR3gKF#EW|#+{nMyo-a>nFFTg&vhyT=b} zDa8+v0(Dgx0yRL@ZXOYIlVSZ0|MFizy0VPW8;AfA5|pe!#j zX}Py^8fl5SyS4g1WSKKtnyP+_PoOwMMwu`(i@Z)diJp~U54*-miOchy7Z35eL>^M z4p<-aIxH4VUZgS783@H%M7P9hX>t{|RU7$n4T(brCG#h9e9p! z+o`i;EGGq3&pF;~5V~eBD}lC)>if$w%Vf}AFxGqO88|ApfHf&Bvu+xdG)@vuF}Yvk z)o;~k-%+0K0g+L`Wala!$=ZV|z$e%>f0%XoLib%)!R^RoS+{!#X?h-6uu zF&&KxORdZU&EwQFITIRLo(7TA3W}y6X{?Y%y2j0It!ekU#<)$qghZtpcS>L3uh`Uj z7GY;6f$9qKynP#oS3$$a{p^{D+0oJQ71`1?OAn_m8)UGZmj3l*ZI)`V-a>MKGGFG< z&^jg#Ok%(hhm>hSrZ5;Qga4u(?^i>GiW_j9%_7M>j(^|Om$#{k+^*ULnEgzW_1gCICtAD^WpC`A z{9&DXkG#01Xo)U$OC(L5Y$DQ|Q4C6CjUKk1UkPj$nXH##J{c8e#K|&{mA*;b$r0E4 zUNo0jthwA(c&N1l=PEe8Rw_8cEl|-eya9z&H3#n`B$t#+aJ03RFMzrV@gowbe8v(c zIFM60^0&lCFO10NU4w@|61xiZ4CVXeaKjd;d?sv52XM*lS8XiVjgWpRB;&U_C0g+`6B5V&w|O6B*_q zsATxL!M}+$He)1eOWECce#eS@2n^xhlB4<_Nn?yCVEQWDs(r`|@2GqLe<#(|&P0U? z$7V5IgpWf09uIf_RazRwC?qEqRaHyL?iiS05UiGesJy%^>-C{{ypTBI&B0-iUYhk> zIk<5xpsuV@g|z(AZD+C-;A!fTG=df1=<%nxy(a(IS+U{ME4ZbDEBtcD_3V=icT6*_ z)>|J?>&6%nvHhZERBtjK+s4xnut*@>GAmA5m*OTp$!^CHTr}vM4n(X1Q*;{e-Rd2BCF-u@1ZGm z!S8hJ6L=Gl4T_SDa7Xx|-{4mxveJg=ctf`BJ*fy!yF6Dz&?w(Q_6B}WQVtNI!BVBC zKfX<>7vd6C96}XAQmF-Jd?1Q4eTfRB3q7hCh0f!(JkdWT5<{iAE#dKy*Jxq&3a1@~ z8C||Dn2mFNyrUV|<-)C^_y7@8c2Fz+2jrae9deBDu;U}tJ{^xAdxCD248(k;dCJ%o z`y3sADe>U%suxwwv~8A1+R$VB=Q?%U?4joI$um;aH+eCrBqpn- z%79D_7rb;R-;-9RTrwi9dPlg8&@tfWhhZ(Vx&1PQ+6(huX`;M9x~LrW~~#3{j0Bh2kDU$}@!fFQej4VGkJv?M4rU^x!RU zEwhu$!CA_iDjFjrJa`aocySDX16?~;+wgav;}Zut6Mg%C4>}8FL?8)Kgwc(Qlj{@#2Pt0?G`$h7P#M+qoXtlV@d}%c&OzO+QYKK`kyXaK{U(O^2DyIXCZlNQjt0^8~8JzNGrIxhj}}M z&~QZlbx%t;MJ(Vux;2tgNKGlAqphLq%pd}JG9uoVHUo?|hN{pLQ6Em%r*+7t^<);X zm~6=qChlNAVXNN*Sow->*4;}T;l;D1I-5T{Bif@4_}=>l`tK;qqDdt5zvisCKhMAH z#r}`)7VW?LZqfdmXQ%zo5bJ00{Xb9^YKrk0Nf|oIW*K@(=`o2Vndz}ZDyk{!u}PVx zzd--+_WC*U{~DH3{?GI64IB+@On&@9X>EUAo&L+G{L^dozaI4C3G#2wr~hseW@K&g zKWs{uHu-9Je!3;4pE>eBltKUXb^*hG8I&413)$J&{D4N%7PcloU6bn%jPxJyQL?g* z9g+YFFEDiE`8rW^laCNzQmi7CTnPfwyg3VDHRAl>h=In6jeaVOP@!-CP60j3+#vpL zEYmh_oP0{-gTe7Or`L6x)6w?77QVi~jD8lWN@3RHcm80iV%M1A!+Y6iHM)05iC64tb$X2lV_%Txk@0l^hZqi^%Z?#- zE;LE0uFx)R08_S-#(wC=dS&}vj6P4>5ZWjhthP=*Hht&TdLtKDR;rXEX4*z0h74FA zMCINqrh3Vq;s%3MC1YL`{WjIAPkVL#3rj^9Pj9Ss7>7duy!9H0vYF%>1jh)EPqvlr6h%R%CxDsk| z!BACz7E%j?bm=pH6Eaw{+suniuY7C9Ut~1cWfOX9KW9=H><&kQlinPV3h9R>3nJvK z4L9(DRM=x;R&d#a@oFY7mB|m8h4692U5eYfcw|QKwqRsshN(q^v$4$)HgPpAJDJ`I zkqjq(8Cd!K!+wCd=d@w%~e$=gdUgD&wj$LQ1r>-E=O@c ze+Z$x{>6(JA-fNVr)X;*)40Eym1TtUZI1Pwwx1hUi+G1Jlk~vCYeXMNYtr)1?qwyg zsX_e*$h?380O00ou?0R@7-Fc59o$UvyVs4cUbujHUA>sH!}L54>`e` zHUx#Q+Hn&Og#YVOuo*niy*GU3rH;%f``nk#NN5-xrZ34NeH$l`4@t);4(+0|Z#I>Y z)~Kzs#exIAaf--65L0UHT_SvV8O2WYeD>Mq^Y6L!Xu8%vnpofG@w!}R7M28?i1*T&zp3X4^OMCY6(Dg<-! zXmcGQrRgHXGYre7GfTJ)rhl|rs%abKT_Nt24_Q``XH{88NVPW+`x4ZdrMuO0iZ0g` z%p}y};~T5gbb9SeL8BSc`SO#ixC$@QhXxZ=B}L`tP}&k?1oSPS=4%{UOHe0<_XWln zwbl5cn(j-qK`)vGHY5B5C|QZd5)W7c@{bNVXqJ!!n$^ufc?N9C-BF2QK1(kv++h!>$QbAjq)_b$$PcJdV+F7hz0Hu@ zqj+}m0qn{t^tD3DfBb~0B36|Q`bs*xs|$i^G4uNUEBl4g;op-;Wl~iThgga?+dL7s zUP(8lMO?g{GcYpDS{NM!UA8Hco?#}eNEioRBHy4`mq!Pd-9@-97|k$hpEX>xoX+dY zDr$wfm^P&}Wu{!%?)U_(%Mn79$(ywvu*kJ9r4u|MyYLI_67U7%6Gd_vb##Nerf@>& z8W11z$$~xEZt$dPG}+*IZky+os5Ju2eRi;1=rUEeIn>t-AzC_IGM-IXWK3^6QNU+2pe=MBn4I*R@A%-iLDCOHTE-O^wo$sL_h{dcPl=^muAQb`_BRm};=cy{qSkui;`WSsj9%c^+bIDQ z0`_?KX0<-=o!t{u(Ln)v>%VGL z0pC=GB7*AQ?N7N{ut*a%MH-tdtNmNC+Yf$|KS)BW(gQJ*z$d{+{j?(e&hgTy^2|AR9vx1Xre2fagGv0YXWqtNkg*v%40v?BJBt|f9wX5 z{QTlCM}b-0{mV?IG>TW_BdviUKhtosrBqdfq&Frdz>cF~yK{P@(w{Vr7z2qKFwLhc zQuogKO@~YwyS9%+d-zD7mJG~@?EFJLSn!a&mhE5$_4xBl&6QHMzL?CdzEnC~C3$X@ zvY!{_GR06ep5;<#cKCSJ%srxX=+pn?ywDwtJ2{TV;0DKBO2t++B(tIO4)Wh`rD13P z4fE$#%zkd=UzOB74gi=-*CuID&Z3zI^-`4U^S?dHxK8fP*;fE|a(KYMgMUo`THIS1f!*6dOI2 zFjC3O=-AL`6=9pp;`CYPTdVX z8(*?V&%QoipuH0>WKlL8A*zTKckD!paN@~hh zmXzm~qZhMGVdQGd=AG8&20HW0RGV8X{$9LldFZYm zE?}`Q3i?xJRz43S?VFMmqRyvWaS#(~Lempg9nTM$EFDP(Gzx#$r)W&lpFKqcAoJh-AxEw$-bjW>`_+gEi z2w`99#UbFZGiQjS8kj~@PGqpsPX`T{YOj`CaEqTFag;$jY z8_{Wzz>HXx&G*Dx<5skhpETxIdhKH?DtY@b9l8$l?UkM#J-Snmts7bd7xayKTFJ(u zyAT&@6cAYcs{PBfpqZa%sxhJ5nSZBPji?Zlf&}#L?t)vC4X5VLp%~fz2Sx<*oN<7` z?ge=k<=X7r<~F7Tvp9#HB{!mA!QWBOf%EiSJ6KIF8QZNjg&x~-%e*tflL(ji_S^sO ztmib1rp09uon}RcsFi#k)oLs@$?vs(i>5k3YN%$T(5Or(TZ5JW9mA6mIMD08=749$ z!d+l*iu{Il7^Yu}H;lgw=En1sJpCKPSqTCHy4(f&NPelr31^*l%KHq^QE>z>Ks_bH zjbD?({~8Din7IvZeJ>8Ey=e;I?thpzD=zE5UHeO|neioJwG;IyLk?xOz(yO&0DTU~ z^#)xcs|s>Flgmp;SmYJ4g(|HMu3v7#;c*Aa8iF#UZo7CvDq4>8#qLJ|YdZ!AsH%^_7N1IQjCro

K7UpUK$>l@ zw`1S}(D?mUXu_C{wupRS-jiX~w=Uqqhf|Vb3Cm9L=T+w91Cu^ z*&Ty%sN?x*h~mJc4g~k{xD4ZmF%FXZNC;oVDwLZ_WvrnzY|{v8hc1nmx4^}Z;yriXsAf+Lp+OFLbR!&Ox?xABwl zu8w&|5pCxmu#$?Cv2_-Vghl2LZ6m7}VLEfR5o2Ou$x02uA-%QB2$c(c1rH3R9hesc zfpn#oqpbKuVsdfV#cv@5pV4^f_!WS+F>SV6N0JQ9E!T90EX((_{bSSFv9ld%I0&}9 zH&Jd4MEX1e0iqDtq~h?DBrxQX1iI0lIs<|kB$Yrh&cpeK0-^K%=FBsCBT46@h#yi!AyDq1V(#V}^;{{V*@T4WJ&U-NTq43w=|K>z8%pr_nC>%C(Wa_l78Ufib$r8Od)IIN=u>417 z`Hl{9A$mI5A(;+-Q&$F&h-@;NR>Z<2U;Y21>>Z;s@0V@SbkMQQj%_;~+qTuQ?c|AV zcWm3XZQHhP&R%QWarS%mJ!9R^&!_)*s(v+VR@I#QrAT}`17Y+l<`b-nvmDNW`De%y zrwTZ9EJrj1AFA>B`1jYDow}~*dfPs}IZMO3=a{Fy#IOILc8F0;JS4x(k-NSpbN@qM z`@aE_e}5{!$v3+qVs7u?sOV(y@1Os*Fgu`fCW9=G@F_#VQ%xf$hj0~wnnP0$hFI+@ zkQj~v#V>xn)u??YutKsX>pxKCl^p!C-o?+9;!Nug^ z{rP!|+KsP5%uF;ZCa5F;O^9TGac=M|=V z_H(PfkV1rz4jl?gJ(ArXMyWT4y(86d3`$iI4^l9`vLdZkzpznSd5Ikfrs8qcSy&>z zTIZgWZGXw0n9ibQxYWE@gI0(3#KA-dAdPcsL_|hg2@~C!VZDM}5;v_Nykfq!*@*Zf zE_wVgx82GMDryKO{U{D>vSzSc%B~|cjDQrt5BN=Ugpsf8H8f1lR4SGo#hCuXPL;QQ z#~b?C4MoepT3X`qdW2dNn& zo8)K}%Lpu>0tQei+{>*VGErz|qjbK#9 zvtd8rcHplw%YyQCKR{kyo6fgg!)6tHUYT(L>B7er5)41iG`j$qe*kSh$fY!PehLcD zWeKZHn<492B34*JUQh=CY1R~jT9Jt=k=jCU2=SL&&y5QI2uAG2?L8qd2U(^AW#{(x zThSy=C#>k+QMo^7caQcpU?Qn}j-`s?1vXuzG#j8(A+RUAY})F@=r&F(8nI&HspAy4 z4>(M>hI9c7?DCW8rw6|23?qQMSq?*Vx?v30U%luBo)B-k2mkL)Ljk5xUha3pK>EEj z@(;tH|M@xkuN?gsz;*bygizwYR!6=(Xgcg^>WlGtRYCozY<rFX2E>kaZo)O<^J7a`MX8Pf`gBd4vrtD|qKn&B)C&wp0O-x*@-|m*0egT=-t@%dD zgP2D+#WPptnc;_ugD6%zN}Z+X4=c61XNLb7L1gWd8;NHrBXwJ7s0ce#lWnnFUMTR& z1_R9Fin4!d17d4jpKcfh?MKRxxQk$@)*hradH2$3)nyXep5Z;B z?yX+-Bd=TqO2!11?MDtG0n(*T^!CIiF@ZQymqq1wPM_X$Iu9-P=^}v7npvvPBu!d$ z7K?@CsA8H38+zjA@{;{kG)#AHME>Ix<711_iQ@WWMObXyVO)a&^qE1GqpP47Q|_AG zP`(AD&r!V^MXQ^e+*n5~Lp9!B+#y3#f8J^5!iC@3Y@P`;FoUH{G*pj*q7MVV)29+j z>BC`a|1@U_v%%o9VH_HsSnM`jZ-&CDvbiqDg)tQEnV>b%Ptm)T|1?TrpIl)Y$LnG_ zzKi5j2Fx^K^PG1=*?GhK;$(UCF-tM~^=Z*+Wp{FSuy7iHt9#4n(sUuHK??@v+6*|10Csdnyg9hAsC5_OrSL;jVkLlf zHXIPukLqbhs~-*oa^gqgvtpgTk_7GypwH><53riYYL*M=Q@F-yEPLqQ&1Sc zZB%w}T~RO|#jFjMWcKMZccxm-SL)s_ig?OC?y_~gLFj{n8D$J_Kw%{r0oB8?@dWzn zB528d-wUBQzrrSSLq?fR!K%59Zv9J4yCQhhDGwhptpA5O5U?Hjqt>8nOD zi{)0CI|&Gu%zunGI*XFZh(ix)q${jT8wnnzbBMPYVJc4HX*9d^mz|21$=R$J$(y7V zo0dxdbX3N#=F$zjstTf*t8vL)2*{XH!+<2IJ1VVFa67|{?LP&P41h$2i2;?N~RA30LV`BsUcj zfO9#Pg1$t}7zpv#&)8`mis3~o+P(DxOMgz-V*(?wWaxi?R=NhtW}<#^Z?(BhSwyar zG|A#Q7wh4OfK<|DAcl9THc-W4*>J4nTevsD%dkj`U~wSUCh15?_N@uMdF^Kw+{agk zJ`im^wDqj`Ev)W3k3stasP`88-M0ZBs7;B6{-tSm3>I@_e-QfT?7|n0D~0RRqDb^G zyHb=is;IwuQ&ITzL4KsP@Z`b$d%B0Wuhioo1CWttW8yhsER1ZUZzA{F*K=wmi-sb#Ju+j z-l@In^IKnb{bQG}Ps>+Vu_W#grNKNGto+yjA)?>0?~X`4I3T@5G1)RqGUZuP^NJCq&^HykuYtMDD8qq+l8RcZNJsvN(10{ zQ1$XcGt}QH-U^WU!-wRR1d--{B$%vY{JLWIV%P4-KQuxxDeJaF#{eu&&r!3Qu{w}0f--8^H|KwE>)ORrcR+2Qf zb})DRcH>k0zWK8@{RX}NYvTF;E~phK{+F;MkIP$)T$93Ba2R2TvKc>`D??#mv9wg$ zd~|-`Qx5LwwsZ2hb*Rt4S9dsF%Cny5<1fscy~)d;0m2r$f=83<->c~!GNyb!U)PA; zq^!`@@)UaG)Ew(9V?5ZBq#c%dCWZrplmuM`o~TyHjAIMh0*#1{B>K4po-dx$Tk-Cq z=WZDkP5x2W&Os`N8KiYHRH#UY*n|nvd(U>yO=MFI-2BEp?x@=N<~CbLJBf6P)}vLS?xJXYJ2^<3KJUdrwKnJnTp{ zjIi|R=L7rn9b*D#Xxr4*R<3T5AuOS+#U8hNlfo&^9JO{VbH!v9^JbK=TCGR-5EWR@ zN8T-_I|&@A}(hKeL4_*eb!1G8p~&_Im8|wc>Cdir+gg90n1dw?QaXcx6Op_W1r=axRw>4;rM*UOpT#Eb9xU1IiWo@h?|5uP zka>-XW0Ikp@dIe;MN8B01a7+5V@h3WN{J=HJ*pe0uwQ3S&MyWFni47X32Q7SyCTNQ z+sR!_9IZa5!>f&V$`q!%H8ci!a|RMx5}5MA_kr+bhtQy{-^)(hCVa@I!^TV4RBi zAFa!Nsi3y37I5EK;0cqu|9MRj<^r&h1lF}u0KpKQD^5Y+LvFEwM zLU@@v4_Na#Axy6tn3P%sD^5P#<7F;sd$f4a7LBMk zGU^RZHBcxSA%kCx*eH&wgA?Qwazm8>9SCSz_!;MqY-QX<1@p$*T8lc?@`ikEqJ>#w zcG``^CoFMAhdEXT9qt47g0IZkaU)4R7wkGs^Ax}usqJ5HfDYAV$!=6?>J6+Ha1I<5 z|6=9soU4>E))tW$<#>F ziZ$6>KJf0bPfbx_)7-}tMINlc=}|H+$uX)mhC6-Hz+XZxsKd^b?RFB6et}O#+>Wmw9Ec9) z{q}XFWp{3@qmyK*Jvzpyqv57LIR;hPXKsrh{G?&dRjF%Zt5&m20Ll?OyfUYC3WRn{cgQ?^V~UAv+5 z&_m#&nIwffgX1*Z2#5^Kl4DbE#NrD&Hi4|7SPqZ}(>_+JMz=s|k77aEL}<=0Zfb)a z%F(*L3zCA<=xO)2U3B|pcTqDbBoFp>QyAEU(jMu8(jLA61-H!ucI804+B!$E^cQQa z)_ERrW3g!B9iLb3nn3dlkvD7KsY?sRvls3QC0qPi>o<)GHx%4Xb$5a3GBTJ(k@`e@ z$RUa^%S15^1oLEmA=sayrP5;9qtf!Z1*?e$ORVPsXpL{jL<6E)0sj&swP3}NPmR%FM?O>SQgN5XfHE< zo(4#Cv11(%Nnw_{_Ro}r6=gKd{k?NebJ~<~Kv0r(r0qe4n3LFx$5%x(BKvrz$m?LG zjLIc;hbj0FMdb9aH9Lpsof#yG$(0sG2%RL;d(n>;#jb!R_+dad+K;Ccw!|RY?uS(a zj~?=&M!4C(5LnlH6k%aYvz@7?xRa^2gml%vn&eKl$R_lJ+e|xsNfXzr#xuh(>`}9g zLHSyiFwK^-p!;p$yt7$F|3*IfO3Mlu9e>Dpx8O`37?fA`cj`C0B-m9uRhJjs^mRp# zWB;Aj6|G^1V6`jg7#7V9UFvnB4((nIwG?k%c7h`?0tS8J3Bn0t#pb#SA}N-|45$-j z$R>%7cc2ebAClXc(&0UtHX<>pd)akR3Kx_cK+n<}FhzmTx!8e9^u2e4%x{>T6pQ`6 zO182bh$-W5A3^wos0SV_TgPmF4WUP-+D25KjbC{y_6W_9I2_vNKwU(^qSdn&>^=*t z&uvp*@c8#2*paD!ZMCi3;K{Na;I4Q35zw$YrW5U@Kk~)&rw;G?d7Q&c9|x<Hg|CNMsxovmfth*|E*GHezPTWa^Hd^F4!B3sF;)? z(NaPyAhocu1jUe(!5Cy|dh|W2=!@fNmuNOzxi^tE_jAtzNJ0JR-avc_H|ve#KO}#S z#a(8secu|^Tx553d4r@3#6^MHbH)vmiBpn0X^29xEv!Vuh1n(Sr5I0V&`jA2;WS|Y zbf0e}X|)wA-Pf5gBZ>r4YX3Mav1kKY(ulAJ0Q*jB)YhviHK)w!TJsi3^dMa$L@^{` z_De`fF4;M87vM3Ph9SzCoCi$#Fsd38u!^0#*sPful^p5oI(xGU?yeYjn;Hq1!wzFk zG&2w}W3`AX4bxoVm03y>ts{KaDf!}b&7$(P4KAMP=vK5?1In^-YYNtx1f#}+2QK@h zeSeAI@E6Z8a?)>sZ`fbq9_snl6LCu6g>o)rO;ijp3|$vig+4t} zylEo7$SEW<_U+qgVcaVhk+4k+C9THI5V10qV*dOV6pPtAI$)QN{!JRBKh-D zk2^{j@bZ}yqW?<#VVuI_27*cI-V~sJiqQv&m07+10XF+#ZnIJdr8t`9s_EE;T2V;B z4UnQUH9EdX%zwh-5&wflY#ve!IWt0UE-My3?L#^Bh%kcgP1q{&26eXLn zTkjJ*w+(|_>Pq0v8{%nX$QZbf)tbJaLY$03;MO=Ic-uqYUmUCuXD>J>o6BCRF=xa% z3R4SK9#t1!K4I_d>tZgE>&+kZ?Q}1qo4&h%U$GfY058s%*=!kac{0Z+4Hwm!)pFLR zJ+5*OpgWUrm0FPI2ib4NPJ+Sk07j(`diti^i#kh&f}i>P4~|d?RFb#!JN)~D@)beox}bw?4VCf^y*`2{4`-@%SFTry2h z>9VBc9#JxEs1+0i2^LR@B1J`B9Ac=#FW=(?2;5;#U$0E0UNag_!jY$&2diQk_n)bT zl5Me_SUvqUjwCqmVcyb`igygB_4YUB*m$h5oeKv3uIF0sk}~es!{D>4r%PC*F~FN3owq5e0|YeUTSG#Vq%&Gk7uwW z0lDo#_wvflqHeRm*}l?}o;EILszBt|EW*zNPmq#?4A+&i0xx^?9obLyY4xx=Y9&^G;xYXYPxG)DOpPg!i_Ccl#3L}6xAAZzNhPK1XaC_~ z!A|mlo?Be*8Nn=a+FhgpOj@G7yYs(Qk(8&|h@_>w8Y^r&5nCqe0V60rRz?b5%J;GYeBqSAjo|K692GxD4` zRZyM2FdI+-jK2}WAZTZ()w_)V{n5tEb@>+JYluDozCb$fA4H)$bzg(Ux{*hXurjO^ zwAxc+UXu=&JV*E59}h3kzQPG4M)X8E*}#_&}w*KEgtX)cU{vm9b$atHa;s>| z+L6&cn8xUL*OSjx4YGjf6{Eq+Q3{!ZyhrL&^6Vz@jGbI%cAM9GkmFlamTbcQGvOlL zmJ?(FI)c86=JEs|*;?h~o)88>12nXlpMR4@yh%qdwFNpct;vMlc=;{FSo*apJ;p}! zAX~t;3tb~VuP|ZW;z$=IHf->F@Ml)&-&Bnb{iQyE#;GZ@C$PzEf6~q}4D>9jic@mTO5x76ulDz@+XAcm35!VSu zT*Gs>;f0b2TNpjU_BjHZ&S6Sqk6V1370+!eppV2H+FY!q*n=GHQ!9Rn6MjY!Jc77A zG7Y!lFp8?TIHN!LXO?gCnsYM-gQxsm=Ek**VmZu7vnuufD7K~GIxfxbsQ@qv2T zPa`tvHB$fFCyZl>3oYg?_wW)C>^_iDOc^B7klnTOoytQH18WkOk)L2BSD0r%xgRSW zQS9elF^?O=_@|58zKLK;(f77l-Zzu}4{fXed2saq!5k#UZAoDBqYQS{sn@j@Vtp|$ zG%gnZ$U|9@u#w1@11Sjl8ze^Co=)7yS(}=;68a3~g;NDe_X^}yJj;~s8xq9ahQ5_r zxAlTMnep*)w1e(TG%tWsjo3RR;yVGPEO4V{Zp?=a_0R#=V^ioQu4YL=BO4r0$$XTX zZfnw#_$V}sDAIDrezGQ+h?q24St0QNug_?{s-pI(^jg`#JRxM1YBV;a@@JQvH8*>> zIJvku74E0NlXkYe_624>znU0J@L<-c=G#F3k4A_)*;ky!C(^uZfj%WB3-*{*B$?9+ zDm$WFp=0(xnt6`vDQV3Jl5f&R(Mp};;q8d3I%Kn>Kx=^;uSVCw0L=gw53%Bp==8Sw zxtx=cs!^-_+i{2OK`Q;913+AXc_&Z5$@z3<)So0CU3;JAv=H?@Zpi~riQ{z-zLtVL z!oF<}@IgJp)Iyz1zVJ42!SPHSkjYNS4%ulVVIXdRuiZ@5Mx8LJS}J#qD^Zi_xQ@>DKDr-_e#>5h3dtje*NcwH_h;i{Sx7}dkdpuW z(yUCjckQsagv*QGMSi9u1`Z|V^}Wjf7B@q%j2DQXyd0nOyqg%m{CK_lAoKlJ7#8M} z%IvR?Vh$6aDWK2W!=i?*<77q&B8O&3?zP(Cs@kapc)&p7En?J;t-TX9abGT#H?TW? ztO5(lPKRuC7fs}zwcUKbRh=7E8wzTsa#Z{a`WR}?UZ%!HohN}d&xJ=JQhpO1PI#>X zHkb>pW04pU%Bj_mf~U}1F1=wxdBZu1790>3Dm44bQ#F=T4V3&HlOLsGH)+AK$cHk6 zia$=$kog?)07HCL*PI6}DRhpM^*%I*kHM<#1Se+AQ!!xyhcy6j7`iDX7Z-2i73_n# zas*?7LkxS-XSqv;YBa zW_n*32D(HTYQ0$feV_Fru1ZxW0g&iwqixPX3=9t4o)o|kOo79V$?$uh?#8Q8e>4e)V6;_(x&ViUVxma+i25qea;d-oK7ouuDsB^ab{ zu1qjQ%`n56VtxBE#0qAzb7lph`Eb-}TYpXB!H-}3Ykqyp`otprp7{VEuW*^IR2n$Fb99*nAtqT&oOFIf z@w*6>YvOGw@Ja?Pp1=whZqydzx@9X4n^2!n83C5{C?G@|E?&$?p*g68)kNvUTJ)I6 z1Q|(#UuP6pj78GUxq11m-GSszc+)X{C2eo-?8ud9sB=3(D47v?`JAa{V(IF zPZQ_0AY*9M97>Jf<o%#O_%Wq}8>YM=q0|tGY+hlXcpE=Z4Od z`NT7Hu2hnvRoqOw@g1f=bv`+nba{GwA$Ak0INlqI1k<9!x_!sL()h?hEWoWrdU3w` zZ%%)VR+Bc@_v!C#koM1p-3v_^L6)_Ktj4HE>aUh%2XZE@JFMOn)J~c`_7VWNb9c-N z2b|SZMR4Z@E7j&q&9(6H3yjEu6HV7{2!1t0lgizD;mZ9$r(r7W5G$ky@w(T_dFnOD z*p#+z$@pKE+>o@%eT(2-p_C}wbQ5s(%Sn_{$HDN@MB+Ev?t@3dPy`%TZ!z}AThZSu zN<1i$siJhXFdjV zP*y|V<`V8t=h#XTRUR~5`c`Z9^-`*BZf?WAehGdg)E2Je)hqFa!k{V(u+(hTf^Yq& zoruUh2(^3pe)2{bvt4&4Y9CY3js)PUHtd4rVG57}uFJL)D(JfSIo^{P=7liFXG zq5yqgof0V8paQcP!gy+;^pp-DA5pj=gbMN0eW=-eY+N8~y+G>t+x}oa!5r>tW$xhI zPQSv=pi;~653Gvf6~*JcQ%t1xOrH2l3Zy@8AoJ+wz@daW@m7?%LXkr!bw9GY@ns3e zSfuWF_gkWnesv?s3I`@}NgE2xwgs&rj?kH-FEy82=O8`+szN ziHch`vvS`zNfap14!&#i9H@wF7}yIPm=UB%(o(}F{wsZ(wA0nJ2aD^@B41>>o-_U6 zUqD~vdo48S8~FTb^+%#zcbQiiYoDKYcj&$#^;Smmb+Ljp(L=1Kt_J!;0s%1|JK}Wi z;={~oL!foo5n8=}rs6MmUW~R&;SIJO3TL4Ky?kh+b2rT9B1Jl4>#Uh-Bec z`Hsp<==#UEW6pGPhNk8H!!DUQR~#F9jEMI6T*OWfN^Ze&X(4nV$wa8QUJ>oTkruH# zm~O<`J7Wxseo@FqaZMl#Y(mrFW9AHM9Kb|XBMqaZ2a)DvJgYipkDD_VUF_PKd~dT7 z#02}bBfPn9a!X!O#83=lbJSK#E}K&yx-HI#T6ua)6o0{|={*HFusCkHzs|Fn&|C3H zBck1cmfcWVUN&i>X$YU^Sn6k2H;r3zuXbJFz)r5~3$d$tUj(l1?o={MM){kjgqXRO zc5R*#{;V7AQh|G|)jLM@wGAK&rm2~@{Pewv#06pHbKn#wL0P6F1!^qw9g&cW3Z=9} zj)POhOlwsh@eF=>z?#sIs*C-Nl(yU!#DaiaxhEs#iJqQ8w%(?+6lU02MYSeDkr!B- zPjMv+on6OLXgGnAtl(ao>|X2Y8*Hb}GRW5}-IzXnoo-d0!m4Vy$GS!XOLy>3_+UGs z2D|YcQx@M#M|}TDOetGi{9lGo9m-=0-^+nKE^*?$^uHkxZh}I{#UTQd;X!L+W@jm( zDg@N4+lUqI92o_rNk{3P>1gxAL=&O;x)ZT=q1mk0kLlE$WeWuY_$0`0jY-Kkt zP*|m3AF}Ubd=`<>(Xg0har*_@x2YH}bn0Wk*OZz3*e5;Zc;2uBdnl8?&XjupbkOeNZsNh6pvsq_ydmJI+*z**{I{0K)-;p1~k8cpJXL$^t!-`E}=*4G^-E8>H!LjTPxSx zcF+cS`ommfKMhNSbas^@YbTpH1*RFrBuATUR zt{oFWSk^$xU&kbFQ;MCX22RAN5F6eq9UfR$ut`Jw--p2YX)A*J69m^!oYfj2y7NYcH6&r+0~_sH^c^nzeN1AU4Ga7=FlR{S|Mm~MpzY0$Z+p2W(a={b-pR9EO1Rs zB%KY|@wLcAA@)KXi!d2_BxrkhDn`DT1=Dec}V!okd{$+wK z4E{n8R*xKyci1(CnNdhf$Dp2(Jpof0-0%-38X=Dd9PQgT+w%Lshx9+loPS~MOm%ZT zt%2B2iL_KU_ita%N>xjB!#71_3=3c}o zgeW~^U_ZTJQ2!PqXulQd=3b=XOQhwATK$y(9$#1jOQ4}4?~l#&nek)H(04f(Sr=s| zWv7Lu1=%WGk4FSw^;;!8&YPM)pQDCY9DhU`hMty1@sq1=Tj7bFsOOBZOFlpR`W>-J$-(kezWJj;`?x-v>ev{*8V z8p|KXJPV$HyQr1A(9LVrM47u-XpcrIyO`yWvx1pVYc&?154aneRpLqgx)EMvRaa#|9?Wwqs2+W8n5~79G z(}iCiLk;?enn}ew`HzhG+tu+Ru@T+K5juvZN)wY;x6HjvqD!&!)$$;1VAh~7fg0K| zEha#aN=Yv|3^~YFH}cc38ovVb%L|g@9W6fo(JtT6$fa?zf@Ct88e}m?i)b*Jgc{fl zExfdvw-BYDmH6>(4QMt#p0;FUIQqkhD}aH?a7)_%JtA~soqj{ppP_82yi9kaxuK>~ ze_)Zt>1?q=ZH*kF{1iq9sr*tVuy=u>Zev}!gEZx@O6-fjyu9X00gpIl-fS_pzjpqJ z1yqBmf9NF!jaF<+YxgH6oXBdK)sH(>VZ)1siyA$P<#KDt;8NT*l_0{xit~5j1P)FN zI8hhYKhQ)i z37^aP13B~u65?sg+_@2Kr^iWHN=U;EDSZ@2W2!5ALhGNWXnFBY%7W?1 z=HI9JzQ-pLKZDYTv<0-lt|6c-RwhxZ)mU2Os{bsX_i^@*fKUj8*aDO5pks=qn3Dv6 zwggpKLuyRCTVPwmw1r}B#AS}?X7b837UlXwp~E2|PJw2SGVueL7){Y&z!jL!XN=0i zU^Eig`S2`{+gU$68aRdWx?BZ{sU_f=8sn~>s~M?GU~`fH5kCc; z8ICp+INM3(3{#k32RZdv6b9MQYdZXNuk7ed8;G?S2nT+NZBG=Tar^KFl2SvhW$bGW#kdWL-I)s_IqVnCDDM9fm8g;P;8 z7t4yZn3^*NQfx7SwmkzP$=fwdC}bafQSEF@pd&P8@H#`swGy_rz;Z?Ty5mkS%>m#% zp_!m9e<()sfKiY(nF<1zBz&&`ZlJf6QLvLhl`_``%RW&{+O>Xhp;lwSsyRqGf=RWd zpftiR`={2(siiPAS|p}@q=NhVc0ELprt%=fMXO3B)4ryC2LT(o=sLM7hJC!}T1@)E zA3^J$3&1*M6Xq>03FX`R&w*NkrZE?FwU+Muut;>qNhj@bX17ZJxnOlPSZ=Zeiz~T_ zOu#yc3t6ONHB;?|r4w+pI)~KGN;HOGC)txxiUN8#mexj+W(cz%9a4sx|IRG=}ia zuEBuba3AHsV2feqw-3MvuL`I+2|`Ud4~7ZkN=JZ;L20|Oxna5vx1qbIh#k2O4$RQF zo`tL()zxaqibg^GbB+BS5#U{@K;WWQj~GcB1zb}zJkPwH|5hZ9iH2308!>_;%msji zJHSL~s)YHBR=Koa1mLEOHos*`gp=s8KA-C zu0aE+W!#iJ*0xqKm3A`fUGy#O+X+5W36myS>Uh2!R*s$aCU^`K&KKLCCDkejX2p=5 z%o7-fl03x`gaSNyr?3_JLv?2RLS3F*8ub>Jd@^Cc17)v8vYEK4aqo?OS@W9mt%ITJ z9=S2%R8M){CugT@k~~0x`}Vl!svYqX=E)c_oU6o}#Hb^%G1l3BudxA{F*tbjG;W_>=xV73pKY53v%>I)@D36I_@&p$h|Aw zonQS`07z_F#@T-%@-Tb|)7;;anoD_WH>9ewFy(ZcEOM$#Y)8>qi7rCnsH9GO-_7zF zu*C87{Df1P4TEOsnzZ@H%&lvV(3V@;Q!%+OYRp`g05PjY^gL$^$-t0Y>H*CDDs?FZly*oZ&dxvsxaUWF!{em4{A>n@vpXg$dwvt@_rgmHF z-MER`ABa8R-t_H*kv>}CzOpz;!>p^^9ztHMsHL|SRnS<-y5Z*r(_}c4=fXF`l^-i}>e7v!qs_jv zqvWhX^F=2sDNWA9c@P0?lUlr6ecrTKM%pNQ^?*Lq?p-0~?_j50xV%^(+H>sMul#Tw zeciF*1=?a7cI(}352%>LO96pD+?9!fNyl^9v3^v&Y4L)mNGK0FN43&Xf8jUlxW1Bw zyiu2;qW-aGNhs=zbuoxnxiwZ3{PFZM#Kw)9H@(hgX23h(`Wm~m4&TvoZoYp{plb^> z_#?vXcxd>r7K+1HKJvhed>gtK`TAbJUazUWQY6T~t2af%#<+Veyr%7-#*A#@&*;@g58{i|E%6yC_InGXCOd{L0;$)z#?n7M`re zh!kO{6=>7I?*}czyF7_frt#)s1CFJ_XE&VrDA?Dp3XbvF{qsEJgb&OLSNz_5g?HpK z9)8rsr4JN!Af3G9!#Qn(6zaUDqLN(g2g8*M)Djap?WMK9NKlkC)E2|-g|#-rp%!Gz zAHd%`iq|81efi93m3yTBw3g0j#;Yb2X{mhRAI?&KDmbGqou(2xiRNb^sV}%%Wu0?< z?($L>(#BO*)^)rSgyNRni$i`R4v;GhlCZ8$@e^ROX(p=2_v6Y!%^As zu022)fHdv_-~Yu_H6WVPLpHQx!W%^6j)cBhS`O3QBW#x(eX54d&I22op(N59b*&$v zFiSRY6rOc^(dgSV1>a7-5C;(5S5MvKcM2Jm-LD9TGqDpP097%52V+0>Xqq!! zq4e3vj53SE6i8J`XcQB|MZPP8j;PAOnpGnllH6#Ku~vS42xP*Nz@~y%db7Xi8s09P z1)e%8ys6&M8D=Dt6&t`iKG_4X=!kgRQoh%Z`dc&mlOUqXk-k`jKv9@(a^2-Upw>?< zt5*^DV~6Zedbec4NVl($2T{&b)zA@b#dUyd>`2JC0=xa_fIm8{5um zr-!ApXZhC8@=vC2WyxO|!@0Km)h8ep*`^he92$@YwP>VcdoS5OC^s38e#7RPsg4j+ zbVGG}WRSET&ZfrcR(x~k8n1rTP%CnfUNKUonD$P?FtNFF#cn!wEIab-;jU=B1dHK@ z(;(yAQJ`O$sMn>h;pf^8{JISW%d+@v6@CnXh9n5TXGC}?FI9i-D0OMaIg&mAg=0Kn zNJ7oz5*ReJukD55fUsMuaP+H4tDN&V9zfqF@ zr=#ecUk9wu{0;!+gl;3Bw=Vn^)z$ahVhhw)io!na&9}LmWurLb0zubxK=UEnU*{5P z+SP}&*(iBKSO4{alBHaY^)5Q=mZ+2OwIooJ7*Q5XJ+2|q`9#f?6myq!&oz?klihLq z4C)$XP!BNS0G_Z1&TM>?Jk{S~{F3n83ioli=IO6f%wkvCl(RFFw~j0tb{GvXTx>*sB0McY0s&SNvj4+^h`9nJ_wM>F!Uc>X}9PifQekn0sKI2SAJP!a4h z5cyGTuCj3ZBM^&{dRelIlT^9zcfaAuL5Y~bl!ppSf`wZbK$z#6U~rdclk``e+!qhe z6Qspo*%<)eu6?C;Bp<^VuW6JI|Ncvyn+LlSl;Mp22Bl7ARQ0Xc24%29(ZrdsIPw&-=yHQ7_Vle|5h>AST0 zUGX2Zk34vp?U~IHT|;$U86T+UUHl_NE4m|}>E~6q``7hccCaT^#y+?wD##Q%HwPd8 zV3x4L4|qqu`B$4(LXqDJngNy-{&@aFBvVsywt@X^}iH7P%>bR?ciC$I^U-4Foa`YKI^qDyGK7k%E%c_P=yzAi`YnxGA%DeNd++j3*h^ z=rn>oBd0|~lZ<6YvmkKY*ZJlJ;Im0tqgWu&E92eqt;+NYdxx`eS(4Hw_Jb5|yVvBg z*tbdY^!AN;luEyN4VRhS@-_DC{({ziH{&Z}iGElSV~qvT>L-8G%+yEL zX#MFOhj{InyKG=mvW-<1B@c-}x$vA(nU?>S>0*eN#!SLzQ)Ex7fvQ)S4D<8|I#N$3 zT5Ei`Z?cxBODHX8(Xp73v`IsAYC@9b;t}z0wxVuQSY1J^GRwDPN@qbM-ZF48T$GZ< z8WU+;Pqo?{ghI-KZ-i*ydXu`Ep0Xw^McH_KE9J0S7G;x8Fe`DVG?j3Pv=0YzJ}yZR z%2=oqHiUjvuk0~Ca>Kol4CFi0_xQT~;_F?=u+!kIDl-9g`#ZNZ9HCy17Ga1v^Jv9# z{T4Kb1-AzUxq*MutfOWWZgD*HnFfyYg0&e9f(5tZ>krPF6{VikNeHoc{linPPt#Si z&*g>(c54V8rT_AX!J&bNm-!umPvOR}vDai#`CX___J#=zeB*{4<&2WpaDncZsOkp* zsg<%@@rbrMkR_ux9?LsQxzoBa1s%$BBn6vk#{&&zUwcfzeCBJUwFYSF$08qDsB;gWQN*g!p8pxjofWbqNSZOEKOaTx@+* zwdt5*Q47@EOZ~EZL9s?1o?A%9TJT=Ob_13yyugvPg*e&ZU(r6^k4=2+D-@n=Hv5vu zSXG|hM(>h9^zn=eQ=$6`JO&70&2|%V5Lsx>)(%#;pcOfu>*nk_3HB_BNaH$`jM<^S zcSftDU1?nL;jy)+sfonQN}(}gUW?d_ikr*3=^{G)=tjBtEPe>TO|0ddVB zTklrSHiW+!#26frPXQQ(YN8DG$PZo?(po(QUCCf_OJC`pw*uey00%gmH!`WJkrKXj2!#6?`T25mTu9OJp2L8z3! z=arrL$ZqxuE{%yV)14Kd>k}j7pxZ6#$Dz8$@WV5p8kTqN<-7W)Q7Gt2{KoOPK_tZ| zf2WG~O5@{qPI+W<4f_;reuFVdO^5`ADC1!JQE|N`s3cq@(0WB!n0uh@*c{=LAd;~} zyGK@hbF-Oo+!nN)@i*O(`@FA#u?o=~e{`4O#5}z&=UkU*50fOrzi11D^&FOqe>wii z?*k+2|EcUs;Gx{!@KBT~>PAwLrIDT7Th=Utu?~?np@t^gFs?zgX=D${RwOY^WGh-+ z+#4$066ISh8eYW#FXWp~S`<*%O^ZuItL1Tyqt8#tZ zY120E;^VG`!lZn&3sPd$RkdHpU#|w+bYV)pJC|SH9g%|5IkxVTQcBA4CL0}$&}ef@ zW^Vtj%M;;_1xxP9x#ex17&4N*{ksO*_4O}xYu(p*JkL#yr}@7b)t5X?%CY<+s5_MJ zuiqt+N_;A(_)%lumoyRFixWa-M7qK_9s6<1X?JDa9fP!+_6u~~M$5L=ipB=7(j#f< zZ34J%=bs549%~_mA(|={uZNs_0?o7;-LBP(ZRnkd{-^|2|=4vUTmtByHL8 zEph`(LSEzQj68a+`d$V<45J7cyv^#|^|%fD#si1Nx!4NW*`l*{->HEWNh6-|g>-=r zXmQ|-i}Ku$ndUeHQ^&ieT!Lf}vf6GaqW9$DJ2NWrqwPY%%4nip$@vK$nRp*_C-v<| zuKz~ZyN&<%!NS26&x?jhy+@awJipMQ-8(X4#Ae5??U<1QMt1l9R=w9fAnEF}NYu$2 z>6}Vkc zIb*A?G*z8^IvibmBKn_u^5&T_1oey0gZS2~obf(#xk=erZGTEdQnt3DMGM+0oPwss zj5zXD;(oWhB_T@~Ig#9@v)AKtXu3>Inmgf@A|-lD-1U>cNyl3h?ADD9)GG4}zUGPk zZzaXe!~Kf?<~@$G?Uql3t8jy9{2!doq4=J}j9ktTxss{p6!9UdjyDERlA*xZ!=Q)KDs5O)phz>Vq3BNGoM(H|=1*Q4$^2fTZw z(%nq1P|5Rt81}SYJpEEzMPl5VJsV5&4e)ZWKDyoZ>1EwpkHx-AQVQc8%JMz;{H~p{=FXV>jIxvm4X*qv52e?Y-f%DJ zxEA165GikEASQ^fH6K#d!Tpu2HP{sFs%E=e$gYd$aj$+xue6N+Wc(rAz~wUsk2`(b z8Kvmyz%bKQxpP}~baG-rwYcYCvkHOi zlkR<=>ZBTU*8RF_d#Bl@zZsRIhx<%~Z@Z=ik z>adw3!DK(8R|q$vy{FTxw%#xliD~6qXmY^7_9kthVPTF~Xy1CfBqbU~?1QmxmU=+k z(ggxvEuA;0e&+ci-zQR{-f7aO{O(Pz_OsEjLh_K>MbvoZ4nxtk5u{g@nPv)cgW_R} z9}EA4K4@z0?7ue}Z(o~R(X&FjejUI2g~08PH1E4w>9o{)S(?1>Z0XMvTb|;&EuyOE zGvWNpYX)Nv<8|a^;1>bh#&znEcl-r!T#pn= z4$?Yudha6F%4b>*8@=BdtXXY4N+`U4Dmx$}>HeVJk-QdTG@t!tVT#0(LeV0gvqyyw z2sEp^9eY0N`u10Tm4n8No&A=)IeEC|gnmEXoNSzu!1<4R<%-9kY_8~5Ej?zRegMn78wuMs#;i&eUA0Zk_RXQ3b&TT} z;SCI=7-FUB@*&;8|n>(_g^HGf3@QODE3LpmX~ELnymQm{Sx9xrKS zK29p~?v@R$0=v6Dr5aW>-!{+h@?Q58|Kz8{{W`%J+lDAdb&M5VHrX_mDY;1-JLnf)ezmPau$)1;=`-FU=-r-83tX=C`S#}GZufju zQ>sXNT0Ny=k@nc%cFnvA_i4SC)?_ORXHq8B4D%el1uPX`c~uG#S1M7C+*MMqLw78E zhY2dI8@+N^qrMI1+;TUda(vGqGSRyU{Fnm`aqrr7bz42c5xsOO-~oZpkzorD1g}Y<6rk&3>PsSGy}W?MtqFky@A(X# zIuNZK0cK?^=;PUAu>j0#HtjbHCV*6?jzA&OoE$*Jlga*}LF`SF?WLhv1O|zqC<>*> zYB;#lsYKx0&kH@BFpW8n*yDcc6?;_zaJs<-jPSkCsSX-!aV=P5kUgF@Nu<{a%#K*F z134Q{9|YX7X(v$62_cY3^G%t~rD>Q0z@)1|zs)vjJ6Jq9;7#Ki`w+eS**En?7;n&7 zu==V3T&eFboN3ZiMx3D8qYc;VjFUk_H-WWCau(VFXSQf~viH0L$gwD$UfFHqNcgN`x}M+YQ6RnN<+@t>JUp#)9YOkqst-Ga?{FsDpEeX0(5v{0J~SEbWiL zXC2}M4?UH@u&|;%0y`eb33ldo4~z-x8zY!oVmV=c+f$m?RfDC35mdQ2E>Pze7KWP- z>!Bh<&57I+O_^s}9Tg^k)h7{xx@0a0IA~GAOt2yy!X%Q$1rt~LbTB6@Du!_0%HV>N zlf)QI1&gvERKwso23mJ!Ou6ZS#zCS5W`gxE5T>C#E|{i<1D35C222I33?Njaz`On7 zi<+VWFP6D{e-{yiN#M|Jgk<44u1TiMI78S5W`Sdb5f+{zu34s{CfWN7a3Cf^@L%!& zN$?|!!9j2c)j$~+R6n#891w-z8(!oBpL2K=+%a$r2|~8-(vQj5_XT`<0Ksf;oP+tz z9CObS!0m)Tgg`K#xBM8B(|Z)Wb&DYL{WTYv`;A=q6~Nnx2+!lTIXtj8J7dZE!P_{z z#f8w6F}^!?^KE#+ZDv+xd5O&3EmomZzsv?>E-~ygGum45fk!SBN&|eo1rKw^?aZJ4 E2O(~oYXATM literal 0 HcmV?d00001 diff --git a/code/gradle/wrapper/gradle-wrapper.properties b/code/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..6c9a2247 --- /dev/null +++ b/code/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/code/gradlew b/code/gradlew new file mode 100644 index 00000000..4f906e0c --- /dev/null +++ b/code/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/code/gradlew.bat b/code/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/code/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/code/hiding/Cake.java b/code/hiding/Cake.java new file mode 100644 index 00000000..d20e2cbf --- /dev/null +++ b/code/hiding/Cake.java @@ -0,0 +1,15 @@ +// hiding/Cake.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Accesses a class in a separate compilation unit + +class Cake { + public static void main(String[] args) { + Pie x = new Pie(); + x.f(); + } +} +/* Output: +Pie.f() +*/ diff --git a/code/hiding/ChocolateChip.java b/code/hiding/ChocolateChip.java new file mode 100644 index 00000000..1467fff4 --- /dev/null +++ b/code/hiding/ChocolateChip.java @@ -0,0 +1,23 @@ +// hiding/ChocolateChip.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Can't use package-access member from another package +import hiding.dessert.*; + +public class ChocolateChip extends Cookie { + public ChocolateChip() { + System.out.println("ChocolateChip constructor"); + } + public void chomp() { + //- bite(); // Can't access bite + } + public static void main(String[] args) { + ChocolateChip x = new ChocolateChip(); + x.chomp(); + } +} +/* Output: +Cookie constructor +ChocolateChip constructor +*/ diff --git a/code/hiding/ChocolateChip2.java b/code/hiding/ChocolateChip2.java new file mode 100644 index 00000000..03c9d1ab --- /dev/null +++ b/code/hiding/ChocolateChip2.java @@ -0,0 +1,21 @@ +// hiding/ChocolateChip2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import hiding.cookie2.*; + +public class ChocolateChip2 extends Cookie { + public ChocolateChip2() { + System.out.println("ChocolateChip2 constructor"); + } + public void chomp() { bite(); } // Protected method + public static void main(String[] args) { + ChocolateChip2 x = new ChocolateChip2(); + x.chomp(); + } +} +/* Output: +Cookie constructor +ChocolateChip2 constructor +bite +*/ diff --git a/code/hiding/CreatePackageAccessObject.java b/code/hiding/CreatePackageAccessObject.java new file mode 100644 index 00000000..8442b51f --- /dev/null +++ b/code/hiding/CreatePackageAccessObject.java @@ -0,0 +1,12 @@ +// hiding/CreatePackageAccessObject.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} +import hiding.packageaccess.*; + +public class CreatePackageAccessObject { + public static void main(String[] args) { + new PublicConstructor(); + } +} diff --git a/code/hiding/Dinner.java b/code/hiding/Dinner.java new file mode 100644 index 00000000..7a7b97d5 --- /dev/null +++ b/code/hiding/Dinner.java @@ -0,0 +1,16 @@ +// hiding/Dinner.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Uses the library +import hiding.dessert.*; + +public class Dinner { + public static void main(String[] args) { + Cookie x = new Cookie(); + //- x.bite(); // Can't access + } +} +/* Output: +Cookie constructor +*/ diff --git a/code/hiding/FullQualification.java b/code/hiding/FullQualification.java new file mode 100644 index 00000000..2fadb28c --- /dev/null +++ b/code/hiding/FullQualification.java @@ -0,0 +1,11 @@ +// hiding/FullQualification.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class FullQualification { + public static void main(String[] args) { + java.util.ArrayList list = + new java.util.ArrayList(); + } +} diff --git a/code/hiding/IceCream.java b/code/hiding/IceCream.java new file mode 100644 index 00000000..d91619a2 --- /dev/null +++ b/code/hiding/IceCream.java @@ -0,0 +1,19 @@ +// hiding/IceCream.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates "private" keyword + +class Sundae { + private Sundae() {} + static Sundae makeASundae() { + return new Sundae(); + } +} + +public class IceCream { + public static void main(String[] args) { + //- Sundae x = new Sundae(); + Sundae x = Sundae.makeASundae(); + } +} diff --git a/code/hiding/ImportedMyClass.java b/code/hiding/ImportedMyClass.java new file mode 100644 index 00000000..a644f5d8 --- /dev/null +++ b/code/hiding/ImportedMyClass.java @@ -0,0 +1,11 @@ +// hiding/ImportedMyClass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import hiding.mypackage.*; + +public class ImportedMyClass { + public static void main(String[] args) { + MyClass m = new MyClass(); + } +} diff --git a/code/hiding/LibTest.java b/code/hiding/LibTest.java new file mode 100644 index 00000000..c439352a --- /dev/null +++ b/code/hiding/LibTest.java @@ -0,0 +1,17 @@ +// hiding/LibTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Uses the library +import com.mindviewinc.simple.*; + +public class LibTest { + public static void main(String[] args) { + Vector v = new Vector(); + List l = new List(); + } +} +/* Output: +com.mindviewinc.simple.Vector +com.mindviewinc.simple.List +*/ diff --git a/code/hiding/Lunch.java b/code/hiding/Lunch.java new file mode 100644 index 00000000..eca4baf0 --- /dev/null +++ b/code/hiding/Lunch.java @@ -0,0 +1,36 @@ +// hiding/Lunch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates class access specifiers. Make a class +// effectively private with private constructors: + +class Soup1 { + private Soup1() {} + public static Soup1 makeSoup() { // [1] + return new Soup1(); + } +} + +class Soup2 { + private Soup2() {} + private static Soup2 ps1 = new Soup2(); // [2] + public static Soup2 access() { + return ps1; + } + public void f() {} +} + +// Only one public class allowed per file: +public class Lunch { + void testPrivate() { + // Can't do this! Private constructor: + //- Soup1 soup = new Soup1(); + } + void testStatic() { + Soup1 soup = Soup1.makeSoup(); + } + void testSingleton() { + Soup2.access().f(); + } +} diff --git a/code/hiding/OrganizedByAccess.java b/code/hiding/OrganizedByAccess.java new file mode 100644 index 00000000..46af158f --- /dev/null +++ b/code/hiding/OrganizedByAccess.java @@ -0,0 +1,15 @@ +// hiding/OrganizedByAccess.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class OrganizedByAccess { + public void pub1() { /* ... */ } + public void pub2() { /* ... */ } + public void pub3() { /* ... */ } + private void priv1() { /* ... */ } + private void priv2() { /* ... */ } + private void priv3() { /* ... */ } + private int i; + // ... +} diff --git a/code/hiding/Pie.java b/code/hiding/Pie.java new file mode 100644 index 00000000..1470fbc3 --- /dev/null +++ b/code/hiding/Pie.java @@ -0,0 +1,9 @@ +// hiding/Pie.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The other class + +class Pie { + void f() { System.out.println("Pie.f()"); } +} diff --git a/code/hiding/QualifiedMyClass.java b/code/hiding/QualifiedMyClass.java new file mode 100644 index 00000000..58a097cc --- /dev/null +++ b/code/hiding/QualifiedMyClass.java @@ -0,0 +1,11 @@ +// hiding/QualifiedMyClass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class QualifiedMyClass { + public static void main(String[] args) { + hiding.mypackage.MyClass m = + new hiding.mypackage.MyClass(); + } +} diff --git a/code/hiding/SingleImport.java b/code/hiding/SingleImport.java new file mode 100644 index 00000000..5168ebe8 --- /dev/null +++ b/code/hiding/SingleImport.java @@ -0,0 +1,11 @@ +// hiding/SingleImport.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.ArrayList; + +public class SingleImport { + public static void main(String[] args) { + ArrayList list = new ArrayList(); + } +} diff --git a/code/hiding/cookie2/Cookie.java b/code/hiding/cookie2/Cookie.java new file mode 100644 index 00000000..aff5bb17 --- /dev/null +++ b/code/hiding/cookie2/Cookie.java @@ -0,0 +1,14 @@ +// hiding/cookie2/Cookie.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package hiding.cookie2; + +public class Cookie { + public Cookie() { + System.out.println("Cookie constructor"); + } + protected void bite() { + System.out.println("bite"); + } +} diff --git a/code/hiding/dessert/Cookie.java b/code/hiding/dessert/Cookie.java new file mode 100644 index 00000000..803e504c --- /dev/null +++ b/code/hiding/dessert/Cookie.java @@ -0,0 +1,13 @@ +// hiding/dessert/Cookie.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creates a library +package hiding.dessert; + +public class Cookie { + public Cookie() { + System.out.println("Cookie constructor"); + } + void bite() { System.out.println("bite"); } +} diff --git a/code/hiding/mypackage/MyClass.java b/code/hiding/mypackage/MyClass.java new file mode 100644 index 00000000..5245d479 --- /dev/null +++ b/code/hiding/mypackage/MyClass.java @@ -0,0 +1,9 @@ +// hiding/mypackage/MyClass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package hiding.mypackage; + +public class MyClass { + // ... +} diff --git a/code/hiding/packageaccess/PublicConstructor.java b/code/hiding/packageaccess/PublicConstructor.java new file mode 100644 index 00000000..533c28a0 --- /dev/null +++ b/code/hiding/packageaccess/PublicConstructor.java @@ -0,0 +1,9 @@ +// hiding/packageaccess/PublicConstructor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package hiding.packageaccess; + +class PublicConstructor { + public PublicConstructor() {} +} diff --git a/code/housekeeping/Apricot.java b/code/housekeeping/Apricot.java new file mode 100644 index 00000000..dae8f33d --- /dev/null +++ b/code/housekeeping/Apricot.java @@ -0,0 +1,8 @@ +// housekeeping/Apricot.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class Apricot { + void pick() { /* ... */ } + void pit() { pick(); /* ... */ } +} diff --git a/code/housekeeping/ArrayClassObj.java b/code/housekeeping/ArrayClassObj.java new file mode 100644 index 00000000..44e31b59 --- /dev/null +++ b/code/housekeeping/ArrayClassObj.java @@ -0,0 +1,22 @@ +// housekeeping/ArrayClassObj.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating an array of nonprimitive objects +import java.util.*; + +public class ArrayClassObj { + public static void main(String[] args) { + Random rand = new Random(47); + Integer[] a = new Integer[rand.nextInt(20)]; + System.out.println("length of a = " + a.length); + for(int i = 0; i < a.length; i++) + a[i] = rand.nextInt(500); // Autoboxing + System.out.println(Arrays.toString(a)); + } +} +/* Output: +length of a = 18 +[55, 193, 361, 461, 429, 368, 200, 22, 207, 288, 128, +51, 89, 309, 278, 498, 361, 20] +*/ diff --git a/code/housekeeping/ArrayInit.java b/code/housekeeping/ArrayInit.java new file mode 100644 index 00000000..4186bd24 --- /dev/null +++ b/code/housekeeping/ArrayInit.java @@ -0,0 +1,25 @@ +// housekeeping/ArrayInit.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Array initialization +import java.util.*; + +public class ArrayInit { + public static void main(String[] args) { + Integer[] a = { + 1, 2, + 3, // Autoboxing + }; + Integer[] b = new Integer[]{ + 1, 2, + 3, // Autoboxing + }; + System.out.println(Arrays.toString(a)); + System.out.println(Arrays.toString(b)); + } +} +/* Output: +[1, 2, 3] +[1, 2, 3] +*/ diff --git a/code/housekeeping/ArrayNew.java b/code/housekeeping/ArrayNew.java new file mode 100644 index 00000000..022cec16 --- /dev/null +++ b/code/housekeeping/ArrayNew.java @@ -0,0 +1,20 @@ +// housekeeping/ArrayNew.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating arrays with new +import java.util.*; + +public class ArrayNew { + public static void main(String[] args) { + int[] a; + Random rand = new Random(47); + a = new int[rand.nextInt(20)]; + System.out.println("length of a = " + a.length); + System.out.println(Arrays.toString(a)); + } +} +/* Output: +length of a = 18 +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +*/ diff --git a/code/housekeeping/ArraysOfPrimitives.java b/code/housekeeping/ArraysOfPrimitives.java new file mode 100644 index 00000000..165afe89 --- /dev/null +++ b/code/housekeeping/ArraysOfPrimitives.java @@ -0,0 +1,23 @@ +// housekeeping/ArraysOfPrimitives.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ArraysOfPrimitives { + public static void main(String[] args) { + int[] a1 = { 1, 2, 3, 4, 5 }; + int[] a2; + a2 = a1; + for(int i = 0; i < a2.length; i++) + a2[i] += 1; + for(int i = 0; i < a1.length; i++) + System.out.println("a1[" + i + "] = " + a1[i]); + } +} +/* Output: +a1[0] = 2 +a1[1] = 3 +a1[2] = 4 +a1[3] = 5 +a1[4] = 6 +*/ diff --git a/code/housekeeping/AutoboxingVarargs.java b/code/housekeeping/AutoboxingVarargs.java new file mode 100644 index 00000000..c670fa67 --- /dev/null +++ b/code/housekeeping/AutoboxingVarargs.java @@ -0,0 +1,22 @@ +// housekeeping/AutoboxingVarargs.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class AutoboxingVarargs { + public static void f(Integer... args) { + for(Integer i : args) + System.out.print(i + " "); + System.out.println(); + } + public static void main(String[] args) { + f(1, 2); + f(4, 5, 6, 7, 8, 9); + f(10, 11, 12); + } +} +/* Output: +1 2 +4 5 6 7 8 9 +10 11 12 +*/ diff --git a/code/housekeeping/BananaPeel.java b/code/housekeeping/BananaPeel.java new file mode 100644 index 00000000..b3e01b27 --- /dev/null +++ b/code/housekeeping/BananaPeel.java @@ -0,0 +1,15 @@ +// housekeeping/BananaPeel.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Banana { void peel(int i) { /* ... */ } } + +public class BananaPeel { + public static void main(String[] args) { + Banana a = new Banana(), + b = new Banana(); + a.peel(1); + b.peel(2); + } +} diff --git a/code/housekeeping/Burrito.java b/code/housekeeping/Burrito.java new file mode 100644 index 00000000..e3fd028b --- /dev/null +++ b/code/housekeeping/Burrito.java @@ -0,0 +1,39 @@ +// housekeeping/Burrito.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Burrito { + Spiciness degree; + public Burrito(Spiciness degree) { + this.degree = degree; + } + public void describe() { + System.out.print("This burrito is "); + switch(degree) { + case NOT: System.out.println( + "not spicy at all."); + break; + case MILD: + case MEDIUM: System.out.println("a little hot."); + break; + case HOT: + case FLAMING: + default: System.out.println("maybe too hot."); + } + } + public static void main(String[] args) { + Burrito + plain = new Burrito(Spiciness.NOT), + greenChile = new Burrito(Spiciness.MEDIUM), + jalapeno = new Burrito(Spiciness.HOT); + plain.describe(); + greenChile.describe(); + jalapeno.describe(); + } +} +/* Output: +This burrito is not spicy at all. +This burrito is a little hot. +This burrito is maybe too hot. +*/ diff --git a/code/housekeeping/Counter.java b/code/housekeeping/Counter.java new file mode 100644 index 00000000..d0a58ecc --- /dev/null +++ b/code/housekeeping/Counter.java @@ -0,0 +1,9 @@ +// housekeeping/Counter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class Counter { + int i; + Counter() { i = 7; } + // ... +} diff --git a/code/housekeeping/DefaultConstructor.java b/code/housekeeping/DefaultConstructor.java new file mode 100644 index 00000000..22e3787d --- /dev/null +++ b/code/housekeeping/DefaultConstructor.java @@ -0,0 +1,12 @@ +// housekeeping/DefaultConstructor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Bird {} + +public class DefaultConstructor { + public static void main(String[] args) { + Bird b = new Bird(); // Default! + } +} diff --git a/code/housekeeping/Demotion.java b/code/housekeeping/Demotion.java new file mode 100644 index 00000000..ad2c4e86 --- /dev/null +++ b/code/housekeeping/Demotion.java @@ -0,0 +1,43 @@ +// housekeeping/Demotion.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demotion of primitives + +public class Demotion { + void f1(double x) { + System.out.println("f1(double)"); + } + void f2(float x) { System.out.println("f2(float)"); } + void f3(long x) { System.out.println("f3(long)"); } + void f4(int x) { System.out.println("f4(int)"); } + void f5(short x) { System.out.println("f5(short)"); } + void f6(byte x) { System.out.println("f6(byte)"); } + void f7(char x) { System.out.println("f7(char)"); } + + void testDouble() { + double x = 0; + System.out.println("double argument:"); + f1(x); + f2((float)x); + f3((long)x); + f4((int)x); + f5((short)x); + f6((byte)x); + f7((char)x); + } + public static void main(String[] args) { + Demotion p = new Demotion(); + p.testDouble(); + } +} +/* Output: +double argument: +f1(double) +f2(float) +f3(long) +f4(int) +f5(short) +f6(byte) +f7(char) +*/ diff --git a/code/housekeeping/DynamicArray.java b/code/housekeeping/DynamicArray.java new file mode 100644 index 00000000..726ec034 --- /dev/null +++ b/code/housekeeping/DynamicArray.java @@ -0,0 +1,21 @@ +// housekeeping/DynamicArray.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Array initialization + +public class DynamicArray { + public static void main(String[] args) { + Other.main(new String[]{ "fiddle", "de", "dum" }); + } +} + +class Other { + public static void main(String[] args) { + for(String s : args) + System.out.print(s + " "); + } +} +/* Output: +fiddle de dum +*/ diff --git a/code/housekeeping/EnumOrder.java b/code/housekeeping/EnumOrder.java new file mode 100644 index 00000000..a3c96284 --- /dev/null +++ b/code/housekeeping/EnumOrder.java @@ -0,0 +1,19 @@ +// housekeeping/EnumOrder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class EnumOrder { + public static void main(String[] args) { + for(Spiciness s : Spiciness.values()) + System.out.println( + s + ", ordinal " + s.ordinal()); + } +} +/* Output: +NOT, ordinal 0 +MILD, ordinal 1 +MEDIUM, ordinal 2 +HOT, ordinal 3 +FLAMING, ordinal 4 +*/ diff --git a/code/housekeeping/ExplicitStatic.java b/code/housekeeping/ExplicitStatic.java new file mode 100644 index 00000000..7d9cb31a --- /dev/null +++ b/code/housekeeping/ExplicitStatic.java @@ -0,0 +1,41 @@ +// housekeeping/ExplicitStatic.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Explicit static initialization with "static" clause + +class Cup { + Cup(int marker) { + System.out.println("Cup(" + marker + ")"); + } + void f(int marker) { + System.out.println("f(" + marker + ")"); + } +} + +class Cups { + static Cup cup1; + static Cup cup2; + static { + cup1 = new Cup(1); + cup2 = new Cup(2); + } + Cups() { + System.out.println("Cups()"); + } +} + +public class ExplicitStatic { + public static void main(String[] args) { + System.out.println("Inside main()"); + Cups.cup1.f(99); // [1] + } + // static Cups cups1 = new Cups(); // [2] + // static Cups cups2 = new Cups(); // [2] +} +/* Output: +Inside main() +Cup(1) +Cup(2) +f(99) +*/ diff --git a/code/housekeeping/Flower.java b/code/housekeeping/Flower.java new file mode 100644 index 00000000..a62d7cbe --- /dev/null +++ b/code/housekeeping/Flower.java @@ -0,0 +1,46 @@ +// housekeeping/Flower.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Calling constructors with "this" + +public class Flower { + int petalCount = 0; + String s = "initial value"; + Flower(int petals) { + petalCount = petals; + System.out.println( + "Constructor w/ int arg only, petalCount= " + + petalCount); + } + Flower(String ss) { + System.out.println( + "Constructor w/ String arg only, s = " + ss); + s = ss; + } + Flower(String s, int petals) { + this(petals); + //- this(s); // Can't call two! + this.s = s; // Another use of "this" + System.out.println("String & int args"); + } + Flower() { + this("hi", 47); + System.out.println("no-arg constructor"); + } + void printPetalCount() { + //- this(11); // Not inside non-constructor! + System.out.println( + "petalCount = " + petalCount + " s = "+ s); + } + public static void main(String[] args) { + Flower x = new Flower(); + x.printPetalCount(); + } +} +/* Output: +Constructor w/ int arg only, petalCount= 47 +String & int args +no-arg constructor +petalCount = 47 s = hi +*/ diff --git a/code/housekeeping/InitialValues.java b/code/housekeeping/InitialValues.java new file mode 100644 index 00000000..dced4dd2 --- /dev/null +++ b/code/housekeeping/InitialValues.java @@ -0,0 +1,44 @@ +// housekeeping/InitialValues.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Shows default initial values + +public class InitialValues { + boolean t; + char c; + byte b; + short s; + int i; + long l; + float f; + double d; + InitialValues reference; + void printInitialValues() { + System.out.println("Data type Initial value"); + System.out.println("boolean " + t); + System.out.println("char [" + c + "]"); + System.out.println("byte " + b); + System.out.println("short " + s); + System.out.println("int " + i); + System.out.println("long " + l); + System.out.println("float " + f); + System.out.println("double " + d); + System.out.println("reference " + reference); + } + public static void main(String[] args) { + new InitialValues().printInitialValues(); + } +} +/* Output: +Data type Initial value +boolean false +char [NUL] +byte 0 +short 0 +int 0 +long 0 +float 0.0 +double 0.0 +reference null +*/ diff --git a/code/housekeeping/InitialValues2.java b/code/housekeeping/InitialValues2.java new file mode 100644 index 00000000..1cb50974 --- /dev/null +++ b/code/housekeeping/InitialValues2.java @@ -0,0 +1,16 @@ +// housekeeping/InitialValues2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Providing explicit initial values + +public class InitialValues2 { + boolean bool = true; + char ch = 'x'; + byte b = 47; + short s = 0xff; + int i = 999; + long lng = 1; + float f = 3.14f; + double d = 3.14159; +} diff --git a/code/housekeeping/Leaf.java b/code/housekeeping/Leaf.java new file mode 100644 index 00000000..f9c560b2 --- /dev/null +++ b/code/housekeeping/Leaf.java @@ -0,0 +1,23 @@ +// housekeeping/Leaf.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple use of the "this" keyword + +public class Leaf { + int i = 0; + Leaf increment() { + i++; + return this; + } + void print() { + System.out.println("i = " + i); + } + public static void main(String[] args) { + Leaf x = new Leaf(); + x.increment().increment().increment().print(); + } +} +/* Output: +i = 3 +*/ diff --git a/code/housekeeping/Measurement.java b/code/housekeeping/Measurement.java new file mode 100644 index 00000000..8a920779 --- /dev/null +++ b/code/housekeeping/Measurement.java @@ -0,0 +1,10 @@ +// housekeeping/Measurement.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +class Depth {} + +public class Measurement { + Depth d = new Depth(); + // ... +} diff --git a/code/housekeeping/MethodInit.java b/code/housekeeping/MethodInit.java new file mode 100644 index 00000000..84e15fce --- /dev/null +++ b/code/housekeeping/MethodInit.java @@ -0,0 +1,8 @@ +// housekeeping/MethodInit.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class MethodInit { + int i = f(); + int f() { return 11; } +} diff --git a/code/housekeeping/MethodInit2.java b/code/housekeeping/MethodInit2.java new file mode 100644 index 00000000..24750fb2 --- /dev/null +++ b/code/housekeeping/MethodInit2.java @@ -0,0 +1,10 @@ +// housekeeping/MethodInit2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class MethodInit2 { + int i = f(); + int j = g(i); + int f() { return 11; } + int g(int n) { return n * 10; } +} diff --git a/code/housekeeping/MethodInit3.java b/code/housekeeping/MethodInit3.java new file mode 100644 index 00000000..2a6524ab --- /dev/null +++ b/code/housekeeping/MethodInit3.java @@ -0,0 +1,10 @@ +// housekeeping/MethodInit3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class MethodInit3 { + //- int j = g(i); // Illegal forward reference + int i = f(); + int f() { return 11; } + int g(int n) { return n * 10; } +} diff --git a/code/housekeeping/Mugs.java b/code/housekeeping/Mugs.java new file mode 100644 index 00000000..e4ebba69 --- /dev/null +++ b/code/housekeeping/Mugs.java @@ -0,0 +1,47 @@ +// housekeeping/Mugs.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Instance initialization + +class Mug { + Mug(int marker) { + System.out.println("Mug(" + marker + ")"); + } +} + +public class Mugs { + Mug mug1; + Mug mug2; + { // [1] + mug1 = new Mug(1); + mug2 = new Mug(2); + System.out.println("mug1 & mug2 initialized"); + } + Mugs() { + System.out.println("Mugs()"); + } + Mugs(int i) { + System.out.println("Mugs(int)"); + } + public static void main(String[] args) { + System.out.println("Inside main()"); + new Mugs(); + System.out.println("new Mugs() completed"); + new Mugs(1); + System.out.println("new Mugs(1) completed"); + } +} +/* Output: +Inside main() +Mug(1) +Mug(2) +mug1 & mug2 initialized +Mugs() +new Mugs() completed +Mug(1) +Mug(2) +mug1 & mug2 initialized +Mugs(int) +new Mugs(1) completed +*/ diff --git a/code/housekeeping/NewVarArgs.java b/code/housekeeping/NewVarArgs.java new file mode 100644 index 00000000..291dd134 --- /dev/null +++ b/code/housekeeping/NewVarArgs.java @@ -0,0 +1,30 @@ +// housekeeping/NewVarArgs.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using array syntax to create variable argument lists + +public class NewVarArgs { + static void printArray(Object... args) { + for(Object obj : args) + System.out.print(obj + " "); + System.out.println(); + } + public static void main(String[] args) { + // Can take individual elements: + printArray(47, (float) 3.14, 11.11); + printArray(47, 3.14F, 11.11); + printArray("one", "two", "three"); + printArray(new A(), new A(), new A()); + // Or an array: + printArray((Object[])new Integer[]{ 1, 2, 3, 4 }); + printArray(); // Empty list is OK + } +} +/* Output: +47 3.14 11.11 +47 3.14 11.11 +one two three +A@15db9742 A@6d06d69c A@7852e922 +1 2 3 4 +*/ diff --git a/code/housekeeping/NoSynthesis.java b/code/housekeeping/NoSynthesis.java new file mode 100644 index 00000000..217c2023 --- /dev/null +++ b/code/housekeeping/NoSynthesis.java @@ -0,0 +1,17 @@ +// housekeeping/NoSynthesis.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Bird2 { + Bird2(int i) {} + Bird2(double d) {} +} + +public class NoSynthesis { + public static void main(String[] args) { + //- Bird2 b = new Bird2(); // No default + Bird2 b2 = new Bird2(1); + Bird2 b3 = new Bird2(1.0); + } +} diff --git a/code/housekeeping/OptionalTrailingArguments.java b/code/housekeeping/OptionalTrailingArguments.java new file mode 100644 index 00000000..d7ee9fbb --- /dev/null +++ b/code/housekeeping/OptionalTrailingArguments.java @@ -0,0 +1,23 @@ +// housekeeping/OptionalTrailingArguments.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class OptionalTrailingArguments { + static void f(int required, String... trailing) { + System.out.print("required: " + required + " "); + for(String s : trailing) + System.out.print(s + " "); + System.out.println(); + } + public static void main(String[] args) { + f(1, "one"); + f(2, "two", "three"); + f(0); + } +} +/* Output: +required: 1 one +required: 2 two three +required: 0 +*/ diff --git a/code/housekeeping/OrderOfInitialization.java b/code/housekeeping/OrderOfInitialization.java new file mode 100644 index 00000000..c715ed7c --- /dev/null +++ b/code/housekeeping/OrderOfInitialization.java @@ -0,0 +1,40 @@ +// housekeeping/OrderOfInitialization.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates initialization order + +// When the constructor is called to create a +// Window object, you'll see a message: +class Window { + Window(int marker) { + System.out.println("Window(" + marker + ")"); + } +} + +class House { + Window w1 = new Window(1); // Before constructor + House() { + // Show that we're in the constructor: + System.out.println("House()"); + w3 = new Window(33); // Reinitialize w3 + } + Window w2 = new Window(2); // After constructor + void f() { System.out.println("f()"); } + Window w3 = new Window(3); // At end +} + +public class OrderOfInitialization { + public static void main(String[] args) { + House h = new House(); + h.f(); // Shows that construction is done + } +} +/* Output: +Window(1) +Window(2) +Window(3) +House() +Window(33) +f() +*/ diff --git a/code/housekeeping/Overloading.java b/code/housekeeping/Overloading.java new file mode 100644 index 00000000..99d21bf8 --- /dev/null +++ b/code/housekeeping/Overloading.java @@ -0,0 +1,56 @@ +// housekeeping/Overloading.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Both constructor and ordinary method overloading + +class Tree { + int height; + Tree() { + System.out.println("Planting a seedling"); + height = 0; + } + Tree(int initialHeight) { + height = initialHeight; + System.out.println("Creating new Tree that is " + + height + " feet tall"); + } + void info() { + System.out.println( + "Tree is " + height + " feet tall"); + } + void info(String s) { + System.out.println( + s + ": Tree is " + height + " feet tall"); + } +} + +public class Overloading { + public static void main(String[] args) { + for(int i = 0; i < 5; i++) { + Tree t = new Tree(i); + t.info(); + t.info("overloaded method"); + } + // Overloaded constructor: + new Tree(); + } +} +/* Output: +Creating new Tree that is 0 feet tall +Tree is 0 feet tall +overloaded method: Tree is 0 feet tall +Creating new Tree that is 1 feet tall +Tree is 1 feet tall +overloaded method: Tree is 1 feet tall +Creating new Tree that is 2 feet tall +Tree is 2 feet tall +overloaded method: Tree is 2 feet tall +Creating new Tree that is 3 feet tall +Tree is 3 feet tall +overloaded method: Tree is 3 feet tall +Creating new Tree that is 4 feet tall +Tree is 4 feet tall +overloaded method: Tree is 4 feet tall +Planting a seedling +*/ diff --git a/code/housekeeping/OverloadingOrder.java b/code/housekeeping/OverloadingOrder.java new file mode 100644 index 00000000..42f6466e --- /dev/null +++ b/code/housekeeping/OverloadingOrder.java @@ -0,0 +1,22 @@ +// housekeeping/OverloadingOrder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Overloading based on the order of the arguments + +public class OverloadingOrder { + static void f(String s, int i) { + System.out.println("String: " + s + ", int: " + i); + } + static void f(int i, String s) { + System.out.println("int: " + i + ", String: " + s); + } + public static void main(String[] args) { + f("String first", 11); + f(99, "Int first"); + } +} +/* Output: +String: String first, int: 11 +int: 99, String: Int first +*/ diff --git a/code/housekeeping/OverloadingVarargs.java b/code/housekeeping/OverloadingVarargs.java new file mode 100644 index 00000000..c13b7406 --- /dev/null +++ b/code/housekeeping/OverloadingVarargs.java @@ -0,0 +1,37 @@ +// housekeeping/OverloadingVarargs.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class OverloadingVarargs { + static void f(Character... args) { + System.out.print("first"); + for(Character c : args) + System.out.print(" " + c); + System.out.println(); + } + static void f(Integer... args) { + System.out.print("second"); + for(Integer i : args) + System.out.print(" " + i); + System.out.println(); + } + static void f(Long... args) { + System.out.println("third"); + } + public static void main(String[] args) { + f('a', 'b', 'c'); + f(1); + f(2, 1); + f(0); + f(0L); + //- f(); // Won't compile -- ambiguous + } +} +/* Output: +first a b c +second 1 +second 2 1 +second 0 +third +*/ diff --git a/code/housekeeping/OverloadingVarargs2.java b/code/housekeeping/OverloadingVarargs2.java new file mode 100644 index 00000000..c3a09845 --- /dev/null +++ b/code/housekeeping/OverloadingVarargs2.java @@ -0,0 +1,18 @@ +// housekeeping/OverloadingVarargs2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} + +public class OverloadingVarargs2 { + static void f(float i, Character... args) { + System.out.println("first"); + } + static void f(Character... args) { + System.out.print("second"); + } + public static void main(String[] args) { + f(1, 'a'); + f('a', 'b'); + } +} diff --git a/code/housekeeping/OverloadingVarargs3.java b/code/housekeeping/OverloadingVarargs3.java new file mode 100644 index 00000000..23e757ec --- /dev/null +++ b/code/housekeeping/OverloadingVarargs3.java @@ -0,0 +1,21 @@ +// housekeeping/OverloadingVarargs3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class OverloadingVarargs3 { + static void f(float i, Character... args) { + System.out.println("first"); + } + static void f(char c, Character... args) { + System.out.println("second"); + } + public static void main(String[] args) { + f(1, 'a'); + f('a', 'b'); + } +} +/* Output: +first +second +*/ diff --git a/code/housekeeping/PassingThis.java b/code/housekeeping/PassingThis.java new file mode 100644 index 00000000..ce725eab --- /dev/null +++ b/code/housekeeping/PassingThis.java @@ -0,0 +1,31 @@ +// housekeeping/PassingThis.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Person { + public void eat(Apple apple) { + Apple peeled = apple.getPeeled(); + System.out.println("Yummy"); + } +} + +class Peeler { + static Apple peel(Apple apple) { + // ... remove peel + return apple; // Peeled + } +} + +class Apple { + Apple getPeeled() { return Peeler.peel(this); } +} + +public class PassingThis { + public static void main(String[] args) { + new Person().eat(new Apple()); + } +} +/* Output: +Yummy +*/ diff --git a/code/housekeeping/PrimitiveOverloading.java b/code/housekeeping/PrimitiveOverloading.java new file mode 100644 index 00000000..1d8c1e2c --- /dev/null +++ b/code/housekeeping/PrimitiveOverloading.java @@ -0,0 +1,120 @@ +// housekeeping/PrimitiveOverloading.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Promotion of primitives and overloading + +public class PrimitiveOverloading { + void f1(char x) { System.out.print("f1(char) "); } + void f1(byte x) { System.out.print("f1(byte) "); } + void f1(short x) { System.out.print("f1(short) "); } + void f1(int x) { System.out.print("f1(int) "); } + void f1(long x) { System.out.print("f1(long) "); } + void f1(float x) { System.out.print("f1(float) "); } + void f1(double x) { System.out.print("f1(double) "); } + + void f2(byte x) { System.out.print("f2(byte) "); } + void f2(short x) { System.out.print("f2(short) "); } + void f2(int x) { System.out.print("f2(int) "); } + void f2(long x) { System.out.print("f2(long) "); } + void f2(float x) { System.out.print("f2(float) "); } + void f2(double x) { System.out.print("f2(double) "); } + + void f3(short x) { System.out.print("f3(short) "); } + void f3(int x) { System.out.print("f3(int) "); } + void f3(long x) { System.out.print("f3(long) "); } + void f3(float x) { System.out.print("f3(float) "); } + void f3(double x) { System.out.print("f3(double) "); } + + void f4(int x) { System.out.print("f4(int) "); } + void f4(long x) { System.out.print("f4(long) "); } + void f4(float x) { System.out.print("f4(float) "); } + void f4(double x) { System.out.print("f4(double) "); } + + void f5(long x) { System.out.print("f5(long) "); } + void f5(float x) { System.out.print("f5(float) "); } + void f5(double x) { System.out.print("f5(double) "); } + + void f6(float x) { System.out.print("f6(float) "); } + void f6(double x) { System.out.print("f6(double) "); } + + void f7(double x) { System.out.print("f7(double) "); } + + void testConstVal() { + System.out.print("5: "); + f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5); + System.out.println(); + } + void testChar() { + char x = 'x'; + System.out.print("char: "); + f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); + System.out.println(); + } + void testByte() { + byte x = 0; + System.out.print("byte: "); + f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); + System.out.println(); + } + void testShort() { + short x = 0; + System.out.print("short: "); + f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); + System.out.println(); + } + void testInt() { + int x = 0; + System.out.print("int: "); + f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); + System.out.println(); + } + void testLong() { + long x = 0; + System.out.print("long: "); + f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); + System.out.println(); + } + void testFloat() { + float x = 0; + System.out.print("float: "); + f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); + System.out.println(); + } + void testDouble() { + double x = 0; + System.out.print("double: "); + f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); + System.out.println(); + } + public static void main(String[] args) { + PrimitiveOverloading p = + new PrimitiveOverloading(); + p.testConstVal(); + p.testChar(); + p.testByte(); + p.testShort(); + p.testInt(); + p.testLong(); + p.testFloat(); + p.testDouble(); + } +} +/* Output: +5: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) +f7(double) +char: f1(char) f2(int) f3(int) f4(int) f5(long) +f6(float) f7(double) +byte: f1(byte) f2(byte) f3(short) f4(int) f5(long) +f6(float) f7(double) +short: f1(short) f2(short) f3(short) f4(int) f5(long) +f6(float) f7(double) +int: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) +f7(double) +long: f1(long) f2(long) f3(long) f4(long) f5(long) +f6(float) f7(double) +float: f1(float) f2(float) f3(float) f4(float) +f5(float) f6(float) f7(double) +double: f1(double) f2(double) f3(double) f4(double) +f5(double) f6(double) f7(double) +*/ diff --git a/code/housekeeping/SimpleConstructor.java b/code/housekeeping/SimpleConstructor.java new file mode 100644 index 00000000..c6917c33 --- /dev/null +++ b/code/housekeeping/SimpleConstructor.java @@ -0,0 +1,21 @@ +// housekeeping/SimpleConstructor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of a simple constructor + +class Rock { + Rock() { // This is the constructor + System.out.print("Rock "); + } +} + +public class SimpleConstructor { + public static void main(String[] args) { + for(int i = 0; i < 10; i++) + new Rock(); + } +} +/* Output: +Rock Rock Rock Rock Rock Rock Rock Rock Rock Rock +*/ diff --git a/code/housekeeping/SimpleConstructor2.java b/code/housekeeping/SimpleConstructor2.java new file mode 100644 index 00000000..4a191af7 --- /dev/null +++ b/code/housekeeping/SimpleConstructor2.java @@ -0,0 +1,21 @@ +// housekeeping/SimpleConstructor2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Constructors can have arguments + +class Rock2 { + Rock2(int i) { + System.out.print("Rock " + i + " "); + } +} + +public class SimpleConstructor2 { + public static void main(String[] args) { + for(int i = 0; i < 8; i++) + new Rock2(i); + } +} +/* Output: +Rock 0 Rock 1 Rock 2 Rock 3 Rock 4 Rock 5 Rock 6 Rock 7 +*/ diff --git a/code/housekeeping/SimpleEnumUse.java b/code/housekeeping/SimpleEnumUse.java new file mode 100644 index 00000000..cc0de33b --- /dev/null +++ b/code/housekeeping/SimpleEnumUse.java @@ -0,0 +1,14 @@ +// housekeeping/SimpleEnumUse.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SimpleEnumUse { + public static void main(String[] args) { + Spiciness howHot = Spiciness.MEDIUM; + System.out.println(howHot); + } +} +/* Output: +MEDIUM +*/ diff --git a/code/housekeeping/Spiciness.java b/code/housekeeping/Spiciness.java new file mode 100644 index 00000000..a134a822 --- /dev/null +++ b/code/housekeeping/Spiciness.java @@ -0,0 +1,8 @@ +// housekeeping/Spiciness.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public enum Spiciness { + NOT, MILD, MEDIUM, HOT, FLAMING +} diff --git a/code/housekeeping/Spoon.java b/code/housekeeping/Spoon.java new file mode 100644 index 00000000..fd344815 --- /dev/null +++ b/code/housekeeping/Spoon.java @@ -0,0 +1,10 @@ +// housekeeping/Spoon.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class Spoon { + static int i; + static { + i = 47; + } +} diff --git a/code/housekeeping/StaticInitialization.java b/code/housekeeping/StaticInitialization.java new file mode 100644 index 00000000..0cfe99ae --- /dev/null +++ b/code/housekeeping/StaticInitialization.java @@ -0,0 +1,73 @@ +// housekeeping/StaticInitialization.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Specifying initial values in a class definition + +class Bowl { + Bowl(int marker) { + System.out.println("Bowl(" + marker + ")"); + } + void f1(int marker) { + System.out.println("f1(" + marker + ")"); + } +} + +class Table { + static Bowl bowl1 = new Bowl(1); + Table() { + System.out.println("Table()"); + bowl2.f1(1); + } + void f2(int marker) { + System.out.println("f2(" + marker + ")"); + } + static Bowl bowl2 = new Bowl(2); +} + +class Cupboard { + Bowl bowl3 = new Bowl(3); + static Bowl bowl4 = new Bowl(4); + Cupboard() { + System.out.println("Cupboard()"); + bowl4.f1(2); + } + void f3(int marker) { + System.out.println("f3(" + marker + ")"); + } + static Bowl bowl5 = new Bowl(5); +} + +public class StaticInitialization { + public static void main(String[] args) { + System.out.println("main creating new Cupboard()"); + new Cupboard(); + System.out.println("main creating new Cupboard()"); + new Cupboard(); + table.f2(1); + cupboard.f3(1); + } + static Table table = new Table(); + static Cupboard cupboard = new Cupboard(); +} +/* Output: +Bowl(1) +Bowl(2) +Table() +f1(1) +Bowl(4) +Bowl(5) +Bowl(3) +Cupboard() +f1(2) +main creating new Cupboard() +Bowl(3) +Cupboard() +f1(2) +main creating new Cupboard() +Bowl(3) +Cupboard() +f1(2) +f2(1) +f3(1) +*/ diff --git a/code/housekeeping/TerminationCondition.java b/code/housekeeping/TerminationCondition.java new file mode 100644 index 00000000..dc8d347b --- /dev/null +++ b/code/housekeeping/TerminationCondition.java @@ -0,0 +1,41 @@ +// housekeeping/TerminationCondition.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using finalize() to detect an object that +// hasn't been properly cleaned up +import onjava.*; + +class Book { + boolean checkedOut = false; + Book(boolean checkOut) { + checkedOut = checkOut; + } + void checkIn() { + checkedOut = false; + } + @SuppressWarnings("deprecation") + @Override + public void finalize() { + if(checkedOut) + System.out.println("Error: checked out"); + // Normally, you'll also do this: + // super.finalize(); // Call the base-class version + } +} + +public class TerminationCondition { + public static void main(String[] args) { + Book novel = new Book(true); + // Proper cleanup: + novel.checkIn(); + // Drop the reference, forget to clean up: + new Book(true); + // Force garbage collection & finalization: + System.gc(); + new Nap(1); // One second delay + } +} +/* Output: +Error: checked out +*/ diff --git a/code/housekeeping/VarArgs.java b/code/housekeeping/VarArgs.java new file mode 100644 index 00000000..73a94c39 --- /dev/null +++ b/code/housekeeping/VarArgs.java @@ -0,0 +1,26 @@ +// housekeeping/VarArgs.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using array syntax to create variable argument lists + +class A {} + +public class VarArgs { + static void printArray(Object[] args) { + for(Object obj : args) + System.out.print(obj + " "); + System.out.println(); + } + public static void main(String[] args) { + printArray(new Object[]{ + 47, (float) 3.14, 11.11}); + printArray(new Object[]{"one", "two", "three" }); + printArray(new Object[]{new A(), new A(), new A()}); + } +} +/* Output: +47 3.14 11.11 +one two three +A@15db9742 A@6d06d69c A@7852e922 +*/ diff --git a/code/housekeeping/VarargType.java b/code/housekeeping/VarargType.java new file mode 100644 index 00000000..5b25b053 --- /dev/null +++ b/code/housekeeping/VarargType.java @@ -0,0 +1,30 @@ +// housekeeping/VarargType.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class VarargType { + static void f(Character... args) { + System.out.print(args.getClass()); + System.out.println(" length " + args.length); + } + static void g(int... args) { + System.out.print(args.getClass()); + System.out.println(" length " + args.length); + } + public static void main(String[] args) { + f('a'); + f(); + g(1); + g(); + System.out.println("int[]: " + + new int[0].getClass()); + } +} +/* Output: +class [Ljava.lang.Character; length 1 +class [Ljava.lang.Character; length 0 +class [I length 1 +class [I length 0 +int[]: class [I +*/ diff --git a/code/innerclasses/AnonymousConstructor.java b/code/innerclasses/AnonymousConstructor.java new file mode 100644 index 00000000..d8e08e7c --- /dev/null +++ b/code/innerclasses/AnonymousConstructor.java @@ -0,0 +1,34 @@ +// innerclasses/AnonymousConstructor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating a constructor for an anonymous inner class + +abstract class Base { + Base(int i) { + System.out.println("Base constructor, i = " + i); + } + public abstract void f(); +} + +public class AnonymousConstructor { + public static Base getBase(int i) { + return new Base(i) { + { System.out.println( + "Inside instance initializer"); } + @Override + public void f() { + System.out.println("In anonymous f()"); + } + }; + } + public static void main(String[] args) { + Base base = getBase(47); + base.f(); + } +} +/* Output: +Base constructor, i = 47 +Inside instance initializer +In anonymous f() +*/ diff --git a/code/innerclasses/BigEgg.java b/code/innerclasses/BigEgg.java new file mode 100644 index 00000000..7b2c3624 --- /dev/null +++ b/code/innerclasses/BigEgg.java @@ -0,0 +1,33 @@ +// innerclasses/BigEgg.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An inner class cannot be overridden like a method + +class Egg { + private Yolk y; + protected class Yolk { + public Yolk() { + System.out.println("Egg.Yolk()"); + } + } + Egg() { + System.out.println("New Egg()"); + y = new Yolk(); + } +} + +public class BigEgg extends Egg { + public class Yolk { + public Yolk() { + System.out.println("BigEgg.Yolk()"); + } + } + public static void main(String[] args) { + new BigEgg(); + } +} +/* Output: +New Egg() +Egg.Yolk() +*/ diff --git a/code/innerclasses/BigEgg2.java b/code/innerclasses/BigEgg2.java new file mode 100644 index 00000000..1631008d --- /dev/null +++ b/code/innerclasses/BigEgg2.java @@ -0,0 +1,44 @@ +// innerclasses/BigEgg2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Proper inheritance of an inner class + +class Egg2 { + protected class Yolk { + public Yolk() { + System.out.println("Egg2.Yolk()"); + } + public void f() { + System.out.println("Egg2.Yolk.f()"); + } + } + private Yolk y = new Yolk(); + Egg2() { System.out.println("New Egg2()"); } + public void insertYolk(Yolk yy) { y = yy; } + public void g() { y.f(); } +} + +public class BigEgg2 extends Egg2 { + public class Yolk extends Egg2.Yolk { + public Yolk() { + System.out.println("BigEgg2.Yolk()"); + } + @Override + public void f() { + System.out.println("BigEgg2.Yolk.f()"); + } + } + public BigEgg2() { insertYolk(new Yolk()); } + public static void main(String[] args) { + Egg2 e2 = new BigEgg2(); + e2.g(); + } +} +/* Output: +Egg2.Yolk() +New Egg2() +Egg2.Yolk() +BigEgg2.Yolk() +BigEgg2.Yolk.f() +*/ diff --git a/code/innerclasses/Callbacks.java b/code/innerclasses/Callbacks.java new file mode 100644 index 00000000..d1659332 --- /dev/null +++ b/code/innerclasses/Callbacks.java @@ -0,0 +1,84 @@ +// innerclasses/Callbacks.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using inner classes for callbacks +// {java innerclasses.Callbacks} +package innerclasses; + +interface Incrementable { + void increment(); +} + +// Very simple to just implement the interface: +class Callee1 implements Incrementable { + private int i = 0; + @Override + public void increment() { + i++; + System.out.println(i); + } +} + +class MyIncrement { + public void increment() { + System.out.println("Other operation"); + } + static void f(MyIncrement mi) { mi.increment(); } +} + +// If your class must implement increment() in +// some other way, you must use an inner class: +class Callee2 extends MyIncrement { + private int i = 0; + @Override + public void increment() { + super.increment(); + i++; + System.out.println(i); + } + private class Closure implements Incrementable { + @Override + public void increment() { + // Specify outer-class method, otherwise + // you'll get an infinite recursion: + Callee2.this.increment(); + } + } + Incrementable getCallbackReference() { + return new Closure(); + } +} + +class Caller { + private Incrementable callbackReference; + Caller(Incrementable cbh) { + callbackReference = cbh; + } + void go() { callbackReference.increment(); } +} + +public class Callbacks { + public static void main(String[] args) { + Callee1 c1 = new Callee1(); + Callee2 c2 = new Callee2(); + MyIncrement.f(c2); + Caller caller1 = new Caller(c1); + Caller caller2 = + new Caller(c2.getCallbackReference()); + caller1.go(); + caller1.go(); + caller2.go(); + caller2.go(); + } +} +/* Output: +Other operation +1 +1 +2 +Other operation +2 +Other operation +3 +*/ diff --git a/code/innerclasses/ClassInInterface.java b/code/innerclasses/ClassInInterface.java new file mode 100644 index 00000000..c3cc0589 --- /dev/null +++ b/code/innerclasses/ClassInInterface.java @@ -0,0 +1,21 @@ +// innerclasses/ClassInInterface.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java ClassInInterface$Test} + +public interface ClassInInterface { + void howdy(); + class Test implements ClassInInterface { + @Override + public void howdy() { + System.out.println("Howdy!"); + } + public static void main(String[] args) { + new Test().howdy(); + } + } +} +/* Output: +Howdy! +*/ diff --git a/code/innerclasses/Contents.java b/code/innerclasses/Contents.java new file mode 100644 index 00000000..0cebe1a0 --- /dev/null +++ b/code/innerclasses/Contents.java @@ -0,0 +1,7 @@ +// innerclasses/Contents.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public interface Contents { + int value(); +} diff --git a/code/innerclasses/Destination.java b/code/innerclasses/Destination.java new file mode 100644 index 00000000..bf221526 --- /dev/null +++ b/code/innerclasses/Destination.java @@ -0,0 +1,7 @@ +// innerclasses/Destination.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public interface Destination { + String readLabel(); +} diff --git a/code/innerclasses/DotNew.java b/code/innerclasses/DotNew.java new file mode 100644 index 00000000..317400e8 --- /dev/null +++ b/code/innerclasses/DotNew.java @@ -0,0 +1,13 @@ +// innerclasses/DotNew.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating an inner class directly using .new syntax + +public class DotNew { + public class Inner {} + public static void main(String[] args) { + DotNew dn = new DotNew(); + DotNew.Inner dni = dn.new Inner(); + } +} diff --git a/code/innerclasses/DotThis.java b/code/innerclasses/DotThis.java new file mode 100644 index 00000000..b87cb1f4 --- /dev/null +++ b/code/innerclasses/DotThis.java @@ -0,0 +1,24 @@ +// innerclasses/DotThis.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Accessing the outer-class object + +public class DotThis { + void f() { System.out.println("DotThis.f()"); } + public class Inner { + public DotThis outer() { + return DotThis.this; + // A plain "this" would be Inner's "this" + } + } + public Inner inner() { return new Inner(); } + public static void main(String[] args) { + DotThis dt = new DotThis(); + DotThis.Inner dti = dt.inner(); + dti.outer().f(); + } +} +/* Output: +DotThis.f() +*/ diff --git a/code/innerclasses/GreenhouseController.java b/code/innerclasses/GreenhouseController.java new file mode 100644 index 00000000..cf3ec653 --- /dev/null +++ b/code/innerclasses/GreenhouseController.java @@ -0,0 +1,54 @@ +// innerclasses/GreenhouseController.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Configure and execute the greenhouse system +import innerclasses.controller.*; + +public class GreenhouseController { + public static void main(String[] args) { + GreenhouseControls gc = new GreenhouseControls(); + // Instead of using code, you could parse + // configuration information from a text file: + gc.addEvent(gc.new Bell(900)); + Event[] eventList = { + gc.new ThermostatNight(0), + gc.new LightOn(200), + gc.new LightOff(400), + gc.new WaterOn(600), + gc.new WaterOff(800), + gc.new ThermostatDay(1400) + }; + gc.addEvent(gc.new Restart(2000, eventList)); + gc.addEvent( + new GreenhouseControls.Terminate(5000)); + gc.run(); + } +} +/* Output: +Thermostat on night setting +Light is on +Light is off +Greenhouse water is on +Greenhouse water is off +Bing! +Thermostat on day setting +Bing! +Restarting system +Thermostat on night setting +Light is on +Light is off +Greenhouse water is on +Bing! +Greenhouse water is off +Thermostat on day setting +Bing! +Restarting system +Thermostat on night setting +Light is on +Light is off +Bing! +Greenhouse water is on +Greenhouse water is off +Terminating +*/ diff --git a/code/innerclasses/GreenhouseControls.java b/code/innerclasses/GreenhouseControls.java new file mode 100644 index 00000000..57458d66 --- /dev/null +++ b/code/innerclasses/GreenhouseControls.java @@ -0,0 +1,150 @@ +// innerclasses/GreenhouseControls.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// This produces a specific application of the +// control system, all in a single class. Inner +// classes allow you to encapsulate different +// functionality for each type of event. +import innerclasses.controller.*; + +public class GreenhouseControls extends Controller { + private boolean light = false; + public class LightOn extends Event { + public LightOn(long delayTime) { + super(delayTime); + } + @Override + public void action() { + // Put hardware control code here to + // physically turn on the light. + light = true; + } + @Override + public String toString() { + return "Light is on"; + } + } + public class LightOff extends Event { + public LightOff(long delayTime) { + super(delayTime); + } + @Override + public void action() { + // Put hardware control code here to + // physically turn off the light. + light = false; + } + @Override + public String toString() { + return "Light is off"; + } + } + private boolean water = false; + public class WaterOn extends Event { + public WaterOn(long delayTime) { + super(delayTime); + } + @Override + public void action() { + // Put hardware control code here. + water = true; + } + @Override + public String toString() { + return "Greenhouse water is on"; + } + } + public class WaterOff extends Event { + public WaterOff(long delayTime) { + super(delayTime); + } + @Override + public void action() { + // Put hardware control code here. + water = false; + } + @Override + public String toString() { + return "Greenhouse water is off"; + } + } + private String thermostat = "Day"; + public class ThermostatNight extends Event { + public ThermostatNight(long delayTime) { + super(delayTime); + } + @Override + public void action() { + // Put hardware control code here. + thermostat = "Night"; + } + @Override + public String toString() { + return "Thermostat on night setting"; + } + } + public class ThermostatDay extends Event { + public ThermostatDay(long delayTime) { + super(delayTime); + } + @Override + public void action() { + // Put hardware control code here. + thermostat = "Day"; + } + @Override + public String toString() { + return "Thermostat on day setting"; + } + } + // An example of an action() that inserts a + // new one of itself into the event list: + public class Bell extends Event { + public Bell(long delayTime) { + super(delayTime); + } + @Override + public void action() { + addEvent(new Bell(delayTime.toMillis())); + } + @Override + public String toString() { + return "Bing!"; + } + } + public class Restart extends Event { + private Event[] eventList; + public + Restart(long delayTime, Event[] eventList) { + super(delayTime); + this.eventList = eventList; + for(Event e : eventList) + addEvent(e); + } + @Override + public void action() { + for(Event e : eventList) { + e.start(); // Rerun each event + addEvent(e); + } + start(); // Rerun this Event + addEvent(this); + } + @Override + public String toString() { + return "Restarting system"; + } + } + public static class Terminate extends Event { + public Terminate(long delayTime) { + super(delayTime); + } + @Override + public void action() { System.exit(0); } + @Override + public String toString() { + return "Terminating"; + } + } +} diff --git a/code/innerclasses/InheritInner.java b/code/innerclasses/InheritInner.java new file mode 100644 index 00000000..ffc86894 --- /dev/null +++ b/code/innerclasses/InheritInner.java @@ -0,0 +1,20 @@ +// innerclasses/InheritInner.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Inheriting an inner class + +class WithInner { + class Inner {} +} + +public class InheritInner extends WithInner.Inner { + //- InheritInner() {} // Won't compile + InheritInner(WithInner wi) { + wi.super(); + } + public static void main(String[] args) { + WithInner wi = new WithInner(); + InheritInner ii = new InheritInner(wi); + } +} diff --git a/code/innerclasses/LocalInnerClass.java b/code/innerclasses/LocalInnerClass.java new file mode 100644 index 00000000..01510854 --- /dev/null +++ b/code/innerclasses/LocalInnerClass.java @@ -0,0 +1,67 @@ +// innerclasses/LocalInnerClass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Holds a sequence of Objects + +interface Counter { + int next(); +} + +public class LocalInnerClass { + private int count = 0; + Counter getCounter(final String name) { + // A local inner class: + class LocalCounter implements Counter { + LocalCounter() { + // Local inner class can have a constructor + System.out.println("LocalCounter()"); + } + @Override + public int next() { + System.out.print(name); // Access local final + return count++; + } + } + return new LocalCounter(); + } + // Repeat, but with an anonymous inner class: + Counter getCounter2(final String name) { + return new Counter() { + // Anonymous inner class cannot have a named + // constructor, only an instance initializer: + { + System.out.println("Counter()"); + } + @Override + public int next() { + System.out.print(name); // Access local final + return count++; + } + }; + } + public static void main(String[] args) { + LocalInnerClass lic = new LocalInnerClass(); + Counter + c1 = lic.getCounter("Local inner "), + c2 = lic.getCounter2("Anonymous inner "); + for(int i = 0; i < 5; i++) + System.out.println(c1.next()); + for(int i = 0; i < 5; i++) + System.out.println(c2.next()); + } +} +/* Output: +LocalCounter() +Counter() +Local inner 0 +Local inner 1 +Local inner 2 +Local inner 3 +Local inner 4 +Anonymous inner 5 +Anonymous inner 6 +Anonymous inner 7 +Anonymous inner 8 +Anonymous inner 9 +*/ diff --git a/code/innerclasses/MultiImplementation.java b/code/innerclasses/MultiImplementation.java new file mode 100644 index 00000000..6eb6c494 --- /dev/null +++ b/code/innerclasses/MultiImplementation.java @@ -0,0 +1,25 @@ +// innerclasses/MultiImplementation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// For concrete or abstract classes, inner classes +// produce "multiple implementation inheritance" +// {java innerclasses.MultiImplementation} +package innerclasses; + +class D {} +abstract class E {} + +class Z extends D { + E makeE() { return new E() {}; } +} + +public class MultiImplementation { + static void takesD(D d) {} + static void takesE(E e) {} + public static void main(String[] args) { + Z z = new Z(); + takesD(z); + takesE(z.makeE()); + } +} diff --git a/code/innerclasses/MultiNestingAccess.java b/code/innerclasses/MultiNestingAccess.java new file mode 100644 index 00000000..bf9e3cb0 --- /dev/null +++ b/code/innerclasses/MultiNestingAccess.java @@ -0,0 +1,28 @@ +// innerclasses/MultiNestingAccess.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Nested classes can access all members of all +// levels of the classes they are nested within + +class MNA { + private void f() {} + class A { + private void g() {} + public class B { + void h() { + g(); + f(); + } + } + } +} + +public class MultiNestingAccess { + public static void main(String[] args) { + MNA mna = new MNA(); + MNA.A mnaa = mna.new A(); + MNA.A.B mnaab = mnaa.new B(); + mnaab.h(); + } +} diff --git a/code/innerclasses/Parcel1.java b/code/innerclasses/Parcel1.java new file mode 100644 index 00000000..94464cbc --- /dev/null +++ b/code/innerclasses/Parcel1.java @@ -0,0 +1,33 @@ +// innerclasses/Parcel1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating inner classes + +public class Parcel1 { + class Contents { + private int i = 11; + public int value() { return i; } + } + class Destination { + private String label; + Destination(String whereTo) { + label = whereTo; + } + String readLabel() { return label; } + } + // Using inner classes looks just like + // using any other class, within Parcel1: + public void ship(String dest) { + Contents c = new Contents(); + Destination d = new Destination(dest); + System.out.println(d.readLabel()); + } + public static void main(String[] args) { + Parcel1 p = new Parcel1(); + p.ship("Tasmania"); + } +} +/* Output: +Tasmania +*/ diff --git a/code/innerclasses/Parcel10.java b/code/innerclasses/Parcel10.java new file mode 100644 index 00000000..7150c192 --- /dev/null +++ b/code/innerclasses/Parcel10.java @@ -0,0 +1,31 @@ +// innerclasses/Parcel10.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using "instance initialization" to perform +// construction on an anonymous inner class + +public class Parcel10 { + public Destination + destination(final String dest, final float price) { + return new Destination() { + private int cost; + // Instance initialization for each object: + { + cost = Math.round(price); + if(cost > 100) + System.out.println("Over budget!"); + } + private String label = dest; + @Override + public String readLabel() { return label; } + }; + } + public static void main(String[] args) { + Parcel10 p = new Parcel10(); + Destination d = p.destination("Tasmania", 101.395F); + } +} +/* Output: +Over budget! +*/ diff --git a/code/innerclasses/Parcel11.java b/code/innerclasses/Parcel11.java new file mode 100644 index 00000000..720981f0 --- /dev/null +++ b/code/innerclasses/Parcel11.java @@ -0,0 +1,40 @@ +// innerclasses/Parcel11.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Nested classes (static inner classes) + +public class Parcel11 { + private static class + ParcelContents implements Contents { + private int i = 11; + @Override + public int value() { return i; } + } + protected static final class ParcelDestination + implements Destination { + private String label; + private ParcelDestination(String whereTo) { + label = whereTo; + } + @Override + public String readLabel() { return label; } + // Nested classes can contain other static elements: + public static void f() {} + static int x = 10; + static class AnotherLevel { + public static void f() {} + static int x = 10; + } + } + public static Destination destination(String s) { + return new ParcelDestination(s); + } + public static Contents contents() { + return new ParcelContents(); + } + public static void main(String[] args) { + Contents c = contents(); + Destination d = destination("Tasmania"); + } +} diff --git a/code/innerclasses/Parcel2.java b/code/innerclasses/Parcel2.java new file mode 100644 index 00000000..1eca5cba --- /dev/null +++ b/code/innerclasses/Parcel2.java @@ -0,0 +1,41 @@ +// innerclasses/Parcel2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Returning a reference to an inner class + +public class Parcel2 { + class Contents { + private int i = 11; + public int value() { return i; } + } + class Destination { + private String label; + Destination(String whereTo) { + label = whereTo; + } + String readLabel() { return label; } + } + public Destination to(String s) { + return new Destination(s); + } + public Contents contents() { + return new Contents(); + } + public void ship(String dest) { + Contents c = contents(); + Destination d = to(dest); + System.out.println(d.readLabel()); + } + public static void main(String[] args) { + Parcel2 p = new Parcel2(); + p.ship("Tasmania"); + Parcel2 q = new Parcel2(); + // Defining references to inner classes: + Parcel2.Contents c = q.contents(); + Parcel2.Destination d = q.to("Borneo"); + } +} +/* Output: +Tasmania +*/ diff --git a/code/innerclasses/Parcel3.java b/code/innerclasses/Parcel3.java new file mode 100644 index 00000000..2e0733e0 --- /dev/null +++ b/code/innerclasses/Parcel3.java @@ -0,0 +1,25 @@ +// innerclasses/Parcel3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using .new to create instances of inner classes + +public class Parcel3 { + class Contents { + private int i = 11; + public int value() { return i; } + } + class Destination { + private String label; + Destination(String whereTo) { label = whereTo; } + String readLabel() { return label; } + } + public static void main(String[] args) { + Parcel3 p = new Parcel3(); + // Must use instance of outer class + // to create an instance of the inner class: + Parcel3.Contents c = p.new Contents(); + Parcel3.Destination d = + p.new Destination("Tasmania"); + } +} diff --git a/code/innerclasses/Parcel5.java b/code/innerclasses/Parcel5.java new file mode 100644 index 00000000..622b3fd0 --- /dev/null +++ b/code/innerclasses/Parcel5.java @@ -0,0 +1,23 @@ +// innerclasses/Parcel5.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Nesting a class within a method + +public class Parcel5 { + public Destination destination(String s) { + final class PDestination implements Destination { + private String label; + private PDestination(String whereTo) { + label = whereTo; + } + @Override + public String readLabel() { return label; } + } + return new PDestination(s); + } + public static void main(String[] args) { + Parcel5 p = new Parcel5(); + Destination d = p.destination("Tasmania"); + } +} diff --git a/code/innerclasses/Parcel6.java b/code/innerclasses/Parcel6.java new file mode 100644 index 00000000..7a2c866e --- /dev/null +++ b/code/innerclasses/Parcel6.java @@ -0,0 +1,28 @@ +// innerclasses/Parcel6.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Nesting a class within a scope + +public class Parcel6 { + private void internalTracking(boolean b) { + if(b) { + class TrackingSlip { + private String id; + TrackingSlip(String s) { + id = s; + } + String getSlip() { return id; } + } + TrackingSlip ts = new TrackingSlip("slip"); + String s = ts.getSlip(); + } + // Can't use it here! Out of scope: + //- TrackingSlip ts = new TrackingSlip("x"); + } + public void track() { internalTracking(true); } + public static void main(String[] args) { + Parcel6 p = new Parcel6(); + p.track(); + } +} diff --git a/code/innerclasses/Parcel7.java b/code/innerclasses/Parcel7.java new file mode 100644 index 00000000..3a4aefbb --- /dev/null +++ b/code/innerclasses/Parcel7.java @@ -0,0 +1,19 @@ +// innerclasses/Parcel7.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Returning an instance of an anonymous inner class + +public class Parcel7 { + public Contents contents() { + return new Contents() { // Insert class definition + private int i = 11; + @Override + public int value() { return i; } + }; // Semicolon required + } + public static void main(String[] args) { + Parcel7 p = new Parcel7(); + Contents c = p.contents(); + } +} diff --git a/code/innerclasses/Parcel7b.java b/code/innerclasses/Parcel7b.java new file mode 100644 index 00000000..bee95727 --- /dev/null +++ b/code/innerclasses/Parcel7b.java @@ -0,0 +1,20 @@ +// innerclasses/Parcel7b.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Expanded version of Parcel7.java + +public class Parcel7b { + class MyContents implements Contents { + private int i = 11; + @Override + public int value() { return i; } + } + public Contents contents() { + return new MyContents(); + } + public static void main(String[] args) { + Parcel7b p = new Parcel7b(); + Contents c = p.contents(); + } +} diff --git a/code/innerclasses/Parcel8.java b/code/innerclasses/Parcel8.java new file mode 100644 index 00000000..1e615ac5 --- /dev/null +++ b/code/innerclasses/Parcel8.java @@ -0,0 +1,21 @@ +// innerclasses/Parcel8.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Calling the base-class constructor + +public class Parcel8 { + public Wrapping wrapping(int x) { + // Base constructor call: + return new Wrapping(x) { // [1] + @Override + public int value() { + return super.value() * 47; + } + }; // [2] + } + public static void main(String[] args) { + Parcel8 p = new Parcel8(); + Wrapping w = p.wrapping(10); + } +} diff --git a/code/innerclasses/Parcel9.java b/code/innerclasses/Parcel9.java new file mode 100644 index 00000000..775390f1 --- /dev/null +++ b/code/innerclasses/Parcel9.java @@ -0,0 +1,20 @@ +// innerclasses/Parcel9.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Parcel9 { + // Argument must be final or "effectively final" + // to use within the anonymous inner class: + public Destination destination(final String dest) { + return new Destination() { + private String label = dest; + @Override + public String readLabel() { return label; } + }; + } + public static void main(String[] args) { + Parcel9 p = new Parcel9(); + Destination d = p.destination("Tasmania"); + } +} diff --git a/code/innerclasses/Sequence.java b/code/innerclasses/Sequence.java new file mode 100644 index 00000000..b5a870b9 --- /dev/null +++ b/code/innerclasses/Sequence.java @@ -0,0 +1,48 @@ +// innerclasses/Sequence.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Holds a sequence of Objects + +interface Selector { + boolean end(); + Object current(); + void next(); +} + +public class Sequence { + private Object[] items; + private int next = 0; + public Sequence(int size) { + items = new Object[size]; + } + public void add(Object x) { + if(next < items.length) + items[next++] = x; + } + private class SequenceSelector implements Selector { + private int i = 0; + @Override + public boolean end() { return i == items.length; } + @Override + public Object current() { return items[i]; } + @Override + public void next() { if(i < items.length) i++; } + } + public Selector selector() { + return new SequenceSelector(); + } + public static void main(String[] args) { + Sequence sequence = new Sequence(10); + for(int i = 0; i < 10; i++) + sequence.add(Integer.toString(i)); + Selector selector = sequence.selector(); + while(!selector.end()) { + System.out.print(selector.current() + " "); + selector.next(); + } + } +} +/* Output: +0 1 2 3 4 5 6 7 8 9 +*/ diff --git a/code/innerclasses/TestBed.java b/code/innerclasses/TestBed.java new file mode 100644 index 00000000..d4bc16dd --- /dev/null +++ b/code/innerclasses/TestBed.java @@ -0,0 +1,19 @@ +// innerclasses/TestBed.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Putting test code in a nested class +// {java TestBed$Tester} + +public class TestBed { + public void f() { System.out.println("f()"); } + public static class Tester { + public static void main(String[] args) { + TestBed t = new TestBed(); + t.f(); + } + } +} +/* Output: +f() +*/ diff --git a/code/innerclasses/TestParcel.java b/code/innerclasses/TestParcel.java new file mode 100644 index 00000000..f1ec5d47 --- /dev/null +++ b/code/innerclasses/TestParcel.java @@ -0,0 +1,37 @@ +// innerclasses/TestParcel.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Parcel4 { + private class PContents implements Contents { + private int i = 11; + @Override + public int value() { return i; } + } + protected final class + PDestination implements Destination { + private String label; + private PDestination(String whereTo) { + label = whereTo; + } + @Override + public String readLabel() { return label; } + } + public Destination destination(String s) { + return new PDestination(s); + } + public Contents contents() { + return new PContents(); + } +} + +public class TestParcel { + public static void main(String[] args) { + Parcel4 p = new Parcel4(); + Contents c = p.contents(); + Destination d = p.destination("Tasmania"); + // Illegal -- can't access private class: + //- Parcel4.PContents pc = p.new PContents(); + } +} diff --git a/code/innerclasses/Wrapping.java b/code/innerclasses/Wrapping.java new file mode 100644 index 00000000..651c0748 --- /dev/null +++ b/code/innerclasses/Wrapping.java @@ -0,0 +1,9 @@ +// innerclasses/Wrapping.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +public class Wrapping { + private int i; + public Wrapping(int x) { i = x; } + public int value() { return i; } +} diff --git a/code/innerclasses/controller/Controller.java b/code/innerclasses/controller/Controller.java new file mode 100644 index 00000000..9a3625b3 --- /dev/null +++ b/code/innerclasses/controller/Controller.java @@ -0,0 +1,24 @@ +// innerclasses/controller/Controller.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The reusable framework for control systems +package innerclasses.controller; +import java.util.*; + +public class Controller { + // A class from java.util to hold Event objects: + private List eventList = new ArrayList<>(); + public void addEvent(Event c) { eventList.add(c); } + public void run() { + while(eventList.size() > 0) + // Make a copy so you're not modifying the list + // while you're selecting the elements in it: + for(Event e : new ArrayList<>(eventList)) + if(e.ready()) { + System.out.println(e); + e.action(); + eventList.remove(e); + } + } +} diff --git a/code/innerclasses/controller/Event.java b/code/innerclasses/controller/Event.java new file mode 100644 index 00000000..5523168f --- /dev/null +++ b/code/innerclasses/controller/Event.java @@ -0,0 +1,23 @@ +// innerclasses/controller/Event.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The common methods for any control event +package innerclasses.controller; +import java.time.*; // Java 8 time classes + +public abstract class Event { + private Instant eventTime; + protected final Duration delayTime; + public Event(long millisecondDelay) { + delayTime = Duration.ofMillis(millisecondDelay); + start(); + } + public void start() { // Allows restarting + eventTime = Instant.now().plus(delayTime); + } + public boolean ready() { + return Instant.now().isAfter(eventTime); + } + public abstract void action(); +} diff --git a/code/innerclasses/mui/MultiInterfaces.java b/code/innerclasses/mui/MultiInterfaces.java new file mode 100644 index 00000000..127a6c80 --- /dev/null +++ b/code/innerclasses/mui/MultiInterfaces.java @@ -0,0 +1,32 @@ +// innerclasses/mui/MultiInterfaces.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Two ways a class can implement multiple interfaces +// {java innerclasses.mui.MultiInterfaces} +package innerclasses.mui; + +interface A {} +interface B {} + +class X implements A, B {} + +class Y implements A { + B makeB() { + // Anonymous inner class: + return new B() {}; + } +} + +public class MultiInterfaces { + static void takesA(A a) {} + static void takesB(B b) {} + public static void main(String[] args) { + X x = new X(); + Y y = new Y(); + takesA(x); + takesA(y); + takesB(x); + takesB(y.makeB()); + } +} diff --git a/code/interfaces/AbstractAccess.java b/code/interfaces/AbstractAccess.java new file mode 100644 index 00000000..c2e43da3 --- /dev/null +++ b/code/interfaces/AbstractAccess.java @@ -0,0 +1,15 @@ +// interfaces/AbstractAccess.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +abstract class AbstractAccess { + private void m1() {} + // private abstract void m1a(); // illegal + protected void m2() {} + protected abstract void m2a(); + void m3() {} + abstract void m3a(); + public void m4() {} + public abstract void m4a(); +} diff --git a/code/interfaces/AbstractWithoutAbstracts.java b/code/interfaces/AbstractWithoutAbstracts.java new file mode 100644 index 00000000..2e6b700c --- /dev/null +++ b/code/interfaces/AbstractWithoutAbstracts.java @@ -0,0 +1,14 @@ +// interfaces/AbstractWithoutAbstracts.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +abstract class Basic3 { + int f() { return 111; } + // No abstract methods +} + +public class AbstractWithoutAbstracts { + // Basic3 b3 = new Basic3(); + // error: Basic3 is abstract; cannot be instantiated +} diff --git a/code/interfaces/AdaptedRandomDoubles.java b/code/interfaces/AdaptedRandomDoubles.java new file mode 100644 index 00000000..6c786655 --- /dev/null +++ b/code/interfaces/AdaptedRandomDoubles.java @@ -0,0 +1,35 @@ +// interfaces/AdaptedRandomDoubles.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating an adapter with inheritance +import java.nio.*; +import java.util.*; + +public class AdaptedRandomDoubles +implements RandomDoubles, Readable { + private int count; + public AdaptedRandomDoubles(int count) { + this.count = count; + } + @Override + public int read(CharBuffer cb) { + if(count-- == 0) + return -1; + String result = Double.toString(next()) + " "; + cb.append(result); + return result.length(); + } + public static void main(String[] args) { + Scanner s = + new Scanner(new AdaptedRandomDoubles(7)); + while(s.hasNextDouble()) + System.out.print(s.nextDouble() + " "); + } +} +/* Output: +0.7271157860730044 0.5309454508634242 +0.16020656493302599 0.18847866977771732 +0.5166020801268457 0.2678662084200585 +0.2613610344283964 +*/ diff --git a/code/interfaces/Adventure.java b/code/interfaces/Adventure.java new file mode 100644 index 00000000..1a7135d1 --- /dev/null +++ b/code/interfaces/Adventure.java @@ -0,0 +1,41 @@ +// interfaces/Adventure.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Multiple interfaces + +interface CanFight { + void fight(); +} + +interface CanSwim { + void swim(); +} + +interface CanFly { + void fly(); +} + +class ActionCharacter { + public void fight() {} +} + +class Hero extends ActionCharacter + implements CanFight, CanSwim, CanFly { + public void swim() {} + public void fly() {} +} + +public class Adventure { + public static void t(CanFight x) { x.fight(); } + public static void u(CanSwim x) { x.swim(); } + public static void v(CanFly x) { x.fly(); } + public static void w(ActionCharacter x) { x.fight(); } + public static void main(String[] args) { + Hero h = new Hero(); + t(h); // Treat it as a CanFight + u(h); // Treat it as a CanSwim + v(h); // Treat it as a CanFly + w(h); // Treat it as an ActionCharacter + } +} diff --git a/code/interfaces/AnImplementation.java b/code/interfaces/AnImplementation.java new file mode 100644 index 00000000..3ff13a30 --- /dev/null +++ b/code/interfaces/AnImplementation.java @@ -0,0 +1,22 @@ +// interfaces/AnImplementation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class AnImplementation implements AnInterface { + public void firstMethod() { + System.out.println("firstMethod"); + } + public void secondMethod() { + System.out.println("secondMethod"); + } + public static void main(String[] args) { + AnInterface i = new AnImplementation(); + i.firstMethod(); + i.secondMethod(); + } +} +/* Output: +firstMethod +secondMethod +*/ diff --git a/code/interfaces/AnInterface.java b/code/interfaces/AnInterface.java new file mode 100644 index 00000000..30f82b3a --- /dev/null +++ b/code/interfaces/AnInterface.java @@ -0,0 +1,9 @@ +// interfaces/AnInterface.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface AnInterface { + void firstMethod(); + void secondMethod(); +} diff --git a/code/interfaces/Applicator.java b/code/interfaces/Applicator.java new file mode 100644 index 00000000..a6aa172f --- /dev/null +++ b/code/interfaces/Applicator.java @@ -0,0 +1,58 @@ +// interfaces/Applicator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class Processor { + public String name() { + return getClass().getSimpleName(); + } + public Object process(Object input) { + return input; + } +} + +class Upcase extends Processor { + @Override // Covariant return: + public String process(Object input) { + return ((String)input).toUpperCase(); + } +} + +class Downcase extends Processor { + @Override + public String process(Object input) { + return ((String)input).toLowerCase(); + } +} + +class Splitter extends Processor { + @Override + public String process(Object input) { + // split() divides a String into pieces: + return Arrays.toString(((String)input).split(" ")); + } +} + +public class Applicator { + public static void apply(Processor p, Object s) { + System.out.println("Using Processor " + p.name()); + System.out.println(p.process(s)); + } + public static void main(String[] args) { + String s = + "We are such stuff as dreams are made on"; + apply(new Upcase(), s); + apply(new Downcase(), s); + apply(new Splitter(), s); + } +} +/* Output: +Using Processor Upcase +WE ARE SUCH STUFF AS DREAMS ARE MADE ON +Using Processor Downcase +we are such stuff as dreams are made on +Using Processor Splitter +[We, are, such, stuff, as, dreams, are, made, on] +*/ diff --git a/code/interfaces/AttemptToUseBasic.java b/code/interfaces/AttemptToUseBasic.java new file mode 100644 index 00000000..0d265527 --- /dev/null +++ b/code/interfaces/AttemptToUseBasic.java @@ -0,0 +1,10 @@ +// interfaces/AttemptToUseBasic.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} + +public class AttemptToUseBasic { + Basic b = new Basic(); + // error: Basic is abstract; cannot be instantiated +} diff --git a/code/interfaces/Basic.java b/code/interfaces/Basic.java new file mode 100644 index 00000000..19c1c75b --- /dev/null +++ b/code/interfaces/Basic.java @@ -0,0 +1,8 @@ +// interfaces/Basic.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +abstract class Basic { + abstract void unimplemented(); +} diff --git a/code/interfaces/Basic2.java b/code/interfaces/Basic2.java new file mode 100644 index 00000000..4c8f0c93 --- /dev/null +++ b/code/interfaces/Basic2.java @@ -0,0 +1,10 @@ +// interfaces/Basic2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +abstract class Basic2 extends Basic { + int f() { return 111; } + abstract void g(); + // unimplemented() still not implemented +} diff --git a/code/interfaces/Factories.java b/code/interfaces/Factories.java new file mode 100644 index 00000000..87e28251 --- /dev/null +++ b/code/interfaces/Factories.java @@ -0,0 +1,67 @@ +// interfaces/Factories.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface Service { + void method1(); + void method2(); +} + +interface ServiceFactory { + Service getService(); +} + +class Service1 implements Service { + Service1() {} // Package access + public void method1() { + System.out.println("Service1 method1"); + } + public void method2() { + System.out.println("Service1 method2"); + } +} + +class Service1Factory implements ServiceFactory { + @Override + public Service getService() { + return new Service1(); + } +} + +class Service2 implements Service { + Service2() {} // Package access + public void method1() { + System.out.println("Service2 method1"); + } + public void method2() { + System.out.println("Service2 method2"); + } +} + +class Service2Factory implements ServiceFactory { + @Override + public Service getService() { + return new Service2(); + } +} + +public class Factories { + public static void + serviceConsumer(ServiceFactory fact) { + Service s = fact.getService(); + s.method1(); + s.method2(); + } + public static void main(String[] args) { + serviceConsumer(new Service1Factory()); + // Services are completely interchangeable: + serviceConsumer(new Service2Factory()); + } +} +/* Output: +Service1 method1 +Service1 method2 +Service2 method1 +Service2 method2 +*/ diff --git a/code/interfaces/Games.java b/code/interfaces/Games.java new file mode 100644 index 00000000..867efe0c --- /dev/null +++ b/code/interfaces/Games.java @@ -0,0 +1,59 @@ +// interfaces/Games.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A Game framework using Factory Methods + +interface Game { boolean move(); } +interface GameFactory { Game getGame(); } + +class Checkers implements Game { + private int moves = 0; + private static final int MOVES = 3; + @Override + public boolean move() { + System.out.println("Checkers move " + moves); + return ++moves != MOVES; + } +} + +class CheckersFactory implements GameFactory { + @Override + public Game getGame() { return new Checkers(); } +} + +class Chess implements Game { + private int moves = 0; + private static final int MOVES = 4; + @Override + public boolean move() { + System.out.println("Chess move " + moves); + return ++moves != MOVES; + } +} + +class ChessFactory implements GameFactory { + @Override + public Game getGame() { return new Chess(); } +} + +public class Games { + public static void playGame(GameFactory factory) { + Game s = factory.getGame(); + while(s.move()) + ; + } + public static void main(String[] args) { + playGame(new CheckersFactory()); + playGame(new ChessFactory()); + } +} +/* Output: +Checkers move 0 +Checkers move 1 +Checkers move 2 +Chess move 0 +Chess move 1 +Chess move 2 +Chess move 3 +*/ diff --git a/code/interfaces/HorrorShow.java b/code/interfaces/HorrorShow.java new file mode 100644 index 00000000..b1c687da --- /dev/null +++ b/code/interfaces/HorrorShow.java @@ -0,0 +1,57 @@ +// interfaces/HorrorShow.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Extending an interface with inheritance + +interface Monster { + void menace(); +} + +interface DangerousMonster extends Monster { + void destroy(); +} + +interface Lethal { + void kill(); +} + +class DragonZilla implements DangerousMonster { + @Override + public void menace() {} + @Override + public void destroy() {} +} + +interface Vampire extends DangerousMonster, Lethal { + void drinkBlood(); +} + +class VeryBadVampire implements Vampire { + @Override + public void menace() {} + @Override + public void destroy() {} + @Override + public void kill() {} + @Override + public void drinkBlood() {} +} + +public class HorrorShow { + static void u(Monster b) { b.menace(); } + static void v(DangerousMonster d) { + d.menace(); + d.destroy(); + } + static void w(Lethal l) { l.kill(); } + public static void main(String[] args) { + DangerousMonster barney = new DragonZilla(); + u(barney); + v(barney); + Vampire vlad = new VeryBadVampire(); + u(vlad); + v(vlad); + w(vlad); + } +} diff --git a/code/interfaces/Implementation2.java b/code/interfaces/Implementation2.java new file mode 100644 index 00000000..61c6efa0 --- /dev/null +++ b/code/interfaces/Implementation2.java @@ -0,0 +1,26 @@ +// interfaces/Implementation2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Implementation2 +implements InterfaceWithDefault { + public void firstMethod() { + System.out.println("firstMethod"); + } + public void secondMethod() { + System.out.println("secondMethod"); + } + public static void main(String[] args) { + InterfaceWithDefault i = + new Implementation2(); + i.firstMethod(); + i.secondMethod(); + i.newMethod(); + } +} +/* Output: +firstMethod +secondMethod +newMethod +*/ diff --git a/code/interfaces/ImplementingAnInterface.java b/code/interfaces/ImplementingAnInterface.java new file mode 100644 index 00000000..6a13ebb6 --- /dev/null +++ b/code/interfaces/ImplementingAnInterface.java @@ -0,0 +1,14 @@ +// interfaces/ImplementingAnInterface.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface Concept { // Package access + void idea1(); + void idea2(); +} + +class Implementation implements Concept { + public void idea1() { System.out.println("idea1"); } + public void idea2() { System.out.println("idea2"); } +} diff --git a/code/interfaces/Instantiable.java b/code/interfaces/Instantiable.java new file mode 100644 index 00000000..427b6ca3 --- /dev/null +++ b/code/interfaces/Instantiable.java @@ -0,0 +1,19 @@ +// interfaces/Instantiable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +abstract class Uninstantiable { + abstract void f(); + abstract int g(); +} + +public class Instantiable extends Uninstantiable { + @Override + void f() { System.out.println("f()"); } + @Override + int g() { return 22; } + public static void main(String[] args) { + Uninstantiable ui = new Instantiable(); + } +} diff --git a/code/interfaces/InterfaceCollision.java b/code/interfaces/InterfaceCollision.java new file mode 100644 index 00000000..0f7de1ac --- /dev/null +++ b/code/interfaces/InterfaceCollision.java @@ -0,0 +1,31 @@ +// interfaces/InterfaceCollision.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface I1 { void f(); } +interface I2 { int f(int i); } +interface I3 { int f(); } +class C { public int f() { return 1; } } + +class C2 implements I1, I2 { + @Override + public void f() {} + @Override + public int f(int i) { return 1; } // overloaded +} + +class C3 extends C implements I2 { + @Override + public int f(int i) { return 1; } // overloaded +} + +class C4 extends C implements I3 { + // Identical, no problem: + @Override + public int f() { return 1; } +} + +// Methods differ only by return type: +//- class C5 extends C implements I1 {} +//- interface I4 extends I1, I3 {} diff --git a/code/interfaces/InterfaceWithDefault.java b/code/interfaces/InterfaceWithDefault.java new file mode 100644 index 00000000..a87f02db --- /dev/null +++ b/code/interfaces/InterfaceWithDefault.java @@ -0,0 +1,12 @@ +// interfaces/InterfaceWithDefault.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface InterfaceWithDefault { + void firstMethod(); + void secondMethod(); + default void newMethod() { + System.out.println("newMethod"); + } +} diff --git a/code/interfaces/Jim.java b/code/interfaces/Jim.java new file mode 100644 index 00000000..515db6e5 --- /dev/null +++ b/code/interfaces/Jim.java @@ -0,0 +1,28 @@ +// interfaces/Jim.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +interface Jim1 { + default void jim() { + System.out.println("Jim1::jim"); + } +} + +interface Jim2 { + default void jim() { + System.out.println("Jim2::jim"); + } +} + +public class Jim implements Jim1, Jim2 { + @Override + public void jim() { Jim2.super.jim(); } + public static void main(String[] args) { + new Jim().jim(); + } +} +/* Output: +Jim2::jim +*/ diff --git a/code/interfaces/MICollision.java b/code/interfaces/MICollision.java new file mode 100644 index 00000000..c96e5696 --- /dev/null +++ b/code/interfaces/MICollision.java @@ -0,0 +1,60 @@ +// interfaces/MICollision.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +interface Bob1 { + default void bob() { + System.out.println("Bob1::bob"); + } +} + +interface Bob2 { + default void bob() { + System.out.println("Bob2::bob"); + } +} + +// class Bob implements Bob1, Bob2 {} +/* Produces: +error: class Bob inherits unrelated defaults +for bob() from types Bob1 and Bob2 +class Bob implements Bob1, Bob2 {} +^ +1 error +*/ + +interface Sam1 { + default void sam() { + System.out.println("Sam1::sam"); + } +} + +interface Sam2 { + default void sam(int i) { + System.out.println(i * 2); + } +} + +// This works because the argument lists are distinct: +class Sam implements Sam1, Sam2 {} + +interface Max1 { + default void max() { + System.out.println("Max1::max"); + } +} + +interface Max2 { + default int max() { return 47; } +} + +// class Max implements Max1, Max2 {} +/* Produces: +error: types Max2 and Max1 are incompatible; +both define max(), but with unrelated return types +class Max implements Max1, Max2 {} +^ +1 error +*/ diff --git a/code/interfaces/Machine.java b/code/interfaces/Machine.java new file mode 100644 index 00000000..2b1144ae --- /dev/null +++ b/code/interfaces/Machine.java @@ -0,0 +1,36 @@ +// interfaces/Machine.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.Operations; + +class Bing implements Operations { + public void execute() { + Operations.show("Bing"); + } +} + +class Crack implements Operations { + public void execute() { + Operations.show("Crack"); + } +} + +class Twist implements Operations { + public void execute() { + Operations.show("Twist"); + } +} + +public class Machine { + public static void main(String[] args) { + Operations.runOps( + new Bing(), new Crack(), new Twist()); + } +} +/* Output: +Bing +Crack +Twist +*/ diff --git a/code/interfaces/Months.java b/code/interfaces/Months.java new file mode 100644 index 00000000..27317dd5 --- /dev/null +++ b/code/interfaces/Months.java @@ -0,0 +1,13 @@ +// interfaces/Months.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using interfaces to create groups of constants + +public interface Months { + int + JANUARY = 1, FEBRUARY = 2, MARCH = 3, + APRIL = 4, MAY = 5, JUNE = 6, JULY = 7, + AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10, + NOVEMBER = 11, DECEMBER = 12; +} diff --git a/code/interfaces/MultipleInheritance.java b/code/interfaces/MultipleInheritance.java new file mode 100644 index 00000000..6ce9c91e --- /dev/null +++ b/code/interfaces/MultipleInheritance.java @@ -0,0 +1,35 @@ +// interfaces/MultipleInheritance.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +interface One { + default void first() { System.out.println("first"); } +} + +interface Two { + default void second() { + System.out.println("second"); + } +} + +interface Three { + default void third() { System.out.println("third"); } +} + +class MI implements One, Two, Three {} + +public class MultipleInheritance { + public static void main(String[] args) { + MI mi = new MI(); + mi.first(); + mi.second(); + mi.third(); + } +} +/* Output: +first +second +third +*/ diff --git a/code/interfaces/PureInterface.java b/code/interfaces/PureInterface.java new file mode 100644 index 00000000..37bf9f0b --- /dev/null +++ b/code/interfaces/PureInterface.java @@ -0,0 +1,11 @@ +// interfaces/PureInterface.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Interface only looked like this before Java 8 + +public interface PureInterface { + int m1(); + void m2(); + double m3(); +} diff --git a/code/interfaces/RandVals.java b/code/interfaces/RandVals.java new file mode 100644 index 00000000..0221c851 --- /dev/null +++ b/code/interfaces/RandVals.java @@ -0,0 +1,15 @@ +// interfaces/RandVals.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Initializing interface fields with +// non-constant initializers +import java.util.*; + +public interface RandVals { + Random RAND = new Random(47); + int RANDOM_INT = RAND.nextInt(10); + long RANDOM_LONG = RAND.nextLong() * 10; + float RANDOM_FLOAT = RAND.nextLong() * 10; + double RANDOM_DOUBLE = RAND.nextDouble() * 10; +} diff --git a/code/interfaces/RandomDoubles.java b/code/interfaces/RandomDoubles.java new file mode 100644 index 00000000..99154d95 --- /dev/null +++ b/code/interfaces/RandomDoubles.java @@ -0,0 +1,21 @@ +// interfaces/RandomDoubles.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public interface RandomDoubles { + Random RAND = new Random(47); + default double next() { return RAND.nextDouble(); } + static void main(String[] args) { + RandomDoubles rd = new RandomDoubles() {}; + for(int i = 0; i < 7; i ++) + System.out.print(rd.next() + " "); + } +} +/* Output: +0.7271157860730044 0.5309454508634242 +0.16020656493302599 0.18847866977771732 +0.5166020801268457 0.2678662084200585 +0.2613610344283964 +*/ diff --git a/code/interfaces/RandomStrings.java b/code/interfaces/RandomStrings.java new file mode 100644 index 00000000..82f98230 --- /dev/null +++ b/code/interfaces/RandomStrings.java @@ -0,0 +1,50 @@ +// interfaces/RandomStrings.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Implementing an interface to conform to a method +import java.nio.*; +import java.util.*; + +public class RandomStrings implements Readable { + private static Random rand = new Random(47); + private static final char[] CAPITALS = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + private static final char[] LOWERS = + "abcdefghijklmnopqrstuvwxyz".toCharArray(); + private static final char[] VOWELS = + "aeiou".toCharArray(); + private int count; + public RandomStrings(int count) { + this.count = count; + } + @Override + public int read(CharBuffer cb) { + if(count-- == 0) + return -1; // Indicates end of input + cb.append(CAPITALS[rand.nextInt(CAPITALS.length)]); + for(int i = 0; i < 4; i++) { + cb.append(VOWELS[rand.nextInt(VOWELS.length)]); + cb.append(LOWERS[rand.nextInt(LOWERS.length)]); + } + cb.append(" "); + return 10; // Number of characters appended + } + public static void main(String[] args) { + Scanner s = new Scanner(new RandomStrings(10)); + while(s.hasNext()) + System.out.println(s.next()); + } +} +/* Output: +Yazeruyac +Fowenucor +Goeazimom +Raeuuacio +Nuoadesiw +Hageaikux +Ruqicibui +Numasetih +Kuuuuozog +Waqizeyoy +*/ diff --git a/code/interfaces/TestRandVals.java b/code/interfaces/TestRandVals.java new file mode 100644 index 00000000..df3490b2 --- /dev/null +++ b/code/interfaces/TestRandVals.java @@ -0,0 +1,19 @@ +// interfaces/TestRandVals.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class TestRandVals { + public static void main(String[] args) { + System.out.println(RandVals.RANDOM_INT); + System.out.println(RandVals.RANDOM_LONG); + System.out.println(RandVals.RANDOM_FLOAT); + System.out.println(RandVals.RANDOM_DOUBLE); + } +} +/* Output: +8 +-32032247016559954 +-8.5939291E18 +5.779976127815049 +*/ diff --git a/code/interfaces/filters/BandPass.java b/code/interfaces/filters/BandPass.java new file mode 100644 index 00000000..7d09ed28 --- /dev/null +++ b/code/interfaces/filters/BandPass.java @@ -0,0 +1,17 @@ +// interfaces/filters/BandPass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package interfaces.filters; + +public class BandPass extends Filter { + double lowCutoff, highCutoff; + public BandPass(double lowCut, double highCut) { + lowCutoff = lowCut; + highCutoff = highCut; + } + @Override + public Waveform process(Waveform input) { + return input; + } +} diff --git a/code/interfaces/filters/Filter.java b/code/interfaces/filters/Filter.java new file mode 100644 index 00000000..72e29a9e --- /dev/null +++ b/code/interfaces/filters/Filter.java @@ -0,0 +1,14 @@ +// interfaces/filters/Filter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package interfaces.filters; + +public class Filter { + public String name() { + return getClass().getSimpleName(); + } + public Waveform process(Waveform input) { + return input; + } +} diff --git a/code/interfaces/filters/HighPass.java b/code/interfaces/filters/HighPass.java new file mode 100644 index 00000000..7bf047df --- /dev/null +++ b/code/interfaces/filters/HighPass.java @@ -0,0 +1,16 @@ +// interfaces/filters/HighPass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package interfaces.filters; + +public class HighPass extends Filter { + double cutoff; + public HighPass(double cutoff) { + this.cutoff = cutoff; + } + @Override + public Waveform process(Waveform input) { + return input; + } +} diff --git a/code/interfaces/filters/LowPass.java b/code/interfaces/filters/LowPass.java new file mode 100644 index 00000000..e9320a82 --- /dev/null +++ b/code/interfaces/filters/LowPass.java @@ -0,0 +1,16 @@ +// interfaces/filters/LowPass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package interfaces.filters; + +public class LowPass extends Filter { + double cutoff; + public LowPass(double cutoff) { + this.cutoff = cutoff; + } + @Override + public Waveform process(Waveform input) { + return input; // Dummy processing + } +} diff --git a/code/interfaces/filters/Waveform.java b/code/interfaces/filters/Waveform.java new file mode 100644 index 00000000..40644677 --- /dev/null +++ b/code/interfaces/filters/Waveform.java @@ -0,0 +1,14 @@ +// interfaces/filters/Waveform.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package interfaces.filters; + +public class Waveform { + private static long counter; + private final long id = counter++; + @Override + public String toString() { + return "Waveform " + id; + } +} diff --git a/code/interfaces/interfaceprocessor/Applicator.java b/code/interfaces/interfaceprocessor/Applicator.java new file mode 100644 index 00000000..77d7a9a6 --- /dev/null +++ b/code/interfaces/interfaceprocessor/Applicator.java @@ -0,0 +1,12 @@ +// interfaces/interfaceprocessor/Applicator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package interfaces.interfaceprocessor; + +public class Applicator { + public static void apply(Processor p, Object s) { + System.out.println("Using Processor " + p.name()); + System.out.println(p.process(s)); + } +} diff --git a/code/interfaces/interfaceprocessor/FilterProcessor.java b/code/interfaces/interfaceprocessor/FilterProcessor.java new file mode 100644 index 00000000..33689ed4 --- /dev/null +++ b/code/interfaces/interfaceprocessor/FilterProcessor.java @@ -0,0 +1,40 @@ +// interfaces/interfaceprocessor/FilterProcessor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java interfaces.interfaceprocessor.FilterProcessor} +package interfaces.interfaceprocessor; +import interfaces.filters.*; + +class FilterAdapter implements Processor { + Filter filter; + FilterAdapter(Filter filter) { + this.filter = filter; + } + @Override + public String name() { return filter.name(); } + @Override + public Waveform process(Object input) { + return filter.process((Waveform)input); + } +} + +public class FilterProcessor { + public static void main(String[] args) { + Waveform w = new Waveform(); + Applicator.apply( + new FilterAdapter(new LowPass(1.0)), w); + Applicator.apply( + new FilterAdapter(new HighPass(2.0)), w); + Applicator.apply( + new FilterAdapter(new BandPass(3.0, 4.0)), w); + } +} +/* Output: +Using Processor LowPass +Waveform 0 +Using Processor HighPass +Waveform 0 +Using Processor BandPass +Waveform 0 +*/ diff --git a/code/interfaces/interfaceprocessor/Processor.java b/code/interfaces/interfaceprocessor/Processor.java new file mode 100644 index 00000000..6315da30 --- /dev/null +++ b/code/interfaces/interfaceprocessor/Processor.java @@ -0,0 +1,12 @@ +// interfaces/interfaceprocessor/Processor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package interfaces.interfaceprocessor; + +public interface Processor { + default String name() { + return getClass().getSimpleName(); + } + Object process(Object input); +} diff --git a/code/interfaces/interfaceprocessor/StringProcessor.java b/code/interfaces/interfaceprocessor/StringProcessor.java new file mode 100644 index 00000000..37cb4946 --- /dev/null +++ b/code/interfaces/interfaceprocessor/StringProcessor.java @@ -0,0 +1,50 @@ +// interfaces/interfaceprocessor/StringProcessor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java interfaces.interfaceprocessor.StringProcessor} +package interfaces.interfaceprocessor; +import java.util.*; + +interface StringProcessor extends Processor { + @Override + String process(Object input); // [1] + String S = // [2] + "If she weighs the same as a duck, " + + "she's made of wood"; + static void main(String[] args) { // [3] + Applicator.apply(new Upcase(), S); + Applicator.apply(new Downcase(), S); + Applicator.apply(new Splitter(), S); + } +} + +class Upcase implements StringProcessor { + @Override // Covariant return: + public String process(Object input) { + return ((String)input).toUpperCase(); + } +} + +class Downcase implements StringProcessor { + @Override + public String process(Object input) { + return ((String)input).toLowerCase(); + } +} + +class Splitter implements StringProcessor { + @Override + public String process(Object input) { + return Arrays.toString(((String)input).split(" ")); + } +} +/* Output: +Using Processor Upcase +IF SHE WEIGHS THE SAME AS A DUCK, SHE'S MADE OF WOOD +Using Processor Downcase +if she weighs the same as a duck, she's made of wood +Using Processor Splitter +[If, she, weighs, the, same, as, a, duck,, she's, made, +of, wood] +*/ diff --git a/code/interfaces/music4/Music4.java b/code/interfaces/music4/Music4.java new file mode 100644 index 00000000..71034149 --- /dev/null +++ b/code/interfaces/music4/Music4.java @@ -0,0 +1,105 @@ +// interfaces/music4/Music4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Abstract classes and methods +// {java interfaces.music4.Music4} +package interfaces.music4; +import polymorphism.music.Note; + +abstract class Instrument { + private int i; // Storage allocated for each + public abstract void play(Note n); + public String what() { return "Instrument"; } + public abstract void adjust(); +} + +class Wind extends Instrument { + @Override + public void play(Note n) { + System.out.println("Wind.play() " + n); + } + @Override + public String what() { return "Wind"; } + @Override + public void adjust() { + System.out.println("Adjusting Wind"); + } +} + +class Percussion extends Instrument { + @Override + public void play(Note n) { + System.out.println("Percussion.play() " + n); + } + @Override + public String what() { return "Percussion"; } + @Override + public void adjust() { + System.out.println("Adjusting Percussion"); + } +} + +class Stringed extends Instrument { + @Override + public void play(Note n) { + System.out.println("Stringed.play() " + n); + } + @Override + public String what() { return "Stringed"; } + @Override + public void adjust() { + System.out.println("Adjusting Stringed"); + } +} + +class Brass extends Wind { + @Override + public void play(Note n) { + System.out.println("Brass.play() " + n); + } + @Override + public void adjust() { + System.out.println("Adjusting Brass"); + } +} + +class Woodwind extends Wind { + @Override + public void play(Note n) { + System.out.println("Woodwind.play() " + n); + } + @Override + public String what() { return "Woodwind"; } +} + +public class Music4 { + // Doesn't care about type, so new types + // added to the system still work right: + static void tune(Instrument i) { + // ... + i.play(Note.MIDDLE_C); + } + static void tuneAll(Instrument[] e) { + for(Instrument i : e) + tune(i); + } + public static void main(String[] args) { + // Upcasting during addition to the array: + Instrument[] orchestra = { + new Wind(), + new Percussion(), + new Stringed(), + new Brass(), + new Woodwind() + }; + tuneAll(orchestra); + } +} +/* Output: +Wind.play() MIDDLE_C +Percussion.play() MIDDLE_C +Stringed.play() MIDDLE_C +Brass.play() MIDDLE_C +Woodwind.play() MIDDLE_C +*/ diff --git a/code/interfaces/music5/Music5.java b/code/interfaces/music5/Music5.java new file mode 100644 index 00000000..2326bdbc --- /dev/null +++ b/code/interfaces/music5/Music5.java @@ -0,0 +1,74 @@ +// interfaces/music5/Music5.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java interfaces.music5.Music5} +package interfaces.music5; +import polymorphism.music.Note; + +interface Instrument { + // Compile-time constant: + int VALUE = 5; // static & final + default void play(Note n) { // Automatically public + System.out.println(this + ".play() " + n); + } + default void adjust() { + System.out.println("Adjusting " + this); + } +} + +class Wind implements Instrument { + @Override + public String toString() { return "Wind"; } +} + +class Percussion implements Instrument { + @Override + public String toString() { return "Percussion"; } +} + +class Stringed implements Instrument { + @Override + public String toString() { return "Stringed"; } +} + +class Brass extends Wind { + @Override + public String toString() { return "Brass"; } +} + +class Woodwind extends Wind { + @Override + public String toString() { return "Woodwind"; } +} + +public class Music5 { + // Doesn't care about type, so new types + // added to the system still work right: + static void tune(Instrument i) { + // ... + i.play(Note.MIDDLE_C); + } + static void tuneAll(Instrument[] e) { + for(Instrument i : e) + tune(i); + } + public static void main(String[] args) { + // Upcasting during addition to the array: + Instrument[] orchestra = { + new Wind(), + new Percussion(), + new Stringed(), + new Brass(), + new Woodwind() + }; + tuneAll(orchestra); + } +} +/* Output: +Wind.play() MIDDLE_C +Percussion.play() MIDDLE_C +Stringed.play() MIDDLE_C +Brass.play() MIDDLE_C +Woodwind.play() MIDDLE_C +*/ diff --git a/code/interfaces/nesting/NestingInterfaces.java b/code/interfaces/nesting/NestingInterfaces.java new file mode 100644 index 00000000..99b466bb --- /dev/null +++ b/code/interfaces/nesting/NestingInterfaces.java @@ -0,0 +1,105 @@ +// interfaces/nesting/NestingInterfaces.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java interfaces.nesting.NestingInterfaces} +package interfaces.nesting; + +class A { + interface B { + void f(); + } + public class BImp implements B { + @Override + public void f() {} + } + private class BImp2 implements B { + @Override + public void f() {} + } + public interface C { + void f(); + } + class CImp implements C { + @Override + public void f() {} + } + private class CImp2 implements C { + @Override + public void f() {} + } + private interface D { + void f(); + } + private class DImp implements D { + @Override + public void f() {} + } + public class DImp2 implements D { + @Override + public void f() {} + } + public D getD() { return new DImp2(); } + private D dRef; + public void receiveD(D d) { + dRef = d; + dRef.f(); + } +} + +interface E { + interface G { + void f(); + } + // Redundant "public": + public interface H { + void f(); + } + void g(); + // Cannot be private within an interface: + //- private interface I {} +} + +public class NestingInterfaces { + public class BImp implements A.B { + @Override + public void f() {} + } + class CImp implements A.C { + @Override + public void f() {} + } + // Cannot implement a private interface except + // within that interface's defining class: + //- class DImp implements A.D { + //- public void f() {} + //- } + class EImp implements E { + @Override + public void g() {} + } + class EGImp implements E.G { + @Override + public void f() {} + } + class EImp2 implements E { + @Override + public void g() {} + class EG implements E.G { + @Override + public void f() {} + } + } + public static void main(String[] args) { + A a = new A(); + // Can't access A.D: + //- A.D ad = a.getD(); + // Doesn't return anything but A.D: + //- A.DImp2 di2 = a.getD(); + // Cannot access a member of the interface: + //- a.getD().f(); + // Only another A can do anything with getD(): + A a2 = new A(); + a2.receiveD(a.getD()); + } +} diff --git a/code/iostreams/BasicFileOutput.java b/code/iostreams/BasicFileOutput.java new file mode 100644 index 00000000..1da5c6fd --- /dev/null +++ b/code/iostreams/BasicFileOutput.java @@ -0,0 +1,26 @@ +// iostreams/BasicFileOutput.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.io.*; + +public class BasicFileOutput { + static String file = "BasicFileOutput.dat"; + public static void main(String[] args) { + try( + BufferedReader in = new BufferedReader( + new StringReader( + BufferedInputFile.read( + "BasicFileOutput.java"))); + PrintWriter out = new PrintWriter( + new BufferedWriter(new FileWriter(file))) + ) { + in.lines().forEach(out::println); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Show the stored file: + System.out.println(BufferedInputFile.read(file)); + } +} diff --git a/code/iostreams/BufferedInputFile.java b/code/iostreams/BufferedInputFile.java new file mode 100644 index 00000000..bfe6396f --- /dev/null +++ b/code/iostreams/BufferedInputFile.java @@ -0,0 +1,23 @@ +// iostreams/BufferedInputFile.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.io.*; +import java.util.stream.*; + +public class BufferedInputFile { + public static String read(String filename) { + try(BufferedReader in = new BufferedReader( + new FileReader(filename))) { + return in.lines() + .collect(Collectors.joining("\n")); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + public static void main(String[] args) { + System.out.print( + read("BufferedInputFile.java")); + } +} diff --git a/code/iostreams/FileOutputShortcut.java b/code/iostreams/FileOutputShortcut.java new file mode 100644 index 00000000..5a160ec0 --- /dev/null +++ b/code/iostreams/FileOutputShortcut.java @@ -0,0 +1,24 @@ +// iostreams/FileOutputShortcut.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.io.*; + +public class FileOutputShortcut { + static String file = "FileOutputShortcut.dat"; + public static void main(String[] args) { + try( + BufferedReader in = new BufferedReader( + new StringReader(BufferedInputFile.read( + "FileOutputShortcut.java"))); + // Here's the shortcut: + PrintWriter out = new PrintWriter(file) + ) { + in.lines().forEach(out::println); + } catch(IOException e) { + throw new RuntimeException(e); + } + System.out.println(BufferedInputFile.read(file)); + } +} diff --git a/code/iostreams/FormattedMemoryInput.java b/code/iostreams/FormattedMemoryInput.java new file mode 100644 index 00000000..055dd882 --- /dev/null +++ b/code/iostreams/FormattedMemoryInput.java @@ -0,0 +1,25 @@ +// iostreams/FormattedMemoryInput.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.io.*; + +public class FormattedMemoryInput { + public static void main(String[] args) { + try( + DataInputStream in = new DataInputStream( + new ByteArrayInputStream( + BufferedInputFile.read( + "FormattedMemoryInput.java") + .getBytes())) + ) { + while(true) + System.out.write((char)in.readByte()); + } catch(EOFException e) { + System.out.println("\nEnd of stream"); + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/iostreams/MemoryInput.java b/code/iostreams/MemoryInput.java new file mode 100644 index 00000000..1326965c --- /dev/null +++ b/code/iostreams/MemoryInput.java @@ -0,0 +1,17 @@ +// iostreams/MemoryInput.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {VisuallyInspectOutput} +import java.io.*; + +public class MemoryInput { + public static void + main(String[] args) throws IOException { + StringReader in = new StringReader( + BufferedInputFile.read("MemoryInput.java")); + int c; + while((c = in.read()) != -1) + System.out.print((char)c); + } +} diff --git a/code/iostreams/StoringAndRecoveringData.java b/code/iostreams/StoringAndRecoveringData.java new file mode 100644 index 00000000..761f022e --- /dev/null +++ b/code/iostreams/StoringAndRecoveringData.java @@ -0,0 +1,42 @@ +// iostreams/StoringAndRecoveringData.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; + +public class StoringAndRecoveringData { + public static void main(String[] args) { + try( + DataOutputStream out = new DataOutputStream( + new BufferedOutputStream( + new FileOutputStream("Data.txt"))) + ) { + out.writeDouble(3.14159); + out.writeUTF("That was pi"); + out.writeDouble(1.41413); + out.writeUTF("Square root of 2"); + } catch(IOException e) { + throw new RuntimeException(e); + } + try( + DataInputStream in = new DataInputStream( + new BufferedInputStream( + new FileInputStream("Data.txt"))) + ) { + System.out.println(in.readDouble()); + // Only readUTF() will recover the + // Java-UTF String properly: + System.out.println(in.readUTF()); + System.out.println(in.readDouble()); + System.out.println(in.readUTF()); + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} +/* Output: +3.14159 +That was pi +1.41413 +Square root of 2 +*/ diff --git a/code/iostreams/TestEOF.java b/code/iostreams/TestEOF.java new file mode 100644 index 00000000..956cb1a0 --- /dev/null +++ b/code/iostreams/TestEOF.java @@ -0,0 +1,22 @@ +// iostreams/TestEOF.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Testing for end of file +// {VisuallyInspectOutput} +import java.io.*; + +public class TestEOF { + public static void main(String[] args) { + try( + DataInputStream in = new DataInputStream( + new BufferedInputStream( + new FileInputStream("TestEOF.java"))) + ) { + while(in.available() != 0) + System.out.write(in.readByte()); + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/iostreams/UsingRandomAccessFile.java b/code/iostreams/UsingRandomAccessFile.java new file mode 100644 index 00000000..dde6d1ee --- /dev/null +++ b/code/iostreams/UsingRandomAccessFile.java @@ -0,0 +1,65 @@ +// iostreams/UsingRandomAccessFile.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; + +public class UsingRandomAccessFile { + static String file = "rtest.dat"; + public static void display() { + try( + RandomAccessFile rf = + new RandomAccessFile(file, "r") + ) { + for(int i = 0; i < 7; i++) + System.out.println( + "Value " + i + ": " + rf.readDouble()); + System.out.println(rf.readUTF()); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + public static void main(String[] args) { + try( + RandomAccessFile rf = + new RandomAccessFile(file, "rw") + ) { + for(int i = 0; i < 7; i++) + rf.writeDouble(i*1.414); + rf.writeUTF("The end of the file"); + rf.close(); + display(); + } catch(IOException e) { + throw new RuntimeException(e); + } + try( + RandomAccessFile rf = + new RandomAccessFile(file, "rw") + ) { + rf.seek(5*8); + rf.writeDouble(47.0001); + rf.close(); + display(); + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} +/* Output: +Value 0: 0.0 +Value 1: 1.414 +Value 2: 2.828 +Value 3: 4.242 +Value 4: 5.656 +Value 5: 7.069999999999999 +Value 6: 8.484 +The end of the file +Value 0: 0.0 +Value 1: 1.414 +Value 2: 2.828 +Value 3: 4.242 +Value 4: 5.656 +Value 5: 47.0001 +Value 6: 8.484 +The end of the file +*/ diff --git a/code/javadoc/Documentation1.java b/code/javadoc/Documentation1.java new file mode 100644 index 00000000..7838fbd9 --- /dev/null +++ b/code/javadoc/Documentation1.java @@ -0,0 +1,11 @@ +// javadoc/Documentation1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +/** A class comment */ +public class Documentation1 { + /** A field comment */ + public int i; + /** A method comment */ + public void f() {} +} diff --git a/code/javadoc/Documentation2.java b/code/javadoc/Documentation2.java new file mode 100644 index 00000000..237755f4 --- /dev/null +++ b/code/javadoc/Documentation2.java @@ -0,0 +1,9 @@ +// javadoc/Documentation2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +/**

+ * System.out.println(new Date());
+ * 
+ */ +public class Documentation2 {} diff --git a/code/javadoc/Documentation3.java b/code/javadoc/Documentation3.java new file mode 100644 index 00000000..a3063c3d --- /dev/null +++ b/code/javadoc/Documentation3.java @@ -0,0 +1,12 @@ +// javadoc/Documentation3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +/** You can even insert a list: + *
    + *
  1. Item one + *
  2. Item two + *
  3. Item three + *
+ */ +public class Documentation3 {} diff --git a/code/javadoc/HelloDateDoc.java b/code/javadoc/HelloDateDoc.java new file mode 100644 index 00000000..54b505a4 --- /dev/null +++ b/code/javadoc/HelloDateDoc.java @@ -0,0 +1,26 @@ +// javadoc/HelloDateDoc.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +/** The first On Java 8 example program. + * Displays a String and today's date. + * @author Bruce Eckel + * @author www.MindviewInc.com + * @version 5.0 + */ +public class HelloDateDoc { + /** Entry point to class & application. + * @param args array of String arguments + * @throws exceptions No exceptions thrown + */ + public static void main(String[] args) { + System.out.println("Hello, it's: "); + System.out.println(new Date()); + } +} +/* Output: +Hello, it's: +Tue May 09 06:07:27 MDT 2017 +*/ diff --git a/code/lowlevel/AtomicEvenProducer.java b/code/lowlevel/AtomicEvenProducer.java new file mode 100644 index 00000000..8c45b61c --- /dev/null +++ b/code/lowlevel/AtomicEvenProducer.java @@ -0,0 +1,21 @@ +// lowlevel/AtomicEvenProducer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Atomic classes: occasionally useful in regular code +import java.util.concurrent.atomic.*; + +public class AtomicEvenProducer extends IntGenerator { + private AtomicInteger currentEvenValue = + new AtomicInteger(0); + @Override + public int next() { + return currentEvenValue.addAndGet(2); + } + public static void main(String[] args) { + EvenChecker.test(new AtomicEvenProducer()); + } +} +/* Output: +No odd numbers discovered +*/ diff --git a/code/lowlevel/AtomicIntegerTest.java b/code/lowlevel/AtomicIntegerTest.java new file mode 100644 index 00000000..09db1ca8 --- /dev/null +++ b/code/lowlevel/AtomicIntegerTest.java @@ -0,0 +1,20 @@ +// lowlevel/AtomicIntegerTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; +import java.util.*; +import onjava.*; + +public class AtomicIntegerTest extends IntTestable { + private AtomicInteger i = new AtomicInteger(0); + public int getAsInt() { return i.get(); } + public void evenIncrement() { i.addAndGet(2); } + public static void main(String[] args) { + Atomicity.test(new AtomicIntegerTest()); + } +} +/* Output: +No failures found +*/ diff --git a/code/lowlevel/AtomicSerialNumbers.java b/code/lowlevel/AtomicSerialNumbers.java new file mode 100644 index 00000000..2e30e9c4 --- /dev/null +++ b/code/lowlevel/AtomicSerialNumbers.java @@ -0,0 +1,21 @@ +// lowlevel/AtomicSerialNumbers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.atomic.*; + +public class +AtomicSerialNumbers extends SerialNumbers { + private AtomicInteger serialNumber = + new AtomicInteger(); + public int nextSerialNumber() { + return serialNumber.getAndIncrement(); + } + public static void main(String[] args) { + SerialNumberChecker.test( + new AtomicSerialNumbers()); + } +} +/* Output: +No duplicates detected +*/ diff --git a/code/lowlevel/Atomicity.java b/code/lowlevel/Atomicity.java new file mode 100644 index 00000000..632631bf --- /dev/null +++ b/code/lowlevel/Atomicity.java @@ -0,0 +1,20 @@ +// lowlevel/Atomicity.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import onjava.TimedAbort; + +public class Atomicity { + public static void test(IntTestable it) { + new TimedAbort(4, "No failures found"); + CompletableFuture.runAsync(it); + while(true) { + int val = it.getAsInt(); + if(val % 2 != 0) { + System.out.println("failed with: " + val); + System.exit(0); + } + } + } +} diff --git a/code/lowlevel/AttemptLocking.java b/code/lowlevel/AttemptLocking.java new file mode 100644 index 00000000..9dbe2b28 --- /dev/null +++ b/code/lowlevel/AttemptLocking.java @@ -0,0 +1,57 @@ +// lowlevel/AttemptLocking.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Locks in the concurrent library allow you +// to give up on trying to acquire a lock +import java.util.concurrent.*; +import java.util.concurrent.locks.*; +import onjava.Nap; + +public class AttemptLocking { + private ReentrantLock lock = new ReentrantLock(); + public void untimed() { + boolean captured = lock.tryLock(); + try { + System.out.println("tryLock(): " + captured); + } finally { + if(captured) + lock.unlock(); + } + } + public void timed() { + boolean captured = false; + try { + captured = lock.tryLock(2, TimeUnit.SECONDS); + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + try { + System.out.println( + "tryLock(2, TimeUnit.SECONDS): " + captured); + } finally { + if(captured) + lock.unlock(); + } + } + public static void main(String[] args) { + final AttemptLocking al = new AttemptLocking(); + al.untimed(); // True -- lock is available + al.timed(); // True -- lock is available + // Now create a second task to grab the lock: + CompletableFuture.runAsync( () -> { + al.lock.lock(); + System.out.println("acquired"); + }); + new Nap(0.1); // Give the second task a chance + al.untimed(); // False -- lock grabbed by task + al.timed(); // False -- lock grabbed by task + } +} +/* Output: +tryLock(): true +tryLock(2, TimeUnit.SECONDS): true +acquired +tryLock(): false +tryLock(2, TimeUnit.SECONDS): false +*/ diff --git a/code/lowlevel/CaptureUncaughtException.java b/code/lowlevel/CaptureUncaughtException.java new file mode 100644 index 00000000..33261667 --- /dev/null +++ b/code/lowlevel/CaptureUncaughtException.java @@ -0,0 +1,56 @@ +// lowlevel/CaptureUncaughtException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +class ExceptionThread2 implements Runnable { + @Override + public void run() { + Thread t = Thread.currentThread(); + System.out.println("run() by " + t.getName()); + System.out.println( + "eh = " + t.getUncaughtExceptionHandler()); + throw new RuntimeException(); + } +} + +class MyUncaughtExceptionHandler implements +Thread.UncaughtExceptionHandler { + @Override + public void uncaughtException(Thread t, Throwable e) { + System.out.println("caught " + e); + } +} + +class HandlerThreadFactory implements ThreadFactory { + @Override + public Thread newThread(Runnable r) { + System.out.println(this + " creating new Thread"); + Thread t = new Thread(r); + System.out.println("created " + t); + t.setUncaughtExceptionHandler( + new MyUncaughtExceptionHandler()); + System.out.println( + "eh = " + t.getUncaughtExceptionHandler()); + return t; + } +} + +public class CaptureUncaughtException { + public static void main(String[] args) { + ExecutorService exec = + Executors.newCachedThreadPool( + new HandlerThreadFactory()); + exec.execute(new ExceptionThread2()); + exec.shutdown(); + } +} +/* Output: +HandlerThreadFactory@4e25154f creating new Thread +created Thread[Thread-0,5,main] +eh = MyUncaughtExceptionHandler@70dea4e +run() by Thread-0 +eh = MyUncaughtExceptionHandler@70dea4e +caught java.lang.RuntimeException +*/ diff --git a/code/lowlevel/CircularSet.java b/code/lowlevel/CircularSet.java new file mode 100644 index 00000000..225eaeca --- /dev/null +++ b/code/lowlevel/CircularSet.java @@ -0,0 +1,29 @@ +// lowlevel/CircularSet.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Reuses storage so we don't run out of memory +import java.util.*; + +public class CircularSet { + private int[] array; + private int size; + private int index = 0; + public CircularSet(int size) { + this.size = size; + array = new int[size]; + // Initialize to a value not produced + // by SerialNumbers: + Arrays.fill(array, -1); + } + public synchronized void add(int i) { + array[index] = i; + // Wrap index and write over old elements: + index = ++index % size; + } + public synchronized boolean contains(int val) { + for(int i = 0; i < size; i++) + if(array[i] == val) return true; + return false; + } +} diff --git a/code/lowlevel/DelayQueueDemo.java b/code/lowlevel/DelayQueueDemo.java new file mode 100644 index 00000000..c5575c68 --- /dev/null +++ b/code/lowlevel/DelayQueueDemo.java @@ -0,0 +1,99 @@ +// lowlevel/DelayQueueDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import static java.util.concurrent.TimeUnit.*; + +class DelayedTask implements Runnable, Delayed { + private static int counter = 0; + private final int id = counter++; + private final int delta; + private final long trigger; + protected static List sequence = + new ArrayList<>(); + DelayedTask(int delayInMilliseconds) { + delta = delayInMilliseconds; + trigger = System.nanoTime() + + NANOSECONDS.convert(delta, MILLISECONDS); + sequence.add(this); + } + @Override + public long getDelay(TimeUnit unit) { + return unit.convert( + trigger - System.nanoTime(), NANOSECONDS); + } + @Override + public int compareTo(Delayed arg) { + DelayedTask that = (DelayedTask)arg; + if(trigger < that.trigger) return -1; + if(trigger > that.trigger) return 1; + return 0; + } + @Override + public void run() { + System.out.print(this + " "); + } + @Override + public String toString() { + return + String.format("[%d] Task %d", delta, id); + } + public String summary() { + return String.format("(%d:%d)", id, delta); + } + public static class EndTask extends DelayedTask { + EndTask(int delay) { super(delay); } + @Override + public void run() { + sequence.forEach(dt -> + System.out.println(dt.summary())); + } + } +} + +public class DelayQueueDemo { + public static void + main(String[] args) throws Exception { + DelayQueue tasks = + Stream.concat( // Random delays: + new Random(47).ints(20, 0, 4000) + .mapToObj(DelayedTask::new), + // Add the summarizing task: + Stream.of(new DelayedTask.EndTask(4000))) + .collect(Collectors + .toCollection(DelayQueue::new)); + while(tasks.size() > 0) + tasks.take().run(); + } +} +/* Output: +[128] Task 12 [429] Task 6 [551] Task 13 [555] Task 2 +[693] Task 3 [809] Task 15 [961] Task 5 [1258] Task 1 +[1258] Task 20 [1520] Task 19 [1861] Task 4 [1998] Task +17 [2200] Task 8 [2207] Task 10 [2288] Task 11 [2522] +Task 9 [2589] Task 14 [2861] Task 18 [2868] Task 7 +[3278] Task 16 (0:4000) +(1:1258) +(2:555) +(3:693) +(4:1861) +(5:961) +(6:429) +(7:2868) +(8:2200) +(9:2522) +(10:2207) +(11:2288) +(12:128) +(13:551) +(14:2589) +(15:809) +(16:3278) +(17:1998) +(18:2861) +(19:1520) +(20:1258) +*/ diff --git a/code/lowlevel/EvenChecker.java b/code/lowlevel/EvenChecker.java new file mode 100644 index 00000000..5e27a39e --- /dev/null +++ b/code/lowlevel/EvenChecker.java @@ -0,0 +1,41 @@ +// lowlevel/EvenChecker.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import onjava.TimedAbort; + +public class EvenChecker implements Runnable { + private IntGenerator generator; + private final int id; + public EvenChecker(IntGenerator generator, int id) { + this.generator = generator; + this.id = id; + } + @Override + public void run() { + while(!generator.isCanceled()) { + int val = generator.next(); + if(val % 2 != 0) { + System.out.println(val + " not even!"); + generator.cancel(); // Cancels all EvenCheckers + } + } + } + // Test any IntGenerator: + public static void test(IntGenerator gp, int count) { + List> checkers = + IntStream.range(0, count) + .mapToObj(i -> new EvenChecker(gp, i)) + .map(CompletableFuture::runAsync) + .collect(Collectors.toList()); + checkers.forEach(CompletableFuture::join); + } + // Default value for count: + public static void test(IntGenerator gp) { + new TimedAbort(4, "No odd numbers discovered"); + test(gp, 10); + } +} diff --git a/code/lowlevel/EvenProducer.java b/code/lowlevel/EvenProducer.java new file mode 100644 index 00000000..30157755 --- /dev/null +++ b/code/lowlevel/EvenProducer.java @@ -0,0 +1,26 @@ +// lowlevel/EvenProducer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// When threads collide +// {VisuallyInspectOutput} + +public class EvenProducer extends IntGenerator { + private int currentEvenValue = 0; + @Override + public int next() { + ++currentEvenValue; // [1] + ++currentEvenValue; + return currentEvenValue; + } + public static void main(String[] args) { + EvenChecker.test(new EvenProducer()); + } +} +/* Output: +419 not even! +425 not even! +423 not even! +421 not even! +417 not even! +*/ diff --git a/code/lowlevel/ExceptionThread.java b/code/lowlevel/ExceptionThread.java new file mode 100644 index 00000000..518b9f5f --- /dev/null +++ b/code/lowlevel/ExceptionThread.java @@ -0,0 +1,30 @@ +// lowlevel/ExceptionThread.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ThrowsException} +import java.util.concurrent.*; + +public class ExceptionThread implements Runnable { + @Override + public void run() { + throw new RuntimeException(); + } + public static void main(String[] args) { + ExecutorService es = + Executors.newCachedThreadPool(); + es.execute(new ExceptionThread()); + es.shutdown(); + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "pool-1-thread-1" +java.lang.RuntimeException + at ExceptionThread.run(ExceptionThread.java:8) + at java.util.concurrent.ThreadPoolExecutor.runW +orker(ThreadPoolExecutor.java:1142) + at java.util.concurrent.ThreadPoolExecutor$Work +er.run(ThreadPoolExecutor.java:617) + at java.lang.Thread.run(Thread.java:745) +*/ diff --git a/code/lowlevel/IntGenerator.java b/code/lowlevel/IntGenerator.java new file mode 100644 index 00000000..e1dd0f62 --- /dev/null +++ b/code/lowlevel/IntGenerator.java @@ -0,0 +1,15 @@ +// lowlevel/IntGenerator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.atomic.AtomicBoolean; + +public abstract class IntGenerator { + private AtomicBoolean canceled = + new AtomicBoolean(); + public abstract int next(); + public void cancel() { canceled.set(true); } + public boolean isCanceled() { + return canceled.get(); + } +} diff --git a/code/lowlevel/IntTestable.java b/code/lowlevel/IntTestable.java new file mode 100644 index 00000000..1989ff4d --- /dev/null +++ b/code/lowlevel/IntTestable.java @@ -0,0 +1,15 @@ +// lowlevel/IntTestable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public abstract class +IntTestable implements Runnable, IntSupplier { + abstract void evenIncrement(); + @Override + public void run() { + while(true) + evenIncrement(); + } +} diff --git a/code/lowlevel/MutexEvenProducer.java b/code/lowlevel/MutexEvenProducer.java new file mode 100644 index 00000000..ae82df82 --- /dev/null +++ b/code/lowlevel/MutexEvenProducer.java @@ -0,0 +1,30 @@ +// lowlevel/MutexEvenProducer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Preventing thread collisions with mutexes +import java.util.concurrent.locks.*; +import onjava.Nap; + +public class MutexEvenProducer extends IntGenerator { + private int currentEvenValue = 0; + private Lock lock = new ReentrantLock(); + @Override + public int next() { + lock.lock(); + try { + ++currentEvenValue; + new Nap(0.01); // Cause failure faster + ++currentEvenValue; + return currentEvenValue; + } finally { + lock.unlock(); + } + } + public static void main(String[] args) { + EvenChecker.test(new MutexEvenProducer()); + } +} +/* +No odd numbers discovered +*/ diff --git a/code/lowlevel/NaiveExceptionHandling.java b/code/lowlevel/NaiveExceptionHandling.java new file mode 100644 index 00000000..3681337e --- /dev/null +++ b/code/lowlevel/NaiveExceptionHandling.java @@ -0,0 +1,32 @@ +// lowlevel/NaiveExceptionHandling.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ThrowsException} +import java.util.concurrent.*; + +public class NaiveExceptionHandling { + public static void main(String[] args) { + ExecutorService es = + Executors.newCachedThreadPool(); + try { + es.execute(new ExceptionThread()); + } catch(RuntimeException ue) { + // This statement will NOT execute! + System.out.println("Exception was handled!"); + } finally { + es.shutdown(); + } + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "pool-1-thread-1" +java.lang.RuntimeException + at ExceptionThread.run(ExceptionThread.java:8) + at java.util.concurrent.ThreadPoolExecutor.runW +orker(ThreadPoolExecutor.java:1142) + at java.util.concurrent.ThreadPoolExecutor$Work +er.run(ThreadPoolExecutor.java:617) + at java.lang.Thread.run(Thread.java:745) +*/ diff --git a/code/lowlevel/NotAtomic.java b/code/lowlevel/NotAtomic.java new file mode 100644 index 00000000..c6c6c321 --- /dev/null +++ b/code/lowlevel/NotAtomic.java @@ -0,0 +1,49 @@ +// lowlevel/NotAtomic.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// javap -c NotAtomic +// {ExcludeFromGradle} +// {VisuallyInspectOutput} + +public class NotAtomic { + int i; + void f1() { i++; } + void f2() { i += 3; } +} +/* Output: +Compiled from "NotAtomic.java" +public class NotAtomic { + int i; + + public NotAtomic(); + Code: + 0: aload_0 + 1: invokespecial #1 // Method java/lang/Object."":()V + 4: return + + void f1(); + Code: + 0: aload_0 + 1: dup + 2: getfield #2 // Field +i:I + 5: iconst_1 + 6: iadd + 7: putfield #2 // Field +i:I + 10: return + + void f2(); + Code: + 0: aload_0 + 1: dup + 2: getfield #2 // Field +i:I + 5: iconst_3 + 6: iadd + 7: putfield #2 // Field +i:I + 10: return +} +*/ diff --git a/code/lowlevel/NumberOfProcessors.java b/code/lowlevel/NumberOfProcessors.java new file mode 100644 index 00000000..44abeb5d --- /dev/null +++ b/code/lowlevel/NumberOfProcessors.java @@ -0,0 +1,14 @@ +// lowlevel/NumberOfProcessors.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class NumberOfProcessors { + public static void main(String[] args) { + System.out.println( + Runtime.getRuntime().availableProcessors()); + } +} +/* Output: +8 +*/ diff --git a/code/lowlevel/PriorityBlockingQueueDemo.java b/code/lowlevel/PriorityBlockingQueueDemo.java new file mode 100644 index 00000000..099a5349 --- /dev/null +++ b/code/lowlevel/PriorityBlockingQueueDemo.java @@ -0,0 +1,139 @@ +// lowlevel/PriorityBlockingQueueDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; +import onjava.Nap; + +class Prioritized implements Comparable { + private static AtomicInteger counter = + new AtomicInteger(); + private final int id = counter.getAndIncrement(); + private final int priority; + private static List sequence = + new CopyOnWriteArrayList<>(); + Prioritized(int priority) { + this.priority = priority; + sequence.add(this); + } + @Override + public int compareTo(Prioritized arg) { + return priority < arg.priority ? 1 : + (priority > arg.priority ? -1 : 0); + } + @Override + public String toString() { + return String.format( + "[%d] Prioritized %d", priority, id); + } + public void displaySequence() { + int count = 0; + for(Prioritized pt : sequence) { + System.out.printf("(%d:%d)", pt.id, pt.priority); + if(++count % 5 == 0) + System.out.println(); + } + } + public static class EndSentinel extends Prioritized { + EndSentinel() { super(-1); } + } +} + +class Producer implements Runnable { + private static AtomicInteger seed = + new AtomicInteger(47); + private SplittableRandom rand = + new SplittableRandom(seed.getAndAdd(10)); + private Queue queue; + Producer(Queue q) { + queue = q; + } + @Override + public void run() { + rand.ints(10, 0, 20) + .mapToObj(Prioritized::new) + .peek(p -> new Nap(rand.nextDouble() / 10)) + .forEach(p -> queue.add(p)); + queue.add(new Prioritized.EndSentinel()); + } +} + +class Consumer implements Runnable { + private PriorityBlockingQueue q; + private SplittableRandom rand = + new SplittableRandom(47); + Consumer(PriorityBlockingQueue q) { + this.q = q; + } + @Override + public void run() { + while(true) { + try { + Prioritized pt = q.take(); + System.out.println(pt); + if(pt instanceof Prioritized.EndSentinel) { + pt.displaySequence(); + break; + } + new Nap(rand.nextDouble() / 10); + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + } + } +} + +public class PriorityBlockingQueueDemo { + public static void main(String[] args) { + PriorityBlockingQueue queue = + new PriorityBlockingQueue<>(); + CompletableFuture.runAsync(new Producer(queue)); + CompletableFuture.runAsync(new Producer(queue)); + CompletableFuture.runAsync(new Producer(queue)); + CompletableFuture.runAsync(new Consumer(queue)) + .join(); + } +} +/* Output: +[15] Prioritized 2 +[17] Prioritized 1 +[17] Prioritized 5 +[16] Prioritized 6 +[14] Prioritized 9 +[12] Prioritized 0 +[11] Prioritized 4 +[11] Prioritized 12 +[13] Prioritized 13 +[12] Prioritized 16 +[14] Prioritized 18 +[15] Prioritized 23 +[18] Prioritized 26 +[16] Prioritized 29 +[12] Prioritized 17 +[11] Prioritized 30 +[11] Prioritized 24 +[10] Prioritized 15 +[10] Prioritized 22 +[8] Prioritized 25 +[8] Prioritized 11 +[8] Prioritized 10 +[6] Prioritized 31 +[3] Prioritized 7 +[2] Prioritized 20 +[1] Prioritized 3 +[0] Prioritized 19 +[0] Prioritized 8 +[0] Prioritized 14 +[0] Prioritized 21 +[-1] Prioritized 28 +(0:12)(2:15)(1:17)(3:1)(4:11) +(5:17)(6:16)(7:3)(8:0)(9:14) +(10:8)(11:8)(12:11)(13:13)(14:0) +(15:10)(16:12)(17:12)(18:14)(19:0) +(20:2)(21:0)(22:10)(23:15)(24:11) +(25:8)(26:18)(27:-1)(28:-1)(29:16) +(30:11)(31:6)(32:-1) +*/ diff --git a/code/lowlevel/ReOrdering.java b/code/lowlevel/ReOrdering.java new file mode 100644 index 00000000..8209ac40 --- /dev/null +++ b/code/lowlevel/ReOrdering.java @@ -0,0 +1,19 @@ +// lowlevel/ReOrdering.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ReOrdering implements Runnable { + int one, two, three, four, five, six; + volatile int volaTile; + @Override + public void run() { + one = 1; + two = 2; + three = 3; + volaTile = 92; + int x = four; + int y = five; + int z = six; + } +} diff --git a/code/lowlevel/SafeReturn.java b/code/lowlevel/SafeReturn.java new file mode 100644 index 00000000..751c96be --- /dev/null +++ b/code/lowlevel/SafeReturn.java @@ -0,0 +1,20 @@ +// lowlevel/SafeReturn.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; +import java.util.concurrent.*; + +public class SafeReturn extends IntTestable { + private int i = 0; + public synchronized int getAsInt() { return i; } + public synchronized void evenIncrement() { + i++; i++; + } + public static void main(String[] args) { + Atomicity.test(new SafeReturn()); + } +} +/* Output: +No failures found +*/ diff --git a/code/lowlevel/SerialNumberChecker.java b/code/lowlevel/SerialNumberChecker.java new file mode 100644 index 00000000..9c2b92ad --- /dev/null +++ b/code/lowlevel/SerialNumberChecker.java @@ -0,0 +1,32 @@ +// lowlevel/SerialNumberChecker.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Test SerialNumbers implementations for thread-safety +import java.util.concurrent.*; +import onjava.Nap; + +public class SerialNumberChecker implements Runnable { + private CircularSet serials = new CircularSet(1000); + private SerialNumbers producer; + public SerialNumberChecker(SerialNumbers producer) { + this.producer = producer; + } + @Override + public void run() { + while(true) { + int serial = producer.nextSerialNumber(); + if(serials.contains(serial)) { + System.out.println("Duplicate: " + serial); + System.exit(0); + } + serials.add(serial); + } + } + static void test(SerialNumbers producer) { + for(int i = 0; i < 10; i++) + CompletableFuture.runAsync( + new SerialNumberChecker(producer)); + new Nap(4, "No duplicates detected"); + } +} diff --git a/code/lowlevel/SerialNumberTest.java b/code/lowlevel/SerialNumberTest.java new file mode 100644 index 00000000..cdeddcd9 --- /dev/null +++ b/code/lowlevel/SerialNumberTest.java @@ -0,0 +1,13 @@ +// lowlevel/SerialNumberTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SerialNumberTest { + public static void main(String[] args) { + SerialNumberChecker.test(new SerialNumbers()); + } +} +/* Output: +Duplicate: 148044 +*/ diff --git a/code/lowlevel/SerialNumbers.java b/code/lowlevel/SerialNumbers.java new file mode 100644 index 00000000..3f6101c7 --- /dev/null +++ b/code/lowlevel/SerialNumbers.java @@ -0,0 +1,11 @@ +// lowlevel/SerialNumbers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SerialNumbers { + private volatile int serialNumber = 0; + public int nextSerialNumber() { + return serialNumber++; // Not thread-safe + } +} diff --git a/code/lowlevel/SettingDefaultHandler.java b/code/lowlevel/SettingDefaultHandler.java new file mode 100644 index 00000000..56a04642 --- /dev/null +++ b/code/lowlevel/SettingDefaultHandler.java @@ -0,0 +1,19 @@ +// lowlevel/SettingDefaultHandler.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class SettingDefaultHandler { + public static void main(String[] args) { + Thread.setDefaultUncaughtExceptionHandler( + new MyUncaughtExceptionHandler()); + ExecutorService es = + Executors.newCachedThreadPool(); + es.execute(new ExceptionThread()); + es.shutdown(); + } +} +/* Output: +caught java.lang.RuntimeException +*/ diff --git a/code/lowlevel/SwallowedException.java b/code/lowlevel/SwallowedException.java new file mode 100644 index 00000000..60edd0d6 --- /dev/null +++ b/code/lowlevel/SwallowedException.java @@ -0,0 +1,17 @@ +// lowlevel/SwallowedException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; + +public class SwallowedException { + public static void main(String[] args) + throws InterruptedException { + ExecutorService exec = + Executors.newSingleThreadExecutor(); + exec.submit(() -> { + throw new RuntimeException(); + }); + exec.shutdown(); + } +} diff --git a/code/lowlevel/SyncOnObject.java b/code/lowlevel/SyncOnObject.java new file mode 100644 index 00000000..846c5573 --- /dev/null +++ b/code/lowlevel/SyncOnObject.java @@ -0,0 +1,70 @@ +// lowlevel/SyncOnObject.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Synchronizing on another object +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import onjava.Nap; + +class DualSynch { + ConcurrentLinkedQueue trace = + new ConcurrentLinkedQueue<>(); + public synchronized void f(boolean nap) { + for(int i = 0; i < 5; i++) { + trace.add(String.format("f() " + i)); + if(nap) new Nap(0.01); + } + } + private Object syncObject = new Object(); + public void g(boolean nap) { + synchronized(syncObject) { + for(int i = 0; i < 5; i++) { + trace.add(String.format("g() " + i)); + if(nap) new Nap(0.01); + } + } + } +} + +public class SyncOnObject { + static void test(boolean fNap, boolean gNap) { + DualSynch ds = new DualSynch(); + List> cfs = + Arrays.stream(new Runnable[] { + () -> ds.f(fNap), () -> ds.g(gNap) }) + .map(CompletableFuture::runAsync) + .collect(Collectors.toList()); + cfs.forEach(CompletableFuture::join); + ds.trace.forEach(System.out::println); + } + public static void main(String[] args) { + test(true, false); + System.out.println("****"); + test(false, true); + } +} +/* Output: +f() 0 +g() 0 +g() 1 +g() 2 +g() 3 +g() 4 +f() 1 +f() 2 +f() 3 +f() 4 +**** +f() 0 +g() 0 +f() 1 +f() 2 +f() 3 +f() 4 +g() 1 +g() 2 +g() 3 +g() 4 +*/ diff --git a/code/lowlevel/SynchronizedComparison.java b/code/lowlevel/SynchronizedComparison.java new file mode 100644 index 00000000..6fbcd1f3 --- /dev/null +++ b/code/lowlevel/SynchronizedComparison.java @@ -0,0 +1,89 @@ +// lowlevel/SynchronizedComparison.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Synchronizing blocks instead of entire methods +// speeds up access. +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; +import onjava.Nap; + +abstract class Guarded { + AtomicLong callCount = new AtomicLong(); + public abstract void method(); + @Override + public String toString() { + return getClass().getSimpleName() + + ": " + callCount.get(); + } +} + +class SynchronizedMethod extends Guarded { + public synchronized void method() { + new Nap(0.01); + callCount.incrementAndGet(); + } +} + +class CriticalSection extends Guarded { + public void method() { + new Nap(0.01); + synchronized(this) { + callCount.incrementAndGet(); + } + } +} + +class Caller implements Runnable { + private Guarded g; + Caller(Guarded g) { this.g = g; } + private AtomicLong successfulCalls = + new AtomicLong(); + private AtomicBoolean stop = + new AtomicBoolean(false); + @Override + public void run() { + new Timer().schedule(new TimerTask() { + public void run() { stop.set(true); } + }, 2500); + while(!stop.get()) { + g.method(); + successfulCalls.getAndIncrement(); + } + System.out.println( + "-> " + successfulCalls.get()); + } +} + +public class SynchronizedComparison { + static void test(Guarded g) { + List> callers = + Stream.of( + new Caller(g), + new Caller(g), + new Caller(g), + new Caller(g)) + .map(CompletableFuture::runAsync) + .collect(Collectors.toList()); + callers.forEach(CompletableFuture::join); + System.out.println(g); + } + public static void main(String[] args) { + test(new CriticalSection()); + test(new SynchronizedMethod()); + } +} +/* Output: +-> 243 +-> 243 +-> 243 +-> 243 +CriticalSection: 972 +-> 69 +-> 61 +-> 83 +-> 36 +SynchronizedMethod: 249 +*/ diff --git a/code/lowlevel/SynchronizedEvenProducer.java b/code/lowlevel/SynchronizedEvenProducer.java new file mode 100644 index 00000000..377aeecb --- /dev/null +++ b/code/lowlevel/SynchronizedEvenProducer.java @@ -0,0 +1,24 @@ +// lowlevel/SynchronizedEvenProducer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simplifying mutexes with the synchronized keyword +import onjava.Nap; + +public class +SynchronizedEvenProducer extends IntGenerator { + private int currentEvenValue = 0; + @Override + public synchronized int next() { + ++currentEvenValue; + new Nap(0.01); // Cause failure faster + ++currentEvenValue; + return currentEvenValue; + } + public static void main(String[] args) { + EvenChecker.test(new SynchronizedEvenProducer()); + } +} +/* Output: +No odd numbers discovered +*/ diff --git a/code/lowlevel/SynchronizedSerialNumbers.java b/code/lowlevel/SynchronizedSerialNumbers.java new file mode 100644 index 00000000..1739d840 --- /dev/null +++ b/code/lowlevel/SynchronizedSerialNumbers.java @@ -0,0 +1,19 @@ +// lowlevel/SynchronizedSerialNumbers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class +SynchronizedSerialNumbers extends SerialNumbers { + private int serialNumber = 0; + public synchronized int nextSerialNumber() { + return serialNumber++; + } + public static void main(String[] args) { + SerialNumberChecker.test( + new SynchronizedSerialNumbers()); + } +} +/* Output: +No duplicates detected +*/ diff --git a/code/lowlevel/TestAbort.java b/code/lowlevel/TestAbort.java new file mode 100644 index 00000000..a9efe528 --- /dev/null +++ b/code/lowlevel/TestAbort.java @@ -0,0 +1,17 @@ +// lowlevel/TestAbort.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; + +public class TestAbort { + public static void main(String[] args) { + new TimedAbort(1); + System.out.println("Napping for 4"); + new Nap(4); + } +} +/* Output: +Napping for 4 +TimedAbort 1.0 +*/ diff --git a/code/lowlevel/ThreadSize.java b/code/lowlevel/ThreadSize.java new file mode 100644 index 00000000..0f00023d --- /dev/null +++ b/code/lowlevel/ThreadSize.java @@ -0,0 +1,31 @@ +// lowlevel/ThreadSize.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromGradle} Takes a long time or hangs +import java.util.concurrent.*; +import onjava.Nap; + +public class ThreadSize { + static class Dummy extends Thread { + @Override + public void run() { new Nap(1); } + } + public static void main(String[] args) { + ExecutorService exec = + Executors.newCachedThreadPool(); + int count = 0; + try { + while(true) { + exec.execute(new Dummy()); + count++; + } + } catch(Error e) { + System.out.println( + e.getClass().getSimpleName() + ": " + count); + System.exit(0); + } finally { + exec.shutdown(); + } + } +} diff --git a/code/lowlevel/UnsafeReturn.java b/code/lowlevel/UnsafeReturn.java new file mode 100644 index 00000000..c2481fc0 --- /dev/null +++ b/code/lowlevel/UnsafeReturn.java @@ -0,0 +1,20 @@ +// lowlevel/UnsafeReturn.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; +import java.util.concurrent.*; + +public class UnsafeReturn extends IntTestable { + private int i = 0; + public int getAsInt() { return i; } + public synchronized void evenIncrement() { + i++; i++; + } + public static void main(String[] args) { + Atomicity.test(new UnsafeReturn()); + } +} +/* Output: +failed with: 79 +*/ diff --git a/code/lowlevel/WorkStealingPool.java b/code/lowlevel/WorkStealingPool.java new file mode 100644 index 00000000..984de706 --- /dev/null +++ b/code/lowlevel/WorkStealingPool.java @@ -0,0 +1,41 @@ +// lowlevel/WorkStealingPool.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; +import java.util.concurrent.*; + +class ShowThread implements Runnable { + @Override + public void run() { + System.out.println( + Thread.currentThread().getName()); + } +} + +public class WorkStealingPool { + public static void main(String[] args) + throws InterruptedException { + System.out.println( + Runtime.getRuntime().availableProcessors()); + ExecutorService exec = + Executors.newWorkStealingPool(); + IntStream.range(0, 10) + .mapToObj(n -> new ShowThread()) + .forEach(exec::execute); + exec.awaitTermination(1, TimeUnit.SECONDS); + } +} +/* Output: +8 +ForkJoinPool-1-worker-2 +ForkJoinPool-1-worker-1 +ForkJoinPool-1-worker-2 +ForkJoinPool-1-worker-3 +ForkJoinPool-1-worker-2 +ForkJoinPool-1-worker-1 +ForkJoinPool-1-worker-3 +ForkJoinPool-1-worker-1 +ForkJoinPool-1-worker-4 +ForkJoinPool-1-worker-2 +*/ diff --git a/code/newio/AvailableCharSets.java b/code/newio/AvailableCharSets.java new file mode 100644 index 00000000..eda3b93c --- /dev/null +++ b/code/newio/AvailableCharSets.java @@ -0,0 +1,43 @@ +// newio/AvailableCharSets.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Displays Charsets and aliases +import java.nio.charset.*; +import java.util.*; + +public class AvailableCharSets { + public static void main(String[] args) { + SortedMap charSets = + Charset.availableCharsets(); + for(String csName : charSets.keySet()) { + System.out.print(csName); + Iterator aliases = charSets.get(csName) + .aliases().iterator(); + if(aliases.hasNext()) + System.out.print(": "); + while(aliases.hasNext()) { + System.out.print(aliases.next()); + if(aliases.hasNext()) + System.out.print(", "); + } + System.out.println(); + } + } +} +/* Output: (First 7 Lines) +Big5: csBig5 +Big5-HKSCS: big5-hkscs, big5hk, Big5_HKSCS, big5hkscs +CESU-8: CESU8, csCESU-8 +EUC-JP: csEUCPkdFmtjapanese, x-euc-jp, eucjis, +Extended_UNIX_Code_Packed_Format_for_Japanese, euc_jp, +eucjp, x-eucjp +EUC-KR: ksc5601-1987, csEUCKR, ksc5601_1987, ksc5601, +5601, +euc_kr, ksc_5601, ks_c_5601-1987, euckr +GB18030: gb18030-2000 +GB2312: gb2312, euc-cn, x-EUC-CN, euccn, EUC_CN, +gb2312-80, +gb2312-1980 + ... +*/ diff --git a/code/newio/BufferToText.java b/code/newio/BufferToText.java new file mode 100644 index 00000000..2f38c2c6 --- /dev/null +++ b/code/newio/BufferToText.java @@ -0,0 +1,93 @@ +// newio/BufferToText.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Converting text to and from ByteBuffers +import java.nio.*; +import java.nio.channels.*; +import java.nio.charset.*; +import java.io.*; + +public class BufferToText { + private static final int BSIZE = 1024; + public static void main(String[] args) { + try( + FileChannel fc = new FileOutputStream( + "data2.txt").getChannel() + ) { + fc.write(ByteBuffer.wrap("Some text".getBytes())); + } catch(IOException e) { + throw new RuntimeException(e); + } + ByteBuffer buff = ByteBuffer.allocate(BSIZE); + try( + FileChannel fc = new FileInputStream( + "data2.txt").getChannel() + ) { + fc.read(buff); + } catch(IOException e) { + throw new RuntimeException(e); + } + buff.flip(); + // Doesn't work: + System.out.println(buff.asCharBuffer()); + // Decode using this system's default Charset: + buff.rewind(); + String encoding = + System.getProperty("file.encoding"); + System.out.println("Decoded using " + + encoding + ": " + + Charset.forName(encoding).decode(buff)); + // Encode with something that prints: + try( + FileChannel fc = new FileOutputStream( + "data2.txt").getChannel() + ) { + fc.write(ByteBuffer.wrap( + "Some text".getBytes("UTF-16BE"))); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Now try reading again: + buff.clear(); + try( + FileChannel fc = new FileInputStream( + "data2.txt").getChannel() + ) { + fc.read(buff); + } catch(IOException e) { + throw new RuntimeException(e); + } + buff.flip(); + System.out.println(buff.asCharBuffer()); + // Use a CharBuffer to write through: + buff = ByteBuffer.allocate(24); + buff.asCharBuffer().put("Some text"); + try( + FileChannel fc = new FileOutputStream( + "data2.txt").getChannel() + ) { + fc.write(buff); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Read and display: + buff.clear(); + try( + FileChannel fc = new FileInputStream( + "data2.txt").getChannel() + ) { + fc.read(buff); + } catch(IOException e) { + throw new RuntimeException(e); + } + buff.flip(); + System.out.println(buff.asCharBuffer()); + } +} +/* Output: +???? +Decoded using windows-1252: Some text +Some text +Some textNULNULNUL +*/ diff --git a/code/newio/ChannelCopy.java b/code/newio/ChannelCopy.java new file mode 100644 index 00000000..84696131 --- /dev/null +++ b/code/newio/ChannelCopy.java @@ -0,0 +1,35 @@ +// newio/ChannelCopy.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Copying a file using channels and buffers +// {java ChannelCopy ChannelCopy.java test.txt} +import java.nio.*; +import java.nio.channels.*; +import java.io.*; + +public class ChannelCopy { + private static final int BSIZE = 1024; + public static void main(String[] args) { + if(args.length != 2) { + System.out.println( + "arguments: sourcefile destfile"); + System.exit(1); + } + try( + FileChannel in = new FileInputStream( + args[0]).getChannel(); + FileChannel out = new FileOutputStream( + args[1]).getChannel() + ) { + ByteBuffer buffer = ByteBuffer.allocate(BSIZE); + while(in.read(buffer) != -1) { + buffer.flip(); // Prepare for writing + out.write(buffer); + buffer.clear(); // Prepare for reading + } + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/newio/Endians.java b/code/newio/Endians.java new file mode 100644 index 00000000..11d66076 --- /dev/null +++ b/code/newio/Endians.java @@ -0,0 +1,28 @@ +// newio/Endians.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Endian differences and data storage +import java.nio.*; +import java.util.*; + +public class Endians { + public static void main(String[] args) { + ByteBuffer bb = ByteBuffer.wrap(new byte[12]); + bb.asCharBuffer().put("abcdef"); + System.out.println(Arrays.toString(bb.array())); + bb.rewind(); + bb.order(ByteOrder.BIG_ENDIAN); + bb.asCharBuffer().put("abcdef"); + System.out.println(Arrays.toString(bb.array())); + bb.rewind(); + bb.order(ByteOrder.LITTLE_ENDIAN); + bb.asCharBuffer().put("abcdef"); + System.out.println(Arrays.toString(bb.array())); + } +} +/* Output: +[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102] +[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102] +[97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0] +*/ diff --git a/code/newio/FileLocking.java b/code/newio/FileLocking.java new file mode 100644 index 00000000..e8c74d2a --- /dev/null +++ b/code/newio/FileLocking.java @@ -0,0 +1,30 @@ +// newio/FileLocking.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.channels.*; +import java.util.concurrent.*; +import java.io.*; + +public class FileLocking { + public static void main(String[] args) { + try( + FileOutputStream fos = + new FileOutputStream("file.txt"); + FileLock fl = fos.getChannel().tryLock() + ) { + if(fl != null) { + System.out.println("Locked File"); + TimeUnit.MILLISECONDS.sleep(100); + fl.release(); + System.out.println("Released Lock"); + } + } catch(IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } +} +/* Output: +Locked File +Released Lock +*/ diff --git a/code/newio/GetChannel.java b/code/newio/GetChannel.java new file mode 100644 index 00000000..16caa340 --- /dev/null +++ b/code/newio/GetChannel.java @@ -0,0 +1,53 @@ +// newio/GetChannel.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Getting channels from streams +import java.nio.*; +import java.nio.channels.*; +import java.io.*; + +public class GetChannel { + private static String name = "data.txt"; + private static final int BSIZE = 1024; + public static void main(String[] args) { + // Write a file: + try( + FileChannel fc = new FileOutputStream(name) + .getChannel() + ) { + fc.write(ByteBuffer + .wrap("Some text ".getBytes())); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Add to the end of the file: + try( + FileChannel fc = new RandomAccessFile( + name, "rw").getChannel() + ) { + fc.position(fc.size()); // Move to the end + fc.write(ByteBuffer + .wrap("Some more".getBytes())); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Read the file: + try( + FileChannel fc = new FileInputStream(name) + .getChannel() + ) { + ByteBuffer buff = ByteBuffer.allocate(BSIZE); + fc.read(buff); + buff.flip(); + while(buff.hasRemaining()) + System.out.write(buff.get()); + } catch(IOException e) { + throw new RuntimeException(e); + } + System.out.flush(); + } +} +/* Output: +Some text Some more +*/ diff --git a/code/newio/GetData.java b/code/newio/GetData.java new file mode 100644 index 00000000..b2518b10 --- /dev/null +++ b/code/newio/GetData.java @@ -0,0 +1,56 @@ +// newio/GetData.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Getting different representations from a ByteBuffer +import java.nio.*; + +public class GetData { + private static final int BSIZE = 1024; + public static void main(String[] args) { + ByteBuffer bb = ByteBuffer.allocate(BSIZE); + // Allocation automatically zeroes the ByteBuffer: + int i = 0; + while(i++ < bb.limit()) + if(bb.get() != 0) + System.out.println("nonzero"); + System.out.println("i = " + i); + bb.rewind(); + // Store and read a char array: + bb.asCharBuffer().put("Howdy!"); + char c; + while((c = bb.getChar()) != 0) + System.out.print(c + " "); + System.out.println(); + bb.rewind(); + // Store and read a short: + bb.asShortBuffer().put((short)471142); + System.out.println(bb.getShort()); + bb.rewind(); + // Store and read an int: + bb.asIntBuffer().put(99471142); + System.out.println(bb.getInt()); + bb.rewind(); + // Store and read a long: + bb.asLongBuffer().put(99471142); + System.out.println(bb.getLong()); + bb.rewind(); + // Store and read a float: + bb.asFloatBuffer().put(99471142); + System.out.println(bb.getFloat()); + bb.rewind(); + // Store and read a double: + bb.asDoubleBuffer().put(99471142); + System.out.println(bb.getDouble()); + bb.rewind(); + } +} +/* Output: +i = 1025 +H o w d y ! +12390 +99471142 +99471142 +9.9471144E7 +9.9471142E7 +*/ diff --git a/code/newio/IntBufferDemo.java b/code/newio/IntBufferDemo.java new file mode 100644 index 00000000..31ffaa8f --- /dev/null +++ b/code/newio/IntBufferDemo.java @@ -0,0 +1,35 @@ +// newio/IntBufferDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Manipulating ints in a ByteBuffer with an IntBuffer +import java.nio.*; + +public class IntBufferDemo { + private static final int BSIZE = 1024; + public static void main(String[] args) { + ByteBuffer bb = ByteBuffer.allocate(BSIZE); + IntBuffer ib = bb.asIntBuffer(); + // Store an array of int: + ib.put(new int[]{ 11, 42, 47, 99, 143, 811, 1016 }); + // Absolute location read and write: + System.out.println(ib.get(3)); + ib.put(3, 1811); + // Setting a new limit before rewinding the buffer. + ib.flip(); + while(ib.hasRemaining()) { + int i = ib.get(); + System.out.println(i); + } + } +} +/* Output: +99 +11 +42 +47 +1811 +143 +811 +1016 +*/ diff --git a/code/newio/LargeMappedFiles.java b/code/newio/LargeMappedFiles.java new file mode 100644 index 00000000..c4976e45 --- /dev/null +++ b/code/newio/LargeMappedFiles.java @@ -0,0 +1,31 @@ +// newio/LargeMappedFiles.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating a very large file using mapping +import java.nio.*; +import java.nio.channels.*; +import java.io.*; + +public class LargeMappedFiles { + static int length = 0x8000000; // 128 MB + public static void + main(String[] args) throws Exception { + try( + RandomAccessFile tdat = + new RandomAccessFile("test.dat", "rw") + ) { + MappedByteBuffer out = tdat.getChannel().map( + FileChannel.MapMode.READ_WRITE, 0, length); + for(int i = 0; i < length; i++) + out.put((byte)'x'); + System.out.println("Finished writing"); + for(int i = length/2; i < length/2 + 6; i++) + System.out.print((char)out.get(i)); + } + } +} +/* Output: +Finished writing +xxxxxx +*/ diff --git a/code/newio/LockingMappedFiles.java b/code/newio/LockingMappedFiles.java new file mode 100644 index 00000000..6fe8fee5 --- /dev/null +++ b/code/newio/LockingMappedFiles.java @@ -0,0 +1,60 @@ +// newio/LockingMappedFiles.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Locking portions of a mapped file +import java.nio.*; +import java.nio.channels.*; +import java.io.*; + +public class LockingMappedFiles { + static final int LENGTH = 0x8FFFFFF; // 128 MB + static FileChannel fc; + public static void + main(String[] args) throws Exception { + fc = new RandomAccessFile("test.dat", "rw") + .getChannel(); + MappedByteBuffer out = fc.map( + FileChannel.MapMode.READ_WRITE, 0, LENGTH); + for(int i = 0; i < LENGTH; i++) + out.put((byte)'x'); + new LockAndModify(out, 0, 0 + LENGTH/3); + new LockAndModify( + out, LENGTH/2, LENGTH/2 + LENGTH/4); + } + private static class LockAndModify extends Thread { + private ByteBuffer buff; + private int start, end; + LockAndModify(ByteBuffer mbb, int start, int end) { + this.start = start; + this.end = end; + mbb.limit(end); + mbb.position(start); + buff = mbb.slice(); + start(); + } + @Override + public void run() { + try { + // Exclusive lock with no overlap: + FileLock fl = fc.lock(start, end, false); + System.out.println( + "Locked: "+ start +" to "+ end); + // Perform modification: + while(buff.position() < buff.limit() - 1) + buff.put((byte)(buff.get() + 1)); + fl.release(); + System.out.println( + "Released: " + start + " to " + end); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + } +} +/* Output: +Locked: 75497471 to 113246206 +Locked: 0 to 50331647 +Released: 75497471 to 113246206 +Released: 0 to 50331647 +*/ diff --git a/code/newio/MappedIO.java b/code/newio/MappedIO.java new file mode 100644 index 00000000..93b4ddf3 --- /dev/null +++ b/code/newio/MappedIO.java @@ -0,0 +1,145 @@ +// newio/MappedIO.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromGradle} Runs too long under WSL2 +import java.util.*; +import java.nio.*; +import java.nio.channels.*; +import java.io.*; + +public class MappedIO { + private static int numOfInts = 4_000_000; + private static int numOfUbuffInts = 100_000; + private abstract static class Tester { + private String name; + Tester(String name) { + this.name = name; + } + public void runTest() { + System.out.print(name + ": "); + long start = System.nanoTime(); + test(); + double duration = System.nanoTime() - start; + System.out.format("%.3f%n", duration/1.0e9); + } + public abstract void test(); + } + private static Tester[] tests = { + new Tester("Stream Write") { + @Override + public void test() { + try( + DataOutputStream dos = + new DataOutputStream( + new BufferedOutputStream( + new FileOutputStream( + new File("temp.tmp")))) + ) { + for(int i = 0; i < numOfInts; i++) + dos.writeInt(i); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + }, + new Tester("Mapped Write") { + @Override + public void test() { + try( + FileChannel fc = + new RandomAccessFile("temp.tmp", "rw") + .getChannel() + ) { + IntBuffer ib = + fc.map(FileChannel.MapMode.READ_WRITE, + 0, fc.size()).asIntBuffer(); + for(int i = 0; i < numOfInts; i++) + ib.put(i); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + }, + new Tester("Stream Read") { + @Override + public void test() { + try( + DataInputStream dis = + new DataInputStream( + new BufferedInputStream( + new FileInputStream("temp.tmp"))) + ) { + for(int i = 0; i < numOfInts; i++) + dis.readInt(); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + }, + new Tester("Mapped Read") { + @Override + public void test() { + try( + FileChannel fc = new FileInputStream( + new File("temp.tmp")).getChannel() + ) { + IntBuffer ib = + fc.map(FileChannel.MapMode.READ_ONLY, + 0, fc.size()).asIntBuffer(); + while(ib.hasRemaining()) + ib.get(); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + }, + new Tester("Stream Read/Write") { + @Override + public void test() { + try( + RandomAccessFile raf = + new RandomAccessFile( + new File("temp.tmp"), "rw") + ) { + raf.writeInt(1); + for(int i = 0; i < numOfUbuffInts; i++) { + raf.seek(raf.length() - 4); + raf.writeInt(raf.readInt()); + } + } catch(IOException e) { + throw new RuntimeException(e); + } + } + }, + new Tester("Mapped Read/Write") { + @Override + public void test() { + try( + FileChannel fc = new RandomAccessFile( + new File("temp.tmp"), "rw").getChannel() + ) { + IntBuffer ib = + fc.map(FileChannel.MapMode.READ_WRITE, + 0, fc.size()).asIntBuffer(); + ib.put(0); + for(int i = 1; i < numOfUbuffInts; i++) + ib.put(ib.get(i - 1)); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + } + }; + public static void main(String[] args) { + Arrays.stream(tests).forEach(Tester::runTest); + } +} +/* Output: +Stream Write: 0.615 +Mapped Write: 0.050 +Stream Read: 0.577 +Mapped Read: 0.015 +Stream Read/Write: 4.069 +Mapped Read/Write: 0.013 +*/ diff --git a/code/newio/TransferTo.java b/code/newio/TransferTo.java new file mode 100644 index 00000000..f3095b71 --- /dev/null +++ b/code/newio/TransferTo.java @@ -0,0 +1,30 @@ +// newio/TransferTo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using transferTo() between channels +// {java TransferTo TransferTo.java TransferTo.txt} +import java.nio.channels.*; +import java.io.*; + +public class TransferTo { + public static void main(String[] args) { + if(args.length != 2) { + System.out.println( + "arguments: sourcefile destfile"); + System.exit(1); + } + try( + FileChannel in = new FileInputStream( + args[0]).getChannel(); + FileChannel out = new FileOutputStream( + args[1]).getChannel() + ) { + in.transferTo(0, in.size(), out); + // Or: + // out.transferFrom(in, 0, in.size()); + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/newio/UsingBuffers.java b/code/newio/UsingBuffers.java new file mode 100644 index 00000000..3f3a6bd1 --- /dev/null +++ b/code/newio/UsingBuffers.java @@ -0,0 +1,35 @@ +// newio/UsingBuffers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.*; + +public class UsingBuffers { + private static + void symmetricScramble(CharBuffer buffer) { + while(buffer.hasRemaining()) { + buffer.mark(); + char c1 = buffer.get(); + char c2 = buffer.get(); + buffer.reset(); + buffer.put(c2).put(c1); + } + } + public static void main(String[] args) { + char[] data = "UsingBuffers".toCharArray(); + ByteBuffer bb = + ByteBuffer.allocate(data.length * 2); + CharBuffer cb = bb.asCharBuffer(); + cb.put(data); + System.out.println(cb.rewind()); + symmetricScramble(cb); + System.out.println(cb.rewind()); + symmetricScramble(cb); + System.out.println(cb.rewind()); + } +} +/* Output: +UsingBuffers +sUniBgfuefsr +UsingBuffers +*/ diff --git a/code/newio/ViewBuffers.java b/code/newio/ViewBuffers.java new file mode 100644 index 00000000..d7bb1adf --- /dev/null +++ b/code/newio/ViewBuffers.java @@ -0,0 +1,69 @@ +// newio/ViewBuffers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.*; + +public class ViewBuffers { + public static void main(String[] args) { + ByteBuffer bb = ByteBuffer.wrap( + new byte[]{ 0, 0, 0, 0, 0, 0, 0, 'a' }); + bb.rewind(); + System.out.print("Byte Buffer "); + while(bb.hasRemaining()) + System.out.print( + bb.position()+ " -> " + bb.get() + ", "); + System.out.println(); + CharBuffer cb = + ((ByteBuffer)bb.rewind()).asCharBuffer(); + System.out.print("Char Buffer "); + while(cb.hasRemaining()) + System.out.print( + cb.position() + " -> " + cb.get() + ", "); + System.out.println(); + FloatBuffer fb = + ((ByteBuffer)bb.rewind()).asFloatBuffer(); + System.out.print("Float Buffer "); + while(fb.hasRemaining()) + System.out.print( + fb.position()+ " -> " + fb.get() + ", "); + System.out.println(); + IntBuffer ib = + ((ByteBuffer)bb.rewind()).asIntBuffer(); + System.out.print("Int Buffer "); + while(ib.hasRemaining()) + System.out.print( + ib.position()+ " -> " + ib.get() + ", "); + System.out.println(); + LongBuffer lb = + ((ByteBuffer)bb.rewind()).asLongBuffer(); + System.out.print("Long Buffer "); + while(lb.hasRemaining()) + System.out.print( + lb.position()+ " -> " + lb.get() + ", "); + System.out.println(); + ShortBuffer sb = + ((ByteBuffer)bb.rewind()).asShortBuffer(); + System.out.print("Short Buffer "); + while(sb.hasRemaining()) + System.out.print( + sb.position()+ " -> " + sb.get() + ", "); + System.out.println(); + DoubleBuffer db = + ((ByteBuffer)bb.rewind()).asDoubleBuffer(); + System.out.print("Double Buffer "); + while(db.hasRemaining()) + System.out.print( + db.position()+ " -> " + db.get() + ", "); + } +} +/* Output: +Byte Buffer 0 -> 0, 1 -> 0, 2 -> 0, 3 -> 0, 4 -> 0, 5 +-> 0, 6 -> 0, 7 -> 97, +Char Buffer 0 -> NUL, 1 -> NUL, 2 -> NUL, 3 -> a, +Float Buffer 0 -> 0.0, 1 -> 1.36E-43, +Int Buffer 0 -> 0, 1 -> 97, +Long Buffer 0 -> 97, +Short Buffer 0 -> 0, 1 -> 0, 2 -> 0, 3 -> 97, +Double Buffer 0 -> 4.8E-322, +*/ diff --git a/code/objects/HelloDate.java b/code/objects/HelloDate.java new file mode 100644 index 00000000..1f613e8e --- /dev/null +++ b/code/objects/HelloDate.java @@ -0,0 +1,12 @@ +// objects/HelloDate.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class HelloDate { + public static void main(String[] args) { + System.out.println("Hello, it's: "); + System.out.println(new Date()); + } +} diff --git a/code/objects/ShowProperties.java b/code/objects/ShowProperties.java new file mode 100644 index 00000000..ac2bf41e --- /dev/null +++ b/code/objects/ShowProperties.java @@ -0,0 +1,39 @@ +// objects/ShowProperties.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class ShowProperties { + public static void main(String[] args) { + System.getProperties().list(System.out); + System.out.println(System.getProperty("user.name")); + System.out.println( + System.getProperty("java.library.path")); + } +} +/* Output: (First 20 Lines) +-- listing properties -- +java.runtime.name=Java(TM) SE Runtime Environment +sun.boot.library.path=C:\Program +Files\Java\jdk1.8.0_112\jr... +java.vm.version=25.112-b15 +java.vm.vendor=Oracle Corporation +java.vendor.url=http://java.oracle.com/ +path.separator=; +java.vm.name=Java HotSpot(TM) 64-Bit Server VM +file.encoding.pkg=sun.io +user.script= +user.country=US +sun.java.launcher=SUN_STANDARD +sun.os.patch.level= +java.vm.specification.name=Java Virtual Machine +Specification +user.dir=C:\Users\Bruce\Documents\GitHub\on-ja... +java.runtime.version=1.8.0_112-b15 +java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment +java.endorsed.dirs=C:\Program +Files\Java\jdk1.8.0_112\jr... +os.arch=amd64 +java.io.tmpdir=C:\Users\Bruce\AppData\Local\Temp\ + ... +*/ diff --git a/code/onjava/ArrayShow.java b/code/onjava/ArrayShow.java new file mode 100644 index 00000000..6edd148f --- /dev/null +++ b/code/onjava/ArrayShow.java @@ -0,0 +1,73 @@ +// onjava/ArrayShow.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.util.*; + +public interface ArrayShow { + static void show(Object[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(boolean[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(byte[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(char[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(short[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(int[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(long[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(float[] a) { + System.out.println(Arrays.toString(a)); + } + static void show(double[] a) { + System.out.println(Arrays.toString(a)); + } + // Start with a description: + static void show(String info, Object[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, boolean[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, byte[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, char[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, short[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, int[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, long[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, float[] a) { + System.out.print(info + ": "); + show(a); + } + static void show(String info, double[] a) { + System.out.print(info + ": "); + show(a); + } +} diff --git a/code/onjava/BasicSupplier.java b/code/onjava/BasicSupplier.java new file mode 100644 index 00000000..d4bf3b3d --- /dev/null +++ b/code/onjava/BasicSupplier.java @@ -0,0 +1,31 @@ +// onjava/BasicSupplier.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Supplier from a class with a no-arg constructor +package onjava; +import java.util.function.*; +import java.lang.reflect.InvocationTargetException; + +public class BasicSupplier implements Supplier { + private Class type; + public BasicSupplier(Class type) { + this.type = type; + } + @Override + public T get() { + try { + // Assumes type is a public class: + return type.getConstructor().newInstance(); + } catch(InstantiationException | + NoSuchMethodException | + InvocationTargetException | + IllegalAccessException e) { + throw new RuntimeException(e); + } + } + // Produce a default Supplier from a type token: + public static Supplier create(Class type) { + return new BasicSupplier<>(type); + } +} diff --git a/code/onjava/CollectionMethodDifferences.java b/code/onjava/CollectionMethodDifferences.java new file mode 100644 index 00000000..375d4e41 --- /dev/null +++ b/code/onjava/CollectionMethodDifferences.java @@ -0,0 +1,117 @@ +// onjava/CollectionMethodDifferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.CollectionMethodDifferences} +package onjava; +import java.lang.reflect.*; +import java.util.*; +import java.util.stream.*; + +public class CollectionMethodDifferences { + static Set methodSet(Class type) { + return Arrays.stream(type.getMethods()) + .map(Method::getName) + .collect(Collectors.toCollection(TreeSet::new)); + } + static void interfaces(Class type) { + System.out.print("Interfaces in " + + type.getSimpleName() + ": "); + System.out.println( + Arrays.stream(type.getInterfaces()) + .map(Class::getSimpleName) + .collect(Collectors.toList())); + } + static Set object = methodSet(Object.class); + static { object.add("clone"); } + static void + difference(Class superset, Class subset) { + System.out.print(superset.getSimpleName() + + " extends " + subset.getSimpleName() + + ", adds: "); + Set comp = Sets.difference( + methodSet(superset), methodSet(subset)); + comp.removeAll(object); // Ignore 'Object' methods + System.out.println(comp); + interfaces(superset); + } + public static void main(String[] args) { + System.out.println("Collection: " + + methodSet(Collection.class)); + interfaces(Collection.class); + difference(Set.class, Collection.class); + difference(HashSet.class, Set.class); + difference(LinkedHashSet.class, HashSet.class); + difference(TreeSet.class, Set.class); + difference(List.class, Collection.class); + difference(ArrayList.class, List.class); + difference(LinkedList.class, List.class); + difference(Queue.class, Collection.class); + difference(PriorityQueue.class, Queue.class); + System.out.println("Map: " + methodSet(Map.class)); + difference(HashMap.class, Map.class); + difference(LinkedHashMap.class, HashMap.class); + difference(SortedMap.class, Map.class); + difference(TreeMap.class, Map.class); + } +} +/* Output: +Collection: [add, addAll, clear, contains, containsAll, +equals, forEach, hashCode, isEmpty, iterator, +parallelStream, remove, removeAll, removeIf, retainAll, +size, spliterator, stream, toArray] +Interfaces in Collection: [Iterable] +Set extends Collection, adds: [] +Interfaces in Set: [Collection] +HashSet extends Set, adds: [] +Interfaces in HashSet: [Set, Cloneable, Serializable] +LinkedHashSet extends HashSet, adds: [] +Interfaces in LinkedHashSet: [Set, Cloneable, +Serializable] +TreeSet extends Set, adds: [headSet, +descendingIterator, descendingSet, pollLast, subSet, +floor, tailSet, ceiling, last, lower, comparator, +pollFirst, first, higher] +Interfaces in TreeSet: [NavigableSet, Cloneable, +Serializable] +List extends Collection, adds: [replaceAll, get, +indexOf, subList, set, sort, lastIndexOf, listIterator] +Interfaces in List: [Collection] +ArrayList extends List, adds: [trimToSize, +ensureCapacity] +Interfaces in ArrayList: [List, RandomAccess, +Cloneable, Serializable] +LinkedList extends List, adds: [offerFirst, poll, +getLast, offer, getFirst, removeFirst, element, +removeLastOccurrence, peekFirst, peekLast, push, +pollFirst, removeFirstOccurrence, descendingIterator, +pollLast, removeLast, pop, addLast, peek, offerLast, +addFirst] +Interfaces in LinkedList: [List, Deque, Cloneable, +Serializable] +Queue extends Collection, adds: [poll, peek, offer, +element] +Interfaces in Queue: [Collection] +PriorityQueue extends Queue, adds: [comparator] +Interfaces in PriorityQueue: [Serializable] +Map: [clear, compute, computeIfAbsent, +computeIfPresent, containsKey, containsValue, entrySet, +equals, forEach, get, getOrDefault, hashCode, isEmpty, +keySet, merge, put, putAll, putIfAbsent, remove, +replace, replaceAll, size, values] +HashMap extends Map, adds: [] +Interfaces in HashMap: [Map, Cloneable, Serializable] +LinkedHashMap extends HashMap, adds: [] +Interfaces in LinkedHashMap: [Map] +SortedMap extends Map, adds: [lastKey, subMap, +comparator, firstKey, headMap, tailMap] +Interfaces in SortedMap: [Map] +TreeMap extends Map, adds: [descendingKeySet, +navigableKeySet, higherEntry, higherKey, floorKey, +subMap, ceilingKey, pollLastEntry, firstKey, lowerKey, +headMap, tailMap, lowerEntry, ceilingEntry, +descendingMap, pollFirstEntry, lastKey, firstEntry, +floorEntry, comparator, lastEntry] +Interfaces in TreeMap: [NavigableMap, Cloneable, +Serializable] +*/ diff --git a/code/onjava/ConvertTo.java b/code/onjava/ConvertTo.java new file mode 100644 index 00000000..cc8febd7 --- /dev/null +++ b/code/onjava/ConvertTo.java @@ -0,0 +1,105 @@ +// onjava/ConvertTo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; + +public interface ConvertTo { + static boolean[] primitive(Boolean[] in) { + boolean[] result = new boolean[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; // Autounboxing + return result; + } + static char[] primitive(Character[] in) { + char[] result = new char[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static byte[] primitive(Byte[] in) { + byte[] result = new byte[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static short[] primitive(Short[] in) { + short[] result = new short[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static int[] primitive(Integer[] in) { + int[] result = new int[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static long[] primitive(Long[] in) { + long[] result = new long[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static float[] primitive(Float[] in) { + float[] result = new float[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static double[] primitive(Double[] in) { + double[] result = new double[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + // Convert from primitive array to wrapped array: + static Boolean[] boxed(boolean[] in) { + Boolean[] result = new Boolean[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; // Autoboxing + return result; + } + static Character[] boxed(char[] in) { + Character[] result = new Character[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static Byte[] boxed(byte[] in) { + Byte[] result = new Byte[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static Short[] boxed(short[] in) { + Short[] result = new Short[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static Integer[] boxed(int[] in) { + Integer[] result = new Integer[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static Long[] boxed(long[] in) { + Long[] result = new Long[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static Float[] boxed(float[] in) { + Float[] result = new Float[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } + static Double[] boxed(double[] in) { + Double[] result = new Double[in.length]; + for(int i = 0; i < in.length; i++) + result[i] = in[i]; + return result; + } +} diff --git a/code/onjava/Count.java b/code/onjava/Count.java new file mode 100644 index 00000000..1f380f87 --- /dev/null +++ b/code/onjava/Count.java @@ -0,0 +1,220 @@ +// onjava/Count.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Generate incremental values of different types +package onjava; +import java.util.*; +import java.util.function.*; +import static onjava.ConvertTo.*; + +public interface Count { + class Boolean + implements Supplier { + private boolean b = true; + @Override + public java.lang.Boolean get() { + b = !b; + return java.lang.Boolean.valueOf(b); + } + public java.lang.Boolean get(int n) { + return get(); + } + public java.lang.Boolean[] array(int sz) { + java.lang.Boolean[] result = + new java.lang.Boolean[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pboolean { + private boolean b = true; + public boolean get() { + b = !b; + return b; + } + public boolean get(int n) { return get(); } + public boolean[] array(int sz) { + return primitive(new Boolean().array(sz)); + } + } + class Byte + implements Supplier { + private byte b; + @Override + public java.lang.Byte get() { return b++; } + public java.lang.Byte get(int n) { + return get(); + } + public java.lang.Byte[] array(int sz) { + java.lang.Byte[] result = + new java.lang.Byte[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pbyte { + private byte b; + public byte get() { return b++; } + public byte get(int n) { return get(); } + public byte[] array(int sz) { + return primitive(new Byte().array(sz)); + } + } + char[] CHARS = + "abcdefghijklmnopqrstuvwxyz".toCharArray(); + class Character + implements Supplier { + private int i; + @Override + public java.lang.Character get() { + i = (i + 1) % CHARS.length; + return CHARS[i]; + } + public java.lang.Character get(int n) { + return get(); + } + public java.lang.Character[] array(int sz) { + java.lang.Character[] result = + new java.lang.Character[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pchar { + private int i; + public char get() { + i = (i + 1) % CHARS.length; + return CHARS[i]; + } + public char get(int n) { return get(); } + public char[] array(int sz) { + return primitive(new Character().array(sz)); + } + } + class Short + implements Supplier { + short s; + @Override + public java.lang.Short get() { return s++; } + public java.lang.Short get(int n) { + return get(); + } + public java.lang.Short[] array(int sz) { + java.lang.Short[] result = + new java.lang.Short[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pshort { + short s; + public short get() { return s++; } + public short get(int n) { return get(); } + public short[] array(int sz) { + return primitive(new Short().array(sz)); + } + } + class Integer + implements Supplier { + int i; + @Override + public java.lang.Integer get() { return i++; } + public java.lang.Integer get(int n) { + return get(); + } + public java.lang.Integer[] array(int sz) { + java.lang.Integer[] result = + new java.lang.Integer[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pint implements IntSupplier { + int i; + public int get() { return i++; } + public int get(int n) { return get(); } + @Override + public int getAsInt() { return get(); } + public int[] array(int sz) { + return primitive(new Integer().array(sz)); + } + } + class Long + implements Supplier { + private long l; + @Override + public java.lang.Long get() { return l++; } + public java.lang.Long get(int n) { + return get(); + } + public java.lang.Long[] array(int sz) { + java.lang.Long[] result = + new java.lang.Long[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Plong implements LongSupplier { + private long l; + public long get() { return l++; } + public long get(int n) { return get(); } + @Override + public long getAsLong() { return get(); } + public long[] array(int sz) { + return primitive(new Long().array(sz)); + } + } + class Float + implements Supplier { + private int i; + @Override + public java.lang.Float get() { + return java.lang.Float.valueOf(i++); + } + public java.lang.Float get(int n) { + return get(); + } + public java.lang.Float[] array(int sz) { + java.lang.Float[] result = + new java.lang.Float[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pfloat { + private int i; + public float get() { return i++; } + public float get(int n) { return get(); } + public float[] array(int sz) { + return primitive(new Float().array(sz)); + } + } + class Double + implements Supplier { + private int i; + @Override + public java.lang.Double get() { + return java.lang.Double.valueOf(i++); + } + public java.lang.Double get(int n) { + return get(); + } + public java.lang.Double[] array(int sz) { + java.lang.Double[] result = + new java.lang.Double[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pdouble implements DoubleSupplier { + private int i; + public double get() { return i++; } + public double get(int n) { return get(); } + @Override + public double getAsDouble() { return get(0); } + public double[] array(int sz) { + return primitive(new Double().array(sz)); + } + } +} diff --git a/code/onjava/CountMap.java b/code/onjava/CountMap.java new file mode 100644 index 00000000..e3759053 --- /dev/null +++ b/code/onjava/CountMap.java @@ -0,0 +1,97 @@ +// onjava/CountMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Unlimited-length Map containing sample data +// {java onjava.CountMap} +package onjava; +import java.util.*; +import java.util.stream.*; + +public class CountMap +extends AbstractMap { + private int size; + private static char[] chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + private static String value(int key) { + return + chars[key % chars.length] + + Integer.toString(key / chars.length); + } + public CountMap(int size) { + this.size = size < 0 ? 0 : size; + } + @Override + public String get(Object key) { + return value((Integer)key); + } + private static class Entry + implements Map.Entry { + int index; + Entry(int index) { this.index = index; } + @Override + public boolean equals(Object o) { + return o instanceof Entry && + Objects.equals(index, ((Entry)o).index); + } + @Override + public Integer getKey() { return index; } + @Override + public String getValue() { + return value(index); + } + @Override + public String setValue(String value) { + throw new UnsupportedOperationException(); + } + @Override + public int hashCode() { + return Objects.hashCode(index); + } + } + @Override + public Set> entrySet() { + // LinkedHashSet retains initialization order: + return IntStream.range(0, size) + .mapToObj(Entry::new) + .collect(Collectors + .toCollection(LinkedHashSet::new)); + } + public static void main(String[] args) { + final int size = 6; + CountMap cm = new CountMap(60); + System.out.println(cm); + System.out.println(cm.get(500)); + cm.values().stream() + .limit(size) + .forEach(System.out::println); + System.out.println(); + new Random(47).ints(size, 0, 1000) + .mapToObj(cm::get) + .forEach(System.out::println); + } +} +/* Output: +{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, +9=J0, 10=K0, 11=L0, 12=M0, 13=N0, 14=O0, 15=P0, 16=Q0, +17=R0, 18=S0, 19=T0, 20=U0, 21=V0, 22=W0, 23=X0, 24=Y0, +25=Z0, 26=A1, 27=B1, 28=C1, 29=D1, 30=E1, 31=F1, 32=G1, +33=H1, 34=I1, 35=J1, 36=K1, 37=L1, 38=M1, 39=N1, 40=O1, +41=P1, 42=Q1, 43=R1, 44=S1, 45=T1, 46=U1, 47=V1, 48=W1, +49=X1, 50=Y1, 51=Z1, 52=A2, 53=B2, 54=C2, 55=D2, 56=E2, +57=F2, 58=G2, 59=H2} +G19 +A0 +B0 +C0 +D0 +E0 +F0 + +Y9 +J21 +R26 +D33 +Z36 +N16 +*/ diff --git a/code/onjava/CountingIntegerList.java b/code/onjava/CountingIntegerList.java new file mode 100644 index 00000000..7d5d4f79 --- /dev/null +++ b/code/onjava/CountingIntegerList.java @@ -0,0 +1,34 @@ +// onjava/CountingIntegerList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// List of any length, containing sample data +// {java onjava.CountingIntegerList} +package onjava; +import java.util.*; + +public class CountingIntegerList +extends AbstractList { + private int size; + public CountingIntegerList() { size = 0; } + public CountingIntegerList(int size) { + this.size = size < 0 ? 0 : size; + } + @Override + public Integer get(int index) { + return index; + } + @Override + public int size() { return size; } + public static void main(String[] args) { + List cil = + new CountingIntegerList(30); + System.out.println(cil); + System.out.println(cil.get(500)); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] +500 +*/ diff --git a/code/onjava/Countries.java b/code/onjava/Countries.java new file mode 100644 index 00000000..ec42b592 --- /dev/null +++ b/code/onjava/Countries.java @@ -0,0 +1,351 @@ +// onjava/Countries.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// "Flyweight" Maps and Lists of sample data +// {java onjava.Countries} +package onjava; +import java.util.*; + +public class Countries { + public static final String[][] DATA = { + // Africa + {"ALGERIA","Algiers"}, + {"ANGOLA","Luanda"}, + {"BENIN","Porto-Novo"}, + {"BOTSWANA","Gaberone"}, + {"BURKINA FASO","Ouagadougou"}, + {"BURUNDI","Bujumbura"}, + {"CAMEROON","Yaounde"}, + {"CAPE VERDE","Praia"}, + {"CENTRAL AFRICAN REPUBLIC","Bangui"}, + {"CHAD","N'djamena"}, + {"COMOROS","Moroni"}, + {"CONGO","Brazzaville"}, + {"DJIBOUTI","Dijibouti"}, + {"EGYPT","Cairo"}, + {"EQUATORIAL GUINEA","Malabo"}, + {"ERITREA","Asmara"}, + {"ETHIOPIA","Addis Ababa"}, + {"GABON","Libreville"}, + {"THE GAMBIA","Banjul"}, + {"GHANA","Accra"}, + {"GUINEA","Conakry"}, + {"BISSAU","Bissau"}, + {"COTE D'IVOIR (IVORY COAST)","Yamoussoukro"}, + {"KENYA","Nairobi"}, + {"LESOTHO","Maseru"}, + {"LIBERIA","Monrovia"}, + {"LIBYA","Tripoli"}, + {"MADAGASCAR","Antananarivo"}, + {"MALAWI","Lilongwe"}, + {"MALI","Bamako"}, + {"MAURITANIA","Nouakchott"}, + {"MAURITIUS","Port Louis"}, + {"MOROCCO","Rabat"}, + {"MOZAMBIQUE","Maputo"}, + {"NAMIBIA","Windhoek"}, + {"NIGER","Niamey"}, + {"NIGERIA","Abuja"}, + {"RWANDA","Kigali"}, + {"SAO TOME E PRINCIPE","Sao Tome"}, + {"SENEGAL","Dakar"}, + {"SEYCHELLES","Victoria"}, + {"SIERRA LEONE","Freetown"}, + {"SOMALIA","Mogadishu"}, + {"SOUTH AFRICA","Pretoria/Cape Town"}, + {"SUDAN","Khartoum"}, + {"SWAZILAND","Mbabane"}, + {"TANZANIA","Dodoma"}, + {"TOGO","Lome"}, + {"TUNISIA","Tunis"}, + {"UGANDA","Kampala"}, + {"DEMOCRATIC REPUBLIC OF THE CONGO (ZAIRE)", + "Kinshasa"}, + {"ZAMBIA","Lusaka"}, + {"ZIMBABWE","Harare"}, + // Asia + {"AFGHANISTAN","Kabul"}, + {"BAHRAIN","Manama"}, + {"BANGLADESH","Dhaka"}, + {"BHUTAN","Thimphu"}, + {"BRUNEI","Bandar Seri Begawan"}, + {"CAMBODIA","Phnom Penh"}, + {"CHINA","Beijing"}, + {"CYPRUS","Nicosia"}, + {"INDIA","New Delhi"}, + {"INDONESIA","Jakarta"}, + {"IRAN","Tehran"}, + {"IRAQ","Baghdad"}, + {"ISRAEL","Jerusalem"}, + {"JAPAN","Tokyo"}, + {"JORDAN","Amman"}, + {"KUWAIT","Kuwait City"}, + {"LAOS","Vientiane"}, + {"LEBANON","Beirut"}, + {"MALAYSIA","Kuala Lumpur"}, + {"THE MALDIVES","Male"}, + {"MONGOLIA","Ulan Bator"}, + {"MYANMAR (BURMA)","Rangoon"}, + {"NEPAL","Katmandu"}, + {"NORTH KOREA","P'yongyang"}, + {"OMAN","Muscat"}, + {"PAKISTAN","Islamabad"}, + {"PHILIPPINES","Manila"}, + {"QATAR","Doha"}, + {"SAUDI ARABIA","Riyadh"}, + {"SINGAPORE","Singapore"}, + {"SOUTH KOREA","Seoul"}, + {"SRI LANKA","Colombo"}, + {"SYRIA","Damascus"}, + {"TAIWAN (REPUBLIC OF CHINA)","Taipei"}, + {"THAILAND","Bangkok"}, + {"TURKEY","Ankara"}, + {"UNITED ARAB EMIRATES","Abu Dhabi"}, + {"VIETNAM","Hanoi"}, + {"YEMEN","Sana'a"}, + // Australia and Oceania + {"AUSTRALIA","Canberra"}, + {"FIJI","Suva"}, + {"KIRIBATI","Bairiki"}, + {"MARSHALL ISLANDS","Dalap-Uliga-Darrit"}, + {"MICRONESIA","Palikir"}, + {"NAURU","Yaren"}, + {"NEW ZEALAND","Wellington"}, + {"PALAU","Koror"}, + {"PAPUA NEW GUINEA","Port Moresby"}, + {"SOLOMON ISLANDS","Honaira"}, + {"TONGA","Nuku'alofa"}, + {"TUVALU","Fongafale"}, + {"VANUATU","Port Vila"}, + {"WESTERN SAMOA","Apia"}, + // Eastern Europe and former USSR + {"ARMENIA","Yerevan"}, + {"AZERBAIJAN","Baku"}, + {"BELARUS (BYELORUSSIA)","Minsk"}, + {"BULGARIA","Sofia"}, + {"GEORGIA","Tbilisi"}, + {"KAZAKSTAN","Almaty"}, + {"KYRGYZSTAN","Alma-Ata"}, + {"MOLDOVA","Chisinau"}, + {"RUSSIA","Moscow"}, + {"TAJIKISTAN","Dushanbe"}, + {"TURKMENISTAN","Ashkabad"}, + {"UKRAINE","Kyiv"}, + {"UZBEKISTAN","Tashkent"}, + // Europe + {"ALBANIA","Tirana"}, + {"ANDORRA","Andorra la Vella"}, + {"AUSTRIA","Vienna"}, + {"BELGIUM","Brussels"}, + {"BOSNIA-HERZEGOVINA","Sarajevo"}, + {"CROATIA","Zagreb"}, + {"CZECH REPUBLIC","Prague"}, + {"DENMARK","Copenhagen"}, + {"ESTONIA","Tallinn"}, + {"FINLAND","Helsinki"}, + {"FRANCE","Paris"}, + {"GERMANY","Berlin"}, + {"GREECE","Athens"}, + {"HUNGARY","Budapest"}, + {"ICELAND","Reykjavik"}, + {"IRELAND","Dublin"}, + {"ITALY","Rome"}, + {"LATVIA","Riga"}, + {"LIECHTENSTEIN","Vaduz"}, + {"LITHUANIA","Vilnius"}, + {"LUXEMBOURG","Luxembourg"}, + {"MACEDONIA","Skopje"}, + {"MALTA","Valletta"}, + {"MONACO","Monaco"}, + {"MONTENEGRO","Podgorica"}, + {"THE NETHERLANDS","Amsterdam"}, + {"NORWAY","Oslo"}, + {"POLAND","Warsaw"}, + {"PORTUGAL","Lisbon"}, + {"ROMANIA","Bucharest"}, + {"SAN MARINO","San Marino"}, + {"SERBIA","Belgrade"}, + {"SLOVAKIA","Bratislava"}, + {"SLOVENIA","Ljuijana"}, + {"SPAIN","Madrid"}, + {"SWEDEN","Stockholm"}, + {"SWITZERLAND","Berne"}, + {"UNITED KINGDOM","London"}, + {"VATICAN CITY","Vatican City"}, + // North and Central America + {"ANTIGUA AND BARBUDA","Saint John's"}, + {"BAHAMAS","Nassau"}, + {"BARBADOS","Bridgetown"}, + {"BELIZE","Belmopan"}, + {"CANADA","Ottawa"}, + {"COSTA RICA","San Jose"}, + {"CUBA","Havana"}, + {"DOMINICA","Roseau"}, + {"DOMINICAN REPUBLIC","Santo Domingo"}, + {"EL SALVADOR","San Salvador"}, + {"GRENADA","Saint George's"}, + {"GUATEMALA","Guatemala City"}, + {"HAITI","Port-au-Prince"}, + {"HONDURAS","Tegucigalpa"}, + {"JAMAICA","Kingston"}, + {"MEXICO","Mexico City"}, + {"NICARAGUA","Managua"}, + {"PANAMA","Panama City"}, + {"ST. KITTS AND NEVIS","Basseterre"}, + {"ST. LUCIA","Castries"}, + {"ST. VINCENT AND THE GRENADINES","Kingstown"}, + {"UNITED STATES OF AMERICA","Washington, D.C."}, + // South America + {"ARGENTINA","Buenos Aires"}, + {"BOLIVIA","Sucre (legal)/La Paz(administrative)"}, + {"BRAZIL","Brasilia"}, + {"CHILE","Santiago"}, + {"COLOMBIA","Bogota"}, + {"ECUADOR","Quito"}, + {"GUYANA","Georgetown"}, + {"PARAGUAY","Asuncion"}, + {"PERU","Lima"}, + {"SURINAME","Paramaribo"}, + {"TRINIDAD AND TOBAGO","Port of Spain"}, + {"URUGUAY","Montevideo"}, + {"VENEZUELA","Caracas"}, + }; + // Use AbstractMap by implementing entrySet() + private static class FlyweightMap + extends AbstractMap { + private static class Entry + implements Map.Entry { + int index; + Entry(int index) { this.index = index; } + @Override + public boolean equals(Object o) { + return o instanceof FlyweightMap && + Objects.equals(DATA[index][0], o); + } + @Override + public int hashCode() { + return Objects.hashCode(DATA[index][0]); + } + @Override + public String getKey() { return DATA[index][0]; } + @Override + public String getValue() { + return DATA[index][1]; + } + @Override + public String setValue(String value) { + throw new UnsupportedOperationException(); + } + } + // Implement size() & iterator() for AbstractSet: + static class EntrySet + extends AbstractSet> { + private int size; + EntrySet(int size) { + if(size < 0) + this.size = 0; + // Can't be any bigger than the array: + else if(size > DATA.length) + this.size = DATA.length; + else + this.size = size; + } + @Override + public int size() { return size; } + private class Iter + implements Iterator> { + // Only one Entry object per Iterator: + private Entry entry = new Entry(-1); + @Override + public boolean hasNext() { + return entry.index < size - 1; + } + @Override + public Map.Entry next() { + entry.index++; + return entry; + } + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + @Override + public + Iterator> iterator() { + return new Iter(); + } + } + private static + Set> entries = + new EntrySet(DATA.length); + @Override + public Set> entrySet() { + return entries; + } + } + // Create a partial map of 'size' countries: + static Map select(final int size) { + return new FlyweightMap() { + @Override + public Set> entrySet() { + return new EntrySet(size); + } + }; + } + static Map map = new FlyweightMap(); + public static Map capitals() { + return map; // The entire map + } + public static Map capitals(int size) { + return select(size); // A partial map + } + static List names = + new ArrayList<>(map.keySet()); + // All the names: + public static List names() { return names; } + // A partial list: + public static List names(int size) { + return new ArrayList<>(select(size).keySet()); + } + public static void main(String[] args) { + System.out.println(capitals(10)); + System.out.println(names(10)); + System.out.println(new HashMap<>(capitals(3))); + System.out.println( + new LinkedHashMap<>(capitals(3))); + System.out.println(new TreeMap<>(capitals(3))); + System.out.println(new Hashtable<>(capitals(3))); + System.out.println(new HashSet<>(names(6))); + System.out.println(new LinkedHashSet<>(names(6))); + System.out.println(new TreeSet<>(names(6))); + System.out.println(new ArrayList<>(names(6))); + System.out.println(new LinkedList<>(names(6))); + System.out.println(capitals().get("BRAZIL")); + } +} +/* Output: +{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo, +BOTSWANA=Gaberone, BURKINA FASO=Ouagadougou, +BURUNDI=Bujumbura, CAMEROON=Yaounde, CAPE VERDE=Praia, +CENTRAL AFRICAN REPUBLIC=Bangui, CHAD=N'djamena} +[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, +BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN +REPUBLIC, CHAD] +{BENIN=Porto-Novo, ANGOLA=Luanda, ALGERIA=Algiers} +{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo} +{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo} +{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo} +[BENIN, BOTSWANA, ANGOLA, BURKINA FASO, ALGERIA, +BURUNDI] +[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, +BURUNDI] +[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, +BURUNDI] +[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, +BURUNDI] +[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, +BURUNDI] +Brasilia +*/ diff --git a/code/onjava/Enums.java b/code/onjava/Enums.java new file mode 100644 index 00000000..0440802f --- /dev/null +++ b/code/onjava/Enums.java @@ -0,0 +1,17 @@ +// onjava/Enums.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.util.*; + +public class Enums { + private static Random rand = new Random(47); + public static + > T random(Class ec) { + return random(ec.getEnumConstants()); + } + public static T random(T[] values) { + return values[rand.nextInt(values.length)]; + } +} diff --git a/code/onjava/FillMap.java b/code/onjava/FillMap.java new file mode 100644 index 00000000..eadc5495 --- /dev/null +++ b/code/onjava/FillMap.java @@ -0,0 +1,38 @@ +// onjava/FillMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public class FillMap { + public static Map + basic(Supplier> pairGen, int size) { + return Stream.generate(pairGen) + .limit(size) + .collect(Collectors + .toMap(Pair::key, Pair::value)); + } + public static Map + basic(Supplier keyGen, + Supplier valueGen, int size) { + return Stream.generate( + () -> Pair.make(keyGen.get(), valueGen.get())) + .limit(size) + .collect(Collectors + .toMap(Pair::key, Pair::value)); + } + public static > + M create(Supplier keyGen, + Supplier valueGen, + Supplier mapSupplier, int size) { + return Stream.generate( () -> + Pair.make(keyGen.get(), valueGen.get())) + .limit(size) + .collect(Collectors + .toMap(Pair::key, Pair::value, + (k, v) -> k, mapSupplier)); + } +} diff --git a/code/onjava/HTMLColors.java b/code/onjava/HTMLColors.java new file mode 100644 index 00000000..bdc3458f --- /dev/null +++ b/code/onjava/HTMLColors.java @@ -0,0 +1,236 @@ +// onjava/HTMLColors.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Sample data for collection examples +package onjava; +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; + +public class HTMLColors { + public static final Object[][] ARRAY = { + { 0xF0F8FF, "AliceBlue" }, + { 0xFAEBD7, "AntiqueWhite" }, + { 0x7FFFD4, "Aquamarine" }, + { 0xF0FFFF, "Azure" }, + { 0xF5F5DC, "Beige" }, + { 0xFFE4C4, "Bisque" }, + { 0x000000, "Black" }, + { 0xFFEBCD, "BlanchedAlmond" }, + { 0x0000FF, "Blue" }, + { 0x8A2BE2, "BlueViolet" }, + { 0xA52A2A, "Brown" }, + { 0xDEB887, "BurlyWood" }, + { 0x5F9EA0, "CadetBlue" }, + { 0x7FFF00, "Chartreuse" }, + { 0xD2691E, "Chocolate" }, + { 0xFF7F50, "Coral" }, + { 0x6495ED, "CornflowerBlue" }, + { 0xFFF8DC, "Cornsilk" }, + { 0xDC143C, "Crimson" }, + { 0x00FFFF, "Cyan" }, + { 0x00008B, "DarkBlue" }, + { 0x008B8B, "DarkCyan" }, + { 0xB8860B, "DarkGoldenRod" }, + { 0xA9A9A9, "DarkGray" }, + { 0x006400, "DarkGreen" }, + { 0xBDB76B, "DarkKhaki" }, + { 0x8B008B, "DarkMagenta" }, + { 0x556B2F, "DarkOliveGreen" }, + { 0xFF8C00, "DarkOrange" }, + { 0x9932CC, "DarkOrchid" }, + { 0x8B0000, "DarkRed" }, + { 0xE9967A, "DarkSalmon" }, + { 0x8FBC8F, "DarkSeaGreen" }, + { 0x483D8B, "DarkSlateBlue" }, + { 0x2F4F4F, "DarkSlateGray" }, + { 0x00CED1, "DarkTurquoise" }, + { 0x9400D3, "DarkViolet" }, + { 0xFF1493, "DeepPink" }, + { 0x00BFFF, "DeepSkyBlue" }, + { 0x696969, "DimGray" }, + { 0x1E90FF, "DodgerBlue" }, + { 0xB22222, "FireBrick" }, + { 0xFFFAF0, "FloralWhite" }, + { 0x228B22, "ForestGreen" }, + { 0xDCDCDC, "Gainsboro" }, + { 0xF8F8FF, "GhostWhite" }, + { 0xFFD700, "Gold" }, + { 0xDAA520, "GoldenRod" }, + { 0x808080, "Gray" }, + { 0x008000, "Green" }, + { 0xADFF2F, "GreenYellow" }, + { 0xF0FFF0, "HoneyDew" }, + { 0xFF69B4, "HotPink" }, + { 0xCD5C5C, "IndianRed" }, + { 0x4B0082, "Indigo" }, + { 0xFFFFF0, "Ivory" }, + { 0xF0E68C, "Khaki" }, + { 0xE6E6FA, "Lavender" }, + { 0xFFF0F5, "LavenderBlush" }, + { 0x7CFC00, "LawnGreen" }, + { 0xFFFACD, "LemonChiffon" }, + { 0xADD8E6, "LightBlue" }, + { 0xF08080, "LightCoral" }, + { 0xE0FFFF, "LightCyan" }, + { 0xFAFAD2, "LightGoldenRodYellow" }, + { 0xD3D3D3, "LightGray" }, + { 0x90EE90, "LightGreen" }, + { 0xFFB6C1, "LightPink" }, + { 0xFFA07A, "LightSalmon" }, + { 0x20B2AA, "LightSeaGreen" }, + { 0x87CEFA, "LightSkyBlue" }, + { 0x778899, "LightSlateGray" }, + { 0xB0C4DE, "LightSteelBlue" }, + { 0xFFFFE0, "LightYellow" }, + { 0x00FF00, "Lime" }, + { 0x32CD32, "LimeGreen" }, + { 0xFAF0E6, "Linen" }, + { 0xFF00FF, "Magenta" }, + { 0x800000, "Maroon" }, + { 0x66CDAA, "MediumAquaMarine" }, + { 0x0000CD, "MediumBlue" }, + { 0xBA55D3, "MediumOrchid" }, + { 0x9370DB, "MediumPurple" }, + { 0x3CB371, "MediumSeaGreen" }, + { 0x7B68EE, "MediumSlateBlue" }, + { 0x00FA9A, "MediumSpringGreen" }, + { 0x48D1CC, "MediumTurquoise" }, + { 0xC71585, "MediumVioletRed" }, + { 0x191970, "MidnightBlue" }, + { 0xF5FFFA, "MintCream" }, + { 0xFFE4E1, "MistyRose" }, + { 0xFFE4B5, "Moccasin" }, + { 0xFFDEAD, "NavajoWhite" }, + { 0x000080, "Navy" }, + { 0xFDF5E6, "OldLace" }, + { 0x808000, "Olive" }, + { 0x6B8E23, "OliveDrab" }, + { 0xFFA500, "Orange" }, + { 0xFF4500, "OrangeRed" }, + { 0xDA70D6, "Orchid" }, + { 0xEEE8AA, "PaleGoldenRod" }, + { 0x98FB98, "PaleGreen" }, + { 0xAFEEEE, "PaleTurquoise" }, + { 0xDB7093, "PaleVioletRed" }, + { 0xFFEFD5, "PapayaWhip" }, + { 0xFFDAB9, "PeachPuff" }, + { 0xCD853F, "Peru" }, + { 0xFFC0CB, "Pink" }, + { 0xDDA0DD, "Plum" }, + { 0xB0E0E6, "PowderBlue" }, + { 0x800080, "Purple" }, + { 0xFF0000, "Red" }, + { 0xBC8F8F, "RosyBrown" }, + { 0x4169E1, "RoyalBlue" }, + { 0x8B4513, "SaddleBrown" }, + { 0xFA8072, "Salmon" }, + { 0xF4A460, "SandyBrown" }, + { 0x2E8B57, "SeaGreen" }, + { 0xFFF5EE, "SeaShell" }, + { 0xA0522D, "Sienna" }, + { 0xC0C0C0, "Silver" }, + { 0x87CEEB, "SkyBlue" }, + { 0x6A5ACD, "SlateBlue" }, + { 0x708090, "SlateGray" }, + { 0xFFFAFA, "Snow" }, + { 0x00FF7F, "SpringGreen" }, + { 0x4682B4, "SteelBlue" }, + { 0xD2B48C, "Tan" }, + { 0x008080, "Teal" }, + { 0xD8BFD8, "Thistle" }, + { 0xFF6347, "Tomato" }, + { 0x40E0D0, "Turquoise" }, + { 0xEE82EE, "Violet" }, + { 0xF5DEB3, "Wheat" }, + { 0xFFFFFF, "White" }, + { 0xF5F5F5, "WhiteSmoke" }, + { 0xFFFF00, "Yellow" }, + { 0x9ACD32, "YellowGreen" }, + }; + public static final Map MAP = + Arrays.stream(ARRAY) + .collect(Collectors.toMap( + element -> (Integer)element[0], + element -> (String)element[1], + (v1, v2) -> { // Merge function + throw new IllegalStateException(); + }, + LinkedHashMap::new + )); + // Inversion only works if values are unique: + public static Map + invert(Map map) { + return map.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getValue, + Map.Entry::getKey, + (v1, v2) -> { + throw new IllegalStateException(); + }, + LinkedHashMap::new + )); + } + public static final Map + INVMAP = invert(MAP); + // Look up RGB value given a name: + public static Integer rgb(String colorName) { + return INVMAP.get(colorName); + } + public static final List LIST = + Arrays.stream(ARRAY) + .map(item -> (String)item[1]) + .collect(Collectors.toList()); + public static final List RGBLIST = + Arrays.stream(ARRAY) + .map(item -> (Integer)item[0]) + .collect(Collectors.toList()); + public static + void show(Map.Entry e) { + System.out.format( + "0x%06X: %s%n", e.getKey(), e.getValue()); + } + public static void + show(Map m, int count) { + m.entrySet().stream() + .limit(count) + .forEach(e -> show(e)); + } + public static void show(Map m) { + show(m, m.size()); + } + public static + void show(Collection lst, int count) { + lst.stream() + .limit(count) + .forEach(System.out::println); + } + public static void show(Collection lst) { + show(lst, lst.size()); + } + public static + void showrgb(Collection lst, int count) { + lst.stream() + .limit(count) + .forEach(n -> System.out.format("0x%06X%n", n)); + } + public static void showrgb(Collection lst) { + showrgb(lst, lst.size()); + } + public static + void showInv(Map m, int count) { + m.entrySet().stream() + .limit(count) + .forEach(e -> + System.out.format( + "%-20s 0x%06X%n", e.getKey(), e.getValue())); + } + public static void showInv(Map m) { + showInv(m, m.size()); + } + public static void border() { + System.out.println( + "******************************"); + } +} diff --git a/code/onjava/MouseClick.java b/code/onjava/MouseClick.java new file mode 100644 index 00000000..70d982f7 --- /dev/null +++ b/code/onjava/MouseClick.java @@ -0,0 +1,19 @@ +// onjava/MouseClick.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Helper interface to allow lambda expressions +package onjava; +import java.awt.event.*; + +// Default everything except mouseClicked(): +public interface MouseClick extends MouseListener { + @Override + default void mouseEntered(MouseEvent e) {} + @Override + default void mouseExited(MouseEvent e) {} + @Override + default void mousePressed(MouseEvent e) {} + @Override + default void mouseReleased(MouseEvent e) {} +} diff --git a/code/onjava/Nap.java b/code/onjava/Nap.java new file mode 100644 index 00000000..2b89745b --- /dev/null +++ b/code/onjava/Nap.java @@ -0,0 +1,20 @@ +// onjava/Nap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.util.concurrent.*; + +public class Nap { + public Nap(double t) { // Seconds + try { + TimeUnit.MILLISECONDS.sleep((int)(1000 * t)); + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + } + public Nap(double t, String msg) { + this(t); + System.out.println(msg); + } +} diff --git a/code/onjava/Null.java b/code/onjava/Null.java new file mode 100644 index 00000000..f3bb70d6 --- /dev/null +++ b/code/onjava/Null.java @@ -0,0 +1,6 @@ +// onjava/Null.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +public interface Null {} diff --git a/code/onjava/OSExecute.java b/code/onjava/OSExecute.java new file mode 100644 index 00000000..25ac7f0c --- /dev/null +++ b/code/onjava/OSExecute.java @@ -0,0 +1,37 @@ +// onjava/OSExecute.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Run an operating system command +// and send the output to the console +package onjava; +import java.io.*; + +public class OSExecute { + public static void command(String command) { + boolean err = false; + try { + Process process = new ProcessBuilder( + command.split(" ")).start(); + try( + BufferedReader results = new BufferedReader( + new InputStreamReader( + process.getInputStream())); + BufferedReader errors = new BufferedReader( + new InputStreamReader( + process.getErrorStream())) + ) { + results.lines() + .forEach(System.out::println); + err = errors.lines() + .peek(System.err::println) + .count() > 0; + } + } catch(IOException e) { + throw new RuntimeException(e); + } + if(err) + throw new OSExecuteException( + "Errors executing " + command); + } +} diff --git a/code/onjava/OSExecuteException.java b/code/onjava/OSExecuteException.java new file mode 100644 index 00000000..17d803e1 --- /dev/null +++ b/code/onjava/OSExecuteException.java @@ -0,0 +1,12 @@ +// onjava/OSExecuteException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; + +public class +OSExecuteException extends RuntimeException { + public OSExecuteException(String why) { + super(why); + } +} diff --git a/code/onjava/Operations.java b/code/onjava/Operations.java new file mode 100644 index 00000000..33b644c6 --- /dev/null +++ b/code/onjava/Operations.java @@ -0,0 +1,17 @@ +// onjava/Operations.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.util.*; + +public interface Operations { + void execute(); + static void runOps(Operations... ops) { + for(Operations op : ops) + op.execute(); + } + static void show(String msg) { + System.out.println(msg); + } +} diff --git a/code/onjava/Pair.java b/code/onjava/Pair.java new file mode 100644 index 00000000..784ef8ac --- /dev/null +++ b/code/onjava/Pair.java @@ -0,0 +1,19 @@ +// onjava/Pair.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; + +public class Pair { + public final K key; + public final V value; + public Pair(K k, V v) { + key = k; + value = v; + } + public K key() { return key; } + public V value() { return value; } + public static Pair make(K k, V v) { + return new Pair(k, v); + } +} diff --git a/code/onjava/ProcessFiles.java b/code/onjava/ProcessFiles.java new file mode 100644 index 00000000..edcea73a --- /dev/null +++ b/code/onjava/ProcessFiles.java @@ -0,0 +1,48 @@ +// onjava/ProcessFiles.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.io.*; +import java.nio.file.*; + +public class ProcessFiles { + public interface Strategy { + void process(File file); + } + private Strategy strategy; + private String ext; + public ProcessFiles(Strategy strategy, String ext) { + this.strategy = strategy; + this.ext = ext; + } + public void start(String[] args) { + try { + if(args.length == 0) + processDirectoryTree(new File(".")); + else + for(String arg : args) { + File fileArg = new File(arg); + if(fileArg.isDirectory()) + processDirectoryTree(fileArg); + else { + // Allow user to leave off extension: + if(!arg.endsWith("." + ext)) + arg += "." + ext; + strategy.process( + new File(arg).getCanonicalFile()); + } + } + } catch(IOException e) { + throw new RuntimeException(e); + } + } + public void + processDirectoryTree(File root) throws IOException { + PathMatcher matcher = FileSystems.getDefault() + .getPathMatcher("glob:**/*.{" + ext + "}"); + Files.walk(root.toPath()) + .filter(matcher::matches) + .forEach(p -> strategy.process(p.toFile())); + } +} diff --git a/code/onjava/Rand.java b/code/onjava/Rand.java new file mode 100644 index 00000000..d21c0e2b --- /dev/null +++ b/code/onjava/Rand.java @@ -0,0 +1,248 @@ +// onjava/Rand.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Generate random values of different types +package onjava; +import java.util.*; +import java.util.function.*; +import static onjava.ConvertTo.*; + +public interface Rand { + int MOD = 10_000; + class Boolean + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Boolean get() { + return r.nextBoolean(); + } + public java.lang.Boolean get(int n) { + return get(); + } + public java.lang.Boolean[] array(int sz) { + java.lang.Boolean[] result = + new java.lang.Boolean[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pboolean { + public boolean[] array(int sz) { + return primitive(new Boolean().array(sz)); + } + } + class Byte + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Byte get() { + return (byte)r.nextInt(MOD); + } + public java.lang.Byte get(int n) { + return get(); + } + public java.lang.Byte[] array(int sz) { + java.lang.Byte[] result = + new java.lang.Byte[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pbyte { + public byte[] array(int sz) { + return primitive(new Byte().array(sz)); + } + } + class Character + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Character get() { + return (char)r.nextInt('a', 'z' + 1); + } + public java.lang.Character get(int n) { + return get(); + } + public java.lang.Character[] array(int sz) { + java.lang.Character[] result = + new java.lang.Character[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pchar { + public char[] array(int sz) { + return primitive(new Character().array(sz)); + } + } + class Short + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Short get() { + return (short)r.nextInt(MOD); + } + public java.lang.Short get(int n) { + return get(); + } + public java.lang.Short[] array(int sz) { + java.lang.Short[] result = + new java.lang.Short[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pshort { + public short[] array(int sz) { + return primitive(new Short().array(sz)); + } + } + class Integer + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Integer get() { + return r.nextInt(MOD); + } + public java.lang.Integer get(int n) { + return get(); + } + public java.lang.Integer[] array(int sz) { + int[] primitive = new Pint().array(sz); + java.lang.Integer[] result = + new java.lang.Integer[sz]; + for(int i = 0; i < sz; i++) + result[i] = primitive[i]; + return result; + } + } + class Pint implements IntSupplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public int getAsInt() { + return r.nextInt(MOD); + } + public int get(int n) { return getAsInt(); } + public int[] array(int sz) { + return r.ints(sz, 0, MOD).toArray(); + } + } + class Long + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Long get() { + return r.nextLong(MOD); + } + public java.lang.Long get(int n) { + return get(); + } + public java.lang.Long[] array(int sz) { + long[] primitive = new Plong().array(sz); + java.lang.Long[] result = + new java.lang.Long[sz]; + for(int i = 0; i < sz; i++) + result[i] = primitive[i]; + return result; + } + } + class Plong implements LongSupplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public long getAsLong() { + return r.nextLong(MOD); + } + public long get(int n) { return getAsLong(); } + public long[] array(int sz) { + return r.longs(sz, 0, MOD).toArray(); + } + } + class Float + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Float get() { + return (float)trim(r.nextDouble()); + } + public java.lang.Float get(int n) { + return get(); + } + public java.lang.Float[] array(int sz) { + java.lang.Float[] result = + new java.lang.Float[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } + class Pfloat { + public float[] array(int sz) { + return primitive(new Float().array(sz)); + } + } + static double trim(double d) { + return + ((double)Math.round(d * 1000.0)) / 100.0; + } + class Double + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public java.lang.Double get() { + return trim(r.nextDouble()); + } + public java.lang.Double get(int n) { + return get(); + } + public java.lang.Double[] array(int sz) { + double[] primitive = + new Rand.Pdouble().array(sz); + java.lang.Double[] result = + new java.lang.Double[sz]; + for(int i = 0; i < sz; i++) + result[i] = primitive[i]; + return result; + } + } + class Pdouble implements DoubleSupplier { + SplittableRandom r = new SplittableRandom(47); + @Override + public double getAsDouble() { + return trim(r.nextDouble()); + } + public double get(int n) { + return getAsDouble(); + } + public double[] array(int sz) { + double[] result = r.doubles(sz).toArray(); + Arrays.setAll(result, + n -> result[n] = trim(result[n])); + return result; + } + } + class String + implements Supplier { + SplittableRandom r = new SplittableRandom(47); + private int strlen = 7; // Default length + public String() {} + public String(int strLength) { + strlen = strLength; + } + @Override + public java.lang.String get() { + return r.ints(strlen, 'a', 'z' + 1) + .collect(StringBuilder::new, + StringBuilder::appendCodePoint, + StringBuilder::append).toString(); + } + public java.lang.String get(int n) { + return get(); + } + public java.lang.String[] array(int sz) { + java.lang.String[] result = + new java.lang.String[sz]; + Arrays.setAll(result, n -> get()); + return result; + } + } +} diff --git a/code/onjava/Range.java b/code/onjava/Range.java new file mode 100644 index 00000000..e075c9ba --- /dev/null +++ b/code/onjava/Range.java @@ -0,0 +1,34 @@ +// onjava/Range.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Array creation methods that can be used without +// qualifiers, using static imports: +package onjava; + +public class Range { + // Produce a sequence [0..n) + public static int[] range(int n) { + int[] result = new int[n]; + for(int i = 0; i < n; i++) + result[i] = i; + return result; + } + // Produce a sequence [start..end) + public static int[] range(int start, int end) { + int sz = end - start; + int[] result = new int[sz]; + for(int i = 0; i < sz; i++) + result[i] = start + i; + return result; + } + // Produce sequence [start..end) incrementing by step + public static + int[] range(int start, int end, int step) { + int sz = (end - start)/step; + int[] result = new int[sz]; + for(int i = 0; i < sz; i++) + result[i] = start + (i * step); + return result; + } +} diff --git a/code/onjava/Repeat.java b/code/onjava/Repeat.java new file mode 100644 index 00000000..7ab61fac --- /dev/null +++ b/code/onjava/Repeat.java @@ -0,0 +1,12 @@ +// onjava/Repeat.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import static java.util.stream.IntStream.*; + +public class Repeat { + public static void repeat(int n, Runnable action) { + range(0, n).forEach(i -> action.run()); + } +} diff --git a/code/onjava/RmDir.java b/code/onjava/RmDir.java new file mode 100644 index 00000000..be7ea494 --- /dev/null +++ b/code/onjava/RmDir.java @@ -0,0 +1,31 @@ +// onjava/RmDir.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.io.IOException; + +public class RmDir { + public static void rmdir(Path dir) + throws IOException { + Files.walkFileTree(dir, + new SimpleFileVisitor() { + @Override + public FileVisitResult + visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult + postVisitDirectory(Path dir, IOException exc) + throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } +} diff --git a/code/onjava/Sets.java b/code/onjava/Sets.java new file mode 100644 index 00000000..62258f15 --- /dev/null +++ b/code/onjava/Sets.java @@ -0,0 +1,32 @@ +// onjava/Sets.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import java.util.*; + +public class Sets { + public static Set union(Set a, Set b) { + Set result = new HashSet<>(a); + result.addAll(b); + return result; + } + public static + Set intersection(Set a, Set b) { + Set result = new HashSet<>(a); + result.retainAll(b); + return result; + } + // Subtract subset from superset: + public static Set + difference(Set superset, Set subset) { + Set result = new HashSet<>(superset); + result.removeAll(subset); + return result; + } + // Reflexive--everything not in the intersection: + public static + Set complement(Set a, Set b) { + return difference(union(a, b), intersection(a, b)); + } +} diff --git a/code/onjava/Stack.java b/code/onjava/Stack.java new file mode 100644 index 00000000..a5108176 --- /dev/null +++ b/code/onjava/Stack.java @@ -0,0 +1,20 @@ +// onjava/Stack.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A Stack class built with an ArrayDeque +package onjava; +import java.util.Deque; +import java.util.ArrayDeque; + +public class Stack { + private Deque storage = new ArrayDeque<>(); + public void push(T v) { storage.push(v); } + public T peek() { return storage.peek(); } + public T pop() { return storage.pop(); } + public boolean isEmpty() { return storage.isEmpty(); } + @Override + public String toString() { + return storage.toString(); + } +} diff --git a/code/onjava/Suppliers.java b/code/onjava/Suppliers.java new file mode 100644 index 00000000..226a70cb --- /dev/null +++ b/code/onjava/Suppliers.java @@ -0,0 +1,36 @@ +// onjava/Suppliers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A utility to use with Suppliers +package onjava; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public class Suppliers { + // Create a collection and fill it: + public static > C + create(Supplier factory, Supplier gen, int n) { + return Stream.generate(gen) + .limit(n) + .collect(factory, C::add, C::addAll); + } + // Fill an existing collection: + public static > + C fill(C coll, Supplier gen, int n) { + Stream.generate(gen) + .limit(n) + .forEach(coll::add); + return coll; + } + // Use an unbound method reference to + // produce a more general method: + public static H fill(H holder, + BiConsumer adder, Supplier
gen, int n) { + Stream.generate(gen) + .limit(n) + .forEach(a -> adder.accept(holder, a)); + return holder; + } +} diff --git a/code/onjava/TimedAbort.java b/code/onjava/TimedAbort.java new file mode 100644 index 00000000..3715cf2e --- /dev/null +++ b/code/onjava/TimedAbort.java @@ -0,0 +1,30 @@ +// onjava/TimedAbort.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Terminate a program after t seconds +package onjava; +import java.util.concurrent.*; + +public class TimedAbort { + private volatile boolean restart = true; + public TimedAbort(double t, String msg) { + CompletableFuture.runAsync(() -> { + try { + while(restart) { + restart = false; + TimeUnit.MILLISECONDS + .sleep((int)(1000 * t)); + } + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + System.out.println(msg); + System.exit(0); + }); + } + public TimedAbort(double t) { + this(t, "TimedAbort " + t); + } + public void restart() { restart = true; } +} diff --git a/code/onjava/Timer.java b/code/onjava/Timer.java new file mode 100644 index 00000000..a695f79f --- /dev/null +++ b/code/onjava/Timer.java @@ -0,0 +1,19 @@ +// onjava/Timer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import static java.util.concurrent.TimeUnit.*; + +public class Timer { + private long start = System.nanoTime(); + public long duration() { + return NANOSECONDS.toMillis( + System.nanoTime() - start); + } + public static long duration(Runnable test) { + Timer timer = new Timer(); + test.run(); + return timer.duration(); + } +} diff --git a/code/onjava/Tuple.java b/code/onjava/Tuple.java new file mode 100644 index 00000000..73cfaa3c --- /dev/null +++ b/code/onjava/Tuple.java @@ -0,0 +1,24 @@ +// onjava/Tuple.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Tuple library using type argument inference +package onjava; + +public class Tuple { + public static Tuple2 tuple(A a, B b) { + return new Tuple2<>(a, b); + } + public static Tuple3 + tuple(A a, B b, C c) { + return new Tuple3<>(a, b, c); + } + public static Tuple4 + tuple(A a, B b, C c, D d) { + return new Tuple4<>(a, b, c, d); + } + public static + Tuple5 tuple(A a, B b, C c, D d, E e) { + return new Tuple5<>(a, b, c, d, e); + } +} diff --git a/code/onjava/Tuple2.java b/code/onjava/Tuple2.java new file mode 100644 index 00000000..7ca8d199 --- /dev/null +++ b/code/onjava/Tuple2.java @@ -0,0 +1,16 @@ +// onjava/Tuple2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; + +public class Tuple2 { + public final A a1; + public final B a2; + public Tuple2(A a, B b) { a1 = a; a2 = b; } + public String rep() { return a1 + ", " + a2; } + @Override + public String toString() { + return "(" + rep() + ")"; + } +} diff --git a/code/onjava/Tuple3.java b/code/onjava/Tuple3.java new file mode 100644 index 00000000..26780642 --- /dev/null +++ b/code/onjava/Tuple3.java @@ -0,0 +1,17 @@ +// onjava/Tuple3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; + +public class Tuple3 extends Tuple2 { + public final C a3; + public Tuple3(A a, B b, C c) { + super(a, b); + a3 = c; + } + @Override + public String rep() { + return super.rep() + ", " + a3; + } +} diff --git a/code/onjava/Tuple4.java b/code/onjava/Tuple4.java new file mode 100644 index 00000000..5ab51dc9 --- /dev/null +++ b/code/onjava/Tuple4.java @@ -0,0 +1,18 @@ +// onjava/Tuple4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; + +public class Tuple4 + extends Tuple3 { + public final D a4; + public Tuple4(A a, B b, C c, D d) { + super(a, b, c); + a4 = d; + } + @Override + public String rep() { + return super.rep() + ", " + a4; + } +} diff --git a/code/onjava/Tuple5.java b/code/onjava/Tuple5.java new file mode 100644 index 00000000..1df88bfd --- /dev/null +++ b/code/onjava/Tuple5.java @@ -0,0 +1,18 @@ +// onjava/Tuple5.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; + +public class Tuple5 +extends Tuple4 { + public final E a5; + public Tuple5(A a, B b, C c, D d, E e) { + super(a, b, c, d); + a5 = e; + } + @Override + public String rep() { + return super.rep() + ", " + a5; + } +} diff --git a/code/onjava/TypeCounter.java b/code/onjava/TypeCounter.java new file mode 100644 index 00000000..d8b262b7 --- /dev/null +++ b/code/onjava/TypeCounter.java @@ -0,0 +1,41 @@ +// onjava/TypeCounter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Counts instances of a type family +package onjava; +import java.util.*; +import java.util.stream.*; + +public class +TypeCounter extends HashMap, Integer> { + private Class baseType; + public TypeCounter(Class baseType) { + this.baseType = baseType; + } + public void count(Object obj) { + Class type = obj.getClass(); + if(!baseType.isAssignableFrom(type)) + throw new RuntimeException( + obj + " incorrect type: " + type + + ", should be type or subtype of " + baseType); + countClass(type); + } + private void countClass(Class type) { + Integer quantity = get(type); + put(type, quantity == null ? 1 : quantity + 1); + Class superClass = type.getSuperclass(); + if(superClass != null && + baseType.isAssignableFrom(superClass)) + countClass(superClass); + } + @Override + public String toString() { + String result = entrySet().stream() + .map(pair -> String.format("%s=%s", + pair.getKey().getSimpleName(), + pair.getValue())) + .collect(Collectors.joining(", ")); + return "{" + result + "}"; + } +} diff --git a/code/onjava/atunit/AtUnit.java b/code/onjava/atunit/AtUnit.java new file mode 100644 index 00000000..b1688cbd --- /dev/null +++ b/code/onjava/atunit/AtUnit.java @@ -0,0 +1,177 @@ +// onjava/atunit/AtUnit.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An annotation-based unit-test framework +// {java onjava.atunit.AtUnit} +package onjava.atunit; +import java.lang.reflect.*; +import java.io.*; +import java.util.*; +import java.nio.file.*; +import java.util.stream.*; +import onjava.*; + +public class AtUnit implements ProcessFiles.Strategy { + static Class testClass; + static List failedTests= new ArrayList<>(); + static long testsRun = 0; + static long failures = 0; + public static void + main(String[] args) throws Exception { + ClassLoader.getSystemClassLoader() + .setDefaultAssertionStatus(true); // Enable assert + new ProcessFiles(new AtUnit(), "class").start(args); + if(failures == 0) + System.out.println("OK (" + testsRun + " tests)"); + else { + System.out.println("(" + testsRun + " tests)"); + System.out.println( + "\n>>> " + failures + " FAILURE" + + (failures > 1 ? "S" : "") + " <<<"); + for(String failed : failedTests) + System.out.println(" " + failed); + } + } + @Override + public void process(File cFile) { + try { + String cName = ClassNameFinder.thisClass( + Files.readAllBytes(cFile.toPath())); + if(!cName.startsWith("public:")) + return; + cName = cName.split(":")[1]; + if(!cName.contains(".")) + return; // Ignore unpackaged classes + testClass = Class.forName(cName); + } catch(IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + TestMethods testMethods = new TestMethods(); + Method creator = null; + Method cleanup = null; + for(Method m : testClass.getDeclaredMethods()) { + testMethods.addIfTestMethod(m); + if(creator == null) + creator = checkForCreatorMethod(m); + if(cleanup == null) + cleanup = checkForCleanupMethod(m); + } + if(testMethods.size() > 0) { + if(creator == null) + try { + if(!Modifier.isPublic(testClass + .getDeclaredConstructor() + .getModifiers())) { + System.out.println("Error: " + testClass + + " no-arg constructor must be public"); + System.exit(1); + } + } catch(NoSuchMethodException e) { + // Synthesized no-arg constructor; OK + } + System.out.println(testClass.getName()); + } + for(Method m : testMethods) { + System.out.print(" . " + m.getName() + " "); + try { + Object testObject = createTestObject(creator); + boolean success = false; + try { + if(m.getReturnType().equals(boolean.class)) + success = (Boolean)m.invoke(testObject); + else { + m.invoke(testObject); + success = true; // If no assert fails + } + } catch(InvocationTargetException e) { + // Actual exception is inside e: + System.out.println(e.getCause()); + } + System.out.println(success ? "" : "(failed)"); + testsRun++; + if(!success) { + failures++; + failedTests.add(testClass.getName() + + ": " + m.getName()); + } + if(cleanup != null) + cleanup.invoke(testObject, testObject); + } catch(IllegalAccessException | + IllegalArgumentException | + InvocationTargetException e) { + throw new RuntimeException(e); + } + } + } + public static + class TestMethods extends ArrayList { + void addIfTestMethod(Method m) { + if(m.getAnnotation(Test.class) == null) + return; + if(!(m.getReturnType().equals(boolean.class) || + m.getReturnType().equals(void.class))) + throw new RuntimeException("@Test method" + + " must return boolean or void"); + m.setAccessible(true); // If it's private, etc. + add(m); + } + } + private static + Method checkForCreatorMethod(Method m) { + if(m.getAnnotation(TestObjectCreate.class) == null) + return null; + if(!m.getReturnType().equals(testClass)) + throw new RuntimeException("@TestObjectCreate " + + "must return instance of Class to be tested"); + if((m.getModifiers() & + java.lang.reflect.Modifier.STATIC) < 1) + throw new RuntimeException("@TestObjectCreate " + + "must be static."); + m.setAccessible(true); + return m; + } + private static + Method checkForCleanupMethod(Method m) { + if(m.getAnnotation(TestObjectCleanup.class) == null) + return null; + if(!m.getReturnType().equals(void.class)) + throw new RuntimeException("@TestObjectCleanup " + + "must return void"); + if((m.getModifiers() & + java.lang.reflect.Modifier.STATIC) < 1) + throw new RuntimeException("@TestObjectCleanup " + + "must be static."); + if(m.getParameterTypes().length == 0 || + m.getParameterTypes()[0] != testClass) + throw new RuntimeException("@TestObjectCleanup " + + "must take an argument of the tested type."); + m.setAccessible(true); + return m; + } + private static Object + createTestObject(Method creator) { + if(creator != null) { + try { + return creator.invoke(testClass); + } catch(IllegalAccessException | + IllegalArgumentException | + InvocationTargetException e) { + throw new RuntimeException("Couldn't run " + + "@TestObject (creator) method."); + } + } else { // Use the no-arg constructor: + try { + return testClass + .getConstructor().newInstance(); + } catch(InstantiationException | + NoSuchMethodException | + InvocationTargetException | + IllegalAccessException e) { + throw new RuntimeException( + "Couldn't create a test object. " + + "Try using a @TestObject method."); + } + } + } +} diff --git a/code/onjava/atunit/ClassNameFinder.java b/code/onjava/atunit/ClassNameFinder.java new file mode 100644 index 00000000..3fef7faf --- /dev/null +++ b/code/onjava/atunit/ClassNameFinder.java @@ -0,0 +1,180 @@ +// onjava/atunit/ClassNameFinder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.atunit.ClassNameFinder} +package onjava.atunit; +import java.io.*; +import java.nio.file.*; +import java.util.*; +import onjava.*; + +public class ClassNameFinder { + public static String thisClass(byte[] classBytes) { + Map offsetTable = new HashMap<>(); + Map classNameTable = + new HashMap<>(); + try { + DataInputStream data = new DataInputStream( + new ByteArrayInputStream(classBytes)); + int magic = data.readInt(); // 0xcafebabe + int minorVersion = data.readShort(); + int majorVersion = data.readShort(); + int constantPoolCount = data.readShort(); + int[] constantPool = new int[constantPoolCount]; + for(int i = 1; i < constantPoolCount; i++) { + int tag = data.read(); + // int tableSize; + switch(tag) { + case 1: // UTF + int length = data.readShort(); + char[] bytes = new char[length]; + for(int k = 0; k < bytes.length; k++) + bytes[k] = (char)data.read(); + String className = new String(bytes); + classNameTable.put(i, className); + break; + case 5: // LONG + case 6: // DOUBLE + data.readLong(); // discard 8 bytes + i++; // Special skip necessary + break; + case 7: // CLASS + int offset = data.readShort(); + offsetTable.put(i, offset); + break; + case 8: // STRING + data.readShort(); // discard 2 bytes + break; + case 3: // INTEGER + case 4: // FLOAT + case 9: // FIELD_REF + case 10: // METHOD_REF + case 11: // INTERFACE_METHOD_REF + case 12: // NAME_AND_TYPE + case 18: // Invoke Dynamic + data.readInt(); // discard 4 bytes + break; + case 15: // Method Handle + data.readByte(); + data.readShort(); + break; + case 16: // Method Type + data.readShort(); + break; + default: + throw + new RuntimeException("Bad tag " + tag); + } + } + short accessFlags = data.readShort(); + String access = (accessFlags & 0x0001) == 0 ? + "nonpublic:" : "public:"; + int thisClass = data.readShort(); + int superClass = data.readShort(); + return access + classNameTable.get( + offsetTable.get(thisClass)).replace('/', '.'); + } catch(IOException | RuntimeException e) { + throw new RuntimeException(e); + } + } + // Demonstration: + public static void + main(String[] args) throws Exception { + PathMatcher matcher = FileSystems.getDefault() + .getPathMatcher("glob:**/*.class"); + // Walk the entire tree: + Files.walk(Paths.get(".")) + .filter(matcher::matches) + .map(p -> { + try { + return thisClass(Files.readAllBytes(p)); + } catch(Exception e) { + throw new RuntimeException(e); + } + }) + .filter(s -> s.startsWith("public:")) + // .filter(s -> s.indexOf('$') >= 0) + .map(s -> s.split(":")[1]) + .filter(s -> !s.startsWith("enums.")) + .filter(s -> s.contains(".")) + .forEach(System.out::println); + } +} +/* Output: +onjava.ArrayShow +onjava.atunit.AtUnit$TestMethods +onjava.atunit.AtUnit +onjava.atunit.ClassNameFinder +onjava.atunit.Test +onjava.atunit.TestObjectCleanup +onjava.atunit.TestObjectCreate +onjava.atunit.TestProperty +onjava.BasicSupplier +onjava.CollectionMethodDifferences +onjava.ConvertTo +onjava.Count$Boolean +onjava.Count$Byte +onjava.Count$Character +onjava.Count$Double +onjava.Count$Float +onjava.Count$Integer +onjava.Count$Long +onjava.Count$Pboolean +onjava.Count$Pbyte +onjava.Count$Pchar +onjava.Count$Pdouble +onjava.Count$Pfloat +onjava.Count$Pint +onjava.Count$Plong +onjava.Count$Pshort +onjava.Count$Short +onjava.Count +onjava.CountingIntegerList +onjava.CountMap +onjava.Countries +onjava.Enums +onjava.FillMap +onjava.HTMLColors +onjava.MouseClick +onjava.Nap +onjava.Null +onjava.Operations +onjava.OSExecute +onjava.OSExecuteException +onjava.Pair +onjava.ProcessFiles$Strategy +onjava.ProcessFiles +onjava.Rand$Boolean +onjava.Rand$Byte +onjava.Rand$Character +onjava.Rand$Double +onjava.Rand$Float +onjava.Rand$Integer +onjava.Rand$Long +onjava.Rand$Pboolean +onjava.Rand$Pbyte +onjava.Rand$Pchar +onjava.Rand$Pdouble +onjava.Rand$Pfloat +onjava.Rand$Pint +onjava.Rand$Plong +onjava.Rand$Pshort +onjava.Rand$Short +onjava.Rand$String +onjava.Rand +onjava.Range +onjava.Repeat +onjava.RmDir +onjava.Sets +onjava.Stack +onjava.Suppliers +onjava.TimedAbort +onjava.Timer +onjava.Tuple +onjava.Tuple2 +onjava.Tuple3 +onjava.Tuple4 +onjava.Tuple5 +onjava.TypeCounter +*/ diff --git a/code/onjava/atunit/Test.java b/code/onjava/atunit/Test.java new file mode 100644 index 00000000..314dce9b --- /dev/null +++ b/code/onjava/atunit/Test.java @@ -0,0 +1,11 @@ +// onjava/atunit/Test.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The @Test tag +package onjava.atunit; +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Test {} diff --git a/code/onjava/atunit/TestObjectCleanup.java b/code/onjava/atunit/TestObjectCleanup.java new file mode 100644 index 00000000..52231177 --- /dev/null +++ b/code/onjava/atunit/TestObjectCleanup.java @@ -0,0 +1,11 @@ +// onjava/atunit/TestObjectCleanup.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The @Unit @TestObjectCleanup tag +package onjava.atunit; +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface TestObjectCleanup {} diff --git a/code/onjava/atunit/TestObjectCreate.java b/code/onjava/atunit/TestObjectCreate.java new file mode 100644 index 00000000..f8b43a09 --- /dev/null +++ b/code/onjava/atunit/TestObjectCreate.java @@ -0,0 +1,11 @@ +// onjava/atunit/TestObjectCreate.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The @Unit @TestObjectCreate tag +package onjava.atunit; +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface TestObjectCreate {} diff --git a/code/onjava/atunit/TestProperty.java b/code/onjava/atunit/TestProperty.java new file mode 100644 index 00000000..4e09cf95 --- /dev/null +++ b/code/onjava/atunit/TestProperty.java @@ -0,0 +1,12 @@ +// onjava/atunit/TestProperty.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The @Unit @TestProperty tag +package onjava.atunit; +import java.lang.annotation.*; + +// Both fields and methods can be tagged as properties: +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface TestProperty {} diff --git a/code/operators/AllOps.java b/code/operators/AllOps.java new file mode 100644 index 00000000..bb94e870 --- /dev/null +++ b/code/operators/AllOps.java @@ -0,0 +1,411 @@ +// operators/AllOps.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Tests all operators on all primitive data types +// to show which ones are accepted by the Java compiler + +public class AllOps { + // To accept the results of a boolean test: + void f(boolean b) {} + void boolTest(boolean x, boolean y) { + // Arithmetic operators: + //- x = x * y; + //- x = x / y; + //- x = x % y; + //- x = x + y; + //- x = x - y; + //- x++; + //- x--; + //- x = +y; + //- x = -y; + // Relational and logical: + //- f(x > y); + //- f(x >= y); + //- f(x < y); + //- f(x <= y); + f(x == y); + f(x != y); + f(!y); + x = x && y; + x = x || y; + // Bitwise operators: + //- x = ~y; + x = x & y; + x = x | y; + x = x ^ y; + //- x = x << 1; + //- x = x >> 1; + //- x = x >>> 1; + // Compound assignment: + //- x += y; + //- x -= y; + //- x *= y; + //- x /= y; + //- x %= y; + //- x <<= 1; + //- x >>= 1; + //- x >>>= 1; + x &= y; + x ^= y; + x |= y; + // Casting: + //- char c = (char)x; + //- byte b = (byte)x; + //- short s = (short)x; + //- int i = (int)x; + //- long l = (long)x; + //- float f = (float)x; + //- double d = (double)x; + } + void charTest(char x, char y) { + // Arithmetic operators: + x = (char)(x * y); + x = (char)(x / y); + x = (char)(x % y); + x = (char)(x + y); + x = (char)(x - y); + x++; + x--; + x = (char) + y; + x = (char) - y; + // Relational and logical: + f(x > y); + f(x >= y); + f(x < y); + f(x <= y); + f(x == y); + f(x != y); + //- f(!x); + //- f(x && y); + //- f(x || y); + // Bitwise operators: + x= (char)~y; + x = (char)(x & y); + x = (char)(x | y); + x = (char)(x ^ y); + x = (char)(x << 1); + x = (char)(x >> 1); + x = (char)(x >>> 1); + // Compound assignment: + x += y; + x -= y; + x *= y; + x /= y; + x %= y; + x <<= 1; + x >>= 1; + x >>>= 1; + x &= y; + x ^= y; + x |= y; + // Casting: + //- boolean bl = (boolean)x; + byte b = (byte)x; + short s = (short)x; + int i = (int)x; + long l = (long)x; + float f = (float)x; + double d = (double)x; + } + void byteTest(byte x, byte y) { + // Arithmetic operators: + x = (byte)(x* y); + x = (byte)(x / y); + x = (byte)(x % y); + x = (byte)(x + y); + x = (byte)(x - y); + x++; + x--; + x = (byte) + y; + x = (byte) - y; + // Relational and logical: + f(x > y); + f(x >= y); + f(x < y); + f(x <= y); + f(x == y); + f(x != y); + //- f(!x); + //- f(x && y); + //- f(x || y); + // Bitwise operators: + x = (byte)~y; + x = (byte)(x & y); + x = (byte)(x | y); + x = (byte)(x ^ y); + x = (byte)(x << 1); + x = (byte)(x >> 1); + x = (byte)(x >>> 1); + // Compound assignment: + x += y; + x -= y; + x *= y; + x /= y; + x %= y; + x <<= 1; + x >>= 1; + x >>>= 1; + x &= y; + x ^= y; + x |= y; + // Casting: + //- boolean bl = (boolean)x; + char c = (char)x; + short s = (short)x; + int i = (int)x; + long l = (long)x; + float f = (float)x; + double d = (double)x; + } + void shortTest(short x, short y) { + // Arithmetic operators: + x = (short)(x * y); + x = (short)(x / y); + x = (short)(x % y); + x = (short)(x + y); + x = (short)(x - y); + x++; + x--; + x = (short) + y; + x = (short) - y; + // Relational and logical: + f(x > y); + f(x >= y); + f(x < y); + f(x <= y); + f(x == y); + f(x != y); + //- f(!x); + //- f(x && y); + //- f(x || y); + // Bitwise operators: + x = (short) ~ y; + x = (short)(x & y); + x = (short)(x | y); + x = (short)(x ^ y); + x = (short)(x << 1); + x = (short)(x >> 1); + x = (short)(x >>> 1); + // Compound assignment: + x += y; + x -= y; + x *= y; + x /= y; + x %= y; + x <<= 1; + x >>= 1; + x >>>= 1; + x &= y; + x ^= y; + x |= y; + // Casting: + //- boolean bl = (boolean)x; + char c = (char)x; + byte b = (byte)x; + int i = (int)x; + long l = (long)x; + float f = (float)x; + double d = (double)x; + } + void intTest(int x, int y) { + // Arithmetic operators: + x = x * y; + x = x / y; + x = x % y; + x = x + y; + x = x - y; + x++; + x--; + x = +y; + x = -y; + // Relational and logical: + f(x > y); + f(x >= y); + f(x < y); + f(x <= y); + f(x == y); + f(x != y); + //- f(!x); + //- f(x && y); + //- f(x || y); + // Bitwise operators: + x = ~y; + x = x & y; + x = x | y; + x = x ^ y; + x = x << 1; + x = x >> 1; + x = x >>> 1; + // Compound assignment: + x += y; + x -= y; + x *= y; + x /= y; + x %= y; + x <<= 1; + x >>= 1; + x >>>= 1; + x &= y; + x ^= y; + x |= y; + // Casting: + //- boolean bl = (boolean)x; + char c = (char)x; + byte b = (byte)x; + short s = (short)x; + long l = (long)x; + float f = (float)x; + double d = (double)x; + } + void longTest(long x, long y) { + // Arithmetic operators: + x = x * y; + x = x / y; + x = x % y; + x = x + y; + x = x - y; + x++; + x--; + x = +y; + x = -y; + // Relational and logical: + f(x > y); + f(x >= y); + f(x < y); + f(x <= y); + f(x == y); + f(x != y); + //- f(!x); + //- f(x && y); + //- f(x || y); + // Bitwise operators: + x = ~y; + x = x & y; + x = x | y; + x = x ^ y; + x = x << 1; + x = x >> 1; + x = x >>> 1; + // Compound assignment: + x += y; + x -= y; + x *= y; + x /= y; + x %= y; + x <<= 1; + x >>= 1; + x >>>= 1; + x &= y; + x ^= y; + x |= y; + // Casting: + //- boolean bl = (boolean)x; + char c = (char)x; + byte b = (byte)x; + short s = (short)x; + int i = (int)x; + float f = (float)x; + double d = (double)x; + } + void floatTest(float x, float y) { + // Arithmetic operators: + x = x * y; + x = x / y; + x = x % y; + x = x + y; + x = x - y; + x++; + x--; + x = +y; + x = -y; + // Relational and logical: + f(x > y); + f(x >= y); + f(x < y); + f(x <= y); + f(x == y); + f(x != y); + //- f(!x); + //- f(x && y); + //- f(x || y); + // Bitwise operators: + //- x = ~y; + //- x = x & y; + //- x = x | y; + //- x = x ^ y; + //- x = x << 1; + //- x = x >> 1; + //- x = x >>> 1; + // Compound assignment: + x += y; + x -= y; + x *= y; + x /= y; + x %= y; + //- x <<= 1; + //- x >>= 1; + //- x >>>= 1; + //- x &= y; + //- x ^= y; + //- x |= y; + // Casting: + //- boolean bl = (boolean)x; + char c = (char)x; + byte b = (byte)x; + short s = (short)x; + int i = (int)x; + long l = (long)x; + double d = (double)x; + } + void doubleTest(double x, double y) { + // Arithmetic operators: + x = x * y; + x = x / y; + x = x % y; + x = x + y; + x = x - y; + x++; + x--; + x = +y; + x = -y; + // Relational and logical: + f(x > y); + f(x >= y); + f(x < y); + f(x <= y); + f(x == y); + f(x != y); + //- f(!x); + //- f(x && y); + //- f(x || y); + // Bitwise operators: + //- x = ~y; + //- x = x & y; + //- x = x | y; + //- x = x ^ y; + //- x = x << 1; + //- x = x >> 1; + //- x = x >>> 1; + // Compound assignment: + x += y; + x -= y; + x *= y; + x /= y; + x %= y; + //- x <<= 1; + //- x >>= 1; + //- x >>>= 1; + //- x &= y; + //- x ^= y; + //- x |= y; + // Casting: + //- boolean bl = (boolean)x; + char c = (char)x; + byte b = (byte)x; + short s = (short)x; + int i = (int)x; + long l = (long)x; + float f = (float)x; + } +} diff --git a/code/operators/Assignment.java b/code/operators/Assignment.java new file mode 100644 index 00000000..7a573a39 --- /dev/null +++ b/code/operators/Assignment.java @@ -0,0 +1,31 @@ +// operators/Assignment.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Assignment with objects is a bit tricky + +class Tank { + int level; +} + +public class Assignment { + public static void main(String[] args) { + Tank t1 = new Tank(); + Tank t2 = new Tank(); + t1.level = 9; + t2.level = 47; + System.out.println("1: t1.level: " + t1.level + + ", t2.level: " + t2.level); + t1 = t2; + System.out.println("2: t1.level: " + t1.level + + ", t2.level: " + t2.level); + t1.level = 27; + System.out.println("3: t1.level: " + t1.level + + ", t2.level: " + t2.level); + } +} +/* Output: +1: t1.level: 9, t2.level: 47 +2: t1.level: 47, t2.level: 47 +3: t1.level: 27, t2.level: 27 +*/ diff --git a/code/operators/AutoInc.java b/code/operators/AutoInc.java new file mode 100644 index 00000000..835875de --- /dev/null +++ b/code/operators/AutoInc.java @@ -0,0 +1,27 @@ +// operators/AutoInc.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates the ++ and -- operators + +public class AutoInc { + public static void main(String[] args) { + int i = 1; + System.out.println("i: " + i); + System.out.println("++i: " + ++i); // Pre-increment + System.out.println("i++: " + i++); // Post-increment + System.out.println("i: " + i); + System.out.println("--i: " + --i); // Pre-decrement + System.out.println("i--: " + i--); // Post-decrement + System.out.println("i: " + i); + } +} +/* Output: +i: 1 +++i: 2 +i++: 2 +i: 3 +--i: 2 +i--: 2 +i: 1 +*/ diff --git a/code/operators/BitManipulation.java b/code/operators/BitManipulation.java new file mode 100644 index 00000000..dc30c442 --- /dev/null +++ b/code/operators/BitManipulation.java @@ -0,0 +1,98 @@ +// operators/BitManipulation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using the bitwise operators +import java.util.*; + +public class BitManipulation { + public static void main(String[] args) { + Random rand = new Random(47); + int i = rand.nextInt(); + int j = rand.nextInt(); + printBinaryInt("-1", -1); + printBinaryInt("+1", +1); + int maxpos = 2147483647; + printBinaryInt("maxpos", maxpos); + int maxneg = -2147483648; + printBinaryInt("maxneg", maxneg); + printBinaryInt("i", i); + printBinaryInt("~i", ~i); + printBinaryInt("-i", -i); + printBinaryInt("j", j); + printBinaryInt("i & j", i & j); + printBinaryInt("i | j", i | j); + printBinaryInt("i ^ j", i ^ j); + printBinaryInt("i << 5", i << 5); + printBinaryInt("i >> 5", i >> 5); + printBinaryInt("(~i) >> 5", (~i) >> 5); + printBinaryInt("i >>> 5", i >>> 5); + printBinaryInt("(~i) >>> 5", (~i) >>> 5); + + long l = rand.nextLong(); + long m = rand.nextLong(); + printBinaryLong("-1L", -1L); + printBinaryLong("+1L", +1L); + long ll = 9223372036854775807L; + printBinaryLong("maxpos", ll); + long lln = -9223372036854775808L; + printBinaryLong("maxneg", lln); + printBinaryLong("l", l); + printBinaryLong("~l", ~l); + printBinaryLong("-l", -l); + printBinaryLong("m", m); + printBinaryLong("l & m", l & m); + printBinaryLong("l | m", l | m); + printBinaryLong("l ^ m", l ^ m); + printBinaryLong("l << 5", l << 5); + printBinaryLong("l >> 5", l >> 5); + printBinaryLong("(~l) >> 5", (~l) >> 5); + printBinaryLong("l >>> 5", l >>> 5); + printBinaryLong("(~l) >>> 5", (~l) >>> 5); + } + static void printBinaryInt(String s, int i) { + System.out.println( + s + ", int: " + i + ", binary:\n " + + Integer.toBinaryString(i)); + } + static void printBinaryLong(String s, long l) { + System.out.println( + s + ", long: " + l + ", binary:\n " + + Long.toBinaryString(l)); + } +} +/* Output: (First 32 Lines) +-1, int: -1, binary: + 11111111111111111111111111111111 ++1, int: 1, binary: + 1 +maxpos, int: 2147483647, binary: + 1111111111111111111111111111111 +maxneg, int: -2147483648, binary: + 10000000000000000000000000000000 +i, int: -1172028779, binary: + 10111010001001000100001010010101 +~i, int: 1172028778, binary: + 1000101110110111011110101101010 +-i, int: 1172028779, binary: + 1000101110110111011110101101011 +j, int: 1717241110, binary: + 1100110010110110000010100010110 +i & j, int: 570425364, binary: + 100010000000000000000000010100 +i | j, int: -25213033, binary: + 11111110011111110100011110010111 +i ^ j, int: -595638397, binary: + 11011100011111110100011110000011 +i << 5, int: 1149784736, binary: + 1000100100010000101001010100000 +i >> 5, int: -36625900, binary: + 11111101110100010010001000010100 +(~i) >> 5, int: 36625899, binary: + 10001011101101110111101011 +i >>> 5, int: 97591828, binary: + 101110100010010001000010100 +(~i) >>> 5, int: 36625899, binary: + 10001011101101110111101011 + ... +*/ diff --git a/code/operators/Bool.java b/code/operators/Bool.java new file mode 100644 index 00000000..e9984adb --- /dev/null +++ b/code/operators/Bool.java @@ -0,0 +1,42 @@ +// operators/Bool.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Relational and logical operators +import java.util.*; + +public class Bool { + public static void main(String[] args) { + Random rand = new Random(47); + int i = rand.nextInt(100); + int j = rand.nextInt(100); + System.out.println("i = " + i); + System.out.println("j = " + j); + System.out.println("i > j is " + (i > j)); + System.out.println("i < j is " + (i < j)); + System.out.println("i >= j is " + (i >= j)); + System.out.println("i <= j is " + (i <= j)); + System.out.println("i == j is " + (i == j)); + System.out.println("i != j is " + (i != j)); + // Treating an int as a boolean is not legal Java: + //- System.out.println("i && j is " + (i && j)); + //- System.out.println("i || j is " + (i || j)); + //- System.out.println("!i is " + !i); + System.out.println("(i < 10) && (j < 10) is " + + ((i < 10) && (j < 10)) ); + System.out.println("(i < 10) || (j < 10) is " + + ((i < 10) || (j < 10)) ); + } +} +/* Output: +i = 58 +j = 55 +i > j is true +i < j is false +i >= j is true +i <= j is false +i == j is false +i != j is true +(i < 10) && (j < 10) is false +(i < 10) || (j < 10) is false +*/ diff --git a/code/operators/Casting.java b/code/operators/Casting.java new file mode 100644 index 00000000..337b24fd --- /dev/null +++ b/code/operators/Casting.java @@ -0,0 +1,16 @@ +// operators/Casting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Casting { + public static void main(String[] args) { + int i = 200; + long lng = (long)i; + lng = i; // "Widening," so a cast is not required + long lng2 = (long)200; + lng2 = 200; + // A "narrowing conversion": + i = (int)lng2; // Cast required + } +} diff --git a/code/operators/CastingNumbers.java b/code/operators/CastingNumbers.java new file mode 100644 index 00000000..a6c04c6e --- /dev/null +++ b/code/operators/CastingNumbers.java @@ -0,0 +1,23 @@ +// operators/CastingNumbers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// What happens when you cast a float +// or double to an integral value? + +public class CastingNumbers { + public static void main(String[] args) { + double above = 0.7, below = 0.4; + float fabove = 0.7f, fbelow = 0.4f; + System.out.println("(int)above: " + (int)above); + System.out.println("(int)below: " + (int)below); + System.out.println("(int)fabove: " + (int)fabove); + System.out.println("(int)fbelow: " + (int)fbelow); + } +} +/* Output: +(int)above: 0 +(int)below: 0 +(int)fabove: 0 +(int)fbelow: 0 +*/ diff --git a/code/operators/EqualsMethod.java b/code/operators/EqualsMethod.java new file mode 100644 index 00000000..f55b1b57 --- /dev/null +++ b/code/operators/EqualsMethod.java @@ -0,0 +1,15 @@ +// operators/EqualsMethod.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class EqualsMethod { + public static void main(String[] args) { + Integer n1 = 47; + Integer n2 = 47; + System.out.println(n1.equals(n2)); + } +} +/* Output: +true +*/ diff --git a/code/operators/EqualsMethod2.java b/code/operators/EqualsMethod2.java new file mode 100644 index 00000000..21393060 --- /dev/null +++ b/code/operators/EqualsMethod2.java @@ -0,0 +1,21 @@ +// operators/EqualsMethod2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Default equals() does not compare contents + +class Value { + int i; +} + +public class EqualsMethod2 { + public static void main(String[] args) { + Value v1 = new Value(); + Value v2 = new Value(); + v1.i = v2.i = 100; + System.out.println(v1.equals(v2)); + } +} +/* Output: +false +*/ diff --git a/code/operators/Equivalence.java b/code/operators/Equivalence.java new file mode 100644 index 00000000..cef07d64 --- /dev/null +++ b/code/operators/Equivalence.java @@ -0,0 +1,17 @@ +// operators/Equivalence.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Equivalence { + public static void main(String[] args) { + Integer n1 = 47; + Integer n2 = 47; + System.out.println(n1 == n2); + System.out.println(n1 != n2); + } +} +/* Output: +true +false +*/ diff --git a/code/operators/Exponents.java b/code/operators/Exponents.java new file mode 100644 index 00000000..924340df --- /dev/null +++ b/code/operators/Exponents.java @@ -0,0 +1,21 @@ +// operators/Exponents.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// "e" means "10 to the power." + +public class Exponents { + public static void main(String[] args) { + // Uppercase and lowercase 'e' are the same: + float expFloat = 1.39e-43f; + expFloat = 1.39E-43f; + System.out.println(expFloat); + double expDouble = 47e47d; // 'd' is optional + double expDouble2 = 47e47; // Automatically double + System.out.println(expDouble); + } +} +/* Output: +1.39E-43 +4.7E48 +*/ diff --git a/code/operators/Literals.java b/code/operators/Literals.java new file mode 100644 index 00000000..ad00e0b8 --- /dev/null +++ b/code/operators/Literals.java @@ -0,0 +1,61 @@ +// operators/Literals.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Literals { + public static void main(String[] args) { + int i1 = 0x2f; // Hexadecimal (lowercase) + System.out.println( + "i1: " + Integer.toBinaryString(i1)); + int i2 = 0X2F; // Hexadecimal (uppercase) + System.out.println( + "i2: " + Integer.toBinaryString(i2)); + int i3 = 0177; // Octal (leading zero) + System.out.println( + "i3: " + Integer.toBinaryString(i3)); + char c = 0xffff; // max char hex value + System.out.println( + "c: " + Integer.toBinaryString(c)); + byte b = 0x7f; // max byte hex value 10101111; + System.out.println( + "b: " + Integer.toBinaryString(b)); + short s = 0x7fff; // max short hex value + System.out.println( + "s: " + Integer.toBinaryString(s)); + long n1 = 200L; // long suffix + long n2 = 200l; // long suffix (can be confusing) + long n3 = 200; + // Java 7 Binary Literals: + byte blb = (byte)0b00110101; + System.out.println( + "blb: " + Integer.toBinaryString(blb)); + short bls = (short)0B0010111110101111; + System.out.println( + "bls: " + Integer.toBinaryString(bls)); + int bli = 0b00101111101011111010111110101111; + System.out.println( + "bli: " + Integer.toBinaryString(bli)); + long bll = 0b00101111101011111010111110101111; + System.out.println( + "bll: " + Long.toBinaryString(bll)); + float f1 = 1; + float f2 = 1F; // float suffix + float f3 = 1f; // float suffix + double d1 = 1d; // double suffix + double d2 = 1D; // double suffix + // (Hex and Octal also work with long) + } +} +/* Output: +i1: 101111 +i2: 101111 +i3: 1111111 +c: 1111111111111111 +b: 1111111 +s: 111111111111111 +blb: 110101 +bls: 10111110101111 +bli: 101111101011111010111110101111 +bll: 101111101011111010111110101111 +*/ diff --git a/code/operators/MathOps.java b/code/operators/MathOps.java new file mode 100644 index 00000000..a9b08938 --- /dev/null +++ b/code/operators/MathOps.java @@ -0,0 +1,75 @@ +// operators/MathOps.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The mathematical operators +import java.util.*; + +public class MathOps { + public static void main(String[] args) { + // Create a seeded random number generator: + Random rand = new Random(47); + int i, j, k; + // Choose value from 1 to 100: + j = rand.nextInt(100) + 1; + System.out.println("j : " + j); + k = rand.nextInt(100) + 1; + System.out.println("k : " + k); + i = j + k; + System.out.println("j + k : " + i); + i = j - k; + System.out.println("j - k : " + i); + i = k / j; + System.out.println("k / j : " + i); + i = k * j; + System.out.println("k * j : " + i); + i = k % j; + System.out.println("k % j : " + i); + j %= k; + System.out.println("j %= k : " + j); + // Floating-point number tests: + float u, v, w; // Applies to doubles, too + v = rand.nextFloat(); + System.out.println("v : " + v); + w = rand.nextFloat(); + System.out.println("w : " + w); + u = v + w; + System.out.println("v + w : " + u); + u = v - w; + System.out.println("v - w : " + u); + u = v * w; + System.out.println("v * w : " + u); + u = v / w; + System.out.println("v / w : " + u); + // The following also works for char, + // byte, short, int, long, and double: + u += v; + System.out.println("u += v : " + u); + u -= v; + System.out.println("u -= v : " + u); + u *= v; + System.out.println("u *= v : " + u); + u /= v; + System.out.println("u /= v : " + u); + } +} +/* Output: +j : 59 +k : 56 +j + k : 115 +j - k : 3 +k / j : 0 +k * j : 3304 +k % j : 56 +j %= k : 3 +v : 0.5309454 +w : 0.0534122 +v + w : 0.5843576 +v - w : 0.47753322 +v * w : 0.028358962 +v / w : 9.940527 +u += v : 10.471473 +u -= v : 9.940527 +u *= v : 5.2778773 +u /= v : 9.940527 +*/ diff --git a/code/operators/Overflow.java b/code/operators/Overflow.java new file mode 100644 index 00000000..851c1456 --- /dev/null +++ b/code/operators/Overflow.java @@ -0,0 +1,18 @@ +// operators/Overflow.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Surprise! Java lets you overflow + +public class Overflow { + public static void main(String[] args) { + int big = Integer.MAX_VALUE; + System.out.println("big = " + big); + int bigger = big * 4; + System.out.println("bigger = " + bigger); + } +} +/* Output: +big = 2147483647 +bigger = -4 +*/ diff --git a/code/operators/PassObject.java b/code/operators/PassObject.java new file mode 100644 index 00000000..af53ab56 --- /dev/null +++ b/code/operators/PassObject.java @@ -0,0 +1,27 @@ +// operators/PassObject.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Passing objects to methods might not be +// what you're used to + +class Letter { + char c; +} + +public class PassObject { + static void f(Letter y) { + y.c = 'z'; + } + public static void main(String[] args) { + Letter x = new Letter(); + x.c = 'a'; + System.out.println("1: x.c: " + x.c); + f(x); + System.out.println("2: x.c: " + x.c); + } +} +/* Output: +1: x.c: a +2: x.c: z +*/ diff --git a/code/operators/Precedence.java b/code/operators/Precedence.java new file mode 100644 index 00000000..f0f8140c --- /dev/null +++ b/code/operators/Precedence.java @@ -0,0 +1,18 @@ +// operators/Precedence.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Precedence { + public static void main(String[] args) { + int x = 1, y = 2, z = 3; + int a = x + y - 2/2 + z; // [1] + int b = x + (y - 2)/(2 + z); // [2] + System.out.println("a = " + a); + System.out.println("b = " + b); + } +} +/* Output: +a = 5 +b = 1 +*/ diff --git a/code/operators/RoundingNumbers.java b/code/operators/RoundingNumbers.java new file mode 100644 index 00000000..e46a2056 --- /dev/null +++ b/code/operators/RoundingNumbers.java @@ -0,0 +1,26 @@ +// operators/RoundingNumbers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Rounding floats and doubles + +public class RoundingNumbers { + public static void main(String[] args) { + double above = 0.7, below = 0.4; + float fabove = 0.7f, fbelow = 0.4f; + System.out.println( + "Math.round(above): " + Math.round(above)); + System.out.println( + "Math.round(below): " + Math.round(below)); + System.out.println( + "Math.round(fabove): " + Math.round(fabove)); + System.out.println( + "Math.round(fbelow): " + Math.round(fbelow)); + } +} +/* Output: +Math.round(above): 1 +Math.round(below): 0 +Math.round(fabove): 1 +Math.round(fbelow): 0 +*/ diff --git a/code/operators/ShortCircuit.java b/code/operators/ShortCircuit.java new file mode 100644 index 00000000..8fc96711 --- /dev/null +++ b/code/operators/ShortCircuit.java @@ -0,0 +1,34 @@ +// operators/ShortCircuit.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Short-circuiting behavior with logical operators + +public class ShortCircuit { + static boolean test1(int val) { + System.out.println("test1(" + val + ")"); + System.out.println("result: " + (val < 1)); + return val < 1; + } + static boolean test2(int val) { + System.out.println("test2(" + val + ")"); + System.out.println("result: " + (val < 2)); + return val < 2; + } + static boolean test3(int val) { + System.out.println("test3(" + val + ")"); + System.out.println("result: " + (val < 3)); + return val < 3; + } + public static void main(String[] args) { + boolean b = test1(0) && test2(2) && test3(2); + System.out.println("expression is " + b); + } +} +/* Output: +test1(0) +result: true +test2(2) +result: false +expression is false +*/ diff --git a/code/operators/StringOperators.java b/code/operators/StringOperators.java new file mode 100644 index 00000000..b1eb211f --- /dev/null +++ b/code/operators/StringOperators.java @@ -0,0 +1,24 @@ +// operators/StringOperators.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class StringOperators { + public static void main(String[] args) { + int x = 0, y = 1, z = 2; + String s = "x, y, z "; + System.out.println(s + x + y + z); + // Converts x to a String: + System.out.println(x + " " + s); + s += "(summed) = "; // Concatenation operator + System.out.println(s + (x + y + z)); + // Shorthand for Integer.toString(): + System.out.println("" + x); + } +} +/* Output: +x, y, z 012 +0 x, y, z +x, y, z (summed) = 3 +0 +*/ diff --git a/code/operators/TernaryIfElse.java b/code/operators/TernaryIfElse.java new file mode 100644 index 00000000..d11d4e24 --- /dev/null +++ b/code/operators/TernaryIfElse.java @@ -0,0 +1,28 @@ +// operators/TernaryIfElse.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class TernaryIfElse { + static int ternary(int i) { + return i < 10 ? i * 100 : i * 10; + } + static int standardIfElse(int i) { + if(i < 10) + return i * 100; + else + return i * 10; + } + public static void main(String[] args) { + System.out.println(ternary(9)); + System.out.println(ternary(10)); + System.out.println(standardIfElse(9)); + System.out.println(standardIfElse(10)); + } +} +/* Output: +900 +100 +900 +100 +*/ diff --git a/code/operators/URShift.java b/code/operators/URShift.java new file mode 100644 index 00000000..8d24f94b --- /dev/null +++ b/code/operators/URShift.java @@ -0,0 +1,42 @@ +// operators/URShift.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Test of unsigned right shift + +public class URShift { + public static void main(String[] args) { + int i = -1; + System.out.println(Integer.toBinaryString(i)); + i >>>= 10; + System.out.println(Integer.toBinaryString(i)); + long l = -1; + System.out.println(Long.toBinaryString(l)); + l >>>= 10; + System.out.println(Long.toBinaryString(l)); + short s = -1; + System.out.println(Integer.toBinaryString(s)); + s >>>= 10; + System.out.println(Integer.toBinaryString(s)); + byte b = -1; + System.out.println(Integer.toBinaryString(b)); + b >>>= 10; + System.out.println(Integer.toBinaryString(b)); + b = -1; + System.out.println(Integer.toBinaryString(b)); + System.out.println(Integer.toBinaryString(b>>>10)); + } +} +/* Output: +11111111111111111111111111111111 +1111111111111111111111 +1111111111111111111111111111111111111111111111111111111 +111111111 +111111111111111111111111111111111111111111111111111111 +11111111111111111111111111111111 +11111111111111111111111111111111 +11111111111111111111111111111111 +11111111111111111111111111111111 +11111111111111111111111111111111 +1111111111111111111111 +*/ diff --git a/code/operators/Underscores.java b/code/operators/Underscores.java new file mode 100644 index 00000000..4d78cd50 --- /dev/null +++ b/code/operators/Underscores.java @@ -0,0 +1,22 @@ +// operators/Underscores.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Underscores { + public static void main(String[] args) { + double d = 341_435_936.445_667; + System.out.println(d); + int bin = 0b0010_1111_1010_1111_1010_1111_1010_1111; + System.out.println(Integer.toBinaryString(bin)); + System.out.printf("%x%n", bin); // [1] + long hex = 0x7f_e9_b7_aa; + System.out.printf("%x%n", hex); + } +} +/* Output: +3.41435936445667E8 +101111101011111010111110101111 +2fafafaf +7fe9b7aa +*/ diff --git a/code/patterns/BoxObserver.java b/code/patterns/BoxObserver.java new file mode 100644 index 00000000..c6f9ec65 --- /dev/null +++ b/code/patterns/BoxObserver.java @@ -0,0 +1,94 @@ +// patterns/BoxObserver.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of Observer pattern using +// Java's built-in observer classes. +// {ExcludeFromGradle} // Won't work under WSL2 +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import onjava.*; +import onjava.MouseClick; + +// You must inherit a new type of Observable: +@SuppressWarnings("deprecation") +class BoxObservable extends Observable { + @Override + public void notifyObservers(Object b) { + // Otherwise it won't propagate changes: + setChanged(); + super.notifyObservers(b); + } +} + +@SuppressWarnings("deprecation") +public class BoxObserver extends JFrame { + Observable notifier = new BoxObservable(); + public BoxObserver(int grid) { + setTitle("Demonstrates Observer pattern"); + Container cp = getContentPane(); + cp.setLayout(new GridLayout(grid, grid)); + for(int x = 0; x < grid; x++) + for(int y = 0; y < grid; y++) + cp.add(new OCBox(x, y, notifier)); + } + public static void main(String[] args) { + // For automated test runs: + // new TimedAbort(4); + int grid = 8; + if(args.length > 0) + grid = Integer.parseInt(args[0]); + JFrame f = new BoxObserver(grid); + f.setSize(500, 400); + f.setVisible(true); + f.setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } +} + +@SuppressWarnings("deprecation") +class OCBox extends JPanel implements Observer { + Observable notifier; + int x, y; // Locations in grid + Color cColor = newColor(); + static final Color[] COLORS = { + Color.black, Color.blue, Color.cyan, + Color.darkGray, Color.gray, Color.green, + Color.lightGray, Color.magenta, + Color.orange, Color.pink, Color.red, + Color.white, Color.yellow + }; + static Color newColor() { + return COLORS[ + (int)(Math.random() * COLORS.length) + ]; + } + OCBox(int x, int y, Observable notifier) { + this.x = x; + this.y = y; + notifier.addObserver(this); + this.notifier = notifier; + addMouseListener((MouseClick) + e -> notifier.notifyObservers(OCBox.this)); + } + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(cColor); + Dimension s = getSize(); + g.fillRect(0, 0, s.width, s.height); + } + @Override + public void update(Observable o, Object arg) { + OCBox clicked = (OCBox)arg; + if(nextTo(clicked)) { + cColor = clicked.cColor; + repaint(); + } + } + private boolean nextTo(OCBox b) { + return Math.abs(x - b.x) <= 1 && + Math.abs(y - b.y) <= 1; + } +} diff --git a/code/patterns/CommandPattern.java b/code/patterns/CommandPattern.java new file mode 100644 index 00000000..f84533aa --- /dev/null +++ b/code/patterns/CommandPattern.java @@ -0,0 +1,19 @@ +// patterns/CommandPattern.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class CommandPattern { + public static void main(String[] args) { + List macro = Arrays.asList( + () -> System.out.print("Hello "), + () -> System.out.print("World! "), + () -> System.out.print("I'm the command pattern!") + ); + macro.forEach(Runnable::run); + } +} +/* Output: +Hello World! I'm the command pattern! +*/ diff --git a/code/patterns/Facade.java b/code/patterns/Facade.java new file mode 100644 index 00000000..0c1accf2 --- /dev/null +++ b/code/patterns/Facade.java @@ -0,0 +1,24 @@ +// patterns/Facade.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class A { A(int x) {} } +class B { B(long x) {} } +class C { C(double x) {} } + +// Other classes that aren't exposed by the +// facade go here ... + +public class Facade { + static A makeA(int x) { return new A(x); } + static B makeB(long x) { return new B(x); } + static C makeC(double x) { return new C(x); } + public static void main(String[] args) { + // The client programmer gets the objects + // by calling the static methods: + A a = Facade.makeA(1); + B b = Facade.makeB(1); + C c = Facade.makeC(1.0); + } +} diff --git a/code/patterns/PaperScissorsRock.java b/code/patterns/PaperScissorsRock.java new file mode 100644 index 00000000..e7a7c44e --- /dev/null +++ b/code/patterns/PaperScissorsRock.java @@ -0,0 +1,135 @@ +// patterns/PaperScissorsRock.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of multiple dispatching +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import onjava.*; +import static onjava.Tuple.*; + +enum Outcome { WIN, LOSE, DRAW } + +interface Item { + Outcome compete(Item it); + Outcome eval(Paper p); + Outcome eval(Scissors s); + Outcome eval(Rock r); +} + +class Paper implements Item { + @Override + public Outcome compete(Item it) { + return it.eval(this); + } + @Override + public Outcome eval(Paper p) { + return Outcome.DRAW; + } + @Override + public Outcome eval(Scissors s) { + return Outcome.WIN; + } + @Override + public Outcome eval(Rock r) { + return Outcome.LOSE; + } + @Override + public String toString() { return "Paper"; } +} + +class Scissors implements Item { + @Override + public Outcome compete(Item it) { + return it.eval(this); + } + @Override + public Outcome eval(Paper p) { + return Outcome.LOSE; + } + @Override + public Outcome eval(Scissors s) { + return Outcome.DRAW; + } + @Override + public Outcome eval(Rock r) { + return Outcome.WIN; + } + @Override + public String toString() { return "Scissors"; } +} + +class Rock implements Item { + @Override + public Outcome compete(Item it) { + return it.eval(this); + } + @Override + public Outcome eval(Paper p) { + return Outcome.WIN; + } + @Override + public Outcome eval(Scissors s) { + return Outcome.LOSE; + } + @Override + public Outcome eval(Rock r) { + return Outcome.DRAW; + } + @Override + public String toString() { return "Rock"; } +} + +class ItemFactory { + static List> items = + Arrays.asList( + Scissors::new, Paper::new, Rock::new); + static final int SZ = items.size(); + private static SplittableRandom rand = + new SplittableRandom(47); + public static Item newItem() { + return items.get(rand.nextInt(SZ)).get(); + } + public static Tuple2 newPair() { + return tuple(newItem(), newItem()); + } +} + +class Compete { + public static Outcome match(Tuple2 p) { + System.out.print(p.a1 + " -> " + p.a2 + " : "); + return p.a1.compete(p.a2); + } +} + +public class PaperScissorsRock { + public static void main(String[] args) { + Stream.generate(ItemFactory::newPair) + .limit(20) + .map(Compete::match) + .forEach(System.out::println); + } +} +/* Output: +Scissors -> Rock : LOSE +Scissors -> Paper : WIN +Rock -> Paper : LOSE +Rock -> Rock : DRAW +Rock -> Paper : LOSE +Paper -> Scissors : LOSE +Rock -> Paper : LOSE +Scissors -> Scissors : DRAW +Scissors -> Rock : LOSE +Scissors -> Paper : WIN +Scissors -> Rock : LOSE +Paper -> Scissors : LOSE +Rock -> Rock : DRAW +Scissors -> Scissors : DRAW +Paper -> Paper : DRAW +Scissors -> Paper : WIN +Scissors -> Rock : LOSE +Scissors -> Paper : WIN +Rock -> Paper : LOSE +Rock -> Scissors : WIN +*/ diff --git a/code/patterns/ProxyDemo.java b/code/patterns/ProxyDemo.java new file mode 100644 index 00000000..58b0e3a8 --- /dev/null +++ b/code/patterns/ProxyDemo.java @@ -0,0 +1,51 @@ +// patterns/ProxyDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple demonstration of the Proxy pattern + +interface ProxyBase { + void f(); + void g(); + void h(); +} + +class Proxy implements ProxyBase { + private ProxyBase implementation; + Proxy() { + implementation = new Implementation(); + } + // Pass method calls to the implementation: + @Override + public void f() { implementation.f(); } + @Override + public void g() { implementation.g(); } + @Override + public void h() { implementation.h(); } +} + +class Implementation implements ProxyBase { + public void f() { + System.out.println("Implementation.f()"); + } + public void g() { + System.out.println("Implementation.g()"); + } + public void h() { + System.out.println("Implementation.h()"); + } +} + +public class ProxyDemo { + public static void main(String[] args) { + Proxy p = new Proxy(); + p.f(); + p.g(); + p.h(); + } +} +/* Output: +Implementation.f() +Implementation.g() +Implementation.h() +*/ diff --git a/code/patterns/ShapeFactory1.java b/code/patterns/ShapeFactory1.java new file mode 100644 index 00000000..dc6f8690 --- /dev/null +++ b/code/patterns/ShapeFactory1.java @@ -0,0 +1,39 @@ +// patterns/ShapeFactory1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A simple static factory method +import java.util.*; +import java.util.stream.*; +import patterns.shapes.*; + +public class ShapeFactory1 implements FactoryMethod { + public Shape create(String type) { + switch(type) { + case "Circle": return new Circle(); + case "Square": return new Square(); + case "Triangle": return new Triangle(); + default: + throw new BadShapeCreation(type); + } + } + public static void main(String[] args) { + FactoryTest.test(new ShapeFactory1()); + } +} +/* Output: +Circle[0] draw +Circle[0] erase +Square[1] draw +Square[1] erase +Triangle[2] draw +Triangle[2] erase +Square[3] draw +Square[3] erase +Circle[4] draw +Circle[4] erase +Circle[5] draw +Circle[5] erase +Triangle[6] draw +Triangle[6] erase +*/ diff --git a/code/patterns/ShapeFactory2.java b/code/patterns/ShapeFactory2.java new file mode 100644 index 00000000..23881105 --- /dev/null +++ b/code/patterns/ShapeFactory2.java @@ -0,0 +1,54 @@ +// patterns/ShapeFactory2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.lang.reflect.*; +import java.util.stream.*; +import patterns.shapes.*; + +public class ShapeFactory2 implements FactoryMethod { + Map factories = + new HashMap<>(); + static Constructor load(String id) { + System.out.println("loading " + id); + try { + return Class.forName("patterns.shapes." + id) + .getConstructor(); + } catch(ClassNotFoundException | + NoSuchMethodException e) { + throw new BadShapeCreation(id); + } + } + public Shape create(String id) { + try { + return (Shape)factories + .computeIfAbsent(id, ShapeFactory2::load) + .newInstance(); + } catch(Exception e) { + throw new BadShapeCreation(id); + } + } + public static void main(String[] args) { + FactoryTest.test(new ShapeFactory2()); + } +} +/* Output: +loading Circle +Circle[0] draw +Circle[0] erase +loading Square +Square[1] draw +Square[1] erase +loading Triangle +Triangle[2] draw +Triangle[2] erase +Square[3] draw +Square[3] erase +Circle[4] draw +Circle[4] erase +Circle[5] draw +Circle[5] erase +Triangle[6] draw +Triangle[6] erase +*/ diff --git a/code/patterns/ShapeFactory3.java b/code/patterns/ShapeFactory3.java new file mode 100644 index 00000000..b735a81d --- /dev/null +++ b/code/patterns/ShapeFactory3.java @@ -0,0 +1,52 @@ +// patterns/ShapeFactory3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Polymorphic factory methods +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import patterns.shapes.*; + +interface PolymorphicFactory { + Shape create(); +} + +class RandomShapes implements Supplier { + private final PolymorphicFactory[] factories; + private Random rand = new Random(42); + RandomShapes(PolymorphicFactory... factories) { + this.factories = factories; + } + public Shape get() { + return factories[ + rand.nextInt(factories.length)].create(); + } +} + +public class ShapeFactory3 { + public static void main(String[] args) { + RandomShapes rs = new RandomShapes( + Circle::new, Square::new, Triangle::new + ); + Stream.generate(rs) + .limit(6) + .peek(Shape::draw) + .peek(Shape::erase) + .count(); + } +} +/* Output: +Triangle[0] draw +Triangle[0] erase +Circle[1] draw +Circle[1] erase +Circle[2] draw +Circle[2] erase +Triangle[3] draw +Triangle[3] erase +Circle[4] draw +Circle[4] erase +Square[5] draw +Square[5] erase +*/ diff --git a/code/patterns/SingletonPattern.java b/code/patterns/SingletonPattern.java new file mode 100644 index 00000000..c2ca1a5f --- /dev/null +++ b/code/patterns/SingletonPattern.java @@ -0,0 +1,58 @@ +// patterns/SingletonPattern.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface Resource { + int getValue(); + void setValue(int x); +} + +// This isn't inherited from a Cloneable +// base class and cloneability isn't added so +// making it final prevents cloneability from +// being added through inheritance. This also +// implements thread-safe lazy initialization: + +final class Singleton { + private static final class + ResourceImpl implements Resource { + private int i; + private ResourceImpl(int i) { + this.i = i; + } + public synchronized int getValue() { + return i; + } + public synchronized void setValue(int x) { + i = x; + } + } + private static class ResourceHolder { + private static Resource resource = + new ResourceImpl(47); + } + public static Resource getResource() { + return ResourceHolder.resource; + } +} + +public class SingletonPattern { + public static void main(String[] args) { + Resource r = Singleton.getResource(); + System.out.println(r.getValue()); + Resource s2 = Singleton.getResource(); + s2.setValue(9); + System.out.println(r.getValue()); + try { + // Can't do this: compile-time error. + // Singleton s3 = (Singleton)s2.clone(); + } catch(Exception e) { + throw new RuntimeException(e); + } + } +} +/* Output: +47 +9 +*/ diff --git a/code/patterns/StateDemo.java b/code/patterns/StateDemo.java new file mode 100644 index 00000000..9efab5b4 --- /dev/null +++ b/code/patterns/StateDemo.java @@ -0,0 +1,87 @@ +// patterns/StateDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple demonstration of the State pattern + +interface StateBase { + void f(); + void g(); + void h(); + void changeImp(StateBase newImp); +} + +class State implements StateBase { + private StateBase implementation; + State(StateBase imp) { + implementation = imp; + } + @Override + public void changeImp(StateBase newImp) { + implementation = newImp; + } + // Pass method calls to the implementation: + @Override + public void f() { implementation.f(); } + @Override + public void g() { implementation.g(); } + @Override + public void h() { implementation.h(); } +} + +class Implementation1 implements StateBase { + @Override + public void f() { + System.out.println("Implementation1.f()"); + } + @Override + public void g() { + System.out.println("Implementation1.g()"); + } + @Override + public void h() { + System.out.println("Implementation1.h()"); + } + @Override + public void changeImp(StateBase newImp) {} +} + +class Implementation2 implements StateBase { + @Override + public void f() { + System.out.println("Implementation2.f()"); + } + @Override + public void g() { + System.out.println("Implementation2.g()"); + } + @Override + public void h() { + System.out.println("Implementation2.h()"); + } + @Override + public void changeImp(StateBase newImp) {} +} + +public class StateDemo { + static void test(StateBase b) { + b.f(); + b.g(); + b.h(); + } + public static void main(String[] args) { + StateBase b = + new State(new Implementation1()); + test(b); + b.changeImp(new Implementation2()); + test(b); + } +} +/* Output: +Implementation1.f() +Implementation1.g() +Implementation1.h() +Implementation2.f() +Implementation2.g() +Implementation2.h() +*/ diff --git a/code/patterns/TemplateMethod.java b/code/patterns/TemplateMethod.java new file mode 100644 index 00000000..eff6d279 --- /dev/null +++ b/code/patterns/TemplateMethod.java @@ -0,0 +1,44 @@ +// patterns/TemplateMethod.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple demonstration of Template Method +import java.util.stream.*; + +abstract class ApplicationFramework { + ApplicationFramework() { + templateMethod(); + } + abstract void customize1(); + abstract void customize2(); + // "private" means automatically "final": + private void templateMethod() { + IntStream.range(0, 5).forEach( + n -> { customize1(); customize2(); }); + } +} + +// Create a new "application": +class MyApp extends ApplicationFramework { + @Override + void customize1() { + System.out.print("Hello "); + } + @Override + void customize2() { + System.out.println("World!"); + } +} + +public class TemplateMethod { + public static void main(String[] args) { + new MyApp(); + } +} +/* Output: +Hello World! +Hello World! +Hello World! +Hello World! +Hello World! +*/ diff --git a/code/patterns/abstractfactory/GameEnvironment.java b/code/patterns/abstractfactory/GameEnvironment.java new file mode 100644 index 00000000..8c0abf7b --- /dev/null +++ b/code/patterns/abstractfactory/GameEnvironment.java @@ -0,0 +1,96 @@ +// patterns/abstractfactory/GameEnvironment.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An example of the Abstract Factory pattern +// {java patterns.abstractfactory.GameEnvironment} +package patterns.abstractfactory; +import java.util.function.*; + +interface Obstacle { + void action(); +} + +interface Player { + void interactWith(Obstacle o); +} + +class Kitty implements Player { + @Override + public void interactWith(Obstacle ob) { + System.out.print("Kitty has encountered a "); + ob.action(); + } +} + +class KungFuGuy implements Player { + @Override + public void interactWith(Obstacle ob) { + System.out.print("KungFuGuy now battles a "); + ob.action(); + } +} + +class Puzzle implements Obstacle { + @Override + public void action() { + System.out.println("Puzzle"); + } +} + +class NastyWeapon implements Obstacle { + @Override + public void action() { + System.out.println("NastyWeapon"); + } +} + +// The Abstract Factory: +class GameElementFactory { + Supplier player; + Supplier obstacle; +} + +// Concrete factories: +class KittiesAndPuzzles +extends GameElementFactory { + KittiesAndPuzzles() { + player = Kitty::new; + obstacle = Puzzle::new; + } +} + +class KillAndDismember +extends GameElementFactory { + KillAndDismember() { + player = KungFuGuy::new; + obstacle = NastyWeapon::new; + } +} + +public class GameEnvironment { + private Player p; + private Obstacle ob; + public + GameEnvironment(GameElementFactory factory) { + p = factory.player.get(); + ob = factory.obstacle.get(); + } + public void play() { + p.interactWith(ob); + } + public static void main(String[] args) { + GameElementFactory + kp = new KittiesAndPuzzles(), + kd = new KillAndDismember(); + GameEnvironment + g1 = new GameEnvironment(kp), + g2 = new GameEnvironment(kd); + g1.play(); + g2.play(); + } +} +/* Output: +Kitty has encountered a Puzzle +KungFuGuy now battles a NastyWeapon +*/ diff --git a/code/patterns/adapt/Adapter.java b/code/patterns/adapt/Adapter.java new file mode 100644 index 00000000..5bfcd6bf --- /dev/null +++ b/code/patterns/adapt/Adapter.java @@ -0,0 +1,85 @@ +// patterns/adapt/Adapter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Variations on the Adapter pattern +// {java patterns.adapt.Adapter} +package patterns.adapt; + +class WhatIHave { + public void g() {} + public void h() {} +} + +interface WhatIWant { + void f(); +} + +class ProxyAdapter implements WhatIWant { + WhatIHave whatIHave; + ProxyAdapter(WhatIHave wih) { + whatIHave = wih; + } + @Override + public void f() { + // Implement behavior using + // methods in WhatIHave: + whatIHave.g(); + whatIHave.h(); + } +} + +class WhatIUse { + public void op(WhatIWant wiw) { + wiw.f(); + } +} + +// Approach 2: build adapter use into op(): +class WhatIUse2 extends WhatIUse { + public void op(WhatIHave wih) { + new ProxyAdapter(wih).f(); + } +} + +// Approach 3: build adapter into WhatIHave: +class WhatIHave2 extends WhatIHave +implements WhatIWant { + @Override + public void f() { + g(); + h(); + } +} + +// Approach 4: use an inner class: +class WhatIHave3 extends WhatIHave { + private class InnerAdapter implements WhatIWant{ + @Override + public void f() { + g(); + h(); + } + } + public WhatIWant whatIWant() { + return new InnerAdapter(); + } +} + +public class Adapter { + public static void main(String[] args) { + WhatIUse whatIUse = new WhatIUse(); + WhatIHave whatIHave = new WhatIHave(); + WhatIWant adapt= new ProxyAdapter(whatIHave); + whatIUse.op(adapt); + // Approach 2: + WhatIUse2 whatIUse2 = new WhatIUse2(); + whatIUse2.op(whatIHave); + // Approach 3: + WhatIHave2 whatIHave2 = new WhatIHave2(); + whatIUse.op(whatIHave2); + // Approach 4: + WhatIHave3 whatIHave3 = new WhatIHave3(); + whatIUse.op(whatIHave3.whatIWant()); + } +} diff --git a/code/patterns/chain/ChainOfResponsibility.java b/code/patterns/chain/ChainOfResponsibility.java new file mode 100644 index 00000000..b733e71c --- /dev/null +++ b/code/patterns/chain/ChainOfResponsibility.java @@ -0,0 +1,90 @@ +// patterns/chain/ChainOfResponsibility.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using the Functional interface +// {java patterns.chain.ChainOfResponsibility} +package patterns.chain; +import java.util.*; +import java.util.function.*; + +class Result { + boolean success; + List line; + Result(List data) { + success = true; + line = data; + } + Result() { + success = false; + line = Collections.emptyList(); + } +} + +class Fail extends Result {} + +interface Algorithm { + Result algorithm(List line); +} + +class FindMinima { + public static Result leastSquares(List line) { + System.out.println("LeastSquares.algorithm"); + boolean weSucceed = false; + if(weSucceed) // Actual test/calculation here + return new Result(Arrays.asList(1.1, 2.2)); + else // Try the next one in the chain: + return new Fail(); + } + public static Result perturbation(List line) { + System.out.println("Perturbation.algorithm"); + boolean weSucceed = false; + if(weSucceed) // Actual test/calculation here + return new Result(Arrays.asList(3.3, 4.4)); + else + return new Fail(); + } + public static Result bisection(List line) { + System.out.println("Bisection.algorithm"); + boolean weSucceed = true; + if(weSucceed) // Actual test/calculation here + return new Result(Arrays.asList(5.5, 6.6)); + else + return new Fail(); + } + static List, Result>> + algorithms = Arrays.asList( + FindMinima::leastSquares, + FindMinima::perturbation, + FindMinima::bisection + ); + public static Result minima(List line) { + for(Function, Result> alg : + algorithms) { + Result result = alg.apply(line); + if(result.success) + return result; + } + return new Fail(); + } +} + +public class ChainOfResponsibility { + public static void main(String[] args) { + FindMinima solver = new FindMinima(); + List line = Arrays.asList( + 1.0, 2.0, 1.0, 2.0, -1.0, + 3.0, 4.0, 5.0, 4.0); + Result result = solver.minima(line); + if(result.success) + System.out.println(result.line); + else + System.out.println("No algorithm found"); + } +} +/* Output: +LeastSquares.algorithm +Perturbation.algorithm +Bisection.algorithm +[5.5, 6.6] +*/ diff --git a/code/patterns/doubledispatch/Aluminum.java b/code/patterns/doubledispatch/Aluminum.java new file mode 100644 index 00000000..5037fac5 --- /dev/null +++ b/code/patterns/doubledispatch/Aluminum.java @@ -0,0 +1,18 @@ +// patterns/doubledispatch/Aluminum.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Aluminum for double dispatching +package patterns.doubledispatch; +import patterns.trash.*; +import java.util.*; + +public class Aluminum extends patterns.trash.Aluminum + implements TypedBinMember { + public Aluminum(double wt) { super(wt); } + @Override + public boolean addToBin(List tbins) { + return tbins.stream() + .anyMatch(tb -> tb.add(this)); + } +} diff --git a/code/patterns/doubledispatch/Cardboard.java b/code/patterns/doubledispatch/Cardboard.java new file mode 100644 index 00000000..5046ddaa --- /dev/null +++ b/code/patterns/doubledispatch/Cardboard.java @@ -0,0 +1,18 @@ +// patterns/doubledispatch/Cardboard.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Cardboard for double dispatching +package patterns.doubledispatch; +import patterns.trash.*; +import java.util.*; + +public class Cardboard extends patterns.trash.Cardboard + implements TypedBinMember { + public Cardboard(double wt) { super(wt); } + @Override + public boolean addToBin(List tbins) { + return tbins.stream() + .anyMatch(tb -> tb.add(this)); + } +} diff --git a/code/patterns/doubledispatch/DoubleDispatch.java b/code/patterns/doubledispatch/DoubleDispatch.java new file mode 100644 index 00000000..91bee562 --- /dev/null +++ b/code/patterns/doubledispatch/DoubleDispatch.java @@ -0,0 +1,96 @@ +// patterns/doubledispatch/DoubleDispatch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using multiple dispatching to handle more +// than one unknown type during a method call +// {java patterns.doubledispatch.DoubleDispatch} +package patterns.doubledispatch; +import patterns.trash.*; +import java.util.*; + +class AluminumBin extends TypedBin { + @Override + public boolean add(Aluminum a) { + return addIt(a); + } +} + +class PaperBin extends TypedBin { + @Override + public boolean add(Paper a) { + return addIt(a); + } +} + +class GlassBin extends TypedBin { + @Override + public boolean add(Glass a) { + return addIt(a); + } +} + +class CardboardBin extends TypedBin { + @Override + public boolean add(Cardboard a) { + return addIt(a); + } +} + +class TrashBinSet { + private List binSet = Arrays.asList( + new AluminumBin(), + new PaperBin(), + new GlassBin(), + new CardboardBin() + ); + @SuppressWarnings("unchecked") + public void sortIntoBins(List bin) { + bin.forEach( aBin -> { + TypedBinMember t = (TypedBinMember)aBin; + if(!t.addToBin(binSet)) + System.err.println("Couldn't add " + t); + }); + } + public List binSet() { return binSet; } +} + +public class DoubleDispatch { + public static void main(String[] args) { + List bin = new ArrayList<>(); + TrashBinSet bins = new TrashBinSet(); + // ParseTrash still works, without changes: + ParseTrash.fillBin("doubledispatch", bin); + // Sort from the master bin into the + // individually-typed bins: + bins.sortIntoBins(bin); + // Perform sumValue for each bin... + bins.binSet() + .forEach(tb -> Trash.sumValue(tb.v)); + // ... and for the master bin + Trash.sumValue(bin); + } +} +/* Output: (First and Last 10 Lines) +Loading patterns.doubledispatch.Glass +Loading patterns.doubledispatch.Paper +Loading patterns.doubledispatch.Aluminum +Loading patterns.doubledispatch.Cardboard +weight of patterns.doubledispatch.Aluminum = 89.0 +weight of patterns.doubledispatch.Aluminum = 76.0 +weight of patterns.doubledispatch.Aluminum = 25.0 +weight of patterns.doubledispatch.Aluminum = 34.0 +weight of patterns.doubledispatch.Aluminum = 27.0 +weight of patterns.doubledispatch.Aluminum = 18.0 +...________...________...________...________... +weight of patterns.doubledispatch.Aluminum = 93.0 +weight of patterns.doubledispatch.Glass = 93.0 +weight of patterns.doubledispatch.Paper = 80.0 +weight of patterns.doubledispatch.Glass = 36.0 +weight of patterns.doubledispatch.Glass = 12.0 +weight of patterns.doubledispatch.Glass = 60.0 +weight of patterns.doubledispatch.Paper = 66.0 +weight of patterns.doubledispatch.Aluminum = 36.0 +weight of patterns.doubledispatch.Cardboard = 22.0 +Total value = 1086.0599818825722 +*/ diff --git a/code/patterns/doubledispatch/Glass.java b/code/patterns/doubledispatch/Glass.java new file mode 100644 index 00000000..79cf7fa2 --- /dev/null +++ b/code/patterns/doubledispatch/Glass.java @@ -0,0 +1,18 @@ +// patterns/doubledispatch/Glass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Glass for double dispatching +package patterns.doubledispatch; +import patterns.trash.*; +import java.util.*; + +public class Glass extends patterns.trash.Glass + implements TypedBinMember { + public Glass(double wt) { super(wt); } + @Override + public boolean addToBin(List tbins) { + return tbins.stream() + .anyMatch(tb -> tb.add(this)); + } +} diff --git a/code/patterns/doubledispatch/Paper.java b/code/patterns/doubledispatch/Paper.java new file mode 100644 index 00000000..b542dfd6 --- /dev/null +++ b/code/patterns/doubledispatch/Paper.java @@ -0,0 +1,18 @@ +// patterns/doubledispatch/Paper.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Paper for double dispatching +package patterns.doubledispatch; +import patterns.trash.*; +import java.util.*; + +public class Paper extends patterns.trash.Paper + implements TypedBinMember { + public Paper(double wt) { super(wt); } + @Override + public boolean addToBin(List tbins) { + return tbins.stream() + .anyMatch(tb -> tb.add(this)); + } +} diff --git a/code/patterns/doubledispatch/TypedBin.java b/code/patterns/doubledispatch/TypedBin.java new file mode 100644 index 00000000..265874cc --- /dev/null +++ b/code/patterns/doubledispatch/TypedBin.java @@ -0,0 +1,28 @@ +// patterns/doubledispatch/TypedBin.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A List that can grab the right type +package patterns.doubledispatch; +import patterns.trash.*; +import java.util.*; + +public class TypedBin { + List v = new ArrayList<>(); + protected boolean addIt(Trash t) { + v.add(t); + return true; + } + public boolean add(Aluminum a) { + return false; + } + public boolean add(Paper a) { + return false; + } + public boolean add(Glass a) { + return false; + } + public boolean add(Cardboard a) { + return false; + } +} diff --git a/code/patterns/doubledispatch/TypedBinMember.java b/code/patterns/doubledispatch/TypedBinMember.java new file mode 100644 index 00000000..c7ce960a --- /dev/null +++ b/code/patterns/doubledispatch/TypedBinMember.java @@ -0,0 +1,14 @@ +// patterns/doubledispatch/TypedBinMember.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An interface for adding the double dispatching +// method to the trash hierarchy without +// modifying the original hierarchy +package patterns.doubledispatch; +import java.util.*; + +public interface TypedBinMember { + // The new method: + boolean addToBin(List bins); +} diff --git a/code/patterns/dynatrash/DynaTrash.java b/code/patterns/dynatrash/DynaTrash.java new file mode 100644 index 00000000..6ce33d8f --- /dev/null +++ b/code/patterns/dynatrash/DynaTrash.java @@ -0,0 +1,74 @@ +// patterns/dynatrash/DynaTrash.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using a Map of Lists and RTTI to automatically +// sort trash into Lists. This solution, despite +// the use of RTTI, is extensible. +// {java patterns.dynatrash.DynaTrash} +package patterns.dynatrash; +import patterns.trash.*; +import java.util.*; +import java.util.stream.*; + +// Generic TypeMap works in any situation: +class TypeMap { + private Map> t = new HashMap<>(); + public void add(T o) { + Class type = o.getClass(); + if(t.containsKey(type)) + t.get(type).add(o); + else { + List v = new ArrayList<>(); + v.add(o); + t.put(type,v); + } + } + public Stream> values() { + return t.values().stream(); + } +} + +// Adapter class for callbacks +// from ParseTrash.fillBin(): +class TypeMapAdapter implements Fillable { + TypeMap map; + TypeMapAdapter(TypeMap tm) { + map = tm; + } + @Override + public void addTrash(Trash t) { map.add(t); } +} + +public class DynaTrash { + @SuppressWarnings("unchecked") + public static void main(String[] args) { + TypeMap bin = new TypeMap<>(); + ParseTrash.fillBin( + "trash", new TypeMapAdapter(bin)); + bin.values().forEach(Trash::sumValue); + } +} +/* Output: (First and Last 10 Lines) +Loading patterns.trash.Glass +Loading patterns.trash.Paper +Loading patterns.trash.Aluminum +Loading patterns.trash.Cardboard +weight of patterns.trash.Paper = 22.0 +weight of patterns.trash.Paper = 11.0 +weight of patterns.trash.Paper = 88.0 +weight of patterns.trash.Paper = 91.0 +weight of patterns.trash.Paper = 80.0 +weight of patterns.trash.Paper = 66.0 +...________...________...________...________... +weight of patterns.trash.Aluminum = 81.0 +weight of patterns.trash.Aluminum = 36.0 +weight of patterns.trash.Aluminum = 93.0 +weight of patterns.trash.Aluminum = 36.0 +Total value = 860.0499778985977 +weight of patterns.trash.Cardboard = 96.0 +weight of patterns.trash.Cardboard = 44.0 +weight of patterns.trash.Cardboard = 12.0 +weight of patterns.trash.Cardboard = 22.0 +Total value = 40.02000072598457 +*/ diff --git a/code/patterns/observer/ObservedFlower.java b/code/patterns/observer/ObservedFlower.java new file mode 100644 index 00000000..009da63e --- /dev/null +++ b/code/patterns/observer/ObservedFlower.java @@ -0,0 +1,125 @@ +// patterns/observer/ObservedFlower.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of "Observer" pattern +// {java patterns.observer.ObservedFlower} +package patterns.observer; +import java.util.*; + +@SuppressWarnings("deprecation") +class Flower { + private boolean isOpen; + private boolean alreadyOpen; + private boolean alreadyClosed; + Flower() { isOpen = false; } + OpenNotifier opening = new OpenNotifier(); + CloseNotifier closing = new CloseNotifier(); + public void open() { // Opens its petals + isOpen = true; + opening.notifyObservers(); + alreadyClosed = false; + } + public void close() { // Closes its petals + isOpen = false; + closing.notifyObservers(); + alreadyOpen = false; + } + class OpenNotifier extends Observable { + @Override + public void notifyObservers() { + if(isOpen && !alreadyOpen) { + setChanged(); + super.notifyObservers(); + alreadyOpen = true; + } + } + } + class CloseNotifier extends Observable{ + @Override + public void notifyObservers() { + if(!isOpen && !alreadyClosed) { + setChanged(); + super.notifyObservers(); + alreadyClosed = true; + } + } + } +} + +@SuppressWarnings("deprecation") +class Bee { + private String name; + Bee(String nm) { name = nm; } + // Observe openings: + public Observer openObserver() { + return (ob, a) -> System.out.println( + "Bee " + name + "'s breakfast time!"); + } + // Observe closings: + public Observer closeObserver() { + return (ob, a) -> System.out.println( + "Bee " + name + "'s bed time!"); + } +} + +@SuppressWarnings("deprecation") +class Hummingbird { + private String name; + Hummingbird(String nm) { name = nm; } + public Observer openObserver() { + return (ob, a) -> System.out.println( + "Hummingbird " + name + + "'s breakfast time!"); + } + public Observer closeObserver() { + return (ob, a) -> System.out.println( + "Hummingbird " + name + "'s bed time!"); + } +} + +public class ObservedFlower { + public static void main(String[] args) { + Flower f = new Flower(); + Bee + ba = new Bee("A"), + bb = new Bee("B"); + Hummingbird + ha = new Hummingbird("A"), + hb = new Hummingbird("B"); + f.opening.addObserver(ha.openObserver()); + f.opening.addObserver(hb.openObserver()); + f.opening.addObserver(ba.openObserver()); + f.opening.addObserver(bb.openObserver()); + f.closing.addObserver(ha.closeObserver()); + f.closing.addObserver(hb.closeObserver()); + f.closing.addObserver(ba.closeObserver()); + f.closing.addObserver(bb.closeObserver()); + // Hummingbird B decides to sleep in: + f.opening.deleteObserver(hb.openObserver()); + // A change that interests observers: + f.open(); + f.open(); // It's already open, no change. + // Bee A doesn't want to go to bed: + f.closing.deleteObserver(ba.closeObserver()); + f.close(); + f.close(); // It's already closed; no change + f.opening.deleteObservers(); + f.open(); + f.close(); + } +} +/* Output: +Bee B's breakfast time! +Bee A's breakfast time! +Hummingbird B's breakfast time! +Hummingbird A's breakfast time! +Bee B's bed time! +Bee A's bed time! +Hummingbird B's bed time! +Hummingbird A's bed time! +Bee B's bed time! +Bee A's bed time! +Hummingbird B's bed time! +Hummingbird A's bed time! +*/ diff --git a/code/patterns/recyclea/RecycleA.java b/code/patterns/recyclea/RecycleA.java new file mode 100644 index 00000000..a73f39e7 --- /dev/null +++ b/code/patterns/recyclea/RecycleA.java @@ -0,0 +1,127 @@ +// patterns/recyclea/RecycleA.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Recycling with RTTI +// {java patterns.recyclea.RecycleA} +package patterns.recyclea; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +abstract class Trash { + double weight; + Trash(double wt) { weight = wt; } + abstract double value(); + // Sums the value of Trash in a bin: + private static double val; + static void sumValue(List bin) { + val = 0.0f; + bin.forEach( t -> { + // Polymorphism in action: + val += t.weight * t.value(); + System.out.println( + "weight of " + + // Using RTTI to get type + // information about the class: + t.getClass().getSimpleName() + + " = " + t.weight); + }); + System.out.println("Total value = " + val); + } +} + +class Aluminum extends Trash { + static double val = 1.67f; + Aluminum(double wt) { super(wt); } + @Override + double value() { return val; } + static void value(double newval) { + val = newval; + } +} + +class Paper extends Trash { + static double val = 0.10f; + Paper(double wt) { super(wt); } + @Override + double value() { return val; } + static void value(double newval) { + val = newval; + } +} + +class Glass extends Trash { + static double val = 0.23f; + Glass(double wt) { super(wt); } + @Override + double value() { return val; } + static void value(double newval) { + val = newval; + } +} + +class TrashFactory { + static List> ttypes = + Arrays.asList( + Aluminum::new, Paper::new, Glass::new); + static final int SZ = ttypes.size(); + private static SplittableRandom rand = + new SplittableRandom(47); + public static Trash newTrash() { + return ttypes + .get(rand.nextInt(SZ)) + .apply(rand.nextDouble()); + } +} + +public class RecycleA { + public static void main(String[] args) { + List bin = + Stream.generate(TrashFactory::newTrash) + .limit(25) + .collect(Collectors.toList()); + List glassBin = new ArrayList<>(); + List paperBin = new ArrayList<>(); + List alBin = new ArrayList<>(); + // Sort the Trash: + bin.forEach( t -> { + // RTTI to discover Trash type: + if(t instanceof Aluminum) + alBin.add((Aluminum)t); + if(t instanceof Paper) + paperBin.add((Paper)t); + if(t instanceof Glass) + glassBin.add((Glass)t); + }); + Trash.sumValue(alBin); + Trash.sumValue(paperBin); + Trash.sumValue(glassBin); + Trash.sumValue(bin); + } +} +/* Output: (First and Last 11 Lines) +weight of Aluminum = 0.2893030122276371 +weight of Aluminum = 0.1970234961398979 +weight of Aluminum = 0.36295525806274787 +weight of Aluminum = 0.4825532324565849 +weight of Aluminum = 0.8036398273294586 +weight of Aluminum = 0.510430896154935 +weight of Aluminum = 0.6703377164093444 +weight of Aluminum = 0.41477933066243455 +weight of Aluminum = 0.3603022312124007 +weight of Aluminum = 0.43690089841661006 +weight of Aluminum = 0.6708820087907101 +...________...________...________...________... +weight of Aluminum = 0.41477933066243455 +weight of Aluminum = 0.3603022312124007 +weight of Aluminum = 0.43690089841661006 +weight of Glass = 0.5999637765664924 +weight of Glass = 0.7748836191212746 +weight of Paper = 0.5735994548427199 +weight of Glass = 0.5362827750851034 +weight of Aluminum = 0.6708820087907101 +weight of Paper = 0.8370669795210507 +weight of Glass = 0.3397919679731668 +Total value = 9.90671597531968 +*/ diff --git a/code/patterns/recycleb/RecycleB.java b/code/patterns/recycleb/RecycleB.java new file mode 100644 index 00000000..1ca38314 --- /dev/null +++ b/code/patterns/recycleb/RecycleB.java @@ -0,0 +1,56 @@ +// patterns/recycleb/RecycleB.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java patterns.recycleb.RecycleB} +package patterns.recycleb; +import patterns.trash.*; +import java.util.*; + +public class RecycleB { + public static void main(String[] args) { + List bin = new ArrayList<>(); + // Fill up the Trash bin: + ParseTrash.fillBin("trash", bin); + List glassBin = new ArrayList<>(); + List paperBin = new ArrayList<>(); + List alBin = new ArrayList<>(); + // Sort the Trash: + bin.forEach( t -> { + // RTTI to discover Trash type: + if(t instanceof Aluminum) + alBin.add((Aluminum)t); + if(t instanceof Paper) + paperBin.add((Paper)t); + if(t instanceof Glass) + glassBin.add((Glass)t); + }); + Trash.sumValue(alBin); + Trash.sumValue(paperBin); + Trash.sumValue(glassBin); + Trash.sumValue(bin); + } +} +/* Output: (First and Last 10 Lines) +Loading patterns.trash.Glass +Loading patterns.trash.Paper +Loading patterns.trash.Aluminum +Loading patterns.trash.Cardboard +weight of patterns.trash.Aluminum = 89.0 +weight of patterns.trash.Aluminum = 76.0 +weight of patterns.trash.Aluminum = 25.0 +weight of patterns.trash.Aluminum = 34.0 +weight of patterns.trash.Aluminum = 27.0 +weight of patterns.trash.Aluminum = 18.0 +...________...________...________...________... +weight of patterns.trash.Aluminum = 93.0 +weight of patterns.trash.Glass = 93.0 +weight of patterns.trash.Paper = 80.0 +weight of patterns.trash.Glass = 36.0 +weight of patterns.trash.Glass = 12.0 +weight of patterns.trash.Glass = 60.0 +weight of patterns.trash.Paper = 66.0 +weight of patterns.trash.Aluminum = 36.0 +weight of patterns.trash.Cardboard = 22.0 +Total value = 1086.0599818825722 +*/ diff --git a/code/patterns/recyclec/RecycleC.java b/code/patterns/recyclec/RecycleC.java new file mode 100644 index 00000000..239e8e79 --- /dev/null +++ b/code/patterns/recyclec/RecycleC.java @@ -0,0 +1,84 @@ +// patterns/recyclec/RecycleC.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Adding more objects to the recycling problem +// {java patterns.recyclec.RecycleC} +package patterns.recyclec; +import patterns.trash.*; +import java.util.*; + +// A List that admits only the right type: +class Tbin extends ArrayList { + Class binType; + Tbin(Class type) { + binType = type; + } + @SuppressWarnings("unchecked") + boolean grab(Trash t) { + // Comparing class types: + if(t.getClass().equals(binType)) { + add((T)t); // Downcast to this TBin's type + return true; // Object grabbed + } + return false; // Object not grabbed + } +} + +class TbinList +extends ArrayList> { // [1] + boolean sort(T t) { + for(Tbin ts : this) + if(ts.grab(t)) + return true; + return false; // bin not found for t + } + void sortBin(Tbin bin) { // [2] + for(T aBin : bin) + if(!sort(aBin)) + System.err.println("Bin not found"); + } +} + +public class RecycleC { + static Tbin bin = new Tbin<>(Trash.class); + public static void main(String[] args) { + // Fill up the Trash bin: + ParseTrash.fillBin("trash", bin); + + TbinList trashBins = new TbinList<>(); + trashBins.add(new Tbin<>(Aluminum.class)); + trashBins.add(new Tbin<>(Paper.class)); + trashBins.add(new Tbin<>(Glass.class)); + // add one line here: [*3*] + trashBins.add(new Tbin<>(Cardboard.class)); + + trashBins.sortBin(bin); // [4] + + trashBins.forEach(Trash::sumValue); + Trash.sumValue(bin); + } +} +/* Output: (First and Last 10 Lines) +Loading patterns.trash.Glass +Loading patterns.trash.Paper +Loading patterns.trash.Aluminum +Loading patterns.trash.Cardboard +weight of patterns.trash.Aluminum = 89.0 +weight of patterns.trash.Aluminum = 76.0 +weight of patterns.trash.Aluminum = 25.0 +weight of patterns.trash.Aluminum = 34.0 +weight of patterns.trash.Aluminum = 27.0 +weight of patterns.trash.Aluminum = 18.0 +...________...________...________...________... +weight of patterns.trash.Aluminum = 93.0 +weight of patterns.trash.Glass = 93.0 +weight of patterns.trash.Paper = 80.0 +weight of patterns.trash.Glass = 36.0 +weight of patterns.trash.Glass = 12.0 +weight of patterns.trash.Glass = 60.0 +weight of patterns.trash.Paper = 66.0 +weight of patterns.trash.Aluminum = 36.0 +weight of patterns.trash.Cardboard = 22.0 +Total value = 1086.0599818825722 +*/ diff --git a/code/patterns/shapes/BadShapeCreation.java b/code/patterns/shapes/BadShapeCreation.java new file mode 100644 index 00000000..2ebda8e5 --- /dev/null +++ b/code/patterns/shapes/BadShapeCreation.java @@ -0,0 +1,12 @@ +// patterns/shapes/BadShapeCreation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.shapes; + +public class BadShapeCreation +extends RuntimeException { + public BadShapeCreation(String msg) { + super(msg); + } +} diff --git a/code/patterns/shapes/Circle.java b/code/patterns/shapes/Circle.java new file mode 100644 index 00000000..461d55e2 --- /dev/null +++ b/code/patterns/shapes/Circle.java @@ -0,0 +1,7 @@ +// patterns/shapes/Circle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.shapes; + +public class Circle extends Shape {} diff --git a/code/patterns/shapes/FactoryMethod.java b/code/patterns/shapes/FactoryMethod.java new file mode 100644 index 00000000..c3b22b1f --- /dev/null +++ b/code/patterns/shapes/FactoryMethod.java @@ -0,0 +1,9 @@ +// patterns/shapes/FactoryMethod.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.shapes; + +public interface FactoryMethod { + Shape create(String type); +} diff --git a/code/patterns/shapes/FactoryTest.java b/code/patterns/shapes/FactoryTest.java new file mode 100644 index 00000000..301bb1ab --- /dev/null +++ b/code/patterns/shapes/FactoryTest.java @@ -0,0 +1,17 @@ +// patterns/shapes/FactoryTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.shapes; +import java.util.stream.*; + +public class FactoryTest { + public static void test(FactoryMethod factory) { + Stream.of("Circle", "Square", "Triangle", + "Square", "Circle", "Circle", "Triangle") + .map(factory::create) + .peek(Shape::draw) + .peek(Shape::erase) + .count(); // Terminal operation + } +} diff --git a/code/patterns/shapes/Shape.java b/code/patterns/shapes/Shape.java new file mode 100644 index 00000000..12fdf3e7 --- /dev/null +++ b/code/patterns/shapes/Shape.java @@ -0,0 +1,21 @@ +// patterns/shapes/Shape.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.shapes; + +public class Shape { + private static int counter = 0; + private int id = counter++; + @Override + public String toString() { + return + getClass().getSimpleName() + "[" + id + "]"; + } + public void draw() { + System.out.println(this + " draw"); + } + public void erase() { + System.out.println(this + " erase"); + } +} diff --git a/code/patterns/shapes/Square.java b/code/patterns/shapes/Square.java new file mode 100644 index 00000000..610dd3e4 --- /dev/null +++ b/code/patterns/shapes/Square.java @@ -0,0 +1,7 @@ +// patterns/shapes/Square.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.shapes; + +public class Square extends Shape {} diff --git a/code/patterns/shapes/Triangle.java b/code/patterns/shapes/Triangle.java new file mode 100644 index 00000000..9fed3d93 --- /dev/null +++ b/code/patterns/shapes/Triangle.java @@ -0,0 +1,7 @@ +// patterns/shapes/Triangle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.shapes; + +public class Triangle extends Shape {} diff --git a/code/patterns/state/StateMachineDemo.java b/code/patterns/state/StateMachineDemo.java new file mode 100644 index 00000000..29f8a876 --- /dev/null +++ b/code/patterns/state/StateMachineDemo.java @@ -0,0 +1,80 @@ +// patterns/state/StateMachineDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The StateMachine pattern and Template method +// {java patterns.state.StateMachineDemo} +package patterns.state; +import onjava.Nap; + +interface State { + void run(); +} + +abstract class StateMachine { + protected State currentState; + protected abstract boolean changeState(); + // Template method: + protected final void runAll() { + while(changeState()) // Customizable + currentState.run(); + } +} + +// A different subclass for each state: + +class Wash implements State { + @Override + public void run() { + System.out.println("Washing"); + new Nap(0.5); + } +} + +class Spin implements State { + @Override + public void run() { + System.out.println("Spinning"); + new Nap(0.5); + } +} + +class Rinse implements State { + @Override + public void run() { + System.out.println("Rinsing"); + new Nap(0.5); + } +} + +class Washer extends StateMachine { + private int i = 0; + // The state table: + private State[] states = { + new Wash(), new Spin(), + new Rinse(), new Spin(), + }; + Washer() { runAll(); } + @Override + public boolean changeState() { + if(i < states.length) { + // Change the state by setting the + // surrogate reference to a new object: + currentState = states[i++]; + return true; + } else + return false; + } +} + +public class StateMachineDemo { + public static void main(String[] args) { + new Washer(); + } +} +/* Output: +Washing +Spinning +Rinsing +Spinning +*/ diff --git a/code/patterns/strategy/StrategyPattern.java b/code/patterns/strategy/StrategyPattern.java new file mode 100644 index 00000000..52561b4b --- /dev/null +++ b/code/patterns/strategy/StrategyPattern.java @@ -0,0 +1,64 @@ +// patterns/strategy/StrategyPattern.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java patterns.strategy.StrategyPattern} +package patterns.strategy; +import java.util.function.*; +import java.util.*; + +// The common strategy base type: +class FindMinima { + Function, List> algorithm; +} + +// The various strategies: +class LeastSquares extends FindMinima { + LeastSquares() { + // Line is a sequence of points (Dummy data): + algorithm = (line) -> Arrays.asList(1.1, 2.2); + } +} + +class Perturbation extends FindMinima { + Perturbation() { + algorithm = (line) -> Arrays.asList(3.3, 4.4); + } +} + +class Bisection extends FindMinima { + Bisection() { + algorithm = (line) -> Arrays.asList(5.5, 6.6); + } +} + +// The "Context" controls the strategy: +class MinimaSolver { + private FindMinima strategy; + MinimaSolver(FindMinima strat) { + strategy = strat; + } + List minima(List line) { + return strategy.algorithm.apply(line); + } + void changeAlgorithm(FindMinima newAlgorithm) { + strategy = newAlgorithm; + } +} + +public class StrategyPattern { + public static void main(String[] args) { + MinimaSolver solver = + new MinimaSolver(new LeastSquares()); + List line = Arrays.asList( + 1.0, 2.0, 1.0, 2.0, -1.0, + 3.0, 4.0, 5.0, 4.0 ); + System.out.println(solver.minima(line)); + solver.changeAlgorithm(new Bisection()); + System.out.println(solver.minima(line)); + } +} +/* Output: +[1.1, 2.2] +[5.5, 6.6] +*/ diff --git a/code/patterns/strategy/StrategyPattern2.java b/code/patterns/strategy/StrategyPattern2.java new file mode 100644 index 00000000..09465f3a --- /dev/null +++ b/code/patterns/strategy/StrategyPattern2.java @@ -0,0 +1,43 @@ +// patterns/strategy/StrategyPattern2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java patterns.strategy.StrategyPattern2} +package patterns.strategy; +import java.util.function.*; +import java.util.*; + +// "Context" is now incorporated: +class FindMinima2 { + Function, List> algorithm; + FindMinima2() { leastSquares(); } // default + // The various strategies: + void leastSquares() { + algorithm = (line) -> Arrays.asList(1.1, 2.2); + } + void perturbation() { + algorithm = (line) -> Arrays.asList(3.3, 4.4); + } + void bisection() { + algorithm = (line) -> Arrays.asList(5.5, 6.6); + } + List minima(List line) { + return algorithm.apply(line); + } +} + +public class StrategyPattern2 { + public static void main(String[] args) { + FindMinima2 solver = new FindMinima2(); + List line = Arrays.asList( + 1.0, 2.0, 1.0, 2.0, -1.0, + 3.0, 4.0, 5.0, 4.0 ); + System.out.println(solver.minima(line)); + solver.bisection(); + System.out.println(solver.minima(line)); + } +} +/* Output: +[1.1, 2.2] +[5.5, 6.6] +*/ diff --git a/code/patterns/trash/Aluminum.java b/code/patterns/trash/Aluminum.java new file mode 100644 index 00000000..0065e964 --- /dev/null +++ b/code/patterns/trash/Aluminum.java @@ -0,0 +1,15 @@ +// patterns/trash/Aluminum.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.trash; + +public class Aluminum extends Trash { + private static double val = 1.67f; + public Aluminum(double wt) { super(wt); } + @Override + public double value() { return val; } + public static void value(double newVal) { + val = newVal; + } +} diff --git a/code/patterns/trash/Cardboard.java b/code/patterns/trash/Cardboard.java new file mode 100644 index 00000000..0b54d135 --- /dev/null +++ b/code/patterns/trash/Cardboard.java @@ -0,0 +1,15 @@ +// patterns/trash/Cardboard.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.trash; + +public class Cardboard extends Trash { + private static double val = 0.23f; + public Cardboard(double wt) { super(wt); } + @Override + public double value() { return val; } + public static void value(double newVal) { + val = newVal; + } +} diff --git a/code/patterns/trash/Fillable.java b/code/patterns/trash/Fillable.java new file mode 100644 index 00000000..a61cb111 --- /dev/null +++ b/code/patterns/trash/Fillable.java @@ -0,0 +1,10 @@ +// patterns/trash/Fillable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Any object that can be filled with Trash +package patterns.trash; + +public interface Fillable { + void addTrash(T t); +} diff --git a/code/patterns/trash/FillableList.java b/code/patterns/trash/FillableList.java new file mode 100644 index 00000000..989a33ec --- /dev/null +++ b/code/patterns/trash/FillableList.java @@ -0,0 +1,17 @@ +// patterns/trash/FillableList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Adapter that makes a List Fillable +package patterns.trash; +import java.util.*; + +public class FillableList +implements Fillable { + private List v; + public FillableList(List vv) { + v = vv; + } + @Override + public void addTrash(T t) { v.add(t); } +} diff --git a/code/patterns/trash/Glass.java b/code/patterns/trash/Glass.java new file mode 100644 index 00000000..f7563dc4 --- /dev/null +++ b/code/patterns/trash/Glass.java @@ -0,0 +1,15 @@ +// patterns/trash/Glass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.trash; + +public class Glass extends Trash { + private static double val = 0.23f; + public Glass(double wt) { super(wt); } + @Override + public double value() { return val; } + public static void value(double newVal) { + val = newVal; + } +} diff --git a/code/patterns/trash/Paper.java b/code/patterns/trash/Paper.java new file mode 100644 index 00000000..2f0b3666 --- /dev/null +++ b/code/patterns/trash/Paper.java @@ -0,0 +1,15 @@ +// patterns/trash/Paper.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package patterns.trash; + +public class Paper extends Trash { + private static double val = 0.10f; + public Paper(double wt) { super(wt); } + @Override + public double value() { return val; } + public static void value(double newVal) { + val = newVal; + } +} diff --git a/code/patterns/trash/ParseTrash.java b/code/patterns/trash/ParseTrash.java new file mode 100644 index 00000000..fc0c0416 --- /dev/null +++ b/code/patterns/trash/ParseTrash.java @@ -0,0 +1,91 @@ +// patterns/trash/ParseTrash.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Open a file and parse its contents into +// Trash objects, placing each into a List +// {java patterns.trash.ParseTrash} +package patterns.trash; +import java.util.*; +import java.util.stream.*; +import java.io.*; +import java.nio.file.*; +import java.nio.file.Files; + +public class ParseTrash { + public static void + fillBin(String pckg, Fillable bin) { + try { + Files.lines(Paths.get("trash", "Trash.dat")) + // Remove empty lines and comment lines: + .filter(line -> line.trim().length() != 0) + .filter(line -> !line.startsWith("//")) + .forEach( line -> { + String type = "patterns." + pckg + "." + + line.substring( + 0, line.indexOf(':')).trim(); + double weight = Double.valueOf( + line.substring(line.indexOf(':') + 1) + .trim()); + bin.addTrash(Trash.factory( + new Trash.Info(type, weight))); + }); + } catch(IOException | + NumberFormatException | + Trash.TrashClassNotFoundException | + Trash.CannotCreateTrashException e) { + throw new RuntimeException(e); + } + } + // Special case to handle List: + public static void + fillBin(String pckg, List bin) { + fillBin(pckg, new FillableList<>(bin)); + } + // Basic test: + public static void main(String[] args) { + List t = new ArrayList<>(); + fillBin("trash", t); + t.forEach(System.out::println); + } +} +/* Output: +Loading patterns.trash.Glass +Loading patterns.trash.Paper +Loading patterns.trash.Aluminum +Loading patterns.trash.Cardboard +patterns.trash.Glass w:54.0 v:0.23 +patterns.trash.Paper w:22.0 v:0.10 +patterns.trash.Paper w:11.0 v:0.10 +patterns.trash.Glass w:17.0 v:0.23 +patterns.trash.Aluminum w:89.0 v:1.67 +patterns.trash.Paper w:88.0 v:0.10 +patterns.trash.Aluminum w:76.0 v:1.67 +patterns.trash.Cardboard w:96.0 v:0.23 +patterns.trash.Aluminum w:25.0 v:1.67 +patterns.trash.Aluminum w:34.0 v:1.67 +patterns.trash.Glass w:11.0 v:0.23 +patterns.trash.Glass w:68.0 v:0.23 +patterns.trash.Glass w:43.0 v:0.23 +patterns.trash.Aluminum w:27.0 v:1.67 +patterns.trash.Cardboard w:44.0 v:0.23 +patterns.trash.Aluminum w:18.0 v:1.67 +patterns.trash.Paper w:91.0 v:0.10 +patterns.trash.Glass w:63.0 v:0.23 +patterns.trash.Glass w:50.0 v:0.23 +patterns.trash.Glass w:80.0 v:0.23 +patterns.trash.Aluminum w:81.0 v:1.67 +patterns.trash.Cardboard w:12.0 v:0.23 +patterns.trash.Glass w:12.0 v:0.23 +patterns.trash.Glass w:54.0 v:0.23 +patterns.trash.Aluminum w:36.0 v:1.67 +patterns.trash.Aluminum w:93.0 v:1.67 +patterns.trash.Glass w:93.0 v:0.23 +patterns.trash.Paper w:80.0 v:0.10 +patterns.trash.Glass w:36.0 v:0.23 +patterns.trash.Glass w:12.0 v:0.23 +patterns.trash.Glass w:60.0 v:0.23 +patterns.trash.Paper w:66.0 v:0.10 +patterns.trash.Aluminum w:36.0 v:1.67 +patterns.trash.Cardboard w:22.0 v:0.23 +*/ diff --git a/code/patterns/trash/Trash.dat b/code/patterns/trash/Trash.dat new file mode 100644 index 00000000..436a7a71 --- /dev/null +++ b/code/patterns/trash/Trash.dat @@ -0,0 +1,35 @@ +// patterns/trash/Trash.dat +Glass:54 +Paper:22 +Paper:11 +Glass:17 +Aluminum:89 +Paper:88 +Aluminum:76 +Cardboard:96 +Aluminum:25 +Aluminum:34 +Glass:11 +Glass:68 +Glass:43 +Aluminum:27 +Cardboard:44 +Aluminum:18 +Paper:91 +Glass:63 +Glass:50 +Glass:80 +Aluminum:81 +Cardboard:12 +Glass:12 +Glass:54 +Aluminum:36 +Aluminum:93 +Glass:93 +Paper:80 +Glass:36 +Glass:12 +Glass:60 +Paper:66 +Aluminum:36 +Cardboard:22 diff --git a/code/patterns/trash/Trash.java b/code/patterns/trash/Trash.java new file mode 100644 index 00000000..7d01de8c --- /dev/null +++ b/code/patterns/trash/Trash.java @@ -0,0 +1,92 @@ +// patterns/trash/Trash.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Base class for Trash recycling examples +package patterns.trash; +import java.util.*; +import java.lang.reflect.*; + +public abstract class Trash { + private double weight; + public Trash(double wt) { weight = wt; } + public Trash() {} + public abstract double value(); + public double weight() { return weight; } + // Sums the value of Trash in a bin: + static double val; + public static + void sumValue(List bin) { + val = 0.0f; + bin.forEach( t -> { + val += t.weight() * t.value(); + System.out.println("weight of " + + // RTTI gets type information + // about the class: + t.getClass().getName() + + " = " + t.weight()); + }); + System.out.println("Total value = " + val); + } + @Override + public String toString() { + // Print correct subclass name: + return getClass().getName() + + " w:" + weight() + " v:" + + String.format("%.2f", value()); + } + // Remainder of class supports dynamic creation: + public static class CannotCreateTrashException + extends RuntimeException { + public CannotCreateTrashException(Exception why) { + super(why); + } + } + public static class TrashClassNotFoundException + extends RuntimeException { + public TrashClassNotFoundException(Exception why) { + super(why); + } + } + public static class Info { + public String id; + public double data; + public Info(String name, double data) { + id = name; + this.data = data; + } + } + private static List trashTypes = + new ArrayList<>(); + @SuppressWarnings("unchecked") + public static T factory(Info info) { + for(Class trashType : trashTypes) { + // Determine the type and create one: + if(trashType.getName().contains(info.id)) { + try { + // Get the dynamic constructor method + // that takes a double argument: + Constructor ctor = + trashType.getConstructor(double.class); + // Call the constructor to create a + // new object: + return + (T)ctor.newInstance(info.data); + } catch(Exception e) { + throw new CannotCreateTrashException(e); + } + } + } + // The necessary Class was not in the list. Try to + // load it, but it must be in your class path! + try { + System.out.println("Loading " + info.id); + trashTypes.add(Class.forName(info.id)); + } catch(Exception e) { + throw new TrashClassNotFoundException(e); + } + // Loaded successfully. Recursive call + // should work this time: + return factory(info); + } +} diff --git a/code/patterns/trashvisitor/Aluminum.java b/code/patterns/trashvisitor/Aluminum.java new file mode 100644 index 00000000..85d5fa14 --- /dev/null +++ b/code/patterns/trashvisitor/Aluminum.java @@ -0,0 +1,16 @@ +// patterns/trashvisitor/Aluminum.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Aluminum for the visitor pattern +package patterns.trashvisitor; +import patterns.trash.*; + +public class Aluminum extends patterns.trash.Aluminum + implements Visitable { + public Aluminum(double wt) { super(wt); } + @Override + public void accept(Visitor v) { + v.visit(this); + } +} diff --git a/code/patterns/trashvisitor/Cardboard.java b/code/patterns/trashvisitor/Cardboard.java new file mode 100644 index 00000000..978202ef --- /dev/null +++ b/code/patterns/trashvisitor/Cardboard.java @@ -0,0 +1,16 @@ +// patterns/trashvisitor/Cardboard.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Cardboard for the visitor pattern +package patterns.trashvisitor; +import patterns.trash.*; + +public class Cardboard extends patterns.trash.Cardboard + implements Visitable { + public Cardboard(double wt) { super(wt); } + @Override + public void accept(Visitor v) { + v.visit(this); + } +} diff --git a/code/patterns/trashvisitor/Glass.java b/code/patterns/trashvisitor/Glass.java new file mode 100644 index 00000000..fbcf4949 --- /dev/null +++ b/code/patterns/trashvisitor/Glass.java @@ -0,0 +1,16 @@ +// patterns/trashvisitor/Glass.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Glass for the visitor pattern +package patterns.trashvisitor; +import patterns.trash.*; + +public class Glass extends patterns.trash.Glass + implements Visitable { + public Glass(double wt) { super(wt); } + @Override + public void accept(Visitor v) { + v.visit(this); + } +} diff --git a/code/patterns/trashvisitor/Paper.java b/code/patterns/trashvisitor/Paper.java new file mode 100644 index 00000000..6e9999f1 --- /dev/null +++ b/code/patterns/trashvisitor/Paper.java @@ -0,0 +1,16 @@ +// patterns/trashvisitor/Paper.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Paper for the visitor pattern +package patterns.trashvisitor; +import patterns.trash.*; + +public class Paper extends patterns.trash.Paper + implements Visitable { + public Paper(double wt) { super(wt); } + @Override + public void accept(Visitor v) { + v.visit(this); + } +} diff --git a/code/patterns/trashvisitor/TrashVisitor.java b/code/patterns/trashvisitor/TrashVisitor.java new file mode 100644 index 00000000..8f956623 --- /dev/null +++ b/code/patterns/trashvisitor/TrashVisitor.java @@ -0,0 +1,127 @@ +// patterns/trashvisitor/TrashVisitor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java patterns.trashvisitor.TrashVisitor} +package patterns.trashvisitor; +import patterns.trash.*; +import java.util.*; + +// Specific group of algorithms packaged +// in each implementation of Visitor: +class PriceVisitor implements Visitor { + private double alSum; // Aluminum + private double pSum; // Paper + private double gSum; // Glass + private double cSum; // Cardboard + public static void show(String s) { + System.out.println(s); + } + @Override + public void visit(Aluminum al) { + double v = al.weight() * al.value(); + show("value of Aluminum= " + v); + alSum += v; + } + @Override + public void visit(Paper p) { + double v = p.weight() * p.value(); + show("value of Paper= " + v); + pSum += v; + } + @Override + public void visit(Glass g) { + double v = g.weight() * g.value(); + show("value of Glass= " + v); + gSum += v; + } + @Override + public void visit(Cardboard c) { + double v = c.weight() * c.value(); + show("value of Cardboard = " + v); + cSum += v; + } + @Override + public void total() { + show( + "Total Aluminum: $" + alSum + "\n" + + "Total Paper: $" + pSum + "\n" + + "Total Glass: $" + gSum + "\n" + + "Total Cardboard: $" + cSum); + } +} + +class WeightVisitor implements Visitor { + private double alSum; // Aluminum + private double pSum; // Paper + private double gSum; // Glass + private double cSum; // Cardboard + public static void show(String s) { + System.out.println(s); + } + @Override + public void visit(Aluminum al) { + alSum += al.weight(); + show("Aluminum weight = " + al.weight()); + } + @Override + public void visit(Paper p) { + pSum += p.weight(); + show("Paper weight = " + p.weight()); + } + @Override + public void visit(Glass g) { + gSum += g.weight(); + show("Glass weight = " + g.weight()); + } + @Override + public void visit(Cardboard c) { + cSum += c.weight(); + show("Cardboard weight = " + c.weight()); + } + @Override + public void total() { + show("Total weight Aluminum:" + alSum); + show("Total weight Paper:" + pSum); + show("Total weight Glass:" + gSum); + show("Total weight Cardboard:" + cSum); + } +} + +public class TrashVisitor { + public static void main(String[] args) { + List bin = new ArrayList<>(); + // ParseTrash still works, without changes: + ParseTrash.fillBin("trashvisitor", bin); + List visitors = Arrays.asList( + new PriceVisitor(), new WeightVisitor()); + bin.forEach( t -> { + Visitable v = (Visitable) t; + visitors.forEach(visitor -> v.accept(visitor)); + }); + visitors.forEach(Visitor::total); + } +} +/* Output: (First and Last 10 Lines) +Loading patterns.trashvisitor.Glass +Loading patterns.trashvisitor.Paper +Loading patterns.trashvisitor.Aluminum +Loading patterns.trashvisitor.Cardboard +value of Glass= 12.420000225305557 +Glass weight = 54.0 +value of Paper= 2.2000000327825546 +Paper weight = 22.0 +value of Paper= 1.1000000163912773 +Paper weight = 11.0 +...________...________...________...________... +value of Cardboard = 5.060000091791153 +Cardboard weight = 22.0 +Total Aluminum: $860.0499778985977 +Total Paper: $35.80000053346157 +Total Glass: $150.1900027245283 +Total Cardboard: $40.02000072598457 +Total weight Aluminum:515.0 +Total weight Paper:358.0 +Total weight Glass:653.0 +Total weight Cardboard:174.0 +*/ diff --git a/code/patterns/trashvisitor/Visitable.java b/code/patterns/trashvisitor/Visitable.java new file mode 100644 index 00000000..f1f9f1da --- /dev/null +++ b/code/patterns/trashvisitor/Visitable.java @@ -0,0 +1,12 @@ +// patterns/trashvisitor/Visitable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An interface to add visitor functionality to the +// Trash hierarchy without modifying the base class +package patterns.trashvisitor; + +public interface Visitable { + // The new method: + void accept(Visitor v); +} diff --git a/code/patterns/trashvisitor/Visitor.java b/code/patterns/trashvisitor/Visitor.java new file mode 100644 index 00000000..07ef4622 --- /dev/null +++ b/code/patterns/trashvisitor/Visitor.java @@ -0,0 +1,14 @@ +// patterns/trashvisitor/Visitor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The base interface for visitors +package patterns.trashvisitor; + +public interface Visitor { + void visit(Aluminum a); + void visit(Paper p); + void visit(Glass g); + void visit(Cardboard c); + void total(); +} diff --git a/code/patterns/visitor/BeeAndFlowers.java b/code/patterns/visitor/BeeAndFlowers.java new file mode 100644 index 00000000..aa86ebfc --- /dev/null +++ b/code/patterns/visitor/BeeAndFlowers.java @@ -0,0 +1,122 @@ +// patterns/visitor/BeeAndFlowers.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of "visitor" pattern +// {java patterns.visitor.BeeAndFlowers} +package patterns.visitor; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +interface Visitor { + void visit(Gladiolus g); + void visit(Renuculus r); + void visit(Chrysanthemum c); +} + +// The Flower hierarchy cannot be changed: +interface Flower { + void accept(Visitor v); +} + +class Gladiolus implements Flower { + @Override + public void accept(Visitor v) { v.visit(this);} +} + +class Renuculus implements Flower { + @Override + public void accept(Visitor v) { v.visit(this);} +} + +class Chrysanthemum implements Flower { + @Override + public void accept(Visitor v) { v.visit(this);} +} + +// Add the ability to produce a String: +class StringVal implements Visitor { + String s; + @Override + public String toString() { return s; } + @Override + public void visit(Gladiolus g) { + s = "Gladiolus"; + } + @Override + public void visit(Renuculus r) { + s = "Renuculus"; + } + @Override + public void visit(Chrysanthemum c) { + s = "Chrysanthemum"; + } +} + +// Add the ability to do "Bee" activities: +class Bee implements Visitor { + @Override + public void visit(Gladiolus g) { + System.out.println("Bee and Gladiolus"); + } + @Override + public void visit(Renuculus r) { + System.out.println("Bee and Renuculus"); + } + @Override + public void visit(Chrysanthemum c) { + System.out.println("Bee and Chrysanthemum"); + } +} + +class FlowerFactory { + static List> flowers = + Arrays.asList(Gladiolus::new, + Renuculus::new, Chrysanthemum::new); + static final int SZ = flowers.size(); + private static SplittableRandom rand = + new SplittableRandom(47); + public static Flower newFlower() { + return flowers.get(rand.nextInt(SZ)).get(); + } +} + +public class BeeAndFlowers { + public static void main(String[] args) { + List flowers = + Stream.generate(FlowerFactory::newFlower) + .limit(10) + .collect(Collectors.toList()); + StringVal sval = new StringVal(); + flowers.forEach(f -> { + f.accept(sval); + System.out.println(sval); + }); + // Perform "Bee" operation on all Flowers: + Bee bee = new Bee(); + flowers.forEach(f -> f.accept(bee)); + } +} +/* Output: +Gladiolus +Chrysanthemum +Gladiolus +Renuculus +Chrysanthemum +Renuculus +Chrysanthemum +Chrysanthemum +Chrysanthemum +Renuculus +Bee and Gladiolus +Bee and Chrysanthemum +Bee and Gladiolus +Bee and Renuculus +Bee and Chrysanthemum +Bee and Renuculus +Bee and Chrysanthemum +Bee and Chrysanthemum +Bee and Chrysanthemum +Bee and Renuculus +*/ diff --git a/code/polymorphism/CovariantReturn.java b/code/polymorphism/CovariantReturn.java new file mode 100644 index 00000000..e88fe590 --- /dev/null +++ b/code/polymorphism/CovariantReturn.java @@ -0,0 +1,38 @@ +// polymorphism/CovariantReturn.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Grain { + @Override + public String toString() { return "Grain"; } +} + +class Wheat extends Grain { + @Override + public String toString() { return "Wheat"; } +} + +class Mill { + Grain process() { return new Grain(); } +} + +class WheatMill extends Mill { + @Override + Wheat process() { return new Wheat(); } +} + +public class CovariantReturn { + public static void main(String[] args) { + Mill m = new Mill(); + Grain g = m.process(); + System.out.println(g); + m = new WheatMill(); + g = m.process(); + System.out.println(g); + } +} +/* Output: +Grain +Wheat +*/ diff --git a/code/polymorphism/FieldAccess.java b/code/polymorphism/FieldAccess.java new file mode 100644 index 00000000..95e47c5e --- /dev/null +++ b/code/polymorphism/FieldAccess.java @@ -0,0 +1,36 @@ +// polymorphism/FieldAccess.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Direct field access is determined at compile time + +class Super { + public int field = 0; + public int getField() { return field; } +} + +class Sub extends Super { + public int field = 1; + @Override + public int getField() { return field; } + public int getSuperField() { return super.field; } +} + +public class FieldAccess { + public static void main(String[] args) { + Super sup = new Sub(); // Upcast + System.out.println("sup.field = " + sup.field + + ", sup.getField() = " + sup.getField()); + Sub sub = new Sub(); + System.out.println("sub.field = " + + sub.field + ", sub.getField() = " + + sub.getField() + + ", sub.getSuperField() = " + + sub.getSuperField()); + } +} +/* Output: +sup.field = 0, sup.getField() = 1 +sub.field = 1, sub.getField() = 1, sub.getSuperField() += 0 +*/ diff --git a/code/polymorphism/Frog.java b/code/polymorphism/Frog.java new file mode 100644 index 00000000..9226910d --- /dev/null +++ b/code/polymorphism/Frog.java @@ -0,0 +1,122 @@ +// polymorphism/Frog.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Cleanup and inheritance +// {java polymorphism.Frog} +package polymorphism; + +class Characteristic { + private String s; + Characteristic(String s) { + this.s = s; + System.out.println("Creating Characteristic " + s); + } + protected void dispose() { + System.out.println("disposing Characteristic " + s); + } +} + +class Description { + private String s; + Description(String s) { + this.s = s; + System.out.println("Creating Description " + s); + } + protected void dispose() { + System.out.println("disposing Description " + s); + } +} + +class LivingCreature { + private Characteristic p = + new Characteristic("is alive"); + private Description t = + new Description("Basic Living Creature"); + LivingCreature() { + System.out.println("LivingCreature()"); + } + protected void dispose() { + System.out.println("LivingCreature dispose"); + t.dispose(); + p.dispose(); + } +} + +class Animal extends LivingCreature { + private Characteristic p = + new Characteristic("has heart"); + private Description t = + new Description("Animal not Vegetable"); + Animal() { System.out.println("Animal()"); } + @Override + protected void dispose() { + System.out.println("Animal dispose"); + t.dispose(); + p.dispose(); + super.dispose(); + } +} + +class Amphibian extends Animal { + private Characteristic p = + new Characteristic("can live in water"); + private Description t = + new Description("Both water and land"); + Amphibian() { + System.out.println("Amphibian()"); + } + @Override + protected void dispose() { + System.out.println("Amphibian dispose"); + t.dispose(); + p.dispose(); + super.dispose(); + } +} + +public class Frog extends Amphibian { + private Characteristic p = + new Characteristic("Croaks"); + private Description t = new Description("Eats Bugs"); + public Frog() { System.out.println("Frog()"); } + @Override + protected void dispose() { + System.out.println("Frog dispose"); + t.dispose(); + p.dispose(); + super.dispose(); + } + public static void main(String[] args) { + Frog frog = new Frog(); + System.out.println("Bye!"); + frog.dispose(); + } +} +/* Output: +Creating Characteristic is alive +Creating Description Basic Living Creature +LivingCreature() +Creating Characteristic has heart +Creating Description Animal not Vegetable +Animal() +Creating Characteristic can live in water +Creating Description Both water and land +Amphibian() +Creating Characteristic Croaks +Creating Description Eats Bugs +Frog() +Bye! +Frog dispose +disposing Description Eats Bugs +disposing Characteristic Croaks +Amphibian dispose +disposing Description Both water and land +disposing Characteristic can live in water +Animal dispose +disposing Description Animal not Vegetable +disposing Characteristic has heart +LivingCreature dispose +disposing Description Basic Living Creature +disposing Characteristic is alive +*/ diff --git a/code/polymorphism/PolyConstructors.java b/code/polymorphism/PolyConstructors.java new file mode 100644 index 00000000..3a99f08b --- /dev/null +++ b/code/polymorphism/PolyConstructors.java @@ -0,0 +1,41 @@ +// polymorphism/PolyConstructors.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Constructors and polymorphism +// don't produce what you might expect + +class Glyph { + void draw() { System.out.println("Glyph.draw()"); } + Glyph() { + System.out.println("Glyph() before draw()"); + draw(); + System.out.println("Glyph() after draw()"); + } +} + +class RoundGlyph extends Glyph { + private int radius = 1; + RoundGlyph(int r) { + radius = r; + System.out.println( + "RoundGlyph.RoundGlyph(), radius = " + radius); + } + @Override + void draw() { + System.out.println( + "RoundGlyph.draw(), radius = " + radius); + } +} + +public class PolyConstructors { + public static void main(String[] args) { + new RoundGlyph(5); + } +} +/* Output: +Glyph() before draw() +RoundGlyph.draw(), radius = 0 +Glyph() after draw() +RoundGlyph.RoundGlyph(), radius = 5 +*/ diff --git a/code/polymorphism/PrivateOverride.java b/code/polymorphism/PrivateOverride.java new file mode 100644 index 00000000..9873e03d --- /dev/null +++ b/code/polymorphism/PrivateOverride.java @@ -0,0 +1,24 @@ +// polymorphism/PrivateOverride.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Trying to override a private method +// {java polymorphism.PrivateOverride} +package polymorphism; + +public class PrivateOverride { + private void f() { + System.out.println("private f()"); + } + public static void main(String[] args) { + PrivateOverride po = new Derived(); + po.f(); + } +} + +class Derived extends PrivateOverride { + public void f() { System.out.println("public f()"); } +} +/* Output: +private f() +*/ diff --git a/code/polymorphism/PrivateOverride2.java b/code/polymorphism/PrivateOverride2.java new file mode 100644 index 00000000..664672bc --- /dev/null +++ b/code/polymorphism/PrivateOverride2.java @@ -0,0 +1,22 @@ +// polymorphism/PrivateOverride2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Detecting a mistaken override using @Override +// {WillNotCompile} +package polymorphism; + +public class PrivateOverride2 { + private void f() { + System.out.println("private f()"); + } + public static void main(String[] args) { + PrivateOverride2 po = new Derived2(); + po.f(); + } +} + +class Derived2 extends PrivateOverride2 { + @Override + public void f() { System.out.println("public f()"); } +} diff --git a/code/polymorphism/RTTI.java b/code/polymorphism/RTTI.java new file mode 100644 index 00000000..39c9029b --- /dev/null +++ b/code/polymorphism/RTTI.java @@ -0,0 +1,43 @@ +// polymorphism/RTTI.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Downcasting & Runtime type information (RTTI) +// {ThrowsException} + +class Useful { + public void f() {} + public void g() {} +} + +class MoreUseful extends Useful { + @Override + public void f() {} + @Override + public void g() {} + public void u() {} + public void v() {} + public void w() {} +} + +public class RTTI { + public static void main(String[] args) { + Useful[] x = { + new Useful(), + new MoreUseful() + }; + x[0].f(); + x[1].g(); + // Compile time: method not found in Useful: + //- x[1].u(); + ((MoreUseful)x[1]).u(); // Downcast/RTTI + ((MoreUseful)x[0]).u(); // Exception thrown + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "main" +java.lang.ClassCastException: Useful cannot be cast to +MoreUseful + at RTTI.main(RTTI.java:31) +*/ diff --git a/code/polymorphism/ReferenceCounting.java b/code/polymorphism/ReferenceCounting.java new file mode 100644 index 00000000..b378117f --- /dev/null +++ b/code/polymorphism/ReferenceCounting.java @@ -0,0 +1,71 @@ +// polymorphism/ReferenceCounting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Cleaning up shared member objects + +class Shared { + private int refcount = 0; + private static long counter = 0; + private final long id = counter++; + Shared() { + System.out.println("Creating " + this); + } + public void addRef() { refcount++; } + protected void dispose() { + if(--refcount == 0) + System.out.println("Disposing " + this); + } + @Override + public String toString() { + return "Shared " + id; + } +} + +class Composing { + private Shared shared; + private static long counter = 0; + private final long id = counter++; + Composing(Shared shared) { + System.out.println("Creating " + this); + this.shared = shared; + this.shared.addRef(); + } + protected void dispose() { + System.out.println("disposing " + this); + shared.dispose(); + } + @Override + public String toString() { + return "Composing " + id; + } +} + +public class ReferenceCounting { + public static void main(String[] args) { + Shared shared = new Shared(); + Composing[] composing = { + new Composing(shared), + new Composing(shared), + new Composing(shared), + new Composing(shared), + new Composing(shared) + }; + for(Composing c : composing) + c.dispose(); + } +} +/* Output: +Creating Shared 0 +Creating Composing 0 +Creating Composing 1 +Creating Composing 2 +Creating Composing 3 +Creating Composing 4 +disposing Composing 0 +disposing Composing 1 +disposing Composing 2 +disposing Composing 3 +disposing Composing 4 +Disposing Shared 0 +*/ diff --git a/code/polymorphism/Sandwich.java b/code/polymorphism/Sandwich.java new file mode 100644 index 00000000..97f80d53 --- /dev/null +++ b/code/polymorphism/Sandwich.java @@ -0,0 +1,54 @@ +// polymorphism/Sandwich.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Order of constructor calls +// {java polymorphism.Sandwich} +package polymorphism; + +class Meal { + Meal() { System.out.println("Meal()"); } +} + +class Bread { + Bread() { System.out.println("Bread()"); } +} + +class Cheese { + Cheese() { System.out.println("Cheese()"); } +} + +class Lettuce { + Lettuce() { System.out.println("Lettuce()"); } +} + +class Lunch extends Meal { + Lunch() { System.out.println("Lunch()"); } +} + +class PortableLunch extends Lunch { + PortableLunch() { + System.out.println("PortableLunch()"); + } +} + +public class Sandwich extends PortableLunch { + private Bread b = new Bread(); + private Cheese c = new Cheese(); + private Lettuce l = new Lettuce(); + public Sandwich() { + System.out.println("Sandwich()"); + } + public static void main(String[] args) { + new Sandwich(); + } +} +/* Output: +Meal() +Lunch() +PortableLunch() +Bread() +Cheese() +Lettuce() +Sandwich() +*/ diff --git a/code/polymorphism/Shapes.java b/code/polymorphism/Shapes.java new file mode 100644 index 00000000..4d051e70 --- /dev/null +++ b/code/polymorphism/Shapes.java @@ -0,0 +1,26 @@ +// polymorphism/Shapes.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Polymorphism in Java +import polymorphism.shape.*; + +public class Shapes { + public static void main(String[] args) { + RandomShapes gen = new RandomShapes(); + // Make polymorphic method calls: + for(Shape shape : gen.array(9)) + shape.draw(); + } +} +/* Output: +Triangle.draw() +Triangle.draw() +Square.draw() +Triangle.draw() +Square.draw() +Triangle.draw() +Square.draw() +Triangle.draw() +Circle.draw() +*/ diff --git a/code/polymorphism/StaticPolymorphism.java b/code/polymorphism/StaticPolymorphism.java new file mode 100644 index 00000000..1ebe733b --- /dev/null +++ b/code/polymorphism/StaticPolymorphism.java @@ -0,0 +1,36 @@ +// polymorphism/StaticPolymorphism.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Static methods are not polymorphic + +class StaticSuper { + public static String staticGet() { + return "Base staticGet()"; + } + public String dynamicGet() { + return "Base dynamicGet()"; + } +} + +class StaticSub extends StaticSuper { + public static String staticGet() { + return "Derived staticGet()"; + } + @Override + public String dynamicGet() { + return "Derived dynamicGet()"; + } +} + +public class StaticPolymorphism { + public static void main(String[] args) { + StaticSuper sup = new StaticSub(); // Upcast + System.out.println(StaticSuper.staticGet()); + System.out.println(sup.dynamicGet()); + } +} +/* Output: +Base staticGet() +Derived dynamicGet() +*/ diff --git a/code/polymorphism/Transmogrify.java b/code/polymorphism/Transmogrify.java new file mode 100644 index 00000000..09877d53 --- /dev/null +++ b/code/polymorphism/Transmogrify.java @@ -0,0 +1,43 @@ +// polymorphism/Transmogrify.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Dynamically changing the behavior of an object +// via composition (the "State" design pattern) + +class Actor { + public void act() {} +} + +class HappyActor extends Actor { + @Override + public void act() { + System.out.println("HappyActor"); + } +} + +class SadActor extends Actor { + @Override + public void act() { + System.out.println("SadActor"); + } +} + +class Stage { + private Actor actor = new HappyActor(); + public void change() { actor = new SadActor(); } + public void performPlay() { actor.act(); } +} + +public class Transmogrify { + public static void main(String[] args) { + Stage stage = new Stage(); + stage.performPlay(); + stage.change(); + stage.performPlay(); + } +} +/* Output: +HappyActor +SadActor +*/ diff --git a/code/polymorphism/music/Instrument.java b/code/polymorphism/music/Instrument.java new file mode 100644 index 00000000..fb6c77e3 --- /dev/null +++ b/code/polymorphism/music/Instrument.java @@ -0,0 +1,11 @@ +// polymorphism/music/Instrument.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package polymorphism.music; + +class Instrument { + public void play(Note n) { + System.out.println("Instrument.play()"); + } +} diff --git a/code/polymorphism/music/Music.java b/code/polymorphism/music/Music.java new file mode 100644 index 00000000..8e903ec0 --- /dev/null +++ b/code/polymorphism/music/Music.java @@ -0,0 +1,21 @@ +// polymorphism/music/Music.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Inheritance & upcasting +// {java polymorphism.music.Music} +package polymorphism.music; + +public class Music { + public static void tune(Instrument i) { + // ... + i.play(Note.MIDDLE_C); + } + public static void main(String[] args) { + Wind flute = new Wind(); + tune(flute); // Upcasting + } +} +/* Output: +Wind.play() MIDDLE_C +*/ diff --git a/code/polymorphism/music/Music2.java b/code/polymorphism/music/Music2.java new file mode 100644 index 00000000..a5bff54b --- /dev/null +++ b/code/polymorphism/music/Music2.java @@ -0,0 +1,46 @@ +// polymorphism/music/Music2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Overloading instead of upcasting +// {java polymorphism.music.Music2} +package polymorphism.music; + +class Stringed extends Instrument { + @Override + public void play(Note n) { + System.out.println("Stringed.play() " + n); + } +} + +class Brass extends Instrument { + @Override + public void play(Note n) { + System.out.println("Brass.play() " + n); + } +} + +public class Music2 { + public static void tune(Wind i) { + i.play(Note.MIDDLE_C); + } + public static void tune(Stringed i) { + i.play(Note.MIDDLE_C); + } + public static void tune(Brass i) { + i.play(Note.MIDDLE_C); + } + public static void main(String[] args) { + Wind flute = new Wind(); + Stringed violin = new Stringed(); + Brass frenchHorn = new Brass(); + tune(flute); // No upcasting + tune(violin); + tune(frenchHorn); + } +} +/* Output: +Wind.play() MIDDLE_C +Stringed.play() MIDDLE_C +Brass.play() MIDDLE_C +*/ diff --git a/code/polymorphism/music/Note.java b/code/polymorphism/music/Note.java new file mode 100644 index 00000000..414367a9 --- /dev/null +++ b/code/polymorphism/music/Note.java @@ -0,0 +1,10 @@ +// polymorphism/music/Note.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Notes to play on musical instruments +package polymorphism.music; + +public enum Note { + MIDDLE_C, C_SHARP, B_FLAT; // Etc. +} diff --git a/code/polymorphism/music/Wind.java b/code/polymorphism/music/Wind.java new file mode 100644 index 00000000..c38ac497 --- /dev/null +++ b/code/polymorphism/music/Wind.java @@ -0,0 +1,15 @@ +// polymorphism/music/Wind.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package polymorphism.music; + +// Wind objects are instruments +// because they have the same interface: +public class Wind extends Instrument { + // Redefine interface method: + @Override + public void play(Note n) { + System.out.println("Wind.play() " + n); + } +} diff --git a/code/polymorphism/music3/Music3.java b/code/polymorphism/music3/Music3.java new file mode 100644 index 00000000..da3eb364 --- /dev/null +++ b/code/polymorphism/music3/Music3.java @@ -0,0 +1,108 @@ +// polymorphism/music3/Music3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// An extensible program +// {java polymorphism.music3.Music3} +package polymorphism.music3; +import polymorphism.music.Note; + +class Instrument { + void play(Note n) { + System.out.println("Instrument.play() " + n); + } + String what() { return "Instrument"; } + void adjust() { + System.out.println("Adjusting Instrument"); + } +} + +class Wind extends Instrument { + @Override + void play(Note n) { + System.out.println("Wind.play() " + n); + } + @Override + String what() { return "Wind"; } + @Override + void adjust() { + System.out.println("Adjusting Wind"); + } +} + +class Percussion extends Instrument { + @Override + void play(Note n) { + System.out.println("Percussion.play() " + n); + } + @Override + String what() { return "Percussion"; } + @Override + void adjust() { + System.out.println("Adjusting Percussion"); + } +} + +class Stringed extends Instrument { + @Override + void play(Note n) { + System.out.println("Stringed.play() " + n); + } + @Override + String what() { return "Stringed"; } + @Override + void adjust() { + System.out.println("Adjusting Stringed"); + } +} + +class Brass extends Wind { + @Override + void play(Note n) { + System.out.println("Brass.play() " + n); + } + @Override + void adjust() { + System.out.println("Adjusting Brass"); + } +} + +class Woodwind extends Wind { + @Override + void play(Note n) { + System.out.println("Woodwind.play() " + n); + } + @Override + String what() { return "Woodwind"; } +} + +public class Music3 { + // Doesn't care about type, so new types + // added to the system still work right: + public static void tune(Instrument i) { + // ... + i.play(Note.MIDDLE_C); + } + public static void tuneAll(Instrument[] e) { + for(Instrument i : e) + tune(i); + } + public static void main(String[] args) { + // Upcasting during addition to the array: + Instrument[] orchestra = { + new Wind(), + new Percussion(), + new Stringed(), + new Brass(), + new Woodwind() + }; + tuneAll(orchestra); + } +} +/* Output: +Wind.play() MIDDLE_C +Percussion.play() MIDDLE_C +Stringed.play() MIDDLE_C +Brass.play() MIDDLE_C +Woodwind.play() MIDDLE_C +*/ diff --git a/code/polymorphism/shape/Circle.java b/code/polymorphism/shape/Circle.java new file mode 100644 index 00000000..fc857950 --- /dev/null +++ b/code/polymorphism/shape/Circle.java @@ -0,0 +1,16 @@ +// polymorphism/shape/Circle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package polymorphism.shape; + +public class Circle extends Shape { + @Override + public void draw() { + System.out.println("Circle.draw()"); + } + @Override + public void erase() { + System.out.println("Circle.erase()"); + } +} diff --git a/code/polymorphism/shape/RandomShapes.java b/code/polymorphism/shape/RandomShapes.java new file mode 100644 index 00000000..c1419f4e --- /dev/null +++ b/code/polymorphism/shape/RandomShapes.java @@ -0,0 +1,26 @@ +// polymorphism/shape/RandomShapes.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A "factory" that randomly creates shapes +package polymorphism.shape; +import java.util.*; + +public class RandomShapes { + private Random rand = new Random(47); + public Shape get() { + switch(rand.nextInt(3)) { + default: + case 0: return new Circle(); + case 1: return new Square(); + case 2: return new Triangle(); + } + } + public Shape[] array(int sz) { + Shape[] shapes = new Shape[sz]; + // Fill up the array with shapes: + for(int i = 0; i < shapes.length; i++) + shapes[i] = get(); + return shapes; + } +} diff --git a/code/polymorphism/shape/Shape.java b/code/polymorphism/shape/Shape.java new file mode 100644 index 00000000..4be93c86 --- /dev/null +++ b/code/polymorphism/shape/Shape.java @@ -0,0 +1,10 @@ +// polymorphism/shape/Shape.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package polymorphism.shape; + +public class Shape { + public void draw() {} + public void erase() {} +} diff --git a/code/polymorphism/shape/Square.java b/code/polymorphism/shape/Square.java new file mode 100644 index 00000000..4938335b --- /dev/null +++ b/code/polymorphism/shape/Square.java @@ -0,0 +1,16 @@ +// polymorphism/shape/Square.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package polymorphism.shape; + +public class Square extends Shape { + @Override + public void draw() { + System.out.println("Square.draw()"); + } + @Override + public void erase() { + System.out.println("Square.erase()"); + } +} diff --git a/code/polymorphism/shape/Triangle.java b/code/polymorphism/shape/Triangle.java new file mode 100644 index 00000000..db7394a3 --- /dev/null +++ b/code/polymorphism/shape/Triangle.java @@ -0,0 +1,16 @@ +// polymorphism/shape/Triangle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package polymorphism.shape; + +public class Triangle extends Shape { + @Override + public void draw() { + System.out.println("Triangle.draw()"); + } + @Override + public void erase() { + System.out.println("Triangle.erase()"); + } +} diff --git a/code/references/AddingClone.java b/code/references/AddingClone.java new file mode 100644 index 00000000..4f03cf06 --- /dev/null +++ b/code/references/AddingClone.java @@ -0,0 +1,67 @@ +// references/AddingClone.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// You must go through a few gyrations +// to add cloning to your own class +import java.util.*; +import java.util.stream.*; + +class Int2 implements Cloneable { + private int i; + Int2(int ii) { i = ii; } + public void increment() { i++; } + @Override + public String toString() { + return Integer.toString(i); + } + @Override + public Int2 clone() { + try { + return (Int2)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } +} + +// Inheritance doesn't remove cloneability: +class Int3 extends Int2 { + private int j; // Automatically duplicated + Int3(int i) { super(i); } +} + +public class AddingClone { + @SuppressWarnings("unchecked") + public static void main(String[] args) { + Int2 x = new Int2(10); + Int2 x2 = x.clone(); + x2.increment(); + System.out.println( + "x = " + x + ", x2 = " + x2); + // Anything inherited is also cloneable: + Int3 x3 = new Int3(7); + x3 = (Int3)x3.clone(); + ArrayList v = IntStream.range(0, 10) + .mapToObj(Int2::new) + .collect(Collectors + .toCollection(ArrayList::new)); + System.out.println("v: " + v); + ArrayList v2 = + (ArrayList)v.clone(); + // Now clone each element: + IntStream.range(0, v.size()) + .forEach(i -> v2.set(i, v.get(i).clone())); + // Increment all v2's elements: + v2.forEach(Int2::increment); + System.out.println("v2: " + v2); + // See if it changed v's elements: + System.out.println("v: " + v); + } +} +/* Output: +x = 10, x2 = 11 +v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +v2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +*/ diff --git a/code/references/Alias1.java b/code/references/Alias1.java new file mode 100644 index 00000000..1af594ec --- /dev/null +++ b/code/references/Alias1.java @@ -0,0 +1,27 @@ +// references/Alias1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Aliasing two references to one object + +public class Alias1 { + private int i; + public Alias1(int ii) { i = ii; } + public static void main(String[] args) { + Alias1 x = new Alias1(7); + Alias1 y = x; // Assign the reference (1) + System.out.println("x: " + x.i); + System.out.println("y: " + y.i); + System.out.println("Incrementing x"); + x.i++; // [2] + System.out.println("x: " + x.i); + System.out.println("y: " + y.i); + } +} +/* Output: +x: 7 +y: 7 +Incrementing x +x: 8 +y: 8 +*/ diff --git a/code/references/Alias2.java b/code/references/Alias2.java new file mode 100644 index 00000000..aa37e1a2 --- /dev/null +++ b/code/references/Alias2.java @@ -0,0 +1,25 @@ +// references/Alias2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Method calls implicitly alias their arguments + +public class Alias2 { + private int i; + public Alias2(int i) { this.i = i; } + public static void f(Alias2 reference) { + reference.i++; + } + public static void main(String[] args) { + Alias2 x = new Alias2(7); + System.out.println("x: " + x.i); + System.out.println("Calling f(x)"); + f(x); + System.out.println("x: " + x.i); + } +} +/* Output: +x: 7 +Calling f(x) +x: 8 +*/ diff --git a/code/references/CheckCloneable.java b/code/references/CheckCloneable.java new file mode 100644 index 00000000..137937a9 --- /dev/null +++ b/code/references/CheckCloneable.java @@ -0,0 +1,113 @@ +// references/CheckCloneable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Check to see if a reference can be cloned + +// Can't clone this -- doesn't override clone(): +class Ordinary {} + +// Overrides clone, doesn't implement Cloneable: +class WrongClone extends Ordinary { + @Override public Object clone() + throws CloneNotSupportedException { + return super.clone(); // Throws exception + } +} + +// Does all the right things for cloning: +class IsCloneable extends Ordinary +implements Cloneable { + @Override public Object clone() + throws CloneNotSupportedException { + return super.clone(); + } +} + +// Turn off cloning by throwing the exception: +class NoMore extends IsCloneable { + @Override public Object clone() + throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } +} + +class TryMore extends NoMore { + @Override public Object clone() + throws CloneNotSupportedException { + // Calls NoMore.clone(), throws exception: + return super.clone(); + } +} + +class BackOn extends NoMore { + private BackOn duplicate(BackOn b) { + // Somehow make a copy of b and return that + // copy. A dummy copy, just to make a point: + return new BackOn(); + } + @Override + public Object clone() { + // Doesn't call NoMore.clone(): + return duplicate(this); + } +} + +// You can't inherit from this, so you can't +// override clone() as you can in BackOn: +final class ReallyNoMore extends NoMore {} + +public class CheckCloneable { + public static + Ordinary tryToClone(Ordinary ord) { + String id = ord.getClass().getName(); + System.out.println("Attempting " + id); + Ordinary x = null; + if(ord instanceof Cloneable) { + try { + x = (Ordinary)((IsCloneable)ord).clone(); + System.out.println("Cloned " + id); + } catch(CloneNotSupportedException e) { + System.out.println( + "Could not clone " + id); + } + } else { + System.out.println("Doesn't implement Cloneable"); + } + return x; + } + public static void main(String[] args) { + // Upcasting: + Ordinary[] ord = { + new IsCloneable(), + new WrongClone(), + new NoMore(), + new TryMore(), + new BackOn(), + new ReallyNoMore(), + }; + Ordinary x = new Ordinary(); + // This won't compile because + // clone() is protected in Object: + //- x = (Ordinary)x.clone(); + // Checks first to see if the class + // implements Cloneable: + for(Ordinary ord1 : ord) { + tryToClone(ord1); + } + } +} +/* Output: +Attempting IsCloneable +Cloned IsCloneable +Attempting WrongClone +Doesn't implement Cloneable +Attempting NoMore +Could not clone NoMore +Attempting TryMore +Could not clone TryMore +Attempting BackOn +Cloned BackOn +Attempting ReallyNoMore +Could not clone ReallyNoMore +*/ diff --git a/code/references/CloneArrayList.java b/code/references/CloneArrayList.java new file mode 100644 index 00000000..601673c2 --- /dev/null +++ b/code/references/CloneArrayList.java @@ -0,0 +1,38 @@ +// references/CloneArrayList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The clone() operation works for only a few +// items in the standard Java library +import java.util.*; +import java.util.stream.*; + +class Int { + private int i; + Int(int ii) { i = ii; } + public void increment() { i++; } + @Override + public String toString() { + return Integer.toString(i); + } +} + +public class CloneArrayList { + public static void main(String[] args) { + ArrayList v = IntStream.range(0, 10) + .mapToObj(Int::new) + .collect(Collectors + .toCollection(ArrayList::new)); + System.out.println("v: " + v); + @SuppressWarnings("unchecked") + ArrayList v2 = (ArrayList)v.clone(); + // Increment all v2's elements: + v2.forEach(Int::increment); + // See if it changed v's elements: + System.out.println("v: " + v); + } +} +/* Output: +v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +v: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +*/ diff --git a/code/references/Compete.java b/code/references/Compete.java new file mode 100644 index 00000000..9e77f3a7 --- /dev/null +++ b/code/references/Compete.java @@ -0,0 +1,89 @@ +// references/Compete.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import onjava.Timer; + +class Thing1 implements Serializable {} +class Thing2 implements Serializable { + Thing1 t1 = new Thing1(); +} + +class Thing3 implements Cloneable { + @Override + public Thing3 clone() { + try { + return (Thing3)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } +} + +class Thing4 implements Cloneable { + private Thing3 t3 = new Thing3(); + @Override + public Thing4 clone() { + Thing4 t4 = null; + try { + t4 = (Thing4)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + // Clone the field, too: + t4.t3 = t3.clone(); + return t4; + } +} + +public class Compete { + public static final int SIZE = 100000; + public static void + main(String[] args) throws Exception { + Thing2[] a = new Thing2[SIZE]; + for(int i = 0; i < SIZE; i++) + a[i] = new Thing2(); + Thing4[] b = new Thing4[SIZE]; + for(int i = 0; i < SIZE; i++) + b[i] = new Thing4(); + Timer timer = new Timer(); + try( + ByteArrayOutputStream buf = + new ByteArrayOutputStream(); + ObjectOutputStream oos = + new ObjectOutputStream(buf) + ) { + for(Thing2 a1 : a) { + oos.writeObject(a1); + } + // Now get copies: + try( + ObjectInputStream in = + new ObjectInputStream( + new ByteArrayInputStream( + buf.toByteArray())) + ) { + Thing2[] c = new Thing2[SIZE]; + for(int i = 0; i < SIZE; i++) + c[i] = (Thing2)in.readObject(); + } + } + System.out.println( + "Duplication via serialization: " + + timer.duration() + " Milliseconds"); + + // Now try cloning: + timer = new Timer(); + Thing4[] d = new Thing4[SIZE]; + for(int i = 0; i < SIZE; i++) + d[i] = b[i].clone(); + System.out.println( + "Duplication via cloning: " + + timer.duration() + " Milliseconds"); + } +} +/* Output: +Duplication via serialization: 516 Milliseconds +Duplication via cloning: 71 Milliseconds +*/ diff --git a/code/references/CopyConstructor.java b/code/references/CopyConstructor.java new file mode 100644 index 00000000..2617f48b --- /dev/null +++ b/code/references/CopyConstructor.java @@ -0,0 +1,188 @@ +// references/CopyConstructor.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A constructor to copy an object of the same +// type, as an attempt to create a local copy +import java.lang.reflect.*; + +class FruitQualities { + private int weight; + private int color; + private int firmness; + private int ripeness; + private int smell; + // etc. + // No-arg constructor: + FruitQualities() { + // Do something meaningful... + } + // Other constructors: + // ... + // Copy constructor: + FruitQualities(FruitQualities f) { + weight = f.weight; + color = f.color; + firmness = f.firmness; + ripeness = f.ripeness; + smell = f.smell; + // etc. + } +} + +class Seed { + // Members... + Seed() { /* No-arg constructor */ } + Seed(Seed s) { /* Copy constructor */ } +} + +class Fruit { + private FruitQualities fq; + private int seeds; + private Seed[] s; + Fruit(FruitQualities q, int seedCount) { + fq = q; + seeds = seedCount; + s = new Seed[seeds]; + for(int i = 0; i < seeds; i++) + s[i] = new Seed(); + } + // Other constructors: + // ... + // Copy constructor: + Fruit(Fruit f) { + fq = new FruitQualities(f.fq); + seeds = f.seeds; + s = new Seed[seeds]; + // Call all Seed copy-constructors: + for(int i = 0; i < seeds; i++) + s[i] = new Seed(f.s[i]); + // Other copy-construction activities... + } + // This allows derived constructors (or other + // methods) to put in different qualities: + protected void addQualities(FruitQualities q) { + fq = q; + } + protected FruitQualities getQualities() { + return fq; + } +} + +class Tomato extends Fruit { + Tomato() { + super(new FruitQualities(), 100); + } + Tomato(Tomato t) { // Copy-constructor + super(t); // Upcast to base copy-constructor + // Other copy-construction activities... + } +} + +class ZebraQualities extends FruitQualities { + private int stripedness; + // No-arg constructor: + ZebraQualities() { + super(); + // do something meaningful... + } + ZebraQualities(ZebraQualities z) { + super(z); + stripedness = z.stripedness; + } +} + +class GreenZebra extends Tomato { + GreenZebra() { + addQualities(new ZebraQualities()); + } + GreenZebra(GreenZebra g) { + super(g); // Calls Tomato(Tomato) + // Restore the right qualities: + addQualities(new ZebraQualities()); + } + public void evaluate() { + ZebraQualities zq = + (ZebraQualities)getQualities(); + // Do something with the qualities + // ... + } +} + +public class CopyConstructor { + public static void ripen(Tomato t) { + // Use the "copy constructor": + t = new Tomato(t); // [1] + System.out.println("In ripen, t is a " + + t.getClass().getName()); + } + public static void slice(Fruit f) { + f = new Fruit(f); // [2] Hmmm... will this work? + System.out.println("In slice, f is a " + + f.getClass().getName()); + } + @SuppressWarnings("unchecked") + public static void ripen2(Tomato t) { + try { + Class c = t.getClass(); + // Use the "copy constructor": + Constructor ct = + c.getConstructor(new Class[] { c }); + Object obj = + ct.newInstance(new Object[] { t }); + System.out.println("In ripen2, t is a " + + obj.getClass().getName()); + } catch(NoSuchMethodException | + SecurityException | + InstantiationException | + IllegalAccessException | + IllegalArgumentException | + InvocationTargetException e) { + System.out.println(e); + } + } + @SuppressWarnings("unchecked") + public static void slice2(Fruit f) { + try { + Class c = f.getClass(); + Constructor ct = + c.getConstructor(new Class[] { c }); + Object obj = + ct.newInstance(new Object[] { f }); + System.out.println("In slice2, f is a " + + obj.getClass().getName()); + } catch(NoSuchMethodException | + SecurityException | + InstantiationException | + IllegalAccessException | + IllegalArgumentException | + InvocationTargetException e) { + System.out.println(e); + } + } + public static void main(String[] args) { + Tomato tomato = new Tomato(); + ripen(tomato); // OK + slice(tomato); // OOPS! + ripen2(tomato); // OK + slice2(tomato); // OK + GreenZebra g = new GreenZebra(); + ripen(g); // OOPS! + slice(g); // OOPS! + ripen2(g); // OK + slice2(g); // OK + g.evaluate(); + } +} +/* Output: +In ripen, t is a Tomato +In slice, f is a Fruit +java.lang.NoSuchMethodException: Tomato.(Tomato) +java.lang.NoSuchMethodException: Tomato.(Tomato) +In ripen, t is a Tomato +In slice, f is a Fruit +java.lang.NoSuchMethodException: +GreenZebra.(GreenZebra) +java.lang.NoSuchMethodException: +GreenZebra.(GreenZebra) +*/ diff --git a/code/references/DepthReading.java b/code/references/DepthReading.java new file mode 100644 index 00000000..00d9dfda --- /dev/null +++ b/code/references/DepthReading.java @@ -0,0 +1,29 @@ +// references/DepthReading.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Cloning a composed object +package references; + +public class DepthReading implements Cloneable { + private double depth; + public DepthReading(double depth) { + this.depth = depth; + } + @Override + public DepthReading clone() { + try { + return (DepthReading)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + public double getDepth() { return depth; } + public void setDepth(double depth) { + this.depth = depth; + } + @Override + public String toString() { + return String.valueOf(depth); + } +} diff --git a/code/references/HorrorFlick.java b/code/references/HorrorFlick.java new file mode 100644 index 00000000..709d15bf --- /dev/null +++ b/code/references/HorrorFlick.java @@ -0,0 +1,35 @@ +// references/HorrorFlick.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Insert Cloneability at any level of inheritance + +class Person {} + +class Hero extends Person {} + +class Scientist extends Person implements Cloneable { + @Override + public Scientist clone() { + try { + return (Scientist)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } +} + +class MadScientist extends Scientist {} + +public class HorrorFlick { + public static void main(String[] args) { + Person p = new Person(); + Hero h = new Hero(); + Scientist s = new Scientist(); + MadScientist m = new MadScientist(); + //- p = (Person)p.clone(); // Compile error + //- h = (Hero)h.clone(); // Compile error + s = s.clone(); + m = (MadScientist)m.clone(); + } +} diff --git a/code/references/Immutable1.java b/code/references/Immutable1.java new file mode 100644 index 00000000..55ac1f6a --- /dev/null +++ b/code/references/Immutable1.java @@ -0,0 +1,34 @@ +// references/Immutable1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Immutable objects are immune to aliasing + +public class Immutable1 { + private int data; + public Immutable1(int initVal) { + data = initVal; + } + public int read() { return data; } + public boolean nonzero() { return data != 0; } + public Immutable1 multiply(int multiplier) { + return new Immutable1(data * multiplier); + } + public static void f(Immutable1 i1) { + Immutable1 quad = i1.multiply(4); + System.out.println("i1 = " + i1.read()); + System.out.println("quad = " + quad.read()); + } + public static void main(String[] args) { + Immutable1 x = new Immutable1(47); + System.out.println("x = " + x.read()); + f(x); + System.out.println("x = " + x.read()); + } +} +/* Output: +x = 47 +i1 = 47 +quad = 188 +x = 47 +*/ diff --git a/code/references/Immutable2.java b/code/references/Immutable2.java new file mode 100644 index 00000000..a565f86a --- /dev/null +++ b/code/references/Immutable2.java @@ -0,0 +1,71 @@ +// references/Immutable2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A companion class to modify immutable objects + +class Mutable { + private int data; + Mutable(int initVal) { + data = initVal; + } + public Mutable add(int x) { + data += x; + return this; + } + public Mutable multiply(int x) { + data *= x; + return this; + } + public Immutable2 makeImmutable2() { + return new Immutable2(data); + } +} + +public class Immutable2 { + private int data; + public Immutable2(int initVal) { + data = initVal; + } + public int read() { return data; } + public boolean nonzero() { + return data != 0; + } + public Immutable2 add(int x) { + return new Immutable2(data + x); + } + public Immutable2 multiply(int x) { + return new Immutable2(data * x); + } + public Mutable makeMutable() { + return new Mutable(data); + } + public static + Immutable2 modify1(Immutable2 y) { + Immutable2 val = y.add(12); + val = val.multiply(3); + val = val.add(11); + val = val.multiply(2); + return val; + } + // This produces the same result: + public static + Immutable2 modify2(Immutable2 y) { + Mutable m = y.makeMutable(); + m.add(12).multiply(3).add(11).multiply(2); + return m.makeImmutable2(); + } + public static void main(String[] args) { + Immutable2 i2 = new Immutable2(47); + Immutable2 r1 = modify1(i2); + Immutable2 r2 = modify2(i2); + System.out.println("i2 = " + i2.read()); + System.out.println("r1 = " + r1.read()); + System.out.println("r2 = " + r2.read()); + } +} +/* Output: +i2 = 47 +r1 = 376 +r2 = 376 +*/ diff --git a/code/references/ImmutableInteger.java b/code/references/ImmutableInteger.java new file mode 100644 index 00000000..906aa7ef --- /dev/null +++ b/code/references/ImmutableInteger.java @@ -0,0 +1,22 @@ +// references/ImmutableInteger.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The Integer class cannot be changed +import java.util.*; +import java.util.stream.*; + +public class ImmutableInteger { + public static void main(String[] args) { + @SuppressWarnings("deprecation") + List v = IntStream.range(0, 10) + .mapToObj(Integer::new) + .collect(Collectors.toList()); + System.out.println(v); + // But how do you change the int + // inside the Integer? + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +*/ diff --git a/code/references/ImmutableStrings.java b/code/references/ImmutableStrings.java new file mode 100644 index 00000000..ad954e3f --- /dev/null +++ b/code/references/ImmutableStrings.java @@ -0,0 +1,25 @@ +// references/ImmutableStrings.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrating StringBuilder + +public class ImmutableStrings { + public static void main(String[] args) { + String foo = "foo"; + String s = "abc" + foo + "def" + + Integer.toString(47); + System.out.println(s); + // The "equivalent" using StringBuilder: + StringBuilder sb = + new StringBuilder("abc"); // Creates String + sb.append(foo); + sb.append("def"); // Creates String + sb.append(Integer.toString(47)); + System.out.println(sb); + } +} +/* Output: +abcfoodef47 +abcfoodef47 +*/ diff --git a/code/references/LocalCopy.java b/code/references/LocalCopy.java new file mode 100644 index 00000000..9c01c09e --- /dev/null +++ b/code/references/LocalCopy.java @@ -0,0 +1,57 @@ +// references/LocalCopy.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creating local copies with clone() + +class Duplo implements Cloneable { + private int n; + Duplo(int n) { this.n = n; } + @Override + public Duplo clone() { // [1] + try { + return (Duplo)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + public int getValue() { return n; } + public void setValue(int n) { this.n = n; } + public void increment() { n++; } + @Override + public String toString() { + return Integer.toString(n); + } +} + +public class LocalCopy { + public static Duplo g(Duplo v) { + // Passing a reference, modifies outside object: + v.increment(); + return v; + } + public static Duplo f(Duplo v) { + v = v.clone(); // [2] Local copy + v.increment(); + return v; + } + public static void main(String[] args) { + Duplo a = new Duplo(11); + Duplo b = g(a); + // Reference equivalence, not object equivalence: + System.out.println("a == b: " + (a == b) + + "\na = " + a + "\nb = " + b); + Duplo c = new Duplo(47); + Duplo d = f(c); + System.out.println("c == d: " + (c == d) + + "\nc = " + c + "\nd = " + d); + } +} +/* Output: +a == b: true +a = 12 +b = 12 +c == d: false +c = 47 +d = 48 +*/ diff --git a/code/references/MutableInteger.java b/code/references/MutableInteger.java new file mode 100644 index 00000000..dfe0cc7b --- /dev/null +++ b/code/references/MutableInteger.java @@ -0,0 +1,34 @@ +// references/MutableInteger.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A changeable wrapper class +import java.util.*; +import java.util.stream.*; + +class IntValue { + private int n; + IntValue(int x) { n = x; } + public int getValue() { return n; } + public void setValue(int n) { this.n = n; } + public void increment() { n++; } + @Override + public String toString() { + return Integer.toString(n); + } +} + +public class MutableInteger { + public static void main(String[] args) { + List v = IntStream.range(0, 10) + .mapToObj(IntValue::new) + .collect(Collectors.toList()); + System.out.println(v); + v.forEach(IntValue::increment); + System.out.println(v); + } +} +/* Output: +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +*/ diff --git a/code/references/OceanReading.java b/code/references/OceanReading.java new file mode 100644 index 00000000..b89f1b04 --- /dev/null +++ b/code/references/OceanReading.java @@ -0,0 +1,48 @@ +// references/OceanReading.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Cloning a composed object +package references; + +public class OceanReading implements Cloneable { + private DepthReading depth; + private TemperatureReading temperature; + public + OceanReading(double tdata, double ddata) { + temperature = new TemperatureReading(tdata); + depth = new DepthReading(ddata); + } + @Override + public OceanReading clone() { + OceanReading or = null; + try { + or = (OceanReading)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + // Must clone references: + or.depth = (DepthReading)or.depth.clone(); + or.temperature = + (TemperatureReading)or.temperature.clone(); + return or; + } + public TemperatureReading getTemperatureReading() { + return temperature; + } + public void + setTemperatureReading(TemperatureReading tr) { + temperature = tr; + } + public DepthReading getDepthReading() { + return depth; + } + public void setDepthReading(DepthReading dr) { + this.depth = dr; + } + @Override + public String toString() { + return "temperature: " + temperature + + ", depth: " + depth; + } +} diff --git a/code/references/PassReferences.java b/code/references/PassReferences.java new file mode 100644 index 00000000..2a163008 --- /dev/null +++ b/code/references/PassReferences.java @@ -0,0 +1,19 @@ +// references/PassReferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class PassReferences { + public static void f(PassReferences h) { + System.out.println("h inside f(): " + h); + } + public static void main(String[] args) { + PassReferences p = new PassReferences(); + System.out.println("p inside main(): " + p); + f(p); + } +} +/* Output: +p inside main(): PassReferences@15db9742 +h inside f(): PassReferences@15db9742 +*/ diff --git a/code/references/SimplerMutableInteger.java b/code/references/SimplerMutableInteger.java new file mode 100644 index 00000000..191068ca --- /dev/null +++ b/code/references/SimplerMutableInteger.java @@ -0,0 +1,30 @@ +// references/SimplerMutableInteger.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A trivial wrapper class +import java.util.*; +import java.util.stream.*; + +class IntValue2 { + public int n; + IntValue2(int n) { this.n = n; } +} + +public class SimplerMutableInteger { + public static void main(String[] args) { + List v = IntStream.range(0, 10) + .mapToObj(IntValue2::new) + .collect(Collectors.toList()); + v.forEach(iv2 -> + System.out.print(iv2.n + " ")); + System.out.println(); + v.forEach(iv2 -> iv2.n += 1); + v.forEach(iv2 -> + System.out.print(iv2.n + " ")); + } +} +/* Output: +0 1 2 3 4 5 6 7 8 9 +1 2 3 4 5 6 7 8 9 10 +*/ diff --git a/code/references/Snake.java b/code/references/Snake.java new file mode 100644 index 00000000..004f7e76 --- /dev/null +++ b/code/references/Snake.java @@ -0,0 +1,51 @@ +// references/Snake.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Tests cloning to see if reference +// destinations are also cloned + +public class Snake implements Cloneable { + private Snake next; + private char c; + // Value of i == number of segments + public Snake(int i, char x) { + c = x; + if(--i > 0) + next = new Snake(i, (char)(x + 1)); + } + public void increment() { + c++; + if(next != null) + next.increment(); + } + @Override + public String toString() { + String s = ":" + c; + if(next != null) + s += next.toString(); + return s; + } + @Override + public Snake clone() { + try { + return (Snake)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + public static void main(String[] args) { + Snake s = new Snake(5, 'a'); + System.out.println("s = " + s); + Snake s2 = s.clone(); + System.out.println("s2 = " + s2); + s.increment(); + System.out.println( + "after s.increment, s2 = " + s2); + } +} +/* Output: +s = :a:b:c:d:e +s2 = :a:b:c:d:e +after s.increment, s2 = :a:c:d:e:f +*/ diff --git a/code/references/Stringer.java b/code/references/Stringer.java new file mode 100644 index 00000000..72663bb5 --- /dev/null +++ b/code/references/Stringer.java @@ -0,0 +1,22 @@ +// references/Stringer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Stringer { + public static String upcase(String s) { + return s.toUpperCase(); + } + public static void main(String[] args) { + String q = new String("howdy"); + System.out.println(q); // howdy + String qq = upcase(q); + System.out.println(qq); // HOWDY + System.out.println(q); // howdy + } +} +/* Output: +howdy +HOWDY +howdy +*/ diff --git a/code/references/TemperatureReading.java b/code/references/TemperatureReading.java new file mode 100644 index 00000000..9b77cfb2 --- /dev/null +++ b/code/references/TemperatureReading.java @@ -0,0 +1,33 @@ +// references/TemperatureReading.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Cloning a composed object +package references; + +public class TemperatureReading implements Cloneable { + private long time; + private double temperature; + public TemperatureReading(double temperature) { + time = System.currentTimeMillis(); + this.temperature = temperature; + } + @Override + public TemperatureReading clone() { + try { + return (TemperatureReading)super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + public double getTemperature() { + return temperature; + } + public void setTemperature(double temp) { + this.temperature = temp; + } + @Override + public String toString() { + return String.valueOf(temperature); + } +} diff --git a/code/references/tests/DeepCopyTest.java b/code/references/tests/DeepCopyTest.java new file mode 100644 index 00000000..b65a8d89 --- /dev/null +++ b/code/references/tests/DeepCopyTest.java @@ -0,0 +1,28 @@ +// references/tests/DeepCopyTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package references; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +public class DeepCopyTest { + @Test + public void testClone() { + OceanReading reading = + new OceanReading(33.9, 100.5); + // Now clone it: + OceanReading clone = reading.clone(); + TemperatureReading tr = + clone.getTemperatureReading(); + tr.setTemperature(tr.getTemperature() + 1); + clone.setTemperatureReading(tr); + DepthReading dr = clone.getDepthReading(); + dr.setDepth(dr.getDepth() + 1); + clone.setDepthReading(dr); + assertEquals(reading.toString(), + "temperature: 33.9, depth: 100.5"); + assertEquals(clone.toString(), + "temperature: 34.9, depth: 101.5"); + } +} diff --git a/code/reuse/Bath.java b/code/reuse/Bath.java new file mode 100644 index 00000000..38e5e819 --- /dev/null +++ b/code/reuse/Bath.java @@ -0,0 +1,61 @@ +// reuse/Bath.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Constructor initialization with composition + +class Soap { + private String s; + Soap() { + System.out.println("Soap()"); + s = "Constructed"; + } + @Override + public String toString() { return s; } +} + +public class Bath { + private String // Initializing at point of definition: + s1 = "Happy", + s2 = "Happy", + s3, s4; + private Soap castille; + private int i; + private float toy; + public Bath() { + System.out.println("Inside Bath()"); + s3 = "Joy"; + toy = 3.14f; + castille = new Soap(); + } + // Instance initialization: + { i = 47; } + @Override + public String toString() { + if(s4 == null) // Delayed initialization: + s4 = "Joy"; + return + "s1 = " + s1 + "\n" + + "s2 = " + s2 + "\n" + + "s3 = " + s3 + "\n" + + "s4 = " + s4 + "\n" + + "i = " + i + "\n" + + "toy = " + toy + "\n" + + "castille = " + castille; + } + public static void main(String[] args) { + Bath b = new Bath(); + System.out.println(b); + } +} +/* Output: +Inside Bath() +Soap() +s1 = Happy +s2 = Happy +s3 = Joy +s4 = Joy +i = 47 +toy = 3.14 +castille = Constructed +*/ diff --git a/code/reuse/Beetle.java b/code/reuse/Beetle.java new file mode 100644 index 00000000..0a41bc17 --- /dev/null +++ b/code/reuse/Beetle.java @@ -0,0 +1,43 @@ +// reuse/Beetle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The full process of initialization + +class Insect { + private int i = 9; + protected int j; + Insect() { + System.out.println("i = " + i + ", j = " + j); + j = 39; + } + private static int x1 = + printInit("static Insect.x1 initialized"); + static int printInit(String s) { + System.out.println(s); + return 47; + } +} + +public class Beetle extends Insect { + private int k = printInit("Beetle.k initialized"); + public Beetle() { + System.out.println("k = " + k); + System.out.println("j = " + j); + } + private static int x2 = + printInit("static Beetle.x2 initialized"); + public static void main(String[] args) { + System.out.println("Beetle constructor"); + Beetle b = new Beetle(); + } +} +/* Output: +static Insect.x1 initialized +static Beetle.x2 initialized +Beetle constructor +i = 9, j = 0 +Beetle.k initialized +k = 47 +j = 39 +*/ diff --git a/code/reuse/BlankFinal.java b/code/reuse/BlankFinal.java new file mode 100644 index 00000000..93818a06 --- /dev/null +++ b/code/reuse/BlankFinal.java @@ -0,0 +1,29 @@ +// reuse/BlankFinal.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// "Blank" final fields + +class Poppet { + private int i; + Poppet(int ii) { i = ii; } +} + +public class BlankFinal { + private final int i = 0; // Initialized final + private final int j; // Blank final + private final Poppet p; // Blank final reference + // Blank finals MUST be initialized in constructor: + public BlankFinal() { + j = 1; // Initialize blank final + p = new Poppet(1); // Init blank final reference + } + public BlankFinal(int x) { + j = x; // Initialize blank final + p = new Poppet(x); // Init blank final reference + } + public static void main(String[] args) { + new BlankFinal(); + new BlankFinal(47); + } +} diff --git a/code/reuse/CADSystem.java b/code/reuse/CADSystem.java new file mode 100644 index 00000000..55fbe0d8 --- /dev/null +++ b/code/reuse/CADSystem.java @@ -0,0 +1,116 @@ +// reuse/CADSystem.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Ensuring proper cleanup +// {java reuse.CADSystem} +package reuse; + +class Shape { + Shape(int i) { + System.out.println("Shape constructor"); + } + void dispose() { + System.out.println("Shape dispose"); + } +} + +class Circle extends Shape { + Circle(int i) { + super(i); + System.out.println("Drawing Circle"); + } + @Override + void dispose() { + System.out.println("Erasing Circle"); + super.dispose(); + } +} + +class Triangle extends Shape { + Triangle(int i) { + super(i); + System.out.println("Drawing Triangle"); + } + @Override + void dispose() { + System.out.println("Erasing Triangle"); + super.dispose(); + } +} + +class Line extends Shape { + private int start, end; + Line(int start, int end) { + super(start); + this.start = start; + this.end = end; + System.out.println( + "Drawing Line: " + start + ", " + end); + } + @Override + void dispose() { + System.out.println( + "Erasing Line: " + start + ", " + end); + super.dispose(); + } +} + +public class CADSystem extends Shape { + private Circle c; + private Triangle t; + private Line[] lines = new Line[3]; + public CADSystem(int i) { + super(i + 1); + for(int j = 0; j < lines.length; j++) + lines[j] = new Line(j, j*j); + c = new Circle(1); + t = new Triangle(1); + System.out.println("Combined constructor"); + } + @Override + public void dispose() { + System.out.println("CADSystem.dispose()"); + // The order of cleanup is the reverse + // of the order of initialization: + t.dispose(); + c.dispose(); + for(int i = lines.length - 1; i >= 0; i--) + lines[i].dispose(); + super.dispose(); + } + public static void main(String[] args) { + CADSystem x = new CADSystem(47); + try { + // Code and exception handling... + } finally { + x.dispose(); + } + } +} +/* Output: +Shape constructor +Shape constructor +Drawing Line: 0, 0 +Shape constructor +Drawing Line: 1, 1 +Shape constructor +Drawing Line: 2, 4 +Shape constructor +Drawing Circle +Shape constructor +Drawing Triangle +Combined constructor +CADSystem.dispose() +Erasing Triangle +Shape dispose +Erasing Circle +Shape dispose +Erasing Line: 2, 4 +Shape dispose +Erasing Line: 1, 1 +Shape dispose +Erasing Line: 0, 0 +Shape dispose +Shape dispose +*/ diff --git a/code/reuse/Car.java b/code/reuse/Car.java new file mode 100644 index 00000000..1bc4377b --- /dev/null +++ b/code/reuse/Car.java @@ -0,0 +1,43 @@ +// reuse/Car.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Composition with public objects + +class Engine { + public void start() {} + public void rev() {} + public void stop() {} +} + +class Wheel { + public void inflate(int psi) {} +} + +class Window { + public void rollup() {} + public void rolldown() {} +} + +class Door { + public Window window = new Window(); + public void open() {} + public void close() {} +} + +public class Car { + public Engine engine = new Engine(); + public Wheel[] wheel = new Wheel[4]; + public Door + left = new Door(), + right = new Door(); // 2-door + public Car() { + for(int i = 0; i < 4; i++) + wheel[i] = new Wheel(); + } + public static void main(String[] args) { + Car car = new Car(); + car.left.window.rollup(); + car.wheel[0].inflate(72); + } +} diff --git a/code/reuse/Cartoon.java b/code/reuse/Cartoon.java new file mode 100644 index 00000000..48741baf --- /dev/null +++ b/code/reuse/Cartoon.java @@ -0,0 +1,31 @@ +// reuse/Cartoon.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Constructor calls during inheritance + +class Art { + Art() { + System.out.println("Art constructor"); + } +} + +class Drawing extends Art { + Drawing() { + System.out.println("Drawing constructor"); + } +} + +public class Cartoon extends Drawing { + public Cartoon() { + System.out.println("Cartoon constructor"); + } + public static void main(String[] args) { + Cartoon x = new Cartoon(); + } +} +/* Output: +Art constructor +Drawing constructor +Cartoon constructor +*/ diff --git a/code/reuse/Chess.java b/code/reuse/Chess.java new file mode 100644 index 00000000..30f2685b --- /dev/null +++ b/code/reuse/Chess.java @@ -0,0 +1,33 @@ +// reuse/Chess.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Inheritance, constructors and arguments + +class Game { + Game(int i) { + System.out.println("Game constructor"); + } +} + +class BoardGame extends Game { + BoardGame(int i) { + super(i); + System.out.println("BoardGame constructor"); + } +} + +public class Chess extends BoardGame { + Chess() { + super(11); + System.out.println("Chess constructor"); + } + public static void main(String[] args) { + Chess x = new Chess(); + } +} +/* Output: +Game constructor +BoardGame constructor +Chess constructor +*/ diff --git a/code/reuse/DerivedSpaceShip.java b/code/reuse/DerivedSpaceShip.java new file mode 100644 index 00000000..dfbe20ac --- /dev/null +++ b/code/reuse/DerivedSpaceShip.java @@ -0,0 +1,19 @@ +// reuse/DerivedSpaceShip.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class +DerivedSpaceShip extends SpaceShipControls { + private String name; + public DerivedSpaceShip(String name) { + this.name = name; + } + @Override + public String toString() { return name; } + public static void main(String[] args) { + DerivedSpaceShip protector = + new DerivedSpaceShip("NSEA Protector"); + protector.forward(100); + } +} diff --git a/code/reuse/Detergent.java b/code/reuse/Detergent.java new file mode 100644 index 00000000..99f4e7cc --- /dev/null +++ b/code/reuse/Detergent.java @@ -0,0 +1,48 @@ +// reuse/Detergent.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Inheritance syntax & properties + +class Cleanser { + private String s = "Cleanser"; + public void append(String a) { s += a; } + public void dilute() { append(" dilute()"); } + public void apply() { append(" apply()"); } + public void scrub() { append(" scrub()"); } + @Override + public String toString() { return s; } + public static void main(String[] args) { + Cleanser x = new Cleanser(); + x.dilute(); x.apply(); x.scrub(); + System.out.println(x); + } +} + +public class Detergent extends Cleanser { + // Change a method: + @Override + public void scrub() { + append(" Detergent.scrub()"); + super.scrub(); // Call base-class version + } + // Add methods to the interface: + public void foam() { append(" foam()"); } + // Test the new class: + public static void main(String[] args) { + Detergent x = new Detergent(); + x.dilute(); + x.apply(); + x.scrub(); + x.foam(); + System.out.println(x); + System.out.println("Testing base class:"); + Cleanser.main(args); + } +} +/* Output: +Cleanser dilute() apply() Detergent.scrub() scrub() +foam() +Testing base class: +Cleanser dilute() apply() scrub() +*/ diff --git a/code/reuse/FinalArguments.java b/code/reuse/FinalArguments.java new file mode 100644 index 00000000..46efed7e --- /dev/null +++ b/code/reuse/FinalArguments.java @@ -0,0 +1,27 @@ +// reuse/FinalArguments.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using "final" with method arguments + +class Gizmo { + public void spin() {} +} + +public class FinalArguments { + void with(final Gizmo g) { + //- g = new Gizmo(); // Illegal -- g is final + } + void without(Gizmo g) { + g = new Gizmo(); // OK -- g not final + g.spin(); + } + // void f(final int i) { i++; } // Can't change + // You can only read from a final primitive: + int g(final int i) { return i + 1; } + public static void main(String[] args) { + FinalArguments bf = new FinalArguments(); + bf.without(null); + bf.with(null); + } +} diff --git a/code/reuse/FinalData.java b/code/reuse/FinalData.java new file mode 100644 index 00000000..4376f5c3 --- /dev/null +++ b/code/reuse/FinalData.java @@ -0,0 +1,57 @@ +// reuse/FinalData.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The effect of final on fields +import java.util.*; + +class Value { + int i; // Package access + Value(int i) { this.i = i; } +} + +public class FinalData { + private static Random rand = new Random(47); + private String id; + public FinalData(String id) { this.id = id; } + // Can be compile-time constants: + private final int valueOne = 9; + private static final int VALUE_TWO = 99; + // Typical public constant: + public static final int VALUE_THREE = 39; + // Cannot be compile-time constants: + private final int i4 = rand.nextInt(20); + static final int INT_5 = rand.nextInt(20); + private Value v1 = new Value(11); + private final Value v2 = new Value(22); + private static final Value VAL_3 = new Value(33); + // Arrays: + private final int[] a = { 1, 2, 3, 4, 5, 6 }; + @Override + public String toString() { + return id + ": " + "i4 = " + i4 + + ", INT_5 = " + INT_5; + } + public static void main(String[] args) { + FinalData fd1 = new FinalData("fd1"); + //- fd1.valueOne++; // Error: can't change value + fd1.v2.i++; // Object isn't constant! + fd1.v1 = new Value(9); // OK -- not final + for(int i = 0; i < fd1.a.length; i++) + fd1.a[i]++; // Object isn't constant! + //- fd1.v2 = new Value(0); // Error: Can't + //- fd1.VAL_3 = new Value(1); // change reference + //- fd1.a = new int[3]; + System.out.println(fd1); + System.out.println("Creating new FinalData"); + FinalData fd2 = new FinalData("fd2"); + System.out.println(fd1); + System.out.println(fd2); + } +} +/* Output: +fd1: i4 = 15, INT_5 = 18 +Creating new FinalData +fd1: i4 = 15, INT_5 = 18 +fd2: i4 = 13, INT_5 = 18 +*/ diff --git a/code/reuse/FinalOverridingIllusion.java b/code/reuse/FinalOverridingIllusion.java new file mode 100644 index 00000000..e5c19ece --- /dev/null +++ b/code/reuse/FinalOverridingIllusion.java @@ -0,0 +1,56 @@ +// reuse/FinalOverridingIllusion.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// It only looks like you can override +// a private or private final method + +class WithFinals { + // Identical to "private" alone: + private final void f() { + System.out.println("WithFinals.f()"); + } + // Also automatically "final": + private void g() { + System.out.println("WithFinals.g()"); + } +} + +class OverridingPrivate extends WithFinals { + private final void f() { + System.out.println("OverridingPrivate.f()"); + } + private void g() { + System.out.println("OverridingPrivate.g()"); + } +} + +class OverridingPrivate2 extends OverridingPrivate { + public final void f() { + System.out.println("OverridingPrivate2.f()"); + } + public void g() { + System.out.println("OverridingPrivate2.g()"); + } +} + +public class FinalOverridingIllusion { + public static void main(String[] args) { + OverridingPrivate2 op2 = new OverridingPrivate2(); + op2.f(); + op2.g(); + // You can upcast: + OverridingPrivate op = op2; + // But you can't call the methods: + //- op.f(); + //- op.g(); + // Same here: + WithFinals wf = op2; + //- wf.f(); + //- wf.g(); + } +} +/* Output: +OverridingPrivate2.f() +OverridingPrivate2.g() +*/ diff --git a/code/reuse/Hide.java b/code/reuse/Hide.java new file mode 100644 index 00000000..f718e4b0 --- /dev/null +++ b/code/reuse/Hide.java @@ -0,0 +1,41 @@ +// reuse/Hide.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Overloading a base-class method name in a derived +// class does not hide the base-class versions + +class Homer { + char doh(char c) { + System.out.println("doh(char)"); + return 'd'; + } + float doh(float f) { + System.out.println("doh(float)"); + return 1.0f; + } +} + +class Milhouse {} + +class Bart extends Homer { + void doh(Milhouse m) { + System.out.println("doh(Milhouse)"); + } +} + +public class Hide { + public static void main(String[] args) { + Bart b = new Bart(); + b.doh(1); + b.doh('x'); + b.doh(1.0f); + b.doh(new Milhouse()); + } +} +/* Output: +doh(float) +doh(char) +doh(float) +doh(Milhouse) +*/ diff --git a/code/reuse/Jurassic.java b/code/reuse/Jurassic.java new file mode 100644 index 00000000..04b7d61c --- /dev/null +++ b/code/reuse/Jurassic.java @@ -0,0 +1,26 @@ +// reuse/Jurassic.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Making an entire class final + +class SmallBrain {} + +final class Dinosaur { + int i = 7; + int j = 1; + SmallBrain x = new SmallBrain(); + void f() {} +} + +//- class Further extends Dinosaur {} +// error: Cannot extend final class 'Dinosaur' + +public class Jurassic { + public static void main(String[] args) { + Dinosaur n = new Dinosaur(); + n.f(); + n.i = 40; + n.j++; + } +} diff --git a/code/reuse/Lisa.java b/code/reuse/Lisa.java new file mode 100644 index 00000000..85ec5cc9 --- /dev/null +++ b/code/reuse/Lisa.java @@ -0,0 +1,11 @@ +// reuse/Lisa.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {WillNotCompile} + +class Lisa extends Homer { + @Override void doh(Milhouse m) { + System.out.println("doh(Milhouse)"); + } +} diff --git a/code/reuse/Orc.java b/code/reuse/Orc.java new file mode 100644 index 00000000..c3ba40a8 --- /dev/null +++ b/code/reuse/Orc.java @@ -0,0 +1,41 @@ +// reuse/Orc.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The protected keyword + +class Villain { + private String name; + protected void set(String nm) { name = nm; } + Villain(String name) { this.name = name; } + @Override + public String toString() { + return "I'm a Villain and my name is " + name; + } +} + +public class Orc extends Villain { + private int orcNumber; + public Orc(String name, int orcNumber) { + super(name); + this.orcNumber = orcNumber; + } + public void change(String name, int orcNumber) { + set(name); // Available because it's protected + this.orcNumber = orcNumber; + } + @Override + public String toString() { + return "Orc " + orcNumber + ": " + super.toString(); + } + public static void main(String[] args) { + Orc orc = new Orc("Limburger", 12); + System.out.println(orc); + orc.change("Bob", 19); + System.out.println(orc); + } +} +/* Output: +Orc 12: I'm a Villain and my name is Limburger +Orc 19: I'm a Villain and my name is Bob +*/ diff --git a/code/reuse/PlaceSetting.java b/code/reuse/PlaceSetting.java new file mode 100644 index 00000000..b57d6383 --- /dev/null +++ b/code/reuse/PlaceSetting.java @@ -0,0 +1,82 @@ +// reuse/PlaceSetting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Combining composition & inheritance + +class Plate { + Plate(int i) { + System.out.println("Plate constructor"); + } +} + +class DinnerPlate extends Plate { + DinnerPlate(int i) { + super(i); + System.out.println("DinnerPlate constructor"); + } +} + +class Utensil { + Utensil(int i) { + System.out.println("Utensil constructor"); + } +} + +class Spoon extends Utensil { + Spoon(int i) { + super(i); + System.out.println("Spoon constructor"); + } +} + +class Fork extends Utensil { + Fork(int i) { + super(i); + System.out.println("Fork constructor"); + } +} + +class Knife extends Utensil { + Knife(int i) { + super(i); + System.out.println("Knife constructor"); + } +} + +// A cultural way of doing something: +class Custom { + Custom(int i) { + System.out.println("Custom constructor"); + } +} + +public class PlaceSetting extends Custom { + private Spoon sp; + private Fork frk; + private Knife kn; + private DinnerPlate pl; + public PlaceSetting(int i) { + super(i + 1); + sp = new Spoon(i + 2); + frk = new Fork(i + 3); + kn = new Knife(i + 4); + pl = new DinnerPlate(i + 5); + System.out.println("PlaceSetting constructor"); + } + public static void main(String[] args) { + PlaceSetting x = new PlaceSetting(9); + } +} +/* Output: +Custom constructor +Utensil constructor +Spoon constructor +Utensil constructor +Fork constructor +Utensil constructor +Knife constructor +Plate constructor +DinnerPlate constructor +PlaceSetting constructor +*/ diff --git a/code/reuse/SpaceShipControls.java b/code/reuse/SpaceShipControls.java new file mode 100644 index 00000000..6fde7086 --- /dev/null +++ b/code/reuse/SpaceShipControls.java @@ -0,0 +1,14 @@ +// reuse/SpaceShipControls.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SpaceShipControls { + void up(int velocity) {} + void down(int velocity) {} + void left(int velocity) {} + void right(int velocity) {} + void forward(int velocity) {} + void back(int velocity) {} + void turboBoost() {} +} diff --git a/code/reuse/SpaceShipDelegation.java b/code/reuse/SpaceShipDelegation.java new file mode 100644 index 00000000..c31316b2 --- /dev/null +++ b/code/reuse/SpaceShipDelegation.java @@ -0,0 +1,40 @@ +// reuse/SpaceShipDelegation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SpaceShipDelegation { + private String name; + private SpaceShipControls controls = + new SpaceShipControls(); + public SpaceShipDelegation(String name) { + this.name = name; + } + // Delegated methods: + public void back(int velocity) { + controls.back(velocity); + } + public void down(int velocity) { + controls.down(velocity); + } + public void forward(int velocity) { + controls.forward(velocity); + } + public void left(int velocity) { + controls.left(velocity); + } + public void right(int velocity) { + controls.right(velocity); + } + public void turboBoost() { + controls.turboBoost(); + } + public void up(int velocity) { + controls.up(velocity); + } + public static void main(String[] args) { + SpaceShipDelegation protector = + new SpaceShipDelegation("NSEA Protector"); + protector.forward(100); + } +} diff --git a/code/reuse/SprinklerSystem.java b/code/reuse/SprinklerSystem.java new file mode 100644 index 00000000..e0ccbe66 --- /dev/null +++ b/code/reuse/SprinklerSystem.java @@ -0,0 +1,41 @@ +// reuse/SprinklerSystem.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Composition for code reuse + +class WaterSource { + private String s; + WaterSource() { + System.out.println("WaterSource()"); + s = "Constructed"; + } + @Override + public String toString() { return s; } +} + +public class SprinklerSystem { + private String valve1, valve2, valve3, valve4; + private WaterSource source = new WaterSource(); + private int i; + private float f; + @Override + public String toString() { + return + "valve1 = " + valve1 + " " + + "valve2 = " + valve2 + " " + + "valve3 = " + valve3 + " " + + "valve4 = " + valve4 + "\n" + + "i = " + i + " " + "f = " + f + " " + + "source = " + source; // [1] + } + public static void main(String[] args) { + SprinklerSystem sprinklers = new SprinklerSystem(); + System.out.println(sprinklers); + } +} +/* Output: +WaterSource() +valve1 = null valve2 = null valve3 = null valve4 = null +i = 0 f = 0.0 source = Constructed +*/ diff --git a/code/reuse/Wind.java b/code/reuse/Wind.java new file mode 100644 index 00000000..3e9a05f6 --- /dev/null +++ b/code/reuse/Wind.java @@ -0,0 +1,22 @@ +// reuse/Wind.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Inheritance & upcasting + +class Instrument { + public void play() {} + static void tune(Instrument i) { + // ... + i.play(); + } +} + +// Wind objects are instruments +// because they have the same interface: +public class Wind extends Instrument { + public static void main(String[] args) { + Wind flute = new Wind(); + Instrument.tune(flute); // Upcasting + } +} diff --git a/code/serialization/APerson.java b/code/serialization/APerson.java new file mode 100644 index 00000000..1f67eb1c --- /dev/null +++ b/code/serialization/APerson.java @@ -0,0 +1,83 @@ +// serialization/APerson.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Use the XOM library to write and read XML +// nu.xom.Node comes from http://www.xom.nu +import nu.xom.*; +import java.io.*; +import java.util.*; + +public class APerson { + private String first, last; + public APerson(String first, String last) { + this.first = first; + this.last = last; + } + // Produce an XML Element from this APerson object: + public Element getXML() { + Element person = new Element("person"); + Element firstName = new Element("first"); + firstName.appendChild(first); + Element lastName = new Element("last"); + lastName.appendChild(last); + person.appendChild(firstName); + person.appendChild(lastName); + return person; + } + // Constructor restores a APerson from XML: + public APerson(Element person) { + first = person + .getFirstChildElement("first").getValue(); + last = person + .getFirstChildElement("last").getValue(); + } + @Override + public String toString() { + return first + " " + last; + } + // Make it human-readable: + public static void + format(OutputStream os, Document doc) + throws Exception { + Serializer serializer = + new Serializer(os,"ISO-8859-1"); + serializer.setIndent(4); + serializer.setMaxLength(60); + serializer.write(doc); + serializer.flush(); + } + public static void + main(String[] args) throws Exception { + List people = Arrays.asList( + new APerson("Dr. Bunsen", "Honeydew"), + new APerson("Gonzo", "The Great"), + new APerson("Phillip J.", "Fry")); + System.out.println(people); + Element root = new Element("people"); + for(APerson p : people) + root.appendChild(p.getXML()); + Document doc = new Document(root); + format(System.out, doc); + format(new BufferedOutputStream( + new FileOutputStream("People.xml")), doc); + } +} +/* Output: +[Dr. Bunsen Honeydew, Gonzo The Great, Phillip J. Fry] + + + + Dr. Bunsen + Honeydew + + + Gonzo + The Great + + + Phillip J. + Fry + + +*/ diff --git a/code/serialization/AStoreCADState.java b/code/serialization/AStoreCADState.java new file mode 100644 index 00000000..0ce8858a --- /dev/null +++ b/code/serialization/AStoreCADState.java @@ -0,0 +1,120 @@ +// serialization/AStoreCADState.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Saving the state of a fictitious CAD system +import java.io.*; +import java.util.*; +import java.util.stream.*; + +enum Color { RED, BLUE, GREEN } + +abstract class Shape implements Serializable { + private int xPos, yPos, dimension; + private static Random rand = new Random(47); + private static int counter = 0; + public abstract void setColor(Color newColor); + public abstract Color getColor(); + Shape(int xVal, int yVal, int dim) { + xPos = xVal; + yPos = yVal; + dimension = dim; + } + public String toString() { + return getClass() + "color[" + getColor() + + "] xPos[" + xPos + "] yPos[" + yPos + + "] dim[" + dimension + "]\n"; + } + public static Shape randomFactory() { + int xVal = rand.nextInt(100); + int yVal = rand.nextInt(100); + int dim = rand.nextInt(100); + switch(counter++ % 3) { + default: + case 0: return new Circle(xVal, yVal, dim); + case 1: return new Square(xVal, yVal, dim); + case 2: return new Line(xVal, yVal, dim); + } + } +} + +class Circle extends Shape { + private static Color color = Color.RED; + Circle(int xVal, int yVal, int dim) { + super(xVal, yVal, dim); + } + public void setColor(Color newColor) { + color = newColor; + } + public Color getColor() { return color; } +} + +class Square extends Shape { + private static Color color = Color.RED; + Square(int xVal, int yVal, int dim) { + super(xVal, yVal, dim); + } + public void setColor(Color newColor) { + color = newColor; + } + public Color getColor() { return color; } +} + +class Line extends Shape { + private static Color color = Color.RED; + public static void + serializeStaticState(ObjectOutputStream os) + throws IOException { os.writeObject(color); } + public static void + deserializeStaticState(ObjectInputStream os) + throws IOException, ClassNotFoundException { + color = (Color)os.readObject(); + } + Line(int xVal, int yVal, int dim) { + super(xVal, yVal, dim); + } + public void setColor(Color newColor) { + color = newColor; + } + public Color getColor() { return color; } +} + +public class AStoreCADState { + public static void main(String[] args) { + List> shapeTypes = + Arrays.asList( + Circle.class, Square.class, Line.class); + List shapes = IntStream.range(0, 10) + .mapToObj(i -> Shape.randomFactory()) + .collect(Collectors.toList()); + // Set all the static colors to GREEN: + shapes.forEach(s -> s.setColor(Color.GREEN)); + // Save the state vector: + try( + ObjectOutputStream out = + new ObjectOutputStream( + new FileOutputStream("CADState.dat")) + ) { + out.writeObject(shapeTypes); + Line.serializeStaticState(out); + out.writeObject(shapes); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Display the shapes: + System.out.println(shapes); + } +} +/* Output: +[class Circlecolor[GREEN] xPos[58] yPos[55] dim[93] +, class Squarecolor[GREEN] xPos[61] yPos[61] dim[29] +, class Linecolor[GREEN] xPos[68] yPos[0] dim[22] +, class Circlecolor[GREEN] xPos[7] yPos[88] dim[28] +, class Squarecolor[GREEN] xPos[51] yPos[89] dim[9] +, class Linecolor[GREEN] xPos[78] yPos[98] dim[61] +, class Circlecolor[GREEN] xPos[20] yPos[58] dim[16] +, class Squarecolor[GREEN] xPos[40] yPos[11] dim[22] +, class Linecolor[GREEN] xPos[4] yPos[83] dim[6] +, class Circlecolor[GREEN] xPos[75] yPos[10] dim[42] +] +*/ diff --git a/code/serialization/Alien.java b/code/serialization/Alien.java new file mode 100644 index 00000000..d0b0f5bf --- /dev/null +++ b/code/serialization/Alien.java @@ -0,0 +1,7 @@ +// serialization/Alien.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A serializable class +import java.io.*; +public class Alien implements Serializable {} diff --git a/code/serialization/Blip3.java b/code/serialization/Blip3.java new file mode 100644 index 00000000..6741298c --- /dev/null +++ b/code/serialization/Blip3.java @@ -0,0 +1,75 @@ +// serialization/Blip3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Reconstructing an externalizable object +import java.io.*; + +public class Blip3 implements Externalizable { + private int i; + private String s; // No initialization + public Blip3() { + System.out.println("Blip3 Constructor"); + // s, i not initialized + } + public Blip3(String x, int a) { + System.out.println("Blip3(String x, int a)"); + s = x; + i = a; + // s & i initialized only in non-no-arg constructor. + } + @Override + public String toString() { return s + i; } + @Override + public void writeExternal(ObjectOutput out) + throws IOException { + System.out.println("Blip3.writeExternal"); + // You must do this: + out.writeObject(s); + out.writeInt(i); + } + @Override + public void readExternal(ObjectInput in) + throws IOException, ClassNotFoundException { + System.out.println("Blip3.readExternal"); + // You must do this: + s = (String)in.readObject(); + i = in.readInt(); + } + public static void main(String[] args) { + System.out.println("Constructing objects:"); + Blip3 b3 = new Blip3("A String ", 47); + System.out.println(b3); + try( + ObjectOutputStream o = new ObjectOutputStream( + new FileOutputStream("Blip3.serialized")) + ) { + System.out.println("Saving object:"); + o.writeObject(b3); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Now get it back: + System.out.println("Recovering b3:"); + try( + ObjectInputStream in = new ObjectInputStream( + new FileInputStream("Blip3.serialized")) + ) { + b3 = (Blip3)in.readObject(); + } catch(IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + System.out.println(b3); + } +} +/* Output: +Constructing objects: +Blip3(String x, int a) +A String 47 +Saving object: +Blip3.writeExternal +Recovering b3: +Blip3 Constructor +Blip3.readExternal +A String 47 +*/ diff --git a/code/serialization/Blips.java b/code/serialization/Blips.java new file mode 100644 index 00000000..88116d84 --- /dev/null +++ b/code/serialization/Blips.java @@ -0,0 +1,80 @@ +// serialization/Blips.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple use of Externalizable & a pitfall +import java.io.*; + +class Blip1 implements Externalizable { + public Blip1() { + System.out.println("Blip1 Constructor"); + } + @Override + public void writeExternal(ObjectOutput out) + throws IOException { + System.out.println("Blip1.writeExternal"); + } + @Override + public void readExternal(ObjectInput in) + throws IOException, ClassNotFoundException { + System.out.println("Blip1.readExternal"); + } +} + +class Blip2 implements Externalizable { + Blip2() { + System.out.println("Blip2 Constructor"); + } + @Override + public void writeExternal(ObjectOutput out) + throws IOException { + System.out.println("Blip2.writeExternal"); + } + @Override + public void readExternal(ObjectInput in) + throws IOException, ClassNotFoundException { + System.out.println("Blip2.readExternal"); + } +} + +public class Blips { + public static void main(String[] args) { + System.out.println("Constructing objects:"); + Blip1 b1 = new Blip1(); + Blip2 b2 = new Blip2(); + try( + ObjectOutputStream o = new ObjectOutputStream( + new FileOutputStream("Blips.serialized")) + ) { + System.out.println("Saving objects:"); + o.writeObject(b1); + o.writeObject(b2); + } catch(IOException e) { + throw new RuntimeException(e); + } + // Now get them back: + System.out.println("Recovering b1:"); + try( + ObjectInputStream in = new ObjectInputStream( + new FileInputStream("Blips.serialized")) + ) { + b1 = (Blip1)in.readObject(); + } catch(IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + // OOPS! Throws an exception: + //- System.out.println("Recovering b2:"); + //- b2 = (Blip2)in.readObject(); + } +} +/* Output: +Constructing objects: +Blip1 Constructor +Blip2 Constructor +Saving objects: +Blip1.writeExternal +Blip2.writeExternal +Recovering b1: +Blip1 Constructor +Blip1.readExternal +*/ diff --git a/code/serialization/FreezeAlien.java b/code/serialization/FreezeAlien.java new file mode 100644 index 00000000..0fe8e831 --- /dev/null +++ b/code/serialization/FreezeAlien.java @@ -0,0 +1,19 @@ +// serialization/FreezeAlien.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Create a serialized output file +import java.io.*; + +public class FreezeAlien { + public static void + main(String[] args) throws Exception { + try( + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream("X.file")); + ) { + Alien quellek = new Alien(); + out.writeObject(quellek); + } + } +} diff --git a/code/serialization/Logon.java b/code/serialization/Logon.java new file mode 100644 index 00000000..3b910968 --- /dev/null +++ b/code/serialization/Logon.java @@ -0,0 +1,62 @@ +// serialization/Logon.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates the "transient" keyword +import java.util.concurrent.*; +import java.io.*; +import java.util.*; +import onjava.Nap; + +public class Logon implements Serializable { + private Date date = new Date(); + private String username; + private transient String password; + public Logon(String name, String pwd) { + username = name; + password = pwd; + } + @Override + public String toString() { + return "logon info: \n username: " + + username + "\n date: " + date + + "\n password: " + password; + } + public static void main(String[] args) { + Logon a = new Logon("Hulk", "myLittlePony"); + System.out.println("logon a = " + a); + try( + ObjectOutputStream o = + new ObjectOutputStream( + new FileOutputStream("Logon.dat")) + ) { + o.writeObject(a); + } catch(IOException e) { + throw new RuntimeException(e); + } + new Nap(1); + // Now get them back: + try( + ObjectInputStream in = new ObjectInputStream( + new FileInputStream("Logon.dat")) + ) { + System.out.println( + "Recovering object at " + new Date()); + a = (Logon)in.readObject(); + } catch(IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + System.out.println("logon a = " + a); + } +} +/* Output: +logon a = logon info: + username: Hulk + date: Tue May 09 06:07:47 MDT 2017 + password: myLittlePony +Recovering object at Tue May 09 06:07:49 MDT 2017 +logon a = logon info: + username: Hulk + date: Tue May 09 06:07:47 MDT 2017 + password: null +*/ diff --git a/code/serialization/MyWorld.java b/code/serialization/MyWorld.java new file mode 100644 index 00000000..99e39de3 --- /dev/null +++ b/code/serialization/MyWorld.java @@ -0,0 +1,100 @@ +// serialization/MyWorld.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.util.*; + +class House implements Serializable {} + +class Animal implements Serializable { + private String name; + private House preferredHouse; + Animal(String nm, House h) { + name = nm; + preferredHouse = h; + } + @Override + public String toString() { + return name + "[" + super.toString() + + "], " + preferredHouse + "\n"; + } +} + +public class MyWorld { + public static void main(String[] args) { + House house = new House(); + List animals = new ArrayList<>(); + animals.add( + new Animal("Bosco the dog", house)); + animals.add( + new Animal("Ralph the hamster", house)); + animals.add( + new Animal("Molly the cat", house)); + System.out.println("animals: " + animals); + try( + ByteArrayOutputStream buf1 = + new ByteArrayOutputStream(); + ObjectOutputStream o1 = + new ObjectOutputStream(buf1) + ) { + o1.writeObject(animals); + o1.writeObject(animals); // Write a 2nd set + // Write to a different stream: + try( + ByteArrayOutputStream buf2 = + new ByteArrayOutputStream(); + ObjectOutputStream o2 = + new ObjectOutputStream(buf2) + ) { + o2.writeObject(animals); + // Now get them back: + try( + ObjectInputStream in1 = + new ObjectInputStream( + new ByteArrayInputStream( + buf1.toByteArray())); + ObjectInputStream in2 = + new ObjectInputStream( + new ByteArrayInputStream( + buf2.toByteArray())) + ) { + List + animals1 = (List)in1.readObject(), + animals2 = (List)in1.readObject(), + animals3 = (List)in2.readObject(); + System.out.println( + "animals1: " + animals1); + System.out.println( + "animals2: " + animals2); + System.out.println( + "animals3: " + animals3); + } + } + } catch(IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} +/* Output: +animals: [Bosco the dog[Animal@15db9742], +House@6d06d69c +, Ralph the hamster[Animal@7852e922], House@6d06d69c +, Molly the cat[Animal@4e25154f], House@6d06d69c +] +animals1: [Bosco the dog[Animal@7ba4f24f], +House@3b9a45b3 +, Ralph the hamster[Animal@7699a589], House@3b9a45b3 +, Molly the cat[Animal@58372a00], House@3b9a45b3 +] +animals2: [Bosco the dog[Animal@7ba4f24f], +House@3b9a45b3 +, Ralph the hamster[Animal@7699a589], House@3b9a45b3 +, Molly the cat[Animal@58372a00], House@3b9a45b3 +] +animals3: [Bosco the dog[Animal@4dd8dc3], +House@6d03e736 +, Ralph the hamster[Animal@568db2f2], House@6d03e736 +, Molly the cat[Animal@378bf509], House@6d03e736 +] +*/ diff --git a/code/serialization/People.java b/code/serialization/People.java new file mode 100644 index 00000000..0e588749 --- /dev/null +++ b/code/serialization/People.java @@ -0,0 +1,28 @@ +// serialization/People.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// nu.xom.Node comes from http://www.xom.nu +// {RunFirst: APerson} +import nu.xom.*; +import java.io.File; +import java.util.*; + +public class People extends ArrayList { + public People(String fileName) throws Exception { + Document doc = + new Builder().build(new File(fileName)); + Elements elements = + doc.getRootElement().getChildElements(); + for(int i = 0; i < elements.size(); i++) + add(new APerson(elements.get(i))); + } + public static void + main(String[] args) throws Exception { + People p = new People("People.xml"); + System.out.println(p); + } +} +/* Output: +[Dr. Bunsen Honeydew, Gonzo The Great, Phillip J. Fry] +*/ diff --git a/code/serialization/RecoverCADState.java b/code/serialization/RecoverCADState.java new file mode 100644 index 00000000..612f501c --- /dev/null +++ b/code/serialization/RecoverCADState.java @@ -0,0 +1,42 @@ +// serialization/RecoverCADState.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Restoring the state of the fictitious CAD system +// {RunFirst: AStoreCADState} +import java.io.*; +import java.util.*; + +public class RecoverCADState { + @SuppressWarnings("unchecked") + public static void main(String[] args) { + try( + ObjectInputStream in = + new ObjectInputStream( + new FileInputStream("CADState.dat")) + ) { + // Read in the same order they were written: + List> shapeTypes = + (List>)in.readObject(); + Line.deserializeStaticState(in); + List shapes = + (List)in.readObject(); + System.out.println(shapes); + } catch(IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} +/* Output: +[class Circlecolor[RED] xPos[58] yPos[55] dim[93] +, class Squarecolor[RED] xPos[61] yPos[61] dim[29] +, class Linecolor[GREEN] xPos[68] yPos[0] dim[22] +, class Circlecolor[RED] xPos[7] yPos[88] dim[28] +, class Squarecolor[RED] xPos[51] yPos[89] dim[9] +, class Linecolor[GREEN] xPos[78] yPos[98] dim[61] +, class Circlecolor[RED] xPos[20] yPos[58] dim[16] +, class Squarecolor[RED] xPos[40] yPos[11] dim[22] +, class Linecolor[GREEN] xPos[4] yPos[83] dim[6] +, class Circlecolor[RED] xPos[75] yPos[10] dim[42] +] +*/ diff --git a/code/serialization/SerialCtl.java b/code/serialization/SerialCtl.java new file mode 100644 index 00000000..ed891633 --- /dev/null +++ b/code/serialization/SerialCtl.java @@ -0,0 +1,60 @@ +// serialization/SerialCtl.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Controlling serialization by adding your own +// writeObject() and readObject() methods +import java.io.*; + +public class SerialCtl implements Serializable { + private String a; + private transient String b; + public SerialCtl(String aa, String bb) { + a = "Not Transient: " + aa; + b = "Transient: " + bb; + } + @Override + public String toString() { return a + "\n" + b; } + private void writeObject(ObjectOutputStream stream) + throws IOException { + stream.defaultWriteObject(); + stream.writeObject(b); + } + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + b = (String)stream.readObject(); + } + public static void main(String[] args) { + SerialCtl sc = new SerialCtl("Test1", "Test2"); + System.out.println("Before:\n" + sc); + try ( + ByteArrayOutputStream buf = + new ByteArrayOutputStream(); + ObjectOutputStream o = + new ObjectOutputStream(buf); + ) { + o.writeObject(sc); + // Now get it back: + try ( + ObjectInputStream in = + new ObjectInputStream( + new ByteArrayInputStream( + buf.toByteArray())); + ) { + SerialCtl sc2 = (SerialCtl)in.readObject(); + System.out.println("After:\n" + sc2); + } + } catch(IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} +/* Output: +Before: +Not Transient: Test1 +Transient: Test2 +After: +Not Transient: Test1 +Transient: Test2 +*/ diff --git a/code/serialization/Worm.java b/code/serialization/Worm.java new file mode 100644 index 00000000..666beb87 --- /dev/null +++ b/code/serialization/Worm.java @@ -0,0 +1,102 @@ +// serialization/Worm.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates object serialization +import java.io.*; +import java.util.*; + +class Data implements Serializable { + private int n; + Data(int n) { this.n = n; } + @Override + public String toString() { + return Integer.toString(n); + } +} + +public class Worm implements Serializable { + private static Random rand = new Random(47); + private Data[] d = { + new Data(rand.nextInt(10)), + new Data(rand.nextInt(10)), + new Data(rand.nextInt(10)) + }; + private Worm next; + private char c; + // Value of i == number of segments + public Worm(int i, char x) { + System.out.println("Worm constructor: " + i); + c = x; + if(--i > 0) + next = new Worm(i, (char)(x + 1)); + } + public Worm() { + System.out.println("No-arg constructor"); + } + @Override + public String toString() { + StringBuilder result = new StringBuilder(":"); + result.append(c); + result.append("("); + for(Data dat : d) + result.append(dat); + result.append(")"); + if(next != null) + result.append(next); + return result.toString(); + } + public static void + main(String[] args) throws ClassNotFoundException, + IOException { + Worm w = new Worm(6, 'a'); + System.out.println("w = " + w); + try( + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream("worm.dat")) + ) { + out.writeObject("Worm storage\n"); + out.writeObject(w); + } + try( + ObjectInputStream in = new ObjectInputStream( + new FileInputStream("worm.dat")) + ) { + String s = (String)in.readObject(); + Worm w2 = (Worm)in.readObject(); + System.out.println(s + "w2 = " + w2); + } + try( + ByteArrayOutputStream bout = + new ByteArrayOutputStream(); + ObjectOutputStream out2 = + new ObjectOutputStream(bout) + ) { + out2.writeObject("Worm storage\n"); + out2.writeObject(w); + out2.flush(); + try( + ObjectInputStream in2 = new ObjectInputStream( + new ByteArrayInputStream( + bout.toByteArray())) + ) { + String s = (String)in2.readObject(); + Worm w3 = (Worm)in2.readObject(); + System.out.println(s + "w3 = " + w3); + } + } + } +} +/* Output: +Worm constructor: 6 +Worm constructor: 5 +Worm constructor: 4 +Worm constructor: 3 +Worm constructor: 2 +Worm constructor: 1 +w = :a(853):b(119):c(802):d(788):e(199):f(881) +Worm storage +w2 = :a(853):b(119):c(802):d(788):e(199):f(881) +Worm storage +w3 = :a(853):b(119):c(802):d(788):e(199):f(881) +*/ diff --git a/code/serialization/xfiles/ThawAlien.java b/code/serialization/xfiles/ThawAlien.java new file mode 100644 index 00000000..1de6ce6a --- /dev/null +++ b/code/serialization/xfiles/ThawAlien.java @@ -0,0 +1,22 @@ +// serialization/xfiles/ThawAlien.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Recover a serialized file +// {java serialization.xfiles.ThawAlien} +// {RunFirst: FreezeAlien} +package serialization.xfiles; +import java.io.*; + +public class ThawAlien { + public static void + main(String[] args) throws Exception { + ObjectInputStream in = new ObjectInputStream( + new FileInputStream(new File("X.file"))); + Object mystery = in.readObject(); + System.out.println(mystery.getClass()); + } +} +/* Output: +class Alien +*/ diff --git a/code/settings.gradle b/code/settings.gradle new file mode 100644 index 00000000..376ca105 --- /dev/null +++ b/code/settings.gradle @@ -0,0 +1,13 @@ +def isSubproject = { File file -> + file.isDirectory() && + !file.name.contains('.git') && + !file.name.contains('.gradle') && + !file.name.contains('.idea') && + !file.name.contains('build') && + !file.name.contains('gradle') && + !file.name.contains('test') +} + +String[] subprojects = rootDir.listFiles().findAll(isSubproject).collect { it.name } + +include subprojects diff --git a/code/standardio/ChangeSystemOut.java b/code/standardio/ChangeSystemOut.java new file mode 100644 index 00000000..2b37acb8 --- /dev/null +++ b/code/standardio/ChangeSystemOut.java @@ -0,0 +1,17 @@ +// standardio/ChangeSystemOut.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Turn System.out into a PrintWriter +import java.io.*; + +public class ChangeSystemOut { + public static void main(String[] args) { + PrintWriter out = + new PrintWriter(System.out, true); + out.println("Hello, world"); + } +} +/* Output: +Hello, world +*/ diff --git a/code/standardio/Echo.java b/code/standardio/Echo.java new file mode 100644 index 00000000..d1a6103e --- /dev/null +++ b/code/standardio/Echo.java @@ -0,0 +1,20 @@ +// standardio/Echo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// How to read from standard input +import java.io.*; +import onjava.TimedAbort; + +public class Echo { + public static void main(String[] args) { + TimedAbort abort = new TimedAbort(2); + new BufferedReader( + new InputStreamReader(System.in)) + .lines() + .peek(ln -> abort.restart()) + .forEach(System.out::println); + // Ctrl-Z or two seconds inactivity + // terminates the program + } +} diff --git a/code/standardio/OSExecuteDemo.java b/code/standardio/OSExecuteDemo.java new file mode 100644 index 00000000..cc2fd4b0 --- /dev/null +++ b/code/standardio/OSExecuteDemo.java @@ -0,0 +1,16 @@ +// standardio/OSExecuteDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates standard I/O redirection +// javap -cp build/classes/java/main OSExecuteDemo +// {ExcludeFromGradle} +import onjava.*; + +public class OSExecuteDemo {} +/* Output: +Compiled from "OSExecuteDemo.java" +public class OSExecuteDemo { + public OSExecuteDemo(); +} +*/ diff --git a/code/standardio/Redirecting.java b/code/standardio/Redirecting.java new file mode 100644 index 00000000..c2986a2b --- /dev/null +++ b/code/standardio/Redirecting.java @@ -0,0 +1,31 @@ +// standardio/Redirecting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates standard I/O redirection +import java.io.*; + +public class Redirecting { + public static void main(String[] args) { + PrintStream console = System.out; + try( + BufferedInputStream in = new BufferedInputStream( + new FileInputStream("Redirecting.java")); + PrintStream out = new PrintStream( + new BufferedOutputStream( + new FileOutputStream("Redirecting.txt"))) + ) { + System.setIn(in); + System.setOut(out); + System.setErr(out); + new BufferedReader( + new InputStreamReader(System.in)) + .lines() + .forEach(System.out::println); + } catch(IOException e) { + throw new RuntimeException(e); + } finally { + System.setOut(console); + } + } +} diff --git a/code/staticchecking/DogsAndRobots.cpp b/code/staticchecking/DogsAndRobots.cpp new file mode 100644 index 00000000..03b69a96 --- /dev/null +++ b/code/staticchecking/DogsAndRobots.cpp @@ -0,0 +1,33 @@ +// staticchecking/DogsAndRobots.cpp +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +#include +using namespace std; + +class Dog { +public: + void talk() { cout << "Arf!" << endl; } + void reproduce() {} +}; + +class Robot { +public: + void talk() { cout << "Click!" << endl; } + void oilChange() {} +}; + +template void speak(T speaker) { + speaker.talk(); +} + +int main() { + Dog d; + Robot r; + speak(d); + speak(r); +} +/* Output: +Arf! +Click! +*/ diff --git a/code/staticchecking/DogsAndRobots.py b/code/staticchecking/DogsAndRobots.py new file mode 100644 index 00000000..a6b239da --- /dev/null +++ b/code/staticchecking/DogsAndRobots.py @@ -0,0 +1,26 @@ +# staticchecking/DogsAndRobots.py +# (c)2020 MindView LLC: see Copyright.txt +# We make no guarantees that this code is fit for any purpose. +# Visit http://OnJava8.com for more book information. + +def speak(anything): + anything.talk() + +class Dog: + def talk(self): print("Arf!") + def reproduce(self): pass + +class Robot: + def talk(self): print("Click!") + def oilChange(self): pass + +a = Dog() +b = Robot() + +speak(a) +speak(b) + +output = """ +Arf! +Click! +""" diff --git a/code/staticchecking/NoBasePetSpeak.py b/code/staticchecking/NoBasePetSpeak.py new file mode 100644 index 00000000..cbe6c82b --- /dev/null +++ b/code/staticchecking/NoBasePetSpeak.py @@ -0,0 +1,35 @@ +# staticchecking/NoBasePetSpeak.py +# (c)2020 MindView LLC: see Copyright.txt +# We make no guarantees that this code is fit for any purpose. +# Visit http://OnJava8.com for more book information. +#- Speaking pets without base classes + +class Cat: + def speak(self): + print("meow!") + +class Dog: + def speak(self): + print("woof!") + +class Bob: + def bow(self): + print("thank you, thank you!") + def speak(self): + print("Welcome to the neighborhood!") + def drive(self): + print("beep, beep!") + +def command(pet): + pet.speak() + +pets = [ Cat(), Dog(), Bob() ] + +for pet in pets: + command(pet) + +output = """ +meow! +woof! +Welcome to the neighborhood! +""" diff --git a/code/staticchecking/PetSpeak.py b/code/staticchecking/PetSpeak.py new file mode 100644 index 00000000..e3734e2f --- /dev/null +++ b/code/staticchecking/PetSpeak.py @@ -0,0 +1,28 @@ +# staticchecking/PetSpeak.py +# (c)2020 MindView LLC: see Copyright.txt +# We make no guarantees that this code is fit for any purpose. +# Visit http://OnJava8.com for more book information. +#- Speaking pets in Python + +class Pet: + def speak(self): pass + +class Cat(Pet): + def speak(self): + print("meow!") + +class Dog(Pet): + def speak(self): + print("woof!") + +def command(pet): + pet.speak() + +pets = [ Cat(), Dog() ] # (1) +for pet in pets: # (2) + command(pet) + +output = """ +meow! +woof! +""" diff --git a/code/staticchecking/dogsandrobots.go b/code/staticchecking/dogsandrobots.go new file mode 100644 index 00000000..d3dd10cb --- /dev/null +++ b/code/staticchecking/dogsandrobots.go @@ -0,0 +1,27 @@ +// staticchecking/dogsandrobots.go +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package main +import "fmt" + +type Dog struct {} +func (this Dog) talk() { fmt.Printf("woof!\n")} +func (this Dog) reproduce() {} + +type Robot struct {} +func (this Robot) talk() { fmt.Printf("Click!\n") } +func (this Robot) oilChange() {} + +func speak(speaker interface { talk() }) { + speaker.talk(); +} + +func main() { + speak(Dog{}) + speak(Robot{}) +} +/* Output: +woof! +Click! +*/ diff --git a/code/staticchecking/dr/DogsAndRobots.java b/code/staticchecking/dr/DogsAndRobots.java new file mode 100644 index 00000000..9bede804 --- /dev/null +++ b/code/staticchecking/dr/DogsAndRobots.java @@ -0,0 +1,42 @@ +// staticchecking/dr/DogsAndRobots.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java staticchecking.dr.DogsAndRobots} +package staticchecking.dr; + +interface Speaks { void talk(); } + +class Dog implements Speaks { + public void talk() { + System.out.println("Woof!"); + } + public void reproduce() { } +} + +class Robot implements Speaks { + public void talk() { + System.out.println("Click!"); + } + public void oilChange() { } +} + +class Communicate { + public static + void speak(T speaker) { + speaker.talk(); + } +} + +public class DogsAndRobots { + public static void main(String[] args) { + Dog d = new Dog(); + Robot r = new Robot(); + Communicate.speak(d); + Communicate.speak(r); + } +} +/* Output: +Woof! +Click! +*/ diff --git a/code/staticchecking/drc/DogAndRobotCollections.java b/code/staticchecking/drc/DogAndRobotCollections.java new file mode 100644 index 00000000..16a82ed5 --- /dev/null +++ b/code/staticchecking/drc/DogAndRobotCollections.java @@ -0,0 +1,58 @@ +// staticchecking/drc/DogAndRobotCollections.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java staticchecking.drc.DogAndRobotCollections} +package staticchecking.drc; +import java.util.*; + +class Dog { + public void talk() { + System.out.println("Woof!"); + } + public void reproduce() { } +} + +class Robot { + public void talk() { + System.out.println("Click!"); + } + public void oilChange() { } +} + +public class DogAndRobotCollections { + public static void main(String[] args) { + List dogList = new ArrayList<>(); + List robotList = new ArrayList<>(); + for(int i = 0; i < 10; i++) + dogList.add(new Dog()); + //- dogList.add(new Robot()); // Compile-time error + for(int i = 0; i < 10; i++) + robotList.add(new Robot()); + //- robotList.add(new Dog()); // Compile-time error + dogList.forEach(Dog::talk); + robotList.forEach(Robot::talk); + } +} +/* Output: +Woof! +Woof! +Woof! +Woof! +Woof! +Woof! +Woof! +Woof! +Woof! +Woof! +Click! +Click! +Click! +Click! +Click! +Click! +Click! +Click! +Click! +Click! +*/ diff --git a/code/staticchecking/latent/Latent.java b/code/staticchecking/latent/Latent.java new file mode 100644 index 00000000..29e53713 --- /dev/null +++ b/code/staticchecking/latent/Latent.java @@ -0,0 +1,60 @@ +// staticchecking/latent/Latent.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java staticchecking.latent.Latent} +package staticchecking.latent; +import java.lang.reflect.*; + +class Dog { + public void talk() { + System.out.println("Woof!"); + } + public void reproduce() {} +} + +class Robot { + public void talk() { + System.out.println("Click!"); + } + public void oilChange() {} +} + +class Mime { + public void walkAgainstTheWind() {} + public String toString() { return "Mime"; } +} + +class Communicate { + public static void speak(Object speaker) { + try { + Class spkr = + speaker.getClass(); + Method talk = + spkr.getMethod("talk", (Class[])null); + talk.invoke(speaker, new Object[]{}); + } catch(NoSuchMethodException e) { + System.out.println( + speaker + " cannot talk"); + } catch(IllegalAccessException e) { + System.out.println( + speaker + " IllegalAccessException"); + } catch(InvocationTargetException e) { + System.out.println( + speaker + " InvocationTargetException"); + } + } +} + +public class Latent { + public static void main(String[] args) { + Communicate.speak(new Dog()); + Communicate.speak(new Robot()); + Communicate.speak(new Mime()); + } +} +/* Output: +Woof! +Click! +Mime cannot talk +*/ diff --git a/code/staticchecking/petspeak.go b/code/staticchecking/petspeak.go new file mode 100644 index 00000000..1d5c5e46 --- /dev/null +++ b/code/staticchecking/petspeak.go @@ -0,0 +1,51 @@ +// staticchecking/petspeak.go +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package main +import "fmt" + +type Cat struct {} +func (this Cat) speak() { fmt.Printf("meow!\n")} + +type Dog struct {} +func (this Dog) speak() { fmt.Printf("woof!\n")} + +type Bob struct {} +func (this Bob) bow() { + fmt.Printf("thank you, thank you!\n") +} +func (this Bob) speak() { + fmt.Printf("Welcome to the neighborhood!\n") +} +func (this Bob) drive() { + fmt.Printf("beep, beep!\n") +} + +type Speaker interface { + speak() +} + +func command(s Speaker) { s.speak() } + +// If "Speaker" is never used +// anywhere else, it can be anonymous: +func command2(s interface { speak() }) { s.speak() } + +func main() { + command(Cat{}) + command(Dog{}) + command(Bob{}) + command2(Cat{}) + command2(Dog{}) + command2(Bob{}) +} + +/* Output: +meow! +woof! +Welcome to the neighborhood! +meow! +woof! +Welcome to the neighborhood! +*/ diff --git a/code/staticchecking/petspeak/PetSpeak.java b/code/staticchecking/petspeak/PetSpeak.java new file mode 100644 index 00000000..0b850c3b --- /dev/null +++ b/code/staticchecking/petspeak/PetSpeak.java @@ -0,0 +1,36 @@ +// staticchecking/petspeak/PetSpeak.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Speaking pets in Java +// {java staticchecking.petspeak.PetSpeak} +package staticchecking.petspeak; + +interface Pet { + void speak(); +} + +class Cat implements Pet { + public void speak() { + System.out.println("meow!"); + } +} + +class Dog implements Pet { + public void speak() { + System.out.println("woof!"); + } +} + +public class PetSpeak { + static void command(Pet p) { p.speak(); } + public static void main(String[] args) { + Pet[] pets = { new Cat(), new Dog() }; + for(Pet pet : pets) + command(pet); + } +} +/* Output: +meow! +woof! +*/ diff --git a/code/streams/ArrayStreams.java b/code/streams/ArrayStreams.java new file mode 100644 index 00000000..dfed6e83 --- /dev/null +++ b/code/streams/ArrayStreams.java @@ -0,0 +1,31 @@ +// streams/ArrayStreams.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class ArrayStreams { + public static void main(String[] args) { + Arrays.stream( + new double[] { 3.14159, 2.718, 1.618 }) + .forEach(n -> System.out.format("%f ", n)); + System.out.println(); + Arrays.stream(new int[] { 1, 3, 5 }) + .forEach(n -> System.out.format("%d ", n)); + System.out.println(); + Arrays.stream(new long[] { 11, 22, 44, 66 }) + .forEach(n -> System.out.format("%d ", n)); + System.out.println(); + // Select a subrange: + Arrays.stream( + new int[] { 1, 3, 5, 7, 15, 28, 37 }, 3, 6) + .forEach(n -> System.out.format("%d ", n)); + } +} +/* Output: +3.141590 2.718000 1.618000 +1 3 5 +11 22 44 66 +7 15 28 +*/ diff --git a/code/streams/Bubble.java b/code/streams/Bubble.java new file mode 100644 index 00000000..5650e5ae --- /dev/null +++ b/code/streams/Bubble.java @@ -0,0 +1,18 @@ +// streams/Bubble.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class Bubble { + public final int i; + public Bubble(int n) { i = n; } + @Override + public String toString() { + return "Bubble(" + i + ")"; + } + private static int count = 0; + public static Bubble bubbler() { + return new Bubble(count++); + } +} diff --git a/code/streams/Bubbles.java b/code/streams/Bubbles.java new file mode 100644 index 00000000..1b3bd2b9 --- /dev/null +++ b/code/streams/Bubbles.java @@ -0,0 +1,20 @@ +// streams/Bubbles.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public class Bubbles { + public static void main(String[] args) { + Stream.generate(Bubble::bubbler) + .limit(5) + .forEach(System.out::println); + } +} +/* Output: +Bubble(0) +Bubble(1) +Bubble(2) +Bubble(3) +Bubble(4) +*/ diff --git a/code/streams/Cheese.dat b/code/streams/Cheese.dat new file mode 100644 index 00000000..936666ed --- /dev/null +++ b/code/streams/Cheese.dat @@ -0,0 +1,6 @@ +// streams/Cheese.dat +Not much of a cheese shop really, is it? +Finest in the district, sir. +And what leads you to that conclusion? +Well, it's so clean. +It's certainly uncontaminated by cheese. diff --git a/code/streams/CollectionToStream.java b/code/streams/CollectionToStream.java new file mode 100644 index 00000000..93236ef1 --- /dev/null +++ b/code/streams/CollectionToStream.java @@ -0,0 +1,39 @@ +// streams/CollectionToStream.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class CollectionToStream { + public static void main(String[] args) { + List bubbles = Arrays.asList( + new Bubble(1), new Bubble(2), new Bubble(3)); + System.out.println( + bubbles.stream() + .mapToInt(b -> b.i) + .sum()); + + Set w = new HashSet<>(Arrays.asList( + "It's a wonderful day for pie!".split(" "))); + w.stream() + .map(x -> x + " ") + .forEach(System.out::print); + System.out.println(); + + Map m = new HashMap<>(); + m.put("pi", 3.14159); + m.put("e", 2.718); + m.put("phi", 1.618); + m.entrySet().stream() + .map(e -> e.getKey() + ": " + e.getValue()) + .forEach(System.out::println); + } +} +/* Output: +6 +a pie! It's for wonderful day +phi: 1.618 +e: 2.718 +pi: 3.14159 +*/ diff --git a/code/streams/CreatingOptionals.java b/code/streams/CreatingOptionals.java new file mode 100644 index 00000000..7e886ddc --- /dev/null +++ b/code/streams/CreatingOptionals.java @@ -0,0 +1,37 @@ +// streams/CreatingOptionals.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +class CreatingOptionals { + static void + test(String testName, Optional opt) { + System.out.println(" === " + testName + " === "); + System.out.println(opt.orElse("Null")); + } + public static void main(String[] args) { + test("empty", Optional.empty()); + test("of", Optional.of("Howdy")); + try { + test("of", Optional.of(null)); + } catch(Exception e) { + System.out.println(e); + } + test("ofNullable", Optional.ofNullable("Hi")); + test("ofNullable", Optional.ofNullable(null)); + } +} +/* Output: + === empty === +Null + === of === +Howdy +java.lang.NullPointerException + === ofNullable === +Hi + === ofNullable === +Null +*/ diff --git a/code/streams/Duplicator.java b/code/streams/Duplicator.java new file mode 100644 index 00000000..267279c7 --- /dev/null +++ b/code/streams/Duplicator.java @@ -0,0 +1,18 @@ +// streams/Duplicator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public class Duplicator { + public static void main(String[] args) { + Stream.generate(() -> "duplicate") + .limit(3) + .forEach(System.out::println); + } +} +/* Output: +duplicate +duplicate +duplicate +*/ diff --git a/code/streams/Fibonacci.java b/code/streams/Fibonacci.java new file mode 100644 index 00000000..fa53c687 --- /dev/null +++ b/code/streams/Fibonacci.java @@ -0,0 +1,34 @@ +// streams/Fibonacci.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public class Fibonacci { + int x = 1; + Stream numbers() { + return Stream.iterate(0, i -> { + int result = x + i; + x = i; + return result; + }); + } + public static void main(String[] args) { + new Fibonacci().numbers() + .skip(20) // Don't use the first 20 + .limit(10) // Then take 10 of them + .forEach(System.out::println); + } +} +/* Output: +6765 +10946 +17711 +28657 +46368 +75025 +121393 +196418 +317811 +514229 +*/ diff --git a/code/streams/FileToWords.java b/code/streams/FileToWords.java new file mode 100644 index 00000000..7f7174cb --- /dev/null +++ b/code/streams/FileToWords.java @@ -0,0 +1,17 @@ +// streams/FileToWords.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.nio.file.*; +import java.util.stream.*; +import java.util.regex.Pattern; + +public class FileToWords { + public static Stream stream(String filePath) + throws Exception { + return Files.lines(Paths.get(filePath)) + .skip(1) // First (comment) line + .flatMap(line -> + Pattern.compile("\\W+").splitAsStream(line)); + } +} diff --git a/code/streams/FileToWordsBuilder.java b/code/streams/FileToWordsBuilder.java new file mode 100644 index 00000000..d5ac62be --- /dev/null +++ b/code/streams/FileToWordsBuilder.java @@ -0,0 +1,31 @@ +// streams/FileToWordsBuilder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.nio.file.*; +import java.util.stream.*; + +public class FileToWordsBuilder { + Stream.Builder builder = Stream.builder(); + public FileToWordsBuilder(String filePath) + throws Exception { + Files.lines(Paths.get(filePath)) + .skip(1) // Skip the comment line at the beginning + .forEach(line -> { + for(String w : line.split("[ .?,]+")) + builder.add(w); + }); + } + Stream stream() { return builder.build(); } + public static void + main(String[] args) throws Exception { + new FileToWordsBuilder("Cheese.dat").stream() + .limit(7) + .map(w -> w + " ") + .forEach(System.out::print); + } +} +/* Output: +Not much of a cheese shop really +*/ diff --git a/code/streams/FileToWordsRegexp.java b/code/streams/FileToWordsRegexp.java new file mode 100644 index 00000000..dfff507e --- /dev/null +++ b/code/streams/FileToWordsRegexp.java @@ -0,0 +1,39 @@ +// streams/FileToWordsRegexp.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.nio.file.*; +import java.util.stream.*; +import java.util.regex.Pattern; + +public class FileToWordsRegexp { + private String all; + public FileToWordsRegexp(String filePath) + throws Exception { + all = Files.lines(Paths.get(filePath)) + .skip(1) // First (comment) line + .collect(Collectors.joining(" ")); + } + public Stream stream() { + return Pattern + .compile("[ .,?]+").splitAsStream(all); + } + public static void + main(String[] args) throws Exception { + FileToWordsRegexp fw = + new FileToWordsRegexp("Cheese.dat"); + fw.stream() + .limit(7) + .map(w -> w + " ") + .forEach(System.out::print); + fw.stream() + .skip(7) + .limit(2) + .map(w -> w + " ") + .forEach(System.out::print); + } +} +/* Output: +Not much of a cheese shop really is it +*/ diff --git a/code/streams/FileToWordsTest.java b/code/streams/FileToWordsTest.java new file mode 100644 index 00000000..a81f7209 --- /dev/null +++ b/code/streams/FileToWordsTest.java @@ -0,0 +1,23 @@ +// streams/FileToWordsTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public class FileToWordsTest { + public static void + main(String[] args) throws Exception { + FileToWords.stream("Cheese.dat") + .limit(7) + .forEach(s -> System.out.format("%s ", s)); + System.out.println(); + FileToWords.stream("Cheese.dat") + .skip(7) + .limit(2) + .forEach(s -> System.out.format("%s ", s)); + } +} +/* Output: +Not much of a cheese shop really +is it +*/ diff --git a/code/streams/FlatMap.java b/code/streams/FlatMap.java new file mode 100644 index 00000000..e2b3137f --- /dev/null +++ b/code/streams/FlatMap.java @@ -0,0 +1,25 @@ +// streams/FlatMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public class FlatMap { + public static void main(String[] args) { + Stream.of(1, 2, 3) + .flatMap( + i -> Stream.of("Gonzo", "Fozzie", "Beaker")) + .forEach(System.out::println); + } +} +/* Output: +Gonzo +Fozzie +Beaker +Gonzo +Fozzie +Beaker +Gonzo +Fozzie +Beaker +*/ diff --git a/code/streams/ForEach.java b/code/streams/ForEach.java new file mode 100644 index 00000000..f0abe255 --- /dev/null +++ b/code/streams/ForEach.java @@ -0,0 +1,28 @@ +// streams/ForEach.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import static streams.RandInts.*; + +public class ForEach { + static final int SZ = 14; + public static void main(String[] args) { + rands().limit(SZ) + .forEach(n -> System.out.format("%d ", n)); + System.out.println(); + rands().limit(SZ) + .parallel() + .forEach(n -> System.out.format("%d ", n)); + System.out.println(); + rands().limit(SZ) + .parallel() + .forEachOrdered(n -> System.out.format("%d ", n)); + } +} +/* Output: +258 555 693 861 961 429 868 200 522 207 288 128 551 589 +551 861 429 589 200 522 555 693 258 128 868 288 961 207 +258 555 693 861 961 429 868 200 522 207 288 128 551 589 +*/ diff --git a/code/streams/FunctionMap.java b/code/streams/FunctionMap.java new file mode 100644 index 00000000..3c7c90e7 --- /dev/null +++ b/code/streams/FunctionMap.java @@ -0,0 +1,60 @@ +// streams/FunctionMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +class FunctionMap { + static String[] elements = { "12", "", "23", "45" }; + static Stream testStream() { + return Arrays.stream(elements); + } + static void + test(String descr, Function func) { + System.out.println(" ---( " + descr + " )---"); + testStream() + .map(func) + .forEach(System.out::println); + } + public static void main(String[] args) { + + test("add brackets", s -> "[" + s + "]"); + + test("Increment", s -> { + try { + return Integer.parseInt(s) + 1 + ""; + } catch(NumberFormatException e) { + return s; + } + }); + + test("Replace", s -> s.replace("2", "9")); + + test("Take last digit", s -> s.length() > 0 ? + s.charAt(s.length() - 1) + "" : s); + } +} +/* Output: + ---( add brackets )--- +[12] +[] +[23] +[45] + ---( Increment )--- +13 + +24 +46 + ---( Replace )--- +19 + +93 +45 + ---( Take last digit )--- +2 + +3 +5 +*/ diff --git a/code/streams/FunctionMap2.java b/code/streams/FunctionMap2.java new file mode 100644 index 00000000..4d9f2972 --- /dev/null +++ b/code/streams/FunctionMap2.java @@ -0,0 +1,32 @@ +// streams/FunctionMap2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Different input and output types +import java.util.*; +import java.util.stream.*; + +class Numbered { + final int n; + Numbered(int n) { this.n = n; } + @Override + public String toString() { + return "Numbered(" + n + ")"; + } +} + +class FunctionMap2 { + public static void main(String[] args) { + Stream.of(1, 5, 7, 9, 11, 13) + .map(Numbered::new) + .forEach(System.out::println); + } +} +/* Output: +Numbered(1) +Numbered(5) +Numbered(7) +Numbered(9) +Numbered(11) +Numbered(13) +*/ diff --git a/code/streams/FunctionMap3.java b/code/streams/FunctionMap3.java new file mode 100644 index 00000000..74236af3 --- /dev/null +++ b/code/streams/FunctionMap3.java @@ -0,0 +1,28 @@ +// streams/FunctionMap3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Producing numeric output streams +import java.util.*; +import java.util.stream.*; + +class FunctionMap3 { + public static void main(String[] args) { + Stream.of("5", "7", "9") + .mapToInt(Integer::parseInt) + .forEach(n -> System.out.format("%d ", n)); + System.out.println(); + Stream.of("17", "19", "23") + .mapToLong(Long::parseLong) + .forEach(n -> System.out.format("%d ", n)); + System.out.println(); + Stream.of("17", "1.9", ".23") + .mapToDouble(Double::parseDouble) + .forEach(n -> System.out.format("%f ", n)); + } +} +/* Output: +5 7 9 +17 19 23 +17.000000 1.900000 0.230000 +*/ diff --git a/code/streams/Generator.java b/code/streams/Generator.java new file mode 100644 index 00000000..c9aba740 --- /dev/null +++ b/code/streams/Generator.java @@ -0,0 +1,25 @@ +// streams/Generator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public class Generator implements Supplier { + Random rand = new Random(47); + char[] letters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + public String get() { + return "" + letters[rand.nextInt(letters.length)]; + } + public static void main(String[] args) { + String word = Stream.generate(new Generator()) + .limit(30) + .collect(Collectors.joining()); + System.out.println(word); + } +} +/* Output: +YNZBRNYGCFOWZNTCQRGSEGZMMJMROE +*/ diff --git a/code/streams/ImperativeRandoms.java b/code/streams/ImperativeRandoms.java new file mode 100644 index 00000000..f9baaca5 --- /dev/null +++ b/code/streams/ImperativeRandoms.java @@ -0,0 +1,21 @@ +// streams/ImperativeRandoms.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ImperativeRandoms { + public static void main(String[] args) { + Random rand = new Random(47); + SortedSet rints = new TreeSet<>(); + while(rints.size() < 7) { + int r = rand.nextInt(20); + if(r < 5) continue; + rints.add(r); + } + System.out.println(rints); + } +} +/* Output: +[7, 8, 9, 11, 13, 15, 18] +*/ diff --git a/code/streams/Informational.java b/code/streams/Informational.java new file mode 100644 index 00000000..dd80585c --- /dev/null +++ b/code/streams/Informational.java @@ -0,0 +1,27 @@ +// streams/Informational.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; +import java.util.function.*; + +public class Informational { + public static void + main(String[] args) throws Exception { + System.out.println( + FileToWords.stream("Cheese.dat").count()); + System.out.println( + FileToWords.stream("Cheese.dat") + .min(String.CASE_INSENSITIVE_ORDER) + .orElse("NONE")); + System.out.println( + FileToWords.stream("Cheese.dat") + .max(String.CASE_INSENSITIVE_ORDER) + .orElse("NONE")); + } +} +/* Output: +32 +a +you +*/ diff --git a/code/streams/LastElement.java b/code/streams/LastElement.java new file mode 100644 index 00000000..398b0488 --- /dev/null +++ b/code/streams/LastElement.java @@ -0,0 +1,24 @@ +// streams/LastElement.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class LastElement { + public static void main(String[] args) { + OptionalInt last = IntStream.range(10, 20) + .reduce((n1, n2) -> n2); + System.out.println(last.orElse(-1)); + // Non-numeric object: + Optional lastobj = + Stream.of("one", "two", "three") + .reduce((n1, n2) -> n2); + System.out.println( + lastobj.orElse("Nothing there!")); + } +} +/* Output: +19 +three +*/ diff --git a/code/streams/Looping.java b/code/streams/Looping.java new file mode 100644 index 00000000..715ad052 --- /dev/null +++ b/code/streams/Looping.java @@ -0,0 +1,20 @@ +// streams/Looping.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import static onjava.Repeat.*; + +public class Looping { + static void hi() { System.out.println("Hi!"); } + public static void main(String[] args) { + repeat(3, () -> System.out.println("Looping!")); + repeat(2, Looping::hi); + } +} +/* Output: +Looping! +Looping! +Looping! +Hi! +Hi! +*/ diff --git a/code/streams/Machine2.java b/code/streams/Machine2.java new file mode 100644 index 00000000..3d407185 --- /dev/null +++ b/code/streams/Machine2.java @@ -0,0 +1,23 @@ +// streams/Machine2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import onjava.Operations; + +public class Machine2 { + public static void main(String[] args) { + Arrays.stream(new Operations[] { + () -> Operations.show("Bing"), + () -> Operations.show("Crack"), + () -> Operations.show("Twist"), + () -> Operations.show("Pop") + }).forEach(Operations::execute); + } +} +/* Output: +Bing +Crack +Twist +Pop +*/ diff --git a/code/streams/MapCollector.java b/code/streams/MapCollector.java new file mode 100644 index 00000000..95811e4b --- /dev/null +++ b/code/streams/MapCollector.java @@ -0,0 +1,48 @@ +// streams/MapCollector.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +class Pair { + public final Character c; + public final Integer i; + Pair(Character c, Integer i) { + this.c = c; + this.i = i; + } + public Character getC() { return c; } + public Integer getI() { return i; } + @Override + public String toString() { + return "Pair(" + c + ", " + i + ")"; + } +} + +class RandomPair { + Random rand = new Random(47); + // An infinite iterator of random capital letters: + Iterator capChars = rand.ints(65,91) + .mapToObj(i -> (char)i) + .iterator(); + public Stream stream() { + return rand.ints(100, 1000).distinct() + .mapToObj(i -> new Pair(capChars.next(), i)); + } +} + +public class MapCollector { + public static void main(String[] args) { + Map map = + new RandomPair().stream() + .limit(8) + .collect( + Collectors.toMap(Pair::getI, Pair::getC)); + System.out.println(map); + } +} +/* Output: +{688=W, 309=C, 293=B, 761=N, 858=N, 668=G, 622=F, +751=N} +*/ diff --git a/code/streams/Matching.java b/code/streams/Matching.java new file mode 100644 index 00000000..f5c01bc6 --- /dev/null +++ b/code/streams/Matching.java @@ -0,0 +1,38 @@ +// streams/Matching.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrates short-circuiting of *Match() operations +import java.util.stream.*; +import java.util.function.*; +import static streams.RandInts.*; + +interface Matcher extends + BiPredicate, Predicate> {} + +public class Matching { + static void show(Matcher match, int val) { + System.out.println( + match.test( + IntStream.rangeClosed(1, 9) + .boxed() + .peek(n -> System.out.format("%d ", n)), + n -> n < val)); + } + public static void main(String[] args) { + show(Stream::allMatch, 10); + show(Stream::allMatch, 4); + show(Stream::anyMatch, 2); + show(Stream::anyMatch, 0); + show(Stream::noneMatch, 5); + show(Stream::noneMatch, 0); + } +} +/* Output: +1 2 3 4 5 6 7 8 9 true +1 2 3 4 false +1 true +1 2 3 4 5 6 7 8 9 false +1 false +1 2 3 4 5 6 7 8 9 true +*/ diff --git a/code/streams/NumericStreamInfo.java b/code/streams/NumericStreamInfo.java new file mode 100644 index 00000000..0d04b6ef --- /dev/null +++ b/code/streams/NumericStreamInfo.java @@ -0,0 +1,24 @@ +// streams/NumericStreamInfo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; +import static streams.RandInts.*; + +public class NumericStreamInfo { + public static void main(String[] args) { + System.out.println(rands().average().getAsDouble()); + System.out.println(rands().max().getAsInt()); + System.out.println(rands().min().getAsInt()); + System.out.println(rands().sum()); + System.out.println(rands().summaryStatistics()); + } +} +/* Output: +507.94 +998 +8 +50794 +IntSummaryStatistics{count=100, sum=50794, min=8, +average=507.940000, max=998} +*/ diff --git a/code/streams/OptionalBasics.java b/code/streams/OptionalBasics.java new file mode 100644 index 00000000..625c450a --- /dev/null +++ b/code/streams/OptionalBasics.java @@ -0,0 +1,23 @@ +// streams/OptionalBasics.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +class OptionalBasics { + static void test(Optional optString) { + if(optString.isPresent()) + System.out.println(optString.get()); + else + System.out.println("Nothing inside!"); + } + public static void main(String[] args) { + test(Stream.of("Epithets").findFirst()); + test(Stream.empty().findFirst()); + } +} +/* Output: +Epithets +Nothing inside! +*/ diff --git a/code/streams/OptionalFilter.java b/code/streams/OptionalFilter.java new file mode 100644 index 00000000..a2095ec3 --- /dev/null +++ b/code/streams/OptionalFilter.java @@ -0,0 +1,72 @@ +// streams/OptionalFilter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +class OptionalFilter { + static String[] elements = { + "Foo", "", "Bar", "Baz", "Bingo" + }; + static Stream testStream() { + return Arrays.stream(elements); + } + static void + test(String descr, Predicate pred) { + System.out.println(" ---( " + descr + " )---"); + for(int i = 0; i <= elements.length; i++) { + System.out.println( + testStream() + .skip(i) + .findFirst() + .filter(pred)); + } + } + public static void main(String[] args) { + test("true", str -> true); + test("false", str -> false); + test("str != \"\"", str -> str != ""); + test("str.length() == 3", str -> str.length() == 3); + test("startsWith(\"B\")", + str -> str.startsWith("B")); + } +} +/* Output: + ---( true )--- +Optional[Foo] +Optional[] +Optional[Bar] +Optional[Baz] +Optional[Bingo] +Optional.empty + ---( false )--- +Optional.empty +Optional.empty +Optional.empty +Optional.empty +Optional.empty +Optional.empty + ---( str != "" )--- +Optional[Foo] +Optional.empty +Optional[Bar] +Optional[Baz] +Optional[Bingo] +Optional.empty + ---( str.length() == 3 )--- +Optional[Foo] +Optional.empty +Optional[Bar] +Optional[Baz] +Optional.empty +Optional.empty + ---( startsWith("B") )--- +Optional.empty +Optional.empty +Optional[Bar] +Optional[Baz] +Optional[Bingo] +Optional.empty +*/ diff --git a/code/streams/OptionalFlatMap.java b/code/streams/OptionalFlatMap.java new file mode 100644 index 00000000..52e8e81e --- /dev/null +++ b/code/streams/OptionalFlatMap.java @@ -0,0 +1,73 @@ +// streams/OptionalFlatMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +class OptionalFlatMap { + static String[] elements = { "12", "", "23", "45" }; + static Stream testStream() { + return Arrays.stream(elements); + } + static void test(String descr, + Function> func) { + System.out.println(" ---( " + descr + " )---"); + for(int i = 0; i <= elements.length; i++) { + System.out.println( + testStream() + .skip(i) + .findFirst() + .flatMap(func)); + } + } + public static void main(String[] args) { + + test("Add brackets", + s -> Optional.of("[" + s + "]")); + + test("Increment", s -> { + try { + return Optional.of( + Integer.parseInt(s) + 1 + ""); + } catch(NumberFormatException e) { + return Optional.of(s); + } + }); + + test("Replace", + s -> Optional.of(s.replace("2", "9"))); + + test("Take last digit", + s -> Optional.of(s.length() > 0 ? + s.charAt(s.length() - 1) + "" + : s)); + } +} +/* Output: + ---( Add brackets )--- +Optional[[12]] +Optional[[]] +Optional[[23]] +Optional[[45]] +Optional.empty + ---( Increment )--- +Optional[13] +Optional[] +Optional[24] +Optional[46] +Optional.empty + ---( Replace )--- +Optional[19] +Optional[] +Optional[93] +Optional[45] +Optional.empty + ---( Take last digit )--- +Optional[2] +Optional[] +Optional[3] +Optional[5] +Optional.empty +*/ diff --git a/code/streams/OptionalMap.java b/code/streams/OptionalMap.java new file mode 100644 index 00000000..83ae4396 --- /dev/null +++ b/code/streams/OptionalMap.java @@ -0,0 +1,74 @@ +// streams/OptionalMap.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +class OptionalMap { + static String[] elements = { "12", "", "23", "45" }; + static Stream testStream() { + return Arrays.stream(elements); + } + static void + test(String descr, Function func) { + System.out.println(" ---( " + descr + " )---"); + for(int i = 0; i <= elements.length; i++) { + System.out.println( + testStream() + .skip(i) + .findFirst() // Produces an Optional + .map(func)); + } + } + public static void main(String[] args) { + + // If Optional is not empty, map() first extracts + // the contents which it then passes + // to the function: + + test("Add brackets", s -> "[" + s + "]"); + + test("Increment", s -> { + try { + return Integer.parseInt(s) + 1 + ""; + } catch(NumberFormatException e) { + return s; + } + }); + + test("Replace", s -> s.replace("2", "9")); + + test("Take last digit", s -> s.length() > 0 ? + s.charAt(s.length() - 1) + "" : s); + } + // After the function is finished, map() wraps the + // result in an Optional before returning it: +} +/* Output: + ---( Add brackets )--- +Optional[[12]] +Optional[[]] +Optional[[23]] +Optional[[45]] +Optional.empty + ---( Increment )--- +Optional[13] +Optional[] +Optional[24] +Optional[46] +Optional.empty + ---( Replace )--- +Optional[19] +Optional[] +Optional[93] +Optional[45] +Optional.empty + ---( Take last digit )--- +Optional[2] +Optional[] +Optional[3] +Optional[5] +Optional.empty +*/ diff --git a/code/streams/Optionals.java b/code/streams/Optionals.java new file mode 100644 index 00000000..4d0d96cb --- /dev/null +++ b/code/streams/Optionals.java @@ -0,0 +1,63 @@ +// streams/Optionals.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +public class Optionals { + static void basics(Optional optString) { + if(optString.isPresent()) + System.out.println(optString.get()); + else + System.out.println("Nothing inside!"); + } + static void ifPresent(Optional optString) { + optString.ifPresent(System.out::println); + } + static void orElse(Optional optString) { + System.out.println(optString.orElse("Nada")); + } + static void orElseGet(Optional optString) { + System.out.println( + optString.orElseGet(() -> "Generated")); + } + static void orElseThrow(Optional optString) { + try { + System.out.println(optString.orElseThrow( + () -> new Exception("Supplied"))); + } catch(Exception e) { + System.out.println("Caught " + e); + } + } + static void test(String testName, + Consumer> cos) { + System.out.println(" === " + testName + " === "); + cos.accept(Stream.of("Epithets").findFirst()); + cos.accept(Stream.empty().findFirst()); + } + public static void main(String[] args) { + test("basics", Optionals::basics); + test("ifPresent", Optionals::ifPresent); + test("orElse", Optionals::orElse); + test("orElseGet", Optionals::orElseGet); + test("orElseThrow", Optionals::orElseThrow); + } +} +/* Output: + === basics === +Epithets +Nothing inside! + === ifPresent === +Epithets + === orElse === +Epithets +Nada + === orElseGet === +Epithets +Generated + === orElseThrow === +Epithets +Caught java.lang.Exception: Supplied +*/ diff --git a/code/streams/OptionalsFromEmptyStreams.java b/code/streams/OptionalsFromEmptyStreams.java new file mode 100644 index 00000000..771a84c0 --- /dev/null +++ b/code/streams/OptionalsFromEmptyStreams.java @@ -0,0 +1,31 @@ +// streams/OptionalsFromEmptyStreams.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +class OptionalsFromEmptyStreams { + public static void main(String[] args) { + System.out.println(Stream.empty() + .findFirst()); + System.out.println(Stream.empty() + .findAny()); + System.out.println(Stream.empty() + .max(String.CASE_INSENSITIVE_ORDER)); + System.out.println(Stream.empty() + .min(String.CASE_INSENSITIVE_ORDER)); + System.out.println(Stream.empty() + .reduce((s1, s2) -> s1 + s2)); + System.out.println(IntStream.empty() + .average()); + } +} +/* Output: +Optional.empty +Optional.empty +Optional.empty +Optional.empty +Optional.empty +OptionalDouble.empty +*/ diff --git a/code/streams/Peeking.java b/code/streams/Peeking.java new file mode 100644 index 00000000..d8800515 --- /dev/null +++ b/code/streams/Peeking.java @@ -0,0 +1,22 @@ +// streams/Peeking.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Peeking { + public static void + main(String[] args) throws Exception { + FileToWords.stream("Cheese.dat") + .skip(21) + .limit(4) + .map(w -> w + " ") + .peek(System.out::print) + .map(String::toUpperCase) + .peek(System.out::print) + .map(String::toLowerCase) + .forEach(System.out::print); + } +} +/* Output: +Well WELL well it IT it s S s so SO so +*/ diff --git a/code/streams/Prime.java b/code/streams/Prime.java new file mode 100644 index 00000000..e14459d1 --- /dev/null +++ b/code/streams/Prime.java @@ -0,0 +1,31 @@ +// streams/Prime.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; +import static java.util.stream.LongStream.*; + +public class Prime { + public static boolean isPrime(long n) { + return rangeClosed(2, (long)Math.sqrt(n)) + .noneMatch(i -> n % i == 0); + } + public LongStream numbers() { + return iterate(2, i -> i + 1) + .filter(Prime::isPrime); + } + public static void main(String[] args) { + new Prime().numbers() + .limit(10) + .forEach(n -> System.out.format("%d ", n)); + System.out.println(); + new Prime().numbers() + .skip(90) + .limit(10) + .forEach(n -> System.out.format("%d ", n)); + } +} +/* Output: +2 3 5 7 11 13 17 19 23 29 +467 479 487 491 499 503 509 521 523 541 +*/ diff --git a/code/streams/RandInts.java b/code/streams/RandInts.java new file mode 100644 index 00000000..8adfc60e --- /dev/null +++ b/code/streams/RandInts.java @@ -0,0 +1,15 @@ +// streams/RandInts.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package streams; +import java.util.*; +import java.util.stream.*; + +public class RandInts { + private static int[] rints = + new Random(47).ints(0, 1000).limit(100).toArray(); + public static IntStream rands() { + return Arrays.stream(rints); + } +} diff --git a/code/streams/RandomGenerators.java b/code/streams/RandomGenerators.java new file mode 100644 index 00000000..904216ac --- /dev/null +++ b/code/streams/RandomGenerators.java @@ -0,0 +1,86 @@ +// streams/RandomGenerators.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class RandomGenerators { + public static void show(Stream stream) { + stream + .limit(4) + .forEach(System.out::println); + System.out.println("++++++++"); + } + public static void main(String[] args) { + Random rand = new Random(47); + show(rand.ints().boxed()); + show(rand.longs().boxed()); + show(rand.doubles().boxed()); + // Control the lower and upper bounds: + show(rand.ints(10, 20).boxed()); + show(rand.longs(50, 100).boxed()); + show(rand.doubles(20, 30).boxed()); + // Control the stream size: + show(rand.ints(2).boxed()); + show(rand.longs(2).boxed()); + show(rand.doubles(2).boxed()); + // Control the stream size and bounds: + show(rand.ints(3, 3, 9).boxed()); + show(rand.longs(3, 12, 22).boxed()); + show(rand.doubles(3, 11.5, 12.3).boxed()); + } +} +/* Output: +-1172028779 +1717241110 +-2014573909 +229403722 +++++++++ +2955289354441303771 +3476817843704654257 +-8917117694134521474 +4941259272818818752 +++++++++ +0.2613610344283964 +0.0508673570556899 +0.8037155449603999 +0.7620665811558285 +++++++++ +16 +10 +11 +12 +++++++++ +65 +99 +54 +58 +++++++++ +29.86777681078574 +24.83968447804611 +20.09247112332014 +24.046793846338723 +++++++++ +1169976606 +1947946283 +++++++++ +2970202997824602425 +-2325326920272830366 +++++++++ +0.7024254510631527 +0.6648552384607359 +++++++++ +6 +7 +7 +++++++++ +17 +12 +20 +++++++++ +12.27872414236691 +11.732085449736195 +12.196509449817267 +++++++++ +*/ diff --git a/code/streams/RandomWords.java b/code/streams/RandomWords.java new file mode 100644 index 00000000..3bf2e51b --- /dev/null +++ b/code/streams/RandomWords.java @@ -0,0 +1,41 @@ +// streams/RandomWords.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; +import java.io.*; +import java.nio.file.*; + +public class RandomWords implements Supplier { + List words = new ArrayList<>(); + Random rand = new Random(47); + RandomWords(String fname) throws IOException { + List lines = + Files.readAllLines(Paths.get(fname)); + // Skip the first line: + for(String line : lines.subList(1, lines.size())) { + for(String word : line.split("[ .?,]+")) + words.add(word.toLowerCase()); + } + } + public String get() { + return words.get(rand.nextInt(words.size())); + } + @Override + public String toString() { + return words.stream() + .collect(Collectors.joining(" ")); + } + public static void + main(String[] args) throws Exception { + System.out.println( + Stream.generate(new RandomWords("Cheese.dat")) + .limit(10) + .collect(Collectors.joining(" "))); + } +} +/* Output: +it shop sir the much cheese by conclusion district is +*/ diff --git a/code/streams/Randoms.java b/code/streams/Randoms.java new file mode 100644 index 00000000..f2b5f6a8 --- /dev/null +++ b/code/streams/Randoms.java @@ -0,0 +1,25 @@ +// streams/Randoms.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class Randoms { + public static void main(String[] args) { + new Random(47) + .ints(5, 20) + .distinct() + .limit(7) + .sorted() + .forEach(System.out::println); + } +} +/* Output: +6 +10 +13 +16 +17 +18 +19 +*/ diff --git a/code/streams/Ranges.java b/code/streams/Ranges.java new file mode 100644 index 00000000..d8fc681a --- /dev/null +++ b/code/streams/Ranges.java @@ -0,0 +1,29 @@ +// streams/Ranges.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import static java.util.stream.IntStream.*; + +public class Ranges { + public static void main(String[] args) { + // The traditional way: + int result = 0; + for(int i = 10; i < 20; i++) + result += i; + System.out.println(result); + + // for-in with a range: + result = 0; + for(int i : range(10, 20).toArray()) + result += i; + System.out.println(result); + + // Use streams: + System.out.println(range(10, 20).sum()); + } +} +/* Output: +145 +145 +145 +*/ diff --git a/code/streams/Reduce.java b/code/streams/Reduce.java new file mode 100644 index 00000000..0e9f07ba --- /dev/null +++ b/code/streams/Reduce.java @@ -0,0 +1,44 @@ +// streams/Reduce.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +class Frobnitz { + int size; + Frobnitz(int sz) { size = sz; } + @Override + public String toString() { + return "Frobnitz(" + size + ")"; + } + // Generator: + static Random rand = new Random(47); + static final int BOUND = 100; + static Frobnitz supply() { + return new Frobnitz(rand.nextInt(BOUND)); + } +} + +public class Reduce { + public static void main(String[] args) { + Stream.generate(Frobnitz::supply) + .limit(10) + .peek(System.out::println) + .reduce((fr0, fr1) -> fr0.size < 50 ? fr0 : fr1) + .ifPresent(System.out::println); + } +} +/* Output: +Frobnitz(58) +Frobnitz(55) +Frobnitz(93) +Frobnitz(61) +Frobnitz(61) +Frobnitz(29) +Frobnitz(68) +Frobnitz(0) +Frobnitz(22) +Frobnitz(7) +Frobnitz(29) +*/ diff --git a/code/streams/SelectElement.java b/code/streams/SelectElement.java new file mode 100644 index 00000000..86846e40 --- /dev/null +++ b/code/streams/SelectElement.java @@ -0,0 +1,24 @@ +// streams/SelectElement.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import static streams.RandInts.*; + +public class SelectElement { + public static void main(String[] args) { + System.out.println(rands().findFirst().getAsInt()); + System.out.println( + rands().parallel().findFirst().getAsInt()); + System.out.println(rands().findAny().getAsInt()); + System.out.println( + rands().parallel().findAny().getAsInt()); + } +} +/* Output: +258 +258 +258 +242 +*/ diff --git a/code/streams/Signal.java b/code/streams/Signal.java new file mode 100644 index 00000000..9dc2a9f4 --- /dev/null +++ b/code/streams/Signal.java @@ -0,0 +1,29 @@ +// streams/Signal.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +public class Signal { + private final String msg; + public Signal(String msg) { this.msg = msg; } + public String getMsg() { return msg; } + @Override + public String toString() { + return "Signal(" + msg + ")"; + } + static Random rand = new Random(47); + public static Signal morse() { + switch(rand.nextInt(4)) { + case 1: return new Signal("dot"); + case 2: return new Signal("dash"); + default: return null; + } + } + public static Stream> stream() { + return Stream.generate(Signal::morse) + .map(signal -> Optional.ofNullable(signal)); + } +} diff --git a/code/streams/SortedComparator.java b/code/streams/SortedComparator.java new file mode 100644 index 00000000..070d60a7 --- /dev/null +++ b/code/streams/SortedComparator.java @@ -0,0 +1,20 @@ +// streams/SortedComparator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SortedComparator { + public static void + main(String[] args) throws Exception { + FileToWords.stream("Cheese.dat") + .skip(10) + .limit(10) + .sorted(Comparator.reverseOrder()) + .map(w -> w + " ") + .forEach(System.out::print); + } +} +/* Output: +you what to the that sir leads in district And +*/ diff --git a/code/streams/SpecialCollector.java b/code/streams/SpecialCollector.java new file mode 100644 index 00000000..9526a73e --- /dev/null +++ b/code/streams/SpecialCollector.java @@ -0,0 +1,24 @@ +// streams/SpecialCollector.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class SpecialCollector { + public static void + main(String[] args) throws Exception { + ArrayList words = + FileToWords.stream("Cheese.dat") + .collect(ArrayList::new, + ArrayList::add, + ArrayList::addAll); + words.stream() + .filter(s -> s.equals("cheese")) + .forEach(System.out::println); + } +} +/* Output: +cheese +cheese +*/ diff --git a/code/streams/StreamOf.java b/code/streams/StreamOf.java new file mode 100644 index 00000000..c143388a --- /dev/null +++ b/code/streams/StreamOf.java @@ -0,0 +1,28 @@ +// streams/StreamOf.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public class StreamOf { + public static void main(String[] args) { + Stream.of( + new Bubble(1), new Bubble(2), new Bubble(3)) + .forEach(System.out::println); + Stream.of("It's ", "a ", "wonderful ", + "day ", "for ", "pie!") + .forEach(System.out::print); + System.out.println(); + Stream.of(3.14159, 2.718, 1.618) + .forEach(System.out::println); + } +} +/* Output: +Bubble(1) +Bubble(2) +Bubble(3) +It's a wonderful day for pie! +3.14159 +2.718 +1.618 +*/ diff --git a/code/streams/StreamOfOptionals.java b/code/streams/StreamOfOptionals.java new file mode 100644 index 00000000..f725df57 --- /dev/null +++ b/code/streams/StreamOfOptionals.java @@ -0,0 +1,37 @@ +// streams/StreamOfOptionals.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class StreamOfOptionals { + public static void main(String[] args) { + Signal.stream() + .limit(10) + .forEach(System.out::println); + System.out.println(" ---"); + Signal.stream() + .limit(10) + .filter(Optional::isPresent) + .map(Optional::get) + .forEach(System.out::println); + } +} +/* Output: +Optional[Signal(dash)] +Optional[Signal(dot)] +Optional[Signal(dash)] +Optional.empty +Optional.empty +Optional[Signal(dash)] +Optional.empty +Optional[Signal(dot)] +Optional[Signal(dash)] +Optional[Signal(dash)] + --- +Signal(dot) +Signal(dot) +Signal(dash) +Signal(dash) +*/ diff --git a/code/streams/StreamOfRandoms.java b/code/streams/StreamOfRandoms.java new file mode 100644 index 00000000..66bf2bc7 --- /dev/null +++ b/code/streams/StreamOfRandoms.java @@ -0,0 +1,20 @@ +// streams/StreamOfRandoms.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class StreamOfRandoms { + static Random rand = new Random(47); + public static void main(String[] args) { + Stream.of(1, 2, 3, 4, 5) + .flatMapToInt(i -> IntStream.concat( + rand.ints(0, 100).limit(i), IntStream.of(-1))) + .forEach(n -> System.out.format("%d ", n)); + } +} +/* Output: +58 -1 55 93 -1 61 61 29 -1 68 0 22 7 -1 88 28 51 89 9 +-1 +*/ diff --git a/code/streams/StreamOfStreams.java b/code/streams/StreamOfStreams.java new file mode 100644 index 00000000..973d83a6 --- /dev/null +++ b/code/streams/StreamOfStreams.java @@ -0,0 +1,19 @@ +// streams/StreamOfStreams.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +public class StreamOfStreams { + public static void main(String[] args) { + Stream.of(1, 2, 3) + .map(i -> Stream.of("Gonzo", "Kermit", "Beaker")) + .map(e-> e.getClass().getName()) + .forEach(System.out::println); + } +} +/* Output: +java.util.stream.ReferencePipeline$Head +java.util.stream.ReferencePipeline$Head +java.util.stream.ReferencePipeline$Head +*/ diff --git a/code/streams/TreeSetOfWords.java b/code/streams/TreeSetOfWords.java new file mode 100644 index 00000000..feaa56a2 --- /dev/null +++ b/code/streams/TreeSetOfWords.java @@ -0,0 +1,31 @@ +// streams/TreeSetOfWords.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.nio.file.*; +import java.util.stream.*; + +public class TreeSetOfWords { + public static void + main(String[] args) throws Exception { + Set words2 = + Files.lines(Paths.get("TreeSetOfWords.java")) + .flatMap(s -> Arrays.stream(s.split("\\W+"))) + .filter(s -> !s.matches("\\d+")) // No numbers + .map(String::trim) + .filter(s -> s.length() > 2) + .limit(100) + .collect(Collectors.toCollection(TreeSet::new)); + System.out.println(words2); + } +} +/* Output: +[Arrays, Collectors, Exception, Files, Output, Paths, +Set, String, System, TreeSet, TreeSetOfWords, args, +class, collect, file, filter, flatMap, get, import, +java, length, limit, lines, main, map, matches, new, +nio, numbers, out, println, public, split, static, +stream, streams, throws, toCollection, trim, util, +void, words2] +*/ diff --git a/code/strings/ArrayListDisplay.java b/code/strings/ArrayListDisplay.java new file mode 100644 index 00000000..7b83296f --- /dev/null +++ b/code/strings/ArrayListDisplay.java @@ -0,0 +1,22 @@ +// strings/ArrayListDisplay.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import generics.coffee.*; + +public class ArrayListDisplay { + public static void main(String[] args) { + List coffees = + Stream.generate(new CoffeeSupplier()) + .limit(10) + .collect(Collectors.toList()); + System.out.println(coffees); + } +} +/* Output: +[Americano 0, Latte 1, Americano 2, Mocha 3, Mocha 4, +Breve 5, Americano 6, Latte 7, Cappuccino 8, Cappuccino +9] +*/ diff --git a/code/strings/BetterRead.java b/code/strings/BetterRead.java new file mode 100644 index 00000000..a3b7aaa2 --- /dev/null +++ b/code/strings/BetterRead.java @@ -0,0 +1,37 @@ +// strings/BetterRead.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class BetterRead { + public static void main(String[] args) { + Scanner stdin = new Scanner(SimpleRead.input); + System.out.println("What is your name?"); + String name = stdin.nextLine(); + System.out.println(name); + System.out.println( + "How old are you? What is your favorite double?"); + System.out.println("(input: )"); + int age = stdin.nextInt(); + double favorite = stdin.nextDouble(); + System.out.println(age); + System.out.println(favorite); + System.out.format("Hi %s.%n", name); + System.out.format("In 5 years you will be %d.%n", + age + 5); + System.out.format("My favorite double is %f.", + favorite / 2); + } +} +/* Output: +What is your name? +Sir Robin of Camelot +How old are you? What is your favorite double? +(input: ) +22 +1.61803 +Hi Sir Robin of Camelot. +In 5 years you will be 27. +My favorite double is 0.809015. +*/ diff --git a/code/strings/Concatenation.java b/code/strings/Concatenation.java new file mode 100644 index 00000000..685f4dbb --- /dev/null +++ b/code/strings/Concatenation.java @@ -0,0 +1,15 @@ +// strings/Concatenation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Concatenation { + public static void main(String[] args) { + String mango = "mango"; + String s = "abc" + mango + "def" + 47; + System.out.println(s); + } +} +/* Output: +abcmangodef47 +*/ diff --git a/code/strings/Conversion.java b/code/strings/Conversion.java new file mode 100644 index 00000000..f839e81a --- /dev/null +++ b/code/strings/Conversion.java @@ -0,0 +1,113 @@ +// strings/Conversion.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.math.*; +import java.util.*; + +public class Conversion { + public static void main(String[] args) { + Formatter f = new Formatter(System.out); + + char u = 'a'; + System.out.println("u = 'a'"); + f.format("s: %s%n", u); + // f.format("d: %d%n", u); + f.format("c: %c%n", u); + f.format("b: %b%n", u); + // f.format("f: %f%n", u); + // f.format("e: %e%n", u); + // f.format("x: %x%n", u); + f.format("h: %h%n", u); + + int v = 121; + System.out.println("v = 121"); + f.format("d: %d%n", v); + f.format("c: %c%n", v); + f.format("b: %b%n", v); + f.format("s: %s%n", v); + // f.format("f: %f%n", v); + // f.format("e: %e%n", v); + f.format("x: %x%n", v); + f.format("h: %h%n", v); + + BigInteger w = new BigInteger("50000000000000"); + System.out.println( + "w = new BigInteger(\"50000000000000\")"); + f.format("d: %d%n", w); + // f.format("c: %c%n", w); + f.format("b: %b%n", w); + f.format("s: %s%n", w); + // f.format("f: %f%n", w); + // f.format("e: %e%n", w); + f.format("x: %x%n", w); + f.format("h: %h%n", w); + + double x = 179.543; + System.out.println("x = 179.543"); + // f.format("d: %d%n", x); + // f.format("c: %c%n", x); + f.format("b: %b%n", x); + f.format("s: %s%n", x); + f.format("f: %f%n", x); + f.format("e: %e%n", x); + // f.format("x: %x%n", x); + f.format("h: %h%n", x); + + Conversion y = new Conversion(); + System.out.println("y = new Conversion()"); + // f.format("d: %d%n", y); + // f.format("c: %c%n", y); + f.format("b: %b%n", y); + f.format("s: %s%n", y); + // f.format("f: %f%n", y); + // f.format("e: %e%n", y); + // f.format("x: %x%n", y); + f.format("h: %h%n", y); + + boolean z = false; + System.out.println("z = false"); + // f.format("d: %d%n", z); + // f.format("c: %c%n", z); + f.format("b: %b%n", z); + f.format("s: %s%n", z); + // f.format("f: %f%n", z); + // f.format("e: %e%n", z); + // f.format("x: %x%n", z); + f.format("h: %h%n", z); + } +} +/* Output: +u = 'a' +s: a +c: a +b: true +h: 61 +v = 121 +d: 121 +c: y +b: true +s: 121 +x: 79 +h: 79 +w = new BigInteger("50000000000000") +d: 50000000000000 +b: true +s: 50000000000000 +x: 2d79883d2000 +h: 8842a1a7 +x = 179.543 +b: true +s: 179.543 +f: 179.543000 +e: 1.795430e+02 +h: 1ef462c +y = new Conversion() +b: true +s: Conversion@15db9742 +h: 15db9742 +z = false +b: false +s: false +h: 4d5 +*/ diff --git a/code/strings/DatabaseException.java b/code/strings/DatabaseException.java new file mode 100644 index 00000000..e8441254 --- /dev/null +++ b/code/strings/DatabaseException.java @@ -0,0 +1,22 @@ +// strings/DatabaseException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class DatabaseException extends Exception { + public DatabaseException(int transactionID, + int queryID, String message) { + super(String.format("(t%d, q%d) %s", transactionID, + queryID, message)); + } + public static void main(String[] args) { + try { + throw new DatabaseException(3, 7, "Write failed"); + } catch(Exception e) { + System.out.println(e); + } + } +} +/* Output: +DatabaseException: (t3, q7) Write failed +*/ diff --git a/code/strings/Finding.java b/code/strings/Finding.java new file mode 100644 index 00000000..f8d7cbbc --- /dev/null +++ b/code/strings/Finding.java @@ -0,0 +1,27 @@ +// strings/Finding.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; + +public class Finding { + public static void main(String[] args) { + Matcher m = Pattern.compile("\\w+") + .matcher( + "Evening is full of the linnet's wings"); + while(m.find()) + System.out.print(m.group() + " "); + System.out.println(); + int i = 0; + while(m.find(i)) { + System.out.print(m.group() + " "); + i++; + } + } +} +/* Output: +Evening is full of the linnet s wings +Evening vening ening ning ing ng g is is s full full +ull ll l of of f the the he e linnet linnet innet nnet +net et t s s wings wings ings ngs gs s +*/ diff --git a/code/strings/Groups.java b/code/strings/Groups.java new file mode 100644 index 00000000..298caf62 --- /dev/null +++ b/code/strings/Groups.java @@ -0,0 +1,40 @@ +// strings/Groups.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; + +public class Groups { + public static final String POEM = + "Twas brillig, and the slithy toves\n" + + "Did gyre and gimble in the wabe.\n" + + "All mimsy were the borogoves,\n" + + "And the mome raths outgrabe.\n\n" + + "Beware the Jabberwock, my son,\n" + + "The jaws that bite, the claws that catch.\n" + + "Beware the Jubjub bird, and shun\n" + + "The frumious Bandersnatch."; + public static void main(String[] args) { + Matcher m = Pattern.compile( + "(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$") + .matcher(POEM); + while(m.find()) { + for(int j = 0; j <= m.groupCount(); j++) + System.out.print("[" + m.group(j) + "]"); + System.out.println(); + } + } +} +/* Output: +[the slithy toves][the][slithy toves][slithy][toves] +[in the wabe.][in][the wabe.][the][wabe.] +[were the borogoves,][were][the +borogoves,][the][borogoves,] +[mome raths outgrabe.][mome][raths +outgrabe.][raths][outgrabe.] +[Jabberwock, my son,][Jabberwock,][my son,][my][son,] +[claws that catch.][claws][that catch.][that][catch.] +[bird, and shun][bird,][and shun][and][shun] +[The frumious Bandersnatch.][The][frumious +Bandersnatch.][frumious][Bandersnatch.] +*/ diff --git a/code/strings/Hex.java b/code/strings/Hex.java new file mode 100644 index 00000000..0fbcea8e --- /dev/null +++ b/code/strings/Hex.java @@ -0,0 +1,44 @@ +// strings/Hex.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {java onjava.Hex} +package onjava; +import java.io.*; +import java.nio.file.*; + +public class Hex { + public static String format(byte[] data) { + StringBuilder result = new StringBuilder(); + int n = 0; + for(byte b : data) { + if(n % 16 == 0) + result.append(String.format("%05X: ", n)); + result.append(String.format("%02X ", b)); + n++; + if(n % 16 == 0) result.append("\n"); + } + result.append("\n"); + return result.toString(); + } + public static void + main(String[] args) throws Exception { + if(args.length == 0) + // Test by displaying this class file: + System.out.println(format( + Files.readAllBytes(Paths.get( + "build/classes/java/main/onjava/Hex.class")))); + else + System.out.println(format( + Files.readAllBytes(Paths.get(args[0])))); + } +} +/* Output: (First 6 Lines) +00000: CA FE BA BE 00 00 00 34 00 61 0A 00 05 00 31 07 +00010: 00 32 0A 00 02 00 31 08 00 33 07 00 34 0A 00 35 +00020: 00 36 0A 00 0F 00 37 0A 00 02 00 38 08 00 39 0A +00030: 00 3A 00 3B 08 00 3C 0A 00 02 00 3D 09 00 3E 00 +00040: 3F 08 00 40 07 00 41 0A 00 42 00 43 0A 00 44 00 +00050: 45 0A 00 14 00 46 0A 00 47 00 48 07 00 49 01 00 + ... +*/ diff --git a/code/strings/Immutable.java b/code/strings/Immutable.java new file mode 100644 index 00000000..4c8b529e --- /dev/null +++ b/code/strings/Immutable.java @@ -0,0 +1,22 @@ +// strings/Immutable.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Immutable { + public static String upcase(String s) { + return s.toUpperCase(); + } + public static void main(String[] args) { + String q = "howdy"; + System.out.println(q); // howdy + String qq = upcase(q); + System.out.println(qq); // HOWDY + System.out.println(q); // howdy + } +} +/* Output: +howdy +HOWDY +howdy +*/ diff --git a/code/strings/InfiniteRecursion.java b/code/strings/InfiniteRecursion.java new file mode 100644 index 00000000..6941490a --- /dev/null +++ b/code/strings/InfiniteRecursion.java @@ -0,0 +1,22 @@ +// strings/InfiniteRecursion.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Accidental recursion +// {ThrowsException} +// {VisuallyInspectOutput} Throws very long exception +import java.util.*; +import java.util.stream.*; + +public class InfiniteRecursion { + @Override + public String toString() { + return + " InfiniteRecursion address: " + this + "\n"; + } + public static void main(String[] args) { + Stream.generate(InfiniteRecursion::new) + .limit(10) + .forEach(System.out::println); + } +} diff --git a/code/strings/IntegerMatch.java b/code/strings/IntegerMatch.java new file mode 100644 index 00000000..5a3a38ac --- /dev/null +++ b/code/strings/IntegerMatch.java @@ -0,0 +1,19 @@ +// strings/IntegerMatch.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class IntegerMatch { + public static void main(String[] args) { + System.out.println("-1234".matches("-?\\d+")); + System.out.println("5678".matches("-?\\d+")); + System.out.println("+911".matches("-?\\d+")); + System.out.println("+911".matches("(-|\\+)?\\d+")); + } +} +/* Output: +true +true +false +true +*/ diff --git a/code/strings/JGrep.java b/code/strings/JGrep.java new file mode 100644 index 00000000..49cec954 --- /dev/null +++ b/code/strings/JGrep.java @@ -0,0 +1,36 @@ +// strings/JGrep.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// A very simple version of the "grep" program +// {java JGrep +// WhitherStringBuilder.java 'return|for|String'} +import java.util.regex.*; +import java.nio.file.*; +import java.util.stream.*; + +public class JGrep { + public static void + main(String[] args) throws Exception { + if(args.length < 2) { + System.out.println( + "Usage: java JGrep file regex"); + System.exit(0); + } + Pattern p = Pattern.compile(args[1]); + // Iterate through the lines of the input file: + int index = 0; + Matcher m = p.matcher(""); + for(String line : + Files.readAllLines(Paths.get(args[0]))) { + m.reset(line); + while(m.find()) + System.out.println(index++ + ": " + + m.group() + ": " + m.start()); + } + } +} +/* Output: +0: for: 4 +1: for: 4 +*/ diff --git a/code/strings/ReFlags.java b/code/strings/ReFlags.java new file mode 100644 index 00000000..856806ee --- /dev/null +++ b/code/strings/ReFlags.java @@ -0,0 +1,23 @@ +// strings/ReFlags.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; + +public class ReFlags { + public static void main(String[] args) { + Pattern p = Pattern.compile("^java", + Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + Matcher m = p.matcher( + "java has regex\nJava has regex\n" + + "JAVA has pretty good regular expressions\n" + + "Regular expressions are in Java"); + while(m.find()) + System.out.println(m.group()); + } +} +/* Output: +java +Java +JAVA +*/ diff --git a/code/strings/ReceiptBuilder.java b/code/strings/ReceiptBuilder.java new file mode 100644 index 00000000..234ca1e6 --- /dev/null +++ b/code/strings/ReceiptBuilder.java @@ -0,0 +1,48 @@ +// strings/ReceiptBuilder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ReceiptBuilder { + private double total = 0; + private Formatter f = + new Formatter(new StringBuilder()); + public ReceiptBuilder() { + f.format( + "%-15s %5s %10s%n", "Item", "Qty", "Price"); + f.format( + "%-15s %5s %10s%n", "----", "---", "-----"); + } + public void add(String name, int qty, double price) { + f.format("%-15.15s %5d %10.2f%n", name, qty, price); + total += price * qty; + } + public String build() { + f.format("%-15s %5s %10.2f%n", "Tax", "", + total * 0.06); + f.format("%-15s %5s %10s%n", "", "", "-----"); + f.format("%-15s %5s %10.2f%n", "Total", "", + total * 1.06); + return f.toString(); + } + public static void main(String[] args) { + ReceiptBuilder receiptBuilder = + new ReceiptBuilder(); + receiptBuilder.add("Jack's Magic Beans", 4, 4.25); + receiptBuilder.add("Princess Peas", 3, 5.1); + receiptBuilder.add( + "Three Bears Porridge", 1, 14.29); + System.out.println(receiptBuilder.build()); + } +} +/* Output: +Item Qty Price +---- --- ----- +Jack's Magic Be 4 4.25 +Princess Peas 3 5.10 +Three Bears Por 1 14.29 +Tax 2.80 + ----- +Total 49.39 +*/ diff --git a/code/strings/Replacing.java b/code/strings/Replacing.java new file mode 100644 index 00000000..dbc21afe --- /dev/null +++ b/code/strings/Replacing.java @@ -0,0 +1,21 @@ +// strings/Replacing.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Replacing { + static String s = Splitting.knights; + public static void main(String[] args) { + System.out.println( + s.replaceFirst("f\\w+", "located")); + System.out.println( + s.replaceAll("shrubbery|tree|herring","banana")); + } +} +/* Output: +Then, when you have located the shrubbery, you must cut +down the mightiest tree in the forest...with... a +herring! +Then, when you have found the banana, you must cut down +the mightiest banana in the forest...with... a banana! +*/ diff --git a/code/strings/ReplacingStringTokenizer.java b/code/strings/ReplacingStringTokenizer.java new file mode 100644 index 00000000..60fad184 --- /dev/null +++ b/code/strings/ReplacingStringTokenizer.java @@ -0,0 +1,26 @@ +// strings/ReplacingStringTokenizer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ReplacingStringTokenizer { + public static void main(String[] args) { + String input = + "But I'm not dead yet! I feel happy!"; + StringTokenizer stoke = new StringTokenizer(input); + while(stoke.hasMoreElements()) + System.out.print(stoke.nextToken() + " "); + System.out.println(); + System.out.println( + Arrays.toString(input.split(" "))); + Scanner scanner = new Scanner(input); + while(scanner.hasNext()) + System.out.print(scanner.next() + " "); + } +} +/* Output: +But I'm not dead yet! I feel happy! +[But, I'm, not, dead, yet!, I, feel, happy!] +But I'm not dead yet! I feel happy! +*/ diff --git a/code/strings/Resetting.java b/code/strings/Resetting.java new file mode 100644 index 00000000..f1565390 --- /dev/null +++ b/code/strings/Resetting.java @@ -0,0 +1,23 @@ +// strings/Resetting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; + +public class Resetting { + public static void + main(String[] args) throws Exception { + Matcher m = Pattern.compile("[frb][aiu][gx]") + .matcher("fix the rug with bags"); + while(m.find()) + System.out.print(m.group() + " "); + System.out.println(); + m.reset("fix the rig with rags"); + while(m.find()) + System.out.print(m.group() + " "); + } +} +/* Output: +fix rug bag +fix rig rag +*/ diff --git a/code/strings/Rudolph.java b/code/strings/Rudolph.java new file mode 100644 index 00000000..7a338510 --- /dev/null +++ b/code/strings/Rudolph.java @@ -0,0 +1,21 @@ +// strings/Rudolph.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class Rudolph { + public static void main(String[] args) { + for(String pattern : new String[]{ + "Rudolph", + "[rR]udolph", + "[rR][aeiou][a-z]ol.*", + "R.*" }) + System.out.println("Rudolph".matches(pattern)); + } +} +/* Output: +true +true +true +true +*/ diff --git a/code/strings/ScannerDelimiter.java b/code/strings/ScannerDelimiter.java new file mode 100644 index 00000000..a06ed990 --- /dev/null +++ b/code/strings/ScannerDelimiter.java @@ -0,0 +1,21 @@ +// strings/ScannerDelimiter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class ScannerDelimiter { + public static void main(String[] args) { + Scanner scanner = new Scanner("12, 42, 78, 99, 42"); + scanner.useDelimiter("\\s*,\\s*"); + while(scanner.hasNextInt()) + System.out.println(scanner.nextInt()); + } +} +/* Output: +12 +42 +78 +99 +42 +*/ diff --git a/code/strings/SimpleFormat.java b/code/strings/SimpleFormat.java new file mode 100644 index 00000000..a3a6e52f --- /dev/null +++ b/code/strings/SimpleFormat.java @@ -0,0 +1,22 @@ +// strings/SimpleFormat.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class SimpleFormat { + public static void main(String[] args) { + int x = 5; + double y = 5.332542; + // The old way: + System.out.println("Row 1: [" + x + " " + y + "]"); + // The new way: + System.out.format("Row 1: [%d %f]%n", x, y); + // or + System.out.printf("Row 1: [%d %f]%n", x, y); + } +} +/* Output: +Row 1: [5 5.332542] +Row 1: [5 5.332542] +Row 1: [5 5.332542] +*/ diff --git a/code/strings/SimpleRead.java b/code/strings/SimpleRead.java new file mode 100644 index 00000000..e85a058a --- /dev/null +++ b/code/strings/SimpleRead.java @@ -0,0 +1,43 @@ +// strings/SimpleRead.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; + +public class SimpleRead { + public static BufferedReader input = + new BufferedReader(new StringReader( + "Sir Robin of Camelot\n22 1.61803")); + public static void main(String[] args) { + try { + System.out.println("What is your name?"); + String name = input.readLine(); + System.out.println(name); + System.out.println("How old are you? " + + "What is your favorite double?"); + System.out.println("(input: )"); + String numbers = input.readLine(); + System.out.println(numbers); + String[] numArray = numbers.split(" "); + int age = Integer.parseInt(numArray[0]); + double favorite = Double.parseDouble(numArray[1]); + System.out.format("Hi %s.%n", name); + System.out.format("In 5 years you will be %d.%n", + age + 5); + System.out.format("My favorite double is %f.", + favorite / 2); + } catch(IOException e) { + System.err.println("I/O exception"); + } + } +} +/* Output: +What is your name? +Sir Robin of Camelot +How old are you? What is your favorite double? +(input: ) +22 1.61803 +Hi Sir Robin of Camelot. +In 5 years you will be 27. +My favorite double is 0.809015. +*/ diff --git a/code/strings/SplitDemo.java b/code/strings/SplitDemo.java new file mode 100644 index 00000000..65745392 --- /dev/null +++ b/code/strings/SplitDemo.java @@ -0,0 +1,22 @@ +// strings/SplitDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; +import java.util.*; + +public class SplitDemo { + public static void main(String[] args) { + String input = + "This!!unusual use!!of exclamation!!points"; + System.out.println(Arrays.toString( + Pattern.compile("!!").split(input))); + // Only do the first three: + System.out.println(Arrays.toString( + Pattern.compile("!!").split(input, 3))); + } +} +/* Output: +[This, unusual use, of exclamation, points] +[This, unusual use, of exclamation!!points] +*/ diff --git a/code/strings/Splitting.java b/code/strings/Splitting.java new file mode 100644 index 00000000..0afe3a40 --- /dev/null +++ b/code/strings/Splitting.java @@ -0,0 +1,32 @@ +// strings/Splitting.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class Splitting { + public static String knights = + "Then, when you have found the shrubbery, " + + "you must cut down the mightiest tree in the " + + "forest...with... a herring!"; + public static void split(String regex) { + System.out.println( + Arrays.toString(knights.split(regex))); + } + public static void main(String[] args) { + split(" "); // Doesn't have to contain regex chars + split("\\W+"); // Non-word characters + split("n\\W+"); // 'n' followed by non-words + } +} +/* Output: +[Then,, when, you, have, found, the, shrubbery,, you, +must, cut, down, the, mightiest, tree, in, the, +forest...with..., a, herring!] +[Then, when, you, have, found, the, shrubbery, you, +must, cut, down, the, mightiest, tree, in, the, forest, +with, a, herring] +[The, whe, you have found the shrubbery, you must cut +dow, the mightiest tree i, the forest...with... a +herring!] +*/ diff --git a/code/strings/StartEnd.java b/code/strings/StartEnd.java new file mode 100644 index 00000000..03caf520 --- /dev/null +++ b/code/strings/StartEnd.java @@ -0,0 +1,82 @@ +// strings/StartEnd.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; + +public class StartEnd { + public static String input = + "As long as there is injustice, whenever a\n" + + "Targathian baby cries out, wherever a distress\n" + + "signal sounds among the stars " + + "... We'll be there.\n"+ + "This fine ship, and this fine crew ...\n" + + "Never give up! Never surrender!"; + private static class Display { + private boolean regexPrinted = false; + private String regex; + Display(String regex) { this.regex = regex; } + void display(String message) { + if(!regexPrinted) { + System.out.println(regex); + regexPrinted = true; + } + System.out.println(message); + } + } + static void examine(String s, String regex) { + Display d = new Display(regex); + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(s); + while(m.find()) + d.display("find() '" + m.group() + + "' start = "+ m.start() + " end = " + m.end()); + if(m.lookingAt()) // No reset() necessary + d.display("lookingAt() start = " + + m.start() + " end = " + m.end()); + if(m.matches()) // No reset() necessary + d.display("matches() start = " + + m.start() + " end = " + m.end()); + } + public static void main(String[] args) { + for(String in : input.split("\n")) { + System.out.println("input : " + in); + for(String regex : new String[]{"\\w*ere\\w*", + "\\w*ever", "T\\w+", "Never.*?!"}) + examine(in, regex); + } + } +} +/* Output: +input : As long as there is injustice, whenever a +\w*ere\w* +find() 'there' start = 11 end = 16 +\w*ever +find() 'whenever' start = 31 end = 39 +input : Targathian baby cries out, wherever a distress +\w*ere\w* +find() 'wherever' start = 27 end = 35 +\w*ever +find() 'wherever' start = 27 end = 35 +T\w+ +find() 'Targathian' start = 0 end = 10 +lookingAt() start = 0 end = 10 +input : signal sounds among the stars ... We'll be +there. +\w*ere\w* +find() 'there' start = 43 end = 48 +input : This fine ship, and this fine crew ... +T\w+ +find() 'This' start = 0 end = 4 +lookingAt() start = 0 end = 4 +input : Never give up! Never surrender! +\w*ever +find() 'Never' start = 0 end = 5 +find() 'Never' start = 15 end = 20 +lookingAt() start = 0 end = 5 +Never.*?! +find() 'Never give up!' start = 0 end = 14 +find() 'Never surrender!' start = 15 end = 31 +lookingAt() start = 0 end = 14 +matches() start = 0 end = 31 +*/ diff --git a/code/strings/TestRegularExpression.java b/code/strings/TestRegularExpression.java new file mode 100644 index 00000000..fe79ce8b --- /dev/null +++ b/code/strings/TestRegularExpression.java @@ -0,0 +1,44 @@ +// strings/TestRegularExpression.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple regular expression demonstration +// {java TestRegularExpression +// abcabcabcdefabc "abc+" "(abc)+" } +import java.util.regex.*; + +public class TestRegularExpression { + public static void main(String[] args) { + if(args.length < 2) { + System.out.println( + "Usage:\njava TestRegularExpression " + + "characterSequence regularExpression+"); + System.exit(0); + } + System.out.println("Input: \"" + args[0] + "\""); + for(String arg : args) { + System.out.println( + "Regular expression: \"" + arg + "\""); + Pattern p = Pattern.compile(arg); + Matcher m = p.matcher(args[0]); + while(m.find()) { + System.out.println( + "Match \"" + m.group() + "\" at positions " + + m.start() + "-" + (m.end() - 1)); + } + } + } +} +/* Output: +Input: "abcabcabcdefabc" +Regular expression: "abcabcabcdefabc" +Match "abcabcabcdefabc" at positions 0-14 +Regular expression: "abc+" +Match "abc" at positions 0-2 +Match "abc" at positions 3-5 +Match "abc" at positions 6-8 +Match "abc" at positions 12-14 +Regular expression: "(abc)+" +Match "abcabcabc" at positions 0-8 +Match "abc" at positions 12-14 +*/ diff --git a/code/strings/TheReplacements.java b/code/strings/TheReplacements.java new file mode 100644 index 00000000..2319552f --- /dev/null +++ b/code/strings/TheReplacements.java @@ -0,0 +1,57 @@ +// strings/TheReplacements.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; +import java.nio.file.*; +import java.util.stream.*; + +/*! Here's a block of text to use as input to + the regular expression matcher. Note that we + first extract the block of text by looking for + the special delimiters, then process the + extracted block. !*/ + +public class TheReplacements { + public static void + main(String[] args) throws Exception { + String s = Files.lines( + Paths.get("TheReplacements.java")) + .collect(Collectors.joining("\n")); + // Match specially commented block of text above: + Matcher mInput = Pattern.compile( + "/\\*!(.*)!\\*/", Pattern.DOTALL).matcher(s); + if(mInput.find()) + s = mInput.group(1); // Captured by parentheses + // Replace two or more spaces with a single space: + s = s.replaceAll(" {2,}", " "); + // Replace 1+ spaces at the beginning of each + // line with no spaces. Must enable MULTILINE mode: + s = s.replaceAll("(?m)^ +", ""); + System.out.println(s); + s = s.replaceFirst("[aeiou]", "(VOWEL1)"); + StringBuffer sbuf = new StringBuffer(); + Pattern p = Pattern.compile("[aeiou]"); + Matcher m = p.matcher(s); + // Process the find information as you + // perform the replacements: + while(m.find()) + m.appendReplacement( + sbuf, m.group().toUpperCase()); + // Put in the remainder of the text: + m.appendTail(sbuf); + System.out.println(sbuf); + } +} +/* Output: +Here's a block of text to use as input to +the regular expression matcher. Note that we +first extract the block of text by looking for +the special delimiters, then process the +extracted block. +H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO +thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE +fIrst ExtrAct thE blOck Of tExt by lOOkIng fOr +thE spEcIAl dElImItErs, thEn prOcEss thE +ExtrActEd blOck. +*/ diff --git a/code/strings/ThreatAnalyzer.java b/code/strings/ThreatAnalyzer.java new file mode 100644 index 00000000..fc145c86 --- /dev/null +++ b/code/strings/ThreatAnalyzer.java @@ -0,0 +1,36 @@ +// strings/ThreatAnalyzer.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.regex.*; +import java.util.*; + +public class ThreatAnalyzer { + static String threatData = + "58.27.82.161@08/10/2015\n" + + "204.45.234.40@08/11/2015\n" + + "58.27.82.161@08/11/2015\n" + + "58.27.82.161@08/12/2015\n" + + "58.27.82.161@08/12/2015\n" + + "[Next log section with different data format]"; + public static void main(String[] args) { + Scanner scanner = new Scanner(threatData); + String pattern = "(\\d+[.]\\d+[.]\\d+[.]\\d+)@" + + "(\\d{2}/\\d{2}/\\d{4})"; + while(scanner.hasNext(pattern)) { + scanner.next(pattern); + MatchResult match = scanner.match(); + String ip = match.group(1); + String date = match.group(2); + System.out.format( + "Threat on %s from %s%n", date,ip); + } + } +} +/* Output: +Threat on 08/10/2015 from 58.27.82.161 +Threat on 08/11/2015 from 204.45.234.40 +Threat on 08/11/2015 from 58.27.82.161 +Threat on 08/12/2015 from 58.27.82.161 +Threat on 08/12/2015 from 58.27.82.161 +*/ diff --git a/code/strings/Turtle.java b/code/strings/Turtle.java new file mode 100644 index 00000000..68977bfc --- /dev/null +++ b/code/strings/Turtle.java @@ -0,0 +1,40 @@ +// strings/Turtle.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.io.*; +import java.util.*; + +public class Turtle { + private String name; + private Formatter f; + public Turtle(String name, Formatter f) { + this.name = name; + this.f = f; + } + public void move(int x, int y) { + f.format("%s The Turtle is at (%d,%d)%n", + name, x, y); + } + public static void main(String[] args) { + PrintStream outAlias = System.out; + Turtle tommy = new Turtle("Tommy", + new Formatter(System.out)); + Turtle terry = new Turtle("Terry", + new Formatter(outAlias)); + tommy.move(0,0); + terry.move(4,8); + tommy.move(3,4); + terry.move(2,5); + tommy.move(3,3); + terry.move(3,3); + } +} +/* Output: +Tommy The Turtle is at (0,0) +Terry The Turtle is at (4,8) +Tommy The Turtle is at (3,4) +Terry The Turtle is at (2,5) +Tommy The Turtle is at (3,3) +Terry The Turtle is at (3,3) +*/ diff --git a/code/strings/UsingStringBuilder.java b/code/strings/UsingStringBuilder.java new file mode 100644 index 00000000..0ff32410 --- /dev/null +++ b/code/strings/UsingStringBuilder.java @@ -0,0 +1,37 @@ +// strings/UsingStringBuilder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; + +public class UsingStringBuilder { + public static String string1() { + Random rand = new Random(47); + StringBuilder result = new StringBuilder("["); + for(int i = 0; i < 25; i++) { + result.append(rand.nextInt(100)); + result.append(", "); + } + result.delete(result.length()-2, result.length()); + result.append("]"); + return result.toString(); + } + public static String string2() { + String result = new Random(47) + .ints(25, 0, 100) + .mapToObj(Integer::toString) + .collect(Collectors.joining(", ")); + return "[" + result + "]"; + } + public static void main(String[] args) { + System.out.println(string1()); + System.out.println(string2()); + } +} +/* Output: +[58, 55, 93, 61, 61, 29, 68, 0, 22, 7, 88, 28, 51, 89, +9, 78, 98, 61, 20, 58, 16, 40, 11, 22, 4] +[58, 55, 93, 61, 61, 29, 68, 0, 22, 7, 88, 28, 51, 89, +9, 78, 98, 61, 20, 58, 16, 40, 11, 22, 4] +*/ diff --git a/code/strings/WhitherStringBuilder.java b/code/strings/WhitherStringBuilder.java new file mode 100644 index 00000000..0c46cae3 --- /dev/null +++ b/code/strings/WhitherStringBuilder.java @@ -0,0 +1,21 @@ +// strings/WhitherStringBuilder.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class WhitherStringBuilder { + public String implicit(String[] fields) { + String result = ""; + for(String field : fields) { + result += field; + } + return result; + } + public String explicit(String[] fields) { + StringBuilder result = new StringBuilder(); + for(String field : fields) { + result.append(field); + } + return result.toString(); + } +} diff --git a/code/typeinfo/AnonymousImplementation.java b/code/typeinfo/AnonymousImplementation.java new file mode 100644 index 00000000..34fa7832 --- /dev/null +++ b/code/typeinfo/AnonymousImplementation.java @@ -0,0 +1,50 @@ +// typeinfo/AnonymousImplementation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Anonymous inner classes can't hide from reflection +import typeinfo.interfacea.*; + +class AnonymousA { + public static A makeA() { + return new A() { + public void f() { + System.out.println("public C.f()"); + } + public void g() { + System.out.println("public C.g()"); + } + void u() { + System.out.println("package C.u()"); + } + protected void v() { + System.out.println("protected C.v()"); + } + private void w() { + System.out.println("private C.w()"); + } + }; + } +} + +public class AnonymousImplementation { + public static void + main(String[] args) throws Exception { + A a = AnonymousA.makeA(); + a.f(); + System.out.println(a.getClass().getName()); + // Reflection still gets into the anonymous class: + HiddenImplementation.callHiddenMethod(a, "g"); + HiddenImplementation.callHiddenMethod(a, "u"); + HiddenImplementation.callHiddenMethod(a, "v"); + HiddenImplementation.callHiddenMethod(a, "w"); + } +} +/* Output: +public C.f() +AnonymousA$1 +public C.g() +package C.u() +protected C.v() +private C.w() +*/ diff --git a/code/typeinfo/BoundedClassReferences.java b/code/typeinfo/BoundedClassReferences.java new file mode 100644 index 00000000..ed0945e6 --- /dev/null +++ b/code/typeinfo/BoundedClassReferences.java @@ -0,0 +1,13 @@ +// typeinfo/BoundedClassReferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class BoundedClassReferences { + public static void main(String[] args) { + Class bounded = int.class; + bounded = double.class; + bounded = Number.class; + // Or anything else derived from Number. + } +} diff --git a/code/typeinfo/ClassCasts.java b/code/typeinfo/ClassCasts.java new file mode 100644 index 00000000..fd0e17cf --- /dev/null +++ b/code/typeinfo/ClassCasts.java @@ -0,0 +1,16 @@ +// typeinfo/ClassCasts.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +class Building {} +class House extends Building {} + +public class ClassCasts { + public static void main(String[] args) { + Building b = new House(); + Class houseType = House.class; + House h = houseType.cast(b); + h = (House)b; // ... or just do this. + } +} diff --git a/code/typeinfo/ClassInitialization.java b/code/typeinfo/ClassInitialization.java new file mode 100644 index 00000000..ba1d50e8 --- /dev/null +++ b/code/typeinfo/ClassInitialization.java @@ -0,0 +1,57 @@ +// typeinfo/ClassInitialization.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class Initable { + static final int STATIC_FINAL = 47; + static final int STATIC_FINAL2 = + ClassInitialization.rand.nextInt(1000); + static { + System.out.println("Initializing Initable"); + } +} + +class Initable2 { + static int staticNonFinal = 147; + static { + System.out.println("Initializing Initable2"); + } +} + +class Initable3 { + static int staticNonFinal = 74; + static { + System.out.println("Initializing Initable3"); + } +} + +public class ClassInitialization { + public static Random rand = new Random(47); + public static void + main(String[] args) throws Exception { + Class initable = Initable.class; + System.out.println("After creating Initable ref"); + // Does not trigger initialization: + System.out.println(Initable.STATIC_FINAL); + // Does trigger initialization: + System.out.println(Initable.STATIC_FINAL2); + // Does trigger initialization: + System.out.println(Initable2.staticNonFinal); + Class initable3 = Class.forName("Initable3"); + System.out.println("After creating Initable3 ref"); + System.out.println(Initable3.staticNonFinal); + } +} +/* Output: +After creating Initable ref +47 +Initializing Initable +258 +Initializing Initable2 +147 +Initializing Initable3 +After creating Initable3 ref +74 +*/ diff --git a/code/typeinfo/DynamicSupplier.java b/code/typeinfo/DynamicSupplier.java new file mode 100644 index 00000000..271af639 --- /dev/null +++ b/code/typeinfo/DynamicSupplier.java @@ -0,0 +1,42 @@ +// typeinfo/DynamicSupplier.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; +import java.util.stream.*; + +class CountedInteger { + private static long counter; + private final long id = counter++; + @Override + public String toString() { return Long.toString(id); } +} + +public class DynamicSupplier implements Supplier { + private Class type; + public DynamicSupplier(Class type) { + this.type = type; + } + @SuppressWarnings("deprecation") + public T get() { + try { + return type.newInstance(); + } catch(Exception e) { + throw new RuntimeException(e); + } + } + public static void main(String[] args) { + Stream.generate( + new DynamicSupplier<>(CountedInteger.class)) + .skip(10) + .limit(5) + .forEach(System.out::println); + } +} +/* Output: +10 +11 +12 +13 +14 +*/ diff --git a/code/typeinfo/FamilyVsExactType.java b/code/typeinfo/FamilyVsExactType.java new file mode 100644 index 00000000..5981bbe6 --- /dev/null +++ b/code/typeinfo/FamilyVsExactType.java @@ -0,0 +1,62 @@ +// typeinfo/FamilyVsExactType.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// The difference between instanceof and class +// {java typeinfo.FamilyVsExactType} +package typeinfo; + +class Base {} +class Derived extends Base {} + +public class FamilyVsExactType { + static void test(Object x) { + System.out.println( + "Testing x of type " + x.getClass()); + System.out.println( + "x instanceof Base " + (x instanceof Base)); + System.out.println( + "x instanceof Derived " + (x instanceof Derived)); + System.out.println( + "Base.isInstance(x) " + Base.class.isInstance(x)); + System.out.println( + "Derived.isInstance(x) " + + Derived.class.isInstance(x)); + System.out.println( + "x.getClass() == Base.class " + + (x.getClass() == Base.class)); + System.out.println( + "x.getClass() == Derived.class " + + (x.getClass() == Derived.class)); + System.out.println( + "x.getClass().equals(Base.class)) "+ + (x.getClass().equals(Base.class))); + System.out.println( + "x.getClass().equals(Derived.class)) " + + (x.getClass().equals(Derived.class))); + } + public static void main(String[] args) { + test(new Base()); + test(new Derived()); + } +} +/* Output: +Testing x of type class typeinfo.Base +x instanceof Base true +x instanceof Derived false +Base.isInstance(x) true +Derived.isInstance(x) false +x.getClass() == Base.class true +x.getClass() == Derived.class false +x.getClass().equals(Base.class)) true +x.getClass().equals(Derived.class)) false +Testing x of type class typeinfo.Derived +x instanceof Base true +x instanceof Derived true +Base.isInstance(x) true +Derived.isInstance(x) true +x.getClass() == Base.class false +x.getClass() == Derived.class true +x.getClass().equals(Base.class)) false +x.getClass().equals(Derived.class)) true +*/ diff --git a/code/typeinfo/GenericClassReferences.java b/code/typeinfo/GenericClassReferences.java new file mode 100644 index 00000000..81ba7f7d --- /dev/null +++ b/code/typeinfo/GenericClassReferences.java @@ -0,0 +1,14 @@ +// typeinfo/GenericClassReferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class GenericClassReferences { + public static void main(String[] args) { + Class intClass = int.class; + Class genericIntClass = int.class; + genericIntClass = Integer.class; // Same thing + intClass = double.class; + // genericIntClass = double.class; // Illegal + } +} diff --git a/code/typeinfo/HiddenImplementation.java b/code/typeinfo/HiddenImplementation.java new file mode 100644 index 00000000..7b41f657 --- /dev/null +++ b/code/typeinfo/HiddenImplementation.java @@ -0,0 +1,44 @@ +// typeinfo/HiddenImplementation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Sneaking around package hiding +import typeinfo.interfacea.*; +import typeinfo.packageaccess.*; +import java.lang.reflect.*; + +public class HiddenImplementation { + public static void + main(String[] args) throws Exception { + A a = HiddenC.makeA(); + a.f(); + System.out.println(a.getClass().getName()); + // Compile error: cannot find symbol 'C': + /* if(a instanceof C) { + C c = (C)a; + c.g(); + } */ + // Oops! Reflection still allows us to call g(): + callHiddenMethod(a, "g"); + // And even less accessible methods! + callHiddenMethod(a, "u"); + callHiddenMethod(a, "v"); + callHiddenMethod(a, "w"); + } + static void + callHiddenMethod(Object a, String methodName) + throws Exception { + Method g = + a.getClass().getDeclaredMethod(methodName); + g.setAccessible(true); + g.invoke(a); + } +} +/* Output: +public C.f() +typeinfo.packageaccess.C +public C.g() +package C.u() +protected C.v() +private C.w() +*/ diff --git a/code/typeinfo/InnerImplementation.java b/code/typeinfo/InnerImplementation.java new file mode 100644 index 00000000..2b6541fa --- /dev/null +++ b/code/typeinfo/InnerImplementation.java @@ -0,0 +1,49 @@ +// typeinfo/InnerImplementation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Private inner classes can't hide from reflection +import typeinfo.interfacea.*; + +class InnerA { + private static class C implements A { + public void f() { + System.out.println("public C.f()"); + } + public void g() { + System.out.println("public C.g()"); + } + void u() { + System.out.println("package C.u()"); + } + protected void v() { + System.out.println("protected C.v()"); + } + private void w() { + System.out.println("private C.w()"); + } + } + public static A makeA() { return new C(); } +} + +public class InnerImplementation { + public static void + main(String[] args) throws Exception { + A a = InnerA.makeA(); + a.f(); + System.out.println(a.getClass().getName()); + // Reflection still gets into the private class: + HiddenImplementation.callHiddenMethod(a, "g"); + HiddenImplementation.callHiddenMethod(a, "u"); + HiddenImplementation.callHiddenMethod(a, "v"); + HiddenImplementation.callHiddenMethod(a, "w"); + } +} +/* Output: +public C.f() +InnerA$C +public C.g() +package C.u() +protected C.v() +private C.w() +*/ diff --git a/code/typeinfo/InterfaceViolation.java b/code/typeinfo/InterfaceViolation.java new file mode 100644 index 00000000..06b13f65 --- /dev/null +++ b/code/typeinfo/InterfaceViolation.java @@ -0,0 +1,27 @@ +// typeinfo/InterfaceViolation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Sneaking around an interface +import typeinfo.interfacea.*; + +class B implements A { + public void f() {} + public void g() {} +} + +public class InterfaceViolation { + public static void main(String[] args) { + A a = new B(); + a.f(); + // a.g(); // Compile error + System.out.println(a.getClass().getName()); + if(a instanceof B) { + B b = (B)a; + b.g(); + } + } +} +/* Output: +B +*/ diff --git a/code/typeinfo/ModifyingPrivateFields.java b/code/typeinfo/ModifyingPrivateFields.java new file mode 100644 index 00000000..fa1a175d --- /dev/null +++ b/code/typeinfo/ModifyingPrivateFields.java @@ -0,0 +1,49 @@ +// typeinfo/ModifyingPrivateFields.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.reflect.*; + +class WithPrivateFinalField { + private int i = 1; + private final String s = "I'm totally safe"; + private String s2 = "Am I safe?"; + @Override + public String toString() { + return "i = " + i + ", " + s + ", " + s2; + } +} + +public class ModifyingPrivateFields { + public static void + main(String[] args) throws Exception { + WithPrivateFinalField pf = + new WithPrivateFinalField(); + System.out.println(pf); + Field f = pf.getClass().getDeclaredField("i"); + f.setAccessible(true); + System.out.println( + "f.getInt(pf): " + f.getInt(pf)); + f.setInt(pf, 47); + System.out.println(pf); + f = pf.getClass().getDeclaredField("s"); + f.setAccessible(true); + System.out.println("f.get(pf): " + f.get(pf)); + f.set(pf, "No, you're not!"); + System.out.println(pf); + f = pf.getClass().getDeclaredField("s2"); + f.setAccessible(true); + System.out.println("f.get(pf): " + f.get(pf)); + f.set(pf, "No, you're not!"); + System.out.println(pf); + } +} +/* Output: +i = 1, I'm totally safe, Am I safe? +f.getInt(pf): 1 +i = 47, I'm totally safe, Am I safe? +f.get(pf): I'm totally safe +i = 47, I'm totally safe, Am I safe? +f.get(pf): Am I safe? +i = 47, I'm totally safe, No, you're not! +*/ diff --git a/code/typeinfo/NullRobot.java b/code/typeinfo/NullRobot.java new file mode 100644 index 00000000..d174ca94 --- /dev/null +++ b/code/typeinfo/NullRobot.java @@ -0,0 +1,63 @@ +// typeinfo/NullRobot.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using a dynamic proxy to create an Optional +import java.lang.reflect.*; +import java.util.*; +import java.util.stream.*; +import onjava.*; + +class NullRobotProxyHandler +implements InvocationHandler { + private String nullName; + private Robot proxied = new NRobot(); + NullRobotProxyHandler(Class type) { + nullName = type.getSimpleName() + " NullRobot"; + } + private class NRobot implements Null, Robot { + @Override + public String name() { return nullName; } + @Override + public String model() { return nullName; } + @Override + public List operations() { + return Collections.emptyList(); + } + } + @Override + public Object + invoke(Object proxy, Method method, Object[] args) + throws Throwable { + return method.invoke(proxied, args); + } +} + +public class NullRobot { + public static Robot + newNullRobot(Class type) { + return (Robot)Proxy.newProxyInstance( + NullRobot.class.getClassLoader(), + new Class[]{ Null.class, Robot.class }, + new NullRobotProxyHandler(type)); + } + public static void main(String[] args) { + Stream.of( + new SnowRemovalRobot("SnowBee"), + newNullRobot(SnowRemovalRobot.class) + ).forEach(Robot::test); + } +} +/* Output: +Robot name: SnowBee +Robot model: SnowBot Series 11 +SnowBee can shovel snow +SnowBee shoveling snow +SnowBee can chip ice +SnowBee chipping ice +SnowBee can clear the roof +SnowBee clearing roof +[Null Robot] +Robot name: SnowRemovalRobot NullRobot +Robot model: SnowRemovalRobot NullRobot +*/ diff --git a/code/typeinfo/Operation.java b/code/typeinfo/Operation.java new file mode 100644 index 00000000..dc872230 --- /dev/null +++ b/code/typeinfo/Operation.java @@ -0,0 +1,15 @@ +// typeinfo/Operation.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.function.*; + +public class Operation { + public final Supplier description; + public final Runnable command; + public + Operation(Supplier descr, Runnable cmd) { + description = descr; + command = cmd; + } +} diff --git a/code/typeinfo/Person.java b/code/typeinfo/Person.java new file mode 100644 index 00000000..7a9807c0 --- /dev/null +++ b/code/typeinfo/Person.java @@ -0,0 +1,49 @@ +// typeinfo/Person.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using Optional with regular classes +import onjava.*; +import java.util.*; + +class Person { + public final Optional first; + public final Optional last; + public final Optional address; + // etc. + public final boolean empty; + Person(String first, String last, String address) { + this.first = Optional.ofNullable(first); + this.last = Optional.ofNullable(last); + this.address = Optional.ofNullable(address); + empty = !this.first.isPresent() + && !this.last.isPresent() + && !this.address.isPresent(); + } + Person(String first, String last) { + this(first, last, null); + } + Person(String last) { this(null, last, null); } + Person() { this(null, null, null); } + @Override + public String toString() { + if(empty) + return ""; + return (first.orElse("") + + " " + last.orElse("") + + " " + address.orElse("")).trim(); + } + public static void main(String[] args) { + System.out.println(new Person()); + System.out.println(new Person("Smith")); + System.out.println(new Person("Bob", "Smith")); + System.out.println(new Person("Bob", "Smith", + "11 Degree Lane, Frostbite Falls, MN")); + } +} +/* Output: + +Smith +Bob Smith +Bob Smith 11 Degree Lane, Frostbite Falls, MN +*/ diff --git a/code/typeinfo/PetCount.java b/code/typeinfo/PetCount.java new file mode 100644 index 00000000..53438d29 --- /dev/null +++ b/code/typeinfo/PetCount.java @@ -0,0 +1,65 @@ +// typeinfo/PetCount.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using instanceof +import typeinfo.pets.*; +import java.util.*; + +public class PetCount { + static class Counter extends HashMap { + public void count(String type) { + Integer quantity = get(type); + if(quantity == null) + put(type, 1); + else + put(type, quantity + 1); + } + } + public static void + countPets(PetCreator creator) { + Counter counter = new Counter(); + for(Pet pet : Pets.array(20)) { + // List each individual pet: + System.out.print( + pet.getClass().getSimpleName() + " "); + if(pet instanceof Pet) + counter.count("Pet"); + if(pet instanceof Dog) + counter.count("Dog"); + if(pet instanceof Mutt) + counter.count("Mutt"); + if(pet instanceof Pug) + counter.count("Pug"); + if(pet instanceof Cat) + counter.count("Cat"); + if(pet instanceof EgyptianMau) + counter.count("EgyptianMau"); + if(pet instanceof Manx) + counter.count("Manx"); + if(pet instanceof Cymric) + counter.count("Cymric"); + if(pet instanceof Rodent) + counter.count("Rodent"); + if(pet instanceof Rat) + counter.count("Rat"); + if(pet instanceof Mouse) + counter.count("Mouse"); + if(pet instanceof Hamster) + counter.count("Hamster"); + } + // Show the counts: + System.out.println(); + System.out.println(counter); + } + public static void main(String[] args) { + countPets(new ForNameCreator()); + } +} +/* Output: +Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat +EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse +Pug Mouse Cymric +{EgyptianMau=2, Pug=3, Rat=2, Cymric=5, Mouse=2, Cat=9, +Manx=7, Rodent=5, Mutt=3, Dog=6, Pet=20, Hamster=1} +*/ diff --git a/code/typeinfo/PetCount2.java b/code/typeinfo/PetCount2.java new file mode 100644 index 00000000..c65e0138 --- /dev/null +++ b/code/typeinfo/PetCount2.java @@ -0,0 +1,18 @@ +// typeinfo/PetCount2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; + +public class PetCount2 { + public static void main(String[] args) { + PetCount.countPets(Pets.CREATOR); + } +} +/* Output: +Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat +EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse +Pug Mouse Cymric +{EgyptianMau=2, Pug=3, Rat=2, Cymric=5, Mouse=2, Cat=9, +Manx=7, Rodent=5, Mutt=3, Dog=6, Pet=20, Hamster=1} +*/ diff --git a/code/typeinfo/PetCount3.java b/code/typeinfo/PetCount3.java new file mode 100644 index 00000000..5b08fb66 --- /dev/null +++ b/code/typeinfo/PetCount3.java @@ -0,0 +1,53 @@ +// typeinfo/PetCount3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using isInstance() +import java.util.*; +import java.util.stream.*; +import onjava.*; +import typeinfo.pets.*; + +public class PetCount3 { + static class Counter extends + LinkedHashMap, Integer> { + Counter() { + super(LiteralPetCreator.ALL_TYPES.stream() + .map(lpc -> Pair.make(lpc, 0)) + .collect( + Collectors.toMap(Pair::key, Pair::value))); + } + public void count(Pet pet) { + // Class.isInstance() eliminates instanceofs: + entrySet().stream() + .filter(pair -> pair.getKey().isInstance(pet)) + .forEach(pair -> + put(pair.getKey(), pair.getValue() + 1)); + } + @Override + public String toString() { + String result = entrySet().stream() + .map(pair -> String.format("%s=%s", + pair.getKey().getSimpleName(), + pair.getValue())) + .collect(Collectors.joining(", ")); + return "{" + result + "}"; + } + } + public static void main(String[] args) { + Counter petCount = new Counter(); + Pets.stream() + .limit(20) + .peek(petCount::count) + .forEach(p -> System.out.print( + p.getClass().getSimpleName() + " ")); + System.out.println("\n" + petCount); + } +} +/* Output: +Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat +EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse +Pug Mouse Cymric +{Rat=2, Pug=3, Mutt=3, Mouse=2, Cat=9, Dog=6, Cymric=5, +EgyptianMau=2, Rodent=5, Hamster=1, Manx=7, Pet=20} +*/ diff --git a/code/typeinfo/PetCount4.java b/code/typeinfo/PetCount4.java new file mode 100644 index 00000000..1ea4873a --- /dev/null +++ b/code/typeinfo/PetCount4.java @@ -0,0 +1,26 @@ +// typeinfo/PetCount4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import typeinfo.pets.*; +import onjava.*; + +public class PetCount4 { + public static void main(String[] args) { + TypeCounter counter = new TypeCounter(Pet.class); + Pets.stream() + .limit(20) + .peek(counter::count) + .forEach(p -> System.out.print( + p.getClass().getSimpleName() + " ")); + System.out.println("\n" + counter); + } +} +/* Output: +Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat +EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse +Pug Mouse Cymric +{Dog=6, Manx=7, Cat=9, Rodent=5, Hamster=1, Rat=2, +Pug=3, Mutt=3, Cymric=5, EgyptianMau=2, Pet=20, +Mouse=2} +*/ diff --git a/code/typeinfo/Position.java b/code/typeinfo/Position.java new file mode 100644 index 00000000..ca81643b --- /dev/null +++ b/code/typeinfo/Position.java @@ -0,0 +1,51 @@ +// typeinfo/Position.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +class EmptyTitleException extends RuntimeException {} + +class Position { + private String title; + private Person person; + Position(String jobTitle, Person employee) { + setTitle(jobTitle); + setPerson(employee); + } + Position(String jobTitle) { + this(jobTitle, null); + } + public String getTitle() { return title; } + public void setTitle(String newTitle) { + // Throws EmptyTitleException if newTitle is null: + title = Optional.ofNullable(newTitle) + .orElseThrow(EmptyTitleException::new); + } + public Person getPerson() { return person; } + public void setPerson(Person newPerson) { + // Uses empty Person if newPerson is null: + person = Optional.ofNullable(newPerson) + .orElse(new Person()); + } + @Override + public String toString() { + return "Position: " + title + + ", Employee: " + person; + } + public static void main(String[] args) { + System.out.println(new Position("CEO")); + System.out.println(new Position("Programmer", + new Person("Arthur", "Fonzarelli"))); + try { + new Position(null); + } catch(Exception e) { + System.out.println("caught " + e); + } + } +} +/* Output: +Position: CEO, Employee: +Position: Programmer, Employee: Arthur Fonzarelli +caught EmptyTitleException +*/ diff --git a/code/typeinfo/RegisteredFactories.java b/code/typeinfo/RegisteredFactories.java new file mode 100644 index 00000000..7708cc4e --- /dev/null +++ b/code/typeinfo/RegisteredFactories.java @@ -0,0 +1,95 @@ +// typeinfo/RegisteredFactories.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Registering Factories in the base class +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +class Part implements Supplier { + @Override + public String toString() { + return getClass().getSimpleName(); + } + static List> prototypes = + Arrays.asList( + new FuelFilter(), + new AirFilter(), + new CabinAirFilter(), + new OilFilter(), + new FanBelt(), + new PowerSteeringBelt(), + new GeneratorBelt() + ); + private static Random rand = new Random(47); + public Part get() { + int n = rand.nextInt(prototypes.size()); + return prototypes.get(n).get(); + } +} + +class Filter extends Part {} + +class FuelFilter extends Filter { + @Override + public FuelFilter get() { return new FuelFilter(); } +} + +class AirFilter extends Filter { + @Override + public AirFilter get() { return new AirFilter(); } +} + +class CabinAirFilter extends Filter { + @Override + public CabinAirFilter get() { + return new CabinAirFilter(); + } +} + +class OilFilter extends Filter { + @Override + public OilFilter get() { return new OilFilter(); } +} + +class Belt extends Part {} + +class FanBelt extends Belt { + @Override + public FanBelt get() { return new FanBelt(); } +} + +class GeneratorBelt extends Belt { + @Override + public GeneratorBelt get() { + return new GeneratorBelt(); + } +} + +class PowerSteeringBelt extends Belt { + @Override + public PowerSteeringBelt get() { + return new PowerSteeringBelt(); + } +} + +public class RegisteredFactories { + public static void main(String[] args) { + Stream.generate(new Part()) + .limit(10) + .forEach(System.out::println); + } +} +/* Output: +GeneratorBelt +CabinAirFilter +GeneratorBelt +AirFilter +PowerSteeringBelt +CabinAirFilter +FuelFilter +PowerSteeringBelt +PowerSteeringBelt +FuelFilter +*/ diff --git a/code/typeinfo/Robot.java b/code/typeinfo/Robot.java new file mode 100644 index 00000000..803ee9fe --- /dev/null +++ b/code/typeinfo/Robot.java @@ -0,0 +1,22 @@ +// typeinfo/Robot.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.*; +import java.util.*; + +public interface Robot { + String name(); + String model(); + List operations(); + static void test(Robot r) { + if(r instanceof Null) + System.out.println("[Null Robot]"); + System.out.println("Robot name: " + r.name()); + System.out.println("Robot model: " + r.model()); + for(Operation operation : r.operations()) { + System.out.println(operation.description.get()); + operation.command.run(); + } + } +} diff --git a/code/typeinfo/SelectingMethods.java b/code/typeinfo/SelectingMethods.java new file mode 100644 index 00000000..d87e928b --- /dev/null +++ b/code/typeinfo/SelectingMethods.java @@ -0,0 +1,69 @@ +// typeinfo/SelectingMethods.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Looking for particular methods in a dynamic proxy +import java.lang.reflect.*; + +class MethodSelector implements InvocationHandler { + private Object proxied; + MethodSelector(Object proxied) { + this.proxied = proxied; + } + @Override + public Object + invoke(Object proxy, Method method, Object[] args) + throws Throwable { + if(method.getName().equals("interesting")) + System.out.println( + "Proxy detected the interesting method"); + return method.invoke(proxied, args); + } +} + +interface SomeMethods { + void boring1(); + void boring2(); + void interesting(String arg); + void boring3(); +} + +class Implementation implements SomeMethods { + @Override + public void boring1() { + System.out.println("boring1"); + } + @Override + public void boring2() { + System.out.println("boring2"); + } + @Override + public void interesting(String arg) { + System.out.println("interesting " + arg); + } + @Override + public void boring3() { + System.out.println("boring3"); + } +} + +class SelectingMethods { + public static void main(String[] args) { + SomeMethods proxy = + (SomeMethods)Proxy.newProxyInstance( + SomeMethods.class.getClassLoader(), + new Class[]{ SomeMethods.class }, + new MethodSelector(new Implementation())); + proxy.boring1(); + proxy.boring2(); + proxy.interesting("bonobo"); + proxy.boring3(); + } +} +/* Output: +boring1 +boring2 +Proxy detected the interesting method +interesting bonobo +boring3 +*/ diff --git a/code/typeinfo/Shapes.java b/code/typeinfo/Shapes.java new file mode 100644 index 00000000..34a2bc56 --- /dev/null +++ b/code/typeinfo/Shapes.java @@ -0,0 +1,39 @@ +// typeinfo/Shapes.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.stream.*; + +abstract class Shape { + void draw() { System.out.println(this + ".draw()"); } + @Override + public abstract String toString(); +} + +class Circle extends Shape { + @Override + public String toString() { return "Circle"; } +} + +class Square extends Shape { + @Override + public String toString() { return "Square"; } +} + +class Triangle extends Shape { + @Override + public String toString() { return "Triangle"; } +} + +public class Shapes { + public static void main(String[] args) { + Stream.of( + new Circle(), new Square(), new Triangle()) + .forEach(Shape::draw); + } +} +/* Output: +Circle.draw() +Square.draw() +Triangle.draw() +*/ diff --git a/code/typeinfo/ShowMethods.java b/code/typeinfo/ShowMethods.java new file mode 100644 index 00000000..be1b635b --- /dev/null +++ b/code/typeinfo/ShowMethods.java @@ -0,0 +1,71 @@ +// typeinfo/ShowMethods.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using reflection to show all the methods of a class, +// even if the methods are defined in the base class +// {java ShowMethods ShowMethods} +import java.lang.reflect.*; +import java.util.regex.*; + +public class ShowMethods { + private static String usage = + "usage:\n" + + "ShowMethods qualified.class.name\n" + + "To show all methods in class or:\n" + + "ShowMethods qualified.class.name word\n" + + "To search for methods involving 'word'"; + private static Pattern p = Pattern.compile("\\w+\\."); + public static void main(String[] args) { + if(args.length < 1) { + System.out.println(usage); + System.exit(0); + } + int lines = 0; + try { + Class c = Class.forName(args[0]); + Method[] methods = c.getMethods(); + Constructor[] ctors = c.getConstructors(); + if(args.length == 1) { + for(Method method : methods) + System.out.println( + p.matcher( + method.toString()).replaceAll("")); + for(Constructor ctor : ctors) + System.out.println( + p.matcher(ctor.toString()).replaceAll("")); + lines = methods.length + ctors.length; + } else { + for(Method method : methods) + if(method.toString().contains(args[1])) { + System.out.println(p.matcher( + method.toString()).replaceAll("")); + lines++; + } + for(Constructor ctor : ctors) + if(ctor.toString().contains(args[1])) { + System.out.println(p.matcher( + ctor.toString()).replaceAll("")); + lines++; + } + } + } catch(ClassNotFoundException e) { + System.out.println("No such class: " + e); + } + } +} +/* Output: +public static void main(String[]) +public final void wait() throws InterruptedException +public final void wait(long,int) throws +InterruptedException +public final native void wait(long) throws +InterruptedException +public boolean equals(Object) +public String toString() +public native int hashCode() +public final native Class getClass() +public final native void notify() +public final native void notifyAll() +public ShowMethods() +*/ diff --git a/code/typeinfo/SimpleDynamicProxy.java b/code/typeinfo/SimpleDynamicProxy.java new file mode 100644 index 00000000..bece57f8 --- /dev/null +++ b/code/typeinfo/SimpleDynamicProxy.java @@ -0,0 +1,53 @@ +// typeinfo/SimpleDynamicProxy.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.lang.reflect.*; + +class DynamicProxyHandler implements InvocationHandler { + private Object proxied; + DynamicProxyHandler(Object proxied) { + this.proxied = proxied; + } + @Override + public Object + invoke(Object proxy, Method method, Object[] args) + throws Throwable { + System.out.println( + "**** proxy: " + proxy.getClass() + + ", method: " + method + ", args: " + args); + if(args != null) + for(Object arg : args) + System.out.println(" " + arg); + return method.invoke(proxied, args); + } +} + +class SimpleDynamicProxy { + public static void consumer(Interface iface) { + iface.doSomething(); + iface.somethingElse("bonobo"); + } + public static void main(String[] args) { + RealObject real = new RealObject(); + consumer(real); + // Insert a proxy and call again: + Interface proxy = (Interface)Proxy.newProxyInstance( + Interface.class.getClassLoader(), + new Class[]{ Interface.class }, + new DynamicProxyHandler(real)); + consumer(proxy); + } +} +/* Output: +doSomething +somethingElse bonobo +**** proxy: class $Proxy0, method: public abstract void +Interface.doSomething(), args: null +doSomething +**** proxy: class $Proxy0, method: public abstract void +Interface.somethingElse(java.lang.String), args: +[Ljava.lang.Object;@6bc7c054 + bonobo +somethingElse bonobo +*/ diff --git a/code/typeinfo/SimpleProxyDemo.java b/code/typeinfo/SimpleProxyDemo.java new file mode 100644 index 00000000..24c3c2c2 --- /dev/null +++ b/code/typeinfo/SimpleProxyDemo.java @@ -0,0 +1,57 @@ +// typeinfo/SimpleProxyDemo.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +interface Interface { + void doSomething(); + void somethingElse(String arg); +} + +class RealObject implements Interface { + @Override + public void doSomething() { + System.out.println("doSomething"); + } + @Override + public void somethingElse(String arg) { + System.out.println("somethingElse " + arg); + } +} + +class SimpleProxy implements Interface { + private Interface proxied; + SimpleProxy(Interface proxied) { + this.proxied = proxied; + } + @Override + public void doSomething() { + System.out.println("SimpleProxy doSomething"); + proxied.doSomething(); + } + @Override + public void somethingElse(String arg) { + System.out.println( + "SimpleProxy somethingElse " + arg); + proxied.somethingElse(arg); + } +} + +class SimpleProxyDemo { + public static void consumer(Interface iface) { + iface.doSomething(); + iface.somethingElse("bonobo"); + } + public static void main(String[] args) { + consumer(new RealObject()); + consumer(new SimpleProxy(new RealObject())); + } +} +/* Output: +doSomething +somethingElse bonobo +SimpleProxy doSomething +doSomething +SimpleProxy somethingElse bonobo +somethingElse bonobo +*/ diff --git a/code/typeinfo/SnowRemovalRobot.java b/code/typeinfo/SnowRemovalRobot.java new file mode 100644 index 00000000..af5b46cd --- /dev/null +++ b/code/typeinfo/SnowRemovalRobot.java @@ -0,0 +1,42 @@ +// typeinfo/SnowRemovalRobot.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class SnowRemovalRobot implements Robot { + private String name; + public SnowRemovalRobot(String name) { + this.name = name; + } + @Override + public String name() { return name; } + @Override + public String model() { return "SnowBot Series 11"; } + private List ops = Arrays.asList( + new Operation( + () -> name + " can shovel snow", + () -> System.out.println( + name + " shoveling snow")), + new Operation( + () -> name + " can chip ice", + () -> System.out.println(name + " chipping ice")), + new Operation( + () -> name + " can clear the roof", + () -> System.out.println( + name + " clearing roof"))); + public List operations() { return ops; } + public static void main(String[] args) { + Robot.test(new SnowRemovalRobot("Slusher")); + } +} +/* Output: +Robot name: Slusher +Robot model: SnowBot Series 11 +Slusher can shovel snow +Slusher shoveling snow +Slusher can chip ice +Slusher chipping ice +Slusher can clear the roof +Slusher clearing roof +*/ diff --git a/code/typeinfo/Staff.java b/code/typeinfo/Staff.java new file mode 100644 index 00000000..569e598f --- /dev/null +++ b/code/typeinfo/Staff.java @@ -0,0 +1,63 @@ +// typeinfo/Staff.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; + +public class Staff extends ArrayList { + public void add(String title, Person person) { + add(new Position(title, person)); + } + public void add(String... titles) { + for(String title : titles) + add(new Position(title)); + } + public Staff(String... titles) { add(titles); } + public boolean positionAvailable(String title) { + for(Position position : this) + if(position.getTitle().equals(title) && + position.getPerson().empty) + return true; + return false; + } + public void fillPosition(String title, Person hire) { + for(Position position : this) + if(position.getTitle().equals(title) && + position.getPerson().empty) { + position.setPerson(hire); + return; + } + throw new RuntimeException( + "Position " + title + " not available"); + } + public static void main(String[] args) { + Staff staff = new Staff("President", "CTO", + "Marketing Manager", "Product Manager", + "Project Lead", "Software Engineer", + "Software Engineer", "Software Engineer", + "Software Engineer", "Test Engineer", + "Technical Writer"); + staff.fillPosition("President", + new Person("Me", "Last", "The Top, Lonely At")); + staff.fillPosition("Project Lead", + new Person("Janet", "Planner", "The Burbs")); + if(staff.positionAvailable("Software Engineer")) + staff.fillPosition("Software Engineer", + new Person( + "Bob", "Coder", "Bright Light City")); + System.out.println(staff); + } +} +/* Output: +[Position: President, Employee: Me Last The Top, Lonely +At, Position: CTO, Employee: , Position: +Marketing Manager, Employee: , Position: Product +Manager, Employee: , Position: Project Lead, +Employee: Janet Planner The Burbs, Position: Software +Engineer, Employee: Bob Coder Bright Light City, +Position: Software Engineer, Employee: , +Position: Software Engineer, Employee: , +Position: Software Engineer, Employee: , +Position: Test Engineer, Employee: , Position: +Technical Writer, Employee: ] +*/ diff --git a/code/typeinfo/SweetShop.java b/code/typeinfo/SweetShop.java new file mode 100644 index 00000000..f85b8c3f --- /dev/null +++ b/code/typeinfo/SweetShop.java @@ -0,0 +1,42 @@ +// typeinfo/SweetShop.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Examination of the way the class loader works + +class Cookie { + static { System.out.println("Loading Cookie"); } +} + +class Gum { + static { System.out.println("Loading Gum"); } +} + +class Candy { + static { System.out.println("Loading Candy"); } +} + +public class SweetShop { + public static void main(String[] args) { + System.out.println("inside main"); + new Candy(); + System.out.println("After creating Candy"); + try { + Class.forName("Gum"); + } catch(ClassNotFoundException e) { + System.out.println("Couldn't find Gum"); + } + System.out.println("After Class.forName(\"Gum\")"); + new Cookie(); + System.out.println("After creating Cookie"); + } +} +/* Output: +inside main +Loading Candy +After creating Candy +Loading Gum +After Class.forName("Gum") +Loading Cookie +After creating Cookie +*/ diff --git a/code/typeinfo/WildcardClassReferences.java b/code/typeinfo/WildcardClassReferences.java new file mode 100644 index 00000000..32d75e86 --- /dev/null +++ b/code/typeinfo/WildcardClassReferences.java @@ -0,0 +1,11 @@ +// typeinfo/WildcardClassReferences.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. + +public class WildcardClassReferences { + public static void main(String[] args) { + Class intClass = int.class; + intClass = double.class; + } +} diff --git a/code/typeinfo/interfacea/A.java b/code/typeinfo/interfacea/A.java new file mode 100644 index 00000000..2ebb99d3 --- /dev/null +++ b/code/typeinfo/interfacea/A.java @@ -0,0 +1,9 @@ +// typeinfo/interfacea/A.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.interfacea; + +public interface A { + void f(); +} diff --git a/code/typeinfo/packageaccess/HiddenC.java b/code/typeinfo/packageaccess/HiddenC.java new file mode 100644 index 00000000..9fb8ffde --- /dev/null +++ b/code/typeinfo/packageaccess/HiddenC.java @@ -0,0 +1,29 @@ +// typeinfo/packageaccess/HiddenC.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.packageaccess; +import typeinfo.interfacea.*; + +class C implements A { + @Override + public void f() { + System.out.println("public C.f()"); + } + public void g() { + System.out.println("public C.g()"); + } + void u() { + System.out.println("package C.u()"); + } + protected void v() { + System.out.println("protected C.v()"); + } + private void w() { + System.out.println("private C.w()"); + } +} + +public class HiddenC { + public static A makeA() { return new C(); } +} diff --git a/code/typeinfo/pets/Cat.java b/code/typeinfo/pets/Cat.java new file mode 100644 index 00000000..75781fd7 --- /dev/null +++ b/code/typeinfo/pets/Cat.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Cat.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Cat extends Pet { + public Cat(String name) { super(name); } + public Cat() { super(); } +} diff --git a/code/typeinfo/pets/Cymric.java b/code/typeinfo/pets/Cymric.java new file mode 100644 index 00000000..fd86fa95 --- /dev/null +++ b/code/typeinfo/pets/Cymric.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Cymric.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Cymric extends Manx { + public Cymric(String name) { super(name); } + public Cymric() { super(); } +} diff --git a/code/typeinfo/pets/Dog.java b/code/typeinfo/pets/Dog.java new file mode 100644 index 00000000..68f43a32 --- /dev/null +++ b/code/typeinfo/pets/Dog.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Dog.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Dog extends Pet { + public Dog(String name) { super(name); } + public Dog() { super(); } +} diff --git a/code/typeinfo/pets/EgyptianMau.java b/code/typeinfo/pets/EgyptianMau.java new file mode 100644 index 00000000..adbdfbb1 --- /dev/null +++ b/code/typeinfo/pets/EgyptianMau.java @@ -0,0 +1,10 @@ +// typeinfo/pets/EgyptianMau.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class EgyptianMau extends Cat { + public EgyptianMau(String name) { super(name); } + public EgyptianMau() { super(); } +} diff --git a/code/typeinfo/pets/ForNameCreator.java b/code/typeinfo/pets/ForNameCreator.java new file mode 100644 index 00000000..29351efa --- /dev/null +++ b/code/typeinfo/pets/ForNameCreator.java @@ -0,0 +1,37 @@ +// typeinfo/pets/ForNameCreator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; +import java.util.*; + +public class ForNameCreator extends PetCreator { + private static List> types = + new ArrayList<>(); + // Types you want randomly created: + private static String[] typeNames = { + "typeinfo.pets.Mutt", + "typeinfo.pets.Pug", + "typeinfo.pets.EgyptianMau", + "typeinfo.pets.Manx", + "typeinfo.pets.Cymric", + "typeinfo.pets.Rat", + "typeinfo.pets.Mouse", + "typeinfo.pets.Hamster" + }; + @SuppressWarnings("unchecked") + private static void loader() { + try { + for(String name : typeNames) + types.add( + (Class)Class.forName(name)); + } catch(ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + static { loader(); } + @Override + public List> types() { + return types; + } +} diff --git a/code/typeinfo/pets/Hamster.java b/code/typeinfo/pets/Hamster.java new file mode 100644 index 00000000..8408ef62 --- /dev/null +++ b/code/typeinfo/pets/Hamster.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Hamster.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Hamster extends Rodent { + public Hamster(String name) { super(name); } + public Hamster() { super(); } +} diff --git a/code/typeinfo/pets/Individual.java b/code/typeinfo/pets/Individual.java new file mode 100644 index 00000000..e3c87dac --- /dev/null +++ b/code/typeinfo/pets/Individual.java @@ -0,0 +1,46 @@ +// typeinfo/pets/Individual.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; +import java.util.*; + +public class +Individual implements Comparable { + private static long counter = 0; + private final long id = counter++; + private String name; + public Individual(String name) { this.name = name; } + // 'name' is optional: + public Individual() {} + @Override + public String toString() { + return getClass().getSimpleName() + + (name == null ? "" : " " + name); + } + public long id() { return id; } + @Override + public boolean equals(Object o) { + return o instanceof Individual && + Objects.equals(id, ((Individual)o).id); + } + @Override + public int hashCode() { + return Objects.hash(name, id); + } + @Override + public int compareTo(Individual arg) { + // Compare by class name first: + String first = getClass().getSimpleName(); + String argFirst = arg.getClass().getSimpleName(); + int firstCompare = first.compareTo(argFirst); + if(firstCompare != 0) + return firstCompare; + if(name != null && arg.name != null) { + int secondCompare = name.compareTo(arg.name); + if(secondCompare != 0) + return secondCompare; + } + return (arg.id < id ? -1 : (arg.id == id ? 0 : 1)); + } +} diff --git a/code/typeinfo/pets/LiteralPetCreator.java b/code/typeinfo/pets/LiteralPetCreator.java new file mode 100644 index 00000000..398baac8 --- /dev/null +++ b/code/typeinfo/pets/LiteralPetCreator.java @@ -0,0 +1,39 @@ +// typeinfo/pets/LiteralPetCreator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using class literals +// {java typeinfo.pets.LiteralPetCreator} +package typeinfo.pets; +import java.util.*; + +public class LiteralPetCreator extends PetCreator { + // No try block needed. + @SuppressWarnings("unchecked") + public static + final List> ALL_TYPES = + Collections.unmodifiableList(Arrays.asList( + Pet.class, Dog.class, Cat.class, Rodent.class, + Mutt.class, Pug.class, EgyptianMau.class, + Manx.class, Cymric.class, Rat.class, + Mouse.class, Hamster.class)); + // Types for random creation: + private static final + List> TYPES = + ALL_TYPES.subList(ALL_TYPES.indexOf(Mutt.class), + ALL_TYPES.size()); + @Override + public List> types() { + return TYPES; + } + public static void main(String[] args) { + System.out.println(TYPES); + } +} +/* Output: +[class typeinfo.pets.Mutt, class typeinfo.pets.Pug, +class typeinfo.pets.EgyptianMau, class +typeinfo.pets.Manx, class typeinfo.pets.Cymric, class +typeinfo.pets.Rat, class typeinfo.pets.Mouse, class +typeinfo.pets.Hamster] +*/ diff --git a/code/typeinfo/pets/Manx.java b/code/typeinfo/pets/Manx.java new file mode 100644 index 00000000..6a5534b1 --- /dev/null +++ b/code/typeinfo/pets/Manx.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Manx.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Manx extends Cat { + public Manx(String name) { super(name); } + public Manx() { super(); } +} diff --git a/code/typeinfo/pets/Mouse.java b/code/typeinfo/pets/Mouse.java new file mode 100644 index 00000000..bbb97cda --- /dev/null +++ b/code/typeinfo/pets/Mouse.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Mouse.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Mouse extends Rodent { + public Mouse(String name) { super(name); } + public Mouse() { super(); } +} diff --git a/code/typeinfo/pets/Mutt.java b/code/typeinfo/pets/Mutt.java new file mode 100644 index 00000000..f51814b9 --- /dev/null +++ b/code/typeinfo/pets/Mutt.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Mutt.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Mutt extends Dog { + public Mutt(String name) { super(name); } + public Mutt() { super(); } +} diff --git a/code/typeinfo/pets/Person.java b/code/typeinfo/pets/Person.java new file mode 100644 index 00000000..4dcfff2c --- /dev/null +++ b/code/typeinfo/pets/Person.java @@ -0,0 +1,9 @@ +// typeinfo/pets/Person.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Person extends Individual { + public Person(String name) { super(name); } +} diff --git a/code/typeinfo/pets/Pet.java b/code/typeinfo/pets/Pet.java new file mode 100644 index 00000000..dcbfd4ab --- /dev/null +++ b/code/typeinfo/pets/Pet.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Pet.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Pet extends Individual { + public Pet(String name) { super(name); } + public Pet() { super(); } +} diff --git a/code/typeinfo/pets/PetCreator.java b/code/typeinfo/pets/PetCreator.java new file mode 100644 index 00000000..76909aa9 --- /dev/null +++ b/code/typeinfo/pets/PetCreator.java @@ -0,0 +1,28 @@ +// typeinfo/pets/PetCreator.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Creates random sequences of Pets +package typeinfo.pets; +import java.util.*; +import java.util.function.*; +import java.lang.reflect.InvocationTargetException; + +public abstract +class PetCreator implements Supplier { + private Random rand = new Random(47); + // The List of the different types of Pet to create: + public abstract List> types(); + public Pet get() { // Create one random Pet + int n = rand.nextInt(types().size()); + try { + return types().get(n) + .getConstructor().newInstance(); + } catch(InstantiationException | + NoSuchMethodException | + InvocationTargetException | + IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/code/typeinfo/pets/Pets.java b/code/typeinfo/pets/Pets.java new file mode 100644 index 00000000..be3037a1 --- /dev/null +++ b/code/typeinfo/pets/Pets.java @@ -0,0 +1,30 @@ +// typeinfo/pets/Pets.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Facade to produce a default PetCreator +package typeinfo.pets; +import java.util.*; +import java.util.stream.*; + +public class Pets { + public static final PetCreator CREATOR = + new LiteralPetCreator(); + public static Pet get() { + return CREATOR.get(); + } + public static Pet[] array(int size) { + Pet[] result = new Pet[size]; + for(int i = 0; i < size; i++) + result[i] = CREATOR.get(); + return result; + } + public static List list(int size) { + List result = new ArrayList<>(); + Collections.addAll(result, array(size)); + return result; + } + public static Stream stream() { + return Stream.generate(CREATOR); + } +} diff --git a/code/typeinfo/pets/Pug.java b/code/typeinfo/pets/Pug.java new file mode 100644 index 00000000..9d8ab467 --- /dev/null +++ b/code/typeinfo/pets/Pug.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Pug.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Pug extends Dog { + public Pug(String name) { super(name); } + public Pug() { super(); } +} diff --git a/code/typeinfo/pets/Rat.java b/code/typeinfo/pets/Rat.java new file mode 100644 index 00000000..2ce5534b --- /dev/null +++ b/code/typeinfo/pets/Rat.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Rat.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Rat extends Rodent { + public Rat(String name) { super(name); } + public Rat() { super(); } +} diff --git a/code/typeinfo/pets/Rodent.java b/code/typeinfo/pets/Rodent.java new file mode 100644 index 00000000..7b998d0a --- /dev/null +++ b/code/typeinfo/pets/Rodent.java @@ -0,0 +1,10 @@ +// typeinfo/pets/Rodent.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package typeinfo.pets; + +public class Rodent extends Pet { + public Rodent(String name) { super(name); } + public Rodent() { super(); } +} diff --git a/code/typeinfo/toys/GenericToyTest.java b/code/typeinfo/toys/GenericToyTest.java new file mode 100644 index 00000000..7dc016cd --- /dev/null +++ b/code/typeinfo/toys/GenericToyTest.java @@ -0,0 +1,23 @@ +// typeinfo/toys/GenericToyTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Testing class Class +// {java typeinfo.toys.GenericToyTest} +package typeinfo.toys; + +public class GenericToyTest { + @SuppressWarnings("deprecation") + public static void + main(String[] args) throws Exception { + Class ftClass = FancyToy.class; + // Produces exact type: + FancyToy fancyToy = ftClass.newInstance(); + Class up = + ftClass.getSuperclass(); + // This won't compile: + // Class up2 = ftClass.getSuperclass(); + // Only produces Object: + Object obj = up.newInstance(); + } +} diff --git a/code/typeinfo/toys/ToyTest.java b/code/typeinfo/toys/ToyTest.java new file mode 100644 index 00000000..e4e5e92d --- /dev/null +++ b/code/typeinfo/toys/ToyTest.java @@ -0,0 +1,78 @@ +// typeinfo/toys/ToyTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Testing class Class +// {java typeinfo.toys.ToyTest} +package typeinfo.toys; +import java.lang.reflect.InvocationTargetException; + +interface HasBatteries {} +interface Waterproof {} +interface Shoots {} + +class Toy { + // Comment out the following no-arg + // constructor to see NoSuchMethodError + Toy() {} + Toy(int i) {} +} + +class FancyToy extends Toy +implements HasBatteries, Waterproof, Shoots { + FancyToy() { super(1); } +} + +public class ToyTest { + static void printInfo(Class cc) { + System.out.println("Class name: " + cc.getName() + + " is interface? [" + cc.isInterface() + "]"); + System.out.println( + "Simple name: " + cc.getSimpleName()); + System.out.println( + "Canonical name : " + cc.getCanonicalName()); + } + @SuppressWarnings("deprecation") + public static void main(String[] args) { + Class c = null; + try { + c = Class.forName("typeinfo.toys.FancyToy"); + } catch(ClassNotFoundException e) { + System.out.println("Can't find FancyToy"); + System.exit(1); + } + printInfo(c); + for(Class face : c.getInterfaces()) + printInfo(face); + Class up = c.getSuperclass(); + Object obj = null; + try { + // Requires no-arg constructor: + obj = up.newInstance(); + } catch(Exception e) { + throw new + RuntimeException("Cannot instantiate"); + } + printInfo(obj.getClass()); + } +} +/* Output: +Class name: typeinfo.toys.FancyToy is interface? +[false] +Simple name: FancyToy +Canonical name : typeinfo.toys.FancyToy +Class name: typeinfo.toys.HasBatteries is interface? +[true] +Simple name: HasBatteries +Canonical name : typeinfo.toys.HasBatteries +Class name: typeinfo.toys.Waterproof is interface? +[true] +Simple name: Waterproof +Canonical name : typeinfo.toys.Waterproof +Class name: typeinfo.toys.Shoots is interface? [true] +Simple name: Shoots +Canonical name : typeinfo.toys.Shoots +Class name: typeinfo.toys.Toy is interface? [false] +Simple name: Toy +Canonical name : typeinfo.toys.Toy +*/ diff --git a/code/validating/Assert1.java b/code/validating/Assert1.java new file mode 100644 index 00000000..013a72f6 --- /dev/null +++ b/code/validating/Assert1.java @@ -0,0 +1,19 @@ +// validating/Assert1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Non-informative style of assert +// Must run using -ea flag: +// {java -ea Assert1} +// {ThrowsException} + +public class Assert1 { + public static void main(String[] args) { + assert false; + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "main" java.lang.AssertionError + at Assert1.main(Assert1.java:9) +*/ diff --git a/code/validating/Assert2.java b/code/validating/Assert2.java new file mode 100644 index 00000000..61b4827d --- /dev/null +++ b/code/validating/Assert2.java @@ -0,0 +1,20 @@ +// validating/Assert2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Assert with an information-expression +// {java Assert2 -ea} +// {ThrowsException} + +public class Assert2 { + public static void main(String[] args) { + assert false: + "Here's a message saying what happened"; + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "main" java.lang.AssertionError: +Here's a message saying what happened + at Assert2.main(Assert2.java:8) +*/ diff --git a/code/validating/BadMicroBenchmark.java b/code/validating/BadMicroBenchmark.java new file mode 100644 index 00000000..2634e67c --- /dev/null +++ b/code/validating/BadMicroBenchmark.java @@ -0,0 +1,29 @@ +// validating/BadMicroBenchmark.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ExcludeFromTravisCI} +import java.util.*; +import onjava.Timer; + +public class BadMicroBenchmark { + static final int SIZE = 250_000_000; + public static void main(String[] args) { + try { // For machines with insufficient memory + long[] la = new long[SIZE]; + System.out.println("setAll: " + + Timer.duration(() -> + Arrays.setAll(la, n -> n))); + System.out.println("parallelSetAll: " + + Timer.duration(() -> + Arrays.parallelSetAll(la, n -> n))); + } catch(OutOfMemoryError e) { + System.out.println("Insufficient memory"); + System.exit(0); + } + } +} +/* Output: +setAll: 272 +parallelSetAll: 301 +*/ diff --git a/code/validating/BadMicroBenchmark2.java b/code/validating/BadMicroBenchmark2.java new file mode 100644 index 00000000..123036a0 --- /dev/null +++ b/code/validating/BadMicroBenchmark2.java @@ -0,0 +1,35 @@ +// validating/BadMicroBenchmark2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Relying on a common resource +import java.util.*; +import onjava.Timer; + +public class BadMicroBenchmark2 { + // SIZE reduced to make it run faster: + static final int SIZE = 5_000_000; + public static void main(String[] args) { + long[] la = new long[SIZE]; + Random r = new Random(); + System.out.println("parallelSetAll: " + + Timer.duration(() -> + Arrays.parallelSetAll(la, n -> r.nextLong()))); + System.out.println("setAll: " + + Timer.duration(() -> + Arrays.setAll(la, n -> r.nextLong()))); + SplittableRandom sr = new SplittableRandom(); + System.out.println("parallelSetAll: " + + Timer.duration(() -> + Arrays.parallelSetAll(la, n -> sr.nextLong()))); + System.out.println("setAll: " + + Timer.duration(() -> + Arrays.setAll(la, n -> sr.nextLong()))); + } +} +/* Output: +parallelSetAll: 1147 +setAll: 174 +parallelSetAll: 86 +setAll: 39 +*/ diff --git a/code/validating/CircularQueue.java b/code/validating/CircularQueue.java new file mode 100644 index 00000000..405e4410 --- /dev/null +++ b/code/validating/CircularQueue.java @@ -0,0 +1,91 @@ +// validating/CircularQueue.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstration of Design by Contract (DbC) +package validating; +import java.util.*; + +public class CircularQueue { + private Object[] data; + private int + in = 0, // Next available storage space + out = 0; // Next gettable object + // Has it wrapped around the circular queue? + private boolean wrapped = false; + public CircularQueue(int size) { + data = new Object[size]; + // Must be true after construction: + assert invariant(); + } + public boolean empty() { + return !wrapped && in == out; + } + public boolean full() { + return wrapped && in == out; + } + public boolean isWrapped() { return wrapped; } + public void put(Object item) { + precondition(item != null, "put() null item"); + precondition(!full(), + "put() into full CircularQueue"); + assert invariant(); + data[in++] = item; + if(in >= data.length) { + in = 0; + wrapped = true; + } + assert invariant(); + } + public Object get() { + precondition(!empty(), + "get() from empty CircularQueue"); + assert invariant(); + Object returnVal = data[out]; + data[out] = null; + out++; + if(out >= data.length) { + out = 0; + wrapped = false; + } + assert postcondition( + returnVal != null, + "Null item in CircularQueue"); + assert invariant(); + return returnVal; + } + // Design-by-contract support methods: + private static void + precondition(boolean cond, String msg) { + if(!cond) throw new CircularQueueException(msg); + } + private static boolean + postcondition(boolean cond, String msg) { + if(!cond) throw new CircularQueueException(msg); + return true; + } + private boolean invariant() { + // Guarantee that no null values are in the + // region of 'data' that holds objects: + for(int i = out; i != in; i = (i + 1) % data.length) + if(data[i] == null) + throw new CircularQueueException( + "null in CircularQueue"); + // Guarantee that only null values are outside the + // region of 'data' that holds objects: + if(full()) return true; + for(int i = in; i != out; i = (i + 1) % data.length) + if(data[i] != null) + throw new CircularQueueException( + "non-null outside of CircularQueue range: " + + dump()); + return true; + } + public String dump() { + return "in = " + in + + ", out = " + out + + ", full() = " + full() + + ", empty() = " + empty() + + ", CircularQueue = " + Arrays.asList(data); + } +} diff --git a/code/validating/CircularQueueException.java b/code/validating/CircularQueueException.java new file mode 100644 index 00000000..142b8ece --- /dev/null +++ b/code/validating/CircularQueueException.java @@ -0,0 +1,12 @@ +// validating/CircularQueueException.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; + +public class +CircularQueueException extends RuntimeException { + public CircularQueueException(String why) { + super(why); + } +} diff --git a/code/validating/CountedList.java b/code/validating/CountedList.java new file mode 100644 index 00000000..6c780f21 --- /dev/null +++ b/code/validating/CountedList.java @@ -0,0 +1,16 @@ +// validating/CountedList.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Keeps track of how many of itself are created. +package validating; +import java.util.*; + +public class CountedList extends ArrayList { + private static int counter = 0; + private int id = counter++; + public CountedList() { + System.out.println("CountedList #" + id); + } + public int getId() { return id; } +} diff --git a/code/validating/GuavaAssertions.java b/code/validating/GuavaAssertions.java new file mode 100644 index 00000000..a499f079 --- /dev/null +++ b/code/validating/GuavaAssertions.java @@ -0,0 +1,49 @@ +// validating/GuavaAssertions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Assertions that are always enabled. +import com.google.common.base.*; +import static com.google.common.base.Verify.*; + +public class GuavaAssertions { + public static void main(String[] args) { + verify(2 + 2 == 4); + try { + verify(1 + 2 == 4); + } catch(VerifyException e) { + System.out.println(e); + } + try { + verify(1 + 2 == 4, "Bad math"); + } catch(VerifyException e) { + System.out.println(e.getMessage()); + } + try { + verify(1 + 2 == 4, "Bad math: %s", "not 4"); + } catch(VerifyException e) { + System.out.println(e.getMessage()); + } + String s = ""; + s = verifyNotNull(s); + s = null; + try { + verifyNotNull(s); + } catch(VerifyException e) { + System.out.println(e.getMessage()); + } + try { + verifyNotNull( + s, "Shouldn't be null: %s", "arg s"); + } catch(VerifyException e) { + System.out.println(e.getMessage()); + } + } +} +/* Output: +com.google.common.base.VerifyException +Bad math +Bad math: not 4 +expected a non-null reference +Shouldn't be null: arg s +*/ diff --git a/code/validating/GuavaPreconditions.java b/code/validating/GuavaPreconditions.java new file mode 100644 index 00000000..3cfc66ae --- /dev/null +++ b/code/validating/GuavaPreconditions.java @@ -0,0 +1,125 @@ +// validating/GuavaPreconditions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Demonstrating Guava Preconditions +import java.util.function.*; +import static com.google.common.base.Preconditions.*; + +public class GuavaPreconditions { + static void test(Consumer c, String s) { + try { + System.out.println(s); + c.accept(s); + System.out.println("Success"); + } catch(Exception e) { + String type = e.getClass().getSimpleName(); + String msg = e.getMessage(); + System.out.println(type + + (msg == null ? "" : ": " + msg)); + } + } + public static void main(String[] args) { + test(s -> s = checkNotNull(s), "X"); + test(s -> s = checkNotNull(s), null); + test(s -> s = checkNotNull(s, "s was null"), null); + test(s -> s = checkNotNull( + s, "s was null, %s %s", "arg2", "arg3"), null); + + test(s -> checkArgument(s == "Fozzie"), "Fozzie"); + test(s -> checkArgument(s == "Fozzie"), "X"); + test(s -> checkArgument(s == "Fozzie"), null); + test(s -> checkArgument( + s == "Fozzie", "Bear Left!"), null); + test(s -> checkArgument( + s == "Fozzie", "Bear Left! %s Right!", "Frog"), + null); + + test(s -> checkState(s.length() > 6), "Mortimer"); + test(s -> checkState(s.length() > 6), "Mort"); + test(s -> checkState(s.length() > 6), null); + + test(s -> + checkElementIndex(6, s.length()), "Robert"); + test(s -> + checkElementIndex(6, s.length()), "Bob"); + test(s -> + checkElementIndex(6, s.length()), null); + + test(s -> + checkPositionIndex(6, s.length()), "Robert"); + test(s -> + checkPositionIndex(6, s.length()), "Bob"); + test(s -> + checkPositionIndex(6, s.length()), null); + + test(s -> checkPositionIndexes( + 0, 6, s.length()), "Hieronymus"); + test(s -> checkPositionIndexes( + 0, 10, s.length()), "Hieronymus"); + test(s -> checkPositionIndexes( + 0, 11, s.length()), "Hieronymus"); + test(s -> checkPositionIndexes( + -1, 6, s.length()), "Hieronymus"); + test(s -> checkPositionIndexes( + 7, 6, s.length()), "Hieronymus"); + test(s -> checkPositionIndexes( + 0, 6, s.length()), null); + } +} +/* Output: +X +Success +null +NullPointerException +null +NullPointerException: s was null +null +NullPointerException: s was null, arg2 arg3 +Fozzie +Success +X +IllegalArgumentException +null +IllegalArgumentException +null +IllegalArgumentException: Bear Left! +null +IllegalArgumentException: Bear Left! Frog Right! +Mortimer +Success +Mort +IllegalStateException +null +NullPointerException +Robert +IndexOutOfBoundsException: index (6) must be less than +size (6) +Bob +IndexOutOfBoundsException: index (6) must be less than +size (3) +null +NullPointerException +Robert +Success +Bob +IndexOutOfBoundsException: index (6) must not be +greater than size (3) +null +NullPointerException +Hieronymus +Success +Hieronymus +Success +Hieronymus +IndexOutOfBoundsException: end index (11) must not be +greater than size (10) +Hieronymus +IndexOutOfBoundsException: start index (-1) must not be +negative +Hieronymus +IndexOutOfBoundsException: end index (6) must not be +less than start index (7) +null +NullPointerException +*/ diff --git a/code/validating/Inverter1.java b/code/validating/Inverter1.java new file mode 100644 index 00000000..8ef828d6 --- /dev/null +++ b/code/validating/Inverter1.java @@ -0,0 +1,9 @@ +// validating/Inverter1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; + +public class Inverter1 implements StringInverter { + public String invert(String str) { return str; } +} diff --git a/code/validating/Inverter2.java b/code/validating/Inverter2.java new file mode 100644 index 00000000..3fb862fd --- /dev/null +++ b/code/validating/Inverter2.java @@ -0,0 +1,19 @@ +// validating/Inverter2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; +import static java.lang.Character.*; + +public class Inverter2 implements StringInverter { + public String invert(String str) { + String result = ""; + for(int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + result += isUpperCase(c) ? + toLowerCase(c) : + toUpperCase(c); + } + return result; + } +} diff --git a/code/validating/Inverter3.java b/code/validating/Inverter3.java new file mode 100644 index 00000000..4bd53c82 --- /dev/null +++ b/code/validating/Inverter3.java @@ -0,0 +1,21 @@ +// validating/Inverter3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; +import static java.lang.Character.*; + +public class Inverter3 implements StringInverter { + public String invert(String str) { + if(str.length() > 30) + throw new RuntimeException("argument too long!"); + String result = ""; + for(int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + result += isUpperCase(c) ? + toLowerCase(c) : + toUpperCase(c); + } + return result; + } +} diff --git a/code/validating/Inverter4.java b/code/validating/Inverter4.java new file mode 100644 index 00000000..0b787059 --- /dev/null +++ b/code/validating/Inverter4.java @@ -0,0 +1,26 @@ +// validating/Inverter4.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; +import static java.lang.Character.*; + +public class Inverter4 implements StringInverter { + static final String ALLOWED = + "abcdefghijklmnopqrstuvwxyz ,." + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + public String invert(String str) { + if(str.length() > 30) + throw new RuntimeException("argument too long!"); + String result = ""; + for(int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if(ALLOWED.indexOf(c) == -1) + throw new RuntimeException(c + " Not allowed"); + result += isUpperCase(c) ? + toLowerCase(c) : + toUpperCase(c); + } + return result; + } +} diff --git a/code/validating/LoaderAssertions.java b/code/validating/LoaderAssertions.java new file mode 100644 index 00000000..52cac347 --- /dev/null +++ b/code/validating/LoaderAssertions.java @@ -0,0 +1,28 @@ +// validating/LoaderAssertions.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Using the class loader to enable assertions +// {ThrowsException} + +public class LoaderAssertions { + public static void main(String[] args) { + ClassLoader.getSystemClassLoader() + .setDefaultAssertionStatus(true); + new Loaded().go(); + } +} + +class Loaded { + public void go() { + assert false: "Loaded.go()"; + } +} +/* Output: +___[ Error Output ]___ +Exception in thread "main" java.lang.AssertionError: +Loaded.go() + at Loaded.go(LoaderAssertions.java:15) + at +LoaderAssertions.main(LoaderAssertions.java:9) +*/ diff --git a/code/validating/NonNullConstruction.java b/code/validating/NonNullConstruction.java new file mode 100644 index 00000000..a95483dd --- /dev/null +++ b/code/validating/NonNullConstruction.java @@ -0,0 +1,18 @@ +// validating/NonNullConstruction.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import static com.google.common.base.Preconditions.*; + +public class NonNullConstruction { + private Integer n; + private String s; + NonNullConstruction(Integer n, String s) { + this.n = checkNotNull(n); + this.s = checkNotNull(s); + } + public static void main(String[] args) { + NonNullConstruction nnc = + new NonNullConstruction(3, "Trousers"); + } +} diff --git a/code/validating/SLF4JLevels.java b/code/validating/SLF4JLevels.java new file mode 100644 index 00000000..c851e7c3 --- /dev/null +++ b/code/validating/SLF4JLevels.java @@ -0,0 +1,29 @@ +// validating/SLF4JLevels.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import org.slf4j.*; + +public class SLF4JLevels { + private static Logger log = + LoggerFactory.getLogger(SLF4JLevels.class); + public static void main(String[] args) { + log.trace("Hello"); + log.debug("Logging"); + log.info("Using"); + log.warn("the SLF4J"); + log.error("Facade"); + } +} +/* Output: +2017-05-09T06:07:52.846 +[main] TRACE SLF4JLevels - Hello +2017-05-09T06:07:52.849 +[main] DEBUG SLF4JLevels - Logging +2017-05-09T06:07:52.849 +[main] INFO SLF4JLevels - Using +2017-05-09T06:07:52.850 +[main] WARN SLF4JLevels - the SLF4J +2017-05-09T06:07:52.851 +[main] ERROR SLF4JLevels - Facade +*/ diff --git a/code/validating/SLF4JLogging.java b/code/validating/SLF4JLogging.java new file mode 100644 index 00000000..f2e94d6e --- /dev/null +++ b/code/validating/SLF4JLogging.java @@ -0,0 +1,17 @@ +// validating/SLF4JLogging.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import org.slf4j.*; + +public class SLF4JLogging { + private static Logger log = + LoggerFactory.getLogger(SLF4JLogging.class); + public static void main(String[] args) { + log.info("hello logging"); + } +} +/* Output: +2017-05-09T06:07:53.418 +[main] INFO SLF4JLogging - hello logging +*/ diff --git a/code/validating/SimpleDebugging.java b/code/validating/SimpleDebugging.java new file mode 100644 index 00000000..863e7de3 --- /dev/null +++ b/code/validating/SimpleDebugging.java @@ -0,0 +1,40 @@ +// validating/SimpleDebugging.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// {ThrowsException} + +public class SimpleDebugging { + private static void foo1() { + System.out.println("In foo1"); + foo2(); + } + private static void foo2() { + System.out.println("In foo2"); + foo3(); + } + private static void foo3() { + System.out.println("In foo3"); + int j = 1; + j--; + int i = 5 / j; + } + public static void main(String[] args) { + foo1(); + } +} +/* Output: +In foo1 +In foo2 +In foo3 +___[ Error Output ]___ +Exception in thread "main" +java.lang.ArithmeticException: / by zero + at +SimpleDebugging.foo3(SimpleDebugging.java:17) + at +SimpleDebugging.foo2(SimpleDebugging.java:11) + at SimpleDebugging.foo1(SimpleDebugging.java:7) + at +SimpleDebugging.main(SimpleDebugging.java:20) +*/ diff --git a/code/validating/StringInverter.java b/code/validating/StringInverter.java new file mode 100644 index 00000000..34c933a7 --- /dev/null +++ b/code/validating/StringInverter.java @@ -0,0 +1,9 @@ +// validating/StringInverter.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; + +interface StringInverter { + String invert(String str); +} diff --git a/code/validating/jmh/JMH1.java b/code/validating/jmh/JMH1.java new file mode 100644 index 00000000..79eb749a --- /dev/null +++ b/code/validating/jmh/JMH1.java @@ -0,0 +1,31 @@ +// validating/jmh/JMH1.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating.jmh; +import java.util.*; +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +// Increase these three for more accuracy: +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(1) +public class JMH1 { + private long[] la; + @Setup + public void setup() { + la = new long[250_000_000]; + } + @Benchmark + public void setAll() { + Arrays.setAll(la, n -> n); + } + @Benchmark + public void parallelSetAll() { + Arrays.parallelSetAll(la, n -> n); + } +} diff --git a/code/validating/jmh/JMH2.java b/code/validating/jmh/JMH2.java new file mode 100644 index 00000000..ae7b56f9 --- /dev/null +++ b/code/validating/jmh/JMH2.java @@ -0,0 +1,44 @@ +// validating/jmh/JMH2.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating.jmh; +import java.util.*; +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(1) +public class JMH2 { + private long[] la; + @Param({ + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "250000000" + }) + int size; + + @Setup + public void setup() { + la = new long[size]; + } + @Benchmark + public void setAll() { + Arrays.setAll(la, n -> n); + } + @Benchmark + public void parallelSetAll() { + Arrays.parallelSetAll(la, n -> n); + } +} diff --git a/code/validating/jmh/JMH3.java b/code/validating/jmh/JMH3.java new file mode 100644 index 00000000..8ce9bb0c --- /dev/null +++ b/code/validating/jmh/JMH3.java @@ -0,0 +1,48 @@ +// validating/jmh/JMH3.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating.jmh; +import java.util.*; +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(1) +public class JMH3 { + private long[] la; + @Param({ + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "250000000" + }) + int size; + + @Setup + public void setup() { + la = new long[size]; + } + public static long f(long x) { + long quadratic = 42 * x * x + 19 * x + 47; + return Long.divideUnsigned(quadratic, x + 1); + } + @Benchmark + public void setAll() { + Arrays.setAll(la, n -> f(n)); + } + @Benchmark + public void parallelSetAll() { + Arrays.parallelSetAll(la, n -> f(n)); + } +} diff --git a/code/validating/logback.xml b/code/validating/logback.xml new file mode 100644 index 00000000..0a774e44 --- /dev/null +++ b/code/validating/logback.xml @@ -0,0 +1,15 @@ + + + + + +%d{yyyy-MM-dd'T'HH:mm:ss.SSS} +[%thread] %-5level %logger - %msg%n + + + + + + + \ No newline at end of file diff --git a/code/validating/tests/CircularQueueTest.java b/code/validating/tests/CircularQueueTest.java new file mode 100644 index 00000000..8da6dc27 --- /dev/null +++ b/code/validating/tests/CircularQueueTest.java @@ -0,0 +1,150 @@ +// validating/tests/CircularQueueTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +public class CircularQueueTest { + private CircularQueue queue = new CircularQueue(10); + private int i = 0; + @BeforeEach + public void initialize() { + while(i < 5) // Pre-load with some data + queue.put(Integer.toString(i++)); + } + // Support methods: + private void showFullness() { + assertTrue(queue.full()); + assertFalse(queue.empty()); + System.out.println(queue.dump()); + } + private void showEmptiness() { + assertFalse(queue.full()); + assertTrue(queue.empty()); + System.out.println(queue.dump()); + } + @Test + public void full() { + System.out.println("testFull"); + System.out.println(queue.dump()); + System.out.println(queue.get()); + System.out.println(queue.get()); + while(!queue.full()) + queue.put(Integer.toString(i++)); + String msg = ""; + try { + queue.put(""); + } catch(CircularQueueException e) { + msg = e.getMessage(); + System.out.println(msg); + } + assertEquals(msg, "put() into full CircularQueue"); + showFullness(); + } + @Test + public void empty() { + System.out.println("testEmpty"); + while(!queue.empty()) + System.out.println(queue.get()); + String msg = ""; + try { + queue.get(); + } catch(CircularQueueException e) { + msg = e.getMessage(); + System.out.println(msg); + } + assertEquals(msg, "get() from empty CircularQueue"); + showEmptiness(); + } + @Test + public void nullPut() { + System.out.println("testNullPut"); + String msg = ""; + try { + queue.put(null); + } catch(CircularQueueException e) { + msg = e.getMessage(); + System.out.println(msg); + } + assertEquals(msg, "put() null item"); + } + @Test + public void circularity() { + System.out.println("testCircularity"); + while(!queue.full()) + queue.put(Integer.toString(i++)); + showFullness(); + assertTrue(queue.isWrapped()); + while(!queue.empty()) + System.out.println(queue.get()); + showEmptiness(); + while(!queue.full()) + queue.put(Integer.toString(i++)); + showFullness(); + while(!queue.empty()) + System.out.println(queue.get()); + showEmptiness(); + } +} +/* Output: +testNullPut +put() null item +testCircularity +in = 0, out = 0, full() = true, empty() = false, +CircularQueue = +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +in = 0, out = 0, full() = false, empty() = true, +CircularQueue = +[null, null, null, null, null, null, null, null, null, +null] +in = 0, out = 0, full() = true, empty() = false, +CircularQueue = +[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +in = 0, out = 0, full() = false, empty() = true, +CircularQueue = +[null, null, null, null, null, null, null, null, null, +null] +testFull +in = 5, out = 0, full() = false, empty() = false, +CircularQueue = +[0, 1, 2, 3, 4, null, null, null, null, null] +0 +1 +put() into full CircularQueue +in = 2, out = 2, full() = true, empty() = false, +CircularQueue = +[10, 11, 2, 3, 4, 5, 6, 7, 8, 9] +testEmpty +0 +1 +2 +3 +4 +get() from empty CircularQueue +in = 5, out = 5, full() = false, empty() = true, +CircularQueue = +[null, null, null, null, null, null, null, null, null, +null] +*/ diff --git a/code/validating/tests/CountedListTest.java b/code/validating/tests/CountedListTest.java new file mode 100644 index 00000000..a9dc0c71 --- /dev/null +++ b/code/validating/tests/CountedListTest.java @@ -0,0 +1,101 @@ +// validating/tests/CountedListTest.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +// Simple use of JUnit to test CountedList. +package validating; +import java.util.*; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +public class CountedListTest { + private CountedList list; + @BeforeAll + static void beforeAllMsg() { + System.out.println(">>> Starting CountedListTest"); + } + @AfterAll + static void afterAllMsg() { + System.out.println(">>> Finished CountedListTest"); + } + @BeforeEach + public void initialize() { + list = new CountedList(); + System.out.println("Set up for " + list.getId()); + for(int i = 0; i < 3; i++) + list.add(Integer.toString(i)); + } + @AfterEach + public void cleanup() { + System.out.println("Cleaning up " + list.getId()); + } + @Test + public void insert() { + System.out.println("Running testInsert()"); + assertEquals(list.size(), 3); + list.add(1, "Insert"); + assertEquals(list.size(), 4); + assertEquals(list.get(1), "Insert"); + } + @Test + public void replace() { + System.out.println("Running testReplace()"); + assertEquals(list.size(), 3); + list.set(1, "Replace"); + assertEquals(list.size(), 3); + assertEquals(list.get(1), "Replace"); + } + // A helper method to simplify the code. As + // long as it's not annotated with @Test, it will + // not be automatically executed by JUnit. + private + void compare(List lst, String[] strs) { + assertArrayEquals(lst.toArray(new String[0]), strs); + } + @Test + public void order() { + System.out.println("Running testOrder()"); + compare(list, new String[] { "0", "1", "2" }); + } + @Test + public void remove() { + System.out.println("Running testRemove()"); + assertEquals(list.size(), 3); + list.remove(1); + assertEquals(list.size(), 2); + compare(list, new String[] { "0", "2" }); + } + @Test + public void addAll() { + System.out.println("Running testAddAll()"); + list.addAll(Arrays.asList(new String[] { + "An", "African", "Swallow"})); + assertEquals(list.size(), 6); + compare(list, new String[] { "0", "1", "2", + "An", "African", "Swallow" }); + } +} +/* Output: +>>> Starting CountedListTest +CountedList #0 +Set up for 0 +Running testRemove() +Cleaning up 0 +CountedList #1 +Set up for 1 +Running testReplace() +Cleaning up 1 +CountedList #2 +Set up for 2 +Running testAddAll() +Cleaning up 2 +CountedList #3 +Set up for 3 +Running testInsert() +Cleaning up 3 +CountedList #4 +Set up for 4 +Running testOrder() +Cleaning up 4 +>>> Finished CountedListTest +*/ diff --git a/code/validating/tests/DynamicStringInverterTests.java b/code/validating/tests/DynamicStringInverterTests.java new file mode 100644 index 00000000..dc980971 --- /dev/null +++ b/code/validating/tests/DynamicStringInverterTests.java @@ -0,0 +1,122 @@ +// validating/tests/DynamicStringInverterTests.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.DynamicTest.*; + +class DynamicStringInverterTests { + // Combine operations to prevent code duplication: + Stream testVersions(String id, + Function test) { + List versions = Arrays.asList( + new Inverter1(), new Inverter2(), + new Inverter3(), new Inverter4()); + return DynamicTest.stream( + versions.iterator(), + inverter -> inverter.getClass().getSimpleName(), + inverter -> { + System.out.println( + inverter.getClass().getSimpleName() + + ": " + id); + try { + if(test.apply(inverter) != "fail") + System.out.println("Success"); + } catch(Exception | Error e) { + System.out.println( + "Exception: " + e.getMessage()); + } + } + ); + } + String isEqual(String lval, String rval) { + if(lval.equals(rval)) + return "success"; + System.out.println("FAIL: " + lval + " != " + rval); + return "fail"; + } + @BeforeAll + static void startMsg() { + System.out.println( + ">>> Starting DynamicStringInverterTests <<<"); + } + @AfterAll + static void endMsg() { + System.out.println( + ">>> Finished DynamicStringInverterTests <<<"); + } + @TestFactory + Stream basicInversion1() { + String in = "Exit, Pursued by a Bear."; + String out = "eXIT, pURSUED BY A bEAR."; + return testVersions( + "Basic inversion (should succeed)", + inverter -> isEqual(inverter.invert(in), out) + ); + } + @TestFactory + Stream basicInversion2() { + return testVersions( + "Basic inversion (should fail)", + inverter -> isEqual(inverter.invert("X"), "X")); + } + @TestFactory + Stream disallowedCharacters() { + String disallowed = ";-_()*&^%$#@!~`0123456789"; + return testVersions( + "Disallowed characters", + inverter -> { + String result = disallowed.chars() + .mapToObj(c -> { + String cc = Character.toString((char)c); + try { + inverter.invert(cc); + return ""; + } catch(RuntimeException e) { + return cc; + } + }).collect(Collectors.joining("")); + if(result.length() == 0) + return "success"; + System.out.println("Bad characters: " + result); + return "fail"; + } + ); + } + @TestFactory + Stream allowedCharacters() { + String lowcase = "abcdefghijklmnopqrstuvwxyz ,."; + String upcase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ,."; + return testVersions( + "Allowed characters (should succeed)", + inverter -> { + assertEquals(inverter.invert(lowcase), upcase); + assertEquals(inverter.invert(upcase), lowcase); + return "success"; + } + ); + } + @TestFactory + Stream lengthNoGreaterThan30() { + String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + assertTrue(str.length() > 30); + return testVersions( + "Length must be less than 31 (throws exception)", + inverter -> inverter.invert(str) + ); + } + @TestFactory + Stream lengthLessThan31() { + String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + assertTrue(str.length() < 31); + return testVersions( + "Length must be less than 31 (should succeed)", + inverter -> inverter.invert(str) + ); + } +} diff --git a/code/validating/tests/StringInverterTests.java b/code/validating/tests/StringInverterTests.java new file mode 100644 index 00000000..e32873b8 --- /dev/null +++ b/code/validating/tests/StringInverterTests.java @@ -0,0 +1,65 @@ +// validating/tests/StringInverterTests.java +// (c)2020 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package validating; +import java.util.*; +import java.util.stream.*; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +public class StringInverterTests { + StringInverter inverter = new Inverter4(); + @BeforeAll + static void startMsg() { + System.out.println(">>> StringInverterTests <<<"); + } + @Test + void basicInversion1() { + String in = "Exit, Pursued by a Bear."; + String out = "eXIT, pURSUED BY A bEAR."; + assertEquals(inverter.invert(in), out); + } + @Test + void basicInversion2() { + assertThrows(Error.class, () -> { + assertEquals(inverter.invert("X"), "X"); + }); + } + @Test + void disallowedCharacters() { + String disallowed = ";-_()*&^%$#@!~`0123456789"; + String result = disallowed.chars() + .mapToObj(c -> { + String cc = Character.toString((char)c); + try { + inverter.invert(cc); + return ""; + } catch(RuntimeException e) { + return cc; + } + }).collect(Collectors.joining("")); + assertEquals(result, disallowed); + } + @Test + void allowedCharacters() { + String lowcase = "abcdefghijklmnopqrstuvwxyz ,."; + String upcase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ,."; + assertEquals(inverter.invert(lowcase), upcase); + assertEquals(inverter.invert(upcase), lowcase); + } + @Test + void lengthNoGreaterThan30() { + String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + assertTrue(str.length() > 30); + assertThrows(RuntimeException.class, () -> { + inverter.invert(str); + }); + } + @Test + void lengthLessThan31() { + String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + assertTrue(str.length() < 31); + inverter.invert(str); + } +} From ec2e1fad5edca8e513f5f2dd4549e622aa1e31d3 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 24 Nov 2020 14:31:15 +0800 Subject: [PATCH 02/68] 2 --- code/.gitattributes | 17 - code/.gitignore | 111 ----- code/.travisXX.yml | 8 - code/CI.txt | 5 - code/Copyright.txt | 72 --- code/README.md | 43 -- code/annotations/AUComposition.java | 30 -- code/annotations/AUExternalTest.java | 29 -- code/annotations/AtUnitExample1.java | 48 -- code/annotations/AtUnitExample2.java | 57 --- code/annotations/AtUnitExample3.java | 42 -- code/annotations/AtUnitExample4.java | 83 ---- code/annotations/AtUnitExample5.java | 63 --- code/annotations/DemoProcessFiles.java | 43 -- code/annotations/HashSetTest.java | 36 -- code/annotations/PasswordUtils.java | 24 - code/annotations/SimulatingNull.java | 12 - code/annotations/StackL.java | 14 - code/annotations/StackLStringTst.java | 42 -- code/annotations/Testable.java | 14 - code/annotations/UseCase.java | 12 - code/annotations/UseCaseTracker.java | 37 -- code/annotations/database/Constraints.java | 14 - code/annotations/database/DBTable.java | 12 - code/annotations/database/Member.java | 22 - code/annotations/database/SQLInteger.java | 13 - code/annotations/database/SQLString.java | 14 - code/annotations/database/TableCreator.java | 106 ----- code/annotations/database/Uniqueness.java | 11 - code/annotations/ifx/ExtractInterface.java | 13 - .../ifx/IfaceExtractorProcessor.java | 91 ---- code/annotations/ifx/Multiplier.java | 34 -- code/annotations/simplest/Simple.java | 20 - .../annotations/simplest/SimpleProcessor.java | 47 -- code/annotations/simplest/SimpleTest.java | 32 -- code/appveyorXX.yml | 4 - code/arrays/AlphabeticSearch.java | 29 -- code/arrays/ArrayCopying.java | 81 ---- code/arrays/ArrayOfGenericType.java | 16 - code/arrays/ArrayOfGenerics.java | 33 -- code/arrays/ArrayOptions.java | 79 ---- code/arrays/ArraySearching.java | 33 -- .../AssemblingMultidimensionalArrays.java | 22 - code/arrays/AutoboxingArrays.java | 22 - code/arrays/CollectionComparison.java | 53 --- code/arrays/CompType.java | 56 --- code/arrays/ComparatorTest.java | 39 -- code/arrays/ComparingArrays.java | 62 --- code/arrays/CountUpward.java | 24 - code/arrays/FillingArrays.java | 55 --- code/arrays/IceCreamFlavors.java | 45 -- code/arrays/ModifyExisting.java | 22 - code/arrays/MultiDimWrapperArray.java | 38 -- code/arrays/MultidimensionalObjectArrays.java | 25 -- .../MultidimensionalPrimitiveArray.java | 18 - code/arrays/ParallelPrefix1.java | 27 -- code/arrays/ParallelPrefix2.java | 20 - code/arrays/ParallelPrefix3.java | 23 - code/arrays/ParallelSetAll.java | 24 - code/arrays/ParameterizedArrayType.java | 25 -- code/arrays/PythonLists.py | 36 -- code/arrays/RaggedArray.java | 26 -- code/arrays/Reverse.java | 32 -- code/arrays/SimpleSetAll.java | 56 --- code/arrays/StreamFromArray.java | 51 --- code/arrays/StringSorting.java | 39 -- code/arrays/TestConvertTo.java | 87 ---- code/arrays/TestCount.java | 167 ------- code/arrays/TestRand.java | 192 -------- code/arrays/ThreeDWithNew.java | 17 - code/arrays/jmh/ParallelSort.java | 25 -- code/build.gradle | 23 - code/checkstyle.xml | 179 -------- code/chkstyle.bat | 2 - code/collections/AdapterMethodIdiom.java | 48 -- code/collections/AddingGroups.java | 24 - .../ApplesAndOrangesWithGenerics.java | 23 - .../ApplesAndOrangesWithoutGenerics.java | 38 -- code/collections/ArrayIsNotIterable.java | 23 - code/collections/AsListInference.java | 34 -- code/collections/CollectionDifferences.java | 71 --- code/collections/CollectionSequence.java | 40 -- .../collections/CrossCollectionIteration.java | 36 -- .../CrossCollectionIteration2.java | 37 -- code/collections/EnvironmentVariables.java | 15 - code/collections/ForInCollections.java | 19 - code/collections/GenericsAndUpcasting.java | 28 -- code/collections/InterfaceVsIterator.java | 55 --- code/collections/IterableClass.java | 35 -- code/collections/LinkedListFeatures.java | 54 --- code/collections/ListFeatures.java | 93 ---- code/collections/ListIteration.java | 37 -- code/collections/MapOfList.java | 65 --- code/collections/ModifyingArraysAsList.java | 32 -- code/collections/MultiIterableClass.java | 53 --- code/collections/NonCollectionSequence.java | 37 -- code/collections/PetMap.java | 27 -- code/collections/PrintingCollections.java | 44 -- code/collections/PriorityQueueDemo.java | 53 --- code/collections/QueueDemo.java | 29 -- code/collections/SetOfInteger.java | 19 - code/collections/SetOfString.java | 25 -- code/collections/SetOperations.java | 40 -- code/collections/SimpleCollection.java | 18 - code/collections/SimpleIteration.java | 36 -- code/collections/SortedSetOfString.java | 25 -- code/collections/StackCollision.java | 25 -- code/collections/StackTest.java | 18 - code/collections/StackTest2.java | 18 - code/collections/Statistics.java | 25 -- code/collections/UniqueWords.java | 29 -- code/collections/UniqueWordsAlphabetic.java | 30 -- code/collectiontopics/AssociativeArray.java | 64 --- code/collectiontopics/Bits.java | 79 ---- code/collectiontopics/CanonicalMapping.java | 56 --- code/collectiontopics/CollectionMethods.java | 135 ------ code/collectiontopics/Enumerations.java | 24 - code/collectiontopics/FailFast.java | 22 - code/collectiontopics/FillMapTest.java | 32 -- code/collectiontopics/FillingLists.java | 35 -- code/collectiontopics/FunctionalMap.java | 38 -- code/collectiontopics/HTMLColorTest.java | 103 ----- code/collectiontopics/LinkedHashMapDemo.java | 31 -- code/collectiontopics/ListOps.java | 167 ------- code/collectiontopics/ListSortSearch.java | 57 --- code/collectiontopics/MapOps.java | 76 ---- code/collectiontopics/NavMap.java | 96 ---- code/collectiontopics/QueueBehavior.java | 50 --- code/collectiontopics/ReadOnly.java | 56 --- code/collectiontopics/References.java | 92 ---- code/collectiontopics/SetOrder.java | 92 ---- code/collectiontopics/SimpleDeques.java | 70 --- code/collectiontopics/SortedMapDemo.java | 42 -- code/collectiontopics/SortedSetDemo.java | 42 -- code/collectiontopics/Stacks.java | 61 --- code/collectiontopics/StreamFillMaps.java | 55 --- .../SuppliersCollectionTest.java | 67 --- code/collectiontopics/Synchronization.java | 24 - code/collectiontopics/ToDoList.java | 56 --- code/collectiontopics/TypesForSets.java | 93 ---- code/collectiontopics/Unsupported.java | 60 --- code/collectiontopics/Utilities.java | 88 ---- code/com/mindviewinc/simple/List.java | 12 - code/com/mindviewinc/simple/Vector.java | 12 - code/compression/GZIPcompress.java | 45 -- code/compression/ZipCompress.java | 83 ---- code/concurrent/Baked.java | 31 -- code/concurrent/Batter.java | 34 -- code/concurrent/Breakable.java | 29 -- code/concurrent/CachedThreadPool.java | 29 -- code/concurrent/CachedThreadPool2.java | 29 -- code/concurrent/CachedThreadPool3.java | 47 -- .../CatchCompletableExceptions.java | 81 ---- code/concurrent/CollectionIntoStream.java | 36 -- code/concurrent/CompletableApply.java | 27 -- code/concurrent/CompletableApplyAsync.java | 31 -- code/concurrent/CompletableApplyChained.java | 27 -- code/concurrent/CompletableExceptions.java | 75 ---- code/concurrent/CompletableOperations.java | 74 ---- code/concurrent/CompletablePizza.java | 87 ---- code/concurrent/CompletableUtilities.java | 27 -- code/concurrent/CompletedMachina.java | 19 - code/concurrent/CountingStream.java | 32 -- code/concurrent/CountingTask.java | 19 - code/concurrent/DiningPhilosophers.java | 33 -- .../concurrent/DualCompletableOperations.java | 115 ----- code/concurrent/FrostedCake.java | 32 -- code/concurrent/Futures.java | 23 - code/concurrent/GuardedIDField.java | 18 - code/concurrent/HasID.java | 8 - code/concurrent/IDChecker.java | 41 -- code/concurrent/InterferingTask.java | 17 - .../LambdasAndMethodReferences.java | 40 -- code/concurrent/Machina.java | 31 -- code/concurrent/MoreTasksAfterShutdown.java | 27 -- code/concurrent/NapTask.java | 20 - code/concurrent/OnePizza.java | 26 -- code/concurrent/ParallelPrime.java | 35 -- code/concurrent/ParallelStreamPuzzle.java | 28 -- code/concurrent/ParallelStreamPuzzle2.java | 38 -- code/concurrent/ParallelStreamPuzzle3.java | 33 -- code/concurrent/Philosopher.java | 30 -- code/concurrent/Pizza.java | 49 --- code/concurrent/PizzaParallelSteps.java | 69 --- code/concurrent/PizzaStreams.java | 60 --- code/concurrent/QuittableTask.java | 20 - code/concurrent/QuittingCompletable.java | 35 -- code/concurrent/QuittingTasks.java | 35 -- .../concurrent/SharedConstructorArgument.java | 44 -- code/concurrent/SingleThreadExecutor.java | 49 --- code/concurrent/SingleThreadExecutor2.java | 30 -- code/concurrent/SingleThreadExecutor3.java | 30 -- code/concurrent/StaticIDField.java | 10 - code/concurrent/StickHolder.java | 27 -- code/concurrent/StreamExceptions.java | 40 -- code/concurrent/Summing.java | 47 -- code/concurrent/Summing2.java | 44 -- code/concurrent/Summing3.java | 42 -- code/concurrent/Summing4.java | 23 - code/concurrent/SynchronizedConstructor.java | 29 -- code/concurrent/SynchronizedFactory.java | 29 -- code/concurrent/TestStaticIDField.java | 13 - code/concurrent/ThrowsChecked.java | 42 -- code/concurrent/Workable.java | 32 -- code/control/BreakAndContinue.java | 38 -- code/control/CommaOperator.java | 18 - code/control/ForInFloat.java | 28 -- code/control/ForInInt.java | 28 -- code/control/ForInString.java | 14 - code/control/IfElse.java | 29 -- code/control/LabeledFor.java | 65 --- code/control/LabeledWhile.java | 51 --- code/control/ListCharacters.java | 27 -- code/control/RandomBounds.java | 30 -- code/control/StringSwitch.java | 44 -- code/control/TestWithReturn.java | 24 - code/control/TrueFalse.java | 15 - code/control/VowelsAndConsonants.java | 44 -- code/control/WhileTest.java | 31 -- code/enums/AlarmPoints.java | 9 - code/enums/BigEnumSet.java | 29 -- code/enums/Burrito2.java | 28 -- code/enums/CarWash.java | 88 ---- code/enums/Competitor.java | 10 - code/enums/ConstantSpecificMethod.java | 41 -- code/enums/EnumClass.java | 51 --- code/enums/EnumMaps.java | 37 -- code/enums/EnumSets.java | 39 -- code/enums/Input.java | 33 -- code/enums/NonEnum.java | 19 - code/enums/NotClasses.java | 50 --- code/enums/Outcome.java | 6 - code/enums/OverrideConstantSpecific.java | 28 -- code/enums/OzWitch.java | 32 -- code/enums/PostOffice.java | 197 --------- code/enums/RandomTest.java | 21 - code/enums/Reflection.java | 71 --- code/enums/RoShamBo.java | 21 - code/enums/RoShamBo1.java | 104 ----- code/enums/RoShamBo2.java | 55 --- code/enums/RoShamBo3.java | 71 --- code/enums/RoShamBo4.java | 57 --- code/enums/RoShamBo5.java | 59 --- code/enums/RoShamBo6.java | 46 -- code/enums/SecurityCategory.java | 46 -- code/enums/SpaceShip.java | 28 -- code/enums/SpicinessEnum.java | 9 - code/enums/TrafficLight.java | 44 -- code/enums/UpcastEnum.java | 21 - code/enums/VendingMachine.java | 183 -------- code/enums/VendingMachineInput.txt | 8 - code/enums/cartoons/EnumImplementation.java | 37 -- code/enums/menu/Course.java | 20 - code/enums/menu/Food.java | 24 - code/enums/menu/Meal.java | 45 -- code/enums/menu/Meal2.java | 74 ---- code/enums/menu/TypeOfFood.java | 16 - code/equalshashcode/ComposedEquality.java | 66 --- code/equalshashcode/CountedString.java | 72 --- code/equalshashcode/DefaultComparison.java | 24 - code/equalshashcode/Equality.java | 77 ---- code/equalshashcode/EqualityFactory.java | 9 - code/equalshashcode/Groundhog.java | 14 - code/equalshashcode/Groundhog2.java | 19 - code/equalshashcode/IndividualTest.java | 31 -- code/equalshashcode/MapEntry.java | 42 -- code/equalshashcode/Prediction.java | 15 - code/equalshashcode/SimpleHashMap.java | 90 ---- code/equalshashcode/SlowMap.java | 64 --- code/equalshashcode/SpringDetector.java | 62 --- code/equalshashcode/SpringDetector2.java | 25 -- code/equalshashcode/StringHashCode.java | 16 - code/equalshashcode/SubtypeEquality.java | 60 --- code/equalshashcode/SubtypeEquality2.java | 40 -- code/equalshashcode/SuccinctEquality.java | 46 -- code/exceptions/AlwaysFinally.java | 33 -- code/exceptions/AutoCloseableDetails.java | 33 -- code/exceptions/BodyException.java | 32 -- code/exceptions/Cleanup.java | 30 -- code/exceptions/CleanupIdiom.java | 72 --- code/exceptions/CloseExceptions.java | 48 -- code/exceptions/ConstructorException.java | 33 -- code/exceptions/DynamicFields.java | 130 ------ code/exceptions/ExceptionMethods.java | 32 -- code/exceptions/ExceptionSilencer.java | 16 - code/exceptions/ExtraFeatures.java | 72 --- code/exceptions/FinallyWorks.java | 32 -- code/exceptions/FullConstructors.java | 44 -- code/exceptions/Human.java | 31 -- code/exceptions/InheritingExceptions.java | 28 -- code/exceptions/InputFile.java | 47 -- code/exceptions/InputFile2.java | 28 -- code/exceptions/LoggingExceptions.java | 48 -- code/exceptions/LoggingExceptions2.java | 32 -- code/exceptions/LostMessage.java | 44 -- code/exceptions/MainException.java | 17 - code/exceptions/MessyExceptions.java | 27 -- code/exceptions/MultiCatch.java | 16 - code/exceptions/MultiCatch2.java | 19 - code/exceptions/MultipleReturns.java | 47 -- code/exceptions/NeverCaught.java | 26 -- code/exceptions/OnOffException1.java | 5 - code/exceptions/OnOffException2.java | 5 - code/exceptions/OnOffSwitch.java | 29 -- code/exceptions/PreciseRethrow.java | 17 - code/exceptions/RethrowNew.java | 47 -- code/exceptions/Rethrowing.java | 70 --- code/exceptions/SameHandler.java | 31 -- code/exceptions/StormyInning.java | 83 ---- code/exceptions/StreamsAreAutoCloseable.java | 24 - code/exceptions/Switch.java | 21 - code/exceptions/TryAnything.java | 16 - code/exceptions/TryWithResources.java | 19 - code/exceptions/TurnOffChecking.java | 64 --- code/exceptions/WhoCalled.java | 39 -- code/exceptions/WithFinally.java | 26 -- code/files/AddAndSubtractPaths.java | 87 ---- code/files/Directories.java | 94 ---- code/files/FileSystemDemo.java | 41 -- code/files/Find.java | 60 --- code/files/ListOfLines.java | 26 -- code/files/PartsOfPaths.java | 45 -- code/files/PathAnalysis.java | 56 --- code/files/PathInfo.java | 102 ----- code/files/PathWatcher.java | 61 --- code/files/ReadLineStream.java | 18 - code/files/StreamInAndOut.java | 24 - code/files/TreeWatcher.java | 51 --- code/files/Writing.java | 31 -- code/functional/AnonymousClosure.java | 17 - code/functional/BiConsumerPermutations.java | 24 - code/functional/ClassFunctionals.java | 45 -- code/functional/Closure1.java | 12 - code/functional/Closure2.java | 12 - code/functional/Closure3.java | 14 - code/functional/Closure4.java | 12 - code/functional/Closure5.java | 15 - code/functional/Closure6.java | 16 - code/functional/Closure7.java | 14 - code/functional/Closure8.java | 32 -- code/functional/Closure9.java | 15 - code/functional/ConsumeFunction.java | 17 - code/functional/CtorReference.java | 36 -- code/functional/CurriedIntAdd.java | 17 - code/functional/Curry3Args.java | 23 - code/functional/CurryingAndPartials.java | 35 -- code/functional/FunctionComposition.java | 24 - code/functional/FunctionVariants.java | 65 --- code/functional/FunctionWithWrapped.java | 12 - code/functional/FunctionalAnnotation.java | 40 -- code/functional/IntCall.java | 8 - code/functional/LambdaExpressions.java | 48 -- code/functional/MethodConversion.java | 31 -- code/functional/MethodReferences.java | 53 --- code/functional/MultiUnbound.java | 36 -- code/functional/PredicateComposition.java | 23 - code/functional/ProduceFunction.java | 21 - code/functional/RecursiveFactorial.java | 26 -- code/functional/RecursiveFibonacci.java | 32 -- code/functional/RunnableMethodReference.java | 33 -- code/functional/SharedStorage.java | 22 - code/functional/Strategize.java | 58 --- code/functional/TransformFunction.java | 35 -- code/functional/TriFunction.java | 9 - code/functional/TriFunctionTest.java | 13 - code/functional/UnboundMethodReference.java | 31 -- code/generics/Amphibian.java | 5 - code/generics/Apply.java | 21 - code/generics/ApplyFunctional.java | 49 --- code/generics/ApplyTest.java | 65 --- code/generics/ArrayMaker.java | 24 - code/generics/ArrayOfGeneric.java | 28 -- code/generics/ArrayOfGenericReference.java | 10 - code/generics/BankTeller.java | 71 --- code/generics/BasicBounds.java | 63 --- code/generics/BasicHolder.java | 14 - code/generics/BasicSupplierDemo.java | 22 - code/generics/ByteSet.java | 14 - code/generics/CRGWithBasicHolder.java | 20 - code/generics/CaptureConversion.java | 62 --- code/generics/CheckedList.java | 35 -- code/generics/ClassCasting.java | 18 - code/generics/ClassTypeCapture.java | 33 -- code/generics/ComparablePet.java | 12 - code/generics/CompilerIntelligence.java | 15 - code/generics/CountedObject.java | 14 - code/generics/CovariantArrays.java | 30 -- code/generics/CovariantReturnTypes.java | 23 - code/generics/CreatorGeneric.java | 31 -- code/generics/CuriouslyRecurringGeneric.java | 9 - code/generics/Diamond.java | 13 - .../DogsAndRobotMethodReferences.java | 45 -- code/generics/DogsAndRobots.cpp | 38 -- code/generics/DogsAndRobots.java | 41 -- code/generics/DogsAndRobots.py | 36 -- code/generics/DynamicProxyMixin.java | 66 --- code/generics/EpicBattle.java | 74 ---- code/generics/Erased.java | 24 - code/generics/ErasedTypeEquivalence.java | 16 - code/generics/ErasureAndInheritance.java | 28 -- code/generics/FactoryConstraint.java | 62 --- code/generics/Fibonacci.java | 27 -- code/generics/FilledList.java | 28 -- code/generics/GenericArray.java | 32 -- code/generics/GenericArray2.java | 39 -- code/generics/GenericArrayWithTypeToken.java | 27 -- code/generics/GenericCast.java | 47 -- code/generics/GenericHolder.java | 19 - code/generics/GenericHolder2.java | 16 - code/generics/GenericMethods.java | 27 -- code/generics/GenericReading.java | 46 -- code/generics/GenericVarargs.java | 30 -- code/generics/GenericsAndCovariance.java | 19 - code/generics/GenericsAndReturnTypes.java | 17 - code/generics/HasF.java | 10 - code/generics/HijackedInterface.java | 16 - code/generics/Holder.java | 42 -- code/generics/Holder1.java | 12 - code/generics/InheritBounds.java | 40 -- code/generics/InstantiateGenericType.cpp | 20 - code/generics/InstantiateGenericType.java | 46 -- code/generics/IterableFibonacci.java | 36 -- code/generics/LatentReflection.java | 65 --- code/generics/LinkedStack.java | 43 -- code/generics/ListMaker.java | 13 - code/generics/ListOfGenerics.java | 11 - code/generics/ListOfInt.java | 20 - code/generics/LostInformation.java | 33 -- code/generics/Manipulation.java | 21 - code/generics/Manipulator2.java | 10 - code/generics/Manipulator3.java | 10 - code/generics/Mixins.cpp | 47 -- code/generics/Mixins.java | 71 --- code/generics/MultipleInterfaceVariants.java | 13 - code/generics/NeedCasting.java | 15 - code/generics/NonCovariantGenerics.java | 11 - code/generics/NotSelfBounded.java | 24 - code/generics/ObjectHolder.java | 20 - code/generics/OrdinaryArguments.java | 31 -- code/generics/Performs.java | 9 - code/generics/PlainGenericInheritance.java | 30 -- code/generics/PrimitiveGenericTest.java | 42 -- code/generics/RandomList.java | 26 -- code/generics/RestrictedComparablePets.java | 19 - code/generics/ReturnGenericType.java | 10 - code/generics/SelfBounding.java | 40 -- .../SelfBoundingAndCovariantArguments.java | 31 -- code/generics/SelfBoundingMethods.java | 13 - code/generics/Shape.java | 19 - code/generics/SimpleDogsAndRobots.java | 25 -- code/generics/SimpleHolder.java | 15 - code/generics/SimpleQueue.java | 16 - code/generics/Square.java | 5 - code/generics/Store.java | 90 ---- code/generics/SuperTypeWildcards.java | 13 - code/generics/Templates.cpp | 27 -- code/generics/ThrowGenericException.java | 82 ---- code/generics/TupleList.java | 23 - code/generics/TupleTest.java | 42 -- code/generics/TupleTest2.java | 42 -- code/generics/UnboundedWildcards1.java | 58 --- code/generics/UnboundedWildcards2.java | 35 -- code/generics/Unconstrained.java | 20 - code/generics/UseList.java | 11 - code/generics/UseList2.java | 10 - code/generics/Vehicle.java | 5 - code/generics/WatercolorSets.java | 54 --- code/generics/Wildcards.java | 285 ------------ code/generics/coffee/Americano.java | 6 - code/generics/coffee/Breve.java | 6 - code/generics/coffee/Cappuccino.java | 6 - code/generics/coffee/Coffee.java | 14 - code/generics/coffee/CoffeeSupplier.java | 72 --- code/generics/coffee/Latte.java | 6 - code/generics/coffee/Mocha.java | 6 - code/generics/decorator/Decoration.java | 51 --- code/generics/dogsandrobots.go | 32 -- code/generics/watercolors/Watercolors.java | 15 - code/gradle.properties | 1 - code/gradle/checkstyle.gradle | 14 - code/gradle/findbugs.gradle | 15 - code/gradle/java.gradle | 39 -- code/gradle/jmh.gradle | 17 - code/gradle/junit-jupiter.gradle | 72 --- code/gradle/subprojects.gradle | 67 --- code/gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 0 bytes code/gradle/wrapper/gradle-wrapper.properties | 5 - code/gradlew | 185 -------- code/gradlew.bat | 89 ---- code/hiding/Cake.java | 15 - code/hiding/ChocolateChip.java | 23 - code/hiding/ChocolateChip2.java | 21 - code/hiding/CreatePackageAccessObject.java | 12 - code/hiding/Dinner.java | 16 - code/hiding/FullQualification.java | 11 - code/hiding/IceCream.java | 19 - code/hiding/ImportedMyClass.java | 11 - code/hiding/LibTest.java | 17 - code/hiding/Lunch.java | 36 -- code/hiding/OrganizedByAccess.java | 15 - code/hiding/Pie.java | 9 - code/hiding/QualifiedMyClass.java | 11 - code/hiding/SingleImport.java | 11 - code/hiding/cookie2/Cookie.java | 14 - code/hiding/dessert/Cookie.java | 13 - code/hiding/mypackage/MyClass.java | 9 - .../packageaccess/PublicConstructor.java | 9 - code/housekeeping/Apricot.java | 8 - code/housekeeping/ArrayClassObj.java | 22 - code/housekeeping/ArrayInit.java | 25 -- code/housekeeping/ArrayNew.java | 20 - code/housekeeping/ArraysOfPrimitives.java | 23 - code/housekeeping/AutoboxingVarargs.java | 22 - code/housekeeping/BananaPeel.java | 15 - code/housekeeping/Burrito.java | 39 -- code/housekeeping/Counter.java | 9 - code/housekeeping/DefaultConstructor.java | 12 - code/housekeeping/Demotion.java | 43 -- code/housekeeping/DynamicArray.java | 21 - code/housekeeping/EnumOrder.java | 19 - code/housekeeping/ExplicitStatic.java | 41 -- code/housekeeping/Flower.java | 46 -- code/housekeeping/InitialValues.java | 44 -- code/housekeeping/InitialValues2.java | 16 - code/housekeeping/Leaf.java | 23 - code/housekeeping/Measurement.java | 10 - code/housekeeping/MethodInit.java | 8 - code/housekeeping/MethodInit2.java | 10 - code/housekeeping/MethodInit3.java | 10 - code/housekeeping/Mugs.java | 47 -- code/housekeeping/NewVarArgs.java | 30 -- code/housekeeping/NoSynthesis.java | 17 - .../OptionalTrailingArguments.java | 23 - code/housekeeping/OrderOfInitialization.java | 40 -- code/housekeeping/Overloading.java | 56 --- code/housekeeping/OverloadingOrder.java | 22 - code/housekeeping/OverloadingVarargs.java | 37 -- code/housekeeping/OverloadingVarargs2.java | 18 - code/housekeeping/OverloadingVarargs3.java | 21 - code/housekeeping/PassingThis.java | 31 -- code/housekeeping/PrimitiveOverloading.java | 120 ----- code/housekeeping/SimpleConstructor.java | 21 - code/housekeeping/SimpleConstructor2.java | 21 - code/housekeeping/SimpleEnumUse.java | 14 - code/housekeeping/Spiciness.java | 8 - code/housekeeping/Spoon.java | 10 - code/housekeeping/StaticInitialization.java | 73 ---- code/housekeeping/TerminationCondition.java | 41 -- code/housekeeping/VarArgs.java | 26 -- code/housekeeping/VarargType.java | 30 -- code/innerclasses/AnonymousConstructor.java | 34 -- code/innerclasses/BigEgg.java | 33 -- code/innerclasses/BigEgg2.java | 44 -- code/innerclasses/Callbacks.java | 84 ---- code/innerclasses/ClassInInterface.java | 21 - code/innerclasses/Contents.java | 7 - code/innerclasses/Destination.java | 7 - code/innerclasses/DotNew.java | 13 - code/innerclasses/DotThis.java | 24 - code/innerclasses/GreenhouseController.java | 54 --- code/innerclasses/GreenhouseControls.java | 150 ------- code/innerclasses/InheritInner.java | 20 - code/innerclasses/LocalInnerClass.java | 67 --- code/innerclasses/MultiImplementation.java | 25 -- code/innerclasses/MultiNestingAccess.java | 28 -- code/innerclasses/Parcel1.java | 33 -- code/innerclasses/Parcel10.java | 31 -- code/innerclasses/Parcel11.java | 40 -- code/innerclasses/Parcel2.java | 41 -- code/innerclasses/Parcel3.java | 25 -- code/innerclasses/Parcel5.java | 23 - code/innerclasses/Parcel6.java | 28 -- code/innerclasses/Parcel7.java | 19 - code/innerclasses/Parcel7b.java | 20 - code/innerclasses/Parcel8.java | 21 - code/innerclasses/Parcel9.java | 20 - code/innerclasses/Sequence.java | 48 -- code/innerclasses/TestBed.java | 19 - code/innerclasses/TestParcel.java | 37 -- code/innerclasses/Wrapping.java | 9 - code/innerclasses/controller/Controller.java | 24 - code/innerclasses/controller/Event.java | 23 - code/innerclasses/mui/MultiInterfaces.java | 32 -- code/interfaces/AbstractAccess.java | 15 - code/interfaces/AbstractWithoutAbstracts.java | 14 - code/interfaces/AdaptedRandomDoubles.java | 35 -- code/interfaces/Adventure.java | 41 -- code/interfaces/AnImplementation.java | 22 - code/interfaces/AnInterface.java | 9 - code/interfaces/Applicator.java | 58 --- code/interfaces/AttemptToUseBasic.java | 10 - code/interfaces/Basic.java | 8 - code/interfaces/Basic2.java | 10 - code/interfaces/Factories.java | 67 --- code/interfaces/Games.java | 59 --- code/interfaces/HorrorShow.java | 57 --- code/interfaces/Implementation2.java | 26 -- code/interfaces/ImplementingAnInterface.java | 14 - code/interfaces/Instantiable.java | 19 - code/interfaces/InterfaceCollision.java | 31 -- code/interfaces/InterfaceWithDefault.java | 12 - code/interfaces/Jim.java | 28 -- code/interfaces/MICollision.java | 60 --- code/interfaces/Machine.java | 36 -- code/interfaces/Months.java | 13 - code/interfaces/MultipleInheritance.java | 35 -- code/interfaces/PureInterface.java | 11 - code/interfaces/RandVals.java | 15 - code/interfaces/RandomDoubles.java | 21 - code/interfaces/RandomStrings.java | 50 --- code/interfaces/TestRandVals.java | 19 - code/interfaces/filters/BandPass.java | 17 - code/interfaces/filters/Filter.java | 14 - code/interfaces/filters/HighPass.java | 16 - code/interfaces/filters/LowPass.java | 16 - code/interfaces/filters/Waveform.java | 14 - .../interfaceprocessor/Applicator.java | 12 - .../interfaceprocessor/FilterProcessor.java | 40 -- .../interfaceprocessor/Processor.java | 12 - .../interfaceprocessor/StringProcessor.java | 50 --- code/interfaces/music4/Music4.java | 105 ----- code/interfaces/music5/Music5.java | 74 ---- .../interfaces/nesting/NestingInterfaces.java | 105 ----- code/iostreams/BasicFileOutput.java | 26 -- code/iostreams/BufferedInputFile.java | 23 - code/iostreams/FileOutputShortcut.java | 24 - code/iostreams/FormattedMemoryInput.java | 25 -- code/iostreams/MemoryInput.java | 17 - code/iostreams/StoringAndRecoveringData.java | 42 -- code/iostreams/TestEOF.java | 22 - code/iostreams/UsingRandomAccessFile.java | 65 --- code/javadoc/Documentation1.java | 11 - code/javadoc/Documentation2.java | 9 - code/javadoc/Documentation3.java | 12 - code/javadoc/HelloDateDoc.java | 26 -- code/lowlevel/AtomicEvenProducer.java | 21 - code/lowlevel/AtomicIntegerTest.java | 20 - code/lowlevel/AtomicSerialNumbers.java | 21 - code/lowlevel/Atomicity.java | 20 - code/lowlevel/AttemptLocking.java | 57 --- code/lowlevel/CaptureUncaughtException.java | 56 --- code/lowlevel/CircularSet.java | 29 -- code/lowlevel/DelayQueueDemo.java | 99 ----- code/lowlevel/EvenChecker.java | 41 -- code/lowlevel/EvenProducer.java | 26 -- code/lowlevel/ExceptionThread.java | 30 -- code/lowlevel/IntGenerator.java | 15 - code/lowlevel/IntTestable.java | 15 - code/lowlevel/MutexEvenProducer.java | 30 -- code/lowlevel/NaiveExceptionHandling.java | 32 -- code/lowlevel/NotAtomic.java | 49 --- code/lowlevel/NumberOfProcessors.java | 14 - code/lowlevel/PriorityBlockingQueueDemo.java | 139 ------ code/lowlevel/ReOrdering.java | 19 - code/lowlevel/SafeReturn.java | 20 - code/lowlevel/SerialNumberChecker.java | 32 -- code/lowlevel/SerialNumberTest.java | 13 - code/lowlevel/SerialNumbers.java | 11 - code/lowlevel/SettingDefaultHandler.java | 19 - code/lowlevel/SwallowedException.java | 17 - code/lowlevel/SyncOnObject.java | 70 --- code/lowlevel/SynchronizedComparison.java | 89 ---- code/lowlevel/SynchronizedEvenProducer.java | 24 - code/lowlevel/SynchronizedSerialNumbers.java | 19 - code/lowlevel/TestAbort.java | 17 - code/lowlevel/ThreadSize.java | 31 -- code/lowlevel/UnsafeReturn.java | 20 - code/lowlevel/WorkStealingPool.java | 41 -- code/newio/AvailableCharSets.java | 43 -- code/newio/BufferToText.java | 93 ---- code/newio/ChannelCopy.java | 35 -- code/newio/Endians.java | 28 -- code/newio/FileLocking.java | 30 -- code/newio/GetChannel.java | 53 --- code/newio/GetData.java | 56 --- code/newio/IntBufferDemo.java | 35 -- code/newio/LargeMappedFiles.java | 31 -- code/newio/LockingMappedFiles.java | 60 --- code/newio/MappedIO.java | 145 ------ code/newio/TransferTo.java | 30 -- code/newio/UsingBuffers.java | 35 -- code/newio/ViewBuffers.java | 69 --- code/objects/HelloDate.java | 12 - code/objects/ShowProperties.java | 39 -- code/onjava/ArrayShow.java | 73 ---- code/onjava/BasicSupplier.java | 31 -- code/onjava/CollectionMethodDifferences.java | 117 ----- code/onjava/ConvertTo.java | 105 ----- code/onjava/Count.java | 220 ---------- code/onjava/CountMap.java | 97 ----- code/onjava/CountingIntegerList.java | 34 -- code/onjava/Countries.java | 351 --------------- code/onjava/Enums.java | 17 - code/onjava/FillMap.java | 38 -- code/onjava/HTMLColors.java | 236 ---------- code/onjava/MouseClick.java | 19 - code/onjava/Nap.java | 20 - code/onjava/Null.java | 6 - code/onjava/OSExecute.java | 37 -- code/onjava/OSExecuteException.java | 12 - code/onjava/Operations.java | 17 - code/onjava/Pair.java | 19 - code/onjava/ProcessFiles.java | 48 -- code/onjava/Rand.java | 248 ----------- code/onjava/Range.java | 34 -- code/onjava/Repeat.java | 12 - code/onjava/RmDir.java | 31 -- code/onjava/Sets.java | 32 -- code/onjava/Stack.java | 20 - code/onjava/Suppliers.java | 36 -- code/onjava/TimedAbort.java | 30 -- code/onjava/Timer.java | 19 - code/onjava/Tuple.java | 24 - code/onjava/Tuple2.java | 16 - code/onjava/Tuple3.java | 17 - code/onjava/Tuple4.java | 18 - code/onjava/Tuple5.java | 18 - code/onjava/TypeCounter.java | 41 -- code/onjava/atunit/AtUnit.java | 177 -------- code/onjava/atunit/ClassNameFinder.java | 180 -------- code/onjava/atunit/Test.java | 11 - code/onjava/atunit/TestObjectCleanup.java | 11 - code/onjava/atunit/TestObjectCreate.java | 11 - code/onjava/atunit/TestProperty.java | 12 - code/operators/AllOps.java | 411 ------------------ code/operators/Assignment.java | 31 -- code/operators/AutoInc.java | 27 -- code/operators/BitManipulation.java | 98 ----- code/operators/Bool.java | 42 -- code/operators/Casting.java | 16 - code/operators/CastingNumbers.java | 23 - code/operators/EqualsMethod.java | 15 - code/operators/EqualsMethod2.java | 21 - code/operators/Equivalence.java | 17 - code/operators/Exponents.java | 21 - code/operators/Literals.java | 61 --- code/operators/MathOps.java | 75 ---- code/operators/Overflow.java | 18 - code/operators/PassObject.java | 27 -- code/operators/Precedence.java | 18 - code/operators/RoundingNumbers.java | 26 -- code/operators/ShortCircuit.java | 34 -- code/operators/StringOperators.java | 24 - code/operators/TernaryIfElse.java | 28 -- code/operators/URShift.java | 42 -- code/operators/Underscores.java | 22 - code/patterns/BoxObserver.java | 94 ---- code/patterns/CommandPattern.java | 19 - code/patterns/Facade.java | 24 - code/patterns/PaperScissorsRock.java | 135 ------ code/patterns/ProxyDemo.java | 51 --- code/patterns/ShapeFactory1.java | 39 -- code/patterns/ShapeFactory2.java | 54 --- code/patterns/ShapeFactory3.java | 52 --- code/patterns/SingletonPattern.java | 58 --- code/patterns/StateDemo.java | 87 ---- code/patterns/TemplateMethod.java | 44 -- .../abstractfactory/GameEnvironment.java | 96 ---- code/patterns/adapt/Adapter.java | 85 ---- .../patterns/chain/ChainOfResponsibility.java | 90 ---- code/patterns/doubledispatch/Aluminum.java | 18 - code/patterns/doubledispatch/Cardboard.java | 18 - .../doubledispatch/DoubleDispatch.java | 96 ---- code/patterns/doubledispatch/Glass.java | 18 - code/patterns/doubledispatch/Paper.java | 18 - code/patterns/doubledispatch/TypedBin.java | 28 -- .../doubledispatch/TypedBinMember.java | 14 - code/patterns/dynatrash/DynaTrash.java | 74 ---- code/patterns/observer/ObservedFlower.java | 125 ------ code/patterns/recyclea/RecycleA.java | 127 ------ code/patterns/recycleb/RecycleB.java | 56 --- code/patterns/recyclec/RecycleC.java | 84 ---- code/patterns/shapes/BadShapeCreation.java | 12 - code/patterns/shapes/Circle.java | 7 - code/patterns/shapes/FactoryMethod.java | 9 - code/patterns/shapes/FactoryTest.java | 17 - code/patterns/shapes/Shape.java | 21 - code/patterns/shapes/Square.java | 7 - code/patterns/shapes/Triangle.java | 7 - code/patterns/state/StateMachineDemo.java | 80 ---- code/patterns/strategy/StrategyPattern.java | 64 --- code/patterns/strategy/StrategyPattern2.java | 43 -- code/patterns/trash/Aluminum.java | 15 - code/patterns/trash/Cardboard.java | 15 - code/patterns/trash/Fillable.java | 10 - code/patterns/trash/FillableList.java | 17 - code/patterns/trash/Glass.java | 15 - code/patterns/trash/Paper.java | 15 - code/patterns/trash/ParseTrash.java | 91 ---- code/patterns/trash/Trash.dat | 35 -- code/patterns/trash/Trash.java | 92 ---- code/patterns/trashvisitor/Aluminum.java | 16 - code/patterns/trashvisitor/Cardboard.java | 16 - code/patterns/trashvisitor/Glass.java | 16 - code/patterns/trashvisitor/Paper.java | 16 - code/patterns/trashvisitor/TrashVisitor.java | 127 ------ code/patterns/trashvisitor/Visitable.java | 12 - code/patterns/trashvisitor/Visitor.java | 14 - code/patterns/visitor/BeeAndFlowers.java | 122 ------ code/polymorphism/CovariantReturn.java | 38 -- code/polymorphism/FieldAccess.java | 36 -- code/polymorphism/Frog.java | 122 ------ code/polymorphism/PolyConstructors.java | 41 -- code/polymorphism/PrivateOverride.java | 24 - code/polymorphism/PrivateOverride2.java | 22 - code/polymorphism/RTTI.java | 43 -- code/polymorphism/ReferenceCounting.java | 71 --- code/polymorphism/Sandwich.java | 54 --- code/polymorphism/Shapes.java | 26 -- code/polymorphism/StaticPolymorphism.java | 36 -- code/polymorphism/Transmogrify.java | 43 -- code/polymorphism/music/Instrument.java | 11 - code/polymorphism/music/Music.java | 21 - code/polymorphism/music/Music2.java | 46 -- code/polymorphism/music/Note.java | 10 - code/polymorphism/music/Wind.java | 15 - code/polymorphism/music3/Music3.java | 108 ----- code/polymorphism/shape/Circle.java | 16 - code/polymorphism/shape/RandomShapes.java | 26 -- code/polymorphism/shape/Shape.java | 10 - code/polymorphism/shape/Square.java | 16 - code/polymorphism/shape/Triangle.java | 16 - code/references/AddingClone.java | 67 --- code/references/Alias1.java | 27 -- code/references/Alias2.java | 25 -- code/references/CheckCloneable.java | 113 ----- code/references/CloneArrayList.java | 38 -- code/references/Compete.java | 89 ---- code/references/CopyConstructor.java | 188 -------- code/references/DepthReading.java | 29 -- code/references/HorrorFlick.java | 35 -- code/references/Immutable1.java | 34 -- code/references/Immutable2.java | 71 --- code/references/ImmutableInteger.java | 22 - code/references/ImmutableStrings.java | 25 -- code/references/LocalCopy.java | 57 --- code/references/MutableInteger.java | 34 -- code/references/OceanReading.java | 48 -- code/references/PassReferences.java | 19 - code/references/SimplerMutableInteger.java | 30 -- code/references/Snake.java | 51 --- code/references/Stringer.java | 22 - code/references/TemperatureReading.java | 33 -- code/references/tests/DeepCopyTest.java | 28 -- code/reuse/Bath.java | 61 --- code/reuse/Beetle.java | 43 -- code/reuse/BlankFinal.java | 29 -- code/reuse/CADSystem.java | 116 ----- code/reuse/Car.java | 43 -- code/reuse/Cartoon.java | 31 -- code/reuse/Chess.java | 33 -- code/reuse/DerivedSpaceShip.java | 19 - code/reuse/Detergent.java | 48 -- code/reuse/FinalArguments.java | 27 -- code/reuse/FinalData.java | 57 --- code/reuse/FinalOverridingIllusion.java | 56 --- code/reuse/Hide.java | 41 -- code/reuse/Jurassic.java | 26 -- code/reuse/Lisa.java | 11 - code/reuse/Orc.java | 41 -- code/reuse/PlaceSetting.java | 82 ---- code/reuse/SpaceShipControls.java | 14 - code/reuse/SpaceShipDelegation.java | 40 -- code/reuse/SprinklerSystem.java | 41 -- code/reuse/Wind.java | 22 - code/serialization/APerson.java | 83 ---- code/serialization/AStoreCADState.java | 120 ----- code/serialization/Alien.java | 7 - code/serialization/Blip3.java | 75 ---- code/serialization/Blips.java | 80 ---- code/serialization/FreezeAlien.java | 19 - code/serialization/Logon.java | 62 --- code/serialization/MyWorld.java | 100 ----- code/serialization/People.java | 28 -- code/serialization/RecoverCADState.java | 42 -- code/serialization/SerialCtl.java | 60 --- code/serialization/Worm.java | 102 ----- code/serialization/xfiles/ThawAlien.java | 22 - code/settings.gradle | 13 - code/standardio/ChangeSystemOut.java | 17 - code/standardio/Echo.java | 20 - code/standardio/OSExecuteDemo.java | 16 - code/standardio/Redirecting.java | 31 -- code/staticchecking/DogsAndRobots.cpp | 33 -- code/staticchecking/DogsAndRobots.py | 26 -- code/staticchecking/NoBasePetSpeak.py | 35 -- code/staticchecking/PetSpeak.py | 28 -- code/staticchecking/dogsandrobots.go | 27 -- code/staticchecking/dr/DogsAndRobots.java | 42 -- .../drc/DogAndRobotCollections.java | 58 --- code/staticchecking/latent/Latent.java | 60 --- code/staticchecking/petspeak.go | 51 --- code/staticchecking/petspeak/PetSpeak.java | 36 -- code/streams/ArrayStreams.java | 31 -- code/streams/Bubble.java | 18 - code/streams/Bubbles.java | 20 - code/streams/Cheese.dat | 6 - code/streams/CollectionToStream.java | 39 -- code/streams/CreatingOptionals.java | 37 -- code/streams/Duplicator.java | 18 - code/streams/Fibonacci.java | 34 -- code/streams/FileToWords.java | 17 - code/streams/FileToWordsBuilder.java | 31 -- code/streams/FileToWordsRegexp.java | 39 -- code/streams/FileToWordsTest.java | 23 - code/streams/FlatMap.java | 25 -- code/streams/ForEach.java | 28 -- code/streams/FunctionMap.java | 60 --- code/streams/FunctionMap2.java | 32 -- code/streams/FunctionMap3.java | 28 -- code/streams/Generator.java | 25 -- code/streams/ImperativeRandoms.java | 21 - code/streams/Informational.java | 27 -- code/streams/LastElement.java | 24 - code/streams/Looping.java | 20 - code/streams/Machine2.java | 23 - code/streams/MapCollector.java | 48 -- code/streams/Matching.java | 38 -- code/streams/NumericStreamInfo.java | 24 - code/streams/OptionalBasics.java | 23 - code/streams/OptionalFilter.java | 72 --- code/streams/OptionalFlatMap.java | 73 ---- code/streams/OptionalMap.java | 74 ---- code/streams/Optionals.java | 63 --- code/streams/OptionalsFromEmptyStreams.java | 31 -- code/streams/Peeking.java | 22 - code/streams/Prime.java | 31 -- code/streams/RandInts.java | 15 - code/streams/RandomGenerators.java | 86 ---- code/streams/RandomWords.java | 41 -- code/streams/Randoms.java | 25 -- code/streams/Ranges.java | 29 -- code/streams/Reduce.java | 44 -- code/streams/SelectElement.java | 24 - code/streams/Signal.java | 29 -- code/streams/SortedComparator.java | 20 - code/streams/SpecialCollector.java | 24 - code/streams/StreamOf.java | 28 -- code/streams/StreamOfOptionals.java | 37 -- code/streams/StreamOfRandoms.java | 20 - code/streams/StreamOfStreams.java | 19 - code/streams/TreeSetOfWords.java | 31 -- code/strings/ArrayListDisplay.java | 22 - code/strings/BetterRead.java | 37 -- code/strings/Concatenation.java | 15 - code/strings/Conversion.java | 113 ----- code/strings/DatabaseException.java | 22 - code/strings/Finding.java | 27 -- code/strings/Groups.java | 40 -- code/strings/Hex.java | 44 -- code/strings/Immutable.java | 22 - code/strings/InfiniteRecursion.java | 22 - code/strings/IntegerMatch.java | 19 - code/strings/JGrep.java | 36 -- code/strings/ReFlags.java | 23 - code/strings/ReceiptBuilder.java | 48 -- code/strings/Replacing.java | 21 - code/strings/ReplacingStringTokenizer.java | 26 -- code/strings/Resetting.java | 23 - code/strings/Rudolph.java | 21 - code/strings/ScannerDelimiter.java | 21 - code/strings/SimpleFormat.java | 22 - code/strings/SimpleRead.java | 43 -- code/strings/SplitDemo.java | 22 - code/strings/Splitting.java | 32 -- code/strings/StartEnd.java | 82 ---- code/strings/TestRegularExpression.java | 44 -- code/strings/TheReplacements.java | 57 --- code/strings/ThreatAnalyzer.java | 36 -- code/strings/Turtle.java | 40 -- code/strings/UsingStringBuilder.java | 37 -- code/strings/WhitherStringBuilder.java | 21 - code/typeinfo/AnonymousImplementation.java | 50 --- code/typeinfo/BoundedClassReferences.java | 13 - code/typeinfo/ClassCasts.java | 16 - code/typeinfo/ClassInitialization.java | 57 --- code/typeinfo/DynamicSupplier.java | 42 -- code/typeinfo/FamilyVsExactType.java | 62 --- code/typeinfo/GenericClassReferences.java | 14 - code/typeinfo/HiddenImplementation.java | 44 -- code/typeinfo/InnerImplementation.java | 49 --- code/typeinfo/InterfaceViolation.java | 27 -- code/typeinfo/ModifyingPrivateFields.java | 49 --- code/typeinfo/NullRobot.java | 63 --- code/typeinfo/Operation.java | 15 - code/typeinfo/Person.java | 49 --- code/typeinfo/PetCount.java | 65 --- code/typeinfo/PetCount2.java | 18 - code/typeinfo/PetCount3.java | 53 --- code/typeinfo/PetCount4.java | 26 -- code/typeinfo/Position.java | 51 --- code/typeinfo/RegisteredFactories.java | 95 ---- code/typeinfo/Robot.java | 22 - code/typeinfo/SelectingMethods.java | 69 --- code/typeinfo/Shapes.java | 39 -- code/typeinfo/ShowMethods.java | 71 --- code/typeinfo/SimpleDynamicProxy.java | 53 --- code/typeinfo/SimpleProxyDemo.java | 57 --- code/typeinfo/SnowRemovalRobot.java | 42 -- code/typeinfo/Staff.java | 63 --- code/typeinfo/SweetShop.java | 42 -- code/typeinfo/WildcardClassReferences.java | 11 - code/typeinfo/interfacea/A.java | 9 - code/typeinfo/packageaccess/HiddenC.java | 29 -- code/typeinfo/pets/Cat.java | 10 - code/typeinfo/pets/Cymric.java | 10 - code/typeinfo/pets/Dog.java | 10 - code/typeinfo/pets/EgyptianMau.java | 10 - code/typeinfo/pets/ForNameCreator.java | 37 -- code/typeinfo/pets/Hamster.java | 10 - code/typeinfo/pets/Individual.java | 46 -- code/typeinfo/pets/LiteralPetCreator.java | 39 -- code/typeinfo/pets/Manx.java | 10 - code/typeinfo/pets/Mouse.java | 10 - code/typeinfo/pets/Mutt.java | 10 - code/typeinfo/pets/Person.java | 9 - code/typeinfo/pets/Pet.java | 10 - code/typeinfo/pets/PetCreator.java | 28 -- code/typeinfo/pets/Pets.java | 30 -- code/typeinfo/pets/Pug.java | 10 - code/typeinfo/pets/Rat.java | 10 - code/typeinfo/pets/Rodent.java | 10 - code/typeinfo/toys/GenericToyTest.java | 23 - code/typeinfo/toys/ToyTest.java | 78 ---- code/validating/Assert1.java | 19 - code/validating/Assert2.java | 20 - code/validating/BadMicroBenchmark.java | 29 -- code/validating/BadMicroBenchmark2.java | 35 -- code/validating/CircularQueue.java | 91 ---- code/validating/CircularQueueException.java | 12 - code/validating/CountedList.java | 16 - code/validating/GuavaAssertions.java | 49 --- code/validating/GuavaPreconditions.java | 125 ------ code/validating/Inverter1.java | 9 - code/validating/Inverter2.java | 19 - code/validating/Inverter3.java | 21 - code/validating/Inverter4.java | 26 -- code/validating/LoaderAssertions.java | 28 -- code/validating/NonNullConstruction.java | 18 - code/validating/SLF4JLevels.java | 29 -- code/validating/SLF4JLogging.java | 17 - code/validating/SimpleDebugging.java | 40 -- code/validating/StringInverter.java | 9 - code/validating/jmh/JMH1.java | 31 -- code/validating/jmh/JMH2.java | 44 -- code/validating/jmh/JMH3.java | 48 -- code/validating/logback.xml | 15 - code/validating/tests/CircularQueueTest.java | 150 ------- code/validating/tests/CountedListTest.java | 101 ----- .../tests/DynamicStringInverterTests.java | 122 ------ .../validating/tests/StringInverterTests.java | 65 --- 1051 files changed, 40784 deletions(-) delete mode 100644 code/.gitattributes delete mode 100644 code/.gitignore delete mode 100644 code/.travisXX.yml delete mode 100644 code/CI.txt delete mode 100644 code/Copyright.txt delete mode 100644 code/README.md delete mode 100644 code/annotations/AUComposition.java delete mode 100644 code/annotations/AUExternalTest.java delete mode 100644 code/annotations/AtUnitExample1.java delete mode 100644 code/annotations/AtUnitExample2.java delete mode 100644 code/annotations/AtUnitExample3.java delete mode 100644 code/annotations/AtUnitExample4.java delete mode 100644 code/annotations/AtUnitExample5.java delete mode 100644 code/annotations/DemoProcessFiles.java delete mode 100644 code/annotations/HashSetTest.java delete mode 100644 code/annotations/PasswordUtils.java delete mode 100644 code/annotations/SimulatingNull.java delete mode 100644 code/annotations/StackL.java delete mode 100644 code/annotations/StackLStringTst.java delete mode 100644 code/annotations/Testable.java delete mode 100644 code/annotations/UseCase.java delete mode 100644 code/annotations/UseCaseTracker.java delete mode 100644 code/annotations/database/Constraints.java delete mode 100644 code/annotations/database/DBTable.java delete mode 100644 code/annotations/database/Member.java delete mode 100644 code/annotations/database/SQLInteger.java delete mode 100644 code/annotations/database/SQLString.java delete mode 100644 code/annotations/database/TableCreator.java delete mode 100644 code/annotations/database/Uniqueness.java delete mode 100644 code/annotations/ifx/ExtractInterface.java delete mode 100644 code/annotations/ifx/IfaceExtractorProcessor.java delete mode 100644 code/annotations/ifx/Multiplier.java delete mode 100644 code/annotations/simplest/Simple.java delete mode 100644 code/annotations/simplest/SimpleProcessor.java delete mode 100644 code/annotations/simplest/SimpleTest.java delete mode 100644 code/appveyorXX.yml delete mode 100644 code/arrays/AlphabeticSearch.java delete mode 100644 code/arrays/ArrayCopying.java delete mode 100644 code/arrays/ArrayOfGenericType.java delete mode 100644 code/arrays/ArrayOfGenerics.java delete mode 100644 code/arrays/ArrayOptions.java delete mode 100644 code/arrays/ArraySearching.java delete mode 100644 code/arrays/AssemblingMultidimensionalArrays.java delete mode 100644 code/arrays/AutoboxingArrays.java delete mode 100644 code/arrays/CollectionComparison.java delete mode 100644 code/arrays/CompType.java delete mode 100644 code/arrays/ComparatorTest.java delete mode 100644 code/arrays/ComparingArrays.java delete mode 100644 code/arrays/CountUpward.java delete mode 100644 code/arrays/FillingArrays.java delete mode 100644 code/arrays/IceCreamFlavors.java delete mode 100644 code/arrays/ModifyExisting.java delete mode 100644 code/arrays/MultiDimWrapperArray.java delete mode 100644 code/arrays/MultidimensionalObjectArrays.java delete mode 100644 code/arrays/MultidimensionalPrimitiveArray.java delete mode 100644 code/arrays/ParallelPrefix1.java delete mode 100644 code/arrays/ParallelPrefix2.java delete mode 100644 code/arrays/ParallelPrefix3.java delete mode 100644 code/arrays/ParallelSetAll.java delete mode 100644 code/arrays/ParameterizedArrayType.java delete mode 100644 code/arrays/PythonLists.py delete mode 100644 code/arrays/RaggedArray.java delete mode 100644 code/arrays/Reverse.java delete mode 100644 code/arrays/SimpleSetAll.java delete mode 100644 code/arrays/StreamFromArray.java delete mode 100644 code/arrays/StringSorting.java delete mode 100644 code/arrays/TestConvertTo.java delete mode 100644 code/arrays/TestCount.java delete mode 100644 code/arrays/TestRand.java delete mode 100644 code/arrays/ThreeDWithNew.java delete mode 100644 code/arrays/jmh/ParallelSort.java delete mode 100644 code/build.gradle delete mode 100644 code/checkstyle.xml delete mode 100644 code/chkstyle.bat delete mode 100644 code/collections/AdapterMethodIdiom.java delete mode 100644 code/collections/AddingGroups.java delete mode 100644 code/collections/ApplesAndOrangesWithGenerics.java delete mode 100644 code/collections/ApplesAndOrangesWithoutGenerics.java delete mode 100644 code/collections/ArrayIsNotIterable.java delete mode 100644 code/collections/AsListInference.java delete mode 100644 code/collections/CollectionDifferences.java delete mode 100644 code/collections/CollectionSequence.java delete mode 100644 code/collections/CrossCollectionIteration.java delete mode 100644 code/collections/CrossCollectionIteration2.java delete mode 100644 code/collections/EnvironmentVariables.java delete mode 100644 code/collections/ForInCollections.java delete mode 100644 code/collections/GenericsAndUpcasting.java delete mode 100644 code/collections/InterfaceVsIterator.java delete mode 100644 code/collections/IterableClass.java delete mode 100644 code/collections/LinkedListFeatures.java delete mode 100644 code/collections/ListFeatures.java delete mode 100644 code/collections/ListIteration.java delete mode 100644 code/collections/MapOfList.java delete mode 100644 code/collections/ModifyingArraysAsList.java delete mode 100644 code/collections/MultiIterableClass.java delete mode 100644 code/collections/NonCollectionSequence.java delete mode 100644 code/collections/PetMap.java delete mode 100644 code/collections/PrintingCollections.java delete mode 100644 code/collections/PriorityQueueDemo.java delete mode 100644 code/collections/QueueDemo.java delete mode 100644 code/collections/SetOfInteger.java delete mode 100644 code/collections/SetOfString.java delete mode 100644 code/collections/SetOperations.java delete mode 100644 code/collections/SimpleCollection.java delete mode 100644 code/collections/SimpleIteration.java delete mode 100644 code/collections/SortedSetOfString.java delete mode 100644 code/collections/StackCollision.java delete mode 100644 code/collections/StackTest.java delete mode 100644 code/collections/StackTest2.java delete mode 100644 code/collections/Statistics.java delete mode 100644 code/collections/UniqueWords.java delete mode 100644 code/collections/UniqueWordsAlphabetic.java delete mode 100644 code/collectiontopics/AssociativeArray.java delete mode 100644 code/collectiontopics/Bits.java delete mode 100644 code/collectiontopics/CanonicalMapping.java delete mode 100644 code/collectiontopics/CollectionMethods.java delete mode 100644 code/collectiontopics/Enumerations.java delete mode 100644 code/collectiontopics/FailFast.java delete mode 100644 code/collectiontopics/FillMapTest.java delete mode 100644 code/collectiontopics/FillingLists.java delete mode 100644 code/collectiontopics/FunctionalMap.java delete mode 100644 code/collectiontopics/HTMLColorTest.java delete mode 100644 code/collectiontopics/LinkedHashMapDemo.java delete mode 100644 code/collectiontopics/ListOps.java delete mode 100644 code/collectiontopics/ListSortSearch.java delete mode 100644 code/collectiontopics/MapOps.java delete mode 100644 code/collectiontopics/NavMap.java delete mode 100644 code/collectiontopics/QueueBehavior.java delete mode 100644 code/collectiontopics/ReadOnly.java delete mode 100644 code/collectiontopics/References.java delete mode 100644 code/collectiontopics/SetOrder.java delete mode 100644 code/collectiontopics/SimpleDeques.java delete mode 100644 code/collectiontopics/SortedMapDemo.java delete mode 100644 code/collectiontopics/SortedSetDemo.java delete mode 100644 code/collectiontopics/Stacks.java delete mode 100644 code/collectiontopics/StreamFillMaps.java delete mode 100644 code/collectiontopics/SuppliersCollectionTest.java delete mode 100644 code/collectiontopics/Synchronization.java delete mode 100644 code/collectiontopics/ToDoList.java delete mode 100644 code/collectiontopics/TypesForSets.java delete mode 100644 code/collectiontopics/Unsupported.java delete mode 100644 code/collectiontopics/Utilities.java delete mode 100644 code/com/mindviewinc/simple/List.java delete mode 100644 code/com/mindviewinc/simple/Vector.java delete mode 100644 code/compression/GZIPcompress.java delete mode 100644 code/compression/ZipCompress.java delete mode 100644 code/concurrent/Baked.java delete mode 100644 code/concurrent/Batter.java delete mode 100644 code/concurrent/Breakable.java delete mode 100644 code/concurrent/CachedThreadPool.java delete mode 100644 code/concurrent/CachedThreadPool2.java delete mode 100644 code/concurrent/CachedThreadPool3.java delete mode 100644 code/concurrent/CatchCompletableExceptions.java delete mode 100644 code/concurrent/CollectionIntoStream.java delete mode 100644 code/concurrent/CompletableApply.java delete mode 100644 code/concurrent/CompletableApplyAsync.java delete mode 100644 code/concurrent/CompletableApplyChained.java delete mode 100644 code/concurrent/CompletableExceptions.java delete mode 100644 code/concurrent/CompletableOperations.java delete mode 100644 code/concurrent/CompletablePizza.java delete mode 100644 code/concurrent/CompletableUtilities.java delete mode 100644 code/concurrent/CompletedMachina.java delete mode 100644 code/concurrent/CountingStream.java delete mode 100644 code/concurrent/CountingTask.java delete mode 100644 code/concurrent/DiningPhilosophers.java delete mode 100644 code/concurrent/DualCompletableOperations.java delete mode 100644 code/concurrent/FrostedCake.java delete mode 100644 code/concurrent/Futures.java delete mode 100644 code/concurrent/GuardedIDField.java delete mode 100644 code/concurrent/HasID.java delete mode 100644 code/concurrent/IDChecker.java delete mode 100644 code/concurrent/InterferingTask.java delete mode 100644 code/concurrent/LambdasAndMethodReferences.java delete mode 100644 code/concurrent/Machina.java delete mode 100644 code/concurrent/MoreTasksAfterShutdown.java delete mode 100644 code/concurrent/NapTask.java delete mode 100644 code/concurrent/OnePizza.java delete mode 100644 code/concurrent/ParallelPrime.java delete mode 100644 code/concurrent/ParallelStreamPuzzle.java delete mode 100644 code/concurrent/ParallelStreamPuzzle2.java delete mode 100644 code/concurrent/ParallelStreamPuzzle3.java delete mode 100644 code/concurrent/Philosopher.java delete mode 100644 code/concurrent/Pizza.java delete mode 100644 code/concurrent/PizzaParallelSteps.java delete mode 100644 code/concurrent/PizzaStreams.java delete mode 100644 code/concurrent/QuittableTask.java delete mode 100644 code/concurrent/QuittingCompletable.java delete mode 100644 code/concurrent/QuittingTasks.java delete mode 100644 code/concurrent/SharedConstructorArgument.java delete mode 100644 code/concurrent/SingleThreadExecutor.java delete mode 100644 code/concurrent/SingleThreadExecutor2.java delete mode 100644 code/concurrent/SingleThreadExecutor3.java delete mode 100644 code/concurrent/StaticIDField.java delete mode 100644 code/concurrent/StickHolder.java delete mode 100644 code/concurrent/StreamExceptions.java delete mode 100644 code/concurrent/Summing.java delete mode 100644 code/concurrent/Summing2.java delete mode 100644 code/concurrent/Summing3.java delete mode 100644 code/concurrent/Summing4.java delete mode 100644 code/concurrent/SynchronizedConstructor.java delete mode 100644 code/concurrent/SynchronizedFactory.java delete mode 100644 code/concurrent/TestStaticIDField.java delete mode 100644 code/concurrent/ThrowsChecked.java delete mode 100644 code/concurrent/Workable.java delete mode 100644 code/control/BreakAndContinue.java delete mode 100644 code/control/CommaOperator.java delete mode 100644 code/control/ForInFloat.java delete mode 100644 code/control/ForInInt.java delete mode 100644 code/control/ForInString.java delete mode 100644 code/control/IfElse.java delete mode 100644 code/control/LabeledFor.java delete mode 100644 code/control/LabeledWhile.java delete mode 100644 code/control/ListCharacters.java delete mode 100644 code/control/RandomBounds.java delete mode 100644 code/control/StringSwitch.java delete mode 100644 code/control/TestWithReturn.java delete mode 100644 code/control/TrueFalse.java delete mode 100644 code/control/VowelsAndConsonants.java delete mode 100644 code/control/WhileTest.java delete mode 100644 code/enums/AlarmPoints.java delete mode 100644 code/enums/BigEnumSet.java delete mode 100644 code/enums/Burrito2.java delete mode 100644 code/enums/CarWash.java delete mode 100644 code/enums/Competitor.java delete mode 100644 code/enums/ConstantSpecificMethod.java delete mode 100644 code/enums/EnumClass.java delete mode 100644 code/enums/EnumMaps.java delete mode 100644 code/enums/EnumSets.java delete mode 100644 code/enums/Input.java delete mode 100644 code/enums/NonEnum.java delete mode 100644 code/enums/NotClasses.java delete mode 100644 code/enums/Outcome.java delete mode 100644 code/enums/OverrideConstantSpecific.java delete mode 100644 code/enums/OzWitch.java delete mode 100644 code/enums/PostOffice.java delete mode 100644 code/enums/RandomTest.java delete mode 100644 code/enums/Reflection.java delete mode 100644 code/enums/RoShamBo.java delete mode 100644 code/enums/RoShamBo1.java delete mode 100644 code/enums/RoShamBo2.java delete mode 100644 code/enums/RoShamBo3.java delete mode 100644 code/enums/RoShamBo4.java delete mode 100644 code/enums/RoShamBo5.java delete mode 100644 code/enums/RoShamBo6.java delete mode 100644 code/enums/SecurityCategory.java delete mode 100644 code/enums/SpaceShip.java delete mode 100644 code/enums/SpicinessEnum.java delete mode 100644 code/enums/TrafficLight.java delete mode 100644 code/enums/UpcastEnum.java delete mode 100644 code/enums/VendingMachine.java delete mode 100644 code/enums/VendingMachineInput.txt delete mode 100644 code/enums/cartoons/EnumImplementation.java delete mode 100644 code/enums/menu/Course.java delete mode 100644 code/enums/menu/Food.java delete mode 100644 code/enums/menu/Meal.java delete mode 100644 code/enums/menu/Meal2.java delete mode 100644 code/enums/menu/TypeOfFood.java delete mode 100644 code/equalshashcode/ComposedEquality.java delete mode 100644 code/equalshashcode/CountedString.java delete mode 100644 code/equalshashcode/DefaultComparison.java delete mode 100644 code/equalshashcode/Equality.java delete mode 100644 code/equalshashcode/EqualityFactory.java delete mode 100644 code/equalshashcode/Groundhog.java delete mode 100644 code/equalshashcode/Groundhog2.java delete mode 100644 code/equalshashcode/IndividualTest.java delete mode 100644 code/equalshashcode/MapEntry.java delete mode 100644 code/equalshashcode/Prediction.java delete mode 100644 code/equalshashcode/SimpleHashMap.java delete mode 100644 code/equalshashcode/SlowMap.java delete mode 100644 code/equalshashcode/SpringDetector.java delete mode 100644 code/equalshashcode/SpringDetector2.java delete mode 100644 code/equalshashcode/StringHashCode.java delete mode 100644 code/equalshashcode/SubtypeEquality.java delete mode 100644 code/equalshashcode/SubtypeEquality2.java delete mode 100644 code/equalshashcode/SuccinctEquality.java delete mode 100644 code/exceptions/AlwaysFinally.java delete mode 100644 code/exceptions/AutoCloseableDetails.java delete mode 100644 code/exceptions/BodyException.java delete mode 100644 code/exceptions/Cleanup.java delete mode 100644 code/exceptions/CleanupIdiom.java delete mode 100644 code/exceptions/CloseExceptions.java delete mode 100644 code/exceptions/ConstructorException.java delete mode 100644 code/exceptions/DynamicFields.java delete mode 100644 code/exceptions/ExceptionMethods.java delete mode 100644 code/exceptions/ExceptionSilencer.java delete mode 100644 code/exceptions/ExtraFeatures.java delete mode 100644 code/exceptions/FinallyWorks.java delete mode 100644 code/exceptions/FullConstructors.java delete mode 100644 code/exceptions/Human.java delete mode 100644 code/exceptions/InheritingExceptions.java delete mode 100644 code/exceptions/InputFile.java delete mode 100644 code/exceptions/InputFile2.java delete mode 100644 code/exceptions/LoggingExceptions.java delete mode 100644 code/exceptions/LoggingExceptions2.java delete mode 100644 code/exceptions/LostMessage.java delete mode 100644 code/exceptions/MainException.java delete mode 100644 code/exceptions/MessyExceptions.java delete mode 100644 code/exceptions/MultiCatch.java delete mode 100644 code/exceptions/MultiCatch2.java delete mode 100644 code/exceptions/MultipleReturns.java delete mode 100644 code/exceptions/NeverCaught.java delete mode 100644 code/exceptions/OnOffException1.java delete mode 100644 code/exceptions/OnOffException2.java delete mode 100644 code/exceptions/OnOffSwitch.java delete mode 100644 code/exceptions/PreciseRethrow.java delete mode 100644 code/exceptions/RethrowNew.java delete mode 100644 code/exceptions/Rethrowing.java delete mode 100644 code/exceptions/SameHandler.java delete mode 100644 code/exceptions/StormyInning.java delete mode 100644 code/exceptions/StreamsAreAutoCloseable.java delete mode 100644 code/exceptions/Switch.java delete mode 100644 code/exceptions/TryAnything.java delete mode 100644 code/exceptions/TryWithResources.java delete mode 100644 code/exceptions/TurnOffChecking.java delete mode 100644 code/exceptions/WhoCalled.java delete mode 100644 code/exceptions/WithFinally.java delete mode 100644 code/files/AddAndSubtractPaths.java delete mode 100644 code/files/Directories.java delete mode 100644 code/files/FileSystemDemo.java delete mode 100644 code/files/Find.java delete mode 100644 code/files/ListOfLines.java delete mode 100644 code/files/PartsOfPaths.java delete mode 100644 code/files/PathAnalysis.java delete mode 100644 code/files/PathInfo.java delete mode 100644 code/files/PathWatcher.java delete mode 100644 code/files/ReadLineStream.java delete mode 100644 code/files/StreamInAndOut.java delete mode 100644 code/files/TreeWatcher.java delete mode 100644 code/files/Writing.java delete mode 100644 code/functional/AnonymousClosure.java delete mode 100644 code/functional/BiConsumerPermutations.java delete mode 100644 code/functional/ClassFunctionals.java delete mode 100644 code/functional/Closure1.java delete mode 100644 code/functional/Closure2.java delete mode 100644 code/functional/Closure3.java delete mode 100644 code/functional/Closure4.java delete mode 100644 code/functional/Closure5.java delete mode 100644 code/functional/Closure6.java delete mode 100644 code/functional/Closure7.java delete mode 100644 code/functional/Closure8.java delete mode 100644 code/functional/Closure9.java delete mode 100644 code/functional/ConsumeFunction.java delete mode 100644 code/functional/CtorReference.java delete mode 100644 code/functional/CurriedIntAdd.java delete mode 100644 code/functional/Curry3Args.java delete mode 100644 code/functional/CurryingAndPartials.java delete mode 100644 code/functional/FunctionComposition.java delete mode 100644 code/functional/FunctionVariants.java delete mode 100644 code/functional/FunctionWithWrapped.java delete mode 100644 code/functional/FunctionalAnnotation.java delete mode 100644 code/functional/IntCall.java delete mode 100644 code/functional/LambdaExpressions.java delete mode 100644 code/functional/MethodConversion.java delete mode 100644 code/functional/MethodReferences.java delete mode 100644 code/functional/MultiUnbound.java delete mode 100644 code/functional/PredicateComposition.java delete mode 100644 code/functional/ProduceFunction.java delete mode 100644 code/functional/RecursiveFactorial.java delete mode 100644 code/functional/RecursiveFibonacci.java delete mode 100644 code/functional/RunnableMethodReference.java delete mode 100644 code/functional/SharedStorage.java delete mode 100644 code/functional/Strategize.java delete mode 100644 code/functional/TransformFunction.java delete mode 100644 code/functional/TriFunction.java delete mode 100644 code/functional/TriFunctionTest.java delete mode 100644 code/functional/UnboundMethodReference.java delete mode 100644 code/generics/Amphibian.java delete mode 100644 code/generics/Apply.java delete mode 100644 code/generics/ApplyFunctional.java delete mode 100644 code/generics/ApplyTest.java delete mode 100644 code/generics/ArrayMaker.java delete mode 100644 code/generics/ArrayOfGeneric.java delete mode 100644 code/generics/ArrayOfGenericReference.java delete mode 100644 code/generics/BankTeller.java delete mode 100644 code/generics/BasicBounds.java delete mode 100644 code/generics/BasicHolder.java delete mode 100644 code/generics/BasicSupplierDemo.java delete mode 100644 code/generics/ByteSet.java delete mode 100644 code/generics/CRGWithBasicHolder.java delete mode 100644 code/generics/CaptureConversion.java delete mode 100644 code/generics/CheckedList.java delete mode 100644 code/generics/ClassCasting.java delete mode 100644 code/generics/ClassTypeCapture.java delete mode 100644 code/generics/ComparablePet.java delete mode 100644 code/generics/CompilerIntelligence.java delete mode 100644 code/generics/CountedObject.java delete mode 100644 code/generics/CovariantArrays.java delete mode 100644 code/generics/CovariantReturnTypes.java delete mode 100644 code/generics/CreatorGeneric.java delete mode 100644 code/generics/CuriouslyRecurringGeneric.java delete mode 100644 code/generics/Diamond.java delete mode 100644 code/generics/DogsAndRobotMethodReferences.java delete mode 100644 code/generics/DogsAndRobots.cpp delete mode 100644 code/generics/DogsAndRobots.java delete mode 100644 code/generics/DogsAndRobots.py delete mode 100644 code/generics/DynamicProxyMixin.java delete mode 100644 code/generics/EpicBattle.java delete mode 100644 code/generics/Erased.java delete mode 100644 code/generics/ErasedTypeEquivalence.java delete mode 100644 code/generics/ErasureAndInheritance.java delete mode 100644 code/generics/FactoryConstraint.java delete mode 100644 code/generics/Fibonacci.java delete mode 100644 code/generics/FilledList.java delete mode 100644 code/generics/GenericArray.java delete mode 100644 code/generics/GenericArray2.java delete mode 100644 code/generics/GenericArrayWithTypeToken.java delete mode 100644 code/generics/GenericCast.java delete mode 100644 code/generics/GenericHolder.java delete mode 100644 code/generics/GenericHolder2.java delete mode 100644 code/generics/GenericMethods.java delete mode 100644 code/generics/GenericReading.java delete mode 100644 code/generics/GenericVarargs.java delete mode 100644 code/generics/GenericsAndCovariance.java delete mode 100644 code/generics/GenericsAndReturnTypes.java delete mode 100644 code/generics/HasF.java delete mode 100644 code/generics/HijackedInterface.java delete mode 100644 code/generics/Holder.java delete mode 100644 code/generics/Holder1.java delete mode 100644 code/generics/InheritBounds.java delete mode 100644 code/generics/InstantiateGenericType.cpp delete mode 100644 code/generics/InstantiateGenericType.java delete mode 100644 code/generics/IterableFibonacci.java delete mode 100644 code/generics/LatentReflection.java delete mode 100644 code/generics/LinkedStack.java delete mode 100644 code/generics/ListMaker.java delete mode 100644 code/generics/ListOfGenerics.java delete mode 100644 code/generics/ListOfInt.java delete mode 100644 code/generics/LostInformation.java delete mode 100644 code/generics/Manipulation.java delete mode 100644 code/generics/Manipulator2.java delete mode 100644 code/generics/Manipulator3.java delete mode 100644 code/generics/Mixins.cpp delete mode 100644 code/generics/Mixins.java delete mode 100644 code/generics/MultipleInterfaceVariants.java delete mode 100644 code/generics/NeedCasting.java delete mode 100644 code/generics/NonCovariantGenerics.java delete mode 100644 code/generics/NotSelfBounded.java delete mode 100644 code/generics/ObjectHolder.java delete mode 100644 code/generics/OrdinaryArguments.java delete mode 100644 code/generics/Performs.java delete mode 100644 code/generics/PlainGenericInheritance.java delete mode 100644 code/generics/PrimitiveGenericTest.java delete mode 100644 code/generics/RandomList.java delete mode 100644 code/generics/RestrictedComparablePets.java delete mode 100644 code/generics/ReturnGenericType.java delete mode 100644 code/generics/SelfBounding.java delete mode 100644 code/generics/SelfBoundingAndCovariantArguments.java delete mode 100644 code/generics/SelfBoundingMethods.java delete mode 100644 code/generics/Shape.java delete mode 100644 code/generics/SimpleDogsAndRobots.java delete mode 100644 code/generics/SimpleHolder.java delete mode 100644 code/generics/SimpleQueue.java delete mode 100644 code/generics/Square.java delete mode 100644 code/generics/Store.java delete mode 100644 code/generics/SuperTypeWildcards.java delete mode 100644 code/generics/Templates.cpp delete mode 100644 code/generics/ThrowGenericException.java delete mode 100644 code/generics/TupleList.java delete mode 100644 code/generics/TupleTest.java delete mode 100644 code/generics/TupleTest2.java delete mode 100644 code/generics/UnboundedWildcards1.java delete mode 100644 code/generics/UnboundedWildcards2.java delete mode 100644 code/generics/Unconstrained.java delete mode 100644 code/generics/UseList.java delete mode 100644 code/generics/UseList2.java delete mode 100644 code/generics/Vehicle.java delete mode 100644 code/generics/WatercolorSets.java delete mode 100644 code/generics/Wildcards.java delete mode 100644 code/generics/coffee/Americano.java delete mode 100644 code/generics/coffee/Breve.java delete mode 100644 code/generics/coffee/Cappuccino.java delete mode 100644 code/generics/coffee/Coffee.java delete mode 100644 code/generics/coffee/CoffeeSupplier.java delete mode 100644 code/generics/coffee/Latte.java delete mode 100644 code/generics/coffee/Mocha.java delete mode 100644 code/generics/decorator/Decoration.java delete mode 100644 code/generics/dogsandrobots.go delete mode 100644 code/generics/watercolors/Watercolors.java delete mode 100644 code/gradle.properties delete mode 100644 code/gradle/checkstyle.gradle delete mode 100644 code/gradle/findbugs.gradle delete mode 100644 code/gradle/java.gradle delete mode 100644 code/gradle/jmh.gradle delete mode 100644 code/gradle/junit-jupiter.gradle delete mode 100644 code/gradle/subprojects.gradle delete mode 100644 code/gradle/wrapper/gradle-wrapper.jar delete mode 100644 code/gradle/wrapper/gradle-wrapper.properties delete mode 100644 code/gradlew delete mode 100644 code/gradlew.bat delete mode 100644 code/hiding/Cake.java delete mode 100644 code/hiding/ChocolateChip.java delete mode 100644 code/hiding/ChocolateChip2.java delete mode 100644 code/hiding/CreatePackageAccessObject.java delete mode 100644 code/hiding/Dinner.java delete mode 100644 code/hiding/FullQualification.java delete mode 100644 code/hiding/IceCream.java delete mode 100644 code/hiding/ImportedMyClass.java delete mode 100644 code/hiding/LibTest.java delete mode 100644 code/hiding/Lunch.java delete mode 100644 code/hiding/OrganizedByAccess.java delete mode 100644 code/hiding/Pie.java delete mode 100644 code/hiding/QualifiedMyClass.java delete mode 100644 code/hiding/SingleImport.java delete mode 100644 code/hiding/cookie2/Cookie.java delete mode 100644 code/hiding/dessert/Cookie.java delete mode 100644 code/hiding/mypackage/MyClass.java delete mode 100644 code/hiding/packageaccess/PublicConstructor.java delete mode 100644 code/housekeeping/Apricot.java delete mode 100644 code/housekeeping/ArrayClassObj.java delete mode 100644 code/housekeeping/ArrayInit.java delete mode 100644 code/housekeeping/ArrayNew.java delete mode 100644 code/housekeeping/ArraysOfPrimitives.java delete mode 100644 code/housekeeping/AutoboxingVarargs.java delete mode 100644 code/housekeeping/BananaPeel.java delete mode 100644 code/housekeeping/Burrito.java delete mode 100644 code/housekeeping/Counter.java delete mode 100644 code/housekeeping/DefaultConstructor.java delete mode 100644 code/housekeeping/Demotion.java delete mode 100644 code/housekeeping/DynamicArray.java delete mode 100644 code/housekeeping/EnumOrder.java delete mode 100644 code/housekeeping/ExplicitStatic.java delete mode 100644 code/housekeeping/Flower.java delete mode 100644 code/housekeeping/InitialValues.java delete mode 100644 code/housekeeping/InitialValues2.java delete mode 100644 code/housekeeping/Leaf.java delete mode 100644 code/housekeeping/Measurement.java delete mode 100644 code/housekeeping/MethodInit.java delete mode 100644 code/housekeeping/MethodInit2.java delete mode 100644 code/housekeeping/MethodInit3.java delete mode 100644 code/housekeeping/Mugs.java delete mode 100644 code/housekeeping/NewVarArgs.java delete mode 100644 code/housekeeping/NoSynthesis.java delete mode 100644 code/housekeeping/OptionalTrailingArguments.java delete mode 100644 code/housekeeping/OrderOfInitialization.java delete mode 100644 code/housekeeping/Overloading.java delete mode 100644 code/housekeeping/OverloadingOrder.java delete mode 100644 code/housekeeping/OverloadingVarargs.java delete mode 100644 code/housekeeping/OverloadingVarargs2.java delete mode 100644 code/housekeeping/OverloadingVarargs3.java delete mode 100644 code/housekeeping/PassingThis.java delete mode 100644 code/housekeeping/PrimitiveOverloading.java delete mode 100644 code/housekeeping/SimpleConstructor.java delete mode 100644 code/housekeeping/SimpleConstructor2.java delete mode 100644 code/housekeeping/SimpleEnumUse.java delete mode 100644 code/housekeeping/Spiciness.java delete mode 100644 code/housekeeping/Spoon.java delete mode 100644 code/housekeeping/StaticInitialization.java delete mode 100644 code/housekeeping/TerminationCondition.java delete mode 100644 code/housekeeping/VarArgs.java delete mode 100644 code/housekeeping/VarargType.java delete mode 100644 code/innerclasses/AnonymousConstructor.java delete mode 100644 code/innerclasses/BigEgg.java delete mode 100644 code/innerclasses/BigEgg2.java delete mode 100644 code/innerclasses/Callbacks.java delete mode 100644 code/innerclasses/ClassInInterface.java delete mode 100644 code/innerclasses/Contents.java delete mode 100644 code/innerclasses/Destination.java delete mode 100644 code/innerclasses/DotNew.java delete mode 100644 code/innerclasses/DotThis.java delete mode 100644 code/innerclasses/GreenhouseController.java delete mode 100644 code/innerclasses/GreenhouseControls.java delete mode 100644 code/innerclasses/InheritInner.java delete mode 100644 code/innerclasses/LocalInnerClass.java delete mode 100644 code/innerclasses/MultiImplementation.java delete mode 100644 code/innerclasses/MultiNestingAccess.java delete mode 100644 code/innerclasses/Parcel1.java delete mode 100644 code/innerclasses/Parcel10.java delete mode 100644 code/innerclasses/Parcel11.java delete mode 100644 code/innerclasses/Parcel2.java delete mode 100644 code/innerclasses/Parcel3.java delete mode 100644 code/innerclasses/Parcel5.java delete mode 100644 code/innerclasses/Parcel6.java delete mode 100644 code/innerclasses/Parcel7.java delete mode 100644 code/innerclasses/Parcel7b.java delete mode 100644 code/innerclasses/Parcel8.java delete mode 100644 code/innerclasses/Parcel9.java delete mode 100644 code/innerclasses/Sequence.java delete mode 100644 code/innerclasses/TestBed.java delete mode 100644 code/innerclasses/TestParcel.java delete mode 100644 code/innerclasses/Wrapping.java delete mode 100644 code/innerclasses/controller/Controller.java delete mode 100644 code/innerclasses/controller/Event.java delete mode 100644 code/innerclasses/mui/MultiInterfaces.java delete mode 100644 code/interfaces/AbstractAccess.java delete mode 100644 code/interfaces/AbstractWithoutAbstracts.java delete mode 100644 code/interfaces/AdaptedRandomDoubles.java delete mode 100644 code/interfaces/Adventure.java delete mode 100644 code/interfaces/AnImplementation.java delete mode 100644 code/interfaces/AnInterface.java delete mode 100644 code/interfaces/Applicator.java delete mode 100644 code/interfaces/AttemptToUseBasic.java delete mode 100644 code/interfaces/Basic.java delete mode 100644 code/interfaces/Basic2.java delete mode 100644 code/interfaces/Factories.java delete mode 100644 code/interfaces/Games.java delete mode 100644 code/interfaces/HorrorShow.java delete mode 100644 code/interfaces/Implementation2.java delete mode 100644 code/interfaces/ImplementingAnInterface.java delete mode 100644 code/interfaces/Instantiable.java delete mode 100644 code/interfaces/InterfaceCollision.java delete mode 100644 code/interfaces/InterfaceWithDefault.java delete mode 100644 code/interfaces/Jim.java delete mode 100644 code/interfaces/MICollision.java delete mode 100644 code/interfaces/Machine.java delete mode 100644 code/interfaces/Months.java delete mode 100644 code/interfaces/MultipleInheritance.java delete mode 100644 code/interfaces/PureInterface.java delete mode 100644 code/interfaces/RandVals.java delete mode 100644 code/interfaces/RandomDoubles.java delete mode 100644 code/interfaces/RandomStrings.java delete mode 100644 code/interfaces/TestRandVals.java delete mode 100644 code/interfaces/filters/BandPass.java delete mode 100644 code/interfaces/filters/Filter.java delete mode 100644 code/interfaces/filters/HighPass.java delete mode 100644 code/interfaces/filters/LowPass.java delete mode 100644 code/interfaces/filters/Waveform.java delete mode 100644 code/interfaces/interfaceprocessor/Applicator.java delete mode 100644 code/interfaces/interfaceprocessor/FilterProcessor.java delete mode 100644 code/interfaces/interfaceprocessor/Processor.java delete mode 100644 code/interfaces/interfaceprocessor/StringProcessor.java delete mode 100644 code/interfaces/music4/Music4.java delete mode 100644 code/interfaces/music5/Music5.java delete mode 100644 code/interfaces/nesting/NestingInterfaces.java delete mode 100644 code/iostreams/BasicFileOutput.java delete mode 100644 code/iostreams/BufferedInputFile.java delete mode 100644 code/iostreams/FileOutputShortcut.java delete mode 100644 code/iostreams/FormattedMemoryInput.java delete mode 100644 code/iostreams/MemoryInput.java delete mode 100644 code/iostreams/StoringAndRecoveringData.java delete mode 100644 code/iostreams/TestEOF.java delete mode 100644 code/iostreams/UsingRandomAccessFile.java delete mode 100644 code/javadoc/Documentation1.java delete mode 100644 code/javadoc/Documentation2.java delete mode 100644 code/javadoc/Documentation3.java delete mode 100644 code/javadoc/HelloDateDoc.java delete mode 100644 code/lowlevel/AtomicEvenProducer.java delete mode 100644 code/lowlevel/AtomicIntegerTest.java delete mode 100644 code/lowlevel/AtomicSerialNumbers.java delete mode 100644 code/lowlevel/Atomicity.java delete mode 100644 code/lowlevel/AttemptLocking.java delete mode 100644 code/lowlevel/CaptureUncaughtException.java delete mode 100644 code/lowlevel/CircularSet.java delete mode 100644 code/lowlevel/DelayQueueDemo.java delete mode 100644 code/lowlevel/EvenChecker.java delete mode 100644 code/lowlevel/EvenProducer.java delete mode 100644 code/lowlevel/ExceptionThread.java delete mode 100644 code/lowlevel/IntGenerator.java delete mode 100644 code/lowlevel/IntTestable.java delete mode 100644 code/lowlevel/MutexEvenProducer.java delete mode 100644 code/lowlevel/NaiveExceptionHandling.java delete mode 100644 code/lowlevel/NotAtomic.java delete mode 100644 code/lowlevel/NumberOfProcessors.java delete mode 100644 code/lowlevel/PriorityBlockingQueueDemo.java delete mode 100644 code/lowlevel/ReOrdering.java delete mode 100644 code/lowlevel/SafeReturn.java delete mode 100644 code/lowlevel/SerialNumberChecker.java delete mode 100644 code/lowlevel/SerialNumberTest.java delete mode 100644 code/lowlevel/SerialNumbers.java delete mode 100644 code/lowlevel/SettingDefaultHandler.java delete mode 100644 code/lowlevel/SwallowedException.java delete mode 100644 code/lowlevel/SyncOnObject.java delete mode 100644 code/lowlevel/SynchronizedComparison.java delete mode 100644 code/lowlevel/SynchronizedEvenProducer.java delete mode 100644 code/lowlevel/SynchronizedSerialNumbers.java delete mode 100644 code/lowlevel/TestAbort.java delete mode 100644 code/lowlevel/ThreadSize.java delete mode 100644 code/lowlevel/UnsafeReturn.java delete mode 100644 code/lowlevel/WorkStealingPool.java delete mode 100644 code/newio/AvailableCharSets.java delete mode 100644 code/newio/BufferToText.java delete mode 100644 code/newio/ChannelCopy.java delete mode 100644 code/newio/Endians.java delete mode 100644 code/newio/FileLocking.java delete mode 100644 code/newio/GetChannel.java delete mode 100644 code/newio/GetData.java delete mode 100644 code/newio/IntBufferDemo.java delete mode 100644 code/newio/LargeMappedFiles.java delete mode 100644 code/newio/LockingMappedFiles.java delete mode 100644 code/newio/MappedIO.java delete mode 100644 code/newio/TransferTo.java delete mode 100644 code/newio/UsingBuffers.java delete mode 100644 code/newio/ViewBuffers.java delete mode 100644 code/objects/HelloDate.java delete mode 100644 code/objects/ShowProperties.java delete mode 100644 code/onjava/ArrayShow.java delete mode 100644 code/onjava/BasicSupplier.java delete mode 100644 code/onjava/CollectionMethodDifferences.java delete mode 100644 code/onjava/ConvertTo.java delete mode 100644 code/onjava/Count.java delete mode 100644 code/onjava/CountMap.java delete mode 100644 code/onjava/CountingIntegerList.java delete mode 100644 code/onjava/Countries.java delete mode 100644 code/onjava/Enums.java delete mode 100644 code/onjava/FillMap.java delete mode 100644 code/onjava/HTMLColors.java delete mode 100644 code/onjava/MouseClick.java delete mode 100644 code/onjava/Nap.java delete mode 100644 code/onjava/Null.java delete mode 100644 code/onjava/OSExecute.java delete mode 100644 code/onjava/OSExecuteException.java delete mode 100644 code/onjava/Operations.java delete mode 100644 code/onjava/Pair.java delete mode 100644 code/onjava/ProcessFiles.java delete mode 100644 code/onjava/Rand.java delete mode 100644 code/onjava/Range.java delete mode 100644 code/onjava/Repeat.java delete mode 100644 code/onjava/RmDir.java delete mode 100644 code/onjava/Sets.java delete mode 100644 code/onjava/Stack.java delete mode 100644 code/onjava/Suppliers.java delete mode 100644 code/onjava/TimedAbort.java delete mode 100644 code/onjava/Timer.java delete mode 100644 code/onjava/Tuple.java delete mode 100644 code/onjava/Tuple2.java delete mode 100644 code/onjava/Tuple3.java delete mode 100644 code/onjava/Tuple4.java delete mode 100644 code/onjava/Tuple5.java delete mode 100644 code/onjava/TypeCounter.java delete mode 100644 code/onjava/atunit/AtUnit.java delete mode 100644 code/onjava/atunit/ClassNameFinder.java delete mode 100644 code/onjava/atunit/Test.java delete mode 100644 code/onjava/atunit/TestObjectCleanup.java delete mode 100644 code/onjava/atunit/TestObjectCreate.java delete mode 100644 code/onjava/atunit/TestProperty.java delete mode 100644 code/operators/AllOps.java delete mode 100644 code/operators/Assignment.java delete mode 100644 code/operators/AutoInc.java delete mode 100644 code/operators/BitManipulation.java delete mode 100644 code/operators/Bool.java delete mode 100644 code/operators/Casting.java delete mode 100644 code/operators/CastingNumbers.java delete mode 100644 code/operators/EqualsMethod.java delete mode 100644 code/operators/EqualsMethod2.java delete mode 100644 code/operators/Equivalence.java delete mode 100644 code/operators/Exponents.java delete mode 100644 code/operators/Literals.java delete mode 100644 code/operators/MathOps.java delete mode 100644 code/operators/Overflow.java delete mode 100644 code/operators/PassObject.java delete mode 100644 code/operators/Precedence.java delete mode 100644 code/operators/RoundingNumbers.java delete mode 100644 code/operators/ShortCircuit.java delete mode 100644 code/operators/StringOperators.java delete mode 100644 code/operators/TernaryIfElse.java delete mode 100644 code/operators/URShift.java delete mode 100644 code/operators/Underscores.java delete mode 100644 code/patterns/BoxObserver.java delete mode 100644 code/patterns/CommandPattern.java delete mode 100644 code/patterns/Facade.java delete mode 100644 code/patterns/PaperScissorsRock.java delete mode 100644 code/patterns/ProxyDemo.java delete mode 100644 code/patterns/ShapeFactory1.java delete mode 100644 code/patterns/ShapeFactory2.java delete mode 100644 code/patterns/ShapeFactory3.java delete mode 100644 code/patterns/SingletonPattern.java delete mode 100644 code/patterns/StateDemo.java delete mode 100644 code/patterns/TemplateMethod.java delete mode 100644 code/patterns/abstractfactory/GameEnvironment.java delete mode 100644 code/patterns/adapt/Adapter.java delete mode 100644 code/patterns/chain/ChainOfResponsibility.java delete mode 100644 code/patterns/doubledispatch/Aluminum.java delete mode 100644 code/patterns/doubledispatch/Cardboard.java delete mode 100644 code/patterns/doubledispatch/DoubleDispatch.java delete mode 100644 code/patterns/doubledispatch/Glass.java delete mode 100644 code/patterns/doubledispatch/Paper.java delete mode 100644 code/patterns/doubledispatch/TypedBin.java delete mode 100644 code/patterns/doubledispatch/TypedBinMember.java delete mode 100644 code/patterns/dynatrash/DynaTrash.java delete mode 100644 code/patterns/observer/ObservedFlower.java delete mode 100644 code/patterns/recyclea/RecycleA.java delete mode 100644 code/patterns/recycleb/RecycleB.java delete mode 100644 code/patterns/recyclec/RecycleC.java delete mode 100644 code/patterns/shapes/BadShapeCreation.java delete mode 100644 code/patterns/shapes/Circle.java delete mode 100644 code/patterns/shapes/FactoryMethod.java delete mode 100644 code/patterns/shapes/FactoryTest.java delete mode 100644 code/patterns/shapes/Shape.java delete mode 100644 code/patterns/shapes/Square.java delete mode 100644 code/patterns/shapes/Triangle.java delete mode 100644 code/patterns/state/StateMachineDemo.java delete mode 100644 code/patterns/strategy/StrategyPattern.java delete mode 100644 code/patterns/strategy/StrategyPattern2.java delete mode 100644 code/patterns/trash/Aluminum.java delete mode 100644 code/patterns/trash/Cardboard.java delete mode 100644 code/patterns/trash/Fillable.java delete mode 100644 code/patterns/trash/FillableList.java delete mode 100644 code/patterns/trash/Glass.java delete mode 100644 code/patterns/trash/Paper.java delete mode 100644 code/patterns/trash/ParseTrash.java delete mode 100644 code/patterns/trash/Trash.dat delete mode 100644 code/patterns/trash/Trash.java delete mode 100644 code/patterns/trashvisitor/Aluminum.java delete mode 100644 code/patterns/trashvisitor/Cardboard.java delete mode 100644 code/patterns/trashvisitor/Glass.java delete mode 100644 code/patterns/trashvisitor/Paper.java delete mode 100644 code/patterns/trashvisitor/TrashVisitor.java delete mode 100644 code/patterns/trashvisitor/Visitable.java delete mode 100644 code/patterns/trashvisitor/Visitor.java delete mode 100644 code/patterns/visitor/BeeAndFlowers.java delete mode 100644 code/polymorphism/CovariantReturn.java delete mode 100644 code/polymorphism/FieldAccess.java delete mode 100644 code/polymorphism/Frog.java delete mode 100644 code/polymorphism/PolyConstructors.java delete mode 100644 code/polymorphism/PrivateOverride.java delete mode 100644 code/polymorphism/PrivateOverride2.java delete mode 100644 code/polymorphism/RTTI.java delete mode 100644 code/polymorphism/ReferenceCounting.java delete mode 100644 code/polymorphism/Sandwich.java delete mode 100644 code/polymorphism/Shapes.java delete mode 100644 code/polymorphism/StaticPolymorphism.java delete mode 100644 code/polymorphism/Transmogrify.java delete mode 100644 code/polymorphism/music/Instrument.java delete mode 100644 code/polymorphism/music/Music.java delete mode 100644 code/polymorphism/music/Music2.java delete mode 100644 code/polymorphism/music/Note.java delete mode 100644 code/polymorphism/music/Wind.java delete mode 100644 code/polymorphism/music3/Music3.java delete mode 100644 code/polymorphism/shape/Circle.java delete mode 100644 code/polymorphism/shape/RandomShapes.java delete mode 100644 code/polymorphism/shape/Shape.java delete mode 100644 code/polymorphism/shape/Square.java delete mode 100644 code/polymorphism/shape/Triangle.java delete mode 100644 code/references/AddingClone.java delete mode 100644 code/references/Alias1.java delete mode 100644 code/references/Alias2.java delete mode 100644 code/references/CheckCloneable.java delete mode 100644 code/references/CloneArrayList.java delete mode 100644 code/references/Compete.java delete mode 100644 code/references/CopyConstructor.java delete mode 100644 code/references/DepthReading.java delete mode 100644 code/references/HorrorFlick.java delete mode 100644 code/references/Immutable1.java delete mode 100644 code/references/Immutable2.java delete mode 100644 code/references/ImmutableInteger.java delete mode 100644 code/references/ImmutableStrings.java delete mode 100644 code/references/LocalCopy.java delete mode 100644 code/references/MutableInteger.java delete mode 100644 code/references/OceanReading.java delete mode 100644 code/references/PassReferences.java delete mode 100644 code/references/SimplerMutableInteger.java delete mode 100644 code/references/Snake.java delete mode 100644 code/references/Stringer.java delete mode 100644 code/references/TemperatureReading.java delete mode 100644 code/references/tests/DeepCopyTest.java delete mode 100644 code/reuse/Bath.java delete mode 100644 code/reuse/Beetle.java delete mode 100644 code/reuse/BlankFinal.java delete mode 100644 code/reuse/CADSystem.java delete mode 100644 code/reuse/Car.java delete mode 100644 code/reuse/Cartoon.java delete mode 100644 code/reuse/Chess.java delete mode 100644 code/reuse/DerivedSpaceShip.java delete mode 100644 code/reuse/Detergent.java delete mode 100644 code/reuse/FinalArguments.java delete mode 100644 code/reuse/FinalData.java delete mode 100644 code/reuse/FinalOverridingIllusion.java delete mode 100644 code/reuse/Hide.java delete mode 100644 code/reuse/Jurassic.java delete mode 100644 code/reuse/Lisa.java delete mode 100644 code/reuse/Orc.java delete mode 100644 code/reuse/PlaceSetting.java delete mode 100644 code/reuse/SpaceShipControls.java delete mode 100644 code/reuse/SpaceShipDelegation.java delete mode 100644 code/reuse/SprinklerSystem.java delete mode 100644 code/reuse/Wind.java delete mode 100644 code/serialization/APerson.java delete mode 100644 code/serialization/AStoreCADState.java delete mode 100644 code/serialization/Alien.java delete mode 100644 code/serialization/Blip3.java delete mode 100644 code/serialization/Blips.java delete mode 100644 code/serialization/FreezeAlien.java delete mode 100644 code/serialization/Logon.java delete mode 100644 code/serialization/MyWorld.java delete mode 100644 code/serialization/People.java delete mode 100644 code/serialization/RecoverCADState.java delete mode 100644 code/serialization/SerialCtl.java delete mode 100644 code/serialization/Worm.java delete mode 100644 code/serialization/xfiles/ThawAlien.java delete mode 100644 code/settings.gradle delete mode 100644 code/standardio/ChangeSystemOut.java delete mode 100644 code/standardio/Echo.java delete mode 100644 code/standardio/OSExecuteDemo.java delete mode 100644 code/standardio/Redirecting.java delete mode 100644 code/staticchecking/DogsAndRobots.cpp delete mode 100644 code/staticchecking/DogsAndRobots.py delete mode 100644 code/staticchecking/NoBasePetSpeak.py delete mode 100644 code/staticchecking/PetSpeak.py delete mode 100644 code/staticchecking/dogsandrobots.go delete mode 100644 code/staticchecking/dr/DogsAndRobots.java delete mode 100644 code/staticchecking/drc/DogAndRobotCollections.java delete mode 100644 code/staticchecking/latent/Latent.java delete mode 100644 code/staticchecking/petspeak.go delete mode 100644 code/staticchecking/petspeak/PetSpeak.java delete mode 100644 code/streams/ArrayStreams.java delete mode 100644 code/streams/Bubble.java delete mode 100644 code/streams/Bubbles.java delete mode 100644 code/streams/Cheese.dat delete mode 100644 code/streams/CollectionToStream.java delete mode 100644 code/streams/CreatingOptionals.java delete mode 100644 code/streams/Duplicator.java delete mode 100644 code/streams/Fibonacci.java delete mode 100644 code/streams/FileToWords.java delete mode 100644 code/streams/FileToWordsBuilder.java delete mode 100644 code/streams/FileToWordsRegexp.java delete mode 100644 code/streams/FileToWordsTest.java delete mode 100644 code/streams/FlatMap.java delete mode 100644 code/streams/ForEach.java delete mode 100644 code/streams/FunctionMap.java delete mode 100644 code/streams/FunctionMap2.java delete mode 100644 code/streams/FunctionMap3.java delete mode 100644 code/streams/Generator.java delete mode 100644 code/streams/ImperativeRandoms.java delete mode 100644 code/streams/Informational.java delete mode 100644 code/streams/LastElement.java delete mode 100644 code/streams/Looping.java delete mode 100644 code/streams/Machine2.java delete mode 100644 code/streams/MapCollector.java delete mode 100644 code/streams/Matching.java delete mode 100644 code/streams/NumericStreamInfo.java delete mode 100644 code/streams/OptionalBasics.java delete mode 100644 code/streams/OptionalFilter.java delete mode 100644 code/streams/OptionalFlatMap.java delete mode 100644 code/streams/OptionalMap.java delete mode 100644 code/streams/Optionals.java delete mode 100644 code/streams/OptionalsFromEmptyStreams.java delete mode 100644 code/streams/Peeking.java delete mode 100644 code/streams/Prime.java delete mode 100644 code/streams/RandInts.java delete mode 100644 code/streams/RandomGenerators.java delete mode 100644 code/streams/RandomWords.java delete mode 100644 code/streams/Randoms.java delete mode 100644 code/streams/Ranges.java delete mode 100644 code/streams/Reduce.java delete mode 100644 code/streams/SelectElement.java delete mode 100644 code/streams/Signal.java delete mode 100644 code/streams/SortedComparator.java delete mode 100644 code/streams/SpecialCollector.java delete mode 100644 code/streams/StreamOf.java delete mode 100644 code/streams/StreamOfOptionals.java delete mode 100644 code/streams/StreamOfRandoms.java delete mode 100644 code/streams/StreamOfStreams.java delete mode 100644 code/streams/TreeSetOfWords.java delete mode 100644 code/strings/ArrayListDisplay.java delete mode 100644 code/strings/BetterRead.java delete mode 100644 code/strings/Concatenation.java delete mode 100644 code/strings/Conversion.java delete mode 100644 code/strings/DatabaseException.java delete mode 100644 code/strings/Finding.java delete mode 100644 code/strings/Groups.java delete mode 100644 code/strings/Hex.java delete mode 100644 code/strings/Immutable.java delete mode 100644 code/strings/InfiniteRecursion.java delete mode 100644 code/strings/IntegerMatch.java delete mode 100644 code/strings/JGrep.java delete mode 100644 code/strings/ReFlags.java delete mode 100644 code/strings/ReceiptBuilder.java delete mode 100644 code/strings/Replacing.java delete mode 100644 code/strings/ReplacingStringTokenizer.java delete mode 100644 code/strings/Resetting.java delete mode 100644 code/strings/Rudolph.java delete mode 100644 code/strings/ScannerDelimiter.java delete mode 100644 code/strings/SimpleFormat.java delete mode 100644 code/strings/SimpleRead.java delete mode 100644 code/strings/SplitDemo.java delete mode 100644 code/strings/Splitting.java delete mode 100644 code/strings/StartEnd.java delete mode 100644 code/strings/TestRegularExpression.java delete mode 100644 code/strings/TheReplacements.java delete mode 100644 code/strings/ThreatAnalyzer.java delete mode 100644 code/strings/Turtle.java delete mode 100644 code/strings/UsingStringBuilder.java delete mode 100644 code/strings/WhitherStringBuilder.java delete mode 100644 code/typeinfo/AnonymousImplementation.java delete mode 100644 code/typeinfo/BoundedClassReferences.java delete mode 100644 code/typeinfo/ClassCasts.java delete mode 100644 code/typeinfo/ClassInitialization.java delete mode 100644 code/typeinfo/DynamicSupplier.java delete mode 100644 code/typeinfo/FamilyVsExactType.java delete mode 100644 code/typeinfo/GenericClassReferences.java delete mode 100644 code/typeinfo/HiddenImplementation.java delete mode 100644 code/typeinfo/InnerImplementation.java delete mode 100644 code/typeinfo/InterfaceViolation.java delete mode 100644 code/typeinfo/ModifyingPrivateFields.java delete mode 100644 code/typeinfo/NullRobot.java delete mode 100644 code/typeinfo/Operation.java delete mode 100644 code/typeinfo/Person.java delete mode 100644 code/typeinfo/PetCount.java delete mode 100644 code/typeinfo/PetCount2.java delete mode 100644 code/typeinfo/PetCount3.java delete mode 100644 code/typeinfo/PetCount4.java delete mode 100644 code/typeinfo/Position.java delete mode 100644 code/typeinfo/RegisteredFactories.java delete mode 100644 code/typeinfo/Robot.java delete mode 100644 code/typeinfo/SelectingMethods.java delete mode 100644 code/typeinfo/Shapes.java delete mode 100644 code/typeinfo/ShowMethods.java delete mode 100644 code/typeinfo/SimpleDynamicProxy.java delete mode 100644 code/typeinfo/SimpleProxyDemo.java delete mode 100644 code/typeinfo/SnowRemovalRobot.java delete mode 100644 code/typeinfo/Staff.java delete mode 100644 code/typeinfo/SweetShop.java delete mode 100644 code/typeinfo/WildcardClassReferences.java delete mode 100644 code/typeinfo/interfacea/A.java delete mode 100644 code/typeinfo/packageaccess/HiddenC.java delete mode 100644 code/typeinfo/pets/Cat.java delete mode 100644 code/typeinfo/pets/Cymric.java delete mode 100644 code/typeinfo/pets/Dog.java delete mode 100644 code/typeinfo/pets/EgyptianMau.java delete mode 100644 code/typeinfo/pets/ForNameCreator.java delete mode 100644 code/typeinfo/pets/Hamster.java delete mode 100644 code/typeinfo/pets/Individual.java delete mode 100644 code/typeinfo/pets/LiteralPetCreator.java delete mode 100644 code/typeinfo/pets/Manx.java delete mode 100644 code/typeinfo/pets/Mouse.java delete mode 100644 code/typeinfo/pets/Mutt.java delete mode 100644 code/typeinfo/pets/Person.java delete mode 100644 code/typeinfo/pets/Pet.java delete mode 100644 code/typeinfo/pets/PetCreator.java delete mode 100644 code/typeinfo/pets/Pets.java delete mode 100644 code/typeinfo/pets/Pug.java delete mode 100644 code/typeinfo/pets/Rat.java delete mode 100644 code/typeinfo/pets/Rodent.java delete mode 100644 code/typeinfo/toys/GenericToyTest.java delete mode 100644 code/typeinfo/toys/ToyTest.java delete mode 100644 code/validating/Assert1.java delete mode 100644 code/validating/Assert2.java delete mode 100644 code/validating/BadMicroBenchmark.java delete mode 100644 code/validating/BadMicroBenchmark2.java delete mode 100644 code/validating/CircularQueue.java delete mode 100644 code/validating/CircularQueueException.java delete mode 100644 code/validating/CountedList.java delete mode 100644 code/validating/GuavaAssertions.java delete mode 100644 code/validating/GuavaPreconditions.java delete mode 100644 code/validating/Inverter1.java delete mode 100644 code/validating/Inverter2.java delete mode 100644 code/validating/Inverter3.java delete mode 100644 code/validating/Inverter4.java delete mode 100644 code/validating/LoaderAssertions.java delete mode 100644 code/validating/NonNullConstruction.java delete mode 100644 code/validating/SLF4JLevels.java delete mode 100644 code/validating/SLF4JLogging.java delete mode 100644 code/validating/SimpleDebugging.java delete mode 100644 code/validating/StringInverter.java delete mode 100644 code/validating/jmh/JMH1.java delete mode 100644 code/validating/jmh/JMH2.java delete mode 100644 code/validating/jmh/JMH3.java delete mode 100644 code/validating/logback.xml delete mode 100644 code/validating/tests/CircularQueueTest.java delete mode 100644 code/validating/tests/CountedListTest.java delete mode 100644 code/validating/tests/DynamicStringInverterTests.java delete mode 100644 code/validating/tests/StringInverterTests.java diff --git a/code/.gitattributes b/code/.gitattributes deleted file mode 100644 index bdb0cabc..00000000 --- a/code/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/code/.gitignore b/code/.gitignore deleted file mode 100644 index 48292956..00000000 --- a/code/.gitignore +++ /dev/null @@ -1,111 +0,0 @@ -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -*.class -*output.txt -Generated.txt -*-control.txt -*-results.txt -*-out.txt -OutputErrors.txt -report.txt -failures -People.xml -annotations/Test0.txt -annotations/Test1.txt -annotations/Test2.txt -io/*.out -io/*.txt -io/*.dat -io/*.tmp -io/test.zip -io/test.gz -io/X.file -*.pyc - -*.out -*.err -/files/bytes.dat -/files/test/ -/exceptions/Results.txt -/files/Cheese.txt -/files/StreamInAndOut.txt - -.gradle -/*.iml -/.idea/ - -/serialization/Blip3.serialized -/serialization/Blips.serialized - -build/ -buildSrc/ - -/compression/test.gz -/compression/test.zip -/iostreams/BasicFileOutput.dat -/iostreams/Data.txt -/iostreams/FileOutputShortcut.dat -/iostreams/rtest.dat -/logging/LogToFile.xml -/logging/LogToFile2.txt -/logging/MultipleHandlers.xml -/logging/MultipleHandlers2.xml -/logging/java0.log -/logging/java1.log -/logging/java2.log -/newio/TransferTo.txt -/newio/data2.txt -/newio/file.txt -/newio/test.dat -/newio/test.txt -/serialization/CADState.dat -/serialization/worm.dat -/serialization/Logon.dat -/serialization/X.file -/standardio/Redirecting.txt -/threads/PSP2.txt -/threads/primes.txt -_* -config.py diff --git a/code/.travisXX.yml b/code/.travisXX.yml deleted file mode 100644 index 54fee659..00000000 --- a/code/.travisXX.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: java -jdk: - - oraclejdk11 -install: true -script: - - ./gradlew --no-daemon --stacktrace run -# - ./gradlew --parallel --stacktrace run -# - ./gradlew --parallel --stacktrace :validating:jmh diff --git a/code/CI.txt b/code/CI.txt deleted file mode 100644 index 524ee206..00000000 --- a/code/CI.txt +++ /dev/null @@ -1,5 +0,0 @@ -Links formerly in the README. Both of these mysteriously started breaking. - -[![](https://travis-ci.org/BruceEckel/OnJava8-Examples.svg?branch=master)](https://travis-ci.org/BruceEckel/OnJava8-Examples) - -[![](https://ci.appveyor.com/api/projects/status/github/BruceEckel/OnJava8-Examples)](https://ci.appveyor.com/project/BruceEckel/onjava-examples) diff --git a/code/Copyright.txt b/code/Copyright.txt deleted file mode 100644 index f0d35035..00000000 --- a/code/Copyright.txt +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright.txt -This computer source code is Copyright 2020 MindView LLC. -All Rights Reserved. - -Permission to use, copy, modify, and distribute this -computer source code (Source Code) and its documentation -without fee and without a written agreement for the -purposes set forth below is hereby granted, provided that -the above copyright notice, this paragraph and the -following five numbered paragraphs appear in all copies. - -1. Permission is granted to compile the Source Code and to -include the compiled code, in executable format only, in -personal and commercial software programs. - -2. Permission is granted to use the Source Code without -modification in classroom situations, including in -presentation materials, provided that the book "On -Java 8" is cited as the origin. - -3. Permission to incorporate the Source Code into printed -media may be obtained by contacting: - -MindView LLC, PO Box 969, Crested Butte, CO 81224 -MindViewInc@gmail.com - -4. The Source Code and documentation are copyrighted by -MindView LLC. The Source code is provided without express -or implied warranty of any kind, including any implied -warranty of merchantability, fitness for a particular -purpose or non-infringement. MindView LLC does not -warrant that the operation of any program that includes the -Source Code will be uninterrupted or error-free. MindView -LLC makes no representation about the suitability of the -Source Code or of any software that includes the Source -Code for any purpose. The entire risk as to the quality -and performance of any program that includes the Source -Code is with the user of the Source Code. The user -understands that the Source Code was developed for research -and instructional purposes and is advised not to rely -exclusively for any reason on the Source Code or any -program that includes the Source Code. Should the Source -Code or any resulting software prove defective, the user -assumes the cost of all necessary servicing, repair, or -correction. - -5. IN NO EVENT SHALL MINDVIEW LLC, OR ITS PUBLISHER BE -LIABLE TO ANY PARTY UNDER ANY LEGAL THEORY FOR DIRECT, -INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, -INCLUDING LOST PROFITS, BUSINESS INTERRUPTION, LOSS OF -BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS, OR FOR -PERSONAL INJURIES, ARISING OUT OF THE USE OF THIS SOURCE -CODE AND ITS DOCUMENTATION, OR ARISING OUT OF THE INABILITY -TO USE ANY RESULTING PROGRAM, EVEN IF MINDVIEW LLC, OR -ITS PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. MINDVIEW LLC SPECIFICALLY DISCLAIMS ANY -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE SOURCE CODE AND DOCUMENTATION PROVIDED -HEREUNDER IS ON AN "AS IS" BASIS, WITHOUT ANY ACCOMPANYING -SERVICES FROM MINDVIEW LLC, AND MINDVIEW LLC HAS NO -OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, -ENHANCEMENTS, OR MODIFICATIONS. - -Please note that MindView LLC maintains a Web site which -is the sole distribution point for electronic copies of the -Source Code, https://github.com/BruceEckel/OnJava8-examples, -where it is freely available under the terms stated above. - -If you think you've found an error in the Source Code, -please submit a correction at: -https://github.com/BruceEckel/OnJava8-examples/issues diff --git a/code/README.md b/code/README.md deleted file mode 100644 index 985dbbe4..00000000 --- a/code/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Example Source Code for the Book "On Java 8" by Bruce Eckel - -Download release from [here](https://github.com/BruceEckel/OnJava8-Examples/releases/tag/v1.0). - -To compile and run these programs, you only need JDK 8 installed. -Invoking `gradlew` will automatically download and install Gradle. -Gradle will also install all additional libraries necessary to compile -and run the Java examples in the book. - -To compile and run everything, the command is: - -`gradlew run` - -If you are on a Unix/Linux based system, you must select the local directory for all commands, for example: - -`./gradlew run` - -To only compile everything, the command is: - -`gradlew compileJava` - -To compile only a single chapter (including dependencies), use for example: - -`gradlew :strings:compileJava` - -To run only a single chapter, say: - -`gradlew :strings:run` - -Gradle can also be used to run a single program. Here, we run the **ReplacingStringTokenizer.java** -program in the **strings** chapter subdirectory: - -`gradlew :strings:ReplacingStringTokenizer` - -However, if the file name is unique throughout the book (the majority are), you can just give the -program name, like this: - -`gradlew ReplacingStringTokenizer` - -Note that all commands are run from the base directory where the example code is installed, and where you find the -`gradlew` script. - -You can learn about other options by just typing `gradlew` with no arguments. diff --git a/code/annotations/AUComposition.java b/code/annotations/AUComposition.java deleted file mode 100644 index ee43e88d..00000000 --- a/code/annotations/AUComposition.java +++ /dev/null @@ -1,30 +0,0 @@ -// annotations/AUComposition.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating non-embedded tests -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/AUComposition.class} -package annotations; -import onjava.atunit.*; -import onjava.*; - -public class AUComposition { - AtUnitExample1 testObject = new AtUnitExample1(); - @Test - boolean tMethodOne() { - return testObject.methodOne() - .equals("This is methodOne"); - } - @Test - boolean tMethodTwo() { - return testObject.methodTwo() == 2; - } -} -/* Output: -annotations.AUComposition - . tMethodTwo This is methodTwo - - . tMethodOne -OK (2 tests) -*/ diff --git a/code/annotations/AUExternalTest.java b/code/annotations/AUExternalTest.java deleted file mode 100644 index cce5c429..00000000 --- a/code/annotations/AUExternalTest.java +++ /dev/null @@ -1,29 +0,0 @@ -// annotations/AUExternalTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating non-embedded tests -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/AUExternalTest.class} -package annotations; -import onjava.atunit.*; -import onjava.*; - -public class -AUExternalTest extends AtUnitExample1 { - @Test - boolean tMethodOne() { - return methodOne().equals("This is methodOne"); - } - @Test - boolean tMethodTwo() { - return methodTwo() == 2; - } -} -/* Output: -annotations.AUExternalTest - . tMethodOne - . tMethodTwo This is methodTwo - -OK (2 tests) -*/ diff --git a/code/annotations/AtUnitExample1.java b/code/annotations/AtUnitExample1.java deleted file mode 100644 index 3b1f6fec..00000000 --- a/code/annotations/AtUnitExample1.java +++ /dev/null @@ -1,48 +0,0 @@ -// annotations/AtUnitExample1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/AtUnitExample1.class} -package annotations; -import onjava.atunit.*; -import onjava.*; - -public class AtUnitExample1 { - public String methodOne() { - return "This is methodOne"; - } - public int methodTwo() { - System.out.println("This is methodTwo"); - return 2; - } - @Test - boolean methodOneTest() { - return methodOne().equals("This is methodOne"); - } - @Test - boolean m2() { return methodTwo() == 2; } - @Test - private boolean m3() { return true; } - // Shows output for failure: - @Test - boolean failureTest() { return false; } - @Test - boolean anotherDisappointment() { - return false; - } -} -/* Output: -annotations.AtUnitExample1 - . m3 - . methodOneTest - . m2 This is methodTwo - - . failureTest (failed) - . anotherDisappointment (failed) -(5 tests) - ->>> 2 FAILURES <<< - annotations.AtUnitExample1: failureTest - annotations.AtUnitExample1: anotherDisappointment -*/ diff --git a/code/annotations/AtUnitExample2.java b/code/annotations/AtUnitExample2.java deleted file mode 100644 index bf3f1d5c..00000000 --- a/code/annotations/AtUnitExample2.java +++ /dev/null @@ -1,57 +0,0 @@ -// annotations/AtUnitExample2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Assertions and exceptions can be used in @Tests -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/AtUnitExample2.class} -package annotations; -import java.io.*; -import onjava.atunit.*; -import onjava.*; - -public class AtUnitExample2 { - public String methodOne() { - return "This is methodOne"; - } - public int methodTwo() { - System.out.println("This is methodTwo"); - return 2; - } - @Test - void assertExample() { - assert methodOne().equals("This is methodOne"); - } - @Test - void assertFailureExample() { - assert 1 == 2: "What a surprise!"; - } - @Test - void exceptionExample() throws IOException { - try(FileInputStream fis = - new FileInputStream("nofile.txt")) {} // Throws - } - @Test - boolean assertAndReturn() { - // Assertion with message: - assert methodTwo() == 2: "methodTwo must equal 2"; - return methodOne().equals("This is methodOne"); - } -} -/* Output: -annotations.AtUnitExample2 - . exceptionExample java.io.FileNotFoundException: -nofile.txt (The system cannot find the file specified) -(failed) - . assertExample - . assertAndReturn This is methodTwo - - . assertFailureExample java.lang.AssertionError: What -a surprise! -(failed) -(4 tests) - ->>> 2 FAILURES <<< - annotations.AtUnitExample2: exceptionExample - annotations.AtUnitExample2: assertFailureExample -*/ diff --git a/code/annotations/AtUnitExample3.java b/code/annotations/AtUnitExample3.java deleted file mode 100644 index 02092591..00000000 --- a/code/annotations/AtUnitExample3.java +++ /dev/null @@ -1,42 +0,0 @@ -// annotations/AtUnitExample3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/AtUnitExample3.class} -package annotations; -import onjava.atunit.*; -import onjava.*; - -public class AtUnitExample3 { - private int n; - public AtUnitExample3(int n) { this.n = n; } - public int getN() { return n; } - public String methodOne() { - return "This is methodOne"; - } - public int methodTwo() { - System.out.println("This is methodTwo"); - return 2; - } - @TestObjectCreate - static AtUnitExample3 create() { - return new AtUnitExample3(47); - } - @Test - boolean initialization() { return n == 47; } - @Test - boolean methodOneTest() { - return methodOne().equals("This is methodOne"); - } - @Test - boolean m2() { return methodTwo() == 2; } -} -/* Output: -annotations.AtUnitExample3 - . initialization - . m2 This is methodTwo - - . methodOneTest -OK (3 tests) -*/ diff --git a/code/annotations/AtUnitExample4.java b/code/annotations/AtUnitExample4.java deleted file mode 100644 index 6b644b17..00000000 --- a/code/annotations/AtUnitExample4.java +++ /dev/null @@ -1,83 +0,0 @@ -// annotations/AtUnitExample4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/AtUnitExample4.class} -// {VisuallyInspectOutput} -package annotations; -import java.util.*; -import onjava.atunit.*; -import onjava.*; - -public class AtUnitExample4 { - static String theory = "All brontosauruses " + - "are thin at one end, much MUCH thicker in the " + - "middle, and then thin again at the far end."; - private String word; - private Random rand = new Random(); // Time-based seed - public AtUnitExample4(String word) { - this.word = word; - } - public String getWord() { return word; } - public String scrambleWord() { - List chars = Arrays.asList( - ConvertTo.boxed(word.toCharArray())); - Collections.shuffle(chars, rand); - StringBuilder result = new StringBuilder(); - for(char ch : chars) - result.append(ch); - return result.toString(); - } - @TestProperty - static List input = - Arrays.asList(theory.split(" ")); - @TestProperty - static Iterator words = input.iterator(); - @TestObjectCreate - static AtUnitExample4 create() { - if(words.hasNext()) - return new AtUnitExample4(words.next()); - else - return null; - } - @Test - boolean words() { - System.out.println("'" + getWord() + "'"); - return getWord().equals("are"); - } - @Test - boolean scramble1() { - // Use specific seed to get verifiable results: - rand = new Random(47); - System.out.println("'" + getWord() + "'"); - String scrambled = scrambleWord(); - System.out.println(scrambled); - return scrambled.equals("lAl"); - } - @Test - boolean scramble2() { - rand = new Random(74); - System.out.println("'" + getWord() + "'"); - String scrambled = scrambleWord(); - System.out.println(scrambled); - return scrambled.equals("tsaeborornussu"); - } -} -/* Output: -annotations.AtUnitExample4 - . words 'All' -(failed) - . scramble1 'brontosauruses' -ntsaueorosurbs -(failed) - . scramble2 'are' -are -(failed) -(3 tests) - ->>> 3 FAILURES <<< - annotations.AtUnitExample4: words - annotations.AtUnitExample4: scramble1 - annotations.AtUnitExample4: scramble2 -*/ diff --git a/code/annotations/AtUnitExample5.java b/code/annotations/AtUnitExample5.java deleted file mode 100644 index d7cf95df..00000000 --- a/code/annotations/AtUnitExample5.java +++ /dev/null @@ -1,63 +0,0 @@ -// annotations/AtUnitExample5.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/AtUnitExample5.class} -package annotations; -import java.io.*; -import onjava.atunit.*; -import onjava.*; - -public class AtUnitExample5 { - private String text; - public AtUnitExample5(String text) { - this.text = text; - } - @Override - public String toString() { return text; } - @TestProperty - static PrintWriter output; - @TestProperty - static int counter; - @TestObjectCreate - static AtUnitExample5 create() { - String id = Integer.toString(counter++); - try { - output = new PrintWriter("Test" + id + ".txt"); - } catch(IOException e) { - throw new RuntimeException(e); - } - return new AtUnitExample5(id); - } - @TestObjectCleanup - static void cleanup(AtUnitExample5 tobj) { - System.out.println("Running cleanup"); - output.close(); - } - @Test - boolean test1() { - output.print("test1"); - return true; - } - @Test - boolean test2() { - output.print("test2"); - return true; - } - @Test - boolean test3() { - output.print("test3"); - return true; - } -} -/* Output: -annotations.AtUnitExample5 - . test1 -Running cleanup - . test3 -Running cleanup - . test2 -Running cleanup -OK (3 tests) -*/ diff --git a/code/annotations/DemoProcessFiles.java b/code/annotations/DemoProcessFiles.java deleted file mode 100644 index 6e250537..00000000 --- a/code/annotations/DemoProcessFiles.java +++ /dev/null @@ -1,43 +0,0 @@ -// annotations/DemoProcessFiles.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.ProcessFiles; - -public class DemoProcessFiles { - public static void main(String[] args) { - new ProcessFiles(file -> System.out.println(file), - "java").start(args); - } -} -/* Output: -.\AtUnitExample1.java -.\AtUnitExample2.java -.\AtUnitExample3.java -.\AtUnitExample4.java -.\AtUnitExample5.java -.\AUComposition.java -.\AUExternalTest.java -.\database\Constraints.java -.\database\DBTable.java -.\database\Member.java -.\database\SQLInteger.java -.\database\SQLString.java -.\database\TableCreator.java -.\database\Uniqueness.java -.\DemoProcessFiles.java -.\HashSetTest.java -.\ifx\ExtractInterface.java -.\ifx\IfaceExtractorProcessor.java -.\ifx\Multiplier.java -.\PasswordUtils.java -.\simplest\Simple.java -.\simplest\SimpleProcessor.java -.\simplest\SimpleTest.java -.\SimulatingNull.java -.\StackL.java -.\StackLStringTst.java -.\Testable.java -.\UseCase.java -.\UseCaseTracker.java -*/ diff --git a/code/annotations/HashSetTest.java b/code/annotations/HashSetTest.java deleted file mode 100644 index 8dfa8a9c..00000000 --- a/code/annotations/HashSetTest.java +++ /dev/null @@ -1,36 +0,0 @@ -// annotations/HashSetTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/HashSetTest.class} -package annotations; -import java.util.*; -import onjava.atunit.*; -import onjava.*; - -public class HashSetTest { - HashSet testObject = new HashSet<>(); - @Test - void initialization() { - assert testObject.isEmpty(); - } - @Test - void tContains() { - testObject.add("one"); - assert testObject.contains("one"); - } - @Test - void tRemove() { - testObject.add("one"); - testObject.remove("one"); - assert testObject.isEmpty(); - } -} -/* Output: -annotations.HashSetTest - . initialization - . tRemove - . tContains -OK (3 tests) -*/ diff --git a/code/annotations/PasswordUtils.java b/code/annotations/PasswordUtils.java deleted file mode 100644 index 74a6df78..00000000 --- a/code/annotations/PasswordUtils.java +++ /dev/null @@ -1,24 +0,0 @@ -// annotations/PasswordUtils.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class PasswordUtils { - @UseCase(id = 47, description = - "Passwords must contain at least one numeric") - public boolean validatePassword(String passwd) { - return (passwd.matches("\\w*\\d\\w*")); - } - @UseCase(id = 48) - public String encryptPassword(String passwd) { - return new StringBuilder(passwd) - .reverse().toString(); - } - @UseCase(id = 49, description = - "New passwords can't equal previously used ones") - public boolean checkForNewPassword( - List prevPasswords, String passwd) { - return !prevPasswords.contains(passwd); - } -} diff --git a/code/annotations/SimulatingNull.java b/code/annotations/SimulatingNull.java deleted file mode 100644 index 8166802b..00000000 --- a/code/annotations/SimulatingNull.java +++ /dev/null @@ -1,12 +0,0 @@ -// annotations/SimulatingNull.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.annotation.*; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface SimulatingNull { - int id() default -1; - String description() default ""; -} diff --git a/code/annotations/StackL.java b/code/annotations/StackL.java deleted file mode 100644 index 6ff806af..00000000 --- a/code/annotations/StackL.java +++ /dev/null @@ -1,14 +0,0 @@ -// annotations/StackL.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A stack built on a LinkedList -package annotations; -import java.util.*; - -public class StackL { - private LinkedList list = new LinkedList<>(); - public void push(T v) { list.addFirst(v); } - public T top() { return list.getFirst(); } - public T pop() { return list.removeFirst(); } -} diff --git a/code/annotations/StackLStringTst.java b/code/annotations/StackLStringTst.java deleted file mode 100644 index 49aef9b7..00000000 --- a/code/annotations/StackLStringTst.java +++ /dev/null @@ -1,42 +0,0 @@ -// annotations/StackLStringTst.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Applying @Unit to generics -// {java onjava.atunit.AtUnit -// build/classes/java/main/annotations/StackLStringTst.class} -package annotations; -import onjava.atunit.*; -import onjava.*; - -public class -StackLStringTst extends StackL { - @Test - void tPush() { - push("one"); - assert top().equals("one"); - push("two"); - assert top().equals("two"); - } - @Test - void tPop() { - push("one"); - push("two"); - assert pop().equals("two"); - assert pop().equals("one"); - } - @Test - void tTop() { - push("A"); - push("B"); - assert top().equals("B"); - assert top().equals("B"); - } -} -/* Output: -annotations.StackLStringTst - . tTop - . tPush - . tPop -OK (3 tests) -*/ diff --git a/code/annotations/Testable.java b/code/annotations/Testable.java deleted file mode 100644 index bc48f416..00000000 --- a/code/annotations/Testable.java +++ /dev/null @@ -1,14 +0,0 @@ -// annotations/Testable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package annotations; -import onjava.atunit.*; - -public class Testable { - public void execute() { - System.out.println("Executing.."); - } - @Test - void testExecute() { execute(); } -} diff --git a/code/annotations/UseCase.java b/code/annotations/UseCase.java deleted file mode 100644 index dfce3149..00000000 --- a/code/annotations/UseCase.java +++ /dev/null @@ -1,12 +0,0 @@ -// annotations/UseCase.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.annotation.*; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface UseCase { - int id(); - String description() default "no description"; -} diff --git a/code/annotations/UseCaseTracker.java b/code/annotations/UseCaseTracker.java deleted file mode 100644 index 5489b762..00000000 --- a/code/annotations/UseCaseTracker.java +++ /dev/null @@ -1,37 +0,0 @@ -// annotations/UseCaseTracker.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.lang.reflect.*; - -public class UseCaseTracker { - public static void - trackUseCases(List useCases, Class cl) { - for(Method m : cl.getDeclaredMethods()) { - UseCase uc = m.getAnnotation(UseCase.class); - if(uc != null) { - System.out.println("Found Use Case " + - uc.id() + "\n " + uc.description()); - useCases.remove(Integer.valueOf(uc.id())); - } - } - useCases.forEach(i -> - System.out.println("Missing use case " + i)); - } - public static void main(String[] args) { - List useCases = IntStream.range(47, 51) - .boxed().collect(Collectors.toList()); - trackUseCases(useCases, PasswordUtils.class); - } -} -/* Output: -Found Use Case 48 - no description -Found Use Case 47 - Passwords must contain at least one numeric -Found Use Case 49 - New passwords can't equal previously used ones -Missing use case 50 -*/ diff --git a/code/annotations/database/Constraints.java b/code/annotations/database/Constraints.java deleted file mode 100644 index 4e4e40fc..00000000 --- a/code/annotations/database/Constraints.java +++ /dev/null @@ -1,14 +0,0 @@ -// annotations/database/Constraints.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package annotations.database; -import java.lang.annotation.*; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Constraints { - boolean primaryKey() default false; - boolean allowNull() default true; - boolean unique() default false; -} diff --git a/code/annotations/database/DBTable.java b/code/annotations/database/DBTable.java deleted file mode 100644 index 9aa5562f..00000000 --- a/code/annotations/database/DBTable.java +++ /dev/null @@ -1,12 +0,0 @@ -// annotations/database/DBTable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package annotations.database; -import java.lang.annotation.*; - -@Target(ElementType.TYPE) // Applies to classes only -@Retention(RetentionPolicy.RUNTIME) -public @interface DBTable { - String name() default ""; -} diff --git a/code/annotations/database/Member.java b/code/annotations/database/Member.java deleted file mode 100644 index d722a3b1..00000000 --- a/code/annotations/database/Member.java +++ /dev/null @@ -1,22 +0,0 @@ -// annotations/database/Member.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package annotations.database; - -@DBTable(name = "MEMBER") -public class Member { - @SQLString(30) String firstName; - @SQLString(50) String lastName; - @SQLInteger Integer age; - @SQLString(value = 30, - constraints = @Constraints(primaryKey = true)) - String reference; - static int memberCount; - public String getReference() { return reference; } - public String getFirstName() { return firstName; } - public String getLastName() { return lastName; } - @Override - public String toString() { return reference; } - public Integer getAge() { return age; } -} diff --git a/code/annotations/database/SQLInteger.java b/code/annotations/database/SQLInteger.java deleted file mode 100644 index 635a907c..00000000 --- a/code/annotations/database/SQLInteger.java +++ /dev/null @@ -1,13 +0,0 @@ -// annotations/database/SQLInteger.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package annotations.database; -import java.lang.annotation.*; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface SQLInteger { - String name() default ""; - Constraints constraints() default @Constraints; -} diff --git a/code/annotations/database/SQLString.java b/code/annotations/database/SQLString.java deleted file mode 100644 index dac9919f..00000000 --- a/code/annotations/database/SQLString.java +++ /dev/null @@ -1,14 +0,0 @@ -// annotations/database/SQLString.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package annotations.database; -import java.lang.annotation.*; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface SQLString { - int value() default 0; - String name() default ""; - Constraints constraints() default @Constraints; -} diff --git a/code/annotations/database/TableCreator.java b/code/annotations/database/TableCreator.java deleted file mode 100644 index 53322fc7..00000000 --- a/code/annotations/database/TableCreator.java +++ /dev/null @@ -1,106 +0,0 @@ -// annotations/database/TableCreator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Reflection-based annotation processor -// {java annotations.database.TableCreator -// annotations.database.Member} -package annotations.database; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; - -public class TableCreator { - public static void - main(String[] args) throws Exception { - if(args.length < 1) { - System.out.println( - "arguments: annotated classes"); - System.exit(0); - } - for(String className : args) { - Class cl = Class.forName(className); - DBTable dbTable = cl.getAnnotation(DBTable.class); - if(dbTable == null) { - System.out.println( - "No DBTable annotations in class " + - className); - continue; - } - String tableName = dbTable.name(); - // If the name is empty, use the Class name: - if(tableName.length() < 1) - tableName = cl.getName().toUpperCase(); - List columnDefs = new ArrayList<>(); - for(Field field : cl.getDeclaredFields()) { - String columnName = null; - Annotation[] anns = - field.getDeclaredAnnotations(); - if(anns.length < 1) - continue; // Not a db table column - if(anns[0] instanceof SQLInteger) { - SQLInteger sInt = (SQLInteger) anns[0]; - // Use field name if name not specified - if(sInt.name().length() < 1) - columnName = field.getName().toUpperCase(); - else - columnName = sInt.name(); - columnDefs.add(columnName + " INT" + - getConstraints(sInt.constraints())); - } - if(anns[0] instanceof SQLString) { - SQLString sString = (SQLString) anns[0]; - // Use field name if name not specified. - if(sString.name().length() < 1) - columnName = field.getName().toUpperCase(); - else - columnName = sString.name(); - columnDefs.add(columnName + " VARCHAR(" + - sString.value() + ")" + - getConstraints(sString.constraints())); - } - StringBuilder createCommand = new StringBuilder( - "CREATE TABLE " + tableName + "("); - for(String columnDef : columnDefs) - createCommand.append( - "\n " + columnDef + ","); - // Remove trailing comma - String tableCreate = createCommand.substring( - 0, createCommand.length() - 1) + ");"; - System.out.println("Table Creation SQL for " + - className + " is:\n" + tableCreate); - } - } - } - private static - String getConstraints(Constraints con) { - String constraints = ""; - if(!con.allowNull()) - constraints += " NOT NULL"; - if(con.primaryKey()) - constraints += " PRIMARY KEY"; - if(con.unique()) - constraints += " UNIQUE"; - return constraints; - } -} -/* Output: -Table Creation SQL for annotations.database.Member is: -CREATE TABLE MEMBER( - FIRSTNAME VARCHAR(30)); -Table Creation SQL for annotations.database.Member is: -CREATE TABLE MEMBER( - FIRSTNAME VARCHAR(30), - LASTNAME VARCHAR(50)); -Table Creation SQL for annotations.database.Member is: -CREATE TABLE MEMBER( - FIRSTNAME VARCHAR(30), - LASTNAME VARCHAR(50), - AGE INT); -Table Creation SQL for annotations.database.Member is: -CREATE TABLE MEMBER( - FIRSTNAME VARCHAR(30), - LASTNAME VARCHAR(50), - AGE INT, - REFERENCE VARCHAR(30) PRIMARY KEY); -*/ diff --git a/code/annotations/database/Uniqueness.java b/code/annotations/database/Uniqueness.java deleted file mode 100644 index 1aa1a36c..00000000 --- a/code/annotations/database/Uniqueness.java +++ /dev/null @@ -1,11 +0,0 @@ -// annotations/database/Uniqueness.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Sample of nested annotations -package annotations.database; - -public @interface Uniqueness { - Constraints constraints() - default @Constraints(unique = true); -} diff --git a/code/annotations/ifx/ExtractInterface.java b/code/annotations/ifx/ExtractInterface.java deleted file mode 100644 index 70a94bf5..00000000 --- a/code/annotations/ifx/ExtractInterface.java +++ /dev/null @@ -1,13 +0,0 @@ -// annotations/ifx/ExtractInterface.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// javac-based annotation processing -package annotations.ifx; -import java.lang.annotation.*; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.SOURCE) -public @interface ExtractInterface { - String interfaceName() default "-!!-"; -} diff --git a/code/annotations/ifx/IfaceExtractorProcessor.java b/code/annotations/ifx/IfaceExtractorProcessor.java deleted file mode 100644 index d17156f8..00000000 --- a/code/annotations/ifx/IfaceExtractorProcessor.java +++ /dev/null @@ -1,91 +0,0 @@ -// annotations/ifx/IfaceExtractorProcessor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// javac-based annotation processing -package annotations.ifx; -import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.*; -import javax.lang.model.util.*; -import java.util.*; -import java.util.stream.*; -import java.io.*; - -@SupportedAnnotationTypes( - "annotations.ifx.ExtractInterface") -@SupportedSourceVersion(SourceVersion.RELEASE_8) -public class IfaceExtractorProcessor -extends AbstractProcessor { - private ArrayList - interfaceMethods = new ArrayList<>(); - Elements elementUtils; - private ProcessingEnvironment processingEnv; - @Override - public void init( - ProcessingEnvironment processingEnv) { - this.processingEnv = processingEnv; - elementUtils = processingEnv.getElementUtils(); - } - @Override - public boolean process( - Set annotations, - RoundEnvironment env) { - for(Element elem:env.getElementsAnnotatedWith( - ExtractInterface.class)) { - String interfaceName = elem.getAnnotation( - ExtractInterface.class).interfaceName(); - for(Element enclosed : - elem.getEnclosedElements()) { - if(enclosed.getKind() - .equals(ElementKind.METHOD) && - enclosed.getModifiers() - .contains(Modifier.PUBLIC) && - !enclosed.getModifiers() - .contains(Modifier.STATIC)) { - interfaceMethods.add(enclosed); - } - } - if(interfaceMethods.size() > 0) - writeInterfaceFile(interfaceName); - } - return false; - } - private void - writeInterfaceFile(String interfaceName) { - try( - Writer writer = processingEnv.getFiler() - .createSourceFile(interfaceName) - .openWriter() - ) { - String packageName = elementUtils - .getPackageOf(interfaceMethods - .get(0)).toString(); - writer.write( - "package " + packageName + ";\n"); - writer.write("public interface " + - interfaceName + " {\n"); - for(Element elem : interfaceMethods) { - ExecutableElement method = - (ExecutableElement)elem; - String signature = " public "; - signature += method.getReturnType() + " "; - signature += method.getSimpleName(); - signature += createArgList( - method.getParameters()); - System.out.println(signature); - writer.write(signature + ";\n"); - } - writer.write("}"); - } catch(Exception e) { - throw new RuntimeException(e); - } - } - private String createArgList( - List parameters) { - String args = parameters.stream() - .map(p -> p.asType() + " " + p.getSimpleName()) - .collect(Collectors.joining(", ")); - return "(" + args + ")"; - } -} diff --git a/code/annotations/ifx/Multiplier.java b/code/annotations/ifx/Multiplier.java deleted file mode 100644 index b5b99a1b..00000000 --- a/code/annotations/ifx/Multiplier.java +++ /dev/null @@ -1,34 +0,0 @@ -// annotations/ifx/Multiplier.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// javac-based annotation processing -// {java annotations.ifx.Multiplier} -package annotations.ifx; - -@ExtractInterface(interfaceName="IMultiplier") -public class Multiplier { - public boolean flag = false; - private int n = 0; - public int multiply(int x, int y) { - int total = 0; - for(int i = 0; i < x; i++) - total = add(total, y); - return total; - } - public int fortySeven() { return 47; } - private int add(int x, int y) { - return x + y; - } - public double timesTen(double arg) { - return arg * 10; - } - public static void main(String[] args) { - Multiplier m = new Multiplier(); - System.out.println( - "11 * 16 = " + m.multiply(11, 16)); - } -} -/* Output: -11 * 16 = 176 -*/ diff --git a/code/annotations/simplest/Simple.java b/code/annotations/simplest/Simple.java deleted file mode 100644 index 0dc555ce..00000000 --- a/code/annotations/simplest/Simple.java +++ /dev/null @@ -1,20 +0,0 @@ -// annotations/simplest/Simple.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A bare-bones annotation -package annotations.simplest; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.annotation.ElementType; - -@Retention(RetentionPolicy.SOURCE) -@Target({ElementType.TYPE, ElementType.METHOD, - ElementType.CONSTRUCTOR, - ElementType.ANNOTATION_TYPE, - ElementType.PACKAGE, ElementType.FIELD, - ElementType.LOCAL_VARIABLE}) -public @interface Simple { - String value() default "-default-"; -} diff --git a/code/annotations/simplest/SimpleProcessor.java b/code/annotations/simplest/SimpleProcessor.java deleted file mode 100644 index a85d8987..00000000 --- a/code/annotations/simplest/SimpleProcessor.java +++ /dev/null @@ -1,47 +0,0 @@ -// annotations/simplest/SimpleProcessor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A bare-bones annotation processor -package annotations.simplest; -import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.*; -import java.util.*; - -@SupportedAnnotationTypes( - "annotations.simplest.Simple") -@SupportedSourceVersion(SourceVersion.RELEASE_8) -public class SimpleProcessor -extends AbstractProcessor { - @Override - public boolean process( - Set annotations, - RoundEnvironment env) { - for(TypeElement t : annotations) - System.out.println(t); - for(Element el : - env.getElementsAnnotatedWith(Simple.class)) - display(el); - return false; - } - private void display(Element el) { - System.out.println("==== " + el + " ===="); - System.out.println(el.getKind() + - " : " + el.getModifiers() + - " : " + el.getSimpleName() + - " : " + el.asType()); - if(el.getKind().equals(ElementKind.CLASS)) { - TypeElement te = (TypeElement)el; - System.out.println(te.getQualifiedName()); - System.out.println(te.getSuperclass()); - System.out.println(te.getEnclosedElements()); - } - if(el.getKind().equals(ElementKind.METHOD)) { - ExecutableElement ex = (ExecutableElement)el; - System.out.print(ex.getReturnType() + " "); - System.out.print(ex.getSimpleName() + "("); - System.out.println(ex.getParameters() + ")"); - } - } -} diff --git a/code/annotations/simplest/SimpleTest.java b/code/annotations/simplest/SimpleTest.java deleted file mode 100644 index 689d12fd..00000000 --- a/code/annotations/simplest/SimpleTest.java +++ /dev/null @@ -1,32 +0,0 @@ -// annotations/simplest/SimpleTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Test the "Simple" annotation -// {java annotations.simplest.SimpleTest} -package annotations.simplest; - -@Simple -public class SimpleTest { - @Simple - int i; - @Simple - public SimpleTest() {} - @Simple - public void foo() { - System.out.println("SimpleTest.foo()"); - } - @Simple - public void bar(String s, int i, float f) { - System.out.println("SimpleTest.bar()"); - } - @Simple - public static void main(String[] args) { - @Simple - SimpleTest st = new SimpleTest(); - st.foo(); - } -} -/* Output: -SimpleTest.foo() -*/ diff --git a/code/appveyorXX.yml b/code/appveyorXX.yml deleted file mode 100644 index 5e586b07..00000000 --- a/code/appveyorXX.yml +++ /dev/null @@ -1,4 +0,0 @@ -build_script: - - gradlew.bat --no-daemon --stacktrace run - -test: off diff --git a/code/arrays/AlphabeticSearch.java b/code/arrays/AlphabeticSearch.java deleted file mode 100644 index 70adc8ff..00000000 --- a/code/arrays/AlphabeticSearch.java +++ /dev/null @@ -1,29 +0,0 @@ -// arrays/AlphabeticSearch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Searching with a Comparator import -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class AlphabeticSearch { - public static void main(String[] args) { - String[] sa = new Rand.String().array(30); - Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER); - show(sa); - int index = Arrays.binarySearch(sa, - sa[10], String.CASE_INSENSITIVE_ORDER); - System.out.println( - "Index: "+ index + "\n"+ sa[index]); - } -} -/* Output: -[anmkkyh, bhmupju, btpenpc, cjwzmmr, cuxszgv, eloztdv, -ewcippc, ezdeklu, fcjpthl, fqmlgsh, gmeinne, hyoubzl, -jbvlgwc, jlxpqds, ljlbynx, mvducuj, qgekgly, skddcat, -taprwxz, uybypgp, vjsszkn, vniyapk, vqqakbm, vwodhcf, -ydpulcq, ygpoalk, yskvett, zehpfmm, zofmmvm, zrxmclh] -Index: 10 -gmeinne -*/ diff --git a/code/arrays/ArrayCopying.java b/code/arrays/ArrayCopying.java deleted file mode 100644 index c68c2a0d..00000000 --- a/code/arrays/ArrayCopying.java +++ /dev/null @@ -1,81 +0,0 @@ -// arrays/ArrayCopying.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrate Arrays.copy() and Arrays.copyOf() -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -class Sup { // Superclass - private int id; - Sup(int n) { id = n; } - @Override - public String toString() { - return getClass().getSimpleName() + id; - } -} - -class Sub extends Sup { // Subclass - Sub(int n) { super(n); } -} - -public class ArrayCopying { - public static final int SZ = 15; - public static void main(String[] args) { - int[] a1 = new int[SZ]; - Arrays.setAll(a1, new Count.Integer()::get); - show("a1", a1); - int[] a2 = Arrays.copyOf(a1, a1.length); // [1] - // Prove they are distinct arrays: - Arrays.fill(a1, 1); - show("a1", a1); - show("a2", a2); - - // Create a shorter result: - a2 = Arrays.copyOf(a2, a2.length/2); // [2] - show("a2", a2); - // Allocate more space: - a2 = Arrays.copyOf(a2, a2.length + 5); - show("a2", a2); - - // Also copies wrapped arrays: - Integer[] a3 = new Integer[SZ]; // [3] - Arrays.setAll(a3, new Count.Integer()::get); - Integer[] a4 = Arrays.copyOfRange(a3, 4, 12); - show("a4", a4); - - Sub[] d = new Sub[SZ/2]; - Arrays.setAll(d, Sub::new); - // Produce Sup[] from Sub[]: - Sup[] b = - Arrays.copyOf(d, d.length, Sup[].class); // [4] - show(b); - - // This "downcast" works fine: - Sub[] d2 = - Arrays.copyOf(b, b.length, Sub[].class); // [5] - show(d2); - - // Bad "downcast" compiles but throws exception: - Sup[] b2 = new Sup[SZ/2]; - Arrays.setAll(b2, Sup::new); - try { - Sub[] d3 = Arrays.copyOf( - b2, b2.length, Sub[].class); // [6] - } catch(Exception e) { - System.out.println(e); - } - } -} -/* Output: -a1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] -a1: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] -a2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] -a2: [0, 1, 2, 3, 4, 5, 6] -a2: [0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0] -a4: [4, 5, 6, 7, 8, 9, 10, 11] -[Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6] -[Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6] -java.lang.ArrayStoreException -*/ diff --git a/code/arrays/ArrayOfGenericType.java b/code/arrays/ArrayOfGenericType.java deleted file mode 100644 index 68f9e8de..00000000 --- a/code/arrays/ArrayOfGenericType.java +++ /dev/null @@ -1,16 +0,0 @@ -// arrays/ArrayOfGenericType.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ArrayOfGenericType { - T[] array; // OK - @SuppressWarnings("unchecked") - public ArrayOfGenericType(int size) { - // error: generic array creation: - //- array = new T[size]; - array = (T[])new Object[size]; // unchecked cast - } - // error: generic array creation: - //- public U[] makeArray() { return new U[10]; } -} diff --git a/code/arrays/ArrayOfGenerics.java b/code/arrays/ArrayOfGenerics.java deleted file mode 100644 index 79971d7a..00000000 --- a/code/arrays/ArrayOfGenerics.java +++ /dev/null @@ -1,33 +0,0 @@ -// arrays/ArrayOfGenerics.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ArrayOfGenerics { - @SuppressWarnings("unchecked") - public static void main(String[] args) { - List[] ls; - List[] la = new List[10]; - ls = (List[])la; // Unchecked cast - ls[0] = new ArrayList<>(); - - //- ls[1] = new ArrayList(); - // error: incompatible types: ArrayList - // cannot be converted to List - // ls[1] = new ArrayList(); - // ^ - - // The problem: List is a subtype of Object - Object[] objects = ls; // So assignment is OK - // Compiles and runs without complaint: - objects[1] = new ArrayList<>(); - - // However, if your needs are straightforward it is - // possible to create an array of generics, albeit - // with an "unchecked cast" warning: - List[] spheres = - (List[])new List[10]; - Arrays.setAll(spheres, n -> new ArrayList<>()); - } -} diff --git a/code/arrays/ArrayOptions.java b/code/arrays/ArrayOptions.java deleted file mode 100644 index bb6cbfbb..00000000 --- a/code/arrays/ArrayOptions.java +++ /dev/null @@ -1,79 +0,0 @@ -// arrays/ArrayOptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Initialization & re-assignment of arrays -import java.util.*; -import static onjava.ArrayShow.*; - -public class ArrayOptions { - public static void main(String[] args) { - // Arrays of objects: - BerylliumSphere[] a; // Uninitialized local - BerylliumSphere[] b = new BerylliumSphere[5]; - - // The references inside the array are - // automatically initialized to null: - show("b", b); - BerylliumSphere[] c = new BerylliumSphere[4]; - for(int i = 0; i < c.length; i++) - if(c[i] == null) // Can test for null reference - c[i] = new BerylliumSphere(); - - // Aggregate initialization: - BerylliumSphere[] d = { - new BerylliumSphere(), - new BerylliumSphere(), - new BerylliumSphere() - }; - - // Dynamic aggregate initialization: - a = new BerylliumSphere[]{ - new BerylliumSphere(), new BerylliumSphere(), - }; - // (Trailing comma is optional) - - System.out.println("a.length = " + a.length); - System.out.println("b.length = " + b.length); - System.out.println("c.length = " + c.length); - System.out.println("d.length = " + d.length); - a = d; - System.out.println("a.length = " + a.length); - - // Arrays of primitives: - int[] e; // Null reference - int[] f = new int[5]; - - // The primitives inside the array are - // automatically initialized to zero: - show("f", f); - int[] g = new int[4]; - for(int i = 0; i < g.length; i++) - g[i] = i*i; - int[] h = { 11, 47, 93 }; - - // Compile error: variable e not initialized: - //- System.out.println("e.length = " + e.length); - System.out.println("f.length = " + f.length); - System.out.println("g.length = " + g.length); - System.out.println("h.length = " + h.length); - e = h; - System.out.println("e.length = " + e.length); - e = new int[]{ 1, 2 }; - System.out.println("e.length = " + e.length); - } -} -/* Output: -b: [null, null, null, null, null] -a.length = 2 -b.length = 5 -c.length = 4 -d.length = 3 -a.length = 3 -f: [0, 0, 0, 0, 0] -f.length = 5 -g.length = 4 -h.length = 3 -e.length = 3 -e.length = 2 -*/ diff --git a/code/arrays/ArraySearching.java b/code/arrays/ArraySearching.java deleted file mode 100644 index fb4085e9..00000000 --- a/code/arrays/ArraySearching.java +++ /dev/null @@ -1,33 +0,0 @@ -// arrays/ArraySearching.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using Arrays.binarySearch() -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class ArraySearching { - public static void main(String[] args) { - Rand.Pint rand = new Rand.Pint(); - int[] a = new Rand.Pint().array(25); - Arrays.sort(a); - show("Sorted array", a); - while(true) { - int r = rand.getAsInt(); - int location = Arrays.binarySearch(a, r); - if(location >= 0) { - System.out.println( - "Location of " + r + " is " + location + - ", a[" + location + "] is " + a[location]); - break; // Out of while loop - } - } - } -} -/* Output: -Sorted array: [125, 267, 635, 650, 1131, 1506, 1634, -2400, 2766, 3063, 3768, 3941, 4720, 4762, 4948, 5070, -5682, 5807, 6177, 6193, 6656, 7021, 8479, 8737, 9954] -Location of 635 is 2, a[2] is 635 -*/ diff --git a/code/arrays/AssemblingMultidimensionalArrays.java b/code/arrays/AssemblingMultidimensionalArrays.java deleted file mode 100644 index e79302b3..00000000 --- a/code/arrays/AssemblingMultidimensionalArrays.java +++ /dev/null @@ -1,22 +0,0 @@ -// arrays/AssemblingMultidimensionalArrays.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating multidimensional arrays -import java.util.*; - -public class AssemblingMultidimensionalArrays { - public static void main(String[] args) { - Integer[][] a; - a = new Integer[3][]; - for(int i = 0; i < a.length; i++) { - a[i] = new Integer[3]; - for(int j = 0; j < a[i].length; j++) - a[i][j] = i * j; // Autoboxing - } - System.out.println(Arrays.deepToString(a)); - } -} -/* Output: -[[0, 0, 0], [0, 1, 2], [0, 2, 4]] -*/ diff --git a/code/arrays/AutoboxingArrays.java b/code/arrays/AutoboxingArrays.java deleted file mode 100644 index 25b3a0e8..00000000 --- a/code/arrays/AutoboxingArrays.java +++ /dev/null @@ -1,22 +0,0 @@ -// arrays/AutoboxingArrays.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class AutoboxingArrays { - public static void main(String[] args) { - Integer[][] a = { // Autoboxing: - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, - { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }, - { 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 }, - { 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 }, - }; - System.out.println(Arrays.deepToString(a)); - } -} -/* Output: -[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [21, 22, 23, 24, 25, -26, 27, 28, 29, 30], [51, 52, 53, 54, 55, 56, 57, 58, -59, 60], [71, 72, 73, 74, 75, 76, 77, 78, 79, 80]] -*/ diff --git a/code/arrays/CollectionComparison.java b/code/arrays/CollectionComparison.java deleted file mode 100644 index fc703c0a..00000000 --- a/code/arrays/CollectionComparison.java +++ /dev/null @@ -1,53 +0,0 @@ -// arrays/CollectionComparison.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -class BerylliumSphere { - private static long counter; - private final long id = counter++; - @Override - public String toString() { - return "Sphere " + id; - } -} - -public class CollectionComparison { - public static void main(String[] args) { - BerylliumSphere[] spheres = - new BerylliumSphere[10]; - for(int i = 0; i < 5; i++) - spheres[i] = new BerylliumSphere(); - show(spheres); - System.out.println(spheres[4]); - - List sphereList = Suppliers.create( - ArrayList::new, BerylliumSphere::new, 5); - System.out.println(sphereList); - System.out.println(sphereList.get(4)); - - int[] integers = { 0, 1, 2, 3, 4, 5 }; - show(integers); - System.out.println(integers[4]); - - List intList = new ArrayList<>( - Arrays.asList(0, 1, 2, 3, 4, 5)); - intList.add(97); - System.out.println(intList); - System.out.println(intList.get(4)); - } -} -/* Output: -[Sphere 0, Sphere 1, Sphere 2, Sphere 3, Sphere 4, -null, null, null, null, null] -Sphere 4 -[Sphere 5, Sphere 6, Sphere 7, Sphere 8, Sphere 9] -Sphere 9 -[0, 1, 2, 3, 4, 5] -4 -[0, 1, 2, 3, 4, 5, 97] -4 -*/ diff --git a/code/arrays/CompType.java b/code/arrays/CompType.java deleted file mode 100644 index 621b33d1..00000000 --- a/code/arrays/CompType.java +++ /dev/null @@ -1,56 +0,0 @@ -// arrays/CompType.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Implementing Comparable in a class -import java.util.*; -import java.util.function.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class CompType implements Comparable { - int i; - int j; - private static int count = 1; - public CompType(int n1, int n2) { - i = n1; - j = n2; - } - @Override - public String toString() { - String result = "[i = " + i + ", j = " + j + "]"; - if(count++ % 3 == 0) - result += "\n"; - return result; - } - @Override - public int compareTo(CompType rv) { - return (i < rv.i ? -1 : (i == rv.i ? 0 : 1)); - } - private static SplittableRandom r = - new SplittableRandom(47); - public static CompType get() { - return new CompType(r.nextInt(100), r.nextInt(100)); - } - public static void main(String[] args) { - CompType[] a = new CompType[12]; - Arrays.setAll(a, n -> get()); - show("Before sorting", a); - Arrays.sort(a); - show("After sorting", a); - } -} -/* Output: -Before sorting: [[i = 35, j = 37], [i = 41, j = 20], [i -= 77, j = 79] -, [i = 56, j = 68], [i = 48, j = 93], [i = 70, j = 7] -, [i = 0, j = 25], [i = 62, j = 34], [i = 50, j = 82] -, [i = 31, j = 67], [i = 66, j = 54], [i = 21, j = 6] -] -After sorting: [[i = 0, j = 25], [i = 21, j = 6], [i = -31, j = 67] -, [i = 35, j = 37], [i = 41, j = 20], [i = 48, j = 93] -, [i = 50, j = 82], [i = 56, j = 68], [i = 62, j = 34] -, [i = 66, j = 54], [i = 70, j = 7], [i = 77, j = 79] -] -*/ diff --git a/code/arrays/ComparatorTest.java b/code/arrays/ComparatorTest.java deleted file mode 100644 index 68f7e380..00000000 --- a/code/arrays/ComparatorTest.java +++ /dev/null @@ -1,39 +0,0 @@ -// arrays/ComparatorTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Implementing a Comparator for a class -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -class CompTypeComparator -implements Comparator { - public int compare(CompType o1, CompType o2) { - return (o1.j < o2.j ? -1 : (o1.j == o2.j ? 0 : 1)); - } -} - -public class ComparatorTest { - public static void main(String[] args) { - CompType[] a = new CompType[12]; - Arrays.setAll(a, n -> CompType.get()); - show("Before sorting", a); - Arrays.sort(a, new CompTypeComparator()); - show("After sorting", a); - } -} -/* Output: -Before sorting: [[i = 35, j = 37], [i = 41, j = 20], [i -= 77, j = 79] -, [i = 56, j = 68], [i = 48, j = 93], [i = 70, j = 7] -, [i = 0, j = 25], [i = 62, j = 34], [i = 50, j = 82] -, [i = 31, j = 67], [i = 66, j = 54], [i = 21, j = 6] -] -After sorting: [[i = 21, j = 6], [i = 70, j = 7], [i = -41, j = 20] -, [i = 0, j = 25], [i = 62, j = 34], [i = 35, j = 37] -, [i = 66, j = 54], [i = 31, j = 67], [i = 56, j = 68] -, [i = 77, j = 79], [i = 50, j = 82], [i = 48, j = 93] -] -*/ diff --git a/code/arrays/ComparingArrays.java b/code/arrays/ComparingArrays.java deleted file mode 100644 index 9ddad69d..00000000 --- a/code/arrays/ComparingArrays.java +++ /dev/null @@ -1,62 +0,0 @@ -// arrays/ComparingArrays.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using Arrays.equals() -import java.util.*; -import onjava.*; - -public class ComparingArrays { - public static final int SZ = 15; - static String[][] twoDArray() { - String[][] md = new String[5][]; - Arrays.setAll(md, n -> new String[n]); - for(int i = 0; i < md.length; i++) - Arrays.setAll(md[i], new Rand.String()::get); - return md; - } - public static void main(String[] args) { - int[] a1 = new int[SZ], a2 = new int[SZ]; - Arrays.setAll(a1, new Count.Integer()::get); - Arrays.setAll(a2, new Count.Integer()::get); - System.out.println( - "a1 == a2: " + Arrays.equals(a1, a2)); - a2[3] = 11; - System.out.println( - "a1 == a2: " + Arrays.equals(a1, a2)); - - Integer[] a1w = new Integer[SZ], - a2w = new Integer[SZ]; - Arrays.setAll(a1w, new Count.Integer()::get); - Arrays.setAll(a2w, new Count.Integer()::get); - System.out.println( - "a1w == a2w: " + Arrays.equals(a1w, a2w)); - a2w[3] = 11; - System.out.println( - "a1w == a2w: " + Arrays.equals(a1w, a2w)); - - String[][] md1 = twoDArray(), md2 = twoDArray(); - System.out.println(Arrays.deepToString(md1)); - System.out.println("deepEquals(md1, md2): " + - Arrays.deepEquals(md1, md2)); - System.out.println( - "md1 == md2: " + Arrays.equals(md1, md2)); - md1[4][1] = "#$#$#$#"; - System.out.println(Arrays.deepToString(md1)); - System.out.println("deepEquals(md1, md2): " + - Arrays.deepEquals(md1, md2)); - } -} -/* Output: -a1 == a2: true -a1 == a2: false -a1w == a2w: true -a1w == a2w: false -[[], [btpenpc], [btpenpc, cuxszgv], [btpenpc, cuxszgv, -gmeinne], [btpenpc, cuxszgv, gmeinne, eloztdv]] -deepEquals(md1, md2): true -md1 == md2: false -[[], [btpenpc], [btpenpc, cuxszgv], [btpenpc, cuxszgv, -gmeinne], [btpenpc, #$#$#$#, gmeinne, eloztdv]] -deepEquals(md1, md2): false -*/ diff --git a/code/arrays/CountUpward.java b/code/arrays/CountUpward.java deleted file mode 100644 index bbeb02ba..00000000 --- a/code/arrays/CountUpward.java +++ /dev/null @@ -1,24 +0,0 @@ -// arrays/CountUpward.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import static onjava.ArrayShow.*; - -public class CountUpward { - static long[] fillCounted(int size) { - return LongStream.iterate(0, i -> i + 1) - .limit(size).toArray(); - } - public static void main(String[] args) { - long[] l1 = fillCounted(20); // No problem - show(l1); - // On my machine, this runs out of heap space: - //- long[] l2 = fillCounted(10_000_000); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19] -*/ diff --git a/code/arrays/FillingArrays.java b/code/arrays/FillingArrays.java deleted file mode 100644 index df54e62f..00000000 --- a/code/arrays/FillingArrays.java +++ /dev/null @@ -1,55 +0,0 @@ -// arrays/FillingArrays.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using Arrays.fill() -import java.util.*; -import static onjava.ArrayShow.*; - -public class FillingArrays { - public static void main(String[] args) { - int size = 6; - boolean[] a1 = new boolean[size]; - byte[] a2 = new byte[size]; - char[] a3 = new char[size]; - short[] a4 = new short[size]; - int[] a5 = new int[size]; - long[] a6 = new long[size]; - float[] a7 = new float[size]; - double[] a8 = new double[size]; - String[] a9 = new String[size]; - Arrays.fill(a1, true); - show("a1", a1); - Arrays.fill(a2, (byte)11); - show("a2", a2); - Arrays.fill(a3, 'x'); - show("a3", a3); - Arrays.fill(a4, (short)17); - show("a4", a4); - Arrays.fill(a5, 19); - show("a5", a5); - Arrays.fill(a6, 23); - show("a6", a6); - Arrays.fill(a7, 29); - show("a7", a7); - Arrays.fill(a8, 47); - show("a8", a8); - Arrays.fill(a9, "Hello"); - show("a9", a9); - // Manipulating ranges: - Arrays.fill(a9, 3, 5, "World"); - show("a9", a9); - } -} -/* Output: -a1: [true, true, true, true, true, true] -a2: [11, 11, 11, 11, 11, 11] -a3: [x, x, x, x, x, x] -a4: [17, 17, 17, 17, 17, 17] -a5: [19, 19, 19, 19, 19, 19] -a6: [23, 23, 23, 23, 23, 23] -a7: [29.0, 29.0, 29.0, 29.0, 29.0, 29.0] -a8: [47.0, 47.0, 47.0, 47.0, 47.0, 47.0] -a9: [Hello, Hello, Hello, Hello, Hello, Hello] -a9: [Hello, Hello, Hello, World, World, Hello] -*/ diff --git a/code/arrays/IceCreamFlavors.java b/code/arrays/IceCreamFlavors.java deleted file mode 100644 index 5e9d2b61..00000000 --- a/code/arrays/IceCreamFlavors.java +++ /dev/null @@ -1,45 +0,0 @@ -// arrays/IceCreamFlavors.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Returning arrays from methods -import java.util.*; -import static onjava.ArrayShow.*; - -public class IceCreamFlavors { - private static SplittableRandom rand = - new SplittableRandom(47); - static final String[] FLAVORS = { - "Chocolate", "Strawberry", "Vanilla Fudge Swirl", - "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", - "Praline Cream", "Mud Pie" - }; - public static String[] flavorSet(int n) { - if(n > FLAVORS.length) - throw new IllegalArgumentException("Set too big"); - String[] results = new String[n]; - boolean[] picked = new boolean[FLAVORS.length]; - for(int i = 0; i < n; i++) { - int t; - do - t = rand.nextInt(FLAVORS.length); - while(picked[t]); - results[i] = FLAVORS[t]; - picked[t] = true; - } - return results; - } - public static void main(String[] args) { - for(int i = 0; i < 7; i++) - show(flavorSet(3)); - } -} -/* Output: -[Praline Cream, Mint Chip, Vanilla Fudge Swirl] -[Strawberry, Vanilla Fudge Swirl, Mud Pie] -[Chocolate, Strawberry, Vanilla Fudge Swirl] -[Rum Raisin, Praline Cream, Chocolate] -[Mint Chip, Rum Raisin, Mocha Almond Fudge] -[Mocha Almond Fudge, Mud Pie, Vanilla Fudge Swirl] -[Mocha Almond Fudge, Mud Pie, Mint Chip] -*/ diff --git a/code/arrays/ModifyExisting.java b/code/arrays/ModifyExisting.java deleted file mode 100644 index d74df78e..00000000 --- a/code/arrays/ModifyExisting.java +++ /dev/null @@ -1,22 +0,0 @@ -// arrays/ModifyExisting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class ModifyExisting { - public static void main(String[] args) { - double[] da = new double[7]; - Arrays.setAll(da, new Rand.Double()::get); - show(da); - Arrays.setAll(da, n -> da[n] / 100); // [1] - show(da); - } -} -/* Output: -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99] -[0.0483, 0.028900000000000002, 0.028999999999999998, -0.0197, 0.0301, 0.0018, 0.009899999999999999] -*/ diff --git a/code/arrays/MultiDimWrapperArray.java b/code/arrays/MultiDimWrapperArray.java deleted file mode 100644 index 1185d0f9..00000000 --- a/code/arrays/MultiDimWrapperArray.java +++ /dev/null @@ -1,38 +0,0 @@ -// arrays/MultiDimWrapperArray.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Multidimensional arrays of "wrapper" objects -import java.util.*; - -public class MultiDimWrapperArray { - public static void main(String[] args) { - Integer[][] a1 = { // Autoboxing - { 1, 2, 3, }, - { 4, 5, 6, }, - }; - Double[][][] a2 = { // Autoboxing - { { 1.1, 2.2 }, { 3.3, 4.4 } }, - { { 5.5, 6.6 }, { 7.7, 8.8 } }, - { { 9.9, 1.2 }, { 2.3, 3.4 } }, - }; - String[][] a3 = { - { "The", "Quick", "Sly", "Fox" }, - { "Jumped", "Over" }, - { "The", "Lazy", "Brown", "Dog", "&", "friend" }, - }; - System.out.println( - "a1: " + Arrays.deepToString(a1)); - System.out.println( - "a2: " + Arrays.deepToString(a2)); - System.out.println( - "a3: " + Arrays.deepToString(a3)); - } -} -/* Output: -a1: [[1, 2, 3], [4, 5, 6]] -a2: [[[1.1, 2.2], [3.3, 4.4]], [[5.5, 6.6], [7.7, -8.8]], [[9.9, 1.2], [2.3, 3.4]]] -a3: [[The, Quick, Sly, Fox], [Jumped, Over], [The, -Lazy, Brown, Dog, &, friend]] -*/ diff --git a/code/arrays/MultidimensionalObjectArrays.java b/code/arrays/MultidimensionalObjectArrays.java deleted file mode 100644 index 998e7c99..00000000 --- a/code/arrays/MultidimensionalObjectArrays.java +++ /dev/null @@ -1,25 +0,0 @@ -// arrays/MultidimensionalObjectArrays.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class MultidimensionalObjectArrays { - public static void main(String[] args) { - BerylliumSphere[][] spheres = { - { new BerylliumSphere(), new BerylliumSphere() }, - { new BerylliumSphere(), new BerylliumSphere(), - new BerylliumSphere(), new BerylliumSphere() }, - { new BerylliumSphere(), new BerylliumSphere(), - new BerylliumSphere(), new BerylliumSphere(), - new BerylliumSphere(), new BerylliumSphere(), - new BerylliumSphere(), new BerylliumSphere() }, - }; - System.out.println(Arrays.deepToString(spheres)); - } -} -/* Output: -[[Sphere 0, Sphere 1], [Sphere 2, Sphere 3, Sphere 4, -Sphere 5], [Sphere 6, Sphere 7, Sphere 8, Sphere 9, -Sphere 10, Sphere 11, Sphere 12, Sphere 13]] -*/ diff --git a/code/arrays/MultidimensionalPrimitiveArray.java b/code/arrays/MultidimensionalPrimitiveArray.java deleted file mode 100644 index 8ed5884f..00000000 --- a/code/arrays/MultidimensionalPrimitiveArray.java +++ /dev/null @@ -1,18 +0,0 @@ -// arrays/MultidimensionalPrimitiveArray.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class MultidimensionalPrimitiveArray { - public static void main(String[] args) { - int[][] a = { - { 1, 2, 3, }, - { 4, 5, 6, }, - }; - System.out.println(Arrays.deepToString(a)); - } -} -/* Output: -[[1, 2, 3], [4, 5, 6]] -*/ diff --git a/code/arrays/ParallelPrefix1.java b/code/arrays/ParallelPrefix1.java deleted file mode 100644 index e180d019..00000000 --- a/code/arrays/ParallelPrefix1.java +++ /dev/null @@ -1,27 +0,0 @@ -// arrays/ParallelPrefix1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class ParallelPrefix1 { - public static void main(String[] args) { - int[] nums = new Count.Pint().array(10); - show(nums); - System.out.println(Arrays.stream(nums) - .reduce(Integer::sum).getAsInt()); - Arrays.parallelPrefix(nums, Integer::sum); - show(nums); - System.out.println(Arrays.stream( - new Count.Pint().array(6)) - .reduce(Integer::sum).getAsInt()); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -45 -[0, 1, 3, 6, 10, 15, 21, 28, 36, 45] -15 -*/ diff --git a/code/arrays/ParallelPrefix2.java b/code/arrays/ParallelPrefix2.java deleted file mode 100644 index 5288d3ce..00000000 --- a/code/arrays/ParallelPrefix2.java +++ /dev/null @@ -1,20 +0,0 @@ -// arrays/ParallelPrefix2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class ParallelPrefix2 { - public static void main(String[] args) { - String[] strings = new Rand.String(1).array(8); - show(strings); - Arrays.parallelPrefix(strings, (a, b) -> a + b); - show(strings); - } -} -/* Output: -[b, t, p, e, n, p, c, c] -[b, bt, btp, btpe, btpen, btpenp, btpenpc, btpenpcc] -*/ diff --git a/code/arrays/ParallelPrefix3.java b/code/arrays/ParallelPrefix3.java deleted file mode 100644 index ed2751dc..00000000 --- a/code/arrays/ParallelPrefix3.java +++ /dev/null @@ -1,23 +0,0 @@ -// arrays/ParallelPrefix3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromTravisCI} -import java.util.*; - -public class ParallelPrefix3 { - static final int SIZE = 10_000_000; - public static void main(String[] args) { - long[] nums = new long[SIZE]; - Arrays.setAll(nums, n -> n); - Arrays.parallelPrefix(nums, Long::sum); - System.out.println("First 20: " + nums[19]); - System.out.println("First 200: " + nums[199]); - System.out.println("All: " + nums[nums.length-1]); - } -} -/* Output: -First 20: 190 -First 200: 19900 -All: 49999995000000 -*/ diff --git a/code/arrays/ParallelSetAll.java b/code/arrays/ParallelSetAll.java deleted file mode 100644 index f6c47ff5..00000000 --- a/code/arrays/ParallelSetAll.java +++ /dev/null @@ -1,24 +0,0 @@ -// arrays/ParallelSetAll.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.*; - -public class ParallelSetAll { - static final int SIZE = 10_000_000; - static void intArray() { - int[] ia = new int[SIZE]; - Arrays.setAll(ia, new Rand.Pint()::get); - Arrays.parallelSetAll(ia, new Rand.Pint()::get); - } - static void longArray() { - long[] la = new long[SIZE]; - Arrays.setAll(la, new Rand.Plong()::get); - Arrays.parallelSetAll(la, new Rand.Plong()::get); - } - public static void main(String[] args) { - intArray(); - longArray(); - } -} diff --git a/code/arrays/ParameterizedArrayType.java b/code/arrays/ParameterizedArrayType.java deleted file mode 100644 index 06c1021c..00000000 --- a/code/arrays/ParameterizedArrayType.java +++ /dev/null @@ -1,25 +0,0 @@ -// arrays/ParameterizedArrayType.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class ClassParameter { - public T[] f(T[] arg) { return arg; } -} - -class MethodParameter { - public static T[] f(T[] arg) { return arg; } -} - -public class ParameterizedArrayType { - public static void main(String[] args) { - Integer[] ints = { 1, 2, 3, 4, 5 }; - Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 }; - Integer[] ints2 = - new ClassParameter().f(ints); - Double[] doubles2 = - new ClassParameter().f(doubles); - ints2 = MethodParameter.f(ints); - doubles2 = MethodParameter.f(doubles); - } -} diff --git a/code/arrays/PythonLists.py b/code/arrays/PythonLists.py deleted file mode 100644 index 910daf18..00000000 --- a/code/arrays/PythonLists.py +++ /dev/null @@ -1,36 +0,0 @@ -# arrays/PythonLists.py -# (c)2020 MindView LLC: see Copyright.txt -# We make no guarantees that this code is fit for any purpose. -# Visit http://OnJava8.com for more book information. - -aList = [1, 2, 3, 4, 5] -print(type(aList)) # -print(aList) # [1, 2, 3, 4, 5] -print(aList[4]) # 5 Basic list indexing -aList.append(6) # lists can be resized -aList += [7, 8] # Add a list to a list -print(aList) # [1, 2, 3, 4, 5, 6, 7, 8] -aSlice = aList[2:4] -print(aSlice) # [3, 4] - -class MyList(list): # Inherit from list - # Define a method; 'this' pointer is explicit: - def getReversed(self): - reversed = self[:] # Copy list using slices - reversed.reverse() # Built-in list method - return reversed - -# No 'new' necessary for object creation: -list2 = MyList(aList) -print(type(list2)) # -print(list2.getReversed()) # [8, 7, 6, 5, 4, 3, 2, 1] - -output = """ - -[1, 2, 3, 4, 5] -5 -[1, 2, 3, 4, 5, 6, 7, 8] -[3, 4] - -[8, 7, 6, 5, 4, 3, 2, 1] -""" diff --git a/code/arrays/RaggedArray.java b/code/arrays/RaggedArray.java deleted file mode 100644 index bd7d625b..00000000 --- a/code/arrays/RaggedArray.java +++ /dev/null @@ -1,26 +0,0 @@ -// arrays/RaggedArray.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class RaggedArray { - static int val = 1; - public static void main(String[] args) { - SplittableRandom rand = new SplittableRandom(47); - // 3-D array with varied-length vectors: - int[][][] a = new int[rand.nextInt(7)][][]; - for(int i = 0; i < a.length; i++) { - a[i] = new int[rand.nextInt(5)][]; - for(int j = 0; j < a[i].length; j++) { - a[i][j] = new int[rand.nextInt(5)]; - Arrays.setAll(a[i][j], n -> val++); // [1] - } - } - System.out.println(Arrays.deepToString(a)); - } -} -/* Output: -[[[1], []], [[2, 3, 4, 5], [6]], [[7, 8, 9], [10, 11, -12], []]] -*/ diff --git a/code/arrays/Reverse.java b/code/arrays/Reverse.java deleted file mode 100644 index 9a7de678..00000000 --- a/code/arrays/Reverse.java +++ /dev/null @@ -1,32 +0,0 @@ -// arrays/Reverse.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The Collections.reverseOrder() Comparator -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class Reverse { - public static void main(String[] args) { - CompType[] a = new CompType[12]; - Arrays.setAll(a, n -> CompType.get()); - show("Before sorting", a); - Arrays.sort(a, Collections.reverseOrder()); - show("After sorting", a); - } -} -/* Output: -Before sorting: [[i = 35, j = 37], [i = 41, j = 20], [i -= 77, j = 79] -, [i = 56, j = 68], [i = 48, j = 93], [i = 70, j = 7] -, [i = 0, j = 25], [i = 62, j = 34], [i = 50, j = 82] -, [i = 31, j = 67], [i = 66, j = 54], [i = 21, j = 6] -] -After sorting: [[i = 77, j = 79], [i = 70, j = 7], [i = -66, j = 54] -, [i = 62, j = 34], [i = 56, j = 68], [i = 50, j = 82] -, [i = 48, j = 93], [i = 41, j = 20], [i = 35, j = 37] -, [i = 31, j = 67], [i = 21, j = 6], [i = 0, j = 25] -] -*/ diff --git a/code/arrays/SimpleSetAll.java b/code/arrays/SimpleSetAll.java deleted file mode 100644 index 70336e79..00000000 --- a/code/arrays/SimpleSetAll.java +++ /dev/null @@ -1,56 +0,0 @@ -// arrays/SimpleSetAll.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import static onjava.ArrayShow.*; - -class Bob { - final int id; - Bob(int n) { id = n; } - @Override - public String toString() { return "Bob" + id; } -} - -public class SimpleSetAll { - public static final int SZ = 8; - static int val = 1; - static char[] chars = "abcdefghijklmnopqrstuvwxyz" - .toCharArray(); - static char getChar(int n) { return chars[n]; } - public static void main(String[] args) { - int[] ia = new int[SZ]; - long[] la = new long[SZ]; - double[] da = new double[SZ]; - Arrays.setAll(ia, n -> n); // [1] - Arrays.setAll(la, n -> n); - Arrays.setAll(da, n -> n); - show(ia); - show(la); - show(da); - Arrays.setAll(ia, n -> val++); // [2] - Arrays.setAll(la, n -> val++); - Arrays.setAll(da, n -> val++); - show(ia); - show(la); - show(da); - - Bob[] ba = new Bob[SZ]; - Arrays.setAll(ba, Bob::new); // [3] - show(ba); - - Character[] ca = new Character[SZ]; - Arrays.setAll(ca, SimpleSetAll::getChar); // [4] - show(ca); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7] -[0, 1, 2, 3, 4, 5, 6, 7] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] -[1, 2, 3, 4, 5, 6, 7, 8] -[9, 10, 11, 12, 13, 14, 15, 16] -[17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0] -[Bob0, Bob1, Bob2, Bob3, Bob4, Bob5, Bob6, Bob7] -[a, b, c, d, e, f, g, h] -*/ diff --git a/code/arrays/StreamFromArray.java b/code/arrays/StreamFromArray.java deleted file mode 100644 index 69628703..00000000 --- a/code/arrays/StreamFromArray.java +++ /dev/null @@ -1,51 +0,0 @@ -// arrays/StreamFromArray.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.*; - -public class StreamFromArray { - public static void main(String[] args) { - String[] s = new Rand.String().array(10); - Arrays.stream(s) - .skip(3) - .limit(5) - .map(ss -> ss + "!") - .forEach(System.out::println); - - int[] ia = new Rand.Pint().array(10); - Arrays.stream(ia) - .skip(3) - .limit(5) - .map(i -> i * 10) - .forEach(System.out::println); - - Arrays.stream(new long[10]); - Arrays.stream(new double[10]); - - // Only int, long and double work: - //- Arrays.stream(new boolean[10]); - //- Arrays.stream(new byte[10]); - //- Arrays.stream(new char[10]); - //- Arrays.stream(new short[10]); - //- Arrays.stream(new float[10]); - - // For the other types you must use wrapped arrays: - float[] fa = new Rand.Pfloat().array(10); - Arrays.stream(ConvertTo.boxed(fa)); - Arrays.stream(new Rand.Float().array(10)); - } -} -/* Output: -eloztdv! -ewcippc! -ygpoalk! -ljlbynx! -taprwxz! -47200 -61770 -84790 -66560 -37680 -*/ diff --git a/code/arrays/StringSorting.java b/code/arrays/StringSorting.java deleted file mode 100644 index 0da5c733..00000000 --- a/code/arrays/StringSorting.java +++ /dev/null @@ -1,39 +0,0 @@ -// arrays/StringSorting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Sorting an array of Strings -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class StringSorting { - public static void main(String[] args) { - String[] sa = new Rand.String().array(20); - show("Before sort", sa); - Arrays.sort(sa); - show("After sort", sa); - Arrays.sort(sa, Collections.reverseOrder()); - show("Reverse sort", sa); - Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER); - show("Case-insensitive sort", sa); - } -} -/* Output: -Before sort: [btpenpc, cuxszgv, gmeinne, eloztdv, -ewcippc, ygpoalk, ljlbynx, taprwxz, bhmupju, cjwzmmr, -anmkkyh, fcjpthl, skddcat, jbvlgwc, mvducuj, ydpulcq, -zehpfmm, zrxmclh, qgekgly, hyoubzl] -After sort: [anmkkyh, bhmupju, btpenpc, cjwzmmr, -cuxszgv, eloztdv, ewcippc, fcjpthl, gmeinne, hyoubzl, -jbvlgwc, ljlbynx, mvducuj, qgekgly, skddcat, taprwxz, -ydpulcq, ygpoalk, zehpfmm, zrxmclh] -Reverse sort: [zrxmclh, zehpfmm, ygpoalk, ydpulcq, -taprwxz, skddcat, qgekgly, mvducuj, ljlbynx, jbvlgwc, -hyoubzl, gmeinne, fcjpthl, ewcippc, eloztdv, cuxszgv, -cjwzmmr, btpenpc, bhmupju, anmkkyh] -Case-insensitive sort: [anmkkyh, bhmupju, btpenpc, -cjwzmmr, cuxszgv, eloztdv, ewcippc, fcjpthl, gmeinne, -hyoubzl, jbvlgwc, ljlbynx, mvducuj, qgekgly, skddcat, -taprwxz, ydpulcq, ygpoalk, zehpfmm, zrxmclh] -*/ diff --git a/code/arrays/TestConvertTo.java b/code/arrays/TestConvertTo.java deleted file mode 100644 index 8ecb72a6..00000000 --- a/code/arrays/TestConvertTo.java +++ /dev/null @@ -1,87 +0,0 @@ -// arrays/TestConvertTo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.*; -import static onjava.ArrayShow.*; -import static onjava.ConvertTo.*; - -public class TestConvertTo { - static final int SIZE = 6; - public static void main(String[] args) { - Boolean[] a1 = new Boolean[SIZE]; - Arrays.setAll(a1, new Rand.Boolean()::get); - boolean[] a1p = primitive(a1); - show("a1p", a1p); - Boolean[] a1b = boxed(a1p); - show("a1b", a1b); - - Byte[] a2 = new Byte[SIZE]; - Arrays.setAll(a2, new Rand.Byte()::get); - byte[] a2p = primitive(a2); - show("a2p", a2p); - Byte[] a2b = boxed(a2p); - show("a2b", a2b); - - Character[] a3 = new Character[SIZE]; - Arrays.setAll(a3, new Rand.Character()::get); - char[] a3p = primitive(a3); - show("a3p", a3p); - Character[] a3b = boxed(a3p); - show("a3b", a3b); - - Short[] a4 = new Short[SIZE]; - Arrays.setAll(a4, new Rand.Short()::get); - short[] a4p = primitive(a4); - show("a4p", a4p); - Short[] a4b = boxed(a4p); - show("a4b", a4b); - - Integer[] a5 = new Integer[SIZE]; - Arrays.setAll(a5, new Rand.Integer()::get); - int[] a5p = primitive(a5); - show("a5p", a5p); - Integer[] a5b = boxed(a5p); - show("a5b", a5b); - - Long[] a6 = new Long[SIZE]; - Arrays.setAll(a6, new Rand.Long()::get); - long[] a6p = primitive(a6); - show("a6p", a6p); - Long[] a6b = boxed(a6p); - show("a6b", a6b); - - Float[] a7 = new Float[SIZE]; - Arrays.setAll(a7, new Rand.Float()::get); - float[] a7p = primitive(a7); - show("a7p", a7p); - Float[] a7b = boxed(a7p); - show("a7b", a7b); - - Double[] a8 = new Double[SIZE]; - Arrays.setAll(a8, new Rand.Double()::get); - double[] a8p = primitive(a8); - show("a8p", a8p); - Double[] a8b = boxed(a8p); - show("a8b", a8b); - } -} -/* Output: -a1p: [true, false, true, true, true, false] -a1b: [true, false, true, true, true, false] -a2p: [123, 33, 101, 112, 33, 31] -a2b: [123, 33, 101, 112, 33, 31] -a3p: [b, t, p, e, n, p] -a3b: [b, t, p, e, n, p] -a4p: [635, 8737, 3941, 4720, 6177, 8479] -a4b: [635, 8737, 3941, 4720, 6177, 8479] -a5p: [635, 8737, 3941, 4720, 6177, 8479] -a5b: [635, 8737, 3941, 4720, 6177, 8479] -a6p: [6882, 3765, 692, 9575, 4439, 2638] -a6b: [6882, 3765, 692, 9575, 4439, 2638] -a7p: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] -a7b: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] -a8p: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] -a8b: [4.83, 2.89, 2.9, 1.97, 3.01, 0.18] -*/ diff --git a/code/arrays/TestCount.java b/code/arrays/TestCount.java deleted file mode 100644 index a77e00f7..00000000 --- a/code/arrays/TestCount.java +++ /dev/null @@ -1,167 +0,0 @@ -// arrays/TestCount.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Test counting generators -import java.util.*; -import java.util.stream.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class TestCount { - static final int SZ = 5; - public static void main(String[] args) { - System.out.println("Boolean"); - Boolean[] a1 = new Boolean[SZ]; - Arrays.setAll(a1, new Count.Boolean()::get); - show(a1); - a1 = Stream.generate(new Count.Boolean()) - .limit(SZ + 1).toArray(Boolean[]::new); - show(a1); - a1 = new Count.Boolean().array(SZ + 2); - show(a1); - boolean[] a1b = - new Count.Pboolean().array(SZ + 3); - show(a1b); - - System.out.println("Byte"); - Byte[] a2 = new Byte[SZ]; - Arrays.setAll(a2, new Count.Byte()::get); - show(a2); - a2 = Stream.generate(new Count.Byte()) - .limit(SZ + 1).toArray(Byte[]::new); - show(a2); - a2 = new Count.Byte().array(SZ + 2); - show(a2); - byte[] a2b = new Count.Pbyte().array(SZ + 3); - show(a2b); - - System.out.println("Character"); - Character[] a3 = new Character[SZ]; - Arrays.setAll(a3, new Count.Character()::get); - show(a3); - a3 = Stream.generate(new Count.Character()) - .limit(SZ + 1).toArray(Character[]::new); - show(a3); - a3 = new Count.Character().array(SZ + 2); - show(a3); - char[] a3b = new Count.Pchar().array(SZ + 3); - show(a3b); - - System.out.println("Short"); - Short[] a4 = new Short[SZ]; - Arrays.setAll(a4, new Count.Short()::get); - show(a4); - a4 = Stream.generate(new Count.Short()) - .limit(SZ + 1).toArray(Short[]::new); - show(a4); - a4 = new Count.Short().array(SZ + 2); - show(a4); - short[] a4b = new Count.Pshort().array(SZ + 3); - show(a4b); - - System.out.println("Integer"); - int[] a5 = new int[SZ]; - Arrays.setAll(a5, new Count.Integer()::get); - show(a5); - Integer[] a5b = - Stream.generate(new Count.Integer()) - .limit(SZ + 1).toArray(Integer[]::new); - show(a5b); - a5b = new Count.Integer().array(SZ + 2); - show(a5b); - a5 = IntStream.generate(new Count.Pint()) - .limit(SZ + 1).toArray(); - show(a5); - a5 = new Count.Pint().array(SZ + 3); - show(a5); - - System.out.println("Long"); - long[] a6 = new long[SZ]; - Arrays.setAll(a6, new Count.Long()::get); - show(a6); - Long[] a6b = Stream.generate(new Count.Long()) - .limit(SZ + 1).toArray(Long[]::new); - show(a6b); - a6b = new Count.Long().array(SZ + 2); - show(a6b); - a6 = LongStream.generate(new Count.Plong()) - .limit(SZ + 1).toArray(); - show(a6); - a6 = new Count.Plong().array(SZ + 3); - show(a6); - - System.out.println("Float"); - Float[] a7 = new Float[SZ]; - Arrays.setAll(a7, new Count.Float()::get); - show(a7); - a7 = Stream.generate(new Count.Float()) - .limit(SZ + 1).toArray(Float[]::new); - show(a7); - a7 = new Count.Float().array(SZ + 2); - show(a7); - float[] a7b = new Count.Pfloat().array(SZ + 3); - show(a7b); - - System.out.println("Double"); - double[] a8 = new double[SZ]; - Arrays.setAll(a8, new Count.Double()::get); - show(a8); - Double[] a8b = - Stream.generate(new Count.Double()) - .limit(SZ + 1).toArray(Double[]::new); - show(a8b); - a8b = new Count.Double().array(SZ + 2); - show(a8b); - a8 = DoubleStream.generate(new Count.Pdouble()) - .limit(SZ + 1).toArray(); - show(a8); - a8 = new Count.Pdouble().array(SZ + 3); - show(a8); - } -} -/* Output: -Boolean -[false, true, false, true, false] -[false, true, false, true, false, true] -[false, true, false, true, false, true, false] -[false, true, false, true, false, true, false, true] -Byte -[0, 1, 2, 3, 4] -[0, 1, 2, 3, 4, 5] -[0, 1, 2, 3, 4, 5, 6] -[0, 1, 2, 3, 4, 5, 6, 7] -Character -[b, c, d, e, f] -[b, c, d, e, f, g] -[b, c, d, e, f, g, h] -[b, c, d, e, f, g, h, i] -Short -[0, 1, 2, 3, 4] -[0, 1, 2, 3, 4, 5] -[0, 1, 2, 3, 4, 5, 6] -[0, 1, 2, 3, 4, 5, 6, 7] -Integer -[0, 1, 2, 3, 4] -[0, 1, 2, 3, 4, 5] -[0, 1, 2, 3, 4, 5, 6] -[0, 1, 2, 3, 4, 5] -[0, 1, 2, 3, 4, 5, 6, 7] -Long -[0, 1, 2, 3, 4] -[0, 1, 2, 3, 4, 5] -[0, 1, 2, 3, 4, 5, 6] -[0, 1, 2, 3, 4, 5] -[0, 1, 2, 3, 4, 5, 6, 7] -Float -[0.0, 1.0, 2.0, 3.0, 4.0] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] -Double -[0.0, 1.0, 2.0, 3.0, 4.0] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0] -[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] -*/ diff --git a/code/arrays/TestRand.java b/code/arrays/TestRand.java deleted file mode 100644 index 17e0718f..00000000 --- a/code/arrays/TestRand.java +++ /dev/null @@ -1,192 +0,0 @@ -// arrays/TestRand.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Test random generators -import java.util.*; -import java.util.stream.*; -import onjava.*; -import static onjava.ArrayShow.*; - -public class TestRand { - static final int SZ = 5; - public static void main(String[] args) { - System.out.println("Boolean"); - Boolean[] a1 = new Boolean[SZ]; - Arrays.setAll(a1, new Rand.Boolean()::get); - show(a1); - a1 = Stream.generate(new Rand.Boolean()) - .limit(SZ + 1).toArray(Boolean[]::new); - show(a1); - a1 = new Rand.Boolean().array(SZ + 2); - show(a1); - boolean[] a1b = - new Rand.Pboolean().array(SZ + 3); - show(a1b); - - System.out.println("Byte"); - Byte[] a2 = new Byte[SZ]; - Arrays.setAll(a2, new Rand.Byte()::get); - show(a2); - a2 = Stream.generate(new Rand.Byte()) - .limit(SZ + 1).toArray(Byte[]::new); - show(a2); - a2 = new Rand.Byte().array(SZ + 2); - show(a2); - byte[] a2b = new Rand.Pbyte().array(SZ + 3); - show(a2b); - - System.out.println("Character"); - Character[] a3 = new Character[SZ]; - Arrays.setAll(a3, new Rand.Character()::get); - show(a3); - a3 = Stream.generate(new Rand.Character()) - .limit(SZ + 1).toArray(Character[]::new); - show(a3); - a3 = new Rand.Character().array(SZ + 2); - show(a3); - char[] a3b = new Rand.Pchar().array(SZ + 3); - show(a3b); - - System.out.println("Short"); - Short[] a4 = new Short[SZ]; - Arrays.setAll(a4, new Rand.Short()::get); - show(a4); - a4 = Stream.generate(new Rand.Short()) - .limit(SZ + 1).toArray(Short[]::new); - show(a4); - a4 = new Rand.Short().array(SZ + 2); - show(a4); - short[] a4b = new Rand.Pshort().array(SZ + 3); - show(a4b); - - System.out.println("Integer"); - int[] a5 = new int[SZ]; - Arrays.setAll(a5, new Rand.Integer()::get); - show(a5); - Integer[] a5b = - Stream.generate(new Rand.Integer()) - .limit(SZ + 1).toArray(Integer[]::new); - show(a5b); - a5b = new Rand.Integer().array(SZ + 2); - show(a5b); - a5 = IntStream.generate(new Rand.Pint()) - .limit(SZ + 1).toArray(); - show(a5); - a5 = new Rand.Pint().array(SZ + 3); - show(a5); - - System.out.println("Long"); - long[] a6 = new long[SZ]; - Arrays.setAll(a6, new Rand.Long()::get); - show(a6); - Long[] a6b = Stream.generate(new Rand.Long()) - .limit(SZ + 1).toArray(Long[]::new); - show(a6b); - a6b = new Rand.Long().array(SZ + 2); - show(a6b); - a6 = LongStream.generate(new Rand.Plong()) - .limit(SZ + 1).toArray(); - show(a6); - a6 = new Rand.Plong().array(SZ + 3); - show(a6); - - System.out.println("Float"); - Float[] a7 = new Float[SZ]; - Arrays.setAll(a7, new Rand.Float()::get); - show(a7); - a7 = Stream.generate(new Rand.Float()) - .limit(SZ + 1).toArray(Float[]::new); - show(a7); - a7 = new Rand.Float().array(SZ + 2); - show(a7); - float[] a7b = new Rand.Pfloat().array(SZ + 3); - show(a7b); - - System.out.println("Double"); - double[] a8 = new double[SZ]; - Arrays.setAll(a8, new Rand.Double()::get); - show(a8); - Double[] a8b = - Stream.generate(new Rand.Double()) - .limit(SZ + 1).toArray(Double[]::new); - show(a8b); - a8b = new Rand.Double().array(SZ + 2); - show(a8b); - a8 = DoubleStream.generate(new Rand.Pdouble()) - .limit(SZ + 1).toArray(); - show(a8); - a8 = new Rand.Pdouble().array(SZ + 3); - show(a8); - - System.out.println("String"); - String[] s = new String[SZ - 1]; - Arrays.setAll(s, new Rand.String()::get); - show(s); - s = Stream.generate(new Rand.String()) - .limit(SZ).toArray(String[]::new); - show(s); - s = new Rand.String().array(SZ + 1); - show(s); - - Arrays.setAll(s, new Rand.String(4)::get); - show(s); - s = Stream.generate(new Rand.String(4)) - .limit(SZ).toArray(String[]::new); - show(s); - s = new Rand.String(4).array(SZ + 1); - show(s); - } -} -/* Output: -Boolean -[true, false, true, true, true] -[true, false, true, true, true, false] -[true, false, true, true, true, false, false] -[true, false, true, true, true, false, false, true] -Byte -[123, 33, 101, 112, 33] -[123, 33, 101, 112, 33, 31] -[123, 33, 101, 112, 33, 31, 0] -[123, 33, 101, 112, 33, 31, 0, -72] -Character -[b, t, p, e, n] -[b, t, p, e, n, p] -[b, t, p, e, n, p, c] -[b, t, p, e, n, p, c, c] -Short -[635, 8737, 3941, 4720, 6177] -[635, 8737, 3941, 4720, 6177, 8479] -[635, 8737, 3941, 4720, 6177, 8479, 6656] -[635, 8737, 3941, 4720, 6177, 8479, 6656, 3768] -Integer -[635, 8737, 3941, 4720, 6177] -[635, 8737, 3941, 4720, 6177, 8479] -[635, 8737, 3941, 4720, 6177, 8479, 6656] -[635, 8737, 3941, 4720, 6177, 8479] -[635, 8737, 3941, 4720, 6177, 8479, 6656, 3768] -Long -[6882, 3765, 692, 9575, 4439] -[6882, 3765, 692, 9575, 4439, 2638] -[6882, 3765, 692, 9575, 4439, 2638, 4011] -[6882, 3765, 692, 9575, 4439, 2638] -[6882, 3765, 692, 9575, 4439, 2638, 4011, 9610] -Float -[4.83, 2.89, 2.9, 1.97, 3.01] -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18] -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99] -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99, 8.28] -Double -[4.83, 2.89, 2.9, 1.97, 3.01] -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18] -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99] -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18] -[4.83, 2.89, 2.9, 1.97, 3.01, 0.18, 0.99, 8.28] -String -[btpenpc, cuxszgv, gmeinne, eloztdv] -[btpenpc, cuxszgv, gmeinne, eloztdv, ewcippc] -[btpenpc, cuxszgv, gmeinne, eloztdv, ewcippc, ygpoalk] -[btpe, npcc, uxsz, gvgm, einn, eelo] -[btpe, npcc, uxsz, gvgm, einn] -[btpe, npcc, uxsz, gvgm, einn, eelo] -*/ diff --git a/code/arrays/ThreeDWithNew.java b/code/arrays/ThreeDWithNew.java deleted file mode 100644 index 7aaef069..00000000 --- a/code/arrays/ThreeDWithNew.java +++ /dev/null @@ -1,17 +0,0 @@ -// arrays/ThreeDWithNew.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ThreeDWithNew { - public static void main(String[] args) { - // 3-D array with fixed length: - int[][][] a = new int[2][2][4]; - System.out.println(Arrays.deepToString(a)); - } -} -/* Output: -[[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, -0]]] -*/ diff --git a/code/arrays/jmh/ParallelSort.java b/code/arrays/jmh/ParallelSort.java deleted file mode 100644 index fe0b505b..00000000 --- a/code/arrays/jmh/ParallelSort.java +++ /dev/null @@ -1,25 +0,0 @@ -// arrays/jmh/ParallelSort.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package arrays.jmh; -import java.util.*; -import onjava.*; -import org.openjdk.jmh.annotations.*; - -@State(Scope.Thread) -public class ParallelSort { - private long[] la; - @Setup - public void setup() { - la = new Rand.Plong().array(100_000); - } - @Benchmark - public void sort() { - Arrays.sort(la); - } - @Benchmark - public void parallelSort() { - Arrays.parallelSort(la); - } -} diff --git a/code/build.gradle b/code/build.gradle deleted file mode 100644 index b4feb13d..00000000 --- a/code/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -buildscript { - repositories { - maven { - url 'https://plugins.gradle.org/m2/' - } - } - dependencies { - classpath 'me.champeau.gradle:jmh-gradle-plugin:0.5.2' - } -} - -apply plugin: 'com.mindviewinc.example-output-verification' - -subprojects { - apply from: "$rootProject.projectDir/gradle/java.gradle" - apply from: "$rootProject.projectDir/gradle/junit-jupiter.gradle" - apply from: "$rootProject.projectDir/gradle/jmh.gradle" - // apply from: "$rootProject.projectDir/gradle/checkstyle.gradle" - apply from: "$rootProject.projectDir/gradle/findbugs.gradle" - apply plugin: 'com.mindviewinc.tagging' -} - -apply from: 'gradle/subprojects.gradle' diff --git a/code/checkstyle.xml b/code/checkstyle.xml deleted file mode 100644 index aabea2c4..00000000 --- a/code/checkstyle.xml +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/code/chkstyle.bat b/code/chkstyle.bat deleted file mode 100644 index 24838fc0..00000000 --- a/code/chkstyle.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo run gradlew clean first! -gradlew checkstyleMain 1> checkstyleout.txt 2>&1 diff --git a/code/collections/AdapterMethodIdiom.java b/code/collections/AdapterMethodIdiom.java deleted file mode 100644 index a97abb41..00000000 --- a/code/collections/AdapterMethodIdiom.java +++ /dev/null @@ -1,48 +0,0 @@ -// collections/AdapterMethodIdiom.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The "Adapter Method" idiom uses for-in -// with additional kinds of Iterables -import java.util.*; - -class ReversibleArrayList extends ArrayList { - ReversibleArrayList(Collection c) { - super(c); - } - public Iterable reversed() { - return new Iterable() { - public Iterator iterator() { - return new Iterator() { - int current = size() - 1; - public boolean hasNext() { - return current > -1; - } - public T next() { return get(current--); } - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - }; - } - }; - } -} - -public class AdapterMethodIdiom { - public static void main(String[] args) { - ReversibleArrayList ral = - new ReversibleArrayList( - Arrays.asList("To be or not to be".split(" "))); - // Grabs the ordinary iterator via iterator(): - for(String s : ral) - System.out.print(s + " "); - System.out.println(); - // Hand it the Iterable of your choice - for(String s : ral.reversed()) - System.out.print(s + " "); - } -} -/* Output: -To be or not to be -be to not or be To -*/ diff --git a/code/collections/AddingGroups.java b/code/collections/AddingGroups.java deleted file mode 100644 index ecfc8a5a..00000000 --- a/code/collections/AddingGroups.java +++ /dev/null @@ -1,24 +0,0 @@ -// collections/AddingGroups.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Adding groups of elements to Collection objects -import java.util.*; - -public class AddingGroups { - public static void main(String[] args) { - Collection collection = - new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); - Integer[] moreInts = { 6, 7, 8, 9, 10 }; - collection.addAll(Arrays.asList(moreInts)); - // Runs significantly faster, but you can't - // construct a Collection this way: - Collections.addAll(collection, 11, 12, 13, 14, 15); - Collections.addAll(collection, moreInts); - // Produces a list "backed by" an array: - List list = Arrays.asList(16,17,18,19,20); - list.set(1, 99); // OK -- modify an element - // list.add(21); // Runtime error; the underlying - // array cannot be resized. - } -} diff --git a/code/collections/ApplesAndOrangesWithGenerics.java b/code/collections/ApplesAndOrangesWithGenerics.java deleted file mode 100644 index c251672c..00000000 --- a/code/collections/ApplesAndOrangesWithGenerics.java +++ /dev/null @@ -1,23 +0,0 @@ -// collections/ApplesAndOrangesWithGenerics.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ApplesAndOrangesWithGenerics { - public static void main(String[] args) { - ArrayList apples = new ArrayList<>(); - for(int i = 0; i < 3; i++) - apples.add(new Apple()); - // Compile-time error: - // apples.add(new Orange()); - for(Apple apple : apples) { - System.out.println(apple.id()); - } - } -} -/* Output: -0 -1 -2 -*/ diff --git a/code/collections/ApplesAndOrangesWithoutGenerics.java b/code/collections/ApplesAndOrangesWithoutGenerics.java deleted file mode 100644 index 6afacd12..00000000 --- a/code/collections/ApplesAndOrangesWithoutGenerics.java +++ /dev/null @@ -1,38 +0,0 @@ -// collections/ApplesAndOrangesWithoutGenerics.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple collection use (suppressing compiler warnings) -// {ThrowsException} -import java.util.*; - -class Apple { - private static long counter; - private final long id = counter++; - public long id() { return id; } -} - -class Orange {} - -public class ApplesAndOrangesWithoutGenerics { - @SuppressWarnings("unchecked") - public static void main(String[] args) { - ArrayList apples = new ArrayList(); - for(int i = 0; i < 3; i++) - apples.add(new Apple()); - // No problem adding an Orange to apples: - apples.add(new Orange()); - for(Object apple : apples) { - ((Apple) apple).id(); - // Orange is detected only at run time - } - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "main" -java.lang.ClassCastException: Orange cannot be cast to -Apple - at ApplesAndOrangesWithoutGenerics.main(ApplesA -ndOrangesWithoutGenerics.java:23) -*/ diff --git a/code/collections/ArrayIsNotIterable.java b/code/collections/ArrayIsNotIterable.java deleted file mode 100644 index d496feb1..00000000 --- a/code/collections/ArrayIsNotIterable.java +++ /dev/null @@ -1,23 +0,0 @@ -// collections/ArrayIsNotIterable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ArrayIsNotIterable { - static void test(Iterable ib) { - for(T t : ib) - System.out.print(t + " "); - } - public static void main(String[] args) { - test(Arrays.asList(1, 2, 3)); - String[] strings = { "A", "B", "C" }; - // An array works in for-in, but it's not Iterable: - //- test(strings); - // You must explicitly convert it to an Iterable: - test(Arrays.asList(strings)); - } -} -/* Output: -1 2 3 A B C -*/ diff --git a/code/collections/AsListInference.java b/code/collections/AsListInference.java deleted file mode 100644 index ef813708..00000000 --- a/code/collections/AsListInference.java +++ /dev/null @@ -1,34 +0,0 @@ -// collections/AsListInference.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class Snow {} -class Powder extends Snow {} -class Light extends Powder {} -class Heavy extends Powder {} -class Crusty extends Snow {} -class Slush extends Snow {} - -public class AsListInference { - public static void main(String[] args) { - List snow1 = Arrays.asList( - new Crusty(), new Slush(), new Powder()); - //- snow1.add(new Heavy()); // Exception - - List snow2 = Arrays.asList( - new Light(), new Heavy()); - //- snow2.add(new Slush()); // Exception - - List snow3 = new ArrayList<>(); - Collections.addAll(snow3, - new Light(), new Heavy(), new Powder()); - snow3.add(new Crusty()); - - // Hint with explicit type argument specification: - List snow4 = Arrays.asList( - new Light(), new Heavy(), new Slush()); - //- snow4.add(new Powder()); // Exception - } -} diff --git a/code/collections/CollectionDifferences.java b/code/collections/CollectionDifferences.java deleted file mode 100644 index 711f7bd7..00000000 --- a/code/collections/CollectionDifferences.java +++ /dev/null @@ -1,71 +0,0 @@ -// collections/CollectionDifferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; - -public class CollectionDifferences { - public static void main(String[] args) { - CollectionMethodDifferences.main(args); - } -} -/* Output: -Collection: [add, addAll, clear, contains, containsAll, -equals, forEach, hashCode, isEmpty, iterator, -parallelStream, remove, removeAll, removeIf, retainAll, -size, spliterator, stream, toArray] -Interfaces in Collection: [Iterable] -Set extends Collection, adds: [] -Interfaces in Set: [Collection] -HashSet extends Set, adds: [] -Interfaces in HashSet: [Set, Cloneable, Serializable] -LinkedHashSet extends HashSet, adds: [] -Interfaces in LinkedHashSet: [Set, Cloneable, -Serializable] -TreeSet extends Set, adds: [headSet, -descendingIterator, descendingSet, pollLast, subSet, -floor, tailSet, ceiling, last, lower, comparator, -pollFirst, first, higher] -Interfaces in TreeSet: [NavigableSet, Cloneable, -Serializable] -List extends Collection, adds: [replaceAll, get, -indexOf, subList, set, sort, lastIndexOf, listIterator] -Interfaces in List: [Collection] -ArrayList extends List, adds: [trimToSize, -ensureCapacity] -Interfaces in ArrayList: [List, RandomAccess, -Cloneable, Serializable] -LinkedList extends List, adds: [offerFirst, poll, -getLast, offer, getFirst, removeFirst, element, -removeLastOccurrence, peekFirst, peekLast, push, -pollFirst, removeFirstOccurrence, descendingIterator, -pollLast, removeLast, pop, addLast, peek, offerLast, -addFirst] -Interfaces in LinkedList: [List, Deque, Cloneable, -Serializable] -Queue extends Collection, adds: [poll, peek, offer, -element] -Interfaces in Queue: [Collection] -PriorityQueue extends Queue, adds: [comparator] -Interfaces in PriorityQueue: [Serializable] -Map: [clear, compute, computeIfAbsent, -computeIfPresent, containsKey, containsValue, entrySet, -equals, forEach, get, getOrDefault, hashCode, isEmpty, -keySet, merge, put, putAll, putIfAbsent, remove, -replace, replaceAll, size, values] -HashMap extends Map, adds: [] -Interfaces in HashMap: [Map, Cloneable, Serializable] -LinkedHashMap extends HashMap, adds: [] -Interfaces in LinkedHashMap: [Map] -SortedMap extends Map, adds: [lastKey, subMap, -comparator, firstKey, headMap, tailMap] -Interfaces in SortedMap: [Map] -TreeMap extends Map, adds: [descendingKeySet, -navigableKeySet, higherEntry, higherKey, floorKey, -subMap, ceilingKey, pollLastEntry, firstKey, lowerKey, -headMap, tailMap, lowerEntry, ceilingEntry, -descendingMap, pollFirstEntry, lastKey, firstEntry, -floorEntry, comparator, lastEntry] -Interfaces in TreeMap: [NavigableMap, Cloneable, -Serializable] -*/ diff --git a/code/collections/CollectionSequence.java b/code/collections/CollectionSequence.java deleted file mode 100644 index 6a12ed69..00000000 --- a/code/collections/CollectionSequence.java +++ /dev/null @@ -1,40 +0,0 @@ -// collections/CollectionSequence.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class CollectionSequence -extends AbstractCollection { - private Pet[] pets = Pets.array(8); - @Override - public int size() { return pets.length; } - @Override - public Iterator iterator() { - return new Iterator() { // [1] - private int index = 0; - @Override - public boolean hasNext() { - return index < pets.length; - } - @Override - public Pet next() { return pets[index++]; } - @Override - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - }; - } - public static void main(String[] args) { - CollectionSequence c = new CollectionSequence(); - InterfaceVsIterator.display(c); - InterfaceVsIterator.display(c.iterator()); - } -} -/* Output: -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -*/ diff --git a/code/collections/CrossCollectionIteration.java b/code/collections/CrossCollectionIteration.java deleted file mode 100644 index 99769fe2..00000000 --- a/code/collections/CrossCollectionIteration.java +++ /dev/null @@ -1,36 +0,0 @@ -// collections/CrossCollectionIteration.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class CrossCollectionIteration { - public static void display(Iterator it) { - while(it.hasNext()) { - Pet p = it.next(); - System.out.print(p.id() + ":" + p + " "); - } - System.out.println(); - } - public static void main(String[] args) { - List pets = Pets.list(8); - LinkedList petsLL = new LinkedList<>(pets); - HashSet petsHS = new HashSet<>(pets); - TreeSet petsTS = new TreeSet<>(pets); - display(pets.iterator()); - display(petsLL.iterator()); - display(petsHS.iterator()); - display(petsTS.iterator()); - } -} -/* Output: -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug -0:Rat -*/ diff --git a/code/collections/CrossCollectionIteration2.java b/code/collections/CrossCollectionIteration2.java deleted file mode 100644 index c7da143f..00000000 --- a/code/collections/CrossCollectionIteration2.java +++ /dev/null @@ -1,37 +0,0 @@ -// collections/CrossCollectionIteration2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class CrossCollectionIteration2 { - public static void display(Iterable ip) { - Iterator it = ip.iterator(); - while(it.hasNext()) { - Pet p = it.next(); - System.out.print(p.id() + ":" + p + " "); - } - System.out.println(); - } - public static void main(String[] args) { - List pets = Pets.list(8); - LinkedList petsLL = new LinkedList<>(pets); - HashSet petsHS = new HashSet<>(pets); - TreeSet petsTS = new TreeSet<>(pets); - display(pets); - display(petsLL); - display(petsHS); - display(petsTS); - } -} -/* Output: -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug -0:Rat -*/ diff --git a/code/collections/EnvironmentVariables.java b/code/collections/EnvironmentVariables.java deleted file mode 100644 index af89e5a2..00000000 --- a/code/collections/EnvironmentVariables.java +++ /dev/null @@ -1,15 +0,0 @@ -// collections/EnvironmentVariables.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.util.*; - -public class EnvironmentVariables { - public static void main(String[] args) { - for(Map.Entry entry: System.getenv().entrySet()) { - System.out.println(entry.getKey() + ": " + - entry.getValue()); - } - } -} diff --git a/code/collections/ForInCollections.java b/code/collections/ForInCollections.java deleted file mode 100644 index a8ddd792..00000000 --- a/code/collections/ForInCollections.java +++ /dev/null @@ -1,19 +0,0 @@ -// collections/ForInCollections.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// All collections work with for-in -import java.util.*; - -public class ForInCollections { - public static void main(String[] args) { - Collection cs = new LinkedList<>(); - Collections.addAll(cs, - "Take the long way home".split(" ")); - for(String s : cs) - System.out.print("'" + s + "' "); - } -} -/* Output: -'Take' 'the' 'long' 'way' 'home' -*/ diff --git a/code/collections/GenericsAndUpcasting.java b/code/collections/GenericsAndUpcasting.java deleted file mode 100644 index ed8d3f55..00000000 --- a/code/collections/GenericsAndUpcasting.java +++ /dev/null @@ -1,28 +0,0 @@ -// collections/GenericsAndUpcasting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class GrannySmith extends Apple {} -class Gala extends Apple {} -class Fuji extends Apple {} -class Braeburn extends Apple {} - -public class GenericsAndUpcasting { - public static void main(String[] args) { - ArrayList apples = new ArrayList<>(); - apples.add(new GrannySmith()); - apples.add(new Gala()); - apples.add(new Fuji()); - apples.add(new Braeburn()); - for(Apple apple : apples) - System.out.println(apple); - } -} -/* Output: -GrannySmith@15db9742 -Gala@6d06d69c -Fuji@7852e922 -Braeburn@4e25154f -*/ diff --git a/code/collections/InterfaceVsIterator.java b/code/collections/InterfaceVsIterator.java deleted file mode 100644 index b5a8663d..00000000 --- a/code/collections/InterfaceVsIterator.java +++ /dev/null @@ -1,55 +0,0 @@ -// collections/InterfaceVsIterator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class InterfaceVsIterator { - public static void display(Iterator it) { - while(it.hasNext()) { - Pet p = it.next(); - System.out.print(p.id() + ":" + p + " "); - } - System.out.println(); - } - public static void display(Collection pets) { - for(Pet p : pets) - System.out.print(p.id() + ":" + p + " "); - System.out.println(); - } - public static void main(String[] args) { - List petList = Pets.list(8); - Set petSet = new HashSet<>(petList); - Map petMap = new LinkedHashMap<>(); - String[] names = ("Ralph, Eric, Robin, Lacey, " + - "Britney, Sam, Spot, Fluffy").split(", "); - for(int i = 0; i < names.length; i++) - petMap.put(names[i], petList.get(i)); - display(petList); - display(petSet); - display(petList.iterator()); - display(petSet.iterator()); - System.out.println(petMap); - System.out.println(petMap.keySet()); - display(petMap.values()); - display(petMap.values().iterator()); - } -} -/* Output: -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -{Ralph=Rat, Eric=Manx, Robin=Cymric, Lacey=Mutt, -Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx} -[Ralph, Eric, Robin, Lacey, Britney, Sam, Spot, Fluffy] -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -*/ diff --git a/code/collections/IterableClass.java b/code/collections/IterableClass.java deleted file mode 100644 index 260edc7d..00000000 --- a/code/collections/IterableClass.java +++ /dev/null @@ -1,35 +0,0 @@ -// collections/IterableClass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Anything Iterable works with for-in -import java.util.*; - -public class IterableClass implements Iterable { - protected String[] words = ("And that is how " + - "we know the Earth to be banana-shaped." - ).split(" "); - @Override - public Iterator iterator() { - return new Iterator() { - private int index = 0; - @Override - public boolean hasNext() { - return index < words.length; - } - @Override - public String next() { return words[index++]; } - @Override - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - }; - } - public static void main(String[] args) { - for(String s : new IterableClass()) - System.out.print(s + " "); - } -} -/* Output: -And that is how we know the Earth to be banana-shaped. -*/ diff --git a/code/collections/LinkedListFeatures.java b/code/collections/LinkedListFeatures.java deleted file mode 100644 index 3c10ff4e..00000000 --- a/code/collections/LinkedListFeatures.java +++ /dev/null @@ -1,54 +0,0 @@ -// collections/LinkedListFeatures.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class LinkedListFeatures { - public static void main(String[] args) { - LinkedList pets = - new LinkedList<>(Pets.list(5)); - System.out.println(pets); - // Identical: - System.out.println( - "pets.getFirst(): " + pets.getFirst()); - System.out.println( - "pets.element(): " + pets.element()); - // Only differs in empty-list behavior: - System.out.println("pets.peek(): " + pets.peek()); - // Identical; remove and return the first element: - System.out.println( - "pets.remove(): " + pets.remove()); - System.out.println( - "pets.removeFirst(): " + pets.removeFirst()); - // Only differs in empty-list behavior: - System.out.println("pets.poll(): " + pets.poll()); - System.out.println(pets); - pets.addFirst(new Rat()); - System.out.println("After addFirst(): " + pets); - pets.offer(Pets.get()); - System.out.println("After offer(): " + pets); - pets.add(Pets.get()); - System.out.println("After add(): " + pets); - pets.addLast(new Hamster()); - System.out.println("After addLast(): " + pets); - System.out.println( - "pets.removeLast(): " + pets.removeLast()); - } -} -/* Output: -[Rat, Manx, Cymric, Mutt, Pug] -pets.getFirst(): Rat -pets.element(): Rat -pets.peek(): Rat -pets.remove(): Rat -pets.removeFirst(): Manx -pets.poll(): Cymric -[Mutt, Pug] -After addFirst(): [Rat, Mutt, Pug] -After offer(): [Rat, Mutt, Pug, Cymric] -After add(): [Rat, Mutt, Pug, Cymric, Pug] -After addLast(): [Rat, Mutt, Pug, Cymric, Pug, Hamster] -pets.removeLast(): Hamster -*/ diff --git a/code/collections/ListFeatures.java b/code/collections/ListFeatures.java deleted file mode 100644 index b4ee16ab..00000000 --- a/code/collections/ListFeatures.java +++ /dev/null @@ -1,93 +0,0 @@ -// collections/ListFeatures.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class ListFeatures { - public static void main(String[] args) { - Random rand = new Random(47); - List pets = Pets.list(7); - System.out.println("1: " + pets); - Hamster h = new Hamster(); - pets.add(h); // Automatically resizes - System.out.println("2: " + pets); - System.out.println("3: " + pets.contains(h)); - pets.remove(h); // Remove by object - Pet p = pets.get(2); - System.out.println( - "4: " + p + " " + pets.indexOf(p)); - Pet cymric = new Cymric(); - System.out.println("5: " + pets.indexOf(cymric)); - System.out.println("6: " + pets.remove(cymric)); - // Must be the exact object: - System.out.println("7: " + pets.remove(p)); - System.out.println("8: " + pets); - pets.add(3, new Mouse()); // Insert at an index - System.out.println("9: " + pets); - List sub = pets.subList(1, 4); - System.out.println("subList: " + sub); - System.out.println("10: " + pets.containsAll(sub)); - Collections.sort(sub); // In-place sort - System.out.println("sorted subList: " + sub); - // Order is not important in containsAll(): - System.out.println("11: " + pets.containsAll(sub)); - Collections.shuffle(sub, rand); // Mix it up - System.out.println("shuffled subList: " + sub); - System.out.println("12: " + pets.containsAll(sub)); - List copy = new ArrayList<>(pets); - sub = Arrays.asList(pets.get(1), pets.get(4)); - System.out.println("sub: " + sub); - copy.retainAll(sub); - System.out.println("13: " + copy); - copy = new ArrayList<>(pets); // Get a fresh copy - copy.remove(2); // Remove by index - System.out.println("14: " + copy); - copy.removeAll(sub); // Only removes exact objects - System.out.println("15: " + copy); - copy.set(1, new Mouse()); // Replace an element - System.out.println("16: " + copy); - copy.addAll(2, sub); // Insert a list in the middle - System.out.println("17: " + copy); - System.out.println("18: " + pets.isEmpty()); - pets.clear(); // Remove all elements - System.out.println("19: " + pets); - System.out.println("20: " + pets.isEmpty()); - pets.addAll(Pets.list(4)); - System.out.println("21: " + pets); - Object[] o = pets.toArray(); - System.out.println("22: " + o[3]); - Pet[] pa = pets.toArray(new Pet[0]); - System.out.println("23: " + pa[3].id()); - } -} -/* Output: -1: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug] -2: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Hamster] -3: true -4: Cymric 2 -5: -1 -6: false -7: true -8: [Rat, Manx, Mutt, Pug, Cymric, Pug] -9: [Rat, Manx, Mutt, Mouse, Pug, Cymric, Pug] -subList: [Manx, Mutt, Mouse] -10: true -sorted subList: [Manx, Mouse, Mutt] -11: true -shuffled subList: [Mouse, Manx, Mutt] -12: true -sub: [Mouse, Pug] -13: [Mouse, Pug] -14: [Rat, Mouse, Mutt, Pug, Cymric, Pug] -15: [Rat, Mutt, Cymric, Pug] -16: [Rat, Mouse, Cymric, Pug] -17: [Rat, Mouse, Mouse, Pug, Cymric, Pug] -18: false -19: [] -20: true -21: [Manx, Cymric, Rat, EgyptianMau] -22: EgyptianMau -23: 14 -*/ diff --git a/code/collections/ListIteration.java b/code/collections/ListIteration.java deleted file mode 100644 index 95d2786c..00000000 --- a/code/collections/ListIteration.java +++ /dev/null @@ -1,37 +0,0 @@ -// collections/ListIteration.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class ListIteration { - public static void main(String[] args) { - List pets = Pets.list(8); - ListIterator it = pets.listIterator(); - while(it.hasNext()) - System.out.print(it.next() + - ", " + it.nextIndex() + - ", " + it.previousIndex() + "; "); - System.out.println(); - // Backwards: - while(it.hasPrevious()) - System.out.print(it.previous().id() + " "); - System.out.println(); - System.out.println(pets); - it = pets.listIterator(3); - while(it.hasNext()) { - it.next(); - it.set(Pets.get()); - } - System.out.println(pets); - } -} -/* Output: -Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug, -5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7; -7 6 5 4 3 2 1 0 -[Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Manx] -[Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster, -EgyptianMau] -*/ diff --git a/code/collections/MapOfList.java b/code/collections/MapOfList.java deleted file mode 100644 index 3a985dd9..00000000 --- a/code/collections/MapOfList.java +++ /dev/null @@ -1,65 +0,0 @@ -// collections/MapOfList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java collections.MapOfList} -package collections; -import typeinfo.pets.*; -import java.util.*; - -public class MapOfList { - public static final Map> - petPeople = new HashMap<>(); - static { - petPeople.put(new Person("Dawn"), - Arrays.asList( - new Cymric("Molly"), - new Mutt("Spot"))); - petPeople.put(new Person("Kate"), - Arrays.asList(new Cat("Shackleton"), - new Cat("Elsie May"), new Dog("Margrett"))); - petPeople.put(new Person("Marilyn"), - Arrays.asList( - new Pug("Louie aka Louis Snorkelstein Dupree"), - new Cat("Stanford"), - new Cat("Pinkola"))); - petPeople.put(new Person("Luke"), - Arrays.asList( - new Rat("Fuzzy"), new Rat("Fizzy"))); - petPeople.put(new Person("Isaac"), - Arrays.asList(new Rat("Freckly"))); - } - public static void main(String[] args) { - System.out.println("People: " + petPeople.keySet()); - System.out.println("Pets: " + petPeople.values()); - for(Person person : petPeople.keySet()) { - System.out.println(person + " has:"); - for(Pet pet : petPeople.get(person)) - System.out.println(" " + pet); - } - } -} -/* Output: -People: [Person Dawn, Person Kate, Person Isaac, Person -Marilyn, Person Luke] -Pets: [[Cymric Molly, Mutt Spot], [Cat Shackleton, Cat -Elsie May, Dog Margrett], [Rat Freckly], [Pug Louie aka -Louis Snorkelstein Dupree, Cat Stanford, Cat Pinkola], -[Rat Fuzzy, Rat Fizzy]] -Person Dawn has: - Cymric Molly - Mutt Spot -Person Kate has: - Cat Shackleton - Cat Elsie May - Dog Margrett -Person Isaac has: - Rat Freckly -Person Marilyn has: - Pug Louie aka Louis Snorkelstein Dupree - Cat Stanford - Cat Pinkola -Person Luke has: - Rat Fuzzy - Rat Fizzy -*/ diff --git a/code/collections/ModifyingArraysAsList.java b/code/collections/ModifyingArraysAsList.java deleted file mode 100644 index fea3da42..00000000 --- a/code/collections/ModifyingArraysAsList.java +++ /dev/null @@ -1,32 +0,0 @@ -// collections/ModifyingArraysAsList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ModifyingArraysAsList { - public static void main(String[] args) { - Random rand = new Random(47); - Integer[] ia = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - List list1 = - new ArrayList<>(Arrays.asList(ia)); - System.out.println("Before shuffling: " + list1); - Collections.shuffle(list1, rand); - System.out.println("After shuffling: " + list1); - System.out.println("array: " + Arrays.toString(ia)); - - List list2 = Arrays.asList(ia); - System.out.println("Before shuffling: " + list2); - Collections.shuffle(list2, rand); - System.out.println("After shuffling: " + list2); - System.out.println("array: " + Arrays.toString(ia)); - } -} -/* Output: -Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -After shuffling: [4, 6, 3, 1, 8, 7, 2, 5, 10, 9] -array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -After shuffling: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8] -array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8] -*/ diff --git a/code/collections/MultiIterableClass.java b/code/collections/MultiIterableClass.java deleted file mode 100644 index 1d7376e5..00000000 --- a/code/collections/MultiIterableClass.java +++ /dev/null @@ -1,53 +0,0 @@ -// collections/MultiIterableClass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Adding several Adapter Methods -import java.util.*; - -public class MultiIterableClass extends IterableClass { - public Iterable reversed() { - return new Iterable() { - public Iterator iterator() { - return new Iterator() { - int current = words.length - 1; - public boolean hasNext() { - return current > -1; - } - public String next() { - return words[current--]; - } - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - }; - } - }; - } - public Iterable randomized() { - return new Iterable() { - public Iterator iterator() { - List shuffled = - new ArrayList(Arrays.asList(words)); - Collections.shuffle(shuffled, new Random(47)); - return shuffled.iterator(); - } - }; - } - public static void main(String[] args) { - MultiIterableClass mic = new MultiIterableClass(); - for(String s : mic.reversed()) - System.out.print(s + " "); - System.out.println(); - for(String s : mic.randomized()) - System.out.print(s + " "); - System.out.println(); - for(String s : mic) - System.out.print(s + " "); - } -} -/* Output: -banana-shaped. be to Earth the know we how is that And -is banana-shaped. Earth that how the be And we know to -And that is how we know the Earth to be banana-shaped. -*/ diff --git a/code/collections/NonCollectionSequence.java b/code/collections/NonCollectionSequence.java deleted file mode 100644 index ed1ae6f6..00000000 --- a/code/collections/NonCollectionSequence.java +++ /dev/null @@ -1,37 +0,0 @@ -// collections/NonCollectionSequence.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -class PetSequence { - protected Pet[] pets = Pets.array(8); -} - -public class NonCollectionSequence extends PetSequence { - public Iterator iterator() { - return new Iterator() { - private int index = 0; - @Override - public boolean hasNext() { - return index < pets.length; - } - @Override - public Pet next() { return pets[index++]; } - @Override - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - }; - } - public static void main(String[] args) { - NonCollectionSequence nc = - new NonCollectionSequence(); - InterfaceVsIterator.display(nc.iterator()); - } -} -/* Output: -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx -*/ diff --git a/code/collections/PetMap.java b/code/collections/PetMap.java deleted file mode 100644 index 18d02ef0..00000000 --- a/code/collections/PetMap.java +++ /dev/null @@ -1,27 +0,0 @@ -// collections/PetMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class PetMap { - public static void main(String[] args) { - Map petMap = new HashMap<>(); - petMap.put("My Cat", new Cat("Molly")); - petMap.put("My Dog", new Dog("Ginger")); - petMap.put("My Hamster", new Hamster("Bosco")); - System.out.println(petMap); - Pet dog = petMap.get("My Dog"); - System.out.println(dog); - System.out.println(petMap.containsKey("My Dog")); - System.out.println(petMap.containsValue(dog)); - } -} -/* Output: -{My Dog=Dog Ginger, My Cat=Cat Molly, My -Hamster=Hamster Bosco} -Dog Ginger -true -true -*/ diff --git a/code/collections/PrintingCollections.java b/code/collections/PrintingCollections.java deleted file mode 100644 index c5746fc3..00000000 --- a/code/collections/PrintingCollections.java +++ /dev/null @@ -1,44 +0,0 @@ -// collections/PrintingCollections.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Collections print themselves automatically -import java.util.*; - -public class PrintingCollections { - static Collection - fill(Collection collection) { - collection.add("rat"); - collection.add("cat"); - collection.add("dog"); - collection.add("dog"); - return collection; - } - static Map fill(Map map) { - map.put("rat", "Fuzzy"); - map.put("cat", "Rags"); - map.put("dog", "Bosco"); - map.put("dog", "Spot"); - return map; - } - public static void main(String[] args) { - System.out.println(fill(new ArrayList<>())); - System.out.println(fill(new LinkedList<>())); - System.out.println(fill(new HashSet<>())); - System.out.println(fill(new TreeSet<>())); - System.out.println(fill(new LinkedHashSet<>())); - System.out.println(fill(new HashMap<>())); - System.out.println(fill(new TreeMap<>())); - System.out.println(fill(new LinkedHashMap<>())); - } -} -/* Output: -[rat, cat, dog, dog] -[rat, cat, dog, dog] -[rat, cat, dog] -[cat, dog, rat] -[rat, cat, dog] -{rat=Fuzzy, cat=Rags, dog=Spot} -{cat=Rags, dog=Spot, rat=Fuzzy} -{rat=Fuzzy, cat=Rags, dog=Spot} -*/ diff --git a/code/collections/PriorityQueueDemo.java b/code/collections/PriorityQueueDemo.java deleted file mode 100644 index 4f71ab0e..00000000 --- a/code/collections/PriorityQueueDemo.java +++ /dev/null @@ -1,53 +0,0 @@ -// collections/PriorityQueueDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class PriorityQueueDemo { - public static void main(String[] args) { - PriorityQueue priorityQueue = - new PriorityQueue<>(); - Random rand = new Random(47); - for(int i = 0; i < 10; i++) - priorityQueue.offer(rand.nextInt(i + 10)); - QueueDemo.printQ(priorityQueue); - - List ints = Arrays.asList(25, 22, 20, - 18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25); - priorityQueue = new PriorityQueue<>(ints); - QueueDemo.printQ(priorityQueue); - priorityQueue = new PriorityQueue<>( - ints.size(), Collections.reverseOrder()); - priorityQueue.addAll(ints); - QueueDemo.printQ(priorityQueue); - - String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION"; - List strings = - Arrays.asList(fact.split("")); - PriorityQueue stringPQ = - new PriorityQueue<>(strings); - QueueDemo.printQ(stringPQ); - stringPQ = new PriorityQueue<>( - strings.size(), Collections.reverseOrder()); - stringPQ.addAll(strings); - QueueDemo.printQ(stringPQ); - - Set charSet = new HashSet<>(); - for(char c : fact.toCharArray()) - charSet.add(c); // Autoboxing - PriorityQueue characterPQ = - new PriorityQueue<>(charSet); - QueueDemo.printQ(characterPQ); - } -} -/* Output: -0 1 1 1 1 1 3 5 8 14 -1 1 2 3 3 9 9 14 14 18 18 20 21 22 23 25 25 -25 25 23 22 21 20 18 18 14 14 9 9 3 3 2 1 1 - A A B C C C D D E E E F H H I I L N N O O O O S S -S T T U U U W -W U U U T T S S S O O O O N N L I I H H F E E E D D C C -C B A A - A B C D E F H I L N O S T U W -*/ diff --git a/code/collections/QueueDemo.java b/code/collections/QueueDemo.java deleted file mode 100644 index f807e89a..00000000 --- a/code/collections/QueueDemo.java +++ /dev/null @@ -1,29 +0,0 @@ -// collections/QueueDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Upcasting to a Queue from a LinkedList -import java.util.*; - -public class QueueDemo { - public static void printQ(Queue queue) { - while(queue.peek() != null) - System.out.print(queue.remove() + " "); - System.out.println(); - } - public static void main(String[] args) { - Queue queue = new LinkedList<>(); - Random rand = new Random(47); - for(int i = 0; i < 10; i++) - queue.offer(rand.nextInt(i + 10)); - printQ(queue); - Queue qc = new LinkedList<>(); - for(char c : "Brontosaurus".toCharArray()) - qc.offer(c); - printQ(qc); - } -} -/* Output: -8 1 1 1 5 14 3 1 0 1 -B r o n t o s a u r u s -*/ diff --git a/code/collections/SetOfInteger.java b/code/collections/SetOfInteger.java deleted file mode 100644 index 78157d5c..00000000 --- a/code/collections/SetOfInteger.java +++ /dev/null @@ -1,19 +0,0 @@ -// collections/SetOfInteger.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SetOfInteger { - public static void main(String[] args) { - Random rand = new Random(47); - Set intset = new HashSet<>(); - for(int i = 0; i < 10000; i++) - intset.add(rand.nextInt(30)); - System.out.println(intset); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] -*/ diff --git a/code/collections/SetOfString.java b/code/collections/SetOfString.java deleted file mode 100644 index 01d9455e..00000000 --- a/code/collections/SetOfString.java +++ /dev/null @@ -1,25 +0,0 @@ -// collections/SetOfString.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SetOfString { - public static void main(String[] args) { - Set colors = new HashSet<>(); - for(int i = 0; i < 100; i++) { - colors.add("Yellow"); - colors.add("Blue"); - colors.add("Red"); - colors.add("Red"); - colors.add("Orange"); - colors.add("Yellow"); - colors.add("Blue"); - colors.add("Purple"); - } - System.out.println(colors); - } -} -/* Output: -[Red, Yellow, Blue, Purple, Orange] -*/ diff --git a/code/collections/SetOperations.java b/code/collections/SetOperations.java deleted file mode 100644 index f716f965..00000000 --- a/code/collections/SetOperations.java +++ /dev/null @@ -1,40 +0,0 @@ -// collections/SetOperations.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SetOperations { - public static void main(String[] args) { - Set set1 = new HashSet<>(); - Collections.addAll(set1, - "A B C D E F G H I J K L".split(" ")); - set1.add("M"); - System.out.println("H: " + set1.contains("H")); - System.out.println("N: " + set1.contains("N")); - Set set2 = new HashSet<>(); - Collections.addAll(set2, "H I J K L".split(" ")); - System.out.println( - "set2 in set1: " + set1.containsAll(set2)); - set1.remove("H"); - System.out.println("set1: " + set1); - System.out.println( - "set2 in set1: " + set1.containsAll(set2)); - set1.removeAll(set2); - System.out.println( - "set2 removed from set1: " + set1); - Collections.addAll(set1, "X Y Z".split(" ")); - System.out.println( - "'X Y Z' added to set1: " + set1); - } -} -/* Output: -H: true -N: false -set2 in set1: true -set1: [A, B, C, D, E, F, G, I, J, K, L, M] -set2 in set1: false -set2 removed from set1: [A, B, C, D, E, F, G, M] -'X Y Z' added to set1: [A, B, C, D, E, F, G, M, X, Y, -Z] -*/ diff --git a/code/collections/SimpleCollection.java b/code/collections/SimpleCollection.java deleted file mode 100644 index 8915e259..00000000 --- a/code/collections/SimpleCollection.java +++ /dev/null @@ -1,18 +0,0 @@ -// collections/SimpleCollection.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SimpleCollection { - public static void main(String[] args) { - Collection c = new ArrayList<>(); - for(int i = 0; i < 10; i++) - c.add(i); // Autoboxing - for(Integer i : c) - System.out.print(i + ", "); - } -} -/* Output: -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -*/ diff --git a/code/collections/SimpleIteration.java b/code/collections/SimpleIteration.java deleted file mode 100644 index a65a2a71..00000000 --- a/code/collections/SimpleIteration.java +++ /dev/null @@ -1,36 +0,0 @@ -// collections/SimpleIteration.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import java.util.*; - -public class SimpleIteration { - public static void main(String[] args) { - List pets = Pets.list(12); - Iterator it = pets.iterator(); - while(it.hasNext()) { - Pet p = it.next(); - System.out.print(p.id() + ":" + p + " "); - } - System.out.println(); - // A simpler approach, when possible: - for(Pet p : pets) - System.out.print(p.id() + ":" + p + " "); - System.out.println(); - // An Iterator can also remove elements: - it = pets.iterator(); - for(int i = 0; i < 6; i++) { - it.next(); - it.remove(); - } - System.out.println(pets); - } -} -/* Output: -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster -0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug -7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster -[Pug, Manx, Cymric, Rat, EgyptianMau, Hamster] -*/ diff --git a/code/collections/SortedSetOfString.java b/code/collections/SortedSetOfString.java deleted file mode 100644 index a043b791..00000000 --- a/code/collections/SortedSetOfString.java +++ /dev/null @@ -1,25 +0,0 @@ -// collections/SortedSetOfString.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SortedSetOfString { - public static void main(String[] args) { - Set colors = new TreeSet<>(); - for(int i = 0; i < 100; i++) { - colors.add("Yellow"); - colors.add("Blue"); - colors.add("Red"); - colors.add("Red"); - colors.add("Orange"); - colors.add("Yellow"); - colors.add("Blue"); - colors.add("Purple"); - } - System.out.println(colors); - } -} -/* Output: -[Blue, Orange, Purple, Red, Yellow] -*/ diff --git a/code/collections/StackCollision.java b/code/collections/StackCollision.java deleted file mode 100644 index 67ee4d90..00000000 --- a/code/collections/StackCollision.java +++ /dev/null @@ -1,25 +0,0 @@ -// collections/StackCollision.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class StackCollision { - public static void main(String[] args) { - onjava.Stack stack = new onjava.Stack<>(); - for(String s : "My dog has fleas".split(" ")) - stack.push(s); - while(!stack.isEmpty()) - System.out.print(stack.pop() + " "); - System.out.println(); - java.util.Stack stack2 = - new java.util.Stack<>(); - for(String s : "My dog has fleas".split(" ")) - stack2.push(s); - while(!stack2.empty()) - System.out.print(stack2.pop() + " "); - } -} -/* Output: -fleas has dog My -fleas has dog My -*/ diff --git a/code/collections/StackTest.java b/code/collections/StackTest.java deleted file mode 100644 index dc1663cc..00000000 --- a/code/collections/StackTest.java +++ /dev/null @@ -1,18 +0,0 @@ -// collections/StackTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class StackTest { - public static void main(String[] args) { - Deque stack = new ArrayDeque<>(); - for(String s : "My dog has fleas".split(" ")) - stack.push(s); - while(!stack.isEmpty()) - System.out.print(stack.pop() + " "); - } -} -/* Output: -fleas has dog My -*/ diff --git a/code/collections/StackTest2.java b/code/collections/StackTest2.java deleted file mode 100644 index 2464d7a9..00000000 --- a/code/collections/StackTest2.java +++ /dev/null @@ -1,18 +0,0 @@ -// collections/StackTest2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; - -public class StackTest2 { - public static void main(String[] args) { - Stack stack = new Stack<>(); - for(String s : "My dog has fleas".split(" ")) - stack.push(s); - while(!stack.isEmpty()) - System.out.print(stack.pop() + " "); - } -} -/* Output: -fleas has dog My -*/ diff --git a/code/collections/Statistics.java b/code/collections/Statistics.java deleted file mode 100644 index f888db58..00000000 --- a/code/collections/Statistics.java +++ /dev/null @@ -1,25 +0,0 @@ -// collections/Statistics.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple demonstration of HashMap -import java.util.*; - -public class Statistics { - public static void main(String[] args) { - Random rand = new Random(47); - Map m = new HashMap<>(); - for(int i = 0; i < 10000; i++) { - // Produce a number between 0 and 20: - int r = rand.nextInt(20); - Integer freq = m.get(r); // [1] - m.put(r, freq == null ? 1 : freq + 1); - } - System.out.println(m); - } -} -/* Output: -{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, -7=471, 8=468, 9=549, 10=513, 11=531, 12=521, 13=506, -14=477, 15=497, 16=533, 17=509, 18=478, 19=464} -*/ diff --git a/code/collections/UniqueWords.java b/code/collections/UniqueWords.java deleted file mode 100644 index c6c3681d..00000000 --- a/code/collections/UniqueWords.java +++ /dev/null @@ -1,29 +0,0 @@ -// collections/UniqueWords.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.nio.file.*; - -public class UniqueWords { - public static void - main(String[] args) throws Exception { - List lines = Files.readAllLines( - Paths.get("SetOperations.java")); - Set words = new TreeSet<>(); - for(String line : lines) - for(String word : line.split("\\W+")) - if(word.trim().length() > 0) - words.add(word); - System.out.println(words); - } -} -/* Output: -[A, B, C, Collections, D, E, F, G, H, HashSet, I, J, K, -L, M, N, Output, Set, SetOperations, String, System, X, -Y, Z, add, addAll, added, args, class, collections, -contains, containsAll, false, from, import, in, java, -main, new, out, println, public, remove, removeAll, -removed, set1, set2, split, static, to, true, util, -void] -*/ diff --git a/code/collections/UniqueWordsAlphabetic.java b/code/collections/UniqueWordsAlphabetic.java deleted file mode 100644 index 66a7fecf..00000000 --- a/code/collections/UniqueWordsAlphabetic.java +++ /dev/null @@ -1,30 +0,0 @@ -// collections/UniqueWordsAlphabetic.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Producing an alphabetic listing -import java.util.*; -import java.nio.file.*; - -public class UniqueWordsAlphabetic { - public static void - main(String[] args) throws Exception { - List lines = Files.readAllLines( - Paths.get("SetOperations.java")); - Set words = - new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - for(String line : lines) - for(String word : line.split("\\W+")) - if(word.trim().length() > 0) - words.add(word); - System.out.println(words); - } -} -/* Output: -[A, add, addAll, added, args, B, C, class, collections, -contains, containsAll, D, E, F, false, from, G, H, -HashSet, I, import, in, J, java, K, L, M, main, N, new, -out, Output, println, public, remove, removeAll, -removed, Set, set1, set2, SetOperations, split, static, -String, System, to, true, util, void, X, Y, Z] -*/ diff --git a/code/collectiontopics/AssociativeArray.java b/code/collectiontopics/AssociativeArray.java deleted file mode 100644 index e7488489..00000000 --- a/code/collectiontopics/AssociativeArray.java +++ /dev/null @@ -1,64 +0,0 @@ -// collectiontopics/AssociativeArray.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Associates keys with values - -public class AssociativeArray { - private Object[][] pairs; - private int index; - public AssociativeArray(int length) { - pairs = new Object[length][2]; - } - public void put(K key, V value) { - if(index >= pairs.length) - throw new ArrayIndexOutOfBoundsException(); - pairs[index++] = new Object[]{ key, value }; - } - @SuppressWarnings("unchecked") - public V get(K key) { - for(int i = 0; i < index; i++) - if(key.equals(pairs[i][0])) - return (V)pairs[i][1]; - return null; // Did not find key - } - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for(int i = 0; i < index; i++) { - result.append(pairs[i][0].toString()); - result.append(" : "); - result.append(pairs[i][1].toString()); - if(i < index - 1) - result.append("\n"); - } - return result.toString(); - } - public static void main(String[] args) { - AssociativeArray map = - new AssociativeArray<>(6); - map.put("sky", "blue"); - map.put("grass", "green"); - map.put("ocean", "dancing"); - map.put("tree", "tall"); - map.put("earth", "brown"); - map.put("sun", "warm"); - try { - map.put("extra", "object"); // Past the end - } catch(ArrayIndexOutOfBoundsException e) { - System.out.println("Too many objects!"); - } - System.out.println(map); - System.out.println(map.get("ocean")); - } -} -/* Output: -Too many objects! -sky : blue -grass : green -ocean : dancing -tree : tall -earth : brown -sun : warm -dancing -*/ diff --git a/code/collectiontopics/Bits.java b/code/collectiontopics/Bits.java deleted file mode 100644 index 16afb361..00000000 --- a/code/collectiontopics/Bits.java +++ /dev/null @@ -1,79 +0,0 @@ -// collectiontopics/Bits.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of BitSet -import java.util.*; - -public class Bits { - public static void printBitSet(BitSet b) { - System.out.println("bits: " + b); - StringBuilder bbits = new StringBuilder(); - for(int j = 0; j < b.size() ; j++) - bbits.append(b.get(j) ? "1" : "0"); - System.out.println("bit pattern: " + bbits); - } - public static void main(String[] args) { - Random rand = new Random(47); - // Take the LSB of nextInt(): - byte bt = (byte)rand.nextInt(); - BitSet bb = new BitSet(); - for(int i = 7; i >= 0; i--) - if(((1 << i) & bt) != 0) - bb.set(i); - else - bb.clear(i); - System.out.println("byte value: " + bt); - printBitSet(bb); - - short st = (short)rand.nextInt(); - BitSet bs = new BitSet(); - for(int i = 15; i >= 0; i--) - if(((1 << i) & st) != 0) - bs.set(i); - else - bs.clear(i); - System.out.println("short value: " + st); - printBitSet(bs); - - int it = rand.nextInt(); - BitSet bi = new BitSet(); - for(int i = 31; i >= 0; i--) - if(((1 << i) & it) != 0) - bi.set(i); - else - bi.clear(i); - System.out.println("int value: " + it); - printBitSet(bi); - - // Test bitsets >= 64 bits: - BitSet b127 = new BitSet(); - b127.set(127); - System.out.println("set bit 127: " + b127); - BitSet b255 = new BitSet(65); - b255.set(255); - System.out.println("set bit 255: " + b255); - BitSet b1023 = new BitSet(512); - b1023.set(1023); - b1023.set(1024); - System.out.println("set bit 1023: " + b1023); - } -} -/* Output: -byte value: -107 -bits: {0, 2, 4, 7} -bit pattern: 101010010000000000000000000000000000000000 -0000000000000000000000 -short value: 1302 -bits: {1, 2, 4, 8, 10} -bit pattern: 011010001010000000000000000000000000000000 -0000000000000000000000 -int value: -2014573909 -bits: {0, 1, 3, 5, 7, 9, 11, 18, 19, 21, 22, 23, 24, -25, 26, 31} -bit pattern: 110101010101000000110111111000010000000000 -0000000000000000000000 -set bit 127: {127} -set bit 255: {255} -set bit 1023: {1023, 1024} -*/ diff --git a/code/collectiontopics/CanonicalMapping.java b/code/collectiontopics/CanonicalMapping.java deleted file mode 100644 index c02f9132..00000000 --- a/code/collectiontopics/CanonicalMapping.java +++ /dev/null @@ -1,56 +0,0 @@ -// collectiontopics/CanonicalMapping.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates WeakHashMap -import java.util.*; - -class Element { - private String ident; - Element(String id) { ident = id; } - @Override - public String toString() { return ident; } - @Override - public int hashCode() { - return Objects.hashCode(ident); - } - @Override - public boolean equals(Object r) { - return r instanceof Element && - Objects.equals(ident, ((Element)r).ident); - } - @SuppressWarnings("deprecation") - @Override - protected void finalize() { - System.out.println("Finalizing " + - getClass().getSimpleName() + " " + ident); - } -} - -class Key extends Element { - Key(String id) { super(id); } -} - -class Value extends Element { - Value(String id) { super(id); } -} - -public class CanonicalMapping { - public static void main(String[] args) { - int size = 1000; - // Or, choose size via the command line: - if(args.length > 0) - size = Integer.valueOf(args[0]); - Key[] keys = new Key[size]; - WeakHashMap map = - new WeakHashMap<>(); - for(int i = 0; i < size; i++) { - Key k = new Key(Integer.toString(i)); - Value v = new Value(Integer.toString(i)); - if(i % 3 == 0) - keys[i] = k; // Save as "real" references - map.put(k, v); - } - System.gc(); - } -} diff --git a/code/collectiontopics/CollectionMethods.java b/code/collectiontopics/CollectionMethods.java deleted file mode 100644 index e32e5982..00000000 --- a/code/collectiontopics/CollectionMethods.java +++ /dev/null @@ -1,135 +0,0 @@ -// collectiontopics/CollectionMethods.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Things you can do with all Collections -import java.util.*; -import static onjava.HTMLColors.*; - -public class CollectionMethods { - public static void main(String[] args) { - Collection c = - new ArrayList<>(LIST.subList(0, 4)); - c.add("ten"); - c.add("eleven"); - show(c); - border(); - // Make an array from the List: - Object[] array = c.toArray(); - // Make a String array from the List: - String[] str = c.toArray(new String[0]); - // Find max and min elements; this means - // different things depending on the way - // the Comparable interface is implemented: - System.out.println( - "Collections.max(c) = " + Collections.max(c)); - System.out.println( - "Collections.min(c) = " + Collections.min(c)); - border(); - // Add a Collection to another Collection - Collection c2 = - new ArrayList<>(LIST.subList(10, 14)); - c.addAll(c2); - show(c); - border(); - c.remove(LIST.get(0)); - show(c); - border(); - // Remove all components that are - // in the argument collection: - c.removeAll(c2); - show(c); - border(); - c.addAll(c2); - show(c); - border(); - // Is an element in this Collection? - String val = LIST.get(3); - System.out.println( - "c.contains(" + val + ") = " + c.contains(val)); - // Is a Collection in this Collection? - System.out.println( - "c.containsAll(c2) = " + c.containsAll(c2)); - Collection c3 = - ((List)c).subList(3, 5); - // Keep all the elements that are in both - // c2 and c3 (an intersection of sets): - c2.retainAll(c3); - show(c2); - // Throw away all the elements - // in c2 that also appear in c3: - c2.removeAll(c3); - System.out.println( - "c2.isEmpty() = " + c2.isEmpty()); - border(); - // Functional operation: - c = new ArrayList<>(LIST); - c.removeIf(s -> !s.startsWith("P")); - c.removeIf(s -> s.startsWith("Pale")); - // Stream operation: - c.stream().forEach(System.out::println); - c.clear(); // Remove all elements - System.out.println("after c.clear():" + c); - } -} -/* Output: -AliceBlue -AntiqueWhite -Aquamarine -Azure -ten -eleven -****************************** -Collections.max(c) = ten -Collections.min(c) = AliceBlue -****************************** -AliceBlue -AntiqueWhite -Aquamarine -Azure -ten -eleven -Brown -BurlyWood -CadetBlue -Chartreuse -****************************** -AntiqueWhite -Aquamarine -Azure -ten -eleven -Brown -BurlyWood -CadetBlue -Chartreuse -****************************** -AntiqueWhite -Aquamarine -Azure -ten -eleven -****************************** -AntiqueWhite -Aquamarine -Azure -ten -eleven -Brown -BurlyWood -CadetBlue -Chartreuse -****************************** -c.contains(Azure) = true -c.containsAll(c2) = true -c2.isEmpty() = true -****************************** -PapayaWhip -PeachPuff -Peru -Pink -Plum -PowderBlue -Purple -after c.clear():[] -*/ diff --git a/code/collectiontopics/Enumerations.java b/code/collectiontopics/Enumerations.java deleted file mode 100644 index 22b83e52..00000000 --- a/code/collectiontopics/Enumerations.java +++ /dev/null @@ -1,24 +0,0 @@ -// collectiontopics/Enumerations.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Java 1.0/1.1 Vector and Enumeration -import java.util.*; -import onjava.*; - -public class Enumerations { - public static void main(String[] args) { - Vector v = - new Vector<>(Countries.names(10)); - Enumeration e = v.elements(); - while(e.hasMoreElements()) - System.out.print(e.nextElement() + ", "); - // Produce an Enumeration from a Collection: - e = Collections.enumeration(new ArrayList<>()); - } -} -/* Output: -ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, -BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN -REPUBLIC, CHAD, -*/ diff --git a/code/collectiontopics/FailFast.java b/code/collectiontopics/FailFast.java deleted file mode 100644 index 0b0ce253..00000000 --- a/code/collectiontopics/FailFast.java +++ /dev/null @@ -1,22 +0,0 @@ -// collectiontopics/FailFast.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates the "fail-fast" behavior -import java.util.*; - -public class FailFast { - public static void main(String[] args) { - Collection c = new ArrayList<>(); - Iterator it = c.iterator(); - c.add("An object"); - try { - String s = it.next(); - } catch(ConcurrentModificationException e) { - System.out.println(e); - } - } -} -/* Output: -java.util.ConcurrentModificationException -*/ diff --git a/code/collectiontopics/FillMapTest.java b/code/collectiontopics/FillMapTest.java deleted file mode 100644 index 5cfd612b..00000000 --- a/code/collectiontopics/FillMapTest.java +++ /dev/null @@ -1,32 +0,0 @@ -// collectiontopics/FillMapTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import onjava.*; - -public class FillMapTest { - public static void main(String[] args) { - Map mcs = FillMap.basic( - new Rand.String(4), new Count.Integer(), 7); - System.out.println(mcs); - HashMap hashm = - FillMap.create(new Rand.String(4), - new Count.Integer(), HashMap::new, 7); - System.out.println(hashm); - LinkedHashMap linkm = - FillMap.create(new Rand.String(4), - new Count.Integer(), LinkedHashMap::new, 7); - System.out.println(linkm); - } -} -/* Output: -{npcc=1, ztdv=6, gvgm=3, btpe=0, einn=4, eelo=5, -uxsz=2} -{npcc=1, ztdv=6, gvgm=3, btpe=0, einn=4, eelo=5, -uxsz=2} -{btpe=0, npcc=1, uxsz=2, gvgm=3, einn=4, eelo=5, -ztdv=6} -*/ diff --git a/code/collectiontopics/FillingLists.java b/code/collectiontopics/FillingLists.java deleted file mode 100644 index 32bdb8ef..00000000 --- a/code/collectiontopics/FillingLists.java +++ /dev/null @@ -1,35 +0,0 @@ -// collectiontopics/FillingLists.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Collections.fill() & Collections.nCopies() -import java.util.*; - -class StringAddress { - private String s; - StringAddress(String s) { this.s = s; } - @Override - public String toString() { - return super.toString() + " " + s; - } -} - -public class FillingLists { - public static void main(String[] args) { - List list = new ArrayList<>( - Collections.nCopies(4, - new StringAddress("Hello"))); - System.out.println(list); - Collections.fill(list, - new StringAddress("World!")); - System.out.println(list); - } -} -/* Output: -[StringAddress@15db9742 Hello, StringAddress@15db9742 -Hello, StringAddress@15db9742 Hello, -StringAddress@15db9742 Hello] -[StringAddress@6d06d69c World!, StringAddress@6d06d69c -World!, StringAddress@6d06d69c World!, -StringAddress@6d06d69c World!] -*/ diff --git a/code/collectiontopics/FunctionalMap.java b/code/collectiontopics/FunctionalMap.java deleted file mode 100644 index 404a1a64..00000000 --- a/code/collectiontopics/FunctionalMap.java +++ /dev/null @@ -1,38 +0,0 @@ -// collectiontopics/FunctionalMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Functional operations on a Map -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import static onjava.HTMLColors.*; - -public class FunctionalMap { - public static void main(String[] args) { - MAP.entrySet().stream() - .map(Map.Entry::getValue) - .filter(v -> v.startsWith("Dark")) - .map(v -> v.replaceFirst("Dark", "Hot")) - .forEach(System.out::println); - } -} -/* Output: -HotBlue -HotCyan -HotGoldenRod -HotGray -HotGreen -HotKhaki -HotMagenta -HotOliveGreen -HotOrange -HotOrchid -HotRed -HotSalmon -HotSeaGreen -HotSlateBlue -HotSlateGray -HotTurquoise -HotViolet -*/ diff --git a/code/collectiontopics/HTMLColorTest.java b/code/collectiontopics/HTMLColorTest.java deleted file mode 100644 index 99037ced..00000000 --- a/code/collectiontopics/HTMLColorTest.java +++ /dev/null @@ -1,103 +0,0 @@ -// collectiontopics/HTMLColorTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import static onjava.HTMLColors.*; - -public class HTMLColorTest { - static final int DISPLAY_SIZE = 20; - public static void main(String[] args) { - show(MAP, DISPLAY_SIZE); - border(); - showInv(INVMAP, DISPLAY_SIZE); - border(); - show(LIST, DISPLAY_SIZE); - border(); - showrgb(RGBLIST, DISPLAY_SIZE); - } -} -/* Output: -0xF0F8FF: AliceBlue -0xFAEBD7: AntiqueWhite -0x7FFFD4: Aquamarine -0xF0FFFF: Azure -0xF5F5DC: Beige -0xFFE4C4: Bisque -0x000000: Black -0xFFEBCD: BlanchedAlmond -0x0000FF: Blue -0x8A2BE2: BlueViolet -0xA52A2A: Brown -0xDEB887: BurlyWood -0x5F9EA0: CadetBlue -0x7FFF00: Chartreuse -0xD2691E: Chocolate -0xFF7F50: Coral -0x6495ED: CornflowerBlue -0xFFF8DC: Cornsilk -0xDC143C: Crimson -0x00FFFF: Cyan -****************************** -AliceBlue 0xF0F8FF -AntiqueWhite 0xFAEBD7 -Aquamarine 0x7FFFD4 -Azure 0xF0FFFF -Beige 0xF5F5DC -Bisque 0xFFE4C4 -Black 0x000000 -BlanchedAlmond 0xFFEBCD -Blue 0x0000FF -BlueViolet 0x8A2BE2 -Brown 0xA52A2A -BurlyWood 0xDEB887 -CadetBlue 0x5F9EA0 -Chartreuse 0x7FFF00 -Chocolate 0xD2691E -Coral 0xFF7F50 -CornflowerBlue 0x6495ED -Cornsilk 0xFFF8DC -Crimson 0xDC143C -Cyan 0x00FFFF -****************************** -AliceBlue -AntiqueWhite -Aquamarine -Azure -Beige -Bisque -Black -BlanchedAlmond -Blue -BlueViolet -Brown -BurlyWood -CadetBlue -Chartreuse -Chocolate -Coral -CornflowerBlue -Cornsilk -Crimson -Cyan -****************************** -0xF0F8FF -0xFAEBD7 -0x7FFFD4 -0xF0FFFF -0xF5F5DC -0xFFE4C4 -0x000000 -0xFFEBCD -0x0000FF -0x8A2BE2 -0xA52A2A -0xDEB887 -0x5F9EA0 -0x7FFF00 -0xD2691E -0xFF7F50 -0x6495ED -0xFFF8DC -0xDC143C -0x00FFFF -*/ diff --git a/code/collectiontopics/LinkedHashMapDemo.java b/code/collectiontopics/LinkedHashMapDemo.java deleted file mode 100644 index d0b93393..00000000 --- a/code/collectiontopics/LinkedHashMapDemo.java +++ /dev/null @@ -1,31 +0,0 @@ -// collectiontopics/LinkedHashMapDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// What you can do with a LinkedHashMap -import java.util.*; -import onjava.*; - -public class LinkedHashMapDemo { - public static void main(String[] args) { - LinkedHashMap linkedMap = - new LinkedHashMap<>(new CountMap(9)); - System.out.println(linkedMap); - // Least-recently-used order: - linkedMap = - new LinkedHashMap<>(16, 0.75f, true); - linkedMap.putAll(new CountMap(9)); - System.out.println(linkedMap); - for(int i = 0; i < 6; i++) - linkedMap.get(i); - System.out.println(linkedMap); - linkedMap.get(0); - System.out.println(linkedMap); - } -} -/* Output: -{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0} -{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0} -{6=G0, 7=H0, 8=I0, 0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0} -{6=G0, 7=H0, 8=I0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 0=A0} -*/ diff --git a/code/collectiontopics/ListOps.java b/code/collectiontopics/ListOps.java deleted file mode 100644 index 824ffba9..00000000 --- a/code/collectiontopics/ListOps.java +++ /dev/null @@ -1,167 +0,0 @@ -// collectiontopics/ListOps.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Things you can do with Lists -import java.util.*; -import onjava.HTMLColors; - -public class ListOps { - // Create a short list for testing: - static final List LIST = - HTMLColors.LIST.subList(0, 10); - private static boolean b; - private static String s; - private static int i; - private static Iterator it; - private static ListIterator lit; - public static void basicTest(List a) { - a.add(1, "x"); // Add at location 1 - a.add("x"); // Add at end - // Add a collection: - a.addAll(LIST); - // Add a collection starting at location 3: - a.addAll(3, LIST); - b = a.contains("1"); // Is it in there? - // Is the entire collection in there? - b = a.containsAll(LIST); - // Lists allow random access, which is cheap - // for ArrayList, expensive for LinkedList: - s = a.get(1); // Get (typed) object at location 1 - i = a.indexOf("1"); // Tell index of object - b = a.isEmpty(); // Any elements inside? - it = a.iterator(); // Ordinary Iterator - lit = a.listIterator(); // ListIterator - lit = a.listIterator(3); // Start at location 3 - i = a.lastIndexOf("1"); // Last match - a.remove(1); // Remove location 1 - a.remove("3"); // Remove this object - a.set(1, "y"); // Set location 1 to "y" - // Keep everything that's in the argument - // (the intersection of the two sets): - a.retainAll(LIST); - // Remove everything that's in the argument: - a.removeAll(LIST); - i = a.size(); // How big is it? - a.clear(); // Remove all elements - } - public static void iterMotion(List a) { - ListIterator it = a.listIterator(); - b = it.hasNext(); - b = it.hasPrevious(); - s = it.next(); - i = it.nextIndex(); - s = it.previous(); - i = it.previousIndex(); - } - public static void iterManipulation(List a) { - ListIterator it = a.listIterator(); - it.add("47"); - // Must move to an element after add(): - it.next(); - // Remove the element after the new one: - it.remove(); - // Must move to an element after remove(): - it.next(); - // Change the element after the deleted one: - it.set("47"); - } - public static void testVisual(List a) { - System.out.println(a); - List b = LIST; - System.out.println("b = " + b); - a.addAll(b); - a.addAll(b); - System.out.println(a); - // Insert, remove, and replace elements - // using a ListIterator: - ListIterator x = - a.listIterator(a.size()/2); - x.add("one"); - System.out.println(a); - System.out.println(x.next()); - x.remove(); - System.out.println(x.next()); - x.set("47"); - System.out.println(a); - // Traverse the list backwards: - x = a.listIterator(a.size()); - while(x.hasPrevious()) - System.out.print(x.previous() + " "); - System.out.println(); - System.out.println("testVisual finished"); - } - // There are some things that only LinkedLists can do: - public static void testLinkedList() { - LinkedList ll = new LinkedList<>(); - ll.addAll(LIST); - System.out.println(ll); - // Treat it like a stack, pushing: - ll.addFirst("one"); - ll.addFirst("two"); - System.out.println(ll); - // Like "peeking" at the top of a stack: - System.out.println(ll.getFirst()); - // Like popping a stack: - System.out.println(ll.removeFirst()); - System.out.println(ll.removeFirst()); - // Treat it like a queue, pulling elements - // off the tail end: - System.out.println(ll.removeLast()); - System.out.println(ll); - } - public static void main(String[] args) { - // Make and fill a new list each time: - basicTest(new LinkedList<>(LIST)); - basicTest(new ArrayList<>(LIST)); - iterMotion(new LinkedList<>(LIST)); - iterMotion(new ArrayList<>(LIST)); - iterManipulation(new LinkedList<>(LIST)); - iterManipulation(new ArrayList<>(LIST)); - testVisual(new LinkedList<>(LIST)); - testLinkedList(); - } -} -/* Output: -[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet] -b = [AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet] -[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet, -AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet, -AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet] -[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet, -AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, one, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet, -AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet] -Bisque -Black -[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet, -AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, one, -47, BlanchedAlmond, Blue, BlueViolet, AliceBlue, -AntiqueWhite, Aquamarine, Azure, Beige, Bisque, Black, -BlanchedAlmond, Blue, BlueViolet] -BlueViolet Blue BlanchedAlmond Black Bisque Beige Azure -Aquamarine AntiqueWhite AliceBlue BlueViolet Blue -BlanchedAlmond 47 one Beige Azure Aquamarine -AntiqueWhite AliceBlue BlueViolet Blue BlanchedAlmond -Black Bisque Beige Azure Aquamarine AntiqueWhite -AliceBlue -testVisual finished -[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue, BlueViolet] -[two, one, AliceBlue, AntiqueWhite, Aquamarine, Azure, -Beige, Bisque, Black, BlanchedAlmond, Blue, BlueViolet] -two -two -one -BlueViolet -[AliceBlue, AntiqueWhite, Aquamarine, Azure, Beige, -Bisque, Black, BlanchedAlmond, Blue] -*/ diff --git a/code/collectiontopics/ListSortSearch.java b/code/collectiontopics/ListSortSearch.java deleted file mode 100644 index 4d1fbcf8..00000000 --- a/code/collectiontopics/ListSortSearch.java +++ /dev/null @@ -1,57 +0,0 @@ -// collectiontopics/ListSortSearch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Sorting/searching Lists with Collections utilities -import java.util.*; - -public class ListSortSearch { - public static void main(String[] args) { - List list = - new ArrayList<>(Utilities.list); - list.addAll(Utilities.list); - System.out.println(list); - Collections.shuffle(list, new Random(47)); - System.out.println("Shuffled: " + list); - // Use ListIterator to trim off last elements: - ListIterator it = list.listIterator(10); - while(it.hasNext()) { - it.next(); - it.remove(); - } - System.out.println("Trimmed: " + list); - Collections.sort(list); - System.out.println("Sorted: " + list); - String key = list.get(7); - int index = Collections.binarySearch(list, key); - System.out.println( - "Location of " + key + " is " + index + - ", list.get(" + index + ") = " + - list.get(index)); - Collections.sort(list, - String.CASE_INSENSITIVE_ORDER); - System.out.println( - "Case-insensitive sorted: " + list); - key = list.get(7); - index = Collections.binarySearch(list, key, - String.CASE_INSENSITIVE_ORDER); - System.out.println( - "Location of " + key + " is " + index + - ", list.get(" + index + ") = " + - list.get(index)); - } -} -/* Output: -[one, Two, three, Four, five, six, one, one, Two, -three, Four, five, six, one] -Shuffled: [Four, five, one, one, Two, six, six, three, -three, five, Four, Two, one, one] -Trimmed: [Four, five, one, one, Two, six, six, three, -three, five] -Sorted: [Four, Two, five, five, one, one, six, six, -three, three] -Location of six is 7, list.get(7) = six -Case-insensitive sorted: [five, five, Four, one, one, -six, six, three, three, Two] -Location of three is 7, list.get(7) = three -*/ diff --git a/code/collectiontopics/MapOps.java b/code/collectiontopics/MapOps.java deleted file mode 100644 index b214fa2d..00000000 --- a/code/collectiontopics/MapOps.java +++ /dev/null @@ -1,76 +0,0 @@ -// collectiontopics/MapOps.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Things you can do with Maps -import java.util.concurrent.*; -import java.util.*; -import onjava.*; - -public class MapOps { - public static - void printKeys(Map map) { - System.out.print("Size = " + map.size() + ", "); - System.out.print("Keys: "); - // Produce a Set of the keys: - System.out.println(map.keySet()); - } - public static - void test(Map map) { - System.out.println( - map.getClass().getSimpleName()); - map.putAll(new CountMap(25)); - // Map has 'Set' behavior for keys: - map.putAll(new CountMap(25)); - printKeys(map); - // Producing a Collection of the values: - System.out.print("Values: "); - System.out.println(map.values()); - System.out.println(map); - System.out.println("map.containsKey(11): " + - map.containsKey(11)); - System.out.println( - "map.get(11): " + map.get(11)); - System.out.println("map.containsValue(\"F0\"): " - + map.containsValue("F0")); - Integer key = map.keySet().iterator().next(); - System.out.println("First key in map: " + key); - map.remove(key); - printKeys(map); - map.clear(); - System.out.println( - "map.isEmpty(): " + map.isEmpty()); - map.putAll(new CountMap(25)); - // Operations on the Set change the Map: - map.keySet().removeAll(map.keySet()); - System.out.println( - "map.isEmpty(): " + map.isEmpty()); - } - public static void main(String[] args) { - test(new HashMap<>()); - test(new TreeMap<>()); - test(new LinkedHashMap<>()); - test(new IdentityHashMap<>()); - test(new ConcurrentHashMap<>()); - test(new WeakHashMap<>()); - } -} -/* Output: (First 11 Lines) -HashMap -Size = 25, Keys: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] -Values: [A0, B0, C0, D0, E0, F0, G0, H0, I0, J0, K0, -L0, M0, N0, O0, P0, Q0, R0, S0, T0, U0, V0, W0, X0, Y0] -{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, -9=J0, 10=K0, 11=L0, 12=M0, 13=N0, 14=O0, 15=P0, 16=Q0, -17=R0, 18=S0, 19=T0, 20=U0, 21=V0, 22=W0, 23=X0, 24=Y0} -map.containsKey(11): true -map.get(11): L0 -map.containsValue("F0"): true -First key in map: 0 -Size = 24, Keys: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] -map.isEmpty(): true -map.isEmpty(): true - ... -*/ diff --git a/code/collectiontopics/NavMap.java b/code/collectiontopics/NavMap.java deleted file mode 100644 index 076ae841..00000000 --- a/code/collectiontopics/NavMap.java +++ /dev/null @@ -1,96 +0,0 @@ -// collectiontopics/NavMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// NavigableMap produces pieces of a Map -import java.util.*; -import java.util.concurrent.*; -import static onjava.HTMLColors.*; - -public class NavMap { - public static final - NavigableMap COLORS = - new ConcurrentSkipListMap<>(MAP); - public static void main(String[] args) { - show(COLORS.firstEntry()); - border(); - show(COLORS.lastEntry()); - border(); - NavigableMap toLime = - COLORS.headMap(rgb("Lime"), true); - show(toLime); - border(); - show(COLORS.ceilingEntry(rgb("DeepSkyBlue") - 1)); - border(); - show(COLORS.floorEntry(rgb("DeepSkyBlue") - 1)); - border(); - show(toLime.descendingMap()); - border(); - show(COLORS.tailMap(rgb("MistyRose"), true)); - border(); - show(COLORS.subMap( - rgb("Orchid"), true, - rgb("DarkSalmon"), false)); - } -} -/* Output: -0x000000: Black -****************************** -0xFFFFFF: White -****************************** -0x000000: Black -0x000080: Navy -0x00008B: DarkBlue -0x0000CD: MediumBlue -0x0000FF: Blue -0x006400: DarkGreen -0x008000: Green -0x008080: Teal -0x008B8B: DarkCyan -0x00BFFF: DeepSkyBlue -0x00CED1: DarkTurquoise -0x00FA9A: MediumSpringGreen -0x00FF00: Lime -****************************** -0x00BFFF: DeepSkyBlue -****************************** -0x008B8B: DarkCyan -****************************** -0x00FF00: Lime -0x00FA9A: MediumSpringGreen -0x00CED1: DarkTurquoise -0x00BFFF: DeepSkyBlue -0x008B8B: DarkCyan -0x008080: Teal -0x008000: Green -0x006400: DarkGreen -0x0000FF: Blue -0x0000CD: MediumBlue -0x00008B: DarkBlue -0x000080: Navy -0x000000: Black -****************************** -0xFFE4E1: MistyRose -0xFFEBCD: BlanchedAlmond -0xFFEFD5: PapayaWhip -0xFFF0F5: LavenderBlush -0xFFF5EE: SeaShell -0xFFF8DC: Cornsilk -0xFFFACD: LemonChiffon -0xFFFAF0: FloralWhite -0xFFFAFA: Snow -0xFFFF00: Yellow -0xFFFFE0: LightYellow -0xFFFFF0: Ivory -0xFFFFFF: White -****************************** -0xDA70D6: Orchid -0xDAA520: GoldenRod -0xDB7093: PaleVioletRed -0xDC143C: Crimson -0xDCDCDC: Gainsboro -0xDDA0DD: Plum -0xDEB887: BurlyWood -0xE0FFFF: LightCyan -0xE6E6FA: Lavender -*/ diff --git a/code/collectiontopics/QueueBehavior.java b/code/collectiontopics/QueueBehavior.java deleted file mode 100644 index 136fbaf8..00000000 --- a/code/collectiontopics/QueueBehavior.java +++ /dev/null @@ -1,50 +0,0 @@ -// collectiontopics/QueueBehavior.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Compares basic behavior -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; - -public class QueueBehavior { - static Stream strings() { - return Arrays.stream( - ("one two three four five six seven " + - "eight nine ten").split(" ")); - } - static void test(int id, Queue queue) { - System.out.print(id + ": "); - strings().map(queue::offer).count(); - while(queue.peek() != null) - System.out.print(queue.remove() + " "); - System.out.println(); - } - public static void main(String[] args) { - int count = 10; - test(1, new LinkedList<>()); - test(2, new PriorityQueue<>()); - test(3, new ArrayBlockingQueue<>(count)); - test(4, new ConcurrentLinkedQueue<>()); - test(5, new LinkedBlockingQueue<>()); - test(6, new PriorityBlockingQueue<>()); - test(7, new ArrayDeque<>()); - test(8, new ConcurrentLinkedDeque<>()); - test(9, new LinkedBlockingDeque<>()); - test(10, new LinkedTransferQueue<>()); - test(11, new SynchronousQueue<>()); - } -} -/* Output: -1: one two three four five six seven eight nine ten -2: eight five four nine one seven six ten three two -3: one two three four five six seven eight nine ten -4: one two three four five six seven eight nine ten -5: one two three four five six seven eight nine ten -6: eight five four nine one seven six ten three two -7: one two three four five six seven eight nine ten -8: one two three four five six seven eight nine ten -9: one two three four five six seven eight nine ten -10: one two three four five six seven eight nine ten -11: -*/ diff --git a/code/collectiontopics/ReadOnly.java b/code/collectiontopics/ReadOnly.java deleted file mode 100644 index 93c336c4..00000000 --- a/code/collectiontopics/ReadOnly.java +++ /dev/null @@ -1,56 +0,0 @@ -// collectiontopics/ReadOnly.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using the Collections.unmodifiable methods -import java.util.*; -import onjava.*; - -public class ReadOnly { - static Collection data = - new ArrayList<>(Countries.names(6)); - public static void main(String[] args) { - Collection c = - Collections.unmodifiableCollection( - new ArrayList<>(data)); - System.out.println(c); // Reading is OK - //- c.add("one"); // Can't change it - - List a = Collections.unmodifiableList( - new ArrayList<>(data)); - ListIterator lit = a.listIterator(); - System.out.println(lit.next()); // Reading is OK - //- lit.add("one"); // Can't change it - - Set s = Collections.unmodifiableSet( - new HashSet<>(data)); - System.out.println(s); // Reading is OK - //- s.add("one"); // Can't change it - - // For a SortedSet: - Set ss = - Collections.unmodifiableSortedSet( - new TreeSet<>(data)); - - Map m = - Collections.unmodifiableMap( - new HashMap<>(Countries.capitals(6))); - System.out.println(m); // Reading is OK - //- m.put("Ralph", "Howdy!"); - - // For a SortedMap: - Map sm = - Collections.unmodifiableSortedMap( - new TreeMap<>(Countries.capitals(6))); - } -} -/* Output: -[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, -BURUNDI] -ALGERIA -[BENIN, BOTSWANA, ANGOLA, BURKINA FASO, ALGERIA, -BURUNDI] -{BENIN=Porto-Novo, BOTSWANA=Gaberone, ANGOLA=Luanda, -BURKINA FASO=Ouagadougou, ALGERIA=Algiers, -BURUNDI=Bujumbura} -*/ diff --git a/code/collectiontopics/References.java b/code/collectiontopics/References.java deleted file mode 100644 index 5fcca940..00000000 --- a/code/collectiontopics/References.java +++ /dev/null @@ -1,92 +0,0 @@ -// collectiontopics/References.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates Reference objects -import java.lang.ref.*; -import java.util.*; - -class VeryBig { - private static final int SIZE = 10000; - private long[] la = new long[SIZE]; - private String ident; - VeryBig(String id) { ident = id; } - @Override - public String toString() { return ident; } - @SuppressWarnings("deprecation") - @Override - protected void finalize() { - System.out.println("Finalizing " + ident); - } -} - -public class References { - private static ReferenceQueue rq = - new ReferenceQueue<>(); - public static void checkQueue() { - Reference inq = rq.poll(); - if(inq != null) - System.out.println("In queue: " + inq.get()); - } - public static void main(String[] args) { - int size = 10; - // Or, choose size via the command line: - if(args.length > 0) - size = Integer.valueOf(args[0]); - LinkedList> sa = - new LinkedList<>(); - for(int i = 0; i < size; i++) { - sa.add(new SoftReference<>( - new VeryBig("Soft " + i), rq)); - System.out.println( - "Just created: " + sa.getLast()); - checkQueue(); - } - LinkedList> wa = - new LinkedList<>(); - for(int i = 0; i < size; i++) { - wa.add(new WeakReference<>( - new VeryBig("Weak " + i), rq)); - System.out.println( - "Just created: " + wa.getLast()); - checkQueue(); - } - SoftReference s = - new SoftReference<>(new VeryBig("Soft")); - WeakReference w = - new WeakReference<>(new VeryBig("Weak")); - System.gc(); - LinkedList> pa = - new LinkedList<>(); - for(int i = 0; i < size; i++) { - pa.add(new PhantomReference<>( - new VeryBig("Phantom " + i), rq)); - System.out.println( - "Just created: " + pa.getLast()); - checkQueue(); - } - } -} -/* Output: (First and Last 10 Lines) -Just created: java.lang.ref.SoftReference@15db9742 -Just created: java.lang.ref.SoftReference@6d06d69c -Just created: java.lang.ref.SoftReference@7852e922 -Just created: java.lang.ref.SoftReference@4e25154f -Just created: java.lang.ref.SoftReference@70dea4e -Just created: java.lang.ref.SoftReference@5c647e05 -Just created: java.lang.ref.SoftReference@33909752 -Just created: java.lang.ref.SoftReference@55f96302 -Just created: java.lang.ref.SoftReference@3d4eac69 -Just created: java.lang.ref.SoftReference@42a57993 -...________...________...________...________... -Just created: java.lang.ref.PhantomReference@45ee12a7 -In queue: null -Just created: java.lang.ref.PhantomReference@330bedb4 -In queue: null -Just created: java.lang.ref.PhantomReference@2503dbd3 -In queue: null -Just created: java.lang.ref.PhantomReference@4b67cf4d -In queue: null -Just created: java.lang.ref.PhantomReference@7ea987ac -In queue: null -*/ diff --git a/code/collectiontopics/SetOrder.java b/code/collectiontopics/SetOrder.java deleted file mode 100644 index 1c25be23..00000000 --- a/code/collectiontopics/SetOrder.java +++ /dev/null @@ -1,92 +0,0 @@ -// collectiontopics/SetOrder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.HTMLColors; - -public class SetOrder { - static String[] sets = { - "java.util.HashSet", - "java.util.TreeSet", - "java.util.concurrent.ConcurrentSkipListSet", - "java.util.LinkedHashSet", - "java.util.concurrent.CopyOnWriteArraySet", - }; - static final List RLIST = - new ArrayList<>(HTMLColors.LIST); - static { - Collections.reverse(RLIST); - } - public static void - main(String[] args) throws Exception { - for(String type: sets) { - System.out.format("[-> %s <-]%n", - type.substring(type.lastIndexOf('.') + 1)); - @SuppressWarnings({"unchecked", "deprecation"}) - Set set = (Set) - Class.forName(type).newInstance(); - set.addAll(RLIST); - set.stream() - .limit(10) - .forEach(System.out::println); - } - } -} -/* Output: -[-> HashSet <-] -MediumOrchid -PaleGoldenRod -Sienna -LightSlateGray -DarkSeaGreen -Black -Gainsboro -Orange -LightCoral -DodgerBlue -[-> TreeSet <-] -AliceBlue -AntiqueWhite -Aquamarine -Azure -Beige -Bisque -Black -BlanchedAlmond -Blue -BlueViolet -[-> ConcurrentSkipListSet <-] -AliceBlue -AntiqueWhite -Aquamarine -Azure -Beige -Bisque -Black -BlanchedAlmond -Blue -BlueViolet -[-> LinkedHashSet <-] -YellowGreen -Yellow -WhiteSmoke -White -Wheat -Violet -Turquoise -Tomato -Thistle -Teal -[-> CopyOnWriteArraySet <-] -YellowGreen -Yellow -WhiteSmoke -White -Wheat -Violet -Turquoise -Tomato -Thistle -Teal -*/ diff --git a/code/collectiontopics/SimpleDeques.java b/code/collectiontopics/SimpleDeques.java deleted file mode 100644 index fbb4a5ff..00000000 --- a/code/collectiontopics/SimpleDeques.java +++ /dev/null @@ -1,70 +0,0 @@ -// collectiontopics/SimpleDeques.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Very basic test of Deques -import java.util.*; -import java.util.concurrent.*; -import java.util.function.*; - -class CountString implements Supplier { - private int n = 0; - CountString() {} - CountString(int start) { n = start; } - @Override - public String get() { - return Integer.toString(n++); - } -} - -public class SimpleDeques { - static void test(Deque deque) { - CountString s1 = new CountString(), - s2 = new CountString(20); - for(int n = 0; n < 8; n++) { - deque.offerFirst(s1.get()); - deque.offerLast(s2.get()); // Same as offer() - } - System.out.println(deque); - String result = ""; - while(deque.size() > 0) { - System.out.print(deque.peekFirst() + " "); - result += deque.pollFirst() + " "; - System.out.print(deque.peekLast() + " "); - result += deque.pollLast() + " "; - } - System.out.println("\n" + result); - } - public static void main(String[] args) { - int count = 10; - System.out.println("LinkedList"); - test(new LinkedList<>()); - System.out.println("ArrayDeque"); - test(new ArrayDeque<>()); - System.out.println("LinkedBlockingDeque"); - test(new LinkedBlockingDeque<>(count)); - System.out.println("ConcurrentLinkedDeque"); - test(new ConcurrentLinkedDeque<>()); - } -} -/* Output: -LinkedList -[7, 6, 5, 4, 3, 2, 1, 0, 20, 21, 22, 23, 24, 25, 26, -27] -7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 -7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 -ArrayDeque -[7, 6, 5, 4, 3, 2, 1, 0, 20, 21, 22, 23, 24, 25, 26, -27] -7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 -7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 -LinkedBlockingDeque -[4, 3, 2, 1, 0, 20, 21, 22, 23, 24] -4 24 3 23 2 22 1 21 0 20 -4 24 3 23 2 22 1 21 0 20 -ConcurrentLinkedDeque -[7, 6, 5, 4, 3, 2, 1, 0, 20, 21, 22, 23, 24, 25, 26, -27] -7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 -7 27 6 26 5 25 4 24 3 23 2 22 1 21 0 20 -*/ diff --git a/code/collectiontopics/SortedMapDemo.java b/code/collectiontopics/SortedMapDemo.java deleted file mode 100644 index 4d57d34a..00000000 --- a/code/collectiontopics/SortedMapDemo.java +++ /dev/null @@ -1,42 +0,0 @@ -// collectiontopics/SortedMapDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// What you can do with a TreeMap -import java.util.*; -import onjava.*; - -public class SortedMapDemo { - public static void main(String[] args) { - TreeMap sortedMap = - new TreeMap<>(new CountMap(10)); - System.out.println(sortedMap); - Integer low = sortedMap.firstKey(); - Integer high = sortedMap.lastKey(); - System.out.println(low); - System.out.println(high); - Iterator it = - sortedMap.keySet().iterator(); - for(int i = 0; i <= 6; i++) { - if(i == 3) low = it.next(); - if(i == 6) high = it.next(); - else it.next(); - } - System.out.println(low); - System.out.println(high); - System.out.println(sortedMap.subMap(low, high)); - System.out.println(sortedMap.headMap(high)); - System.out.println(sortedMap.tailMap(low)); - } -} -/* Output: -{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, -9=J0} -0 -9 -3 -7 -{3=D0, 4=E0, 5=F0, 6=G0} -{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0} -{3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, 9=J0} -*/ diff --git a/code/collectiontopics/SortedSetDemo.java b/code/collectiontopics/SortedSetDemo.java deleted file mode 100644 index 6ed81fb1..00000000 --- a/code/collectiontopics/SortedSetDemo.java +++ /dev/null @@ -1,42 +0,0 @@ -// collectiontopics/SortedSetDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import static java.util.stream.Collectors.*; - -public class SortedSetDemo { - public static void main(String[] args) { - SortedSet sortedSet = - Arrays.stream( - "one two three four five six seven eight" - .split(" ")) - .collect(toCollection(TreeSet::new)); - System.out.println(sortedSet); - String low = sortedSet.first(); - String high = sortedSet.last(); - System.out.println(low); - System.out.println(high); - Iterator it = sortedSet.iterator(); - for(int i = 0; i <= 6; i++) { - if(i == 3) low = it.next(); - if(i == 6) high = it.next(); - else it.next(); - } - System.out.println(low); - System.out.println(high); - System.out.println(sortedSet.subSet(low, high)); - System.out.println(sortedSet.headSet(high)); - System.out.println(sortedSet.tailSet(low)); - } -} -/* Output: -[eight, five, four, one, seven, six, three, two] -eight -two -one -two -[one, seven, six, three] -[eight, five, four, one, seven, six, three] -[one, seven, six, three, two] -*/ diff --git a/code/collectiontopics/Stacks.java b/code/collectiontopics/Stacks.java deleted file mode 100644 index 79a684cb..00000000 --- a/code/collectiontopics/Stacks.java +++ /dev/null @@ -1,61 +0,0 @@ -// collectiontopics/Stacks.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of Stack Class -import java.util.*; - -enum Month { JANUARY, FEBRUARY, MARCH, APRIL, - MAY, JUNE, JULY, AUGUST, SEPTEMBER, - OCTOBER, NOVEMBER } - -public class Stacks { - public static void main(String[] args) { - Stack stack = new Stack<>(); - for(Month m : Month.values()) - stack.push(m.toString()); - System.out.println("stack = " + stack); - // Treating a stack as a Vector: - stack.addElement("The last line"); - System.out.println( - "element 5 = " + stack.elementAt(5)); - System.out.println("popping elements:"); - while(!stack.empty()) - System.out.print(stack.pop() + " "); - - // Using a LinkedList as a Stack: - LinkedList lstack = new LinkedList<>(); - for(Month m : Month.values()) - lstack.addFirst(m.toString()); - System.out.println("lstack = " + lstack); - while(!lstack.isEmpty()) - System.out.print(lstack.removeFirst() + " "); - - // Using the Stack class from - // the Collections Chapter: - onjava.Stack stack2 = - new onjava.Stack<>(); - for(Month m : Month.values()) - stack2.push(m.toString()); - System.out.println("stack2 = " + stack2); - while(!stack2.isEmpty()) - System.out.print(stack2.pop() + " "); - - } -} -/* Output: -stack = [JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, -JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER] -element 5 = JUNE -popping elements: -The last line NOVEMBER OCTOBER SEPTEMBER AUGUST JULY -JUNE MAY APRIL MARCH FEBRUARY JANUARY lstack = -[NOVEMBER, OCTOBER, SEPTEMBER, AUGUST, JULY, JUNE, MAY, -APRIL, MARCH, FEBRUARY, JANUARY] -NOVEMBER OCTOBER SEPTEMBER AUGUST JULY JUNE MAY APRIL -MARCH FEBRUARY JANUARY stack2 = [NOVEMBER, OCTOBER, -SEPTEMBER, AUGUST, JULY, JUNE, MAY, APRIL, MARCH, -FEBRUARY, JANUARY] -NOVEMBER OCTOBER SEPTEMBER AUGUST JULY JUNE MAY APRIL -MARCH FEBRUARY JANUARY -*/ diff --git a/code/collectiontopics/StreamFillMaps.java b/code/collectiontopics/StreamFillMaps.java deleted file mode 100644 index 816a74b3..00000000 --- a/code/collectiontopics/StreamFillMaps.java +++ /dev/null @@ -1,55 +0,0 @@ -// collectiontopics/StreamFillMaps.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import onjava.*; - -class Letters -implements Supplier> { - private int number = 1; - private char letter = 'A'; - @Override - public Pair get() { - return new Pair<>(number++, "" + letter++); - } -} - -public class StreamFillMaps { - public static void main(String[] args) { - Map m = - Stream.generate(new Letters()) - .limit(11) - .collect(Collectors - .toMap(Pair::key, Pair::value)); - System.out.println(m); - - // Two separate Suppliers: - Rand.String rs = new Rand.String(3); - Count.Character cc = new Count.Character(); - Map mcs = Stream.generate( - () -> Pair.make(cc.get(), rs.get())) - .limit(8) - .collect(Collectors - .toMap(Pair::key, Pair::value)); - System.out.println(mcs); - - // A key Supplier and a single value: - Map mcs2 = Stream.generate( - () -> Pair.make(cc.get(), "Val")) - .limit(8) - .collect(Collectors - .toMap(Pair::key, Pair::value)); - System.out.println(mcs2); - } -} -/* Output: -{1=A, 2=B, 3=C, 4=D, 5=E, 6=F, 7=G, 8=H, 9=I, 10=J, -11=K} -{b=btp, c=enp, d=ccu, e=xsz, f=gvg, g=mei, h=nne, -i=elo} -{p=Val, q=Val, j=Val, k=Val, l=Val, m=Val, n=Val, -o=Val} -*/ diff --git a/code/collectiontopics/SuppliersCollectionTest.java b/code/collectiontopics/SuppliersCollectionTest.java deleted file mode 100644 index b30f1490..00000000 --- a/code/collectiontopics/SuppliersCollectionTest.java +++ /dev/null @@ -1,67 +0,0 @@ -// collectiontopics/SuppliersCollectionTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import onjava.*; - -class Government implements Supplier { - static String[] foundation = ( - "strange women lying in ponds " + - "distributing swords is no basis " + - "for a system of government").split(" "); - private int index; - @Override - public String get() { - return foundation[index++]; - } -} - -public class SuppliersCollectionTest { - public static void main(String[] args) { - // Suppliers class from the Generics chapter: - Set set = Suppliers.create( - LinkedHashSet::new, new Government(), 15); - System.out.println(set); - List list = Suppliers.create( - LinkedList::new, new Government(), 15); - System.out.println(list); - list = new ArrayList<>(); - Suppliers.fill(list, new Government(), 15); - System.out.println(list); - - // Or we can use Streams: - set = Arrays.stream(Government.foundation) - .collect(Collectors.toSet()); - System.out.println(set); - list = Arrays.stream(Government.foundation) - .collect(Collectors.toList()); - System.out.println(list); - list = Arrays.stream(Government.foundation) - .collect(Collectors - .toCollection(LinkedList::new)); - System.out.println(list); - set = Arrays.stream(Government.foundation) - .collect(Collectors - .toCollection(LinkedHashSet::new)); - System.out.println(set); - } -} -/* Output: -[strange, women, lying, in, ponds, distributing, -swords, is, no, basis, for, a, system, of, government] -[strange, women, lying, in, ponds, distributing, -swords, is, no, basis, for, a, system, of, government] -[strange, women, lying, in, ponds, distributing, -swords, is, no, basis, for, a, system, of, government] -[ponds, no, a, in, swords, for, is, basis, strange, -system, government, distributing, of, women, lying] -[strange, women, lying, in, ponds, distributing, -swords, is, no, basis, for, a, system, of, government] -[strange, women, lying, in, ponds, distributing, -swords, is, no, basis, for, a, system, of, government] -[strange, women, lying, in, ponds, distributing, -swords, is, no, basis, for, a, system, of, government] -*/ diff --git a/code/collectiontopics/Synchronization.java b/code/collectiontopics/Synchronization.java deleted file mode 100644 index c7d3b732..00000000 --- a/code/collectiontopics/Synchronization.java +++ /dev/null @@ -1,24 +0,0 @@ -// collectiontopics/Synchronization.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using the Collections.synchronized methods -import java.util.*; - -public class Synchronization { - public static void main(String[] args) { - Collection c = - Collections.synchronizedCollection( - new ArrayList<>()); - List list = Collections - .synchronizedList(new ArrayList<>()); - Set s = Collections - .synchronizedSet(new HashSet<>()); - Set ss = Collections - .synchronizedSortedSet(new TreeSet<>()); - Map m = Collections - .synchronizedMap(new HashMap<>()); - Map sm = Collections - .synchronizedSortedMap(new TreeMap<>()); - } -} diff --git a/code/collectiontopics/ToDoList.java b/code/collectiontopics/ToDoList.java deleted file mode 100644 index b288e8e1..00000000 --- a/code/collectiontopics/ToDoList.java +++ /dev/null @@ -1,56 +0,0 @@ -// collectiontopics/ToDoList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A more complex use of PriorityQueue -import java.util.*; - -class ToDoItem implements Comparable { - private char primary; - private int secondary; - private String item; - ToDoItem(String td, char pri, int sec) { - primary = pri; - secondary = sec; - item = td; - } - @Override - public int compareTo(ToDoItem arg) { - if(primary > arg.primary) - return +1; - if(primary == arg.primary) - if(secondary > arg.secondary) - return +1; - else if(secondary == arg.secondary) - return 0; - return -1; - } - @Override - public String toString() { - return Character.toString(primary) + - secondary + ": " + item; - } -} - -class ToDoList { - public static void main(String[] args) { - PriorityQueue toDo = - new PriorityQueue<>(); - toDo.add(new ToDoItem("Empty trash", 'C', 4)); - toDo.add(new ToDoItem("Feed dog", 'A', 2)); - toDo.add(new ToDoItem("Feed bird", 'B', 7)); - toDo.add(new ToDoItem("Mow lawn", 'C', 3)); - toDo.add(new ToDoItem("Water lawn", 'A', 1)); - toDo.add(new ToDoItem("Feed cat", 'B', 1)); - while(!toDo.isEmpty()) - System.out.println(toDo.remove()); - } -} -/* Output: -A1: Water lawn -A2: Feed dog -B1: Feed cat -B7: Feed bird -C3: Mow lawn -C4: Empty trash -*/ diff --git a/code/collectiontopics/TypesForSets.java b/code/collectiontopics/TypesForSets.java deleted file mode 100644 index 9950b003..00000000 --- a/code/collectiontopics/TypesForSets.java +++ /dev/null @@ -1,93 +0,0 @@ -// collectiontopics/TypesForSets.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Methods necessary to put your own type in a Set -import java.util.*; -import java.util.function.*; -import java.util.Objects; - -class SetType { - protected int i; - SetType(int n) { i = n; } - @Override - public boolean equals(Object o) { - return o instanceof SetType && - Objects.equals(i, ((SetType)o).i); - } - @Override - public String toString() { - return Integer.toString(i); - } -} - -class HashType extends SetType { - HashType(int n) { super(n); } - @Override - public int hashCode() { - return Objects.hashCode(i); - } -} - -class TreeType extends SetType -implements Comparable { - TreeType(int n) { super(n); } - @Override - public int compareTo(TreeType arg) { - return Integer.compare(arg.i, i); - // Equivalent to: - // return arg.i < i ? -1 : (arg.i == i ? 0 : 1); - } -} - -public class TypesForSets { - static void - fill(Set set, Function type) { - for(int i = 10; i >= 5; i--) // Descending - set.add(type.apply(i)); - for(int i = 0; i < 5; i++) // Ascending - set.add(type.apply(i)); - } - static void - test(Set set, Function type) { - fill(set, type); - fill(set, type); // Try to add duplicates - fill(set, type); - System.out.println(set); - } - public static void main(String[] args) { - test(new HashSet<>(), HashType::new); - test(new LinkedHashSet<>(), HashType::new); - test(new TreeSet<>(), TreeType::new); - // Things that don't work: - test(new HashSet<>(), SetType::new); - test(new HashSet<>(), TreeType::new); - test(new LinkedHashSet<>(), SetType::new); - test(new LinkedHashSet<>(), TreeType::new); - try { - test(new TreeSet<>(), SetType::new); - } catch(Exception e) { - System.out.println(e.getMessage()); - } - try { - test(new TreeSet<>(), HashType::new); - } catch(Exception e) { - System.out.println(e.getMessage()); - } - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -[10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4] -[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] -[1, 6, 8, 6, 2, 7, 8, 9, 4, 10, 7, 5, 1, 3, 4, 9, 9, -10, 5, 3, 2, 0, 4, 1, 2, 0, 8, 3, 0, 10, 6, 5, 7] -[3, 1, 4, 8, 7, 6, 9, 5, 3, 0, 10, 5, 5, 10, 7, 8, 8, -9, 1, 4, 10, 2, 6, 9, 1, 6, 0, 3, 2, 0, 7, 2, 4] -[10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, -0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4] -[10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, -0, 1, 2, 3, 4, 10, 9, 8, 7, 6, 5, 0, 1, 2, 3, 4] -SetType cannot be cast to java.lang.Comparable -HashType cannot be cast to java.lang.Comparable -*/ diff --git a/code/collectiontopics/Unsupported.java b/code/collectiontopics/Unsupported.java deleted file mode 100644 index a66b1cfd..00000000 --- a/code/collectiontopics/Unsupported.java +++ /dev/null @@ -1,60 +0,0 @@ -// collectiontopics/Unsupported.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Unsupported operations in Java collections -import java.util.*; - -public class Unsupported { - static void - check(String description, Runnable tst) { - try { - tst.run(); - } catch(Exception e) { - System.out.println(description + "(): " + e); - } - } - static void test(String msg, List list) { - System.out.println("--- " + msg + " ---"); - Collection c = list; - Collection subList = list.subList(1,8); - // Copy of the sublist: - Collection c2 = new ArrayList<>(subList); - check("retainAll", () -> c.retainAll(c2)); - check("removeAll", () -> c.removeAll(c2)); - check("clear", () -> c.clear()); - check("add", () -> c.add("X")); - check("addAll", () -> c.addAll(c2)); - check("remove", () -> c.remove("C")); - // The List.set() method modifies the value but - // doesn't change the size of the data structure: - check("List.set", () -> list.set(0, "X")); - } - public static void main(String[] args) { - List list = Arrays.asList( - "A B C D E F G H I J K L".split(" ")); - test("Modifiable Copy", new ArrayList<>(list)); - test("Arrays.asList()", list); - test("unmodifiableList()", - Collections.unmodifiableList( - new ArrayList<>(list))); - } -} -/* Output: ---- Modifiable Copy --- ---- Arrays.asList() --- -retainAll(): java.lang.UnsupportedOperationException -removeAll(): java.lang.UnsupportedOperationException -clear(): java.lang.UnsupportedOperationException -add(): java.lang.UnsupportedOperationException -addAll(): java.lang.UnsupportedOperationException -remove(): java.lang.UnsupportedOperationException ---- unmodifiableList() --- -retainAll(): java.lang.UnsupportedOperationException -removeAll(): java.lang.UnsupportedOperationException -clear(): java.lang.UnsupportedOperationException -add(): java.lang.UnsupportedOperationException -addAll(): java.lang.UnsupportedOperationException -remove(): java.lang.UnsupportedOperationException -List.set(): java.lang.UnsupportedOperationException -*/ diff --git a/code/collectiontopics/Utilities.java b/code/collectiontopics/Utilities.java deleted file mode 100644 index a2acc427..00000000 --- a/code/collectiontopics/Utilities.java +++ /dev/null @@ -1,88 +0,0 @@ -// collectiontopics/Utilities.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple demonstrations of the Collections utilities -import java.util.*; - -public class Utilities { - static List list = Arrays.asList( - "one Two three Four five six one".split(" ")); - public static void main(String[] args) { - System.out.println(list); - System.out.println("'list' disjoint (Four)?: " + - Collections.disjoint(list, - Collections.singletonList("Four"))); - System.out.println( - "max: " + Collections.max(list)); - System.out.println( - "min: " + Collections.min(list)); - System.out.println( - "max w/ comparator: " + Collections.max(list, - String.CASE_INSENSITIVE_ORDER)); - System.out.println( - "min w/ comparator: " + Collections.min(list, - String.CASE_INSENSITIVE_ORDER)); - List sublist = - Arrays.asList("Four five six".split(" ")); - System.out.println("indexOfSubList: " + - Collections.indexOfSubList(list, sublist)); - System.out.println("lastIndexOfSubList: " + - Collections.lastIndexOfSubList(list, sublist)); - Collections.replaceAll(list, "one", "Yo"); - System.out.println("replaceAll: " + list); - Collections.reverse(list); - System.out.println("reverse: " + list); - Collections.rotate(list, 3); - System.out.println("rotate: " + list); - List source = - Arrays.asList("in the matrix".split(" ")); - Collections.copy(list, source); - System.out.println("copy: " + list); - Collections.swap(list, 0, list.size() - 1); - System.out.println("swap: " + list); - Collections.shuffle(list, new Random(47)); - System.out.println("shuffled: " + list); - Collections.fill(list, "pop"); - System.out.println("fill: " + list); - System.out.println("frequency of 'pop': " + - Collections.frequency(list, "pop")); - List dups = - Collections.nCopies(3, "snap"); - System.out.println("dups: " + dups); - System.out.println("'list' disjoint 'dups'?: " + - Collections.disjoint(list, dups)); - // Getting an old-style Enumeration: - Enumeration e = - Collections.enumeration(dups); - Vector v = new Vector<>(); - while(e.hasMoreElements()) - v.addElement(e.nextElement()); - // Converting an old-style Vector - // to a List via an Enumeration: - ArrayList arrayList = - Collections.list(v.elements()); - System.out.println("arrayList: " + arrayList); - } -} -/* Output: -[one, Two, three, Four, five, six, one] -'list' disjoint (Four)?: false -max: three -min: Four -max w/ comparator: Two -min w/ comparator: five -indexOfSubList: 3 -lastIndexOfSubList: 3 -replaceAll: [Yo, Two, three, Four, five, six, Yo] -reverse: [Yo, six, five, Four, three, Two, Yo] -rotate: [three, Two, Yo, Yo, six, five, Four] -copy: [in, the, matrix, Yo, six, five, Four] -swap: [Four, the, matrix, Yo, six, five, in] -shuffled: [six, matrix, the, Four, Yo, five, in] -fill: [pop, pop, pop, pop, pop, pop, pop] -frequency of 'pop': 7 -dups: [snap, snap, snap] -'list' disjoint 'dups'?: true -arrayList: [snap, snap, snap] -*/ diff --git a/code/com/mindviewinc/simple/List.java b/code/com/mindviewinc/simple/List.java deleted file mode 100644 index 84b30315..00000000 --- a/code/com/mindviewinc/simple/List.java +++ /dev/null @@ -1,12 +0,0 @@ -// com/mindviewinc/simple/List.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating a package -package com.mindviewinc.simple; - -public class List { - public List() { - System.out.println("com.mindviewinc.simple.List"); - } -} diff --git a/code/com/mindviewinc/simple/Vector.java b/code/com/mindviewinc/simple/Vector.java deleted file mode 100644 index 19824cce..00000000 --- a/code/com/mindviewinc/simple/Vector.java +++ /dev/null @@ -1,12 +0,0 @@ -// com/mindviewinc/simple/Vector.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating a package -package com.mindviewinc.simple; - -public class Vector { - public Vector() { - System.out.println("com.mindviewinc.simple.Vector"); - } -} diff --git a/code/compression/GZIPcompress.java b/code/compression/GZIPcompress.java deleted file mode 100644 index c9022e78..00000000 --- a/code/compression/GZIPcompress.java +++ /dev/null @@ -1,45 +0,0 @@ -// compression/GZIPcompress.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java GZIPcompress GZIPcompress.java} -// {VisuallyInspectOutput} -import java.util.zip.*; -import java.io.*; - -public class GZIPcompress { - public static void main(String[] args) { - if(args.length == 0) { - System.out.println( - "Usage: \nGZIPcompress file\n" + - "\tUses GZIP compression to compress " + - "the file to test.gz"); - System.exit(1); - } - try( - InputStream in = new BufferedInputStream( - new FileInputStream(args[0])); - BufferedOutputStream out = - new BufferedOutputStream( - new GZIPOutputStream( - new FileOutputStream("test.gz"))) - ) { - System.out.println("Writing file"); - int c; - while((c = in.read()) != -1) - out.write(c); - } catch(IOException e) { - throw new RuntimeException(e); - } - System.out.println("Reading file"); - try( - BufferedReader in2 = new BufferedReader( - new InputStreamReader(new GZIPInputStream( - new FileInputStream("test.gz")))) - ) { - in2.lines().forEach(System.out::println); - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/compression/ZipCompress.java b/code/compression/ZipCompress.java deleted file mode 100644 index f9ce7670..00000000 --- a/code/compression/ZipCompress.java +++ /dev/null @@ -1,83 +0,0 @@ -// compression/ZipCompress.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Uses Zip compression to compress any -// number of files given on the command line -// {java ZipCompress ZipCompress.java} -// {VisuallyInspectOutput} -import java.util.zip.*; -import java.io.*; -import java.util.*; - -public class ZipCompress { - public static void main(String[] args) { - try( - FileOutputStream f = - new FileOutputStream("test.zip"); - CheckedOutputStream csum = - new CheckedOutputStream(f, new Adler32()); - ZipOutputStream zos = new ZipOutputStream(csum); - BufferedOutputStream out = - new BufferedOutputStream(zos) - ) { - zos.setComment("A test of Java Zipping"); - // No corresponding getComment(), though. - for(String arg : args) { - System.out.println("Writing file " + arg); - try( - InputStream in = new BufferedInputStream( - new FileInputStream(arg)) - ) { - zos.putNextEntry(new ZipEntry(arg)); - int c; - while((c = in.read()) != -1) - out.write(c); - } - out.flush(); - } - // Checksum valid only after the file is closed! - System.out.println( - "Checksum: " + csum.getChecksum().getValue()); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Now extract the files: - System.out.println("Reading file"); - try( - FileInputStream fi = - new FileInputStream("test.zip"); - CheckedInputStream csumi = - new CheckedInputStream(fi, new Adler32()); - ZipInputStream in2 = new ZipInputStream(csumi); - BufferedInputStream bis = - new BufferedInputStream(in2) - ) { - ZipEntry ze; - while((ze = in2.getNextEntry()) != null) { - System.out.println("Reading file " + ze); - int x; - while((x = bis.read()) != -1) - System.out.write(x); - } - if(args.length == 1) - System.out.println( - "Checksum: "+csumi.getChecksum().getValue()); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Alternative way to open and read Zip files: - try( - ZipFile zf = new ZipFile("test.zip") - ) { - Enumeration e = zf.entries(); - while(e.hasMoreElements()) { - ZipEntry ze2 = (ZipEntry)e.nextElement(); - System.out.println("File: " + ze2); - // ... and extract the data as before - } - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/concurrent/Baked.java b/code/concurrent/Baked.java deleted file mode 100644 index d616d94b..00000000 --- a/code/concurrent/Baked.java +++ /dev/null @@ -1,31 +0,0 @@ -// concurrent/Baked.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; -import onjava.Nap; - -public class Baked { - static class Pan {} - static Pan pan(Batter b) { - new Nap(0.1); - return new Pan(); - } - static Baked heat(Pan p) { - new Nap(0.1); - return new Baked(); - } - static CompletableFuture - bake(CompletableFuture cfb) { - return cfb - .thenApplyAsync(Baked::pan) - .thenApplyAsync(Baked::heat); - } - public static - Stream> batch() { - CompletableFuture batter = Batter.mix(); - return Stream.of(bake(batter), bake(batter), - bake(batter), bake(batter)); - } -} diff --git a/code/concurrent/Batter.java b/code/concurrent/Batter.java deleted file mode 100644 index 9fe14c4f..00000000 --- a/code/concurrent/Batter.java +++ /dev/null @@ -1,34 +0,0 @@ -// concurrent/Batter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import onjava.Nap; - -public class Batter { - static class Eggs {} - static class Milk {} - static class Sugar {} - static class Flour {} - static T prepare(T ingredient) { - new Nap(0.1); - return ingredient; - } - static CompletableFuture prep(T ingredient) { - return CompletableFuture - .completedFuture(ingredient) - .thenApplyAsync(Batter::prepare); - } - public static CompletableFuture mix() { - CompletableFuture eggs = prep(new Eggs()); - CompletableFuture milk = prep(new Milk()); - CompletableFuture sugar = prep(new Sugar()); - CompletableFuture flour = prep(new Flour()); - CompletableFuture - .allOf(eggs, milk, sugar, flour) - .join(); - new Nap(0.1); // Mixing time - return - CompletableFuture.completedFuture(new Batter()); - } -} diff --git a/code/concurrent/Breakable.java b/code/concurrent/Breakable.java deleted file mode 100644 index facd7095..00000000 --- a/code/concurrent/Breakable.java +++ /dev/null @@ -1,29 +0,0 @@ -// concurrent/Breakable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class Breakable { - String id; - private int failcount; - public Breakable(String id, int failcount) { - this.id = id; - this.failcount = failcount; - } - @Override - public String toString() { - return "Breakable_" + id + - " [" + failcount + "]"; - } - public static Breakable work(Breakable b) { - if(--b.failcount == 0) { - System.out.println( - "Throwing Exception for " + b.id + ""); - throw new RuntimeException( - "Breakable_" + b.id + " failed"); - } - System.out.println(b); - return b; - } -} diff --git a/code/concurrent/CachedThreadPool.java b/code/concurrent/CachedThreadPool.java deleted file mode 100644 index e0b825a2..00000000 --- a/code/concurrent/CachedThreadPool.java +++ /dev/null @@ -1,29 +0,0 @@ -// concurrent/CachedThreadPool.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; - -public class CachedThreadPool { - public static void main(String[] args) { - ExecutorService exec = - Executors.newCachedThreadPool(); - IntStream.range(0, 10) - .mapToObj(NapTask::new) - .forEach(exec::execute); - exec.shutdown(); - } -} -/* Output: -NapTask[7] pool-1-thread-8 -NapTask[4] pool-1-thread-5 -NapTask[1] pool-1-thread-2 -NapTask[3] pool-1-thread-4 -NapTask[0] pool-1-thread-1 -NapTask[8] pool-1-thread-9 -NapTask[2] pool-1-thread-3 -NapTask[9] pool-1-thread-10 -NapTask[6] pool-1-thread-7 -NapTask[5] pool-1-thread-6 -*/ diff --git a/code/concurrent/CachedThreadPool2.java b/code/concurrent/CachedThreadPool2.java deleted file mode 100644 index 9d763656..00000000 --- a/code/concurrent/CachedThreadPool2.java +++ /dev/null @@ -1,29 +0,0 @@ -// concurrent/CachedThreadPool2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; - -public class CachedThreadPool2 { - public static void main(String[] args) { - ExecutorService exec = - Executors.newCachedThreadPool(); - IntStream.range(0, 10) - .mapToObj(InterferingTask::new) - .forEach(exec::execute); - exec.shutdown(); - } -} -/* Output: -0 pool-1-thread-1 200 -1 pool-1-thread-2 200 -4 pool-1-thread-5 300 -5 pool-1-thread-6 400 -8 pool-1-thread-9 500 -9 pool-1-thread-10 600 -2 pool-1-thread-3 700 -7 pool-1-thread-8 800 -3 pool-1-thread-4 900 -6 pool-1-thread-7 1000 -*/ diff --git a/code/concurrent/CachedThreadPool3.java b/code/concurrent/CachedThreadPool3.java deleted file mode 100644 index 4b6e6d2e..00000000 --- a/code/concurrent/CachedThreadPool3.java +++ /dev/null @@ -1,47 +0,0 @@ -// concurrent/CachedThreadPool3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.concurrent.*; -import java.util.stream.*; - -public class CachedThreadPool3 { - public static Integer - extractResult(Future f) { - try { - return f.get(); - } catch(Exception e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) - throws InterruptedException { - ExecutorService exec = - Executors.newCachedThreadPool(); - List tasks = - IntStream.range(0, 10) - .mapToObj(CountingTask::new) - .collect(Collectors.toList()); - List> futures = - exec.invokeAll(tasks); - Integer sum = futures.stream() - .map(CachedThreadPool3::extractResult) - .reduce(0, Integer::sum); - System.out.println("sum = " + sum); - exec.shutdown(); - } -} -/* Output: -1 pool-1-thread-2 100 -0 pool-1-thread-1 100 -4 pool-1-thread-5 100 -5 pool-1-thread-6 100 -8 pool-1-thread-9 100 -9 pool-1-thread-10 100 -2 pool-1-thread-3 100 -3 pool-1-thread-4 100 -6 pool-1-thread-7 100 -7 pool-1-thread-8 100 -sum = 1000 -*/ diff --git a/code/concurrent/CatchCompletableExceptions.java b/code/concurrent/CatchCompletableExceptions.java deleted file mode 100644 index 67451ed4..00000000 --- a/code/concurrent/CatchCompletableExceptions.java +++ /dev/null @@ -1,81 +0,0 @@ -// concurrent/CatchCompletableExceptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class CatchCompletableExceptions { - static void handleException(int failcount) { - // Call the Function only if there's an - // exception, must produce same type as came in: - CompletableExceptions - .test("exceptionally", failcount) - .exceptionally((ex) -> { // Function - if(ex == null) - System.out.println("I don't get it yet"); - return new Breakable(ex.getMessage(), 0); - }) - .thenAccept(str -> - System.out.println("result: " + str)); - - // Create a new result (recover): - CompletableExceptions - .test("handle", failcount) - .handle((result, fail) -> { // BiFunction - if(fail != null) - return "Failure recovery object"; - else - return result + " is good"; - }) - .thenAccept(str -> - System.out.println("result: " + str)); - - // Do something but pass the same result through: - CompletableExceptions - .test("whenComplete", failcount) - .whenComplete((result, fail) -> { // BiConsumer - if(fail != null) - System.out.println("It failed"); - else - System.out.println(result + " OK"); - }) - .thenAccept(r -> - System.out.println("result: " + r)); - } - public static void main(String[] args) { - System.out.println("**** Failure Mode ****"); - handleException(2); - System.out.println("**** Success Mode ****"); - handleException(0); - } -} -/* Output: -**** Failure Mode **** -Breakable_exceptionally [1] -Throwing Exception for exceptionally -result: Breakable_java.lang.RuntimeException: -Breakable_exceptionally failed [0] -Breakable_handle [1] -Throwing Exception for handle -result: Failure recovery object -Breakable_whenComplete [1] -Throwing Exception for whenComplete -It failed -**** Success Mode **** -Breakable_exceptionally [-1] -Breakable_exceptionally [-2] -Breakable_exceptionally [-3] -Breakable_exceptionally [-4] -result: Breakable_exceptionally [-4] -Breakable_handle [-1] -Breakable_handle [-2] -Breakable_handle [-3] -Breakable_handle [-4] -result: Breakable_handle [-4] is good -Breakable_whenComplete [-1] -Breakable_whenComplete [-2] -Breakable_whenComplete [-3] -Breakable_whenComplete [-4] -Breakable_whenComplete [-4] OK -result: Breakable_whenComplete [-4] -*/ diff --git a/code/concurrent/CollectionIntoStream.java b/code/concurrent/CollectionIntoStream.java deleted file mode 100644 index 2dc51a7e..00000000 --- a/code/concurrent/CollectionIntoStream.java +++ /dev/null @@ -1,36 +0,0 @@ -// concurrent/CollectionIntoStream.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; -import java.util.*; -import java.util.stream.*; - -public class CollectionIntoStream { - public static void main(String[] args) { - List strings = - Stream.generate(new Rand.String(5)) - .limit(10) - .collect(Collectors.toList()); - strings.forEach(System.out::println); - // Convert to a Stream for many more options: - String result = strings.stream() - .map(String::toUpperCase) - .map(s -> s.substring(2)) - .reduce(":", (s1, s2) -> s1 + s2); - System.out.println(result); - } -} -/* Output: -btpen -pccux -szgvg -meinn -eeloz -tdvew -cippc -ygpoa -lkljl -bynxt -:PENCUXGVGINNLOZVEWPPCPOALJLNXT -*/ diff --git a/code/concurrent/CompletableApply.java b/code/concurrent/CompletableApply.java deleted file mode 100644 index 2f5bd9b4..00000000 --- a/code/concurrent/CompletableApply.java +++ /dev/null @@ -1,27 +0,0 @@ -// concurrent/CompletableApply.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class CompletableApply { - public static void main(String[] args) { - CompletableFuture cf = - CompletableFuture.completedFuture( - new Machina(0)); - CompletableFuture cf2 = - cf.thenApply(Machina::work); - CompletableFuture cf3 = - cf2.thenApply(Machina::work); - CompletableFuture cf4 = - cf3.thenApply(Machina::work); - CompletableFuture cf5 = - cf4.thenApply(Machina::work); - } -} -/* Output: -Machina0: ONE -Machina0: TWO -Machina0: THREE -Machina0: complete -*/ diff --git a/code/concurrent/CompletableApplyAsync.java b/code/concurrent/CompletableApplyAsync.java deleted file mode 100644 index fa7c9271..00000000 --- a/code/concurrent/CompletableApplyAsync.java +++ /dev/null @@ -1,31 +0,0 @@ -// concurrent/CompletableApplyAsync.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import onjava.*; - -public class CompletableApplyAsync { - public static void main(String[] args) { - Timer timer = new Timer(); - CompletableFuture cf = - CompletableFuture.completedFuture( - new Machina(0)) - .thenApplyAsync(Machina::work) - .thenApplyAsync(Machina::work) - .thenApplyAsync(Machina::work) - .thenApplyAsync(Machina::work); - System.out.println(timer.duration()); - System.out.println(cf.join()); - System.out.println(timer.duration()); - } -} -/* Output: -116 -Machina0: ONE -Machina0: TWO -Machina0: THREE -Machina0: complete -Machina0: complete -552 -*/ diff --git a/code/concurrent/CompletableApplyChained.java b/code/concurrent/CompletableApplyChained.java deleted file mode 100644 index aa6828d5..00000000 --- a/code/concurrent/CompletableApplyChained.java +++ /dev/null @@ -1,27 +0,0 @@ -// concurrent/CompletableApplyChained.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import onjava.Timer; - -public class CompletableApplyChained { - public static void main(String[] args) { - Timer timer = new Timer(); - CompletableFuture cf = - CompletableFuture.completedFuture( - new Machina(0)) - .thenApply(Machina::work) - .thenApply(Machina::work) - .thenApply(Machina::work) - .thenApply(Machina::work); - System.out.println(timer.duration()); - } -} -/* Output: -Machina0: ONE -Machina0: TWO -Machina0: THREE -Machina0: complete -514 -*/ diff --git a/code/concurrent/CompletableExceptions.java b/code/concurrent/CompletableExceptions.java deleted file mode 100644 index 624815d5..00000000 --- a/code/concurrent/CompletableExceptions.java +++ /dev/null @@ -1,75 +0,0 @@ -// concurrent/CompletableExceptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class CompletableExceptions { - static CompletableFuture - test(String id, int failcount) { - return - CompletableFuture.completedFuture( - new Breakable(id, failcount)) - .thenApply(Breakable::work) - .thenApply(Breakable::work) - .thenApply(Breakable::work) - .thenApply(Breakable::work); - } - public static void main(String[] args) { - // Exceptions don't appear ... - test("A", 1); - test("B", 2); - test("C", 3); - test("D", 4); - test("E", 5); - // ... until you try to fetch the value: - try { - test("F", 2).get(); // or join() - } catch(Exception e) { - System.out.println(e.getMessage()); - } - // Test for exceptions: - System.out.println( - test("G", 2).isCompletedExceptionally()); - // Counts as "done": - System.out.println(test("H", 2).isDone()); - // Force an exception: - CompletableFuture cfi = - new CompletableFuture<>(); - System.out.println("done? " + cfi.isDone()); - cfi.completeExceptionally( - new RuntimeException("forced")); - try { - cfi.get(); - } catch(Exception e) { - System.out.println(e.getMessage()); - } - } -} -/* Output: -Throwing Exception for A -Breakable_B [1] -Throwing Exception for B -Breakable_C [2] -Breakable_C [1] -Throwing Exception for C -Breakable_D [3] -Breakable_D [2] -Breakable_D [1] -Throwing Exception for D -Breakable_E [4] -Breakable_E [3] -Breakable_E [2] -Breakable_E [1] -Breakable_F [1] -Throwing Exception for F -java.lang.RuntimeException: Breakable_F failed -Breakable_G [1] -Throwing Exception for G -true -Breakable_H [1] -Throwing Exception for H -true -done? false -java.lang.RuntimeException: forced -*/ diff --git a/code/concurrent/CompletableOperations.java b/code/concurrent/CompletableOperations.java deleted file mode 100644 index d03e8422..00000000 --- a/code/concurrent/CompletableOperations.java +++ /dev/null @@ -1,74 +0,0 @@ -// concurrent/CompletableOperations.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import static onjava.CompletableUtilities.*; - -public class CompletableOperations { - static CompletableFuture cfi(int i) { - return - CompletableFuture.completedFuture( - Integer.valueOf(i)); - } - public static void main(String[] args) { - showr(cfi(1)); // Basic test - voidr(cfi(2).runAsync(() -> - System.out.println("runAsync"))); - voidr(cfi(3).thenRunAsync(() -> - System.out.println("thenRunAsync"))); - voidr(CompletableFuture.runAsync(() -> - System.out.println("runAsync is static"))); - showr(CompletableFuture.supplyAsync(() -> 99)); - voidr(cfi(4).thenAcceptAsync(i -> - System.out.println("thenAcceptAsync: " + i))); - showr(cfi(5).thenApplyAsync(i -> i + 42)); - showr(cfi(6).thenComposeAsync(i -> cfi(i + 99))); - CompletableFuture c = cfi(7); - c.obtrudeValue(111); - showr(c); - showr(cfi(8).toCompletableFuture()); - c = new CompletableFuture<>(); - c.complete(9); - showr(c); - c = new CompletableFuture<>(); - c.cancel(true); - System.out.println("cancelled: " + - c.isCancelled()); - System.out.println("completed exceptionally: " + - c.isCompletedExceptionally()); - System.out.println("done: " + c.isDone()); - System.out.println(c); - c = new CompletableFuture<>(); - System.out.println(c.getNow(777)); - c = new CompletableFuture<>(); - c.thenApplyAsync(i -> i + 42) - .thenApplyAsync(i -> i * 12); - System.out.println("dependents: " + - c.getNumberOfDependents()); - c.thenApplyAsync(i -> i / 2); - System.out.println("dependents: " + - c.getNumberOfDependents()); - } -} -/* Output: -1 -runAsync -thenRunAsync -runAsync is static -99 -thenAcceptAsync: 4 -47 -105 -111 -8 -9 -cancelled: true -completed exceptionally: true -done: true -java.util.concurrent.CompletableFuture@6d311334[Complet -ed exceptionally] -777 -dependents: 1 -dependents: 2 -*/ diff --git a/code/concurrent/CompletablePizza.java b/code/concurrent/CompletablePizza.java deleted file mode 100644 index 97b68545..00000000 --- a/code/concurrent/CompletablePizza.java +++ /dev/null @@ -1,87 +0,0 @@ -// concurrent/CompletablePizza.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.concurrent.*; -import java.util.stream.*; -import onjava.Timer; - -public class CompletablePizza { - static final int QUANTITY = 5; - public static CompletableFuture - makeCF(Pizza za) { - return CompletableFuture - .completedFuture(za) - .thenApplyAsync(Pizza::roll) - .thenApplyAsync(Pizza::sauce) - .thenApplyAsync(Pizza::cheese) - .thenApplyAsync(Pizza::toppings) - .thenApplyAsync(Pizza::bake) - .thenApplyAsync(Pizza::slice) - .thenApplyAsync(Pizza::box); - } - public static void - show(CompletableFuture cf) { - try { - System.out.println(cf.get()); - } catch(Exception e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) { - Timer timer = new Timer(); - List> pizzas = - IntStream.range(0, QUANTITY) - .mapToObj(Pizza::new) - .map(CompletablePizza::makeCF) - .collect(Collectors.toList()); - System.out.println(timer.duration()); - pizzas.forEach(CompletablePizza::show); - System.out.println(timer.duration()); - } -} -/* Output: -169 -Pizza 0: ROLLED -Pizza 1: ROLLED -Pizza 2: ROLLED -Pizza 4: ROLLED -Pizza 3: ROLLED -Pizza 1: SAUCED -Pizza 0: SAUCED -Pizza 2: SAUCED -Pizza 4: SAUCED -Pizza 3: SAUCED -Pizza 0: CHEESED -Pizza 4: CHEESED -Pizza 1: CHEESED -Pizza 2: CHEESED -Pizza 3: CHEESED -Pizza 0: TOPPED -Pizza 4: TOPPED -Pizza 1: TOPPED -Pizza 2: TOPPED -Pizza 3: TOPPED -Pizza 0: BAKED -Pizza 4: BAKED -Pizza 1: BAKED -Pizza 3: BAKED -Pizza 2: BAKED -Pizza 0: SLICED -Pizza 4: SLICED -Pizza 1: SLICED -Pizza 3: SLICED -Pizza 2: SLICED -Pizza 4: BOXED -Pizza 0: BOXED -Pizza0: complete -Pizza 1: BOXED -Pizza1: complete -Pizza 3: BOXED -Pizza 2: BOXED -Pizza2: complete -Pizza3: complete -Pizza4: complete -1797 -*/ diff --git a/code/concurrent/CompletableUtilities.java b/code/concurrent/CompletableUtilities.java deleted file mode 100644 index 8f3a0e51..00000000 --- a/code/concurrent/CompletableUtilities.java +++ /dev/null @@ -1,27 +0,0 @@ -// concurrent/CompletableUtilities.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.util.concurrent.*; - -public class CompletableUtilities { - // Get and show value stored in a CF: - public static void showr(CompletableFuture c) { - try { - System.out.println(c.get()); - } catch(InterruptedException - | ExecutionException e) { - throw new RuntimeException(e); - } - } - // For CF operations that have no value: - public static void voidr(CompletableFuture c) { - try { - c.get(); // Returns void - } catch(InterruptedException - | ExecutionException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/concurrent/CompletedMachina.java b/code/concurrent/CompletedMachina.java deleted file mode 100644 index 06a78710..00000000 --- a/code/concurrent/CompletedMachina.java +++ /dev/null @@ -1,19 +0,0 @@ -// concurrent/CompletedMachina.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class CompletedMachina { - public static void main(String[] args) { - CompletableFuture cf = - CompletableFuture.completedFuture( - new Machina(0)); - try { - Machina m = cf.get(); // Doesn't block - } catch(InterruptedException | - ExecutionException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/concurrent/CountingStream.java b/code/concurrent/CountingStream.java deleted file mode 100644 index 4cebb24e..00000000 --- a/code/concurrent/CountingStream.java +++ /dev/null @@ -1,32 +0,0 @@ -// concurrent/CountingStream.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.util.*; -import java.util.concurrent.*; -import java.util.stream.*; - -public class CountingStream { - public static void main(String[] args) { - System.out.println( - IntStream.range(0, 10) - .parallel() - .mapToObj(CountingTask::new) - .map(ct -> ct.call()) - .reduce(0, Integer::sum)); - } -} -/* Output: -1 ForkJoinPool.commonPool-worker-3 100 -8 ForkJoinPool.commonPool-worker-2 100 -0 ForkJoinPool.commonPool-worker-6 100 -2 ForkJoinPool.commonPool-worker-1 100 -4 ForkJoinPool.commonPool-worker-5 100 -9 ForkJoinPool.commonPool-worker-7 100 -6 main 100 -7 ForkJoinPool.commonPool-worker-4 100 -5 ForkJoinPool.commonPool-worker-2 100 -3 ForkJoinPool.commonPool-worker-3 100 -1000 -*/ diff --git a/code/concurrent/CountingTask.java b/code/concurrent/CountingTask.java deleted file mode 100644 index b1fb7b89..00000000 --- a/code/concurrent/CountingTask.java +++ /dev/null @@ -1,19 +0,0 @@ -// concurrent/CountingTask.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class CountingTask implements Callable { - final int id; - public CountingTask(int id) { this.id = id; } - @Override - public Integer call() { - Integer val = 0; - for(int i = 0; i < 100; i++) - val++; - System.out.println(id + " " + - Thread.currentThread().getName() + " " + val); - return val; - } -} diff --git a/code/concurrent/DiningPhilosophers.java b/code/concurrent/DiningPhilosophers.java deleted file mode 100644 index 5c2b2f1b..00000000 --- a/code/concurrent/DiningPhilosophers.java +++ /dev/null @@ -1,33 +0,0 @@ -// concurrent/DiningPhilosophers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Hidden deadlock -// {ExcludeFromGradle} Gradle has trouble -import java.util.*; -import java.util.concurrent.*; -import onjava.Nap; - -public class DiningPhilosophers { - private StickHolder[] sticks; - private Philosopher[] philosophers; - public DiningPhilosophers(int n) { - sticks = new StickHolder[n]; - Arrays.setAll(sticks, i -> new StickHolder()); - philosophers = new Philosopher[n]; - Arrays.setAll(philosophers, i -> - new Philosopher(i, - sticks[i], sticks[(i + 1) % n])); // [1] - // Fix by reversing stick order for this one: - // philosophers[1] = // [2] - // new Philosopher(0, sticks[0], sticks[1]); - Arrays.stream(philosophers) - .forEach(CompletableFuture::runAsync); // [3] - } - public static void main(String[] args) { - // Returns right away: - new DiningPhilosophers(5); // [4] - // Keeps main() from exiting: - new Nap(3, "Shutdown"); - } -} diff --git a/code/concurrent/DualCompletableOperations.java b/code/concurrent/DualCompletableOperations.java deleted file mode 100644 index 42052312..00000000 --- a/code/concurrent/DualCompletableOperations.java +++ /dev/null @@ -1,115 +0,0 @@ -// concurrent/DualCompletableOperations.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import static onjava.CompletableUtilities.*; - -public class DualCompletableOperations { - static CompletableFuture cfA, cfB; - static void init() { - cfA = Workable.make("A", 0.15); - cfB = Workable.make("B", 0.10); // Always wins - } - static void join() { - cfA.join(); - cfB.join(); - System.out.println("*****************"); - } - public static void main(String[] args) { - init(); - voidr(cfA.runAfterEitherAsync(cfB, () -> - System.out.println("runAfterEither"))); - join(); - - init(); - voidr(cfA.runAfterBothAsync(cfB, () -> - System.out.println("runAfterBoth"))); - join(); - - init(); - showr(cfA.applyToEitherAsync(cfB, w -> { - System.out.println("applyToEither: " + w); - return w; - })); - join(); - - init(); - voidr(cfA.acceptEitherAsync(cfB, w -> { - System.out.println("acceptEither: " + w); - })); - join(); - - init(); - voidr(cfA.thenAcceptBothAsync(cfB, (w1, w2) -> { - System.out.println("thenAcceptBoth: " - + w1 + ", " + w2); - })); - join(); - - init(); - showr(cfA.thenCombineAsync(cfB, (w1, w2) -> { - System.out.println("thenCombine: " - + w1 + ", " + w2); - return w1; - })); - join(); - - init(); - CompletableFuture - cfC = Workable.make("C", 0.08), - cfD = Workable.make("D", 0.09); - CompletableFuture.anyOf(cfA, cfB, cfC, cfD) - .thenRunAsync(() -> - System.out.println("anyOf")); - join(); - - init(); - cfC = Workable.make("C", 0.08); - cfD = Workable.make("D", 0.09); - CompletableFuture.allOf(cfA, cfB, cfC, cfD) - .thenRunAsync(() -> - System.out.println("allOf")); - join(); - } -} -/* Output: -Workable[BW] -runAfterEither -Workable[AW] -***************** -Workable[BW] -Workable[AW] -runAfterBoth -***************** -Workable[BW] -applyToEither: Workable[BW] -Workable[BW] -Workable[AW] -***************** -Workable[BW] -acceptEither: Workable[BW] -Workable[AW] -***************** -Workable[BW] -Workable[AW] -thenAcceptBoth: Workable[AW], Workable[BW] -***************** -Workable[BW] -Workable[AW] -thenCombine: Workable[AW], Workable[BW] -Workable[AW] -***************** -Workable[CW] -anyOf -Workable[DW] -Workable[BW] -Workable[AW] -***************** -Workable[CW] -Workable[DW] -Workable[BW] -Workable[AW] -***************** -allOf -*/ diff --git a/code/concurrent/FrostedCake.java b/code/concurrent/FrostedCake.java deleted file mode 100644 index 1be8b661..00000000 --- a/code/concurrent/FrostedCake.java +++ /dev/null @@ -1,32 +0,0 @@ -// concurrent/FrostedCake.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; -import onjava.Nap; - -final class Frosting { - private Frosting() {} - static CompletableFuture make() { - new Nap(0.1); - return CompletableFuture - .completedFuture(new Frosting()); - } -} - -public class FrostedCake { - public FrostedCake(Baked baked, Frosting frosting) { - new Nap(0.1); - } - @Override - public String toString() { return "FrostedCake"; } - public static void main(String[] args) { - Baked.batch().forEach(baked -> baked - .thenCombineAsync(Frosting.make(), - (cake, frosting) -> - new FrostedCake(cake, frosting)) - .thenAcceptAsync(System.out::println) - .join()); - } -} diff --git a/code/concurrent/Futures.java b/code/concurrent/Futures.java deleted file mode 100644 index 888e7f0d..00000000 --- a/code/concurrent/Futures.java +++ /dev/null @@ -1,23 +0,0 @@ -// concurrent/Futures.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.concurrent.*; -import java.util.stream.*; - -public class Futures { - public static void main(String[] args) - throws InterruptedException, ExecutionException { - ExecutorService exec = - Executors.newSingleThreadExecutor(); - Future f = - exec.submit(new CountingTask(99)); - System.out.println(f.get()); // [1] - exec.shutdown(); - } -} -/* Output: -99 pool-1-thread-1 100 -100 -*/ diff --git a/code/concurrent/GuardedIDField.java b/code/concurrent/GuardedIDField.java deleted file mode 100644 index e570a5d3..00000000 --- a/code/concurrent/GuardedIDField.java +++ /dev/null @@ -1,18 +0,0 @@ -// concurrent/GuardedIDField.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.atomic.*; - -public class GuardedIDField implements HasID { - private static AtomicInteger counter = - new AtomicInteger(); - private int id = counter.getAndIncrement(); - public int getID() { return id; } - public static void main(String[] args) { - IDChecker.test(GuardedIDField::new); - } -} -/* Output: -0 -*/ diff --git a/code/concurrent/HasID.java b/code/concurrent/HasID.java deleted file mode 100644 index e5e13438..00000000 --- a/code/concurrent/HasID.java +++ /dev/null @@ -1,8 +0,0 @@ -// concurrent/HasID.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public interface HasID { - int getID(); -} diff --git a/code/concurrent/IDChecker.java b/code/concurrent/IDChecker.java deleted file mode 100644 index 845c9e6a..00000000 --- a/code/concurrent/IDChecker.java +++ /dev/null @@ -1,41 +0,0 @@ -// concurrent/IDChecker.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import java.util.concurrent.*; -import com.google.common.collect.Sets; - -public class IDChecker { - public static final int SIZE = 100_000; - static class MakeObjects - implements Supplier> { - private Supplier gen; - MakeObjects(Supplier gen) { - this.gen = gen; - } - @Override - public List get() { - return - Stream.generate(gen) - .limit(SIZE) - .map(HasID::getID) - .collect(Collectors.toList()); - } - } - public static void test(Supplier gen) { - CompletableFuture> - groupA = CompletableFuture - .supplyAsync(new MakeObjects(gen)), - groupB = CompletableFuture - .supplyAsync(new MakeObjects(gen)); - groupA.thenAcceptBoth(groupB, (a, b) -> { - System.out.println( - Sets.intersection( - Sets.newHashSet(a), - Sets.newHashSet(b)).size()); - }).join(); - } -} diff --git a/code/concurrent/InterferingTask.java b/code/concurrent/InterferingTask.java deleted file mode 100644 index da08f653..00000000 --- a/code/concurrent/InterferingTask.java +++ /dev/null @@ -1,17 +0,0 @@ -// concurrent/InterferingTask.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class InterferingTask implements Runnable { - final int id; - private static Integer val = 0; - public InterferingTask(int id) { this.id = id; } - @Override - public void run() { - for(int i = 0; i < 100; i++) - val++; - System.out.println(id + " " + - Thread.currentThread().getName() + " " + val); - } -} diff --git a/code/concurrent/LambdasAndMethodReferences.java b/code/concurrent/LambdasAndMethodReferences.java deleted file mode 100644 index 10552499..00000000 --- a/code/concurrent/LambdasAndMethodReferences.java +++ /dev/null @@ -1,40 +0,0 @@ -// concurrent/LambdasAndMethodReferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -class NotRunnable { - public void go() { - System.out.println("NotRunnable"); - } -} - -class NotCallable { - public Integer get() { - System.out.println("NotCallable"); - return 1; - } -} - -public class LambdasAndMethodReferences { - public static void main(String[] args) - throws InterruptedException { - ExecutorService exec = - Executors.newCachedThreadPool(); - exec.submit(() -> System.out.println("Lambda1")); - exec.submit(new NotRunnable()::go); - exec.submit(() -> { - System.out.println("Lambda2"); - return 1; - }); - exec.submit(new NotCallable()::get); - exec.shutdown(); - } -} -/* Output: -Lambda1 -NotCallable -NotRunnable -Lambda2 -*/ diff --git a/code/concurrent/Machina.java b/code/concurrent/Machina.java deleted file mode 100644 index e70cd2b4..00000000 --- a/code/concurrent/Machina.java +++ /dev/null @@ -1,31 +0,0 @@ -// concurrent/Machina.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.Nap; - -public class Machina { - public enum State { - START, ONE, TWO, THREE, END; - State step() { - if(equals(END)) return END; - return values()[ordinal() + 1]; - } - } - private State state = State.START; - private final int id; - public Machina(int id) { this.id = id; } - public static Machina work(Machina m) { - if(!m.state.equals(State.END)){ - new Nap(0.1); - m.state = m.state.step(); - } - System.out.println(m); - return m; - } - @Override - public String toString() { - return "Machina" + id + ": " + - (state.equals(State.END)? "complete" : state); - } -} diff --git a/code/concurrent/MoreTasksAfterShutdown.java b/code/concurrent/MoreTasksAfterShutdown.java deleted file mode 100644 index 28b96af8..00000000 --- a/code/concurrent/MoreTasksAfterShutdown.java +++ /dev/null @@ -1,27 +0,0 @@ -// concurrent/MoreTasksAfterShutdown.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class MoreTasksAfterShutdown { - public static void main(String[] args) { - ExecutorService exec = - Executors.newSingleThreadExecutor(); - exec.execute(new NapTask(1)); - exec.shutdown(); - try { - exec.execute(new NapTask(99)); - } catch(RejectedExecutionException e) { - System.out.println(e); - } - } -} -/* Output: -java.util.concurrent.RejectedExecutionException: Task -NapTask[99] rejected from java.util.concurrent.ThreadPo -olExecutor@4e25154f[Shutting down, pool size = 1, -active threads = 1, queued tasks = 0, completed tasks = -0] -NapTask[1] pool-1-thread-1 -*/ diff --git a/code/concurrent/NapTask.java b/code/concurrent/NapTask.java deleted file mode 100644 index 92df6b60..00000000 --- a/code/concurrent/NapTask.java +++ /dev/null @@ -1,20 +0,0 @@ -// concurrent/NapTask.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.Nap; - -public class NapTask implements Runnable { - final int id; - public NapTask(int id) { this.id = id; } - @Override - public void run() { - new Nap(0.1); // Seconds - System.out.println(this + " " + - Thread.currentThread().getName()); - } - @Override - public String toString() { - return "NapTask[" + id + "]"; - } -} diff --git a/code/concurrent/OnePizza.java b/code/concurrent/OnePizza.java deleted file mode 100644 index f4f27249..00000000 --- a/code/concurrent/OnePizza.java +++ /dev/null @@ -1,26 +0,0 @@ -// concurrent/OnePizza.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.Timer; - -public class OnePizza { - public static void main(String[] args) { - Pizza za = new Pizza(0); - System.out.println( - Timer.duration(() -> { - while(!za.complete()) - za.next(); - })); - } -} -/* Output: -Pizza 0: ROLLED -Pizza 0: SAUCED -Pizza 0: CHEESED -Pizza 0: TOPPED -Pizza 0: BAKED -Pizza 0: SLICED -Pizza 0: BOXED -1622 -*/ diff --git a/code/concurrent/ParallelPrime.java b/code/concurrent/ParallelPrime.java deleted file mode 100644 index 97c02575..00000000 --- a/code/concurrent/ParallelPrime.java +++ /dev/null @@ -1,35 +0,0 @@ -// concurrent/ParallelPrime.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import static java.util.stream.LongStream.*; -import java.io.*; -import java.nio.file.*; -import onjava.Timer; - -public class ParallelPrime { - static final int COUNT = 100_000; - public static boolean isPrime(long n) { - return rangeClosed(2, (long)Math.sqrt(n)) - .noneMatch(i -> n % i == 0); - } - public static void main(String[] args) - throws IOException { - Timer timer = new Timer(); - List primes = - iterate(2, i -> i + 1) - .parallel() // [1] - .filter(ParallelPrime::isPrime) - .limit(COUNT) - .mapToObj(Long::toString) - .collect(Collectors.toList()); - System.out.println(timer.duration()); - Files.write(Paths.get("primes.txt"), primes, - StandardOpenOption.CREATE); - } -} -/* Output: -1224 -*/ diff --git a/code/concurrent/ParallelStreamPuzzle.java b/code/concurrent/ParallelStreamPuzzle.java deleted file mode 100644 index f57dec24..00000000 --- a/code/concurrent/ParallelStreamPuzzle.java +++ /dev/null @@ -1,28 +0,0 @@ -// concurrent/ParallelStreamPuzzle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -public class ParallelStreamPuzzle { - static class IntGenerator - implements Supplier { - private int current = 0; - public Integer get() { - return current++; - } - } - public static void main(String[] args) { - List x = - Stream.generate(new IntGenerator()) - .limit(10) - .parallel() // [1] - .collect(Collectors.toList()); - System.out.println(x); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -*/ diff --git a/code/concurrent/ParallelStreamPuzzle2.java b/code/concurrent/ParallelStreamPuzzle2.java deleted file mode 100644 index 2fc11d48..00000000 --- a/code/concurrent/ParallelStreamPuzzle2.java +++ /dev/null @@ -1,38 +0,0 @@ -// concurrent/ParallelStreamPuzzle2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.nio.file.*; - -public class ParallelStreamPuzzle2 { - public static final Deque trace = - new ConcurrentLinkedDeque<>(); - static class - IntGenerator implements Supplier { - private AtomicInteger current = - new AtomicInteger(); - public Integer get() { - trace.add(current.get() + ": " + - Thread.currentThread().getName()); - return current.getAndIncrement(); - } - } - public static void - main(String[] args) throws Exception { - List x = - Stream.generate(new IntGenerator()) - .limit(10) - .parallel() - .collect(Collectors.toList()); - System.out.println(x); - Files.write(Paths.get("PSP2.txt"), trace); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -*/ diff --git a/code/concurrent/ParallelStreamPuzzle3.java b/code/concurrent/ParallelStreamPuzzle3.java deleted file mode 100644 index 757bddd5..00000000 --- a/code/concurrent/ParallelStreamPuzzle3.java +++ /dev/null @@ -1,33 +0,0 @@ -// concurrent/ParallelStreamPuzzle3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.util.*; -import java.util.stream.*; - -public class ParallelStreamPuzzle3 { - public static void main(String[] args) { - List x = IntStream.range(0, 30) - .peek(e -> System.out.println(e + ": " + - Thread.currentThread().getName())) - .limit(10) - .parallel() - .boxed() - .collect(Collectors.toList()); - System.out.println(x); - } -} -/* Output: -8: main -6: ForkJoinPool.commonPool-worker-5 -3: ForkJoinPool.commonPool-worker-7 -5: ForkJoinPool.commonPool-worker-5 -1: ForkJoinPool.commonPool-worker-3 -2: ForkJoinPool.commonPool-worker-6 -4: ForkJoinPool.commonPool-worker-1 -0: ForkJoinPool.commonPool-worker-4 -7: ForkJoinPool.commonPool-worker-1 -9: ForkJoinPool.commonPool-worker-2 -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -*/ diff --git a/code/concurrent/Philosopher.java b/code/concurrent/Philosopher.java deleted file mode 100644 index 48facb38..00000000 --- a/code/concurrent/Philosopher.java +++ /dev/null @@ -1,30 +0,0 @@ -// concurrent/Philosopher.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Philosopher implements Runnable { - private final int seat; - private final StickHolder left, right; - public Philosopher(int seat, - StickHolder left, StickHolder right) { - this.seat = seat; - this.left = left; - this.right = right; - } - @Override - public String toString() { - return "P" + seat; - } - @Override - public void run() { - while(true) { - // System.out.println("Thinking"); // [1] - right.pickUp(); - left.pickUp(); - System.out.println(this + " eating"); - right.putDown(); - left.putDown(); - } - } -} diff --git a/code/concurrent/Pizza.java b/code/concurrent/Pizza.java deleted file mode 100644 index 8cd5ff30..00000000 --- a/code/concurrent/Pizza.java +++ /dev/null @@ -1,49 +0,0 @@ -// concurrent/Pizza.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; -import onjava.Nap; - -public class Pizza { - public enum Step { - DOUGH(4), ROLLED(1), SAUCED(1), CHEESED(2), - TOPPED(5), BAKED(2), SLICED(1), BOXED(0); - int effort; // Needed to get to the next step - Step(int effort) { this.effort = effort; } - Step forward() { - if(equals(BOXED)) return BOXED; - new Nap(effort * 0.1); - return values()[ordinal() + 1]; - } - } - private Step step = Step.DOUGH; - private final int id; - public Pizza(int id) { this.id = id; } - public Pizza next() { - step = step.forward(); - System.out.println("Pizza " + id + ": " + step); - return this; - } - public Pizza next(Step previousStep) { - if(!step.equals(previousStep)) - throw new IllegalStateException("Expected " + - previousStep + " but found " + step); - return next(); - } - public Pizza roll() { return next(Step.DOUGH); } - public Pizza sauce() { return next(Step.ROLLED); } - public Pizza cheese() { return next(Step.SAUCED); } - public Pizza toppings() { return next(Step.CHEESED); } - public Pizza bake() { return next(Step.TOPPED); } - public Pizza slice() { return next(Step.BAKED); } - public Pizza box() { return next(Step.SLICED); } - public boolean complete() { - return step.equals(Step.BOXED); - } - @Override - public String toString() { - return "Pizza" + id + ": " + - (step.equals(Step.BOXED)? "complete" : step); - } -} diff --git a/code/concurrent/PizzaParallelSteps.java b/code/concurrent/PizzaParallelSteps.java deleted file mode 100644 index 605e9985..00000000 --- a/code/concurrent/PizzaParallelSteps.java +++ /dev/null @@ -1,69 +0,0 @@ -// concurrent/PizzaParallelSteps.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import onjava.Timer; - -public class PizzaParallelSteps { - static final int QUANTITY = 5; - public static void main(String[] args) { - Timer timer = new Timer(); - IntStream.range(0, QUANTITY) - .mapToObj(Pizza::new) - .parallel() - .map(Pizza::roll) - .map(Pizza::sauce) - .map(Pizza::cheese) - .map(Pizza::toppings) - .map(Pizza::bake) - .map(Pizza::slice) - .map(Pizza::box) - .forEach(za -> System.out.println(za)); - System.out.println(timer.duration()); - } -} -/* Output: -Pizza 2: ROLLED -Pizza 0: ROLLED -Pizza 1: ROLLED -Pizza 4: ROLLED -Pizza 3: ROLLED -Pizza 1: SAUCED -Pizza 0: SAUCED -Pizza 2: SAUCED -Pizza 3: SAUCED -Pizza 4: SAUCED -Pizza 1: CHEESED -Pizza 0: CHEESED -Pizza 2: CHEESED -Pizza 3: CHEESED -Pizza 4: CHEESED -Pizza 0: TOPPED -Pizza 2: TOPPED -Pizza 1: TOPPED -Pizza 3: TOPPED -Pizza 4: TOPPED -Pizza 1: BAKED -Pizza 2: BAKED -Pizza 0: BAKED -Pizza 4: BAKED -Pizza 3: BAKED -Pizza 0: SLICED -Pizza 2: SLICED -Pizza 1: SLICED -Pizza 3: SLICED -Pizza 4: SLICED -Pizza 1: BOXED -Pizza1: complete -Pizza 2: BOXED -Pizza 0: BOXED -Pizza2: complete -Pizza0: complete -Pizza 3: BOXED -Pizza 4: BOXED -Pizza4: complete -Pizza3: complete -1738 -*/ diff --git a/code/concurrent/PizzaStreams.java b/code/concurrent/PizzaStreams.java deleted file mode 100644 index 16be983a..00000000 --- a/code/concurrent/PizzaStreams.java +++ /dev/null @@ -1,60 +0,0 @@ -// concurrent/PizzaStreams.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import onjava.Timer; - -public class PizzaStreams { - static final int QUANTITY = 5; - public static void main(String[] args) { - Timer timer = new Timer(); - IntStream.range(0, QUANTITY) - .mapToObj(Pizza::new) - .parallel() // [1] - .forEach(za -> { - while(!za.complete()) - za.next(); - }); - System.out.println(timer.duration()); - } -} -/* Output: -Pizza 2: ROLLED -Pizza 0: ROLLED -Pizza 1: ROLLED -Pizza 4: ROLLED -Pizza 3: ROLLED -Pizza 2: SAUCED -Pizza 1: SAUCED -Pizza 0: SAUCED -Pizza 4: SAUCED -Pizza 3: SAUCED -Pizza 2: CHEESED -Pizza 1: CHEESED -Pizza 0: CHEESED -Pizza 4: CHEESED -Pizza 3: CHEESED -Pizza 2: TOPPED -Pizza 1: TOPPED -Pizza 0: TOPPED -Pizza 4: TOPPED -Pizza 3: TOPPED -Pizza 2: BAKED -Pizza 1: BAKED -Pizza 0: BAKED -Pizza 4: BAKED -Pizza 3: BAKED -Pizza 2: SLICED -Pizza 1: SLICED -Pizza 0: SLICED -Pizza 4: SLICED -Pizza 3: SLICED -Pizza 2: BOXED -Pizza 1: BOXED -Pizza 0: BOXED -Pizza 4: BOXED -Pizza 3: BOXED -1739 -*/ diff --git a/code/concurrent/QuittableTask.java b/code/concurrent/QuittableTask.java deleted file mode 100644 index 3cf2a62e..00000000 --- a/code/concurrent/QuittableTask.java +++ /dev/null @@ -1,20 +0,0 @@ -// concurrent/QuittableTask.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.atomic.AtomicBoolean; -import onjava.Nap; - -public class QuittableTask implements Runnable { - final int id; - public QuittableTask(int id) { this.id = id; } - private AtomicBoolean running = - new AtomicBoolean(true); - public void quit() { running.set(false); } - @Override - public void run() { - while(running.get()) // [1] - new Nap(0.1); - System.out.print(id + " "); // [2] - } -} diff --git a/code/concurrent/QuittingCompletable.java b/code/concurrent/QuittingCompletable.java deleted file mode 100644 index e41e3899..00000000 --- a/code/concurrent/QuittingCompletable.java +++ /dev/null @@ -1,35 +0,0 @@ -// concurrent/QuittingCompletable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import onjava.Nap; - -public class QuittingCompletable { - public static void main(String[] args) { - List tasks = - IntStream.range(1, QuittingTasks.COUNT) - .mapToObj(QuittableTask::new) - .collect(Collectors.toList()); - List> cfutures = - tasks.stream() - .map(CompletableFuture::runAsync) - .collect(Collectors.toList()); - new Nap(1); - tasks.forEach(QuittableTask::quit); - cfutures.forEach(CompletableFuture::join); - } -} -/* Output: -7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 -26 27 28 29 30 31 32 33 34 6 35 4 38 39 40 41 42 43 44 -45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 -63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 -81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 -99 100 101 102 103 104 105 106 107 108 109 110 111 112 -1 113 114 116 117 118 119 120 121 122 123 124 125 126 -127 128 129 130 131 132 133 134 135 136 137 138 139 140 -141 142 143 144 145 146 147 148 149 5 115 37 36 2 3 -*/ diff --git a/code/concurrent/QuittingTasks.java b/code/concurrent/QuittingTasks.java deleted file mode 100644 index 326e24ce..00000000 --- a/code/concurrent/QuittingTasks.java +++ /dev/null @@ -1,35 +0,0 @@ -// concurrent/QuittingTasks.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import onjava.Nap; - -public class QuittingTasks { - public static final int COUNT = 150; - public static void main(String[] args) { - ExecutorService es = - Executors.newCachedThreadPool(); - List tasks = - IntStream.range(1, COUNT) - .mapToObj(QuittableTask::new) - .peek(qt -> es.execute(qt)) - .collect(Collectors.toList()); - new Nap(1); - tasks.forEach(QuittableTask::quit); - es.shutdown(); - } -} -/* Output: -24 27 31 8 11 7 19 12 16 4 23 3 28 32 15 20 63 60 68 67 -64 39 47 52 51 55 40 43 48 59 44 56 36 35 71 72 83 103 -96 92 88 99 100 87 91 79 75 84 76 115 108 112 104 107 -111 95 80 147 120 127 119 123 144 143 116 132 124 128 -136 131 135 139 148 140 2 126 6 5 1 18 129 17 14 13 21 -22 9 10 30 33 58 37 125 26 34 133 145 78 137 141 138 62 -74 142 86 65 73 146 70 42 149 121 110 134 105 82 117 -106 113 122 45 114 118 38 50 29 90 101 89 57 53 94 41 -61 66 130 69 77 81 85 93 25 102 54 109 98 49 46 97 -*/ diff --git a/code/concurrent/SharedConstructorArgument.java b/code/concurrent/SharedConstructorArgument.java deleted file mode 100644 index 4b09cc26..00000000 --- a/code/concurrent/SharedConstructorArgument.java +++ /dev/null @@ -1,44 +0,0 @@ -// concurrent/SharedConstructorArgument.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.atomic.*; - -interface SharedArg { - int get(); -} - -class Unsafe implements SharedArg { - private int i = 0; - public int get() { return i++; } -} - -class Safe implements SharedArg { - private static AtomicInteger counter = - new AtomicInteger(); - public int get() { - return counter.getAndIncrement(); - } -} - -class SharedUser implements HasID { - private final int id; - SharedUser(SharedArg sa) { - id = sa.get(); - } - @Override - public int getID() { return id; } -} - -public class SharedConstructorArgument { - public static void main(String[] args) { - Unsafe unsafe = new Unsafe(); - IDChecker.test(() -> new SharedUser(unsafe)); - Safe safe = new Safe(); - IDChecker.test(() -> new SharedUser(safe)); - } -} -/* Output: -24838 -0 -*/ diff --git a/code/concurrent/SingleThreadExecutor.java b/code/concurrent/SingleThreadExecutor.java deleted file mode 100644 index ef89e3a5..00000000 --- a/code/concurrent/SingleThreadExecutor.java +++ /dev/null @@ -1,49 +0,0 @@ -// concurrent/SingleThreadExecutor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; -import onjava.*; - -public class SingleThreadExecutor { - public static void main(String[] args) { - ExecutorService exec = - Executors.newSingleThreadExecutor(); - IntStream.range(0, 10) - .mapToObj(NapTask::new) - .forEach(exec::execute); - System.out.println("All tasks submitted"); - exec.shutdown(); - while(!exec.isTerminated()) { - System.out.println( - Thread.currentThread().getName() + - " awaiting termination"); - new Nap(0.1); - } - } -} -/* Output: -All tasks submitted -main awaiting termination -main awaiting termination -NapTask[0] pool-1-thread-1 -main awaiting termination -NapTask[1] pool-1-thread-1 -main awaiting termination -NapTask[2] pool-1-thread-1 -main awaiting termination -NapTask[3] pool-1-thread-1 -main awaiting termination -NapTask[4] pool-1-thread-1 -main awaiting termination -NapTask[5] pool-1-thread-1 -main awaiting termination -NapTask[6] pool-1-thread-1 -main awaiting termination -NapTask[7] pool-1-thread-1 -main awaiting termination -NapTask[8] pool-1-thread-1 -main awaiting termination -NapTask[9] pool-1-thread-1 -*/ diff --git a/code/concurrent/SingleThreadExecutor2.java b/code/concurrent/SingleThreadExecutor2.java deleted file mode 100644 index 08467df5..00000000 --- a/code/concurrent/SingleThreadExecutor2.java +++ /dev/null @@ -1,30 +0,0 @@ -// concurrent/SingleThreadExecutor2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; - -public class SingleThreadExecutor2 { - public static void main(String[] args) - throws InterruptedException { - ExecutorService exec = - Executors.newSingleThreadExecutor(); - IntStream.range(0, 10) - .mapToObj(NapTask::new) - .forEach(exec::execute); - exec.shutdown(); - } -} -/* Output: -NapTask[0] pool-1-thread-1 -NapTask[1] pool-1-thread-1 -NapTask[2] pool-1-thread-1 -NapTask[3] pool-1-thread-1 -NapTask[4] pool-1-thread-1 -NapTask[5] pool-1-thread-1 -NapTask[6] pool-1-thread-1 -NapTask[7] pool-1-thread-1 -NapTask[8] pool-1-thread-1 -NapTask[9] pool-1-thread-1 -*/ diff --git a/code/concurrent/SingleThreadExecutor3.java b/code/concurrent/SingleThreadExecutor3.java deleted file mode 100644 index 58149423..00000000 --- a/code/concurrent/SingleThreadExecutor3.java +++ /dev/null @@ -1,30 +0,0 @@ -// concurrent/SingleThreadExecutor3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; - -public class SingleThreadExecutor3 { - public static void main(String[] args) - throws InterruptedException { - ExecutorService exec = - Executors.newSingleThreadExecutor(); - IntStream.range(0, 10) - .mapToObj(InterferingTask::new) - .forEach(exec::execute); - exec.shutdown(); - } -} -/* Output: -0 pool-1-thread-1 100 -1 pool-1-thread-1 200 -2 pool-1-thread-1 300 -3 pool-1-thread-1 400 -4 pool-1-thread-1 500 -5 pool-1-thread-1 600 -6 pool-1-thread-1 700 -7 pool-1-thread-1 800 -8 pool-1-thread-1 900 -9 pool-1-thread-1 1000 -*/ diff --git a/code/concurrent/StaticIDField.java b/code/concurrent/StaticIDField.java deleted file mode 100644 index 22623faa..00000000 --- a/code/concurrent/StaticIDField.java +++ /dev/null @@ -1,10 +0,0 @@ -// concurrent/StaticIDField.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class StaticIDField implements HasID { - private static int counter = 0; - private int id = counter++; - public int getID() { return id; } -} diff --git a/code/concurrent/StickHolder.java b/code/concurrent/StickHolder.java deleted file mode 100644 index 719a1c63..00000000 --- a/code/concurrent/StickHolder.java +++ /dev/null @@ -1,27 +0,0 @@ -// concurrent/StickHolder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class StickHolder { - private static class Chopstick {} - private Chopstick stick = new Chopstick(); - private BlockingQueue holder = - new ArrayBlockingQueue<>(1); - public StickHolder() { putDown(); } - public void pickUp() { - try { - holder.take(); // Blocks if unavailable - } catch(InterruptedException e) { - throw new RuntimeException(e); - } - } - public void putDown() { - try { - holder.put(stick); - } catch(InterruptedException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/concurrent/StreamExceptions.java b/code/concurrent/StreamExceptions.java deleted file mode 100644 index 493daee1..00000000 --- a/code/concurrent/StreamExceptions.java +++ /dev/null @@ -1,40 +0,0 @@ -// concurrent/StreamExceptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.stream.*; - -public class StreamExceptions { - static Stream - test(String id, int failcount) { - return - Stream.of(new Breakable(id, failcount)) - .map(Breakable::work) - .map(Breakable::work) - .map(Breakable::work) - .map(Breakable::work); - } - public static void main(String[] args) { - // No operations are even applied ... - test("A", 1); - test("B", 2); - Stream c = test("C", 3); - test("D", 4); - test("E", 5); - // ... until there's a terminal operation: - System.out.println("Entering try"); - try { - c.forEach(System.out::println); // [1] - } catch(Exception e) { - System.out.println(e.getMessage()); - } - } -} -/* Output: -Entering try -Breakable_C [2] -Breakable_C [1] -Throwing Exception for C -Breakable_C failed -*/ diff --git a/code/concurrent/Summing.java b/code/concurrent/Summing.java deleted file mode 100644 index 321dcb57..00000000 --- a/code/concurrent/Summing.java +++ /dev/null @@ -1,47 +0,0 @@ -// concurrent/Summing.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; -import java.util.function.*; -import onjava.Timer; - -public class Summing { - static void timeTest(String id, long checkValue, - LongSupplier operation) { - System.out.print(id + ": "); - Timer timer = new Timer(); - long result = operation.getAsLong(); - if(result == checkValue) - System.out.println(timer.duration() + "ms"); - else - System.out.format("result: %d%ncheckValue: %d%n", - result, checkValue); - } - public static final int SZ = 100_000_000; - // This even works: - // public static final int SZ = 1_000_000_000; - public static final long CHECK = - (long)SZ * ((long)SZ + 1)/2; // Gauss's formula - public static void main(String[] args) { - System.out.println(CHECK); - timeTest("Sum Stream", CHECK, () -> - LongStream.rangeClosed(0, SZ).sum()); - timeTest("Sum Stream Parallel", CHECK, () -> - LongStream.rangeClosed(0, SZ).parallel().sum()); - timeTest("Sum Iterated", CHECK, () -> - LongStream.iterate(0, i -> i + 1) - .limit(SZ+1).sum()); - // Slower & runs out of memory above 1_000_000: - // timeTest("Sum Iterated Parallel", CHECK, () -> - // LongStream.iterate(0, i -> i + 1) - // .parallel() - // .limit(SZ+1).sum()); - } -} -/* Output: -5000000050000000 -Sum Stream: 167ms -Sum Stream Parallel: 46ms -Sum Iterated: 284ms -*/ diff --git a/code/concurrent/Summing2.java b/code/concurrent/Summing2.java deleted file mode 100644 index c046721f..00000000 --- a/code/concurrent/Summing2.java +++ /dev/null @@ -1,44 +0,0 @@ -// concurrent/Summing2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromTravisCI} -import java.util.*; - -public class Summing2 { - static long basicSum(long[] ia) { - long sum = 0; - int size = ia.length; - for(int i = 0; i < size; i++) - sum += ia[i]; - return sum; - } - // Approximate largest value of SZ before - // running out of memory on my machine: - public static final int SZ = 20_000_000; - public static final long CHECK = - (long)SZ * ((long)SZ + 1)/2; - public static void main(String[] args) { - System.out.println(CHECK); - long[] la = new long[SZ+1]; - Arrays.parallelSetAll(la, i -> i); - Summing.timeTest("Array Stream Sum", CHECK, () -> - Arrays.stream(la).sum()); - Summing.timeTest("Parallel", CHECK, () -> - Arrays.stream(la).parallel().sum()); - Summing.timeTest("Basic Sum", CHECK, () -> - basicSum(la)); - // Destructive summation: - Summing.timeTest("parallelPrefix", CHECK, () -> { - Arrays.parallelPrefix(la, Long::sum); - return la[la.length - 1]; - }); - } -} -/* Output: -200000010000000 -Array Stream Sum: 104ms -Parallel: 81ms -Basic Sum: 106ms -parallelPrefix: 265ms -*/ diff --git a/code/concurrent/Summing3.java b/code/concurrent/Summing3.java deleted file mode 100644 index 252e96f7..00000000 --- a/code/concurrent/Summing3.java +++ /dev/null @@ -1,42 +0,0 @@ -// concurrent/Summing3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromTravisCI} -import java.util.*; - -public class Summing3 { - static long basicSum(Long[] ia) { - long sum = 0; - int size = ia.length; - for(int i = 0; i < size; i++) - sum += ia[i]; - return sum; - } - // Approximate largest value of SZ before - // running out of memory on my machine: - public static final int SZ = 10_000_000; - public static final long CHECK = - (long)SZ * ((long)SZ + 1)/2; - public static void main(String[] args) { - System.out.println(CHECK); - Long[] aL = new Long[SZ+1]; - Arrays.parallelSetAll(aL, i -> (long)i); - Summing.timeTest("Long Array Stream Reduce", - CHECK, () -> - Arrays.stream(aL).reduce(0L, Long::sum)); - Summing.timeTest("Long Basic Sum", CHECK, () -> - basicSum(aL)); - // Destructive summation: - Summing.timeTest("Long parallelPrefix",CHECK, ()-> { - Arrays.parallelPrefix(aL, Long::sum); - return aL[aL.length - 1]; - }); - } -} -/* Output: -50000005000000 -Long Array Stream Reduce: 1038ms -Long Basic Sum: 21ms -Long parallelPrefix: 3616ms -*/ diff --git a/code/concurrent/Summing4.java b/code/concurrent/Summing4.java deleted file mode 100644 index bb4fe2ea..00000000 --- a/code/concurrent/Summing4.java +++ /dev/null @@ -1,23 +0,0 @@ -// concurrent/Summing4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromTravisCI} -import java.util.*; - -public class Summing4 { - public static void main(String[] args) { - System.out.println(Summing3.CHECK); - Long[] aL = new Long[Summing3.SZ+1]; - Arrays.parallelSetAll(aL, i -> (long)i); - Summing.timeTest("Long Parallel", - Summing3.CHECK, () -> - Arrays.stream(aL) - .parallel() - .reduce(0L,Long::sum)); - } -} -/* Output: -50000005000000 -Long Parallel: 1014ms -*/ diff --git a/code/concurrent/SynchronizedConstructor.java b/code/concurrent/SynchronizedConstructor.java deleted file mode 100644 index 95aa6a54..00000000 --- a/code/concurrent/SynchronizedConstructor.java +++ /dev/null @@ -1,29 +0,0 @@ -// concurrent/SynchronizedConstructor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.atomic.*; - -class SyncConstructor implements HasID { - private final int id; - private static Object - constructorLock = new Object(); - SyncConstructor(SharedArg sa) { - synchronized(constructorLock) { - id = sa.get(); - } - } - @Override - public int getID() { return id; } -} - -public class SynchronizedConstructor { - public static void main(String[] args) { - Unsafe unsafe = new Unsafe(); - IDChecker.test(() -> - new SyncConstructor(unsafe)); - } -} -/* Output: -0 -*/ diff --git a/code/concurrent/SynchronizedFactory.java b/code/concurrent/SynchronizedFactory.java deleted file mode 100644 index 669d4d76..00000000 --- a/code/concurrent/SynchronizedFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -// concurrent/SynchronizedFactory.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.atomic.*; - -final class SyncFactory implements HasID { - private final int id; - private SyncFactory(SharedArg sa) { - id = sa.get(); - } - @Override - public int getID() { return id; } - public static synchronized - SyncFactory factory(SharedArg sa) { - return new SyncFactory(sa); - } -} - -public class SynchronizedFactory { - public static void main(String[] args) { - Unsafe unsafe = new Unsafe(); - IDChecker.test(() -> - SyncFactory.factory(unsafe)); - } -} -/* Output: -0 -*/ diff --git a/code/concurrent/TestStaticIDField.java b/code/concurrent/TestStaticIDField.java deleted file mode 100644 index 5df298b7..00000000 --- a/code/concurrent/TestStaticIDField.java +++ /dev/null @@ -1,13 +0,0 @@ -// concurrent/TestStaticIDField.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class TestStaticIDField { - public static void main(String[] args) { - IDChecker.test(StaticIDField::new); - } -} -/* Output: -13287 -*/ diff --git a/code/concurrent/ThrowsChecked.java b/code/concurrent/ThrowsChecked.java deleted file mode 100644 index 59177b35..00000000 --- a/code/concurrent/ThrowsChecked.java +++ /dev/null @@ -1,42 +0,0 @@ -// concurrent/ThrowsChecked.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; -import java.util.concurrent.*; - -public class ThrowsChecked { - class Checked extends Exception {} - static ThrowsChecked nochecked(ThrowsChecked tc) { - return tc; - } - static ThrowsChecked - withchecked(ThrowsChecked tc) throws Checked { - return tc; - } - static void testStream() { - Stream.of(new ThrowsChecked()) - .map(ThrowsChecked::nochecked) - // .map(ThrowsChecked::withchecked); // [1] - .map(tc -> { - try { - return withchecked(tc); - } catch(Checked e) { - throw new RuntimeException(e); - } - }); - } - static void testCompletableFuture() { - CompletableFuture - .completedFuture(new ThrowsChecked()) - .thenApply(ThrowsChecked::nochecked) - // .thenApply(ThrowsChecked::withchecked); // [2] - .thenApply(tc -> { - try { - return withchecked(tc); - } catch(Checked e) { - throw new RuntimeException(e); - } - }); - } -} diff --git a/code/concurrent/Workable.java b/code/concurrent/Workable.java deleted file mode 100644 index fcdbbbf8..00000000 --- a/code/concurrent/Workable.java +++ /dev/null @@ -1,32 +0,0 @@ -// concurrent/Workable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import onjava.Nap; - -public class Workable { - String id; - final double duration; - public Workable(String id, double duration) { - this.id = id; - this.duration = duration; - } - @Override - public String toString() { - return "Workable[" + id + "]"; - } - public static Workable work(Workable tt) { - new Nap(tt.duration); // Seconds - tt.id = tt.id + "W"; - System.out.println(tt); - return tt; - } - public static CompletableFuture - make(String id, double duration) { - return - CompletableFuture.completedFuture( - new Workable(id, duration)) - .thenApplyAsync(Workable::work); - } -} diff --git a/code/control/BreakAndContinue.java b/code/control/BreakAndContinue.java deleted file mode 100644 index 1faaaa03..00000000 --- a/code/control/BreakAndContinue.java +++ /dev/null @@ -1,38 +0,0 @@ -// control/BreakAndContinue.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Break and continue keywords -import static onjava.Range.*; - -public class BreakAndContinue { - public static void main(String[] args) { - for(int i = 0; i < 100; i++) { // [1] - if(i == 74) break; // Out of for loop - if(i % 9 != 0) continue; // Next iteration - System.out.print(i + " "); - } - System.out.println(); - // Using for-in: - for(int i : range(100)) { // [2] - if(i == 74) break; // Out of for loop - if(i % 9 != 0) continue; // Next iteration - System.out.print(i + " "); - } - System.out.println(); - int i = 0; - // An "infinite loop": - while(true) { // [3] - i++; - int j = i * 27; - if(j == 1269) break; // Out of loop - if(i % 10 != 0) continue; // Top of loop - System.out.print(i + " "); - } - } -} -/* Output: -0 9 18 27 36 45 54 63 72 -0 9 18 27 36 45 54 63 72 -10 20 30 40 -*/ diff --git a/code/control/CommaOperator.java b/code/control/CommaOperator.java deleted file mode 100644 index eae2df82..00000000 --- a/code/control/CommaOperator.java +++ /dev/null @@ -1,18 +0,0 @@ -// control/CommaOperator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class CommaOperator { - public static void main(String[] args) { - for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) { - System.out.println("i = " + i + " j = " + j); - } - } -} -/* Output: -i = 1 j = 11 -i = 2 j = 4 -i = 3 j = 6 -i = 4 j = 8 -*/ diff --git a/code/control/ForInFloat.java b/code/control/ForInFloat.java deleted file mode 100644 index cee845b5..00000000 --- a/code/control/ForInFloat.java +++ /dev/null @@ -1,28 +0,0 @@ -// control/ForInFloat.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ForInFloat { - public static void main(String[] args) { - Random rand = new Random(47); - float[] f = new float[10]; - for(int i = 0; i < 10; i++) - f[i] = rand.nextFloat(); - for(float x : f) - System.out.println(x); - } -} -/* Output: -0.72711575 -0.39982635 -0.5309454 -0.0534122 -0.16020656 -0.57799757 -0.18847865 -0.4170137 -0.51660204 -0.73734957 -*/ diff --git a/code/control/ForInInt.java b/code/control/ForInInt.java deleted file mode 100644 index f6b283a3..00000000 --- a/code/control/ForInInt.java +++ /dev/null @@ -1,28 +0,0 @@ -// control/ForInInt.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import static onjava.Range.*; - -public class ForInInt { - public static void main(String[] args) { - for(int i : range(10)) // 0..9 - System.out.print(i + " "); - System.out.println(); - for(int i : range(5, 10)) // 5..9 - System.out.print(i + " "); - System.out.println(); - for(int i : range(5, 20, 3)) // 5..20 step 3 - System.out.print(i + " "); - System.out.println(); - for(int i : range(20, 5, -3)) // Count down - System.out.print(i + " "); - System.out.println(); - } -} -/* Output: -0 1 2 3 4 5 6 7 8 9 -5 6 7 8 9 -5 8 11 14 17 -20 17 14 11 8 -*/ diff --git a/code/control/ForInString.java b/code/control/ForInString.java deleted file mode 100644 index 73e16538..00000000 --- a/code/control/ForInString.java +++ /dev/null @@ -1,14 +0,0 @@ -// control/ForInString.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ForInString { - public static void main(String[] args) { - for(char c : "An African Swallow".toCharArray()) - System.out.print(c + " "); - } -} -/* Output: -A n A f r i c a n S w a l l o w -*/ diff --git a/code/control/IfElse.java b/code/control/IfElse.java deleted file mode 100644 index f40a07b7..00000000 --- a/code/control/IfElse.java +++ /dev/null @@ -1,29 +0,0 @@ -// control/IfElse.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class IfElse { - static int result = 0; - static void test(int testval, int target) { - if(testval > target) - result = +1; - else if(testval < target) // [1] - result = -1; - else - result = 0; // Match - } - public static void main(String[] args) { - test(10, 5); - System.out.println(result); - test(5, 10); - System.out.println(result); - test(5, 5); - System.out.println(result); - } -} -/* Output: -1 --1 -0 -*/ diff --git a/code/control/LabeledFor.java b/code/control/LabeledFor.java deleted file mode 100644 index 2df79bad..00000000 --- a/code/control/LabeledFor.java +++ /dev/null @@ -1,65 +0,0 @@ -// control/LabeledFor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// For loops with "labeled break"/"labeled continue." - -public class LabeledFor { - public static void main(String[] args) { - int i = 0; - outer: // Can't have statements here - for(; true ;) { // infinite loop - inner: // Can't have statements here - for(; i < 10; i++) { - System.out.println("i = " + i); - if(i == 2) { - System.out.println("continue"); - continue; - } - if(i == 3) { - System.out.println("break"); - i++; // Otherwise i never - // gets incremented. - break; - } - if(i == 7) { - System.out.println("continue outer"); - i++; // Otherwise i never - // gets incremented. - continue outer; - } - if(i == 8) { - System.out.println("break outer"); - break outer; - } - for(int k = 0; k < 5; k++) { - if(k == 3) { - System.out.println("continue inner"); - continue inner; - } - } - } - } - // Can't break or continue to labels here - } -} -/* Output: -i = 0 -continue inner -i = 1 -continue inner -i = 2 -continue -i = 3 -break -i = 4 -continue inner -i = 5 -continue inner -i = 6 -continue inner -i = 7 -continue outer -i = 8 -break outer -*/ diff --git a/code/control/LabeledWhile.java b/code/control/LabeledWhile.java deleted file mode 100644 index 961f5ff3..00000000 --- a/code/control/LabeledWhile.java +++ /dev/null @@ -1,51 +0,0 @@ -// control/LabeledWhile.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// "While" with "labeled break" and "labeled continue." - -public class LabeledWhile { - public static void main(String[] args) { - int i = 0; - outer: - while(true) { - System.out.println("Outer while loop"); - while(true) { - i++; - System.out.println("i = " + i); - if(i == 1) { - System.out.println("continue"); - continue; - } - if(i == 3) { - System.out.println("continue outer"); - continue outer; - } - if(i == 5) { - System.out.println("break"); - break; - } - if(i == 7) { - System.out.println("break outer"); - break outer; - } - } - } - } -} -/* Output: -Outer while loop -i = 1 -continue -i = 2 -i = 3 -continue outer -Outer while loop -i = 4 -i = 5 -break -Outer while loop -i = 6 -i = 7 -break outer -*/ diff --git a/code/control/ListCharacters.java b/code/control/ListCharacters.java deleted file mode 100644 index 43efce9f..00000000 --- a/code/control/ListCharacters.java +++ /dev/null @@ -1,27 +0,0 @@ -// control/ListCharacters.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// List all the lowercase ASCII letters - -public class ListCharacters { - public static void main(String[] args) { - for(char c = 0; c < 128; c++) - if(Character.isLowerCase(c)) - System.out.println("value: " + (int)c + - " character: " + c); - } -} -/* Output: (First 10 Lines) -value: 97 character: a -value: 98 character: b -value: 99 character: c -value: 100 character: d -value: 101 character: e -value: 102 character: f -value: 103 character: g -value: 104 character: h -value: 105 character: i -value: 106 character: j - ... -*/ diff --git a/code/control/RandomBounds.java b/code/control/RandomBounds.java deleted file mode 100644 index 6befc6f4..00000000 --- a/code/control/RandomBounds.java +++ /dev/null @@ -1,30 +0,0 @@ -// control/RandomBounds.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Does Math.random() produce 0.0 and 1.0? -// {java RandomBounds lower} -import onjava.*; - -public class RandomBounds { - public static void main(String[] args) { - new TimedAbort(3); - switch(args.length == 0 ? "" : args[0]) { - case "lower": - while(Math.random() != 0.0) - ; // Keep trying - System.out.println("Produced 0.0!"); - break; - case "upper": - while(Math.random() != 1.0) - ; // Keep trying - System.out.println("Produced 1.0!"); - break; - default: - System.out.println("Usage:"); - System.out.println("\tRandomBounds lower"); - System.out.println("\tRandomBounds upper"); - System.exit(1); - } - } -} diff --git a/code/control/StringSwitch.java b/code/control/StringSwitch.java deleted file mode 100644 index 638cc427..00000000 --- a/code/control/StringSwitch.java +++ /dev/null @@ -1,44 +0,0 @@ -// control/StringSwitch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class StringSwitch { - public static void main(String[] args) { - String color = "red"; - // Old way: using if-then - if("red".equals(color)) { - System.out.println("RED"); - } else if("green".equals(color)) { - System.out.println("GREEN"); - } else if("blue".equals(color)) { - System.out.println("BLUE"); - } else if("yellow".equals(color)) { - System.out.println("YELLOW"); - } else { - System.out.println("Unknown"); - } - // New way: Strings in switch - switch(color) { - case "red": - System.out.println("RED"); - break; - case "green": - System.out.println("GREEN"); - break; - case "blue": - System.out.println("BLUE"); - break; - case "yellow": - System.out.println("YELLOW"); - break; - default: - System.out.println("Unknown"); - break; - } - } -} -/* Output: -RED -RED -*/ diff --git a/code/control/TestWithReturn.java b/code/control/TestWithReturn.java deleted file mode 100644 index efe05c90..00000000 --- a/code/control/TestWithReturn.java +++ /dev/null @@ -1,24 +0,0 @@ -// control/TestWithReturn.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class TestWithReturn { - static int test(int testval, int target) { - if(testval > target) - return +1; - if(testval < target) - return -1; - return 0; // Match - } - public static void main(String[] args) { - System.out.println(test(10, 5)); - System.out.println(test(5, 10)); - System.out.println(test(5, 5)); - } -} -/* Output: -1 --1 -0 -*/ diff --git a/code/control/TrueFalse.java b/code/control/TrueFalse.java deleted file mode 100644 index e87dade4..00000000 --- a/code/control/TrueFalse.java +++ /dev/null @@ -1,15 +0,0 @@ -// control/TrueFalse.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class TrueFalse { - public static void main(String[] args) { - System.out.println(1 == 1); - System.out.println(1 == 2); - } -} -/* Output: -true -false -*/ diff --git a/code/control/VowelsAndConsonants.java b/code/control/VowelsAndConsonants.java deleted file mode 100644 index d3a192d0..00000000 --- a/code/control/VowelsAndConsonants.java +++ /dev/null @@ -1,44 +0,0 @@ -// control/VowelsAndConsonants.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates the switch statement -import java.util.*; - -public class VowelsAndConsonants { - public static void main(String[] args) { - Random rand = new Random(47); - for(int i = 0; i < 100; i++) { - int c = rand.nextInt(26) + 'a'; - System.out.print((char)c + ", " + c + ": "); - switch(c) { - case 'a': - case 'e': - case 'i': - case 'o': - case 'u': System.out.println("vowel"); - break; - case 'y': - case 'w': System.out.println("Sometimes vowel"); - break; - default: System.out.println("consonant"); - } - } - } -} -/* Output: (First 13 Lines) -y, 121: Sometimes vowel -n, 110: consonant -z, 122: consonant -b, 98: consonant -r, 114: consonant -n, 110: consonant -y, 121: Sometimes vowel -g, 103: consonant -c, 99: consonant -f, 102: consonant -o, 111: vowel -w, 119: Sometimes vowel -z, 122: consonant - ... -*/ diff --git a/code/control/WhileTest.java b/code/control/WhileTest.java deleted file mode 100644 index 075068cf..00000000 --- a/code/control/WhileTest.java +++ /dev/null @@ -1,31 +0,0 @@ -// control/WhileTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates the while loop - -public class WhileTest { - static boolean condition() { - boolean result = Math.random() < 0.99; - System.out.print(result + ", "); - return result; - } - public static void main(String[] args) { - while(condition()) - System.out.println("Inside 'while'"); - System.out.println("Exited 'while'"); - } -} -/* Output: (First and Last 5 Lines) -true, Inside 'while' -true, Inside 'while' -true, Inside 'while' -true, Inside 'while' -true, Inside 'while' -...________...________...________...________... -true, Inside 'while' -true, Inside 'while' -true, Inside 'while' -true, Inside 'while' -false, Exited 'while' -*/ diff --git a/code/enums/AlarmPoints.java b/code/enums/AlarmPoints.java deleted file mode 100644 index a8731137..00000000 --- a/code/enums/AlarmPoints.java +++ /dev/null @@ -1,9 +0,0 @@ -// enums/AlarmPoints.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package enums; -public enum AlarmPoints { - STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3, - OFFICE4, BATHROOM, UTILITY, KITCHEN -} diff --git a/code/enums/BigEnumSet.java b/code/enums/BigEnumSet.java deleted file mode 100644 index 52ac3445..00000000 --- a/code/enums/BigEnumSet.java +++ /dev/null @@ -1,29 +0,0 @@ -// enums/BigEnumSet.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class BigEnumSet { - enum Big { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, - A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, - A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, - A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, - A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, - A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, - A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, - A70, A71, A72, A73, A74, A75 } - public static void main(String[] args) { - EnumSet bigEnumSet = EnumSet.allOf(Big.class); - System.out.println(bigEnumSet); - } -} -/* Output: -[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, -A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, -A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, -A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, -A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, -A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, -A68, A69, A70, A71, A72, A73, A74, A75] -*/ diff --git a/code/enums/Burrito2.java b/code/enums/Burrito2.java deleted file mode 100644 index 8b92ab0d..00000000 --- a/code/enums/Burrito2.java +++ /dev/null @@ -1,28 +0,0 @@ -// enums/Burrito2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java enums.Burrito2} -package enums; -import static enums.SpicinessEnum.*; - -public class Burrito2 { - SpicinessEnum degree; - public Burrito2(SpicinessEnum degree) { - this.degree = degree; - } - @Override - public String toString() { - return "Burrito is "+ degree; - } - public static void main(String[] args) { - System.out.println(new Burrito2(NOT)); - System.out.println(new Burrito2(MEDIUM)); - System.out.println(new Burrito2(HOT)); - } -} -/* Output: -Burrito is NOT -Burrito is MEDIUM -Burrito is HOT -*/ diff --git a/code/enums/CarWash.java b/code/enums/CarWash.java deleted file mode 100644 index 95800e8f..00000000 --- a/code/enums/CarWash.java +++ /dev/null @@ -1,88 +0,0 @@ -// enums/CarWash.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class CarWash { - public enum Cycle { - UNDERBODY { - @Override - void action() { - System.out.println("Spraying the underbody"); - } - }, - WHEELWASH { - @Override - void action() { - System.out.println("Washing the wheels"); - } - }, - PREWASH { - @Override - void action() { - System.out.println("Loosening the dirt"); - } - }, - BASIC { - @Override - void action() { - System.out.println("The basic wash"); - } - }, - HOTWAX { - @Override - void action() { - System.out.println("Applying hot wax"); - } - }, - RINSE { - @Override - void action() { - System.out.println("Rinsing"); - } - }, - BLOWDRY { - @Override - void action() { - System.out.println("Blowing dry"); - } - }; - abstract void action(); - } - EnumSet cycles = - EnumSet.of(Cycle.BASIC, Cycle.RINSE); - public void add(Cycle cycle) { - cycles.add(cycle); - } - public void washCar() { - for(Cycle c : cycles) - c.action(); - } - @Override - public String toString() { - return cycles.toString(); - } - public static void main(String[] args) { - CarWash wash = new CarWash(); - System.out.println(wash); - wash.washCar(); - // Order of addition is unimportant: - wash.add(Cycle.BLOWDRY); - wash.add(Cycle.BLOWDRY); // Duplicates ignored - wash.add(Cycle.RINSE); - wash.add(Cycle.HOTWAX); - System.out.println(wash); - wash.washCar(); - } -} -/* Output: -[BASIC, RINSE] -The basic wash -Rinsing -[BASIC, HOTWAX, RINSE, BLOWDRY] -The basic wash -Applying hot wax -Rinsing -Blowing dry -*/ diff --git a/code/enums/Competitor.java b/code/enums/Competitor.java deleted file mode 100644 index 09bf7141..00000000 --- a/code/enums/Competitor.java +++ /dev/null @@ -1,10 +0,0 @@ -// enums/Competitor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Switching one enum on another -package enums; - -public interface Competitor> { - Outcome compete(T competitor); -} diff --git a/code/enums/ConstantSpecificMethod.java b/code/enums/ConstantSpecificMethod.java deleted file mode 100644 index 913aa291..00000000 --- a/code/enums/ConstantSpecificMethod.java +++ /dev/null @@ -1,41 +0,0 @@ -// enums/ConstantSpecificMethod.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.text.*; - -public enum ConstantSpecificMethod { - DATE_TIME { - @Override - String getInfo() { - return - DateFormat.getDateInstance() - .format(new Date()); - } - }, - CLASSPATH { - @Override - String getInfo() { - return System.getenv("CLASSPATH"); - } - }, - VERSION { - @Override - String getInfo() { - return System.getProperty("java.version"); - } - }; - abstract String getInfo(); - public static void main(String[] args) { - for(ConstantSpecificMethod csm : values()) - System.out.println(csm.getInfo()); - } -} -/* Output: -May 9, 2017 -C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\\gradle\wrapper\gradle- -wrapper.jar -1.8.0_112 -*/ diff --git a/code/enums/EnumClass.java b/code/enums/EnumClass.java deleted file mode 100644 index 061f8abf..00000000 --- a/code/enums/EnumClass.java +++ /dev/null @@ -1,51 +0,0 @@ -// enums/EnumClass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Capabilities of the Enum class - -enum Shrubbery { GROUND, CRAWLING, HANGING } - -public class EnumClass { - public static void main(String[] args) { - for(Shrubbery s : Shrubbery.values()) { - System.out.println( - s + " ordinal: " + s.ordinal()); - System.out.print( - s.compareTo(Shrubbery.CRAWLING) + " "); - System.out.print( - s.equals(Shrubbery.CRAWLING) + " "); - System.out.println(s == Shrubbery.CRAWLING); - System.out.println(s.getDeclaringClass()); - System.out.println(s.name()); - System.out.println("********************"); - } - // Produce an enum value from a String name: - for(String s : - "HANGING CRAWLING GROUND".split(" ")) { - Shrubbery shrub = - Enum.valueOf(Shrubbery.class, s); - System.out.println(shrub); - } - } -} -/* Output: -GROUND ordinal: 0 --1 false false -class Shrubbery -GROUND -******************** -CRAWLING ordinal: 1 -0 true true -class Shrubbery -CRAWLING -******************** -HANGING ordinal: 2 -1 false false -class Shrubbery -HANGING -******************** -HANGING -CRAWLING -GROUND -*/ diff --git a/code/enums/EnumMaps.java b/code/enums/EnumMaps.java deleted file mode 100644 index f75c5cd4..00000000 --- a/code/enums/EnumMaps.java +++ /dev/null @@ -1,37 +0,0 @@ -// enums/EnumMaps.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Basics of EnumMaps -// {java enums.EnumMaps} -package enums; -import java.util.*; -import static enums.AlarmPoints.*; - -interface Command { void action(); } - -public class EnumMaps { - public static void main(String[] args) { - EnumMap em = - new EnumMap<>(AlarmPoints.class); - em.put(KITCHEN, - () -> System.out.println("Kitchen fire!")); - em.put(BATHROOM, - () -> System.out.println("Bathroom alert!")); - for(Map.Entry e: - em.entrySet()) { - System.out.print(e.getKey() + ": "); - e.getValue().action(); - } - try { // If there's no value for a particular key: - em.get(UTILITY).action(); - } catch(Exception e) { - System.out.println("Expected: " + e); - } - } -} -/* Output: -BATHROOM: Bathroom alert! -KITCHEN: Kitchen fire! -Expected: java.lang.NullPointerException -*/ diff --git a/code/enums/EnumSets.java b/code/enums/EnumSets.java deleted file mode 100644 index 0e749cad..00000000 --- a/code/enums/EnumSets.java +++ /dev/null @@ -1,39 +0,0 @@ -// enums/EnumSets.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Operations on EnumSets -// {java enums.EnumSets} -package enums; -import java.util.*; -import static enums.AlarmPoints.*; - -public class EnumSets { - public static void main(String[] args) { - EnumSet points = - EnumSet.noneOf(AlarmPoints.class); // Empty - points.add(BATHROOM); - System.out.println(points); - points.addAll( - EnumSet.of(STAIR1, STAIR2, KITCHEN)); - System.out.println(points); - points = EnumSet.allOf(AlarmPoints.class); - points.removeAll( - EnumSet.of(STAIR1, STAIR2, KITCHEN)); - System.out.println(points); - points.removeAll( - EnumSet.range(OFFICE1, OFFICE4)); - System.out.println(points); - points = EnumSet.complementOf(points); - System.out.println(points); - } -} -/* Output: -[BATHROOM] -[STAIR1, STAIR2, BATHROOM, KITCHEN] -[LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, -UTILITY] -[LOBBY, BATHROOM, UTILITY] -[STAIR1, STAIR2, OFFICE1, OFFICE2, OFFICE3, OFFICE4, -KITCHEN] -*/ diff --git a/code/enums/Input.java b/code/enums/Input.java deleted file mode 100644 index 3dc0ec44..00000000 --- a/code/enums/Input.java +++ /dev/null @@ -1,33 +0,0 @@ -// enums/Input.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public enum Input { - NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100), - TOOTHPASTE(200), CHIPS(75), SODA(100), SOAP(50), - ABORT_TRANSACTION { - @Override - public int amount() { // Disallow - throw new RuntimeException("ABORT.amount()"); - } - }, - STOP { // This must be the last instance. - @Override - public int amount() { // Disallow - throw new - RuntimeException("SHUT_DOWN.amount()"); - } - }; - int value; // In cents - Input(int value) { this.value = value; } - Input() {} - int amount() { return value; }; // In cents - static Random rand = new Random(47); - public static Input randomSelection() { - // Don't include STOP: - return - values()[rand.nextInt(values().length - 1)]; - } -} diff --git a/code/enums/NonEnum.java b/code/enums/NonEnum.java deleted file mode 100644 index 34440730..00000000 --- a/code/enums/NonEnum.java +++ /dev/null @@ -1,19 +0,0 @@ -// enums/NonEnum.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class NonEnum { - public static void main(String[] args) { - Class intClass = Integer.class; - try { - for(Object en : intClass.getEnumConstants()) - System.out.println(en); - } catch(Exception e) { - System.out.println("Expected: " + e); - } - } -} -/* Output: -Expected: java.lang.NullPointerException -*/ diff --git a/code/enums/NotClasses.java b/code/enums/NotClasses.java deleted file mode 100644 index 681e807d..00000000 --- a/code/enums/NotClasses.java +++ /dev/null @@ -1,50 +0,0 @@ -// enums/NotClasses.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromGradle} -// javap -c LikeClasses - -enum LikeClasses { - WINKEN { - @Override - void behavior() { - System.out.println("Behavior1"); - } - }, - BLINKEN { - @Override - void behavior() { - System.out.println("Behavior2"); - } - }, - NOD { - @Override - void behavior() { - System.out.println("Behavior3"); - } - }; - abstract void behavior(); -} - -public class NotClasses { - // void f1(LikeClasses.WINKEN instance) {} // Nope -} -/* Output: (First 12 Lines) -Compiled from "NotClasses.java" -abstract class LikeClasses extends -java.lang.Enum { - public static final LikeClasses WINKEN; - - public static final LikeClasses BLINKEN; - - public static final LikeClasses NOD; - - public static LikeClasses[] values(); - Code: - 0: getstatic #2 // Field -$VALUES:[LLikeClasses; - 3: invokevirtual #3 // Method -"[LLikeClasses;".clone:()Ljava/lang/Object; - ... -*/ diff --git a/code/enums/Outcome.java b/code/enums/Outcome.java deleted file mode 100644 index 0e2a25d6..00000000 --- a/code/enums/Outcome.java +++ /dev/null @@ -1,6 +0,0 @@ -// enums/Outcome.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package enums; -public enum Outcome { WIN, LOSE, DRAW } diff --git a/code/enums/OverrideConstantSpecific.java b/code/enums/OverrideConstantSpecific.java deleted file mode 100644 index 28e3343b..00000000 --- a/code/enums/OverrideConstantSpecific.java +++ /dev/null @@ -1,28 +0,0 @@ -// enums/OverrideConstantSpecific.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public enum OverrideConstantSpecific { - NUT, BOLT, - WASHER { - @Override - void f() { - System.out.println("Overridden method"); - } - }; - void f() { - System.out.println("default behavior"); - } - public static void main(String[] args) { - for(OverrideConstantSpecific ocs : values()) { - System.out.print(ocs + ": "); - ocs.f(); - } - } -} -/* Output: -NUT: default behavior -BOLT: default behavior -WASHER: Overridden method -*/ diff --git a/code/enums/OzWitch.java b/code/enums/OzWitch.java deleted file mode 100644 index c9eedb4f..00000000 --- a/code/enums/OzWitch.java +++ /dev/null @@ -1,32 +0,0 @@ -// enums/OzWitch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The witches in the land of Oz - -public enum OzWitch { - // Instances must be defined first, before methods: - WEST("Miss Gulch, aka the Wicked Witch of the West"), - NORTH("Glinda, the Good Witch of the North"), - EAST("Wicked Witch of the East, wearer of the Ruby " + - "Slippers, crushed by Dorothy's house"), - SOUTH("Good by inference, but missing"); - private String description; - // Constructor must be package or private access: - private OzWitch(String description) { - this.description = description; - } - public String getDescription() { return description; } - public static void main(String[] args) { - for(OzWitch witch : OzWitch.values()) - System.out.println( - witch + ": " + witch.getDescription()); - } -} -/* Output: -WEST: Miss Gulch, aka the Wicked Witch of the West -NORTH: Glinda, the Good Witch of the North -EAST: Wicked Witch of the East, wearer of the Ruby -Slippers, crushed by Dorothy's house -SOUTH: Good by inference, but missing -*/ diff --git a/code/enums/PostOffice.java b/code/enums/PostOffice.java deleted file mode 100644 index 05634820..00000000 --- a/code/enums/PostOffice.java +++ /dev/null @@ -1,197 +0,0 @@ -// enums/PostOffice.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Modeling a post office -import java.util.*; -import onjava.*; - -class Mail { - // The NO's reduce probability of random selection: - enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5} - enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4} - enum Readability {ILLEGIBLE,YES1,YES2,YES3,YES4} - enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6} - enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5} - GeneralDelivery generalDelivery; - Scannability scannability; - Readability readability; - Address address; - ReturnAddress returnAddress; - static long counter = 0; - long id = counter++; - @Override - public String toString() { return "Mail " + id; } - public String details() { - return toString() + - ", General Delivery: " + generalDelivery + - ", Address Scanability: " + scannability + - ", Address Readability: " + readability + - ", Address Address: " + address + - ", Return address: " + returnAddress; - } - // Generate test Mail: - public static Mail randomMail() { - Mail m = new Mail(); - m.generalDelivery = - Enums.random(GeneralDelivery.class); - m.scannability = - Enums.random(Scannability.class); - m.readability = - Enums.random(Readability.class); - m.address = Enums.random(Address.class); - m.returnAddress = - Enums.random(ReturnAddress.class); - return m; - } - public static - Iterable generator(final int count) { - return new Iterable() { - int n = count; - @Override - public Iterator iterator() { - return new Iterator() { - @Override - public boolean hasNext() { - return n-- > 0; - } - @Override - public Mail next() { - return randomMail(); - } - @Override - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - }; - } - }; - } -} - -public class PostOffice { - enum MailHandler { - GENERAL_DELIVERY { - @Override - boolean handle(Mail m) { - switch(m.generalDelivery) { - case YES: - System.out.println( - "Using general delivery for " + m); - return true; - default: return false; - } - } - }, - MACHINE_SCAN { - @Override - boolean handle(Mail m) { - switch(m.scannability) { - case UNSCANNABLE: return false; - default: - switch(m.address) { - case INCORRECT: return false; - default: - System.out.println( - "Delivering "+ m + " automatically"); - return true; - } - } - } - }, - VISUAL_INSPECTION { - @Override - boolean handle(Mail m) { - switch(m.readability) { - case ILLEGIBLE: return false; - default: - switch(m.address) { - case INCORRECT: return false; - default: - System.out.println( - "Delivering " + m + " normally"); - return true; - } - } - } - }, - RETURN_TO_SENDER { - @Override - boolean handle(Mail m) { - switch(m.returnAddress) { - case MISSING: return false; - default: - System.out.println( - "Returning " + m + " to sender"); - return true; - } - } - }; - abstract boolean handle(Mail m); - } - static void handle(Mail m) { - for(MailHandler handler : MailHandler.values()) - if(handler.handle(m)) - return; - System.out.println(m + " is a dead letter"); - } - public static void main(String[] args) { - for(Mail mail : Mail.generator(10)) { - System.out.println(mail.details()); - handle(mail); - System.out.println("*****"); - } - } -} -/* Output: -Mail 0, General Delivery: NO2, Address Scanability: -UNSCANNABLE, Address Readability: YES3, Address -Address: OK1, Return address: OK1 -Delivering Mail 0 normally -***** -Mail 1, General Delivery: NO5, Address Scanability: -YES3, Address Readability: ILLEGIBLE, Address Address: -OK5, Return address: OK1 -Delivering Mail 1 automatically -***** -Mail 2, General Delivery: YES, Address Scanability: -YES3, Address Readability: YES1, Address Address: OK1, -Return address: OK5 -Using general delivery for Mail 2 -***** -Mail 3, General Delivery: NO4, Address Scanability: -YES3, Address Readability: YES1, Address Address: -INCORRECT, Return address: OK4 -Returning Mail 3 to sender -***** -Mail 4, General Delivery: NO4, Address Scanability: -UNSCANNABLE, Address Readability: YES1, Address -Address: INCORRECT, Return address: OK2 -Returning Mail 4 to sender -***** -Mail 5, General Delivery: NO3, Address Scanability: -YES1, Address Readability: ILLEGIBLE, Address Address: -OK4, Return address: OK2 -Delivering Mail 5 automatically -***** -Mail 6, General Delivery: YES, Address Scanability: -YES4, Address Readability: ILLEGIBLE, Address Address: -OK4, Return address: OK4 -Using general delivery for Mail 6 -***** -Mail 7, General Delivery: YES, Address Scanability: -YES3, Address Readability: YES4, Address Address: OK2, -Return address: MISSING -Using general delivery for Mail 7 -***** -Mail 8, General Delivery: NO3, Address Scanability: -YES1, Address Readability: YES3, Address Address: -INCORRECT, Return address: MISSING -Mail 8 is a dead letter -***** -Mail 9, General Delivery: NO1, Address Scanability: -UNSCANNABLE, Address Readability: YES2, Address -Address: OK1, Return address: OK4 -Delivering Mail 9 normally -***** -*/ diff --git a/code/enums/RandomTest.java b/code/enums/RandomTest.java deleted file mode 100644 index 92f2e481..00000000 --- a/code/enums/RandomTest.java +++ /dev/null @@ -1,21 +0,0 @@ -// enums/RandomTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; - -enum Activity { SITTING, LYING, STANDING, HOPPING, - RUNNING, DODGING, JUMPING, FALLING, FLYING } - -public class RandomTest { - public static void main(String[] args) { - for(int i = 0; i < 20; i++) - System.out.print( - Enums.random(Activity.class) + " "); - } -} -/* Output: -STANDING FLYING RUNNING STANDING RUNNING STANDING LYING -DODGING SITTING RUNNING HOPPING HOPPING HOPPING RUNNING -STANDING LYING FALLING RUNNING FLYING LYING -*/ diff --git a/code/enums/Reflection.java b/code/enums/Reflection.java deleted file mode 100644 index 822a134e..00000000 --- a/code/enums/Reflection.java +++ /dev/null @@ -1,71 +0,0 @@ -// enums/Reflection.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Analyzing enums using reflection -import java.lang.reflect.*; -import java.util.*; -import onjava.*; - -enum Explore { HERE, THERE } - -public class Reflection { - public static - Set analyze(Class enumClass) { - System.out.println( - "_____ Analyzing " + enumClass + " _____"); - System.out.println("Interfaces:"); - for(Type t : enumClass.getGenericInterfaces()) - System.out.println(t); - System.out.println( - "Base: " + enumClass.getSuperclass()); - System.out.println("Methods: "); - Set methods = new TreeSet<>(); - for(Method m : enumClass.getMethods()) - methods.add(m.getName()); - System.out.println(methods); - return methods; - } - public static void main(String[] args) { - Set exploreMethods = - analyze(Explore.class); - Set enumMethods = analyze(Enum.class); - System.out.println( - "Explore.containsAll(Enum)? " + - exploreMethods.containsAll(enumMethods)); - System.out.print("Explore.removeAll(Enum): "); - exploreMethods.removeAll(enumMethods); - System.out.println(exploreMethods); - // Decompile the code for the enum: - OSExecute.command( - "javap -cp build/classes/java/main Explore"); - } -} -/* Output: -_____ Analyzing class Explore _____ -Interfaces: -Base: class java.lang.Enum -Methods: -[compareTo, equals, getClass, getDeclaringClass, -hashCode, name, notify, notifyAll, ordinal, toString, -valueOf, values, wait] -_____ Analyzing class java.lang.Enum _____ -Interfaces: -java.lang.Comparable -interface java.io.Serializable -Base: class java.lang.Object -Methods: -[compareTo, equals, getClass, getDeclaringClass, -hashCode, name, notify, notifyAll, ordinal, toString, -valueOf, wait] -Explore.containsAll(Enum)? true -Explore.removeAll(Enum): [values] -Compiled from "Reflection.java" -final class Explore extends java.lang.Enum { - public static final Explore HERE; - public static final Explore THERE; - public static Explore[] values(); - public static Explore valueOf(java.lang.String); - static {}; -} -*/ diff --git a/code/enums/RoShamBo.java b/code/enums/RoShamBo.java deleted file mode 100644 index 76b3d76f..00000000 --- a/code/enums/RoShamBo.java +++ /dev/null @@ -1,21 +0,0 @@ -// enums/RoShamBo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Common tools for RoShamBo examples -package enums; -import onjava.*; - -public class RoShamBo { - public static > - void match(T a, T b) { - System.out.println( - a + " vs. " + b + ": " + a.compete(b)); - } - public static & Competitor> - void play(Class rsbClass, int size) { - for(int i = 0; i < size; i++) - match( - Enums.random(rsbClass),Enums.random(rsbClass)); - } -} diff --git a/code/enums/RoShamBo1.java b/code/enums/RoShamBo1.java deleted file mode 100644 index abf52c9c..00000000 --- a/code/enums/RoShamBo1.java +++ /dev/null @@ -1,104 +0,0 @@ -// enums/RoShamBo1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of multiple dispatching -// {java enums.RoShamBo1} -package enums; -import java.util.*; -import static enums.Outcome.*; - -interface Item { - Outcome compete(Item it); - Outcome eval(Paper p); - Outcome eval(Scissors s); - Outcome eval(Rock r); -} - -class Paper implements Item { - @Override - public Outcome compete(Item it) { - return it.eval(this); - } - @Override - public Outcome eval(Paper p) { return DRAW; } - @Override - public Outcome eval(Scissors s) { return WIN; } - @Override - public Outcome eval(Rock r) { return LOSE; } - @Override - public String toString() { return "Paper"; } -} - -class Scissors implements Item { - @Override - public Outcome compete(Item it) { - return it.eval(this); - } - @Override - public Outcome eval(Paper p) { return LOSE; } - @Override - public Outcome eval(Scissors s) { return DRAW; } - @Override - public Outcome eval(Rock r) { return WIN; } - @Override - public String toString() { return "Scissors"; } -} - -class Rock implements Item { - @Override - public Outcome compete(Item it) { - return it.eval(this); - } - @Override - public Outcome eval(Paper p) { return WIN; } - @Override - public Outcome eval(Scissors s) { return LOSE; } - @Override - public Outcome eval(Rock r) { return DRAW; } - @Override - public String toString() { return "Rock"; } -} - -public class RoShamBo1 { - static final int SIZE = 20; - private static Random rand = new Random(47); - public static Item newItem() { - switch(rand.nextInt(3)) { - default: - case 0: return new Scissors(); - case 1: return new Paper(); - case 2: return new Rock(); - } - } - public static void match(Item a, Item b) { - System.out.println( - a + " vs. " + b + ": " + a.compete(b)); - } - public static void main(String[] args) { - for(int i = 0; i < SIZE; i++) - match(newItem(), newItem()); - } -} -/* Output: -Rock vs. Rock: DRAW -Paper vs. Rock: WIN -Paper vs. Rock: WIN -Paper vs. Rock: WIN -Scissors vs. Paper: WIN -Scissors vs. Scissors: DRAW -Scissors vs. Paper: WIN -Rock vs. Paper: LOSE -Paper vs. Paper: DRAW -Rock vs. Paper: LOSE -Paper vs. Scissors: LOSE -Paper vs. Scissors: LOSE -Rock vs. Scissors: WIN -Rock vs. Paper: LOSE -Paper vs. Rock: WIN -Scissors vs. Paper: WIN -Paper vs. Scissors: LOSE -Paper vs. Scissors: LOSE -Paper vs. Scissors: LOSE -Paper vs. Scissors: LOSE -*/ diff --git a/code/enums/RoShamBo2.java b/code/enums/RoShamBo2.java deleted file mode 100644 index ec8ab25b..00000000 --- a/code/enums/RoShamBo2.java +++ /dev/null @@ -1,55 +0,0 @@ -// enums/RoShamBo2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Switching one enum on another -// {java enums.RoShamBo2} -package enums; -import static enums.Outcome.*; - -public enum RoShamBo2 implements Competitor { - PAPER(DRAW, LOSE, WIN), - SCISSORS(WIN, DRAW, LOSE), - ROCK(LOSE, WIN, DRAW); - private Outcome vPAPER, vSCISSORS, vROCK; - RoShamBo2(Outcome paper, - Outcome scissors, Outcome rock) { - this.vPAPER = paper; - this.vSCISSORS = scissors; - this.vROCK = rock; - } - @Override - public Outcome compete(RoShamBo2 it) { - switch(it) { - default: - case PAPER: return vPAPER; - case SCISSORS: return vSCISSORS; - case ROCK: return vROCK; - } - } - public static void main(String[] args) { - RoShamBo.play(RoShamBo2.class, 20); - } -} -/* Output: -ROCK vs. ROCK: DRAW -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -PAPER vs. PAPER: DRAW -PAPER vs. SCISSORS: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. SCISSORS: DRAW -ROCK vs. SCISSORS: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -ROCK vs. PAPER: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -*/ diff --git a/code/enums/RoShamBo3.java b/code/enums/RoShamBo3.java deleted file mode 100644 index ffcd2cf1..00000000 --- a/code/enums/RoShamBo3.java +++ /dev/null @@ -1,71 +0,0 @@ -// enums/RoShamBo3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using constant-specific methods -// {java enums.RoShamBo3} -package enums; -import static enums.Outcome.*; - -public enum RoShamBo3 implements Competitor { - PAPER { - @Override - public Outcome compete(RoShamBo3 it) { - switch(it) { - default: // To placate the compiler - case PAPER: return DRAW; - case SCISSORS: return LOSE; - case ROCK: return WIN; - } - } - }, - SCISSORS { - @Override - public Outcome compete(RoShamBo3 it) { - switch(it) { - default: - case PAPER: return WIN; - case SCISSORS: return DRAW; - case ROCK: return LOSE; - } - } - }, - ROCK { - @Override - public Outcome compete(RoShamBo3 it) { - switch(it) { - default: - case PAPER: return LOSE; - case SCISSORS: return WIN; - case ROCK: return DRAW; - } - } - }; - @Override - public abstract Outcome compete(RoShamBo3 it); - public static void main(String[] args) { - RoShamBo.play(RoShamBo3.class, 20); - } -} -/* Output: -ROCK vs. ROCK: DRAW -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -PAPER vs. PAPER: DRAW -PAPER vs. SCISSORS: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. SCISSORS: DRAW -ROCK vs. SCISSORS: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -ROCK vs. PAPER: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -*/ diff --git a/code/enums/RoShamBo4.java b/code/enums/RoShamBo4.java deleted file mode 100644 index f0b473ae..00000000 --- a/code/enums/RoShamBo4.java +++ /dev/null @@ -1,57 +0,0 @@ -// enums/RoShamBo4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java enums.RoShamBo4} -package enums; - -public enum RoShamBo4 implements Competitor { - ROCK { - @Override - public Outcome compete(RoShamBo4 opponent) { - return compete(SCISSORS, opponent); - } - }, - SCISSORS { - @Override - public Outcome compete(RoShamBo4 opponent) { - return compete(PAPER, opponent); - } - }, - PAPER { - @Override - public Outcome compete(RoShamBo4 opponent) { - return compete(ROCK, opponent); - } - }; - Outcome compete(RoShamBo4 loser, RoShamBo4 opponent) { - return ((opponent == this) ? Outcome.DRAW - : ((opponent == loser) ? Outcome.WIN - : Outcome.LOSE)); - } - public static void main(String[] args) { - RoShamBo.play(RoShamBo4.class, 20); - } -} -/* Output: -PAPER vs. PAPER: DRAW -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -ROCK vs. SCISSORS: WIN -ROCK vs. ROCK: DRAW -ROCK vs. SCISSORS: WIN -PAPER vs. SCISSORS: LOSE -SCISSORS vs. SCISSORS: DRAW -PAPER vs. SCISSORS: LOSE -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -PAPER vs. ROCK: WIN -PAPER vs. SCISSORS: LOSE -SCISSORS vs. PAPER: WIN -ROCK vs. SCISSORS: WIN -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -*/ diff --git a/code/enums/RoShamBo5.java b/code/enums/RoShamBo5.java deleted file mode 100644 index 69885c01..00000000 --- a/code/enums/RoShamBo5.java +++ /dev/null @@ -1,59 +0,0 @@ -// enums/RoShamBo5.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Multiple dispatching using an EnumMap of EnumMaps -// {java enums.RoShamBo5} -package enums; -import java.util.*; -import static enums.Outcome.*; - -enum RoShamBo5 implements Competitor { - PAPER, SCISSORS, ROCK; - static EnumMap> - table = new EnumMap<>(RoShamBo5.class); - static { - for(RoShamBo5 it : RoShamBo5.values()) - table.put(it, new EnumMap<>(RoShamBo5.class)); - initRow(PAPER, DRAW, LOSE, WIN); - initRow(SCISSORS, WIN, DRAW, LOSE); - initRow(ROCK, LOSE, WIN, DRAW); - } - static void initRow(RoShamBo5 it, - Outcome vPAPER, Outcome vSCISSORS, Outcome vROCK) { - EnumMap row = - RoShamBo5.table.get(it); - row.put(RoShamBo5.PAPER, vPAPER); - row.put(RoShamBo5.SCISSORS, vSCISSORS); - row.put(RoShamBo5.ROCK, vROCK); - } - @Override - public Outcome compete(RoShamBo5 it) { - return table.get(this).get(it); - } - public static void main(String[] args) { - RoShamBo.play(RoShamBo5.class, 20); - } -} -/* Output: -ROCK vs. ROCK: DRAW -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -PAPER vs. PAPER: DRAW -PAPER vs. SCISSORS: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. SCISSORS: DRAW -ROCK vs. SCISSORS: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -ROCK vs. PAPER: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -*/ diff --git a/code/enums/RoShamBo6.java b/code/enums/RoShamBo6.java deleted file mode 100644 index 164911d5..00000000 --- a/code/enums/RoShamBo6.java +++ /dev/null @@ -1,46 +0,0 @@ -// enums/RoShamBo6.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Enums using "tables" instead of multiple dispatch -// {java enums.RoShamBo6} -package enums; -import static enums.Outcome.*; - -enum RoShamBo6 implements Competitor { - PAPER, SCISSORS, ROCK; - private static Outcome[][] table = { - { DRAW, LOSE, WIN }, // PAPER - { WIN, DRAW, LOSE }, // SCISSORS - { LOSE, WIN, DRAW }, // ROCK - }; - @Override - public Outcome compete(RoShamBo6 other) { - return table[this.ordinal()][other.ordinal()]; - } - public static void main(String[] args) { - RoShamBo.play(RoShamBo6.class, 20); - } -} -/* Output: -ROCK vs. ROCK: DRAW -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -PAPER vs. PAPER: DRAW -PAPER vs. SCISSORS: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. SCISSORS: DRAW -ROCK vs. SCISSORS: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -ROCK vs. PAPER: LOSE -ROCK vs. SCISSORS: WIN -SCISSORS vs. ROCK: LOSE -PAPER vs. SCISSORS: LOSE -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -SCISSORS vs. PAPER: WIN -*/ diff --git a/code/enums/SecurityCategory.java b/code/enums/SecurityCategory.java deleted file mode 100644 index 884cb56a..00000000 --- a/code/enums/SecurityCategory.java +++ /dev/null @@ -1,46 +0,0 @@ -// enums/SecurityCategory.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// More succinct subcategorization of enums -import onjava.*; - -enum SecurityCategory { - STOCK(Security.Stock.class), - BOND(Security.Bond.class); - Security[] values; - SecurityCategory(Class kind) { - values = kind.getEnumConstants(); - } - interface Security { - enum Stock implements Security { - SHORT, LONG, MARGIN - } - enum Bond implements Security { - MUNICIPAL, JUNK - } - } - public Security randomSelection() { - return Enums.random(values); - } - public static void main(String[] args) { - for(int i = 0; i < 10; i++) { - SecurityCategory category = - Enums.random(SecurityCategory.class); - System.out.println(category + ": " + - category.randomSelection()); - } - } -} -/* Output: -BOND: MUNICIPAL -BOND: MUNICIPAL -STOCK: MARGIN -STOCK: MARGIN -BOND: JUNK -STOCK: SHORT -STOCK: LONG -STOCK: LONG -BOND: MUNICIPAL -BOND: JUNK -*/ diff --git a/code/enums/SpaceShip.java b/code/enums/SpaceShip.java deleted file mode 100644 index 3623389e..00000000 --- a/code/enums/SpaceShip.java +++ /dev/null @@ -1,28 +0,0 @@ -// enums/SpaceShip.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public enum SpaceShip { - SCOUT, CARGO, TRANSPORT, - CRUISER, BATTLESHIP, MOTHERSHIP; - @Override - public String toString() { - String id = name(); - String lower = id.substring(1).toLowerCase(); - return id.charAt(0) + lower; - } - public static void main(String[] args) { - Stream.of(values()) - .forEach(System.out::println); - } -} -/* Output: -Scout -Cargo -Transport -Cruiser -Battleship -Mothership -*/ diff --git a/code/enums/SpicinessEnum.java b/code/enums/SpicinessEnum.java deleted file mode 100644 index eef6f89a..00000000 --- a/code/enums/SpicinessEnum.java +++ /dev/null @@ -1,9 +0,0 @@ -// enums/SpicinessEnum.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package enums; - -public enum SpicinessEnum { - NOT, MILD, MEDIUM, HOT, FLAMING -} diff --git a/code/enums/TrafficLight.java b/code/enums/TrafficLight.java deleted file mode 100644 index b018e02c..00000000 --- a/code/enums/TrafficLight.java +++ /dev/null @@ -1,44 +0,0 @@ -// enums/TrafficLight.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Enums in switch statements - -// Define an enum type: -enum Signal { GREEN, YELLOW, RED, } - -public class TrafficLight { - Signal color = Signal.RED; - public void change() { - switch(color) { - // Note you don't have to say Signal.RED - // in the case statement: - case RED: color = Signal.GREEN; - break; - case GREEN: color = Signal.YELLOW; - break; - case YELLOW: color = Signal.RED; - break; - } - } - @Override - public String toString() { - return "The traffic light is " + color; - } - public static void main(String[] args) { - TrafficLight t = new TrafficLight(); - for(int i = 0; i < 7; i++) { - System.out.println(t); - t.change(); - } - } -} -/* Output: -The traffic light is RED -The traffic light is GREEN -The traffic light is YELLOW -The traffic light is RED -The traffic light is GREEN -The traffic light is YELLOW -The traffic light is RED -*/ diff --git a/code/enums/UpcastEnum.java b/code/enums/UpcastEnum.java deleted file mode 100644 index a5df2a86..00000000 --- a/code/enums/UpcastEnum.java +++ /dev/null @@ -1,21 +0,0 @@ -// enums/UpcastEnum.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// No values() method if you upcast an enum - -enum Search { HITHER, YON } - -public class UpcastEnum { - public static void main(String[] args) { - Search[] vals = Search.values(); - Enum e = Search.HITHER; // Upcast - // e.values(); // No values() in Enum - for(Enum en : e.getClass().getEnumConstants()) - System.out.println(en); - } -} -/* Output: -HITHER -YON -*/ diff --git a/code/enums/VendingMachine.java b/code/enums/VendingMachine.java deleted file mode 100644 index bc7d7c19..00000000 --- a/code/enums/VendingMachine.java +++ /dev/null @@ -1,183 +0,0 @@ -// enums/VendingMachine.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java VendingMachine VendingMachineInput.txt} -import java.util.*; -import java.io.IOException; -import java.util.function.*; -import java.nio.file.*; -import java.util.stream.*; - -enum Category { - MONEY(Input.NICKEL, Input.DIME, - Input.QUARTER, Input.DOLLAR), - ITEM_SELECTION(Input.TOOTHPASTE, Input.CHIPS, - Input.SODA, Input.SOAP), - QUIT_TRANSACTION(Input.ABORT_TRANSACTION), - SHUT_DOWN(Input.STOP); - private Input[] values; - Category(Input... types) { values = types; } - private static EnumMap categories = - new EnumMap<>(Input.class); - static { - for(Category c : Category.class.getEnumConstants()) - for(Input type : c.values) - categories.put(type, c); - } - public static Category categorize(Input input) { - return categories.get(input); - } -} - -public class VendingMachine { - private static State state = State.RESTING; - private static int amount = 0; - private static Input selection = null; - enum StateDuration { TRANSIENT } // Tagging enum - enum State { - RESTING { - @Override - void next(Input input) { - switch(Category.categorize(input)) { - case MONEY: - amount += input.amount(); - state = ADDING_MONEY; - break; - case SHUT_DOWN: - state = TERMINAL; - default: - } - } - }, - ADDING_MONEY { - @Override - void next(Input input) { - switch(Category.categorize(input)) { - case MONEY: - amount += input.amount(); - break; - case ITEM_SELECTION: - selection = input; - if(amount < selection.amount()) - System.out.println( - "Insufficient money for " + selection); - else state = DISPENSING; - break; - case QUIT_TRANSACTION: - state = GIVING_CHANGE; - break; - case SHUT_DOWN: - state = TERMINAL; - default: - } - } - }, - DISPENSING(StateDuration.TRANSIENT) { - @Override - void next() { - System.out.println("here is your " + selection); - amount -= selection.amount(); - state = GIVING_CHANGE; - } - }, - GIVING_CHANGE(StateDuration.TRANSIENT) { - @Override - void next() { - if(amount > 0) { - System.out.println("Your change: " + amount); - amount = 0; - } - state = RESTING; - } - }, - TERMINAL {@Override - void output() { System.out.println("Halted"); } }; - private boolean isTransient = false; - State() {} - State(StateDuration trans) { isTransient = true; } - void next(Input input) { - throw new RuntimeException("Only call " + - "next(Input input) for non-transient states"); - } - void next() { - throw new RuntimeException( - "Only call next() for " + - "StateDuration.TRANSIENT states"); - } - void output() { System.out.println(amount); } - } - static void run(Supplier gen) { - while(state != State.TERMINAL) { - state.next(gen.get()); - while(state.isTransient) - state.next(); - state.output(); - } - } - public static void main(String[] args) { - Supplier gen = new RandomInputSupplier(); - if(args.length == 1) - gen = new FileInputSupplier(args[0]); - run(gen); - } -} - -// For a basic sanity check: -class RandomInputSupplier implements Supplier { - @Override - public Input get() { - return Input.randomSelection(); - } -} - -// Create Inputs from a file of ';'-separated strings: -class FileInputSupplier implements Supplier { - private Iterator input; - FileInputSupplier(String fileName) { - try { - input = Files.lines(Paths.get(fileName)) - .skip(1) // Skip the comment line - .flatMap(s -> Arrays.stream(s.split(";"))) - .map(String::trim) - .collect(Collectors.toList()) - .iterator(); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - @Override - public Input get() { - if(!input.hasNext()) - return null; - return Enum.valueOf( - Input.class, input.next().trim()); - } -} -/* Output: -25 -50 -75 -here is your CHIPS -0 -100 -200 -here is your TOOTHPASTE -0 -25 -35 -Your change: 35 -0 -25 -35 -Insufficient money for SODA -35 -60 -70 -75 -Insufficient money for SODA -75 -Your change: 75 -0 -Halted -*/ diff --git a/code/enums/VendingMachineInput.txt b/code/enums/VendingMachineInput.txt deleted file mode 100644 index b39554f0..00000000 --- a/code/enums/VendingMachineInput.txt +++ /dev/null @@ -1,8 +0,0 @@ -// enums/VendingMachineInput.txt -QUARTER; QUARTER; QUARTER; CHIPS; -DOLLAR; DOLLAR; TOOTHPASTE; -QUARTER; DIME; ABORT_TRANSACTION; -QUARTER; DIME; SODA; -QUARTER; DIME; NICKEL; SODA; -ABORT_TRANSACTION; -STOP; diff --git a/code/enums/cartoons/EnumImplementation.java b/code/enums/cartoons/EnumImplementation.java deleted file mode 100644 index 58902e3f..00000000 --- a/code/enums/cartoons/EnumImplementation.java +++ /dev/null @@ -1,37 +0,0 @@ -// enums/cartoons/EnumImplementation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An enum can implement an interface -// {java enums.cartoons.EnumImplementation} -package enums.cartoons; -import java.util.*; -import java.util.function.*; - -enum CartoonCharacter -implements Supplier { - SLAPPY, SPANKY, PUNCHY, - SILLY, BOUNCY, NUTTY, BOB; - private Random rand = - new Random(47); - @Override - public CartoonCharacter get() { - return values()[rand.nextInt(values().length)]; - } -} - -public class EnumImplementation { - public static void printNext(Supplier rg) { - System.out.print(rg.get() + ", "); - } - public static void main(String[] args) { - // Choose any instance: - CartoonCharacter cc = CartoonCharacter.BOB; - for(int i = 0; i < 10; i++) - printNext(cc); - } -} -/* Output: -BOB, PUNCHY, BOB, SPANKY, NUTTY, PUNCHY, SLAPPY, NUTTY, -NUTTY, SLAPPY, -*/ diff --git a/code/enums/menu/Course.java b/code/enums/menu/Course.java deleted file mode 100644 index 96481f1e..00000000 --- a/code/enums/menu/Course.java +++ /dev/null @@ -1,20 +0,0 @@ -// enums/menu/Course.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package enums.menu; -import onjava.*; - -public enum Course { - APPETIZER(Food.Appetizer.class), - MAINCOURSE(Food.MainCourse.class), - DESSERT(Food.Dessert.class), - COFFEE(Food.Coffee.class); - private Food[] values; - private Course(Class kind) { - values = kind.getEnumConstants(); - } - public Food randomSelection() { - return Enums.random(values); - } -} diff --git a/code/enums/menu/Food.java b/code/enums/menu/Food.java deleted file mode 100644 index 4b97f69e..00000000 --- a/code/enums/menu/Food.java +++ /dev/null @@ -1,24 +0,0 @@ -// enums/menu/Food.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Subcategorization of enums within interfaces -package enums.menu; - -public interface Food { - enum Appetizer implements Food { - SALAD, SOUP, SPRING_ROLLS; - } - enum MainCourse implements Food { - LASAGNE, BURRITO, PAD_THAI, - LENTILS, HUMMOUS, VINDALOO; - } - enum Dessert implements Food { - TIRAMISU, GELATO, BLACK_FOREST_CAKE, - FRUIT, CREME_CARAMEL; - } - enum Coffee implements Food { - BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, - LATTE, CAPPUCCINO, TEA, HERB_TEA; - } -} diff --git a/code/enums/menu/Meal.java b/code/enums/menu/Meal.java deleted file mode 100644 index 64bc496d..00000000 --- a/code/enums/menu/Meal.java +++ /dev/null @@ -1,45 +0,0 @@ -// enums/menu/Meal.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java enums.menu.Meal} -package enums.menu; - -public class Meal { - public static void main(String[] args) { - for(int i = 0; i < 5; i++) { - for(Course course : Course.values()) { - Food food = course.randomSelection(); - System.out.println(food); - } - System.out.println("***"); - } - } -} -/* Output: -SPRING_ROLLS -VINDALOO -FRUIT -DECAF_COFFEE -*** -SOUP -VINDALOO -FRUIT -TEA -*** -SALAD -BURRITO -FRUIT -TEA -*** -SALAD -BURRITO -CREME_CARAMEL -LATTE -*** -SOUP -BURRITO -TIRAMISU -ESPRESSO -*** -*/ diff --git a/code/enums/menu/Meal2.java b/code/enums/menu/Meal2.java deleted file mode 100644 index df1b90a5..00000000 --- a/code/enums/menu/Meal2.java +++ /dev/null @@ -1,74 +0,0 @@ -// enums/menu/Meal2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java enums.menu.Meal2} -package enums.menu; -import onjava.*; - -public enum Meal2 { - APPETIZER(Food.Appetizer.class), - MAINCOURSE(Food.MainCourse.class), - DESSERT(Food.Dessert.class), - COFFEE(Food.Coffee.class); - private Food[] values; - private Meal2(Class kind) { - values = kind.getEnumConstants(); - } - public interface Food { - enum Appetizer implements Food { - SALAD, SOUP, SPRING_ROLLS; - } - enum MainCourse implements Food { - LASAGNE, BURRITO, PAD_THAI, - LENTILS, HUMMOUS, VINDALOO; - } - enum Dessert implements Food { - TIRAMISU, GELATO, BLACK_FOREST_CAKE, - FRUIT, CREME_CARAMEL; - } - enum Coffee implements Food { - BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, - LATTE, CAPPUCCINO, TEA, HERB_TEA; - } - } - public Food randomSelection() { - return Enums.random(values); - } - public static void main(String[] args) { - for(int i = 0; i < 5; i++) { - for(Meal2 meal : Meal2.values()) { - Food food = meal.randomSelection(); - System.out.println(food); - } - System.out.println("***"); - } - } -} -/* Output: -SPRING_ROLLS -VINDALOO -FRUIT -DECAF_COFFEE -*** -SOUP -VINDALOO -FRUIT -TEA -*** -SALAD -BURRITO -FRUIT -TEA -*** -SALAD -BURRITO -CREME_CARAMEL -LATTE -*** -SOUP -BURRITO -TIRAMISU -ESPRESSO -*** -*/ diff --git a/code/enums/menu/TypeOfFood.java b/code/enums/menu/TypeOfFood.java deleted file mode 100644 index 5e59e78b..00000000 --- a/code/enums/menu/TypeOfFood.java +++ /dev/null @@ -1,16 +0,0 @@ -// enums/menu/TypeOfFood.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java enums.menu.TypeOfFood} -package enums.menu; -import static enums.menu.Food.*; - -public class TypeOfFood { - public static void main(String[] args) { - Food food = Appetizer.SALAD; - food = MainCourse.LASAGNE; - food = Dessert.GELATO; - food = Coffee.CAPPUCCINO; - } -} diff --git a/code/equalshashcode/ComposedEquality.java b/code/equalshashcode/ComposedEquality.java deleted file mode 100644 index c224231c..00000000 --- a/code/equalshashcode/ComposedEquality.java +++ /dev/null @@ -1,66 +0,0 @@ -// equalshashcode/ComposedEquality.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class Part { - String ss; - double dd; - Part(String ss, double dd) { - this.ss = ss; - this.dd = dd; - } - @Override - public boolean equals(Object rval) { - return rval instanceof Part && - Objects.equals(ss, ((Part)rval).ss) && - Objects.equals(dd, ((Part)rval).dd); - } -} - -public class ComposedEquality extends SuccinctEquality { - Part part; - public ComposedEquality(int i, String s, double d) { - super(i, s, d); - part = new Part(s, d); - System.out.println("made 'ComposedEquality'"); - } - @Override - public boolean equals(Object rval) { - return rval instanceof ComposedEquality && - super.equals(rval) && - Objects.equals(part, - ((ComposedEquality)rval).part); - } - public static void main(String[] args) { - Equality.testAll( (i, s, d) -> - new ComposedEquality(i, s, d)); - } -} -/* Output: -made 'Equality' -made 'SuccinctEquality' -made 'ComposedEquality' -made 'Equality' -made 'SuccinctEquality' -made 'ComposedEquality' -made 'Equality' -made 'SuccinctEquality' -made 'ComposedEquality' --- Testing null -- -null instanceof Equality: false -Expected false, got false --- Testing same object -- -same object instanceof Equality: true -Expected true, got true --- Testing different type -- -different type instanceof Equality: false -Expected false, got false --- Testing same values -- -same values instanceof Equality: true -Expected true, got true --- Testing different values -- -different values instanceof Equality: true -Expected false, got false -*/ diff --git a/code/equalshashcode/CountedString.java b/code/equalshashcode/CountedString.java deleted file mode 100644 index 5a6ec5fa..00000000 --- a/code/equalshashcode/CountedString.java +++ /dev/null @@ -1,72 +0,0 @@ -// equalshashcode/CountedString.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating a good hashCode() -import java.util.*; - -public class CountedString { - private static List created = - new ArrayList<>(); - private String s; - private int id = 0; - public CountedString(String str) { - s = str; - created.add(s); - // id is the total number of instances - // of this String used by CountedString: - for(String s2 : created) - if(s2.equals(s)) - id++; - } - @Override - public String toString() { - return "String: " + s + " id: " + id + - " hashCode(): " + hashCode(); - } - @Override - public int hashCode() { - // The very simple approach: - // return s.hashCode() * id; - // Using Joshua Bloch's recipe: - int result = 17; - result = 37 * result + s.hashCode(); - result = 37 * result + id; - return result; - } - @Override - public boolean equals(Object o) { - return o instanceof CountedString && - Objects.equals(s, ((CountedString)o).s) && - Objects.equals(id, ((CountedString)o).id); - } - public static void main(String[] args) { - Map map = new HashMap<>(); - CountedString[] cs = new CountedString[5]; - for(int i = 0; i < cs.length; i++) { - cs[i] = new CountedString("hi"); - map.put(cs[i], i); // Autobox int to Integer - } - System.out.println(map); - for(CountedString cstring : cs) { - System.out.println("Looking up " + cstring); - System.out.println(map.get(cstring)); - } - } -} -/* Output: -{String: hi id: 4 hashCode(): 146450=3, String: hi id: -5 hashCode(): 146451=4, String: hi id: 2 hashCode(): -146448=1, String: hi id: 3 hashCode(): 146449=2, -String: hi id: 1 hashCode(): 146447=0} -Looking up String: hi id: 1 hashCode(): 146447 -0 -Looking up String: hi id: 2 hashCode(): 146448 -1 -Looking up String: hi id: 3 hashCode(): 146449 -2 -Looking up String: hi id: 4 hashCode(): 146450 -3 -Looking up String: hi id: 5 hashCode(): 146451 -4 -*/ diff --git a/code/equalshashcode/DefaultComparison.java b/code/equalshashcode/DefaultComparison.java deleted file mode 100644 index d855de36..00000000 --- a/code/equalshashcode/DefaultComparison.java +++ /dev/null @@ -1,24 +0,0 @@ -// equalshashcode/DefaultComparison.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class DefaultComparison { - private int i, j, k; - DefaultComparison(int i, int j, int k) { - this.i = i; - this.j = j; - this.k = k; - } - public static void main(String[] args) { - DefaultComparison - a = new DefaultComparison(1, 2, 3), - b = new DefaultComparison(1, 2, 3); - System.out.println(a == a); - System.out.println(a == b); - } -} -/* Output: -true -false -*/ diff --git a/code/equalshashcode/Equality.java b/code/equalshashcode/Equality.java deleted file mode 100644 index 6ab13e5e..00000000 --- a/code/equalshashcode/Equality.java +++ /dev/null @@ -1,77 +0,0 @@ -// equalshashcode/Equality.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class Equality { - protected int i; - protected String s; - protected double d; - public Equality(int i, String s, double d) { - this.i = i; - this.s = s; - this.d = d; - System.out.println("made 'Equality'"); - } - @Override - public boolean equals(Object rval) { - if(rval == null) - return false; - if(rval == this) - return true; - if(!(rval instanceof Equality)) - return false; - Equality other = (Equality)rval; - if(!Objects.equals(i, other.i)) - return false; - if(!Objects.equals(s, other.s)) - return false; - if(!Objects.equals(d, other.d)) - return false; - return true; - } - public void - test(String descr, String expected, Object rval) { - System.out.format("-- Testing %s --%n" + - "%s instanceof Equality: %s%n" + - "Expected %s, got %s%n", - descr, descr, rval instanceof Equality, - expected, equals(rval)); - } - public static void testAll(EqualityFactory eqf) { - Equality - e = eqf.make(1, "Monty", 3.14), - eq = eqf.make(1, "Monty", 3.14), - neq = eqf.make(99, "Bob", 1.618); - e.test("null", "false", null); - e.test("same object", "true", e); - e.test("different type", - "false", Integer.valueOf(99)); - e.test("same values", "true", eq); - e.test("different values", "false", neq); - } - public static void main(String[] args) { - testAll( (i, s, d) -> new Equality(i, s, d)); - } -} -/* Output: -made 'Equality' -made 'Equality' -made 'Equality' --- Testing null -- -null instanceof Equality: false -Expected false, got false --- Testing same object -- -same object instanceof Equality: true -Expected true, got true --- Testing different type -- -different type instanceof Equality: false -Expected false, got false --- Testing same values -- -same values instanceof Equality: true -Expected true, got true --- Testing different values -- -different values instanceof Equality: true -Expected false, got false -*/ diff --git a/code/equalshashcode/EqualityFactory.java b/code/equalshashcode/EqualityFactory.java deleted file mode 100644 index 378b56b0..00000000 --- a/code/equalshashcode/EqualityFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -// equalshashcode/EqualityFactory.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -interface EqualityFactory { - Equality make(int i, String s, double d); -} diff --git a/code/equalshashcode/Groundhog.java b/code/equalshashcode/Groundhog.java deleted file mode 100644 index 55c77563..00000000 --- a/code/equalshashcode/Groundhog.java +++ /dev/null @@ -1,14 +0,0 @@ -// equalshashcode/Groundhog.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Looks plausible, but doesn't work as a HashMap key - -public class Groundhog { - protected int number; - public Groundhog(int n) { number = n; } - @Override - public String toString() { - return "Groundhog #" + number; - } -} diff --git a/code/equalshashcode/Groundhog2.java b/code/equalshashcode/Groundhog2.java deleted file mode 100644 index 5348d1e5..00000000 --- a/code/equalshashcode/Groundhog2.java +++ /dev/null @@ -1,19 +0,0 @@ -// equalshashcode/Groundhog2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A class that's used as a key in a HashMap -// must override hashCode() and equals() -import java.util.*; - -public class Groundhog2 extends Groundhog { - public Groundhog2(int n) { super(n); } - @Override - public int hashCode() { return number; } - @Override - public boolean equals(Object o) { - return o instanceof Groundhog2 && - Objects.equals( - number, ((Groundhog2)o).number); - } -} diff --git a/code/equalshashcode/IndividualTest.java b/code/equalshashcode/IndividualTest.java deleted file mode 100644 index d8f50974..00000000 --- a/code/equalshashcode/IndividualTest.java +++ /dev/null @@ -1,31 +0,0 @@ -// equalshashcode/IndividualTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import collections.MapOfList; -import typeinfo.pets.*; -import java.util.*; - -public class IndividualTest { - public static void main(String[] args) { - Set pets = new TreeSet<>(); - for(List lp : - MapOfList.petPeople.values()) - for(Pet p : lp) - pets.add(p); - pets.forEach(System.out::println); - } -} -/* Output: -Cat Elsie May -Cat Pinkola -Cat Shackleton -Cat Stanford -Cymric Molly -Dog Margrett -Mutt Spot -Pug Louie aka Louis Snorkelstein Dupree -Rat Fizzy -Rat Freckly -Rat Fuzzy -*/ diff --git a/code/equalshashcode/MapEntry.java b/code/equalshashcode/MapEntry.java deleted file mode 100644 index c6e28bf4..00000000 --- a/code/equalshashcode/MapEntry.java +++ /dev/null @@ -1,42 +0,0 @@ -// equalshashcode/MapEntry.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A simple Map.Entry for sample Map implementations -import java.util.*; - -public class MapEntry implements Map.Entry { - private K key; - private V value; - public MapEntry(K key, V value) { - this.key = key; - this.value = value; - } - @Override - public K getKey() { return key; } - @Override - public V getValue() { return value; } - @Override - public V setValue(V v) { - V result = value; - value = v; - return result; - } - @Override - public int hashCode() { - return Objects.hash(key, value); - } - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object rval) { - return rval instanceof MapEntry && - Objects.equals(key, - ((MapEntry)rval).getKey()) && - Objects.equals(value, - ((MapEntry)rval).getValue()); - } - @Override - public String toString() { - return key + "=" + value; - } -} diff --git a/code/equalshashcode/Prediction.java b/code/equalshashcode/Prediction.java deleted file mode 100644 index c8ff9777..00000000 --- a/code/equalshashcode/Prediction.java +++ /dev/null @@ -1,15 +0,0 @@ -// equalshashcode/Prediction.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Predicting the weather -import java.util.*; - -public class Prediction { - private static Random rand = new Random(47); - @Override - public String toString() { - return rand.nextBoolean() ? - "Six more weeks of Winter!" : "Early Spring!"; - } -} diff --git a/code/equalshashcode/SimpleHashMap.java b/code/equalshashcode/SimpleHashMap.java deleted file mode 100644 index f82022a1..00000000 --- a/code/equalshashcode/SimpleHashMap.java +++ /dev/null @@ -1,90 +0,0 @@ -// equalshashcode/SimpleHashMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A demonstration hashed Map -import java.util.*; -import onjava.*; - -public -class SimpleHashMap extends AbstractMap { - // Choose a prime number for the hash table - // size, to achieve a uniform distribution: - static final int SIZE = 997; - // You can't have a physical array of generics, - // but you can upcast to one: - @SuppressWarnings("unchecked") - LinkedList>[] buckets = - new LinkedList[SIZE]; - @Override - public V put(K key, V value) { - V oldValue = null; - int index = Math.abs(key.hashCode()) % SIZE; - if(buckets[index] == null) - buckets[index] = new LinkedList<>(); - LinkedList> bucket = buckets[index]; - MapEntry pair = new MapEntry<>(key, value); - boolean found = false; - ListIterator> it = - bucket.listIterator(); - while(it.hasNext()) { - MapEntry iPair = it.next(); - if(iPair.getKey().equals(key)) { - oldValue = iPair.getValue(); - it.set(pair); // Replace old with new - found = true; - break; - } - } - if(!found) - buckets[index].add(pair); - return oldValue; - } - @Override - public V get(Object key) { - int index = Math.abs(key.hashCode()) % SIZE; - if(buckets[index] == null) return null; - for(MapEntry iPair : buckets[index]) - if(iPair.getKey().equals(key)) - return iPair.getValue(); - return null; - } - @Override - public Set> entrySet() { - Set> set= new HashSet<>(); - for(LinkedList> bucket : buckets) { - if(bucket == null) continue; - for(MapEntry mpair : bucket) - set.add(mpair); - } - return set; - } - public static void main(String[] args) { - SimpleHashMap m = - new SimpleHashMap<>(); - m.putAll(Countries.capitals(8)); - m.forEach((k, v) -> - System.out.println(k + "=" + v)); - System.out.println(m.get("BENIN")); - m.entrySet().forEach(System.out::println); - } -} -/* Output: -CAMEROON=Yaounde -ANGOLA=Luanda -BURKINA FASO=Ouagadougou -BURUNDI=Bujumbura -ALGERIA=Algiers -BENIN=Porto-Novo -CAPE VERDE=Praia -BOTSWANA=Gaberone -Porto-Novo -CAMEROON=Yaounde -ANGOLA=Luanda -BURKINA FASO=Ouagadougou -BURUNDI=Bujumbura -ALGERIA=Algiers -BENIN=Porto-Novo -CAPE VERDE=Praia -BOTSWANA=Gaberone -*/ diff --git a/code/equalshashcode/SlowMap.java b/code/equalshashcode/SlowMap.java deleted file mode 100644 index 63f17092..00000000 --- a/code/equalshashcode/SlowMap.java +++ /dev/null @@ -1,64 +0,0 @@ -// equalshashcode/SlowMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A Map implemented with ArrayLists -import java.util.*; -import onjava.*; - -public class SlowMap extends AbstractMap { - private List keys = new ArrayList<>(); - private List values = new ArrayList<>(); - @Override - public V put(K key, V value) { - V oldValue = get(key); // The old value or null - if(!keys.contains(key)) { - keys.add(key); - values.add(value); - } else - values.set(keys.indexOf(key), value); - return oldValue; - } - @Override - public V get(Object key) { // key: type Object, not K - if(!keys.contains(key)) - return null; - return values.get(keys.indexOf(key)); - } - @Override - public Set> entrySet() { - Set> set= new HashSet<>(); - Iterator ki = keys.iterator(); - Iterator vi = values.iterator(); - while(ki.hasNext()) - set.add(new MapEntry<>(ki.next(), vi.next())); - return set; - } - public static void main(String[] args) { - SlowMap m= new SlowMap<>(); - m.putAll(Countries.capitals(8)); - m.forEach((k, v) -> - System.out.println(k + "=" + v)); - System.out.println(m.get("BENIN")); - m.entrySet().forEach(System.out::println); - } -} -/* Output: -CAMEROON=Yaounde -ANGOLA=Luanda -BURKINA FASO=Ouagadougou -BURUNDI=Bujumbura -ALGERIA=Algiers -BENIN=Porto-Novo -CAPE VERDE=Praia -BOTSWANA=Gaberone -Porto-Novo -CAMEROON=Yaounde -ANGOLA=Luanda -BURKINA FASO=Ouagadougou -BURUNDI=Bujumbura -ALGERIA=Algiers -BENIN=Porto-Novo -CAPE VERDE=Praia -BOTSWANA=Gaberone -*/ diff --git a/code/equalshashcode/SpringDetector.java b/code/equalshashcode/SpringDetector.java deleted file mode 100644 index 9b41bd3e..00000000 --- a/code/equalshashcode/SpringDetector.java +++ /dev/null @@ -1,62 +0,0 @@ -// equalshashcode/SpringDetector.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// What will the weather be? -import java.util.*; -import java.util.stream.*; -import java.util.function.*; -import java.lang.reflect.*; - -public class SpringDetector { - public static - void detectSpring(Class type) { - try { - Constructor ghog = - type.getConstructor(int.class); - Map map = - IntStream.range(0, 10) - .mapToObj(i -> { - try { - return ghog.newInstance(i); - } catch(Exception e) { - throw new RuntimeException(e); - } - }) - .collect(Collectors.toMap( - Function.identity(), - gh -> new Prediction())); - map.forEach((k, v) -> - System.out.println(k + ": " + v)); - Groundhog gh = ghog.newInstance(3); - System.out.println( - "Looking up prediction for " + gh); - if(map.containsKey(gh)) - System.out.println(map.get(gh)); - else - System.out.println("Key not found: " + gh); - } catch(NoSuchMethodException | - IllegalAccessException | - InvocationTargetException | - InstantiationException e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) { - detectSpring(Groundhog.class); - } -} -/* Output: -Groundhog #3: Six more weeks of Winter! -Groundhog #0: Early Spring! -Groundhog #8: Six more weeks of Winter! -Groundhog #6: Early Spring! -Groundhog #4: Early Spring! -Groundhog #2: Six more weeks of Winter! -Groundhog #1: Early Spring! -Groundhog #9: Early Spring! -Groundhog #5: Six more weeks of Winter! -Groundhog #7: Six more weeks of Winter! -Looking up prediction for Groundhog #3 -Key not found: Groundhog #3 -*/ diff --git a/code/equalshashcode/SpringDetector2.java b/code/equalshashcode/SpringDetector2.java deleted file mode 100644 index 1e136e47..00000000 --- a/code/equalshashcode/SpringDetector2.java +++ /dev/null @@ -1,25 +0,0 @@ -// equalshashcode/SpringDetector2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A working key - -public class SpringDetector2 { - public static void main(String[] args) { - SpringDetector.detectSpring(Groundhog2.class); - } -} -/* Output: -Groundhog #0: Six more weeks of Winter! -Groundhog #1: Early Spring! -Groundhog #2: Six more weeks of Winter! -Groundhog #3: Early Spring! -Groundhog #4: Early Spring! -Groundhog #5: Six more weeks of Winter! -Groundhog #6: Early Spring! -Groundhog #7: Early Spring! -Groundhog #8: Six more weeks of Winter! -Groundhog #9: Six more weeks of Winter! -Looking up prediction for Groundhog #3 -Early Spring! -*/ diff --git a/code/equalshashcode/StringHashCode.java b/code/equalshashcode/StringHashCode.java deleted file mode 100644 index 222fa612..00000000 --- a/code/equalshashcode/StringHashCode.java +++ /dev/null @@ -1,16 +0,0 @@ -// equalshashcode/StringHashCode.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class StringHashCode { - public static void main(String[] args) { - String[] hellos = "Hello Hello".split(" "); - System.out.println(hellos[0].hashCode()); - System.out.println(hellos[1].hashCode()); - } -} -/* Output: -69609650 -69609650 -*/ diff --git a/code/equalshashcode/SubtypeEquality.java b/code/equalshashcode/SubtypeEquality.java deleted file mode 100644 index 90320c88..00000000 --- a/code/equalshashcode/SubtypeEquality.java +++ /dev/null @@ -1,60 +0,0 @@ -// equalshashcode/SubtypeEquality.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -enum Size { SMALL, MEDIUM, LARGE } - -class Animal { - private static int counter = 0; - private final int id = counter++; - private final String name; - private final Size size; - Animal(String name, Size size) { - this.name = name; - this.size = size; - } - @Override - public boolean equals(Object rval) { - return rval instanceof Animal && - // Objects.equals(id, ((Animal)rval).id) && // [1] - Objects.equals(name, ((Animal)rval).name) && - Objects.equals(size, ((Animal)rval).size); - } - @Override - public int hashCode() { - return Objects.hash(name, size); - // return Objects.hash(name, size, id); // [2] - } - @Override - public String toString() { - return String.format("%s[%d]: %s %s %x", - getClass().getSimpleName(), id, - name, size, hashCode()); - } -} - -class Dog extends Animal { - Dog(String name, Size size) { - super(name, size); - } -} - -class Pig extends Animal { - Pig(String name, Size size) { - super(name, size); - } -} - -public class SubtypeEquality { - public static void main(String[] args) { - Set pets = new HashSet<>(); - pets.add(new Dog("Ralph", Size.MEDIUM)); - pets.add(new Pig("Ralph", Size.MEDIUM)); - pets.forEach(System.out::println); - } -} -/* Output: -Dog[0]: Ralph MEDIUM a752aeee -*/ diff --git a/code/equalshashcode/SubtypeEquality2.java b/code/equalshashcode/SubtypeEquality2.java deleted file mode 100644 index c0ac5057..00000000 --- a/code/equalshashcode/SubtypeEquality2.java +++ /dev/null @@ -1,40 +0,0 @@ -// equalshashcode/SubtypeEquality2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class Dog2 extends Animal { - Dog2(String name, Size size) { - super(name, size); - } - @Override - public boolean equals(Object rval) { - return rval instanceof Dog2 && - super.equals(rval); - } -} - -class Pig2 extends Animal { - Pig2(String name, Size size) { - super(name, size); - } - @Override - public boolean equals(Object rval) { - return rval instanceof Pig2 && - super.equals(rval); - } -} - -public class SubtypeEquality2 { - public static void main(String[] args) { - Set pets = new HashSet<>(); - pets.add(new Dog2("Ralph", Size.MEDIUM)); - pets.add(new Pig2("Ralph", Size.MEDIUM)); - pets.forEach(System.out::println); - } -} -/* Output: -Dog2[0]: Ralph MEDIUM a752aeee -Pig2[1]: Ralph MEDIUM a752aeee -*/ diff --git a/code/equalshashcode/SuccinctEquality.java b/code/equalshashcode/SuccinctEquality.java deleted file mode 100644 index 55a0d8de..00000000 --- a/code/equalshashcode/SuccinctEquality.java +++ /dev/null @@ -1,46 +0,0 @@ -// equalshashcode/SuccinctEquality.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SuccinctEquality extends Equality { - public SuccinctEquality(int i, String s, double d) { - super(i, s, d); - System.out.println("made 'SuccinctEquality'"); - } - @Override - public boolean equals(Object rval) { - return rval instanceof SuccinctEquality && - Objects.equals(i, ((SuccinctEquality)rval).i) && - Objects.equals(s, ((SuccinctEquality)rval).s) && - Objects.equals(d, ((SuccinctEquality)rval).d); - } - public static void main(String[] args) { - Equality.testAll( (i, s, d) -> - new SuccinctEquality(i, s, d)); - } -} -/* Output: -made 'Equality' -made 'SuccinctEquality' -made 'Equality' -made 'SuccinctEquality' -made 'Equality' -made 'SuccinctEquality' --- Testing null -- -null instanceof Equality: false -Expected false, got false --- Testing same object -- -same object instanceof Equality: true -Expected true, got true --- Testing different type -- -different type instanceof Equality: false -Expected false, got false --- Testing same values -- -same values instanceof Equality: true -Expected true, got true --- Testing different values -- -different values instanceof Equality: true -Expected false, got false -*/ diff --git a/code/exceptions/AlwaysFinally.java b/code/exceptions/AlwaysFinally.java deleted file mode 100644 index bb2270f7..00000000 --- a/code/exceptions/AlwaysFinally.java +++ /dev/null @@ -1,33 +0,0 @@ -// exceptions/AlwaysFinally.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Finally is always executed - -class FourException extends Exception {} - -public class AlwaysFinally { - public static void main(String[] args) { - System.out.println("Entering first try block"); - try { - System.out.println("Entering second try block"); - try { - throw new FourException(); - } finally { - System.out.println("finally in 2nd try block"); - } - } catch(FourException e) { - System.out.println( - "Caught FourException in 1st try block"); - } finally { - System.out.println("finally in 1st try block"); - } - } -} -/* Output: -Entering first try block -Entering second try block -finally in 2nd try block -Caught FourException in 1st try block -finally in 1st try block -*/ diff --git a/code/exceptions/AutoCloseableDetails.java b/code/exceptions/AutoCloseableDetails.java deleted file mode 100644 index 24a22e9d..00000000 --- a/code/exceptions/AutoCloseableDetails.java +++ /dev/null @@ -1,33 +0,0 @@ -// exceptions/AutoCloseableDetails.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Reporter implements AutoCloseable { - String name = getClass().getSimpleName(); - Reporter() { - System.out.println("Creating " + name); - } - public void close() { - System.out.println("Closing " + name); - } -} - -class First extends Reporter {} -class Second extends Reporter {} - -public class AutoCloseableDetails { - public static void main(String[] args) { - try( - First f = new First(); - Second s = new Second() - ) { - } - } -} -/* Output: -Creating First -Creating Second -Closing Second -Closing First -*/ diff --git a/code/exceptions/BodyException.java b/code/exceptions/BodyException.java deleted file mode 100644 index 3e907f8a..00000000 --- a/code/exceptions/BodyException.java +++ /dev/null @@ -1,32 +0,0 @@ -// exceptions/BodyException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Third extends Reporter {} - -public class BodyException { - public static void main(String[] args) { - try( - First f = new First(); - Second s2 = new Second() - ) { - System.out.println("In body"); - Third t = new Third(); - new SecondExcept(); - System.out.println("End of body"); - } catch(CE e) { - System.out.println("Caught: " + e); - } - } -} -/* Output: -Creating First -Creating Second -In body -Creating Third -Creating SecondExcept -Closing Second -Closing First -Caught: CE -*/ diff --git a/code/exceptions/Cleanup.java b/code/exceptions/Cleanup.java deleted file mode 100644 index 3d072304..00000000 --- a/code/exceptions/Cleanup.java +++ /dev/null @@ -1,30 +0,0 @@ -// exceptions/Cleanup.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Guaranteeing proper cleanup of a resource - -public class Cleanup { - public static void main(String[] args) { - try { - InputFile in = new InputFile("Cleanup.java"); - try { - String s; - int i = 1; - while((s = in.getLine()) != null) - ; // Perform line-by-line processing here... - } catch(Exception e) { - System.out.println("Caught Exception in main"); - e.printStackTrace(System.out); - } finally { - in.dispose(); - } - } catch(Exception e) { - System.out.println( - "InputFile construction failed"); - } - } -} -/* Output: -dispose() successful -*/ diff --git a/code/exceptions/CleanupIdiom.java b/code/exceptions/CleanupIdiom.java deleted file mode 100644 index e8dd62c4..00000000 --- a/code/exceptions/CleanupIdiom.java +++ /dev/null @@ -1,72 +0,0 @@ -// exceptions/CleanupIdiom.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Disposable objects must be followed by a try-finally - -class NeedsCleanup { // Construction can't fail - private static long counter = 1; - private final long id = counter++; - public void dispose() { - System.out.println( - "NeedsCleanup " + id + " disposed"); - } -} - -class ConstructionException extends Exception {} - -class NeedsCleanup2 extends NeedsCleanup { - // Construction can fail: - NeedsCleanup2() throws ConstructionException {} -} - -public class CleanupIdiom { - public static void main(String[] args) { - // [1]: - NeedsCleanup nc1 = new NeedsCleanup(); - try { - // ... - } finally { - nc1.dispose(); - } - - // [2]: - // If construction cannot fail, - // you can group objects: - NeedsCleanup nc2 = new NeedsCleanup(); - NeedsCleanup nc3 = new NeedsCleanup(); - try { - // ... - } finally { - nc3.dispose(); // Reverse order of construction - nc2.dispose(); - } - - // [3]: - // If construction can fail you must guard each one: - try { - NeedsCleanup2 nc4 = new NeedsCleanup2(); - try { - NeedsCleanup2 nc5 = new NeedsCleanup2(); - try { - // ... - } finally { - nc5.dispose(); - } - } catch(ConstructionException e) { // nc5 const. - System.out.println(e); - } finally { - nc4.dispose(); - } - } catch(ConstructionException e) { // nc4 const. - System.out.println(e); - } - } -} -/* Output: -NeedsCleanup 1 disposed -NeedsCleanup 3 disposed -NeedsCleanup 2 disposed -NeedsCleanup 5 disposed -NeedsCleanup 4 disposed -*/ diff --git a/code/exceptions/CloseExceptions.java b/code/exceptions/CloseExceptions.java deleted file mode 100644 index 4309a888..00000000 --- a/code/exceptions/CloseExceptions.java +++ /dev/null @@ -1,48 +0,0 @@ -// exceptions/CloseExceptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class CloseException extends Exception {} - -class Reporter2 implements AutoCloseable { - String name = getClass().getSimpleName(); - Reporter2() { - System.out.println("Creating " + name); - } - public void close() throws CloseException { - System.out.println("Closing " + name); - } -} - -class Closer extends Reporter2 { - @Override - public void close() throws CloseException { - super.close(); - throw new CloseException(); - } -} - -public class CloseExceptions { - public static void main(String[] args) { - try( - First f = new First(); - Closer c = new Closer(); - Second s = new Second() - ) { - System.out.println("In body"); - } catch(CloseException e) { - System.out.println("Caught: " + e); - } - } -} -/* Output: -Creating First -Creating Closer -Creating Second -In body -Closing Second -Closing Closer -Closing First -Caught: CloseException -*/ diff --git a/code/exceptions/ConstructorException.java b/code/exceptions/ConstructorException.java deleted file mode 100644 index 54eaaba3..00000000 --- a/code/exceptions/ConstructorException.java +++ /dev/null @@ -1,33 +0,0 @@ -// exceptions/ConstructorException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class CE extends Exception {} - -class SecondExcept extends Reporter { - SecondExcept() throws CE { - super(); - throw new CE(); - } -} - -public class ConstructorException { - public static void main(String[] args) { - try( - First f = new First(); - SecondExcept s = new SecondExcept(); - Second s2 = new Second() - ) { - System.out.println("In body"); - } catch(CE e) { - System.out.println("Caught: " + e); - } - } -} -/* Output: -Creating First -Creating SecondExcept -Closing First -Caught: CE -*/ diff --git a/code/exceptions/DynamicFields.java b/code/exceptions/DynamicFields.java deleted file mode 100644 index da3b9617..00000000 --- a/code/exceptions/DynamicFields.java +++ /dev/null @@ -1,130 +0,0 @@ -// exceptions/DynamicFields.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A Class that dynamically adds fields to itself to -// demonstrate exception chaining - -class DynamicFieldsException extends Exception {} - -public class DynamicFields { - private Object[][] fields; - public DynamicFields(int initialSize) { - fields = new Object[initialSize][2]; - for(int i = 0; i < initialSize; i++) - fields[i] = new Object[] { null, null }; - } - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for(Object[] obj : fields) { - result.append(obj[0]); - result.append(": "); - result.append(obj[1]); - result.append("\n"); - } - return result.toString(); - } - private int hasField(String id) { - for(int i = 0; i < fields.length; i++) - if(id.equals(fields[i][0])) - return i; - return -1; - } - private int getFieldNumber(String id) - throws NoSuchFieldException { - int fieldNum = hasField(id); - if(fieldNum == -1) - throw new NoSuchFieldException(); - return fieldNum; - } - private int makeField(String id) { - for(int i = 0; i < fields.length; i++) - if(fields[i][0] == null) { - fields[i][0] = id; - return i; - } - // No empty fields. Add one: - Object[][] tmp = new Object[fields.length + 1][2]; - for(int i = 0; i < fields.length; i++) - tmp[i] = fields[i]; - for(int i = fields.length; i < tmp.length; i++) - tmp[i] = new Object[] { null, null }; - fields = tmp; - // Recursive call with expanded fields: - return makeField(id); - } - public Object - getField(String id) throws NoSuchFieldException { - return fields[getFieldNumber(id)][1]; - } - public Object setField(String id, Object value) - throws DynamicFieldsException { - if(value == null) { - // Most exceptions don't have a "cause" - // constructor. In these cases you must use - // initCause(), available in all - // Throwable subclasses. - DynamicFieldsException dfe = - new DynamicFieldsException(); - dfe.initCause(new NullPointerException()); - throw dfe; - } - int fieldNumber = hasField(id); - if(fieldNumber == -1) - fieldNumber = makeField(id); - Object result = null; - try { - result = getField(id); // Get old value - } catch(NoSuchFieldException e) { - // Use constructor that takes "cause": - throw new RuntimeException(e); - } - fields[fieldNumber][1] = value; - return result; - } - public static void main(String[] args) { - DynamicFields df = new DynamicFields(3); - System.out.println(df); - try { - df.setField("d", "A value for d"); - df.setField("number", 47); - df.setField("number2", 48); - System.out.println(df); - df.setField("d", "A new value for d"); - df.setField("number3", 11); - System.out.println("df: " + df); - System.out.println("df.getField(\"d\") : " - + df.getField("d")); - Object field = - df.setField("d", null); // Exception - } catch(NoSuchFieldException | - DynamicFieldsException e) { - e.printStackTrace(System.out); - } - } -} -/* Output: -null: null -null: null -null: null - -d: A value for d -number: 47 -number2: 48 - -df: d: A new value for d -number: 47 -number2: 48 -number3: 11 - -df.getField("d") : A new value for d -DynamicFieldsException - at -DynamicFields.setField(DynamicFields.java:65) - at DynamicFields.main(DynamicFields.java:97) -Caused by: java.lang.NullPointerException - at -DynamicFields.setField(DynamicFields.java:67) - ... 1 more -*/ diff --git a/code/exceptions/ExceptionMethods.java b/code/exceptions/ExceptionMethods.java deleted file mode 100644 index bd6e8259..00000000 --- a/code/exceptions/ExceptionMethods.java +++ /dev/null @@ -1,32 +0,0 @@ -// exceptions/ExceptionMethods.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrating the Exception Methods - -public class ExceptionMethods { - public static void main(String[] args) { - try { - throw new Exception("My Exception"); - } catch(Exception e) { - System.out.println("Caught Exception"); - System.out.println( - "getMessage():" + e.getMessage()); - System.out.println("getLocalizedMessage():" + - e.getLocalizedMessage()); - System.out.println("toString():" + e); - System.out.println("printStackTrace():"); - e.printStackTrace(System.out); - } - } -} -/* Output: -Caught Exception -getMessage():My Exception -getLocalizedMessage():My Exception -toString():java.lang.Exception: My Exception -printStackTrace(): -java.lang.Exception: My Exception - at -ExceptionMethods.main(ExceptionMethods.java:7) -*/ diff --git a/code/exceptions/ExceptionSilencer.java b/code/exceptions/ExceptionSilencer.java deleted file mode 100644 index e418e9de..00000000 --- a/code/exceptions/ExceptionSilencer.java +++ /dev/null @@ -1,16 +0,0 @@ -// exceptions/ExceptionSilencer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ExceptionSilencer { - public static void main(String[] args) { - try { - throw new RuntimeException(); - } finally { - // Using 'return' inside the finally block - // will silence any thrown exception. - return; - } - } -} diff --git a/code/exceptions/ExtraFeatures.java b/code/exceptions/ExtraFeatures.java deleted file mode 100644 index 8aa922af..00000000 --- a/code/exceptions/ExtraFeatures.java +++ /dev/null @@ -1,72 +0,0 @@ -// exceptions/ExtraFeatures.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Further embellishment of exception classes - -class MyException2 extends Exception { - private int x; - MyException2() {} - MyException2(String msg) { super(msg); } - MyException2(String msg, int x) { - super(msg); - this.x = x; - } - public int val() { return x; } - @Override - public String getMessage() { - return "Detail Message: "+ x - + " "+ super.getMessage(); - } -} - -public class ExtraFeatures { - public static void f() throws MyException2 { - System.out.println( - "Throwing MyException2 from f()"); - throw new MyException2(); - } - public static void g() throws MyException2 { - System.out.println( - "Throwing MyException2 from g()"); - throw new MyException2("Originated in g()"); - } - public static void h() throws MyException2 { - System.out.println( - "Throwing MyException2 from h()"); - throw new MyException2("Originated in h()", 47); - } - public static void main(String[] args) { - try { - f(); - } catch(MyException2 e) { - e.printStackTrace(System.out); - } - try { - g(); - } catch(MyException2 e) { - e.printStackTrace(System.out); - } - try { - h(); - } catch(MyException2 e) { - e.printStackTrace(System.out); - System.out.println("e.val() = " + e.val()); - } - } -} -/* Output: -Throwing MyException2 from f() -MyException2: Detail Message: 0 null - at ExtraFeatures.f(ExtraFeatures.java:24) - at ExtraFeatures.main(ExtraFeatures.java:38) -Throwing MyException2 from g() -MyException2: Detail Message: 0 Originated in g() - at ExtraFeatures.g(ExtraFeatures.java:29) - at ExtraFeatures.main(ExtraFeatures.java:43) -Throwing MyException2 from h() -MyException2: Detail Message: 47 Originated in h() - at ExtraFeatures.h(ExtraFeatures.java:34) - at ExtraFeatures.main(ExtraFeatures.java:48) -e.val() = 47 -*/ diff --git a/code/exceptions/FinallyWorks.java b/code/exceptions/FinallyWorks.java deleted file mode 100644 index fc4fec0a..00000000 --- a/code/exceptions/FinallyWorks.java +++ /dev/null @@ -1,32 +0,0 @@ -// exceptions/FinallyWorks.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The finally clause is always executed - -class ThreeException extends Exception {} - -public class FinallyWorks { - static int count = 0; - public static void main(String[] args) { - while(true) { - try { - // Post-increment is zero first time: - if(count++ == 0) - throw new ThreeException(); - System.out.println("No exception"); - } catch(ThreeException e) { - System.out.println("ThreeException"); - } finally { - System.out.println("In finally clause"); - if(count == 2) break; // out of "while" - } - } - } -} -/* Output: -ThreeException -In finally clause -No exception -In finally clause -*/ diff --git a/code/exceptions/FullConstructors.java b/code/exceptions/FullConstructors.java deleted file mode 100644 index f5b4c9ff..00000000 --- a/code/exceptions/FullConstructors.java +++ /dev/null @@ -1,44 +0,0 @@ -// exceptions/FullConstructors.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class MyException extends Exception { - MyException() {} - MyException(String msg) { super(msg); } -} - -public class FullConstructors { - public static void f() throws MyException { - System.out.println("Throwing MyException from f()"); - throw new MyException(); - } - public static void g() throws MyException { - System.out.println("Throwing MyException from g()"); - throw new MyException("Originated in g()"); - } - public static void main(String[] args) { - try { - f(); - } catch(MyException e) { - e.printStackTrace(System.out); - } - try { - g(); - } catch(MyException e) { - e.printStackTrace(System.out); - } - } -} -/* Output: -Throwing MyException from f() -MyException - at FullConstructors.f(FullConstructors.java:11) - at -FullConstructors.main(FullConstructors.java:19) -Throwing MyException from g() -MyException: Originated in g() - at FullConstructors.g(FullConstructors.java:15) - at -FullConstructors.main(FullConstructors.java:24) -*/ diff --git a/code/exceptions/Human.java b/code/exceptions/Human.java deleted file mode 100644 index 7ee7dcaa..00000000 --- a/code/exceptions/Human.java +++ /dev/null @@ -1,31 +0,0 @@ -// exceptions/Human.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Catching exception hierarchies - -class Annoyance extends Exception {} -class Sneeze extends Annoyance {} - -public class Human { - public static void main(String[] args) { - // Catch the exact type: - try { - throw new Sneeze(); - } catch(Sneeze s) { - System.out.println("Caught Sneeze"); - } catch(Annoyance a) { - System.out.println("Caught Annoyance"); - } - // Catch the base type: - try { - throw new Sneeze(); - } catch(Annoyance a) { - System.out.println("Caught Annoyance"); - } - } -} -/* Output: -Caught Sneeze -Caught Annoyance -*/ diff --git a/code/exceptions/InheritingExceptions.java b/code/exceptions/InheritingExceptions.java deleted file mode 100644 index abb80c3b..00000000 --- a/code/exceptions/InheritingExceptions.java +++ /dev/null @@ -1,28 +0,0 @@ -// exceptions/InheritingExceptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating your own exceptions - -class SimpleException extends Exception {} - -public class InheritingExceptions { - public void f() throws SimpleException { - System.out.println( - "Throw SimpleException from f()"); - throw new SimpleException(); - } - public static void main(String[] args) { - InheritingExceptions sed = - new InheritingExceptions(); - try { - sed.f(); - } catch(SimpleException e) { - System.out.println("Caught it!"); - } - } -} -/* Output: -Throw SimpleException from f() -Caught it! -*/ diff --git a/code/exceptions/InputFile.java b/code/exceptions/InputFile.java deleted file mode 100644 index 5c269851..00000000 --- a/code/exceptions/InputFile.java +++ /dev/null @@ -1,47 +0,0 @@ -// exceptions/InputFile.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Paying attention to exceptions in constructors -import java.io.*; - -public class InputFile { - private BufferedReader in; - public InputFile(String fname) throws Exception { - try { - in = new BufferedReader(new FileReader(fname)); - // Other code that might throw exceptions - } catch(FileNotFoundException e) { - System.out.println("Could not open " + fname); - // Wasn't open, so don't close it - throw e; - } catch(Exception e) { - // All other exceptions must close it - try { - in.close(); - } catch(IOException e2) { - System.out.println("in.close() unsuccessful"); - } - throw e; // Rethrow - } finally { - // Don't close it here!!! - } - } - public String getLine() { - String s; - try { - s = in.readLine(); - } catch(IOException e) { - throw new RuntimeException("readLine() failed"); - } - return s; - } - public void dispose() { - try { - in.close(); - System.out.println("dispose() successful"); - } catch(IOException e2) { - throw new RuntimeException("in.close() failed"); - } - } -} diff --git a/code/exceptions/InputFile2.java b/code/exceptions/InputFile2.java deleted file mode 100644 index 74a68c3f..00000000 --- a/code/exceptions/InputFile2.java +++ /dev/null @@ -1,28 +0,0 @@ -// exceptions/InputFile2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.nio.file.*; -import java.util.stream.*; - -public class InputFile2 { - private String fname; - public InputFile2(String fname) { - this.fname = fname; - } - public - Stream getLines() throws IOException { - return Files.lines(Paths.get(fname)); - } - public static void - main(String[] args) throws IOException { - new InputFile2("InputFile2.java").getLines() - .skip(15) - .limit(1) - .forEach(System.out::println); - } -} -/* Output: - main(String[] args) throws IOException { -*/ diff --git a/code/exceptions/LoggingExceptions.java b/code/exceptions/LoggingExceptions.java deleted file mode 100644 index 0120ee17..00000000 --- a/code/exceptions/LoggingExceptions.java +++ /dev/null @@ -1,48 +0,0 @@ -// exceptions/LoggingExceptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An exception that reports through a Logger -// {ErrorOutputExpected} -import java.util.logging.*; -import java.io.*; - -class LoggingException extends Exception { - private static Logger logger = - Logger.getLogger("LoggingException"); - LoggingException() { - StringWriter trace = new StringWriter(); - printStackTrace(new PrintWriter(trace)); - logger.severe(trace.toString()); - } -} - -public class LoggingExceptions { - public static void main(String[] args) { - try { - throw new LoggingException(); - } catch(LoggingException e) { - System.err.println("Caught " + e); - } - try { - throw new LoggingException(); - } catch(LoggingException e) { - System.err.println("Caught " + e); - } - } -} -/* Output: -___[ Error Output ]___ -May 09, 2017 6:07:17 AM LoggingException -SEVERE: LoggingException - at -LoggingExceptions.main(LoggingExceptions.java:20) - -Caught LoggingException -May 09, 2017 6:07:17 AM LoggingException -SEVERE: LoggingException - at -LoggingExceptions.main(LoggingExceptions.java:25) - -Caught LoggingException -*/ diff --git a/code/exceptions/LoggingExceptions2.java b/code/exceptions/LoggingExceptions2.java deleted file mode 100644 index 21a92137..00000000 --- a/code/exceptions/LoggingExceptions2.java +++ /dev/null @@ -1,32 +0,0 @@ -// exceptions/LoggingExceptions2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Logging caught exceptions -// {ErrorOutputExpected} -import java.util.logging.*; -import java.io.*; - -public class LoggingExceptions2 { - private static Logger logger = - Logger.getLogger("LoggingExceptions2"); - static void logException(Exception e) { - StringWriter trace = new StringWriter(); - e.printStackTrace(new PrintWriter(trace)); - logger.severe(trace.toString()); - } - public static void main(String[] args) { - try { - throw new NullPointerException(); - } catch(NullPointerException e) { - logException(e); - } - } -} -/* Output: -___[ Error Output ]___ -May 09, 2017 6:07:17 AM LoggingExceptions2 logException -SEVERE: java.lang.NullPointerException - at -LoggingExceptions2.main(LoggingExceptions2.java:17) -*/ diff --git a/code/exceptions/LostMessage.java b/code/exceptions/LostMessage.java deleted file mode 100644 index 1446d903..00000000 --- a/code/exceptions/LostMessage.java +++ /dev/null @@ -1,44 +0,0 @@ -// exceptions/LostMessage.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// How an exception can be lost - -class VeryImportantException extends Exception { - @Override - public String toString() { - return "A very important exception!"; - } -} - -class HoHumException extends Exception { - @Override - public String toString() { - return "A trivial exception"; - } -} - -public class LostMessage { - void f() throws VeryImportantException { - throw new VeryImportantException(); - } - void dispose() throws HoHumException { - throw new HoHumException(); - } - public static void main(String[] args) { - try { - LostMessage lm = new LostMessage(); - try { - lm.f(); - } finally { - lm.dispose(); - } - } catch(VeryImportantException | - HoHumException e) { - System.out.println(e); - } - } -} -/* Output: -A trivial exception -*/ diff --git a/code/exceptions/MainException.java b/code/exceptions/MainException.java deleted file mode 100644 index 7a7e2638..00000000 --- a/code/exceptions/MainException.java +++ /dev/null @@ -1,17 +0,0 @@ -// exceptions/MainException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.nio.file.*; - -public class MainException { - // Pass exceptions to the console: - public static void - main(String[] args) throws Exception { - // Open the file: - List lines = Files.readAllLines( - Paths.get("MainException.java")); - // Use the file ... - } -} diff --git a/code/exceptions/MessyExceptions.java b/code/exceptions/MessyExceptions.java deleted file mode 100644 index e8f7fc9d..00000000 --- a/code/exceptions/MessyExceptions.java +++ /dev/null @@ -1,27 +0,0 @@ -// exceptions/MessyExceptions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; - -public class MessyExceptions { - public static void main(String[] args) { - InputStream in = null; - try { - in = new FileInputStream( - new File("MessyExceptions.java")); - int contents = in.read(); - // Process contents - } catch(IOException e) { - // Handle the error - } finally { - if(in != null) { - try { - in.close(); - } catch(IOException e) { - // Handle the close() error - } - } - } - } -} diff --git a/code/exceptions/MultiCatch.java b/code/exceptions/MultiCatch.java deleted file mode 100644 index f97bde13..00000000 --- a/code/exceptions/MultiCatch.java +++ /dev/null @@ -1,16 +0,0 @@ -// exceptions/MultiCatch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class MultiCatch { - void x() throws Except1, Except2, Except3, Except4 {} - void process() {} - void f() { - try { - x(); - } catch(Except1 | Except2 | Except3 | Except4 e) { - process(); - } - } -} diff --git a/code/exceptions/MultiCatch2.java b/code/exceptions/MultiCatch2.java deleted file mode 100644 index 4629e93f..00000000 --- a/code/exceptions/MultiCatch2.java +++ /dev/null @@ -1,19 +0,0 @@ -// exceptions/MultiCatch2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class MultiCatch2 { - void x() throws Except1, Except2, Except3, Except4 {} - void process1() {} - void process2() {} - void f() { - try { - x(); - } catch(Except1 | Except2 e) { - process1(); - } catch(Except3 | Except4 e) { - process2(); - } - } -} diff --git a/code/exceptions/MultipleReturns.java b/code/exceptions/MultipleReturns.java deleted file mode 100644 index 3f667b33..00000000 --- a/code/exceptions/MultipleReturns.java +++ /dev/null @@ -1,47 +0,0 @@ -// exceptions/MultipleReturns.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class MultipleReturns { - public static void f(int i) { - System.out.println( - "Initialization that requires cleanup"); - try { - System.out.println("Point 1"); - if(i == 1) return; - System.out.println("Point 2"); - if(i == 2) return; - System.out.println("Point 3"); - if(i == 3) return; - System.out.println("End"); - return; - } finally { - System.out.println("Performing cleanup"); - } - } - public static void main(String[] args) { - for(int i = 1; i <= 4; i++) - f(i); - } -} -/* Output: -Initialization that requires cleanup -Point 1 -Performing cleanup -Initialization that requires cleanup -Point 1 -Point 2 -Performing cleanup -Initialization that requires cleanup -Point 1 -Point 2 -Point 3 -Performing cleanup -Initialization that requires cleanup -Point 1 -Point 2 -Point 3 -End -Performing cleanup -*/ diff --git a/code/exceptions/NeverCaught.java b/code/exceptions/NeverCaught.java deleted file mode 100644 index c8bb0a2f..00000000 --- a/code/exceptions/NeverCaught.java +++ /dev/null @@ -1,26 +0,0 @@ -// exceptions/NeverCaught.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Ignoring RuntimeExceptions -// {ThrowsException} - -public class NeverCaught { - static void f() { - throw new RuntimeException("From f()"); - } - static void g() { - f(); - } - public static void main(String[] args) { - g(); - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "main" java.lang.RuntimeException: -From f() - at NeverCaught.f(NeverCaught.java:7) - at NeverCaught.g(NeverCaught.java:10) - at NeverCaught.main(NeverCaught.java:13) -*/ diff --git a/code/exceptions/OnOffException1.java b/code/exceptions/OnOffException1.java deleted file mode 100644 index 3333d815..00000000 --- a/code/exceptions/OnOffException1.java +++ /dev/null @@ -1,5 +0,0 @@ -// exceptions/OnOffException1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class OnOffException1 extends Exception {} diff --git a/code/exceptions/OnOffException2.java b/code/exceptions/OnOffException2.java deleted file mode 100644 index 0bb5e164..00000000 --- a/code/exceptions/OnOffException2.java +++ /dev/null @@ -1,5 +0,0 @@ -// exceptions/OnOffException2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class OnOffException2 extends Exception {} diff --git a/code/exceptions/OnOffSwitch.java b/code/exceptions/OnOffSwitch.java deleted file mode 100644 index fe05fa35..00000000 --- a/code/exceptions/OnOffSwitch.java +++ /dev/null @@ -1,29 +0,0 @@ -// exceptions/OnOffSwitch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Why use finally? - -public class OnOffSwitch { - private static Switch sw = new Switch(); - public static void f() - throws OnOffException1, OnOffException2 {} - public static void main(String[] args) { - try { - sw.on(); - // Code that can throw exceptions... - f(); - sw.off(); - } catch(OnOffException1 e) { - System.out.println("OnOffException1"); - sw.off(); - } catch(OnOffException2 e) { - System.out.println("OnOffException2"); - sw.off(); - } - } -} -/* Output: -on -off -*/ diff --git a/code/exceptions/PreciseRethrow.java b/code/exceptions/PreciseRethrow.java deleted file mode 100644 index f8849a3d..00000000 --- a/code/exceptions/PreciseRethrow.java +++ /dev/null @@ -1,17 +0,0 @@ -// exceptions/PreciseRethrow.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class BaseException extends Exception {} -class DerivedException extends BaseException {} - -public class PreciseRethrow { - void catcher() throws DerivedException { - try { - throw new DerivedException(); - } catch(BaseException e) { - throw e; - } - } -} diff --git a/code/exceptions/RethrowNew.java b/code/exceptions/RethrowNew.java deleted file mode 100644 index daa4ad41..00000000 --- a/code/exceptions/RethrowNew.java +++ /dev/null @@ -1,47 +0,0 @@ -// exceptions/RethrowNew.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Rethrow a different object from the one you caught - -class OneException extends Exception { - OneException(String s) { super(s); } -} - -class TwoException extends Exception { - TwoException(String s) { super(s); } -} - -public class RethrowNew { - public static void f() throws OneException { - System.out.println( - "originating the exception in f()"); - throw new OneException("thrown from f()"); - } - public static void main(String[] args) { - try { - try { - f(); - } catch(OneException e) { - System.out.println( - "Caught in inner try, e.printStackTrace()"); - e.printStackTrace(System.out); - throw new TwoException("from inner try"); - } - } catch(TwoException e) { - System.out.println( - "Caught in outer try, e.printStackTrace()"); - e.printStackTrace(System.out); - } - } -} -/* Output: -originating the exception in f() -Caught in inner try, e.printStackTrace() -OneException: thrown from f() - at RethrowNew.f(RethrowNew.java:16) - at RethrowNew.main(RethrowNew.java:21) -Caught in outer try, e.printStackTrace() -TwoException: from inner try - at RethrowNew.main(RethrowNew.java:26) -*/ diff --git a/code/exceptions/Rethrowing.java b/code/exceptions/Rethrowing.java deleted file mode 100644 index 5bf1a635..00000000 --- a/code/exceptions/Rethrowing.java +++ /dev/null @@ -1,70 +0,0 @@ -// exceptions/Rethrowing.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrating fillInStackTrace() - -public class Rethrowing { - public static void f() throws Exception { - System.out.println( - "originating the exception in f()"); - throw new Exception("thrown from f()"); - } - public static void g() throws Exception { - try { - f(); - } catch(Exception e) { - System.out.println( - "Inside g(), e.printStackTrace()"); - e.printStackTrace(System.out); - throw e; - } - } - public static void h() throws Exception { - try { - f(); - } catch(Exception e) { - System.out.println( - "Inside h(), e.printStackTrace()"); - e.printStackTrace(System.out); - throw (Exception)e.fillInStackTrace(); - } - } - public static void main(String[] args) { - try { - g(); - } catch(Exception e) { - System.out.println("main: printStackTrace()"); - e.printStackTrace(System.out); - } - try { - h(); - } catch(Exception e) { - System.out.println("main: printStackTrace()"); - e.printStackTrace(System.out); - } - } -} -/* Output: -originating the exception in f() -Inside g(), e.printStackTrace() -java.lang.Exception: thrown from f() - at Rethrowing.f(Rethrowing.java:8) - at Rethrowing.g(Rethrowing.java:12) - at Rethrowing.main(Rethrowing.java:32) -main: printStackTrace() -java.lang.Exception: thrown from f() - at Rethrowing.f(Rethrowing.java:8) - at Rethrowing.g(Rethrowing.java:12) - at Rethrowing.main(Rethrowing.java:32) -originating the exception in f() -Inside h(), e.printStackTrace() -java.lang.Exception: thrown from f() - at Rethrowing.f(Rethrowing.java:8) - at Rethrowing.h(Rethrowing.java:22) - at Rethrowing.main(Rethrowing.java:38) -main: printStackTrace() -java.lang.Exception: thrown from f() - at Rethrowing.h(Rethrowing.java:27) - at Rethrowing.main(Rethrowing.java:38) -*/ diff --git a/code/exceptions/SameHandler.java b/code/exceptions/SameHandler.java deleted file mode 100644 index 8c680567..00000000 --- a/code/exceptions/SameHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -// exceptions/SameHandler.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class EBase1 extends Exception {} -class Except1 extends EBase1 {} -class EBase2 extends Exception {} -class Except2 extends EBase2 {} -class EBase3 extends Exception {} -class Except3 extends EBase3 {} -class EBase4 extends Exception {} -class Except4 extends EBase4 {} - -public class SameHandler { - void x() throws Except1, Except2, Except3, Except4 {} - void process() {} - void f() { - try { - x(); - } catch(Except1 e) { - process(); - } catch(Except2 e) { - process(); - } catch(Except3 e) { - process(); - } catch(Except4 e) { - process(); - } - } -} diff --git a/code/exceptions/StormyInning.java b/code/exceptions/StormyInning.java deleted file mode 100644 index 644c10ba..00000000 --- a/code/exceptions/StormyInning.java +++ /dev/null @@ -1,83 +0,0 @@ -// exceptions/StormyInning.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Overridden methods can throw only the exceptions -// specified in their base-class versions, or exceptions -// derived from the base-class exceptions - -class BaseballException extends Exception {} -class Foul extends BaseballException {} -class Strike extends BaseballException {} - -abstract class Inning { - Inning() throws BaseballException {} - public void event() throws BaseballException { - // Doesn't actually have to throw anything - } - public abstract void atBat() throws Strike, Foul; - public void walk() {} // Throws no checked exceptions -} - -class StormException extends Exception {} -class RainedOut extends StormException {} -class PopFoul extends Foul {} - -interface Storm { - void event() throws RainedOut; - void rainHard() throws RainedOut; -} - -public -class StormyInning extends Inning implements Storm { - // OK to add new exceptions for constructors, but you - // must deal with the base constructor exceptions: - public StormyInning() - throws RainedOut, BaseballException {} - public StormyInning(String s) - throws BaseballException {} - // Regular methods must conform to base class: - //- void walk() throws PopFoul {} //Compile error - // Interface CANNOT add exceptions to existing - // methods from the base class: - //- public void event() throws RainedOut {} - // If the method doesn't already exist in the - // base class, the exception is OK: - @Override - public void rainHard() throws RainedOut {} - // You can choose to not throw any exceptions, - // even if the base version does: - @Override - public void event() {} - // Overridden methods can throw inherited exceptions: - @Override - public void atBat() throws PopFoul {} - public static void main(String[] args) { - try { - StormyInning si = new StormyInning(); - si.atBat(); - } catch(PopFoul e) { - System.out.println("Pop foul"); - } catch(RainedOut e) { - System.out.println("Rained out"); - } catch(BaseballException e) { - System.out.println("Generic baseball exception"); - } - // Strike not thrown in derived version. - try { - // What happens if you upcast? - Inning i = new StormyInning(); - i.atBat(); - // You must catch the exceptions from the - // base-class version of the method: - } catch(Strike e) { - System.out.println("Strike"); - } catch(Foul e) { - System.out.println("Foul"); - } catch(RainedOut e) { - System.out.println("Rained out"); - } catch(BaseballException e) { - System.out.println("Generic baseball exception"); - } - } -} diff --git a/code/exceptions/StreamsAreAutoCloseable.java b/code/exceptions/StreamsAreAutoCloseable.java deleted file mode 100644 index c55bf417..00000000 --- a/code/exceptions/StreamsAreAutoCloseable.java +++ /dev/null @@ -1,24 +0,0 @@ -// exceptions/StreamsAreAutoCloseable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.nio.file.*; -import java.util.stream.*; - -public class StreamsAreAutoCloseable { - public static void - main(String[] args) throws IOException{ - try( - Stream in = Files.lines( - Paths.get("StreamsAreAutoCloseable.java")); - PrintWriter outfile = new PrintWriter( - "Results.txt"); // [1] - ) { - in.skip(5) - .limit(1) - .map(String::toLowerCase) - .forEachOrdered(outfile::println); - } // [2] - } -} diff --git a/code/exceptions/Switch.java b/code/exceptions/Switch.java deleted file mode 100644 index 7d491d00..00000000 --- a/code/exceptions/Switch.java +++ /dev/null @@ -1,21 +0,0 @@ -// exceptions/Switch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Switch { - private boolean state = false; - public boolean read() { return state; } - public void on() { - state = true; - System.out.println(this); - } - public void off() { - state = false; - System.out.println(this); - } - @Override - public String toString() { - return state ? "on" : "off"; - } -} diff --git a/code/exceptions/TryAnything.java b/code/exceptions/TryAnything.java deleted file mode 100644 index 9eeee07b..00000000 --- a/code/exceptions/TryAnything.java +++ /dev/null @@ -1,16 +0,0 @@ -// exceptions/TryAnything.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} - -class Anything {} - -public class TryAnything { - public static void main(String[] args) { - try( - Anything a = new Anything() - ) { - } - } -} diff --git a/code/exceptions/TryWithResources.java b/code/exceptions/TryWithResources.java deleted file mode 100644 index cdc83a5c..00000000 --- a/code/exceptions/TryWithResources.java +++ /dev/null @@ -1,19 +0,0 @@ -// exceptions/TryWithResources.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; - -public class TryWithResources { - public static void main(String[] args) { - try( - InputStream in = new FileInputStream( - new File("TryWithResources.java")) - ) { - int contents = in.read(); - // Process contents - } catch(IOException e) { - // Handle the error - } - } -} diff --git a/code/exceptions/TurnOffChecking.java b/code/exceptions/TurnOffChecking.java deleted file mode 100644 index 898431b6..00000000 --- a/code/exceptions/TurnOffChecking.java +++ /dev/null @@ -1,64 +0,0 @@ -// exceptions/TurnOffChecking.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// "Turning off" Checked exceptions -import java.io.*; - -class WrapCheckedException { - void throwRuntimeException(int type) { - try { - switch(type) { - case 0: throw new FileNotFoundException(); - case 1: throw new IOException(); - case 2: throw new - RuntimeException("Where am I?"); - default: return; - } - } catch(IOException | RuntimeException e) { - // Adapt to unchecked: - throw new RuntimeException(e); - } - } -} - -class SomeOtherException extends Exception {} - -public class TurnOffChecking { - public static void main(String[] args) { - WrapCheckedException wce = - new WrapCheckedException(); - // You can call throwRuntimeException() without - // a try block, and let RuntimeExceptions - // leave the method: - wce.throwRuntimeException(3); - // Or you can choose to catch exceptions: - for(int i = 0; i < 4; i++) - try { - if(i < 3) - wce.throwRuntimeException(i); - else - throw new SomeOtherException(); - } catch(SomeOtherException e) { - System.out.println( - "SomeOtherException: " + e); - } catch(RuntimeException re) { - try { - throw re.getCause(); - } catch(FileNotFoundException e) { - System.out.println( - "FileNotFoundException: " + e); - } catch(IOException e) { - System.out.println("IOException: " + e); - } catch(Throwable e) { - System.out.println("Throwable: " + e); - } - } - } -} -/* Output: -FileNotFoundException: java.io.FileNotFoundException -IOException: java.io.IOException -Throwable: java.lang.RuntimeException: Where am I? -SomeOtherException: SomeOtherException -*/ diff --git a/code/exceptions/WhoCalled.java b/code/exceptions/WhoCalled.java deleted file mode 100644 index 4c4e0104..00000000 --- a/code/exceptions/WhoCalled.java +++ /dev/null @@ -1,39 +0,0 @@ -// exceptions/WhoCalled.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Programmatic access to stack trace information - -public class WhoCalled { - static void f() { - // Generate an exception to fill in the stack trace - try { - throw new Exception(); - } catch(Exception e) { - for(StackTraceElement ste : e.getStackTrace()) - System.out.println(ste.getMethodName()); - } - } - static void g() { f(); } - static void h() { g(); } - public static void main(String[] args) { - f(); - System.out.println("*******"); - g(); - System.out.println("*******"); - h(); - } -} -/* Output: -f -main -******* -f -g -main -******* -f -g -h -main -*/ diff --git a/code/exceptions/WithFinally.java b/code/exceptions/WithFinally.java deleted file mode 100644 index 9d3efc3a..00000000 --- a/code/exceptions/WithFinally.java +++ /dev/null @@ -1,26 +0,0 @@ -// exceptions/WithFinally.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Finally Guarantees cleanup - -public class WithFinally { - static Switch sw = new Switch(); - public static void main(String[] args) { - try { - sw.on(); - // Code that can throw exceptions... - OnOffSwitch.f(); - } catch(OnOffException1 e) { - System.out.println("OnOffException1"); - } catch(OnOffException2 e) { - System.out.println("OnOffException2"); - } finally { - sw.off(); - } - } -} -/* Output: -on -off -*/ diff --git a/code/files/AddAndSubtractPaths.java b/code/files/AddAndSubtractPaths.java deleted file mode 100644 index f3984d19..00000000 --- a/code/files/AddAndSubtractPaths.java +++ /dev/null @@ -1,87 +0,0 @@ -// files/AddAndSubtractPaths.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.file.*; -import java.io.IOException; - -public class AddAndSubtractPaths { - static Path base = Paths.get("..", "..", "..") - .toAbsolutePath() - .normalize(); - static void show(int id, Path result) { - if(result.isAbsolute()) - System.out.println("(" + id + ")r " + - base.relativize(result)); - else - System.out.println("(" + id + ") " + result); - try { - System.out.println("RealPath: " - + result.toRealPath()); - } catch(IOException e) { - System.out.println(e); - } - } - public static void main(String[] args) { - System.out.println(System.getProperty("os.name")); - System.out.println(base); - Path p = Paths.get("AddAndSubtractPaths.java") - .toAbsolutePath(); - show(1, p); - Path convoluted = p.getParent().getParent() - .resolve("strings") - .resolve("..") - .resolve(p.getParent().getFileName()); - show(2, convoluted); - show(3, convoluted.normalize()); - - Path p2 = Paths.get("..", ".."); - show(4, p2); - show(5, p2.normalize()); - show(6, p2.toAbsolutePath().normalize()); - - Path p3 = Paths.get(".").toAbsolutePath(); - Path p4 = p3.resolve(p2); - show(7, p4); - show(8, p4.normalize()); - - Path p5 = Paths.get("").toAbsolutePath(); - show(9, p5); - show(10, p5.resolveSibling("strings")); - show(11, Paths.get("nonexistent")); - } -} -/* Output: -Windows 10 -C:\Users\Bruce\Documents\GitHub -(1)r on- -java\ExtractedExamples\files\AddAndSubtractPaths.java -RealPath: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files\AddAndSubtractPaths.java -(2)r on-java\ExtractedExamples\strings\..\files -RealPath: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files -(3)r on-java\ExtractedExamples\files -RealPath: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files -(4) ..\.. -RealPath: C:\Users\Bruce\Documents\GitHub\on-java -(5) ..\.. -RealPath: C:\Users\Bruce\Documents\GitHub\on-java -(6)r on-java -RealPath: C:\Users\Bruce\Documents\GitHub\on-java -(7)r on-java\ExtractedExamples\files\.\..\.. -RealPath: C:\Users\Bruce\Documents\GitHub\on-java -(8)r on-java -RealPath: C:\Users\Bruce\Documents\GitHub\on-java -(9)r on-java\ExtractedExamples\files -RealPath: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files -(10)r on-java\ExtractedExamples\strings -RealPath: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\strings -(11) nonexistent -java.nio.file.NoSuchFileException: -C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files\nonexistent -*/ diff --git a/code/files/Directories.java b/code/files/Directories.java deleted file mode 100644 index 10ad9bee..00000000 --- a/code/files/Directories.java +++ /dev/null @@ -1,94 +0,0 @@ -// files/Directories.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.nio.file.*; -import onjava.RmDir; - -public class Directories { - static Path test = Paths.get("test"); - static String sep = - FileSystems.getDefault().getSeparator(); - static List parts = - Arrays.asList("foo", "bar", "baz", "bag"); - static Path makeVariant() { - Collections.rotate(parts, 1); - return Paths.get("test", String.join(sep, parts)); - } - static void refreshTestDir() throws Exception { - if(Files.exists(test)) - RmDir.rmdir(test); - if(!Files.exists(test)) - Files.createDirectory(test); - } - public static void - main(String[] args) throws Exception { - refreshTestDir(); - Files.createFile(test.resolve("Hello.txt")); - Path variant = makeVariant(); - // Throws exception (too many levels): - try { - Files.createDirectory(variant); - } catch(Exception e) { - System.out.println("Nope, that doesn't work."); - } - populateTestDir(); - Path tempdir = - Files.createTempDirectory(test, "DIR_"); - Files.createTempFile(tempdir, "pre", ".non"); - Files.newDirectoryStream(test) - .forEach(System.out::println); - System.out.println("*********"); - Files.walk(test).forEach(System.out::println); - } - static void populateTestDir() throws Exception { - for(int i = 0; i < parts.size(); i++) { - Path variant = makeVariant(); - if(!Files.exists(variant)) { - Files.createDirectories(variant); - Files.copy(Paths.get("Directories.java"), - variant.resolve("File.txt")); - Files.createTempFile(variant, null, null); - } - } - } -} -/* Output: -Nope, that doesn't work. -test\bag -test\bar -test\baz -test\DIR_5142667942049986036 -test\foo -test\Hello.txt -********* -test -test\bag -test\bag\foo -test\bag\foo\bar -test\bag\foo\bar\baz -test\bag\foo\bar\baz\8279660869874696036.tmp -test\bag\foo\bar\baz\File.txt -test\bar -test\bar\baz -test\bar\baz\bag -test\bar\baz\bag\foo -test\bar\baz\bag\foo\1274043134240426261.tmp -test\bar\baz\bag\foo\File.txt -test\baz -test\baz\bag -test\baz\bag\foo -test\baz\bag\foo\bar -test\baz\bag\foo\bar\6130572530014544105.tmp -test\baz\bag\foo\bar\File.txt -test\DIR_5142667942049986036 -test\DIR_5142667942049986036\pre7704286843227113253.non -test\foo -test\foo\bar -test\foo\bar\baz -test\foo\bar\baz\bag -test\foo\bar\baz\bag\5412864507741775436.tmp -test\foo\bar\baz\bag\File.txt -test\Hello.txt -*/ diff --git a/code/files/FileSystemDemo.java b/code/files/FileSystemDemo.java deleted file mode 100644 index 3d9024ca..00000000 --- a/code/files/FileSystemDemo.java +++ /dev/null @@ -1,41 +0,0 @@ -// files/FileSystemDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.file.*; - -public class FileSystemDemo { - static void show(String id, Object o) { - System.out.println(id + ": " + o); - } - public static void main(String[] args) { - System.out.println(System.getProperty("os.name")); - FileSystem fsys = FileSystems.getDefault(); - for(FileStore fs : fsys.getFileStores()) - show("File Store", fs); - for(Path rd : fsys.getRootDirectories()) - show("Root Directory", rd); - show("Separator", fsys.getSeparator()); - show("UserPrincipalLookupService", - fsys.getUserPrincipalLookupService()); - show("isOpen", fsys.isOpen()); - show("isReadOnly", fsys.isReadOnly()); - show("FileSystemProvider", fsys.provider()); - show("File Attribute Views", - fsys.supportedFileAttributeViews()); - } -} -/* Output: -Windows 10 -File Store: SSD (C:) -Root Directory: C:\ -Root Directory: D:\ -Separator: \ -UserPrincipalLookupService: -sun.nio.fs.WindowsFileSystem$LookupService$1@15db9742 -isOpen: true -isReadOnly: false -FileSystemProvider: -sun.nio.fs.WindowsFileSystemProvider@6d06d69c -File Attribute Views: [owner, dos, acl, basic, user] -*/ diff --git a/code/files/Find.java b/code/files/Find.java deleted file mode 100644 index ac97ebdc..00000000 --- a/code/files/Find.java +++ /dev/null @@ -1,60 +0,0 @@ -// files/Find.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromGradle} -import java.nio.file.*; - -public class Find { - public static void - main(String[] args) throws Exception { - Path test = Paths.get("test"); - Directories.refreshTestDir(); - Directories.populateTestDir(); - // Creating a *directory*, not a file: - Files.createDirectory(test.resolve("dir.tmp")); - - PathMatcher matcher = FileSystems.getDefault() - .getPathMatcher("glob:**/*.{tmp,txt}"); - Files.walk(test) - .filter(matcher::matches) - .forEach(System.out::println); - System.out.println("***************"); - - PathMatcher matcher2 = FileSystems.getDefault() - .getPathMatcher("glob:*.tmp"); - Files.walk(test) - .map(Path::getFileName) - .filter(matcher2::matches) - .forEach(System.out::println); - System.out.println("***************"); - - Files.walk(test) // Only look for files - .filter(Files::isRegularFile) - .map(Path::getFileName) - .filter(matcher2::matches) - .forEach(System.out::println); - } -} -/* Output: -test\bag\foo\bar\baz\5208762845883213974.tmp -test\bag\foo\bar\baz\File.txt -test\bar\baz\bag\foo\7918367201207778677.tmp -test\bar\baz\bag\foo\File.txt -test\baz\bag\foo\bar\8016595521026696632.tmp -test\baz\bag\foo\bar\File.txt -test\dir.tmp -test\foo\bar\baz\bag\5832319279813617280.tmp -test\foo\bar\baz\bag\File.txt -*************** -5208762845883213974.tmp -7918367201207778677.tmp -8016595521026696632.tmp -dir.tmp -5832319279813617280.tmp -*************** -5208762845883213974.tmp -7918367201207778677.tmp -8016595521026696632.tmp -5832319279813617280.tmp -*/ diff --git a/code/files/ListOfLines.java b/code/files/ListOfLines.java deleted file mode 100644 index 6f9ef467..00000000 --- a/code/files/ListOfLines.java +++ /dev/null @@ -1,26 +0,0 @@ -// files/ListOfLines.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.nio.file.*; - -public class ListOfLines { - public static void - main(String[] args) throws Exception { - Files.readAllLines( - Paths.get("../streams/Cheese.dat")) - .stream() - .filter(line -> !line.startsWith("//")) - .map(line -> - line.substring(0, line.length()/2)) - .forEach(System.out::println); - } -} -/* Output: -Not much of a cheese -Finest in the -And what leads you -Well, it's -It's certainly uncon -*/ diff --git a/code/files/PartsOfPaths.java b/code/files/PartsOfPaths.java deleted file mode 100644 index 1170fc68..00000000 --- a/code/files/PartsOfPaths.java +++ /dev/null @@ -1,45 +0,0 @@ -// files/PartsOfPaths.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.file.*; - -public class PartsOfPaths { - public static void main(String[] args) { - System.out.println(System.getProperty("os.name")); - Path p = - Paths.get("PartsOfPaths.java").toAbsolutePath(); - for(int i = 0; i < p.getNameCount(); i++) - System.out.println(p.getName(i)); - System.out.println("ends with '.java': " + - p.endsWith(".java")); - for(Path pp : p) { - System.out.print(pp + ": "); - System.out.print(p.startsWith(pp) + " : "); - System.out.println(p.endsWith(pp)); - } - System.out.println("Starts with " + p.getRoot() + - " " + p.startsWith(p.getRoot())); - } -} -/* Output: -Windows 10 -Users -Bruce -Documents -GitHub -on-java -ExtractedExamples -files -PartsOfPaths.java -ends with '.java': false -Users: false : false -Bruce: false : false -Documents: false : false -GitHub: false : false -on-java: false : false -ExtractedExamples: false : false -files: false : false -PartsOfPaths.java: false : true -Starts with C:\ true -*/ diff --git a/code/files/PathAnalysis.java b/code/files/PathAnalysis.java deleted file mode 100644 index 117119cd..00000000 --- a/code/files/PathAnalysis.java +++ /dev/null @@ -1,56 +0,0 @@ -// files/PathAnalysis.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.file.*; -import java.io.IOException; - -public class PathAnalysis { - static void say(String id, Object result) { - System.out.print(id + ": "); - System.out.println(result); - } - public static void - main(String[] args) throws IOException { - System.out.println(System.getProperty("os.name")); - Path p = - Paths.get("PathAnalysis.java").toAbsolutePath(); - say("Exists", Files.exists(p)); - say("Directory", Files.isDirectory(p)); - say("Executable", Files.isExecutable(p)); - say("Readable", Files.isReadable(p)); - say("RegularFile", Files.isRegularFile(p)); - say("Writable", Files.isWritable(p)); - say("notExists", Files.notExists(p)); - say("Hidden", Files.isHidden(p)); - say("size", Files.size(p)); - say("FileStore", Files.getFileStore(p)); - say("LastModified: ", Files.getLastModifiedTime(p)); - say("Owner", Files.getOwner(p)); - say("ContentType", Files.probeContentType(p)); - say("SymbolicLink", Files.isSymbolicLink(p)); - if(Files.isSymbolicLink(p)) - say("SymbolicLink", Files.readSymbolicLink(p)); - if(FileSystems.getDefault() - .supportedFileAttributeViews().contains("posix")) - say("PosixFilePermissions", - Files.getPosixFilePermissions(p)); - } -} -/* Output: -Windows 10 -Exists: true -Directory: false -Executable: true -Readable: true -RegularFile: true -Writable: true -notExists: false -Hidden: false -size: 1631 -FileStore: SSD (C:) -LastModified: : 2017-05-09T12:07:00.428366Z -Owner: MINDVIEWTOSHIBA\Bruce (User) -ContentType: null -SymbolicLink: false -*/ diff --git a/code/files/PathInfo.java b/code/files/PathInfo.java deleted file mode 100644 index 96af9d93..00000000 --- a/code/files/PathInfo.java +++ /dev/null @@ -1,102 +0,0 @@ -// files/PathInfo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.file.*; -import java.net.URI; -import java.io.File; -import java.io.IOException; - -public class PathInfo { - static void show(String id, Object p) { - System.out.println(id + ": " + p); - } - static void info(Path p) { - show("toString", p); - show("Exists", Files.exists(p)); - show("RegularFile", Files.isRegularFile(p)); - show("Directory", Files.isDirectory(p)); - show("Absolute", p.isAbsolute()); - show("FileName", p.getFileName()); - show("Parent", p.getParent()); - show("Root", p.getRoot()); - System.out.println("******************"); - } - public static void main(String[] args) { - System.out.println(System.getProperty("os.name")); - info(Paths.get( - "C:", "path", "to", "nowhere", "NoFile.txt")); - Path p = Paths.get("PathInfo.java"); - info(p); - Path ap = p.toAbsolutePath(); - info(ap); - info(ap.getParent()); - try { - info(p.toRealPath()); - } catch(IOException e) { - System.out.println(e); - } - URI u = p.toUri(); - System.out.println("URI: " + u); - Path puri = Paths.get(u); - System.out.println(Files.exists(puri)); - File f = ap.toFile(); // Don't be fooled - } -} -/* Output: -Windows 10 -toString: C:\path\to\nowhere\NoFile.txt -Exists: false -RegularFile: false -Directory: false -Absolute: true -FileName: NoFile.txt -Parent: C:\path\to\nowhere -Root: C:\ -****************** -toString: PathInfo.java -Exists: true -RegularFile: true -Directory: false -Absolute: false -FileName: PathInfo.java -Parent: null -Root: null -****************** -toString: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files\PathInfo.java -Exists: true -RegularFile: true -Directory: false -Absolute: true -FileName: PathInfo.java -Parent: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files -Root: C:\ -****************** -toString: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files -Exists: true -RegularFile: false -Directory: true -Absolute: true -FileName: files -Parent: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples -Root: C:\ -****************** -toString: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files\PathInfo.java -Exists: true -RegularFile: true -Directory: false -Absolute: true -FileName: PathInfo.java -Parent: C:\Users\Bruce\Documents\GitHub\on- -java\ExtractedExamples\files -Root: C:\ -****************** -URI: file:///C:/Users/Bruce/Documents/GitHub/on- -java/ExtractedExamples/files/PathInfo.java -true -*/ diff --git a/code/files/PathWatcher.java b/code/files/PathWatcher.java deleted file mode 100644 index 162641d7..00000000 --- a/code/files/PathWatcher.java +++ /dev/null @@ -1,61 +0,0 @@ -// files/PathWatcher.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromGradle} -import java.io.IOException; -import java.nio.file.*; -import static java.nio.file.StandardWatchEventKinds.*; -import java.util.concurrent.*; - -public class PathWatcher { - static Path test = Paths.get("test"); - static void delTxtFiles() { - try { - Files.walk(test) - .filter(f -> - f.toString().endsWith(".txt")) - .forEach(f -> { - try { - System.out.println("deleting " + f); - Files.delete(f); - } catch(IOException e) { - throw new RuntimeException(e); - } - }); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - public static void - main(String[] args) throws Exception { - Directories.refreshTestDir(); - Directories.populateTestDir(); - Files.createFile(test.resolve("Hello.txt")); - WatchService watcher = - FileSystems.getDefault().newWatchService(); - test.register(watcher, ENTRY_DELETE); - Executors.newSingleThreadScheduledExecutor() - .schedule( - PathWatcher::delTxtFiles, - 250, TimeUnit.MILLISECONDS); - WatchKey key = watcher.take(); - for(WatchEvent evt : key.pollEvents()) { - System.out.println( - "evt.context(): " + evt.context() + - "\nevt.count(): " + evt.count() + - "\nevt.kind(): " + evt.kind()); - System.exit(0); - } - } -} -/* Output: -deleting test\bag\foo\bar\baz\File.txt -deleting test\bar\baz\bag\foo\File.txt -deleting test\baz\bag\foo\bar\File.txt -deleting test\foo\bar\baz\bag\File.txt -deleting test\Hello.txt -evt.context(): Hello.txt -evt.count(): 1 -evt.kind(): ENTRY_DELETE -*/ diff --git a/code/files/ReadLineStream.java b/code/files/ReadLineStream.java deleted file mode 100644 index 64b0f562..00000000 --- a/code/files/ReadLineStream.java +++ /dev/null @@ -1,18 +0,0 @@ -// files/ReadLineStream.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.file.*; - -public class ReadLineStream { - public static void - main(String[] args) throws Exception { - Files.lines(Paths.get("PathInfo.java")) - .skip(13) - .findFirst() - .ifPresent(System.out::println); - } -} -/* Output: - show("RegularFile", Files.isRegularFile(p)); -*/ diff --git a/code/files/StreamInAndOut.java b/code/files/StreamInAndOut.java deleted file mode 100644 index ec17c700..00000000 --- a/code/files/StreamInAndOut.java +++ /dev/null @@ -1,24 +0,0 @@ -// files/StreamInAndOut.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.nio.file.*; -import java.util.stream.*; - -public class StreamInAndOut { - public static void main(String[] args) { - try( - Stream input = - Files.lines(Paths.get("StreamInAndOut.java")); - PrintWriter output = - new PrintWriter("StreamInAndOut.txt") - ) { - input - .map(String::toUpperCase) - .forEachOrdered(output::println); - } catch(Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/files/TreeWatcher.java b/code/files/TreeWatcher.java deleted file mode 100644 index f0660888..00000000 --- a/code/files/TreeWatcher.java +++ /dev/null @@ -1,51 +0,0 @@ -// files/TreeWatcher.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromGradle} -import java.io.IOException; -import java.nio.file.*; -import static java.nio.file.StandardWatchEventKinds.*; -import java.util.concurrent.*; - -public class TreeWatcher { - static void watchDir(Path dir) { - try { - WatchService watcher = - FileSystems.getDefault().newWatchService(); - dir.register(watcher, ENTRY_DELETE); - Executors.newSingleThreadExecutor().submit(() -> { - try { - WatchKey key = watcher.take(); - for(WatchEvent evt : key.pollEvents()) { - System.out.println( - "evt.context(): " + evt.context() + - "\nevt.count(): " + evt.count() + - "\nevt.kind(): " + evt.kind()); - System.exit(0); - } - } catch(InterruptedException e) { - return; - } - }); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - public static void - main(String[] args) throws Exception { - Directories.refreshTestDir(); - Directories.populateTestDir(); - Files.walk(Paths.get("test")) - .filter(Files::isDirectory) - .forEach(TreeWatcher::watchDir); - PathWatcher.delTxtFiles(); - } -} -/* Output: -deleting test\bag\foo\bar\baz\File.txt -deleting test\bar\baz\bag\foo\File.txt -evt.context(): File.txt -evt.count(): 1 -evt.kind(): ENTRY_DELETE -*/ diff --git a/code/files/Writing.java b/code/files/Writing.java deleted file mode 100644 index 68a04fbc..00000000 --- a/code/files/Writing.java +++ /dev/null @@ -1,31 +0,0 @@ -// files/Writing.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.nio.file.*; - -public class Writing { - static Random rand = new Random(47); - static final int SIZE = 1000; - public static void - main(String[] args) throws Exception { - // Write bytes to a file: - byte[] bytes = new byte[SIZE]; - rand.nextBytes(bytes); - Files.write(Paths.get("bytes.dat"), bytes); - System.out.println("bytes.dat: " + - Files.size(Paths.get("bytes.dat"))); - - // Write an iterable to a file: - List lines = Files.readAllLines( - Paths.get("../streams/Cheese.dat")); - Files.write(Paths.get("Cheese.txt"), lines); - System.out.println("Cheese.txt: " + - Files.size(Paths.get("Cheese.txt"))); - } -} -/* Output: -bytes.dat: 1000 -Cheese.txt: 199 -*/ diff --git a/code/functional/AnonymousClosure.java b/code/functional/AnonymousClosure.java deleted file mode 100644 index 497a1a52..00000000 --- a/code/functional/AnonymousClosure.java +++ /dev/null @@ -1,17 +0,0 @@ -// functional/AnonymousClosure.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class AnonymousClosure { - IntSupplier makeFun(int x) { - int i = 0; - // Same rules apply: - // i++; // Not "effectively final" - // x++; // Ditto - return new IntSupplier() { - public int getAsInt() { return x + i; } - }; - } -} diff --git a/code/functional/BiConsumerPermutations.java b/code/functional/BiConsumerPermutations.java deleted file mode 100644 index 75b7c32d..00000000 --- a/code/functional/BiConsumerPermutations.java +++ /dev/null @@ -1,24 +0,0 @@ -// functional/BiConsumerPermutations.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class BiConsumerPermutations { - static BiConsumer bicid = (i, d) -> - System.out.format("%d, %f%n", i, d); - static BiConsumer bicdi = (d, i) -> - System.out.format("%d, %f%n", i, d); - static BiConsumer bicil = (i, l) -> - System.out.format("%d, %d%n", i, l); - public static void main(String[] args) { - bicid.accept(47, 11.34); - bicdi.accept(22.45, 92); - bicil.accept(1, 11L); - } -} -/* Output: -47, 11.340000 -92, 22.450000 -1, 11 -*/ diff --git a/code/functional/ClassFunctionals.java b/code/functional/ClassFunctionals.java deleted file mode 100644 index e5101df4..00000000 --- a/code/functional/ClassFunctionals.java +++ /dev/null @@ -1,45 +0,0 @@ -// functional/ClassFunctionals.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; - -class AA {} -class BB {} -class CC {} - -public class ClassFunctionals { - static AA f1() { return new AA(); } - static int f2(AA aa1, AA aa2) { return 1; } - static void f3(AA aa) {} - static void f4(AA aa, BB bb) {} - static CC f5(AA aa) { return new CC(); } - static CC f6(AA aa, BB bb) { return new CC(); } - static boolean f7(AA aa) { return true; } - static boolean f8(AA aa, BB bb) { return true; } - static AA f9(AA aa) { return new AA(); } - static AA f10(AA aa1, AA aa2) { return new AA(); } - public static void main(String[] args) { - Supplier s = ClassFunctionals::f1; - s.get(); - Comparator c = ClassFunctionals::f2; - c.compare(new AA(), new AA()); - Consumer cons = ClassFunctionals::f3; - cons.accept(new AA()); - BiConsumer bicons = ClassFunctionals::f4; - bicons.accept(new AA(), new BB()); - Function f = ClassFunctionals::f5; - CC cc = f.apply(new AA()); - BiFunction bif = ClassFunctionals::f6; - cc = bif.apply(new AA(), new BB()); - Predicate p = ClassFunctionals::f7; - boolean result = p.test(new AA()); - BiPredicate bip = ClassFunctionals::f8; - result = bip.test(new AA(), new BB()); - UnaryOperator uo = ClassFunctionals::f9; - AA aa = uo.apply(new AA()); - BinaryOperator bo = ClassFunctionals::f10; - aa = bo.apply(new AA(), new AA()); - } -} diff --git a/code/functional/Closure1.java b/code/functional/Closure1.java deleted file mode 100644 index 2f504f42..00000000 --- a/code/functional/Closure1.java +++ /dev/null @@ -1,12 +0,0 @@ -// functional/Closure1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class Closure1 { - int i; - IntSupplier makeFun(int x) { - return () -> x + i++; - } -} diff --git a/code/functional/Closure2.java b/code/functional/Closure2.java deleted file mode 100644 index 825cf423..00000000 --- a/code/functional/Closure2.java +++ /dev/null @@ -1,12 +0,0 @@ -// functional/Closure2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class Closure2 { - IntSupplier makeFun(int x) { - int i = 0; - return () -> x + i; - } -} diff --git a/code/functional/Closure3.java b/code/functional/Closure3.java deleted file mode 100644 index 811179fb..00000000 --- a/code/functional/Closure3.java +++ /dev/null @@ -1,14 +0,0 @@ -// functional/Closure3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -import java.util.function.*; - -public class Closure3 { - IntSupplier makeFun(int x) { - int i = 0; - // Neither x++ nor i++ will work: - return () -> x++ + i++; - } -} diff --git a/code/functional/Closure4.java b/code/functional/Closure4.java deleted file mode 100644 index 148aaf64..00000000 --- a/code/functional/Closure4.java +++ /dev/null @@ -1,12 +0,0 @@ -// functional/Closure4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class Closure4 { - IntSupplier makeFun(final int x) { - final int i = 0; - return () -> x + i; - } -} diff --git a/code/functional/Closure5.java b/code/functional/Closure5.java deleted file mode 100644 index fb9aad77..00000000 --- a/code/functional/Closure5.java +++ /dev/null @@ -1,15 +0,0 @@ -// functional/Closure5.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -import java.util.function.*; - -public class Closure5 { - IntSupplier makeFun(int x) { - int i = 0; - i++; - x++; - return () -> x + i; - } -} diff --git a/code/functional/Closure6.java b/code/functional/Closure6.java deleted file mode 100644 index 178f9b4a..00000000 --- a/code/functional/Closure6.java +++ /dev/null @@ -1,16 +0,0 @@ -// functional/Closure6.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class Closure6 { - IntSupplier makeFun(int x) { - int i = 0; - i++; - x++; - final int iFinal = i; - final int xFinal = x; - return () -> xFinal + iFinal; - } -} diff --git a/code/functional/Closure7.java b/code/functional/Closure7.java deleted file mode 100644 index 9facdc06..00000000 --- a/code/functional/Closure7.java +++ /dev/null @@ -1,14 +0,0 @@ -// functional/Closure7.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -import java.util.function.*; - -public class Closure7 { - IntSupplier makeFun(int x) { - Integer i = 0; - i = i + 1; - return () -> x + i; - } -} diff --git a/code/functional/Closure8.java b/code/functional/Closure8.java deleted file mode 100644 index 7ec059b2..00000000 --- a/code/functional/Closure8.java +++ /dev/null @@ -1,32 +0,0 @@ -// functional/Closure8.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; - -public class Closure8 { - Supplier> makeFun() { - final List ai = new ArrayList<>(); - ai.add(1); - return () -> ai; - } - public static void main(String[] args) { - Closure8 c7 = new Closure8(); - List - l1 = c7.makeFun().get(), - l2 = c7.makeFun().get(); - System.out.println(l1); - System.out.println(l2); - l1.add(42); - l2.add(96); - System.out.println(l1); - System.out.println(l2); - } -} -/* Output: -[1] -[1] -[1, 42] -[1, 96] -*/ diff --git a/code/functional/Closure9.java b/code/functional/Closure9.java deleted file mode 100644 index 4eddb47a..00000000 --- a/code/functional/Closure9.java +++ /dev/null @@ -1,15 +0,0 @@ -// functional/Closure9.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -import java.util.*; -import java.util.function.*; - -public class Closure9 { - Supplier> makeFun() { - List ai = new ArrayList<>(); - ai = new ArrayList<>(); // Reassignment - return () -> ai; - } -} diff --git a/code/functional/ConsumeFunction.java b/code/functional/ConsumeFunction.java deleted file mode 100644 index ea84a24a..00000000 --- a/code/functional/ConsumeFunction.java +++ /dev/null @@ -1,17 +0,0 @@ -// functional/ConsumeFunction.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -class One {} -class Two {} - -public class ConsumeFunction { - static Two consume(Function onetwo) { - return onetwo.apply(new One()); - } - public static void main(String[] args) { - Two two = consume(one -> new Two()); - } -} diff --git a/code/functional/CtorReference.java b/code/functional/CtorReference.java deleted file mode 100644 index 4c22bdf1..00000000 --- a/code/functional/CtorReference.java +++ /dev/null @@ -1,36 +0,0 @@ -// functional/CtorReference.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Dog { - String name; - int age = -1; // For "unknown" - Dog() { name = "stray"; } - Dog(String nm) { name = nm; } - Dog(String nm, int yrs) { name = nm; age = yrs; } -} - -interface MakeNoArgs { - Dog make(); -} - -interface Make1Arg { - Dog make(String nm); -} - -interface Make2Args { - Dog make(String nm, int age); -} - -public class CtorReference { - public static void main(String[] args) { - MakeNoArgs mna = Dog::new; // [1] - Make1Arg m1a = Dog::new; // [2] - Make2Args m2a = Dog::new; // [3] - - Dog dn = mna.make(); - Dog d1 = m1a.make("Comet"); - Dog d2 = m2a.make("Ralph", 4); - } -} diff --git a/code/functional/CurriedIntAdd.java b/code/functional/CurriedIntAdd.java deleted file mode 100644 index e89ac8e2..00000000 --- a/code/functional/CurriedIntAdd.java +++ /dev/null @@ -1,17 +0,0 @@ -// functional/CurriedIntAdd.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class CurriedIntAdd { - public static void main(String[] args) { - IntFunction - curriedIntAdd = a -> b -> a + b; - IntUnaryOperator add4 = curriedIntAdd.apply(4); - System.out.println(add4.applyAsInt(5)); - } -} -/* Output: -9 -*/ diff --git a/code/functional/Curry3Args.java b/code/functional/Curry3Args.java deleted file mode 100644 index 0fd376bc..00000000 --- a/code/functional/Curry3Args.java +++ /dev/null @@ -1,23 +0,0 @@ -// functional/Curry3Args.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class Curry3Args { - public static void main(String[] args) { - Function>> sum = - a -> b -> c -> a + b + c; - Function> hi = - sum.apply("Hi "); - Function ho = - hi.apply("Ho "); - System.out.println(ho.apply("Hup")); - } -} -/* Output: -Hi Ho Hup -*/ diff --git a/code/functional/CurryingAndPartials.java b/code/functional/CurryingAndPartials.java deleted file mode 100644 index 0addb811..00000000 --- a/code/functional/CurryingAndPartials.java +++ /dev/null @@ -1,35 +0,0 @@ -// functional/CurryingAndPartials.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class CurryingAndPartials { - // Uncurried: - static String uncurried(String a, String b) { - return a + b; - } - public static void main(String[] args) { - // Curried function: - Function> sum = - a -> b -> a + b; // [1] - - System.out.println(uncurried("Hi ", "Ho")); - - Function - hi = sum.apply("Hi "); // [2] - System.out.println(hi.apply("Ho")); - - // Partial application: - Function sumHi = - sum.apply("Hup "); - System.out.println(sumHi.apply("Ho")); - System.out.println(sumHi.apply("Hey")); - } -} -/* Output: -Hi Ho -Hi Ho -Hup Ho -Hup Hey -*/ diff --git a/code/functional/FunctionComposition.java b/code/functional/FunctionComposition.java deleted file mode 100644 index a183039d..00000000 --- a/code/functional/FunctionComposition.java +++ /dev/null @@ -1,24 +0,0 @@ -// functional/FunctionComposition.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class FunctionComposition { - static Function - f1 = s -> { - System.out.println(s); - return s.replace('A', '_'); - }, - f2 = s -> s.substring(3), - f3 = s -> s.toLowerCase(), - f4 = f1.compose(f2).andThen(f3); - public static void main(String[] args) { - System.out.println( - f4.apply("GO AFTER ALL AMBULANCES")); - } -} -/* Output: -AFTER ALL AMBULANCES -_fter _ll _mbul_nces -*/ diff --git a/code/functional/FunctionVariants.java b/code/functional/FunctionVariants.java deleted file mode 100644 index a6205462..00000000 --- a/code/functional/FunctionVariants.java +++ /dev/null @@ -1,65 +0,0 @@ -// functional/FunctionVariants.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -class Foo {} - -class Bar { - Foo f; - Bar(Foo f) { this.f = f; } -} - -class IBaz { - int i; - IBaz(int i) { - this.i = i; - } -} - -class LBaz { - long l; - LBaz(long l) { - this.l = l; - } -} - -class DBaz { - double d; - DBaz(double d) { - this.d = d; - } -} - -public class FunctionVariants { - static Function f1 = f -> new Bar(f); - static IntFunction f2 = i -> new IBaz(i); - static LongFunction f3 = l -> new LBaz(l); - static DoubleFunction f4 = d -> new DBaz(d); - static ToIntFunction f5 = ib -> ib.i; - static ToLongFunction f6 = lb -> lb.l; - static ToDoubleFunction f7 = db -> db.d; - static IntToLongFunction f8 = i -> i; - static IntToDoubleFunction f9 = i -> i; - static LongToIntFunction f10 = l -> (int)l; - static LongToDoubleFunction f11 = l -> l; - static DoubleToIntFunction f12 = d -> (int)d; - static DoubleToLongFunction f13 = d -> (long)d; - - public static void main(String[] args) { - Bar b = f1.apply(new Foo()); - IBaz ib = f2.apply(11); - LBaz lb = f3.apply(11); - DBaz db = f4.apply(11); - int i = f5.applyAsInt(ib); - long l = f6.applyAsLong(lb); - double d = f7.applyAsDouble(db); - l = f8.applyAsLong(12); - d = f9.applyAsDouble(12); - i = f10.applyAsInt(12); - d = f11.applyAsDouble(12); - i = f12.applyAsInt(13.0); - l = f13.applyAsLong(13.0); - } -} diff --git a/code/functional/FunctionWithWrapped.java b/code/functional/FunctionWithWrapped.java deleted file mode 100644 index b654da65..00000000 --- a/code/functional/FunctionWithWrapped.java +++ /dev/null @@ -1,12 +0,0 @@ -// functional/FunctionWithWrapped.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class FunctionWithWrapped { - public static void main(String[] args) { - Function fid = i -> (double)i; - IntToDoubleFunction fid2 = i -> i; - } -} diff --git a/code/functional/FunctionalAnnotation.java b/code/functional/FunctionalAnnotation.java deleted file mode 100644 index 84cec649..00000000 --- a/code/functional/FunctionalAnnotation.java +++ /dev/null @@ -1,40 +0,0 @@ -// functional/FunctionalAnnotation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -@FunctionalInterface -interface Functional { - String goodbye(String arg); -} - -interface FunctionalNoAnn { - String goodbye(String arg); -} - -/* -@FunctionalInterface -interface NotFunctional { - String goodbye(String arg); - String hello(String arg); -} -Produces error message: -NotFunctional is not a functional interface -multiple non-overriding abstract methods -found in interface NotFunctional -*/ - -public class FunctionalAnnotation { - public String goodbye(String arg) { - return "Goodbye, " + arg; - } - public static void main(String[] args) { - FunctionalAnnotation fa = - new FunctionalAnnotation(); - Functional f = fa::goodbye; - FunctionalNoAnn fna = fa::goodbye; - // Functional fac = fa; // Incompatible - Functional fl = a -> "Goodbye, " + a; - FunctionalNoAnn fnal = a -> "Goodbye, " + a; - } -} diff --git a/code/functional/IntCall.java b/code/functional/IntCall.java deleted file mode 100644 index a8256a00..00000000 --- a/code/functional/IntCall.java +++ /dev/null @@ -1,8 +0,0 @@ -// functional/IntCall.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface IntCall { - int call(int arg); -} diff --git a/code/functional/LambdaExpressions.java b/code/functional/LambdaExpressions.java deleted file mode 100644 index fe7e3acb..00000000 --- a/code/functional/LambdaExpressions.java +++ /dev/null @@ -1,48 +0,0 @@ -// functional/LambdaExpressions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface Description { - String brief(); -} - -interface Body { - String detailed(String head); -} - -interface Multi { - String twoArg(String head, Double d); -} - -public class LambdaExpressions { - - static Body bod = h -> h + " No Parens!"; // [1] - - static Body bod2 = (h) -> h + " More details"; // [2] - - static Description desc = () -> "Short info"; // [3] - - static Multi mult = (h, n) -> h + n; // [4] - - static Description moreLines = () -> { // [5] - System.out.println("moreLines()"); - return "from moreLines()"; - }; - - public static void main(String[] args) { - System.out.println(bod.detailed("Oh!")); - System.out.println(bod2.detailed("Hi!")); - System.out.println(desc.brief()); - System.out.println(mult.twoArg("Pi! ", 3.14159)); - System.out.println(moreLines.brief()); - } -} -/* Output: -Oh! No Parens! -Hi! More details -Short info -Pi! 3.14159 -moreLines() -from moreLines() -*/ diff --git a/code/functional/MethodConversion.java b/code/functional/MethodConversion.java deleted file mode 100644 index 008ecfc0..00000000 --- a/code/functional/MethodConversion.java +++ /dev/null @@ -1,31 +0,0 @@ -// functional/MethodConversion.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -class In1 {} -class In2 {} - -public class MethodConversion { - static void accept(In1 i1, In2 i2) { - System.out.println("accept()"); - } - static void someOtherName(In1 i1, In2 i2) { - System.out.println("someOtherName()"); - } - public static void main(String[] args) { - BiConsumer bic; - - bic = MethodConversion::accept; - bic.accept(new In1(), new In2()); - - bic = MethodConversion::someOtherName; - // bic.someOtherName(new In1(), new In2()); // Nope - bic.accept(new In1(), new In2()); - } -} -/* Output: -accept() -someOtherName() -*/ diff --git a/code/functional/MethodReferences.java b/code/functional/MethodReferences.java deleted file mode 100644 index 63bc365d..00000000 --- a/code/functional/MethodReferences.java +++ /dev/null @@ -1,53 +0,0 @@ -// functional/MethodReferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -interface Callable { // [1] - void call(String s); -} - -class Describe { - void show(String msg) { // [2] - System.out.println(msg); - } -} - -public class MethodReferences { - static void hello(String name) { // [3] - System.out.println("Hello, " + name); - } - static class Description { - String about; - Description(String desc) { about = desc; } - void help(String msg) { // [4] - System.out.println(about + " " + msg); - } - } - static class Helper { - static void assist(String msg) { // [5] - System.out.println(msg); - } - } - public static void main(String[] args) { - Describe d = new Describe(); - Callable c = d::show; // [6] - c.call("call()"); // [7] - - c = MethodReferences::hello; // [8] - c.call("Bob"); - - c = new Description("valuable")::help; // [9] - c.call("information"); - - c = Helper::assist; // [10] - c.call("Help!"); - } -} -/* Output: -call() -Hello, Bob -valuable information -Help! -*/ diff --git a/code/functional/MultiUnbound.java b/code/functional/MultiUnbound.java deleted file mode 100644 index 4209fb04..00000000 --- a/code/functional/MultiUnbound.java +++ /dev/null @@ -1,36 +0,0 @@ -// functional/MultiUnbound.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Unbound methods with multiple arguments - -class This { - void two(int i, double d) {} - void three(int i, double d, String s) {} - void four(int i, double d, String s, char c) {} -} - -interface TwoArgs { - void call2(This athis, int i, double d); -} - -interface ThreeArgs { - void call3(This athis, int i, double d, String s); -} - -interface FourArgs { - void call4( - This athis, int i, double d, String s, char c); -} - -public class MultiUnbound { - public static void main(String[] args) { - TwoArgs twoargs = This::two; - ThreeArgs threeargs = This::three; - FourArgs fourargs = This::four; - This athis = new This(); - twoargs.call2(athis, 11, 3.14); - threeargs.call3(athis, 11, 3.14, "Three"); - fourargs.call4(athis, 11, 3.14, "Four", 'Z'); - } -} diff --git a/code/functional/PredicateComposition.java b/code/functional/PredicateComposition.java deleted file mode 100644 index f95bbcbd..00000000 --- a/code/functional/PredicateComposition.java +++ /dev/null @@ -1,23 +0,0 @@ -// functional/PredicateComposition.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; -import java.util.stream.*; - -public class PredicateComposition { - static Predicate - p1 = s -> s.contains("bar"), - p2 = s -> s.length() < 5, - p3 = s -> s.contains("foo"), - p4 = p1.negate().and(p2).or(p3); - public static void main(String[] args) { - Stream.of("bar", "foobar", "foobaz", "fongopuckey") - .filter(p4) - .forEach(System.out::println); - } -} -/* Output: -foobar -foobaz -*/ diff --git a/code/functional/ProduceFunction.java b/code/functional/ProduceFunction.java deleted file mode 100644 index 03471601..00000000 --- a/code/functional/ProduceFunction.java +++ /dev/null @@ -1,21 +0,0 @@ -// functional/ProduceFunction.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -interface -FuncSS extends Function {} // [1] - -public class ProduceFunction { - static FuncSS produce() { - return s -> s.toLowerCase(); // [2] - } - public static void main(String[] args) { - FuncSS f = produce(); - System.out.println(f.apply("YELLING")); - } -} -/* Output: -yelling -*/ diff --git a/code/functional/RecursiveFactorial.java b/code/functional/RecursiveFactorial.java deleted file mode 100644 index 2d610441..00000000 --- a/code/functional/RecursiveFactorial.java +++ /dev/null @@ -1,26 +0,0 @@ -// functional/RecursiveFactorial.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class RecursiveFactorial { - static IntCall fact; - public static void main(String[] args) { - fact = n -> n == 0 ? 1 : n * fact.call(n - 1); - for(int i = 0; i <= 10; i++) - System.out.println(fact.call(i)); - } -} -/* Output: -1 -1 -2 -6 -24 -120 -720 -5040 -40320 -362880 -3628800 -*/ diff --git a/code/functional/RecursiveFibonacci.java b/code/functional/RecursiveFibonacci.java deleted file mode 100644 index 9be43dc6..00000000 --- a/code/functional/RecursiveFibonacci.java +++ /dev/null @@ -1,32 +0,0 @@ -// functional/RecursiveFibonacci.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class RecursiveFibonacci { - IntCall fib; - RecursiveFibonacci() { - fib = n -> n == 0 ? 0 : - n == 1 ? 1 : - fib.call(n - 1) + fib.call(n - 2); - } - int fibonacci(int n) { return fib.call(n); } - public static void main(String[] args) { - RecursiveFibonacci rf = new RecursiveFibonacci(); - for(int i = 0; i <= 10; i++) - System.out.println(rf.fibonacci(i)); - } -} -/* Output: -0 -1 -1 -2 -3 -5 -8 -13 -21 -34 -55 -*/ diff --git a/code/functional/RunnableMethodReference.java b/code/functional/RunnableMethodReference.java deleted file mode 100644 index 5fb8cd00..00000000 --- a/code/functional/RunnableMethodReference.java +++ /dev/null @@ -1,33 +0,0 @@ -// functional/RunnableMethodReference.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Method references with interface Runnable - -class Go { - static void go() { - System.out.println("Go::go()"); - } -} - -public class RunnableMethodReference { - public static void main(String[] args) { - - new Thread(new Runnable() { - public void run() { - System.out.println("Anonymous"); - } - }).start(); - - new Thread( - () -> System.out.println("lambda") - ).start(); - - new Thread(Go::go).start(); - } -} -/* Output: -Anonymous -lambda -Go::go() -*/ diff --git a/code/functional/SharedStorage.java b/code/functional/SharedStorage.java deleted file mode 100644 index c2a41f66..00000000 --- a/code/functional/SharedStorage.java +++ /dev/null @@ -1,22 +0,0 @@ -// functional/SharedStorage.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class SharedStorage { - public static void main(String[] args) { - Closure1 c1 = new Closure1(); - IntSupplier f1 = c1.makeFun(0); - IntSupplier f2 = c1.makeFun(0); - IntSupplier f3 = c1.makeFun(0); - System.out.println(f1.getAsInt()); - System.out.println(f2.getAsInt()); - System.out.println(f3.getAsInt()); - } -} -/* Output: -0 -1 -2 -*/ diff --git a/code/functional/Strategize.java b/code/functional/Strategize.java deleted file mode 100644 index e46c9143..00000000 --- a/code/functional/Strategize.java +++ /dev/null @@ -1,58 +0,0 @@ -// functional/Strategize.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface Strategy { - String approach(String msg); -} - -class Soft implements Strategy { - public String approach(String msg) { - return msg.toLowerCase() + "?"; - } -} - -class Unrelated { - static String twice(String msg) { - return msg + " " + msg; - } -} - -public class Strategize { - Strategy strategy; - String msg; - Strategize(String msg) { - strategy = new Soft(); // [1] - this.msg = msg; - } - void communicate() { - System.out.println(strategy.approach(msg)); - } - void changeStrategy(Strategy strategy) { - this.strategy = strategy; - } - public static void main(String[] args) { - Strategy[] strategies = { - new Strategy() { // [2] - public String approach(String msg) { - return msg.toUpperCase() + "!"; - } - }, - msg -> msg.substring(0, 5), // [3] - Unrelated::twice // [4] - }; - Strategize s = new Strategize("Hello there"); - s.communicate(); - for(Strategy newStrategy : strategies) { - s.changeStrategy(newStrategy); // [5] - s.communicate(); // [6] - } - } -} -/* Output: -hello there? -HELLO THERE! -Hello -Hello there Hello there -*/ diff --git a/code/functional/TransformFunction.java b/code/functional/TransformFunction.java deleted file mode 100644 index 1a046eb1..00000000 --- a/code/functional/TransformFunction.java +++ /dev/null @@ -1,35 +0,0 @@ -// functional/TransformFunction.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -class I { - @Override - public String toString() { return "I"; } -} - -class O { - @Override - public String toString() { return "O"; } -} - -public class TransformFunction { - static Function transform(Function in) { - return in.andThen(o -> { - System.out.println(o); - return o; - }); - } - public static void main(String[] args) { - Function f2 = transform(i -> { - System.out.println(i); - return new O(); - }); - O o = f2.apply(new I()); - } -} -/* Output: -I -O -*/ diff --git a/code/functional/TriFunction.java b/code/functional/TriFunction.java deleted file mode 100644 index 76049621..00000000 --- a/code/functional/TriFunction.java +++ /dev/null @@ -1,9 +0,0 @@ -// functional/TriFunction.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -@FunctionalInterface -public interface TriFunction { - R apply(T t, U u, V v); -} diff --git a/code/functional/TriFunctionTest.java b/code/functional/TriFunctionTest.java deleted file mode 100644 index fccf8b9a..00000000 --- a/code/functional/TriFunctionTest.java +++ /dev/null @@ -1,13 +0,0 @@ -// functional/TriFunctionTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class TriFunctionTest { - static int f(int i, long l, double d) { return 99; } - public static void main(String[] args) { - TriFunction tf = - TriFunctionTest::f; - tf = (i, l, d) -> 12; - } -} diff --git a/code/functional/UnboundMethodReference.java b/code/functional/UnboundMethodReference.java deleted file mode 100644 index da2c7872..00000000 --- a/code/functional/UnboundMethodReference.java +++ /dev/null @@ -1,31 +0,0 @@ -// functional/UnboundMethodReference.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Method reference without an object - -class X { - String f() { return "X::f()"; } -} - -interface MakeString { - String make(); -} - -interface TransformX { - String transform(X x); -} - -public class UnboundMethodReference { - public static void main(String[] args) { - // MakeString ms = X::f; // [1] - TransformX sp = X::f; - X x = new X(); - System.out.println(sp.transform(x)); // [2] - System.out.println(x.f()); // Same effect - } -} -/* Output: -X::f() -X::f() -*/ diff --git a/code/generics/Amphibian.java b/code/generics/Amphibian.java deleted file mode 100644 index 5e76d8b1..00000000 --- a/code/generics/Amphibian.java +++ /dev/null @@ -1,5 +0,0 @@ -// generics/Amphibian.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class Amphibian {} diff --git a/code/generics/Apply.java b/code/generics/Apply.java deleted file mode 100644 index c9378611..00000000 --- a/code/generics/Apply.java +++ /dev/null @@ -1,21 +0,0 @@ -// generics/Apply.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.reflect.*; -import java.util.*; - -public class Apply { - public static > - void apply(S seq, Method f, Object... args) { - try { - for(T t: seq) - f.invoke(t, args); - } catch(IllegalAccessException | - IllegalArgumentException | - InvocationTargetException e) { - // Failures are programmer errors - throw new RuntimeException(e); - } - } -} diff --git a/code/generics/ApplyFunctional.java b/code/generics/ApplyFunctional.java deleted file mode 100644 index 4cce156e..00000000 --- a/code/generics/ApplyFunctional.java +++ /dev/null @@ -1,49 +0,0 @@ -// generics/ApplyFunctional.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; -import onjava.*; - -public class ApplyFunctional { - public static void main(String[] args) { - Stream.of( - Stream.generate(Shape::new).limit(2), - Stream.generate(Square::new).limit(2)) - .flatMap(c -> c) // flatten into one stream - .peek(Shape::rotate) - .forEach(s -> s.resize(7)); - - new FilledList<>(Shape::new, 2) - .forEach(Shape::rotate); - new FilledList<>(Square::new, 2) - .forEach(Shape::rotate); - - SimpleQueue shapeQ = Suppliers.fill( - new SimpleQueue<>(), SimpleQueue::add, - Shape::new, 2); - Suppliers.fill(shapeQ, SimpleQueue::add, - Square::new, 2); - shapeQ.forEach(Shape::rotate); - } -} -/* Output: -Shape 0 rotate -Shape 0 resize 7 -Shape 1 rotate -Shape 1 resize 7 -Square 2 rotate -Square 2 resize 7 -Square 3 rotate -Square 3 resize 7 -Shape 4 rotate -Shape 5 rotate -Square 6 rotate -Square 7 rotate -Shape 8 rotate -Shape 9 rotate -Square 10 rotate -Square 11 rotate -*/ diff --git a/code/generics/ApplyTest.java b/code/generics/ApplyTest.java deleted file mode 100644 index 62ef4eec..00000000 --- a/code/generics/ApplyTest.java +++ /dev/null @@ -1,65 +0,0 @@ -// generics/ApplyTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import onjava.*; - -public class ApplyTest { - public static - void main(String[] args) throws Exception { - List shapes = - Suppliers.create(ArrayList::new, Shape::new, 3); - Apply.apply(shapes, - Shape.class.getMethod("rotate")); - Apply.apply(shapes, - Shape.class.getMethod("resize", int.class), 7); - - List squares = - Suppliers.create(ArrayList::new, Square::new, 3); - Apply.apply(squares, - Shape.class.getMethod("rotate")); - Apply.apply(squares, - Shape.class.getMethod("resize", int.class), 7); - - Apply.apply(new FilledList<>(Shape::new, 3), - Shape.class.getMethod("rotate")); - Apply.apply(new FilledList<>(Square::new, 3), - Shape.class.getMethod("rotate")); - - SimpleQueue shapeQ = Suppliers.fill( - new SimpleQueue<>(), SimpleQueue::add, - Shape::new, 3); - Suppliers.fill(shapeQ, SimpleQueue::add, - Square::new, 3); - Apply.apply(shapeQ, - Shape.class.getMethod("rotate")); - } -} -/* Output: -Shape 0 rotate -Shape 1 rotate -Shape 2 rotate -Shape 0 resize 7 -Shape 1 resize 7 -Shape 2 resize 7 -Square 3 rotate -Square 4 rotate -Square 5 rotate -Square 3 resize 7 -Square 4 resize 7 -Square 5 resize 7 -Shape 6 rotate -Shape 7 rotate -Shape 8 rotate -Square 9 rotate -Square 10 rotate -Square 11 rotate -Shape 12 rotate -Shape 13 rotate -Shape 14 rotate -Square 15 rotate -Square 16 rotate -Square 17 rotate -*/ diff --git a/code/generics/ArrayMaker.java b/code/generics/ArrayMaker.java deleted file mode 100644 index f1bb6b9a..00000000 --- a/code/generics/ArrayMaker.java +++ /dev/null @@ -1,24 +0,0 @@ -// generics/ArrayMaker.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.reflect.*; -import java.util.*; - -public class ArrayMaker { - private Class kind; - public ArrayMaker(Class kind) { this.kind = kind; } - @SuppressWarnings("unchecked") - T[] create(int size) { - return (T[])Array.newInstance(kind, size); - } - public static void main(String[] args) { - ArrayMaker stringMaker = - new ArrayMaker<>(String.class); - String[] stringArray = stringMaker.create(9); - System.out.println(Arrays.toString(stringArray)); - } -} -/* Output: -[null, null, null, null, null, null, null, null, null] -*/ diff --git a/code/generics/ArrayOfGeneric.java b/code/generics/ArrayOfGeneric.java deleted file mode 100644 index 67e6cb97..00000000 --- a/code/generics/ArrayOfGeneric.java +++ /dev/null @@ -1,28 +0,0 @@ -// generics/ArrayOfGeneric.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ArrayOfGeneric { - static final int SIZE = 100; - static Generic[] gia; - @SuppressWarnings("unchecked") - public static void main(String[] args) { - try { - gia = (Generic[])new Object[SIZE]; - } catch(ClassCastException e) { - System.out.println(e.getMessage()); - } - // Runtime type is the raw (erased) type: - gia = (Generic[])new Generic[SIZE]; - System.out.println(gia.getClass().getSimpleName()); - gia[0] = new Generic<>(); - //- gia[1] = new Object(); // Compile-time error - // Discovers type mismatch at compile time: - //- gia[2] = new Generic(); - } -} -/* Output: -[Ljava.lang.Object; cannot be cast to [LGeneric; -Generic[] -*/ diff --git a/code/generics/ArrayOfGenericReference.java b/code/generics/ArrayOfGenericReference.java deleted file mode 100644 index 1cb2f345..00000000 --- a/code/generics/ArrayOfGenericReference.java +++ /dev/null @@ -1,10 +0,0 @@ -// generics/ArrayOfGenericReference.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Generic {} - -public class ArrayOfGenericReference { - static Generic[] gia; -} diff --git a/code/generics/BankTeller.java b/code/generics/BankTeller.java deleted file mode 100644 index 68301996..00000000 --- a/code/generics/BankTeller.java +++ /dev/null @@ -1,71 +0,0 @@ -// generics/BankTeller.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A very simple bank teller simulation -import java.util.*; -import onjava.*; - -class Customer { - private static long counter = 1; - private final long id = counter++; - @Override - public String toString() { - return "Customer " + id; - } -} - -class Teller { - private static long counter = 1; - private final long id = counter++; - @Override - public String toString() { - return "Teller " + id; - } -} - -class Bank { - private List tellers = - new ArrayList<>(); - public void put(BankTeller bt) { - tellers.add(bt); - } -} - -public class BankTeller { - public static void serve(Teller t, Customer c) { - System.out.println(t + " serves " + c); - } - public static void main(String[] args) { - // Demonstrate create(): - RandomList tellers = - Suppliers.create( - RandomList::new, Teller::new, 4); - // Demonstrate fill(): - List customers = Suppliers.fill( - new ArrayList<>(), Customer::new, 12); - customers.forEach(c -> - serve(tellers.select(), c)); - // Demonstrate assisted latent typing: - Bank bank = Suppliers.fill( - new Bank(), Bank::put, BankTeller::new, 3); - // Can also use second version of fill(): - List customers2 = Suppliers.fill( - new ArrayList<>(), - List::add, Customer::new, 12); - } -} -/* Output: -Teller 3 serves Customer 1 -Teller 2 serves Customer 2 -Teller 3 serves Customer 3 -Teller 1 serves Customer 4 -Teller 1 serves Customer 5 -Teller 3 serves Customer 6 -Teller 1 serves Customer 7 -Teller 2 serves Customer 8 -Teller 3 serves Customer 9 -Teller 3 serves Customer 10 -Teller 2 serves Customer 11 -Teller 4 serves Customer 12 -*/ diff --git a/code/generics/BasicBounds.java b/code/generics/BasicBounds.java deleted file mode 100644 index 434d0fd8..00000000 --- a/code/generics/BasicBounds.java +++ /dev/null @@ -1,63 +0,0 @@ -// generics/BasicBounds.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface HasColor { java.awt.Color getColor(); } - -class WithColor { - T item; - WithColor(T item) { this.item = item; } - T getItem() { return item; } - // The bound allows you to call a method: - java.awt.Color color() { return item.getColor(); } -} - -class Coord { public int x, y, z; } - -// This fails. Class must be first, then interfaces: -// class WithColorCoord { - -// Multiple bounds: -class WithColorCoord { - T item; - WithColorCoord(T item) { this.item = item; } - T getItem() { return item; } - java.awt.Color color() { return item.getColor(); } - int getX() { return item.x; } - int getY() { return item.y; } - int getZ() { return item.z; } -} - -interface Weight { int weight(); } - -// As with inheritance, you can have only one -// concrete class but multiple interfaces: -class Solid { - T item; - Solid(T item) { this.item = item; } - T getItem() { return item; } - java.awt.Color color() { return item.getColor(); } - int getX() { return item.x; } - int getY() { return item.y; } - int getZ() { return item.z; } - int weight() { return item.weight(); } -} - -class Bounded -extends Coord implements HasColor, Weight { - @Override - public java.awt.Color getColor() { return null; } - @Override - public int weight() { return 0; } -} - -public class BasicBounds { - public static void main(String[] args) { - Solid solid = - new Solid<>(new Bounded()); - solid.color(); - solid.getY(); - solid.weight(); - } -} diff --git a/code/generics/BasicHolder.java b/code/generics/BasicHolder.java deleted file mode 100644 index 2b8b8a9b..00000000 --- a/code/generics/BasicHolder.java +++ /dev/null @@ -1,14 +0,0 @@ -// generics/BasicHolder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class BasicHolder { - T element; - void set(T arg) { element = arg; } - T get() { return element; } - void f() { - System.out.println( - element.getClass().getSimpleName()); - } -} diff --git a/code/generics/BasicSupplierDemo.java b/code/generics/BasicSupplierDemo.java deleted file mode 100644 index 1ce95ca1..00000000 --- a/code/generics/BasicSupplierDemo.java +++ /dev/null @@ -1,22 +0,0 @@ -// generics/BasicSupplierDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; -import java.util.stream.*; - -public class BasicSupplierDemo { - public static void main(String[] args) { - Stream.generate( - BasicSupplier.create(CountedObject.class)) - .limit(5) - .forEach(System.out::println); - } -} -/* Output: -CountedObject 0 -CountedObject 1 -CountedObject 2 -CountedObject 3 -CountedObject 4 -*/ diff --git a/code/generics/ByteSet.java b/code/generics/ByteSet.java deleted file mode 100644 index 19b27091..00000000 --- a/code/generics/ByteSet.java +++ /dev/null @@ -1,14 +0,0 @@ -// generics/ByteSet.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ByteSet { - Byte[] possibles = { 1,2,3,4,5,6,7,8,9 }; - Set mySet = - new HashSet<>(Arrays.asList(possibles)); - // But you can't do this: - // Set mySet2 = new HashSet<>( - // Arrays.asList(1,2,3,4,5,6,7,8,9)); -} diff --git a/code/generics/CRGWithBasicHolder.java b/code/generics/CRGWithBasicHolder.java deleted file mode 100644 index eb85868a..00000000 --- a/code/generics/CRGWithBasicHolder.java +++ /dev/null @@ -1,20 +0,0 @@ -// generics/CRGWithBasicHolder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Subtype extends BasicHolder {} - -public class CRGWithBasicHolder { - public static void main(String[] args) { - Subtype - st1 = new Subtype(), - st2 = new Subtype(); - st1.set(st2); - Subtype st3 = st1.get(); - st1.f(); - } -} -/* Output: -Subtype -*/ diff --git a/code/generics/CaptureConversion.java b/code/generics/CaptureConversion.java deleted file mode 100644 index 16348468..00000000 --- a/code/generics/CaptureConversion.java +++ /dev/null @@ -1,62 +0,0 @@ -// generics/CaptureConversion.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class CaptureConversion { - static void f1(Holder holder) { - T t = holder.get(); - System.out.println(t.getClass().getSimpleName()); - } - static void f2(Holder holder) { - f1(holder); // Call with captured type - } - @SuppressWarnings("unchecked") - public static void main(String[] args) { - Holder raw = new Holder<>(1); - - f1(raw); - // warning: [unchecked] unchecked method invocation: - // method f1 in class CaptureConversion - // is applied to given types - // f1(raw); - // ^ - // required: Holder - // found: Holder - // where T is a type-variable: - // T extends Object declared in - // method f1(Holder) - // warning: [unchecked] unchecked conversion - // f1(raw); - // ^ - // required: Holder - // found: Holder - // where T is a type-variable: - // T extends Object declared in - // method f1(Holder) - // 2 warnings - - f2(raw); // No warnings - Holder rawBasic = new Holder(); - - rawBasic.set(new Object()); - // warning: [unchecked] unchecked call to set(T) - // as a member of the raw type Holder - // rawBasic.set(new Object()); - // ^ - // where T is a type-variable: - // T extends Object declared in class Holder - // 1 warning - - f2(rawBasic); // No warnings - // Upcast to Holder, still figures it out: - Holder wildcarded = new Holder<>(1.0); - f2(wildcarded); - } -} -/* Output: -Integer -Integer -Object -Double -*/ diff --git a/code/generics/CheckedList.java b/code/generics/CheckedList.java deleted file mode 100644 index 6e330cf6..00000000 --- a/code/generics/CheckedList.java +++ /dev/null @@ -1,35 +0,0 @@ -// generics/CheckedList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using Collection.checkedList() -import typeinfo.pets.*; -import java.util.*; - -public class CheckedList { - @SuppressWarnings("unchecked") - static void oldStyleMethod(List probablyDogs) { - probablyDogs.add(new Cat()); - } - public static void main(String[] args) { - List dogs1 = new ArrayList<>(); - oldStyleMethod(dogs1); // Quietly accepts a Cat - List dogs2 = Collections.checkedList( - new ArrayList<>(), Dog.class); - try { - oldStyleMethod(dogs2); // Throws an exception - } catch(Exception e) { - System.out.println("Expected: " + e); - } - // Derived types work fine: - List pets = Collections.checkedList( - new ArrayList<>(), Pet.class); - pets.add(new Dog()); - pets.add(new Cat()); - } -} -/* Output: -Expected: java.lang.ClassCastException: Attempt to -insert class typeinfo.pets.Cat element into collection -with element type class typeinfo.pets.Dog -*/ diff --git a/code/generics/ClassCasting.java b/code/generics/ClassCasting.java deleted file mode 100644 index c6da592a..00000000 --- a/code/generics/ClassCasting.java +++ /dev/null @@ -1,18 +0,0 @@ -// generics/ClassCasting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.util.*; - -public class ClassCasting { - @SuppressWarnings("unchecked") - public void f(String[] args) throws Exception { - ObjectInputStream in = new ObjectInputStream( - new FileInputStream(args[0])); - // Won't Compile: -// List lw1 = -// List<>.class.cast(in.readObject()); - List lw2 = List.class.cast(in.readObject()); - } -} diff --git a/code/generics/ClassTypeCapture.java b/code/generics/ClassTypeCapture.java deleted file mode 100644 index ab193dfe..00000000 --- a/code/generics/ClassTypeCapture.java +++ /dev/null @@ -1,33 +0,0 @@ -// generics/ClassTypeCapture.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Building {} -class House extends Building {} - -public class ClassTypeCapture { - Class kind; - public ClassTypeCapture(Class kind) { - this.kind = kind; - } - public boolean f(Object arg) { - return kind.isInstance(arg); - } - public static void main(String[] args) { - ClassTypeCapture ctt1 = - new ClassTypeCapture<>(Building.class); - System.out.println(ctt1.f(new Building())); - System.out.println(ctt1.f(new House())); - ClassTypeCapture ctt2 = - new ClassTypeCapture<>(House.class); - System.out.println(ctt2.f(new Building())); - System.out.println(ctt2.f(new House())); - } -} -/* Output: -true -true -false -true -*/ diff --git a/code/generics/ComparablePet.java b/code/generics/ComparablePet.java deleted file mode 100644 index 3646e66a..00000000 --- a/code/generics/ComparablePet.java +++ /dev/null @@ -1,12 +0,0 @@ -// generics/ComparablePet.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ComparablePet -implements Comparable { - @Override - public int compareTo(ComparablePet arg) { - return 0; - } -} diff --git a/code/generics/CompilerIntelligence.java b/code/generics/CompilerIntelligence.java deleted file mode 100644 index 6e4cd0e8..00000000 --- a/code/generics/CompilerIntelligence.java +++ /dev/null @@ -1,15 +0,0 @@ -// generics/CompilerIntelligence.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class CompilerIntelligence { - public static void main(String[] args) { - List flist = - Arrays.asList(new Apple()); - Apple a = (Apple)flist.get(0); // No warning - flist.contains(new Apple()); // Argument is 'Object' - flist.indexOf(new Apple()); // Argument is 'Object' - } -} diff --git a/code/generics/CountedObject.java b/code/generics/CountedObject.java deleted file mode 100644 index ab4caecd..00000000 --- a/code/generics/CountedObject.java +++ /dev/null @@ -1,14 +0,0 @@ -// generics/CountedObject.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class CountedObject { - private static long counter = 0; - private final long id = counter++; - public long id() { return id; } - @Override - public String toString() { - return "CountedObject " + id; - } -} diff --git a/code/generics/CovariantArrays.java b/code/generics/CovariantArrays.java deleted file mode 100644 index e202ca07..00000000 --- a/code/generics/CovariantArrays.java +++ /dev/null @@ -1,30 +0,0 @@ -// generics/CovariantArrays.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Fruit {} -class Apple extends Fruit {} -class Jonathan extends Apple {} -class Orange extends Fruit {} - -public class CovariantArrays { - public static void main(String[] args) { - Fruit[] fruit = new Apple[10]; - fruit[0] = new Apple(); // OK - fruit[1] = new Jonathan(); // OK - // Runtime type is Apple[], not Fruit[] or Orange[]: - try { - // Compiler allows you to add Fruit: - fruit[0] = new Fruit(); // ArrayStoreException - } catch(Exception e) { System.out.println(e); } - try { - // Compiler allows you to add Oranges: - fruit[0] = new Orange(); // ArrayStoreException - } catch(Exception e) { System.out.println(e); } - } -} -/* Output: -java.lang.ArrayStoreException: Fruit -java.lang.ArrayStoreException: Orange -*/ diff --git a/code/generics/CovariantReturnTypes.java b/code/generics/CovariantReturnTypes.java deleted file mode 100644 index 04178ad4..00000000 --- a/code/generics/CovariantReturnTypes.java +++ /dev/null @@ -1,23 +0,0 @@ -// generics/CovariantReturnTypes.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Base {} -class Derived extends Base {} - -interface OrdinaryGetter { - Base get(); -} - -interface DerivedGetter extends OrdinaryGetter { - // Overridden method return type can vary: - @Override - Derived get(); -} - -public class CovariantReturnTypes { - void test(DerivedGetter d) { - Derived d2 = d.get(); - } -} diff --git a/code/generics/CreatorGeneric.java b/code/generics/CreatorGeneric.java deleted file mode 100644 index 7fd90df4..00000000 --- a/code/generics/CreatorGeneric.java +++ /dev/null @@ -1,31 +0,0 @@ -// generics/CreatorGeneric.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -abstract class GenericWithCreate { - final T element; - GenericWithCreate() { element = create(); } - abstract T create(); -} - -class X {} - -class XCreator extends GenericWithCreate { - @Override - X create() { return new X(); } - void f() { - System.out.println( - element.getClass().getSimpleName()); - } -} - -public class CreatorGeneric { - public static void main(String[] args) { - XCreator xc = new XCreator(); - xc.f(); - } -} -/* Output: -X -*/ diff --git a/code/generics/CuriouslyRecurringGeneric.java b/code/generics/CuriouslyRecurringGeneric.java deleted file mode 100644 index ee1f3a61..00000000 --- a/code/generics/CuriouslyRecurringGeneric.java +++ /dev/null @@ -1,9 +0,0 @@ -// generics/CuriouslyRecurringGeneric.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class GenericType {} - -public class CuriouslyRecurringGeneric - extends GenericType {} diff --git a/code/generics/Diamond.java b/code/generics/Diamond.java deleted file mode 100644 index 32c3ff1a..00000000 --- a/code/generics/Diamond.java +++ /dev/null @@ -1,13 +0,0 @@ -// generics/Diamond.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Bob {} - -public class Diamond { - public static void main(String[] args) { - GenericHolder h3 = new GenericHolder<>(); - h3.set(new Bob()); - } -} diff --git a/code/generics/DogsAndRobotMethodReferences.java b/code/generics/DogsAndRobotMethodReferences.java deleted file mode 100644 index 7c3fa357..00000000 --- a/code/generics/DogsAndRobotMethodReferences.java +++ /dev/null @@ -1,45 +0,0 @@ -// generics/DogsAndRobotMethodReferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// "Assisted Latent Typing" -import typeinfo.pets.*; -import java.util.function.*; - -class PerformingDogA extends Dog { - public void speak() { System.out.println("Woof!"); } - public void sit() { System.out.println("Sitting"); } - public void reproduce() {} -} - -class RobotA { - public void speak() { System.out.println("Click!"); } - public void sit() { System.out.println("Clank!"); } - public void oilChange() {} -} - -class CommunicateA { - public static

void perform(P performer, - Consumer

action1, Consumer

action2) { - action1.accept(performer); - action2.accept(performer); - } -} - -public class DogsAndRobotMethodReferences { - public static void main(String[] args) { - CommunicateA.perform(new PerformingDogA(), - PerformingDogA::speak, PerformingDogA::sit); - CommunicateA.perform(new RobotA(), - RobotA::speak, RobotA::sit); - CommunicateA.perform(new Mime(), - Mime::walkAgainstTheWind, - Mime::pushInvisibleWalls); - } -} -/* Output: -Woof! -Sitting -Click! -Clank! -*/ diff --git a/code/generics/DogsAndRobots.cpp b/code/generics/DogsAndRobots.cpp deleted file mode 100644 index 81ced5d9..00000000 --- a/code/generics/DogsAndRobots.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// generics/DogsAndRobots.cpp -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -#include -using namespace std; - -class Dog { -public: - void speak() { cout << "Arf!" << endl; } - void sit() { cout << "Sitting" << endl; } - void reproduce() {} -}; - -class Robot { -public: - void speak() { cout << "Click!" << endl; } - void sit() { cout << "Clank!" << endl; } - void oilChange() {} -}; - -template void perform(T anything) { - anything.speak(); - anything.sit(); -} - -int main() { - Dog d; - Robot r; - perform(d); - perform(r); -} -/* Output: -Arf! -Sitting -Click! -Clank! -*/ diff --git a/code/generics/DogsAndRobots.java b/code/generics/DogsAndRobots.java deleted file mode 100644 index b6151122..00000000 --- a/code/generics/DogsAndRobots.java +++ /dev/null @@ -1,41 +0,0 @@ -// generics/DogsAndRobots.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// No (direct) latent typing in Java -import typeinfo.pets.*; - -class PerformingDog extends Dog implements Performs { - @Override - public void speak() { System.out.println("Woof!"); } - @Override - public void sit() { System.out.println("Sitting"); } - public void reproduce() {} -} - -class Robot implements Performs { - public void speak() { System.out.println("Click!"); } - public void sit() { System.out.println("Clank!"); } - public void oilChange() {} -} - -class Communicate { - public static - void perform(T performer) { - performer.speak(); - performer.sit(); - } -} - -public class DogsAndRobots { - public static void main(String[] args) { - Communicate.perform(new PerformingDog()); - Communicate.perform(new Robot()); - } -} -/* Output: -Woof! -Sitting -Click! -Clank! -*/ diff --git a/code/generics/DogsAndRobots.py b/code/generics/DogsAndRobots.py deleted file mode 100644 index c9ca6fef..00000000 --- a/code/generics/DogsAndRobots.py +++ /dev/null @@ -1,36 +0,0 @@ -# generics/DogsAndRobots.py -# (c)2020 MindView LLC: see Copyright.txt -# We make no guarantees that this code is fit for any purpose. -# Visit http://OnJava8.com for more book information. - -class Dog: - def speak(self): - print("Arf!") - def sit(self): - print("Sitting") - def reproduce(self): - pass - -class Robot: - def speak(self): - print("Click!") - def sit(self): - print("Clank!") - def oilChange(self): - pass - -def perform(anything): - anything.speak() - anything.sit() - -a = Dog() -b = Robot() -perform(a) -perform(b) - -output = """ -Arf! -Sitting -Click! -Clank! -""" diff --git a/code/generics/DynamicProxyMixin.java b/code/generics/DynamicProxyMixin.java deleted file mode 100644 index 38431e31..00000000 --- a/code/generics/DynamicProxyMixin.java +++ /dev/null @@ -1,66 +0,0 @@ -// generics/DynamicProxyMixin.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.reflect.*; -import java.util.*; -import onjava.*; -import static onjava.Tuple.*; - -class MixinProxy implements InvocationHandler { - Map delegatesByMethod; - @SuppressWarnings("unchecked") - MixinProxy(Tuple2>... pairs) { - delegatesByMethod = new HashMap<>(); - for(Tuple2> pair : pairs) { - for(Method method : pair.a2.getMethods()) { - String methodName = method.getName(); - // The first interface in the map - // implements the method. - if(!delegatesByMethod.containsKey(methodName)) - delegatesByMethod.put(methodName, pair.a1); - } - } - } - @Override - public Object invoke(Object proxy, Method method, - Object[] args) throws Throwable { - String methodName = method.getName(); - Object delegate = delegatesByMethod.get(methodName); - return method.invoke(delegate, args); - } - @SuppressWarnings("unchecked") - public static Object newInstance(Tuple2... pairs) { - Class[] interfaces = new Class[pairs.length]; - for(int i = 0; i < pairs.length; i++) { - interfaces[i] = (Class)pairs[i].a2; - } - ClassLoader cl = - pairs[0].a1.getClass().getClassLoader(); - return Proxy.newProxyInstance( - cl, interfaces, new MixinProxy(pairs)); - } -} - -public class DynamicProxyMixin { - public static void main(String[] args) { - @SuppressWarnings("unchecked") - Object mixin = MixinProxy.newInstance( - tuple(new BasicImp(), Basic.class), - tuple(new TimeStampedImp(), TimeStamped.class), - tuple(new SerialNumberedImp(), - SerialNumbered.class)); - Basic b = (Basic)mixin; - TimeStamped t = (TimeStamped)mixin; - SerialNumbered s = (SerialNumbered)mixin; - b.set("Hello"); - System.out.println(b.get()); - System.out.println(t.getStamp()); - System.out.println(s.getSerialNumber()); - } -} -/* Output: -Hello -1494331653339 -1 -*/ diff --git a/code/generics/EpicBattle.java b/code/generics/EpicBattle.java deleted file mode 100644 index 908a3343..00000000 --- a/code/generics/EpicBattle.java +++ /dev/null @@ -1,74 +0,0 @@ -// generics/EpicBattle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Bounds in Java generics -import java.util.*; - -interface SuperPower {} - -interface XRayVision extends SuperPower { - void seeThroughWalls(); -} - -interface SuperHearing extends SuperPower { - void hearSubtleNoises(); -} - -interface SuperSmell extends SuperPower { - void trackBySmell(); -} - -class SuperHero { - POWER power; - SuperHero(POWER power) { this.power = power; } - POWER getPower() { return power; } -} - -class SuperSleuth -extends SuperHero { - SuperSleuth(POWER power) { super(power); } - void see() { power.seeThroughWalls(); } -} - -class -CanineHero -extends SuperHero { - CanineHero(POWER power) { super(power); } - void hear() { power.hearSubtleNoises(); } - void smell() { power.trackBySmell(); } -} - -class SuperHearSmell -implements SuperHearing, SuperSmell { - @Override - public void hearSubtleNoises() {} - @Override - public void trackBySmell() {} -} - -class DogPerson extends CanineHero { - DogPerson() { super(new SuperHearSmell()); } -} - -public class EpicBattle { - // Bounds in generic methods: - static - void useSuperHearing(SuperHero hero) { - hero.getPower().hearSubtleNoises(); - } - static - void superFind(SuperHero hero) { - hero.getPower().hearSubtleNoises(); - hero.getPower().trackBySmell(); - } - public static void main(String[] args) { - DogPerson dogPerson = new DogPerson(); - useSuperHearing(dogPerson); - superFind(dogPerson); - // You can do this: - List audioPeople; - // But you can't do this: - // List dogPs; - } -} diff --git a/code/generics/Erased.java b/code/generics/Erased.java deleted file mode 100644 index 911839c3..00000000 --- a/code/generics/Erased.java +++ /dev/null @@ -1,24 +0,0 @@ -// generics/Erased.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} - -public class Erased { - private final int SIZE = 100; - public void f(Object arg) { - - // error: illegal generic type for instanceof - if(arg instanceof T) {} - - // error: unexpected type - T var = new T(); - - // error: generic array creation - T[] array = new T[SIZE]; - - // warning: [unchecked] unchecked cast - T[] array = (T[])new Object[SIZE]; - - } -} diff --git a/code/generics/ErasedTypeEquivalence.java b/code/generics/ErasedTypeEquivalence.java deleted file mode 100644 index 6034b304..00000000 --- a/code/generics/ErasedTypeEquivalence.java +++ /dev/null @@ -1,16 +0,0 @@ -// generics/ErasedTypeEquivalence.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ErasedTypeEquivalence { - public static void main(String[] args) { - Class c1 = new ArrayList().getClass(); - Class c2 = new ArrayList().getClass(); - System.out.println(c1 == c2); - } -} -/* Output: -true -*/ diff --git a/code/generics/ErasureAndInheritance.java b/code/generics/ErasureAndInheritance.java deleted file mode 100644 index 44a07b62..00000000 --- a/code/generics/ErasureAndInheritance.java +++ /dev/null @@ -1,28 +0,0 @@ -// generics/ErasureAndInheritance.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class GenericBase { - private T element; - public void set(T arg) { element = arg; } - public T get() { return element; } -} - -class Derived1 extends GenericBase {} - -class Derived2 extends GenericBase {} // No warning - -// class Derived3 extends GenericBase {} -// Strange error: -// unexpected type -// required: class or interface without bounds - -public class ErasureAndInheritance { - @SuppressWarnings("unchecked") - public static void main(String[] args) { - Derived2 d2 = new Derived2(); - Object obj = d2.get(); - d2.set(obj); // Warning here! - } -} diff --git a/code/generics/FactoryConstraint.java b/code/generics/FactoryConstraint.java deleted file mode 100644 index f0651073..00000000 --- a/code/generics/FactoryConstraint.java +++ /dev/null @@ -1,62 +0,0 @@ -// generics/FactoryConstraint.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import onjava.*; - -class IntegerFactory implements Supplier { - private int i = 0; - @Override - public Integer get() { - return ++i; - } -} - -class Widget { - private int id; - Widget(int n) { id = n; } - @Override - public String toString() { - return "Widget " + id; - } - public static - class Factory implements Supplier { - private int i = 0; - @Override - public Widget get() { return new Widget(++i); } - } -} - -class Fudge { - private static int count = 1; - private int n = count++; - @Override - public String toString() { return "Fudge " + n; } -} - -class Foo2 { - private List x = new ArrayList<>(); - Foo2(Supplier factory) { - Suppliers.fill(x, factory, 5); - } - @Override - public String toString() { return x.toString(); } -} - -public class FactoryConstraint { - public static void main(String[] args) { - System.out.println( - new Foo2<>(new IntegerFactory())); - System.out.println( - new Foo2<>(new Widget.Factory())); - System.out.println( - new Foo2<>(Fudge::new)); - } -} -/* Output: -[1, 2, 3, 4, 5] -[Widget 1, Widget 2, Widget 3, Widget 4, Widget 5] -[Fudge 1, Fudge 2, Fudge 3, Fudge 4, Fudge 5] -*/ diff --git a/code/generics/Fibonacci.java b/code/generics/Fibonacci.java deleted file mode 100644 index 11540061..00000000 --- a/code/generics/Fibonacci.java +++ /dev/null @@ -1,27 +0,0 @@ -// generics/Fibonacci.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Generate a Fibonacci sequence -import java.util.function.*; -import java.util.stream.*; - -public class Fibonacci implements Supplier { - private int count = 0; - @Override - public Integer get() { return fib(count++); } - private int fib(int n) { - if(n < 2) return 1; - return fib(n-2) + fib(n-1); - } - public static void main(String[] args) { - Stream.generate(new Fibonacci()) - .limit(18) - .map(n -> n + " ") - .forEach(System.out::print); - } -} -/* Output: -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 -2584 -*/ diff --git a/code/generics/FilledList.java b/code/generics/FilledList.java deleted file mode 100644 index e24423ce..00000000 --- a/code/generics/FilledList.java +++ /dev/null @@ -1,28 +0,0 @@ -// generics/FilledList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import onjava.*; - -public class FilledList extends ArrayList { - FilledList(Supplier gen, int size) { - Suppliers.fill(this, gen, size); - } - public FilledList(T t, int size) { - for(int i = 0; i < size; i++) - this.add(t); - } - public static void main(String[] args) { - List list = new FilledList<>("Hello", 4); - System.out.println(list); - // Supplier version: - List ilist = new FilledList<>(() -> 47, 4); - System.out.println(ilist); - } -} -/* Output: -[Hello, Hello, Hello, Hello] -[47, 47, 47, 47] -*/ diff --git a/code/generics/GenericArray.java b/code/generics/GenericArray.java deleted file mode 100644 index f0ffba3d..00000000 --- a/code/generics/GenericArray.java +++ /dev/null @@ -1,32 +0,0 @@ -// generics/GenericArray.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class GenericArray { - private T[] array; - @SuppressWarnings("unchecked") - public GenericArray(int sz) { - array = (T[])new Object[sz]; - } - public void put(int index, T item) { - array[index] = item; - } - public T get(int index) { return array[index]; } - // Method that exposes the underlying representation: - public T[] rep() { return array; } - public static void main(String[] args) { - GenericArray gai = new GenericArray<>(10); - try { - Integer[] ia = gai.rep(); - } catch(ClassCastException e) { - System.out.println(e.getMessage()); - } - // This is OK: - Object[] oa = gai.rep(); - } -} -/* Output: -[Ljava.lang.Object; cannot be cast to -[Ljava.lang.Integer; -*/ diff --git a/code/generics/GenericArray2.java b/code/generics/GenericArray2.java deleted file mode 100644 index 7ef4179e..00000000 --- a/code/generics/GenericArray2.java +++ /dev/null @@ -1,39 +0,0 @@ -// generics/GenericArray2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class GenericArray2 { - private Object[] array; - public GenericArray2(int sz) { - array = new Object[sz]; - } - public void put(int index, T item) { - array[index] = item; - } - @SuppressWarnings("unchecked") - public T get(int index) { return (T)array[index]; } - @SuppressWarnings("unchecked") - public T[] rep() { - return (T[])array; // Unchecked cast - } - public static void main(String[] args) { - GenericArray2 gai = - new GenericArray2<>(10); - for(int i = 0; i < 10; i ++) - gai.put(i, i); - for(int i = 0; i < 10; i ++) - System.out.print(gai.get(i) + " "); - System.out.println(); - try { - Integer[] ia = gai.rep(); - } catch(Exception e) { - System.out.println(e); - } - } -} -/* Output: -0 1 2 3 4 5 6 7 8 9 -java.lang.ClassCastException: [Ljava.lang.Object; -cannot be cast to [Ljava.lang.Integer; -*/ diff --git a/code/generics/GenericArrayWithTypeToken.java b/code/generics/GenericArrayWithTypeToken.java deleted file mode 100644 index 6ea36a76..00000000 --- a/code/generics/GenericArrayWithTypeToken.java +++ /dev/null @@ -1,27 +0,0 @@ -// generics/GenericArrayWithTypeToken.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.reflect.*; - -public class GenericArrayWithTypeToken { - private T[] array; - @SuppressWarnings("unchecked") - public - GenericArrayWithTypeToken(Class type, int sz) { - array = (T[])Array.newInstance(type, sz); - } - public void put(int index, T item) { - array[index] = item; - } - public T get(int index) { return array[index]; } - // Expose the underlying representation: - public T[] rep() { return array; } - public static void main(String[] args) { - GenericArrayWithTypeToken gai = - new GenericArrayWithTypeToken<>( - Integer.class, 10); - // This now works: - Integer[] ia = gai.rep(); - } -} diff --git a/code/generics/GenericCast.java b/code/generics/GenericCast.java deleted file mode 100644 index c3f82dac..00000000 --- a/code/generics/GenericCast.java +++ /dev/null @@ -1,47 +0,0 @@ -// generics/GenericCast.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -class FixedSizeStack { - private final int size; - private Object[] storage; - private int index = 0; - FixedSizeStack(int size) { - this.size = size; - storage = new Object[size]; - } - public void push(T item) { - if(index < size) - storage[index++] = item; - } - @SuppressWarnings("unchecked") - public T pop() { - return index == 0 ? null : (T)storage[--index]; - } - @SuppressWarnings("unchecked") - Stream stream() { - return (Stream)Arrays.stream(storage); - } -} - -public class GenericCast { - static String[] letters = - "ABCDEFGHIJKLMNOPQRS".split(""); - public static void main(String[] args) { - FixedSizeStack strings = - new FixedSizeStack<>(letters.length); - Arrays.stream("ABCDEFGHIJKLMNOPQRS".split("")) - .forEach(strings::push); - System.out.println(strings.pop()); - strings.stream() - .map(s -> s + " ") - .forEach(System.out::print); - } -} -/* Output: -S -A B C D E F G H I J K L M N O P Q R S -*/ diff --git a/code/generics/GenericHolder.java b/code/generics/GenericHolder.java deleted file mode 100644 index 6d998a1c..00000000 --- a/code/generics/GenericHolder.java +++ /dev/null @@ -1,19 +0,0 @@ -// generics/GenericHolder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class GenericHolder { - private T a; - public GenericHolder() {} - public void set(T a) { this.a = a; } - public T get() { return a; } - public static void main(String[] args) { - GenericHolder h3 = - new GenericHolder(); - h3.set(new Automobile()); // type checked - Automobile a = h3.get(); // No cast needed - //- h3.set("Not an Automobile"); // Error - //- h3.set(1); // Error - } -} diff --git a/code/generics/GenericHolder2.java b/code/generics/GenericHolder2.java deleted file mode 100644 index 9747f49b..00000000 --- a/code/generics/GenericHolder2.java +++ /dev/null @@ -1,16 +0,0 @@ -// generics/GenericHolder2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class GenericHolder2 { - private T obj; - public void set(T obj) { this.obj = obj; } - public T get() { return obj; } - public static void main(String[] args) { - GenericHolder2 holder = - new GenericHolder2<>(); - holder.set("Item"); - String s = holder.get(); - } -} diff --git a/code/generics/GenericMethods.java b/code/generics/GenericMethods.java deleted file mode 100644 index 66f40e72..00000000 --- a/code/generics/GenericMethods.java +++ /dev/null @@ -1,27 +0,0 @@ -// generics/GenericMethods.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class GenericMethods { - public void f(T x) { - System.out.println(x.getClass().getName()); - } - public static void main(String[] args) { - GenericMethods gm = new GenericMethods(); - gm.f(""); - gm.f(1); - gm.f(1.0); - gm.f(1.0F); - gm.f('c'); - gm.f(gm); - } -} -/* Output: -java.lang.String -java.lang.Integer -java.lang.Double -java.lang.Float -java.lang.Character -GenericMethods -*/ diff --git a/code/generics/GenericReading.java b/code/generics/GenericReading.java deleted file mode 100644 index 5709c7a9..00000000 --- a/code/generics/GenericReading.java +++ /dev/null @@ -1,46 +0,0 @@ -// generics/GenericReading.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class GenericReading { - static List apples = - Arrays.asList(new Apple()); - static List fruit = Arrays.asList(new Fruit()); - static T readExact(List list) { - return list.get(0); - } - // A static method adapts to each call: - static void f1() { - Apple a = readExact(apples); - Fruit f = readExact(fruit); - f = readExact(apples); - } - // A class type is established - // when the class is instantiated: - static class Reader { - T readExact(List list) { return list.get(0); } - } - static void f2() { - Reader fruitReader = new Reader<>(); - Fruit f = fruitReader.readExact(fruit); - //- Fruit a = fruitReader.readExact(apples); - // error: incompatible types: List - // cannot be converted to List - } - static class CovariantReader { - T readCovariant(List list) { - return list.get(0); - } - } - static void f3() { - CovariantReader fruitReader = - new CovariantReader<>(); - Fruit f = fruitReader.readCovariant(fruit); - Fruit a = fruitReader.readCovariant(apples); - } - public static void main(String[] args) { - f1(); f2(); f3(); - } -} diff --git a/code/generics/GenericVarargs.java b/code/generics/GenericVarargs.java deleted file mode 100644 index 3a6e348c..00000000 --- a/code/generics/GenericVarargs.java +++ /dev/null @@ -1,30 +0,0 @@ -// generics/GenericVarargs.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class GenericVarargs { - @SafeVarargs - public static List makeList(T... args) { - List result = new ArrayList<>(); - for(T item : args) - result.add(item); - return result; - } - public static void main(String[] args) { - List ls = makeList("A"); - System.out.println(ls); - ls = makeList("A", "B", "C"); - System.out.println(ls); - ls = makeList( - "ABCDEFFHIJKLMNOPQRSTUVWXYZ".split("")); - System.out.println(ls); - } -} -/* Output: -[A] -[A, B, C] -[A, B, C, D, E, F, F, H, I, J, K, L, M, N, O, P, Q, R, -S, T, U, V, W, X, Y, Z] -*/ diff --git a/code/generics/GenericsAndCovariance.java b/code/generics/GenericsAndCovariance.java deleted file mode 100644 index f16b837b..00000000 --- a/code/generics/GenericsAndCovariance.java +++ /dev/null @@ -1,19 +0,0 @@ -// generics/GenericsAndCovariance.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class GenericsAndCovariance { - public static void main(String[] args) { - // Wildcards allow covariance: - List flist = new ArrayList<>(); - // Compile Error: can't add any type of object: - // flist.add(new Apple()); - // flist.add(new Fruit()); - // flist.add(new Object()); - flist.add(null); // Legal but uninteresting - // We know it returns at least Fruit: - Fruit f = flist.get(0); - } -} diff --git a/code/generics/GenericsAndReturnTypes.java b/code/generics/GenericsAndReturnTypes.java deleted file mode 100644 index de661864..00000000 --- a/code/generics/GenericsAndReturnTypes.java +++ /dev/null @@ -1,17 +0,0 @@ -// generics/GenericsAndReturnTypes.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface GenericGetter> { - T get(); -} - -interface Getter extends GenericGetter {} - -public class GenericsAndReturnTypes { - void test(Getter g) { - Getter result = g.get(); - GenericGetter gg = g.get(); // Also the base type - } -} diff --git a/code/generics/HasF.java b/code/generics/HasF.java deleted file mode 100644 index f967386e..00000000 --- a/code/generics/HasF.java +++ /dev/null @@ -1,10 +0,0 @@ -// generics/HasF.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class HasF { - public void f() { - System.out.println("HasF.f()"); - } -} diff --git a/code/generics/HijackedInterface.java b/code/generics/HijackedInterface.java deleted file mode 100644 index 868e1d46..00000000 --- a/code/generics/HijackedInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -// generics/HijackedInterface.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} - -class Cat - extends ComparablePet implements Comparable{ - // error: Comparable cannot be inherited with - // different arguments: and - // class Cat - // ^ - // 1 error - - public int compareTo(Cat arg) { return 0; } -} diff --git a/code/generics/Holder.java b/code/generics/Holder.java deleted file mode 100644 index e4301dc6..00000000 --- a/code/generics/Holder.java +++ /dev/null @@ -1,42 +0,0 @@ -// generics/Holder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.Objects; - -public class Holder { - private T value; - public Holder() {} - public Holder(T val) { value = val; } - public void set(T val) { value = val; } - public T get() { return value; } - @Override - public boolean equals(Object o) { - return o instanceof Holder && - Objects.equals(value, ((Holder)o).value); - } - @Override - public int hashCode() { - return Objects.hashCode(value); - } - public static void main(String[] args) { - Holder apple = new Holder<>(new Apple()); - Apple d = apple.get(); - apple.set(d); - // Holder Fruit = apple; // Cannot upcast - Holder fruit = apple; // OK - Fruit p = fruit.get(); - d = (Apple)fruit.get(); // Returns 'Object' - try { - Orange c = (Orange)fruit.get(); // No warning - } catch(Exception e) { System.out.println(e); } - // fruit.set(new Apple()); // Cannot call set() - // fruit.set(new Fruit()); // Cannot call set() - System.out.println(fruit.equals(d)); // OK - } -} -/* Output: -java.lang.ClassCastException: Apple cannot be cast to -Orange -false -*/ diff --git a/code/generics/Holder1.java b/code/generics/Holder1.java deleted file mode 100644 index 0c222cb5..00000000 --- a/code/generics/Holder1.java +++ /dev/null @@ -1,12 +0,0 @@ -// generics/Holder1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Automobile {} - -public class Holder1 { - private Automobile a; - public Holder1(Automobile a) { this.a = a; } - Automobile get() { return a; } -} diff --git a/code/generics/InheritBounds.java b/code/generics/InheritBounds.java deleted file mode 100644 index fddd2543..00000000 --- a/code/generics/InheritBounds.java +++ /dev/null @@ -1,40 +0,0 @@ -// generics/InheritBounds.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class HoldItem { - T item; - HoldItem(T item) { this.item = item; } - T getItem() { return item; } -} - -class WithColor2 -extends HoldItem { - WithColor2(T item) { super(item); } - java.awt.Color color() { return item.getColor(); } -} - -class WithColorCoord2 -extends WithColor2 { - WithColorCoord2(T item) { super(item); } - int getX() { return item.x; } - int getY() { return item.y; } - int getZ() { return item.z; } -} - -class Solid2 -extends WithColorCoord2 { - Solid2(T item) { super(item); } - int weight() { return item.weight(); } -} - -public class InheritBounds { - public static void main(String[] args) { - Solid2 solid2 = - new Solid2<>(new Bounded()); - solid2.color(); - solid2.getY(); - solid2.weight(); - } -} diff --git a/code/generics/InstantiateGenericType.cpp b/code/generics/InstantiateGenericType.cpp deleted file mode 100644 index 1799d05b..00000000 --- a/code/generics/InstantiateGenericType.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// generics/InstantiateGenericType.cpp -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// C++, not Java! - -template class Foo { - T x; // Create a field of type T - T* y; // Pointer to T -public: - // Initialize the pointer: - Foo() { y = new T(); } -}; - -class Bar {}; - -int main() { - Foo fb; - Foo fi; // ... and it works with primitives -} diff --git a/code/generics/InstantiateGenericType.java b/code/generics/InstantiateGenericType.java deleted file mode 100644 index 9424c9a1..00000000 --- a/code/generics/InstantiateGenericType.java +++ /dev/null @@ -1,46 +0,0 @@ -// generics/InstantiateGenericType.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; -import java.lang.reflect.InvocationTargetException; - -class ClassAsFactory implements Supplier { - Class kind; - ClassAsFactory(Class kind) { - this.kind = kind; - } - @SuppressWarnings("deprecation") - @Override - public T get() { - try { - return kind.newInstance(); - } catch(Exception e) { - throw new RuntimeException(e); - } - } -} - -class Employee { - @Override - public String toString() { return "Employee"; } -} - -public class InstantiateGenericType { - public static void main(String[] args) { - ClassAsFactory fe = - new ClassAsFactory<>(Employee.class); - System.out.println(fe.get()); - ClassAsFactory fi = - new ClassAsFactory<>(Integer.class); - try { - System.out.println(fi.get()); - } catch(Exception e) { - System.out.println(e.getMessage()); - } - } -} -/* Output: -Employee -java.lang.InstantiationException: java.lang.Integer -*/ diff --git a/code/generics/IterableFibonacci.java b/code/generics/IterableFibonacci.java deleted file mode 100644 index b5ccf285..00000000 --- a/code/generics/IterableFibonacci.java +++ /dev/null @@ -1,36 +0,0 @@ -// generics/IterableFibonacci.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Adapt the Fibonacci class to make it Iterable -import java.util.*; - -public class IterableFibonacci -extends Fibonacci implements Iterable { - private int n; - public IterableFibonacci(int count) { n = count; } - @Override - public Iterator iterator() { - return new Iterator() { - @Override - public boolean hasNext() { return n > 0; } - @Override - public Integer next() { - n--; - return IterableFibonacci.this.get(); - } - @Override - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - }; - } - public static void main(String[] args) { - for(int i : new IterableFibonacci(18)) - System.out.print(i + " "); - } -} -/* Output: -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 -2584 -*/ diff --git a/code/generics/LatentReflection.java b/code/generics/LatentReflection.java deleted file mode 100644 index 0e9511a3..00000000 --- a/code/generics/LatentReflection.java +++ /dev/null @@ -1,65 +0,0 @@ -// generics/LatentReflection.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using reflection for latent typing -import java.lang.reflect.*; - -// Does not implement Performs: -class Mime { - public void walkAgainstTheWind() {} - public void sit() { - System.out.println("Pretending to sit"); - } - public void pushInvisibleWalls() {} - @Override - public String toString() { return "Mime"; } -} - -// Does not implement Performs: -class SmartDog { - public void speak() { System.out.println("Woof!"); } - public void sit() { System.out.println("Sitting"); } - public void reproduce() {} -} - -class CommunicateReflectively { - public static void perform(Object speaker) { - Class spkr = speaker.getClass(); - try { - try { - Method speak = spkr.getMethod("speak"); - speak.invoke(speaker); - } catch(NoSuchMethodException e) { - System.out.println(speaker + " cannot speak"); - } - try { - Method sit = spkr.getMethod("sit"); - sit.invoke(speaker); - } catch(NoSuchMethodException e) { - System.out.println(speaker + " cannot sit"); - } - } catch(SecurityException | - IllegalAccessException | - IllegalArgumentException | - InvocationTargetException e) { - throw new RuntimeException(speaker.toString(), e); - } - } -} - -public class LatentReflection { - public static void main(String[] args) { - CommunicateReflectively.perform(new SmartDog()); - CommunicateReflectively.perform(new Robot()); - CommunicateReflectively.perform(new Mime()); - } -} -/* Output: -Woof! -Sitting -Click! -Clank! -Mime cannot speak -Pretending to sit -*/ diff --git a/code/generics/LinkedStack.java b/code/generics/LinkedStack.java deleted file mode 100644 index 5142bcc7..00000000 --- a/code/generics/LinkedStack.java +++ /dev/null @@ -1,43 +0,0 @@ -// generics/LinkedStack.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A stack implemented with an internal linked structure - -public class LinkedStack { - private static class Node { - U item; - Node next; - Node() { item = null; next = null; } - Node(U item, Node next) { - this.item = item; - this.next = next; - } - boolean end() { - return item == null && next == null; - } - } - private Node top = new Node<>(); // End sentinel - public void push(T item) { - top = new Node<>(item, top); - } - public T pop() { - T result = top.item; - if(!top.end()) - top = top.next; - return result; - } - public static void main(String[] args) { - LinkedStack lss = new LinkedStack<>(); - for(String s : "Phasers on stun!".split(" ")) - lss.push(s); - String s; - while((s = lss.pop()) != null) - System.out.println(s); - } -} -/* Output: -stun! -on -Phasers -*/ diff --git a/code/generics/ListMaker.java b/code/generics/ListMaker.java deleted file mode 100644 index 582cbaea..00000000 --- a/code/generics/ListMaker.java +++ /dev/null @@ -1,13 +0,0 @@ -// generics/ListMaker.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ListMaker { - List create() { return new ArrayList<>(); } - public static void main(String[] args) { - ListMaker stringMaker = new ListMaker<>(); - List stringList = stringMaker.create(); - } -} diff --git a/code/generics/ListOfGenerics.java b/code/generics/ListOfGenerics.java deleted file mode 100644 index 10a48031..00000000 --- a/code/generics/ListOfGenerics.java +++ /dev/null @@ -1,11 +0,0 @@ -// generics/ListOfGenerics.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ListOfGenerics { - private List array = new ArrayList<>(); - public void add(T item) { array.add(item); } - public T get(int index) { return array.get(index); } -} diff --git a/code/generics/ListOfInt.java b/code/generics/ListOfInt.java deleted file mode 100644 index f8ac8e11..00000000 --- a/code/generics/ListOfInt.java +++ /dev/null @@ -1,20 +0,0 @@ -// generics/ListOfInt.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Autoboxing compensates for the inability -// to use primitives in generics -import java.util.*; -import java.util.stream.*; - -public class ListOfInt { - public static void main(String[] args) { - List li = IntStream.range(38, 48) - .boxed() // Converts ints to Integers - .collect(Collectors.toList()); - System.out.println(li); - } -} -/* Output: -[38, 39, 40, 41, 42, 43, 44, 45, 46, 47] -*/ diff --git a/code/generics/LostInformation.java b/code/generics/LostInformation.java deleted file mode 100644 index e27430d2..00000000 --- a/code/generics/LostInformation.java +++ /dev/null @@ -1,33 +0,0 @@ -// generics/LostInformation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class Frob {} -class Fnorkle {} -class Quark {} -class Particle {} - -public class LostInformation { - public static void main(String[] args) { - List list = new ArrayList<>(); - Map map = new HashMap<>(); - Quark quark = new Quark<>(); - Particle p = new Particle<>(); - System.out.println(Arrays.toString( - list.getClass().getTypeParameters())); - System.out.println(Arrays.toString( - map.getClass().getTypeParameters())); - System.out.println(Arrays.toString( - quark.getClass().getTypeParameters())); - System.out.println(Arrays.toString( - p.getClass().getTypeParameters())); - } -} -/* Output: -[E] -[K, V] -[Q] -[POSITION, MOMENTUM] -*/ diff --git a/code/generics/Manipulation.java b/code/generics/Manipulation.java deleted file mode 100644 index f365cf19..00000000 --- a/code/generics/Manipulation.java +++ /dev/null @@ -1,21 +0,0 @@ -// generics/Manipulation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} - -class Manipulator { - private T obj; - Manipulator(T x) { obj = x; } - // Error: cannot find symbol: method f(): - public void manipulate() { obj.f(); } -} - -public class Manipulation { - public static void main(String[] args) { - HasF hf = new HasF(); - Manipulator manipulator = - new Manipulator<>(hf); - manipulator.manipulate(); - } -} diff --git a/code/generics/Manipulator2.java b/code/generics/Manipulator2.java deleted file mode 100644 index 7c7c648b..00000000 --- a/code/generics/Manipulator2.java +++ /dev/null @@ -1,10 +0,0 @@ -// generics/Manipulator2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Manipulator2 { - private T obj; - Manipulator2(T x) { obj = x; } - public void manipulate() { obj.f(); } -} diff --git a/code/generics/Manipulator3.java b/code/generics/Manipulator3.java deleted file mode 100644 index 2201d474..00000000 --- a/code/generics/Manipulator3.java +++ /dev/null @@ -1,10 +0,0 @@ -// generics/Manipulator3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Manipulator3 { - private HasF obj; - Manipulator3(HasF x) { obj = x; } - public void manipulate() { obj.f(); } -} diff --git a/code/generics/Mixins.cpp b/code/generics/Mixins.cpp deleted file mode 100644 index 89949d46..00000000 --- a/code/generics/Mixins.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// generics/Mixins.cpp -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -#include -#include -#include -using namespace std; - -template class TimeStamped : public T { - long timeStamp; -public: - TimeStamped() { timeStamp = time(0); } - long getStamp() { return timeStamp; } -}; - -template class SerialNumbered : public T { - long serialNumber; - static long counter; -public: - SerialNumbered() { serialNumber = counter++; } - long getSerialNumber() { return serialNumber; } -}; - -// Define and initialize the static storage: -template long SerialNumbered::counter = 1; - -class Basic { - string value; -public: - void set(string val) { value = val; } - string get() { return value; } -}; - -int main() { - TimeStamped> mixin1, mixin2; - mixin1.set("test string 1"); - mixin2.set("test string 2"); - cout << mixin1.get() << " " << mixin1.getStamp() << - " " << mixin1.getSerialNumber() << endl; - cout << mixin2.get() << " " << mixin2.getStamp() << - " " << mixin2.getSerialNumber() << endl; -} -/* Output: -test string 1 1452987605 1 -test string 2 1452987605 2 -*/ diff --git a/code/generics/Mixins.java b/code/generics/Mixins.java deleted file mode 100644 index af58b81e..00000000 --- a/code/generics/Mixins.java +++ /dev/null @@ -1,71 +0,0 @@ -// generics/Mixins.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -interface TimeStamped { long getStamp(); } - -class TimeStampedImp implements TimeStamped { - private final long timeStamp; - TimeStampedImp() { - timeStamp = new Date().getTime(); - } - @Override - public long getStamp() { return timeStamp; } -} - -interface SerialNumbered { long getSerialNumber(); } - -class SerialNumberedImp implements SerialNumbered { - private static long counter = 1; - private final long serialNumber = counter++; - @Override - public long getSerialNumber() { return serialNumber; } -} - -interface Basic { - void set(String val); - String get(); -} - -class BasicImp implements Basic { - private String value; - @Override - public void set(String val) { value = val; } - @Override - public String get() { return value; } -} - -class Mixin extends BasicImp -implements TimeStamped, SerialNumbered { - private TimeStamped timeStamp = new TimeStampedImp(); - private SerialNumbered serialNumber = - new SerialNumberedImp(); - @Override - public long getStamp() { - return timeStamp.getStamp(); - } - @Override - public long getSerialNumber() { - return serialNumber.getSerialNumber(); - } -} - -public class Mixins { - public static void main(String[] args) { - Mixin mixin1 = new Mixin(), mixin2 = new Mixin(); - mixin1.set("test string 1"); - mixin2.set("test string 2"); - System.out.println(mixin1.get() + " " + - mixin1.getStamp() + " " + - mixin1.getSerialNumber()); - System.out.println(mixin2.get() + " " + - mixin2.getStamp() + " " + - mixin2.getSerialNumber()); - } -} -/* Output: -test string 1 1494331663026 1 -test string 2 1494331663027 2 -*/ diff --git a/code/generics/MultipleInterfaceVariants.java b/code/generics/MultipleInterfaceVariants.java deleted file mode 100644 index 70a535a2..00000000 --- a/code/generics/MultipleInterfaceVariants.java +++ /dev/null @@ -1,13 +0,0 @@ -// generics/MultipleInterfaceVariants.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -package generics; - -interface Payable {} - -class Employee implements Payable {} - -class Hourly extends Employee -implements Payable {} diff --git a/code/generics/NeedCasting.java b/code/generics/NeedCasting.java deleted file mode 100644 index 8801f5d8..00000000 --- a/code/generics/NeedCasting.java +++ /dev/null @@ -1,15 +0,0 @@ -// generics/NeedCasting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.util.*; - -public class NeedCasting { - @SuppressWarnings("unchecked") - public void f(String[] args) throws Exception { - ObjectInputStream in = new ObjectInputStream( - new FileInputStream(args[0])); - List shapes = (List)in.readObject(); - } -} diff --git a/code/generics/NonCovariantGenerics.java b/code/generics/NonCovariantGenerics.java deleted file mode 100644 index c219a0d3..00000000 --- a/code/generics/NonCovariantGenerics.java +++ /dev/null @@ -1,11 +0,0 @@ -// generics/NonCovariantGenerics.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -import java.util.*; - -public class NonCovariantGenerics { - // Compile Error: incompatible types: - List flist = new ArrayList(); -} diff --git a/code/generics/NotSelfBounded.java b/code/generics/NotSelfBounded.java deleted file mode 100644 index 76aa593c..00000000 --- a/code/generics/NotSelfBounded.java +++ /dev/null @@ -1,24 +0,0 @@ -// generics/NotSelfBounded.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class NotSelfBounded { - T element; - NotSelfBounded set(T arg) { - element = arg; - return this; - } - T get() { return element; } -} - -class A2 extends NotSelfBounded {} -class B2 extends NotSelfBounded {} - -class C2 extends NotSelfBounded { - C2 setAndGet(C2 arg) { set(arg); return get(); } -} - -class D2 {} -// Now this is OK: -class E2 extends NotSelfBounded {} diff --git a/code/generics/ObjectHolder.java b/code/generics/ObjectHolder.java deleted file mode 100644 index f1dafd30..00000000 --- a/code/generics/ObjectHolder.java +++ /dev/null @@ -1,20 +0,0 @@ -// generics/ObjectHolder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ObjectHolder { - private Object a; - public ObjectHolder(Object a) { this.a = a; } - public void set(Object a) { this.a = a; } - public Object get() { return a; } - public static void main(String[] args) { - ObjectHolder h2 = - new ObjectHolder(new Automobile()); - Automobile a = (Automobile)h2.get(); - h2.set("Not an Automobile"); - String s = (String)h2.get(); - h2.set(1); // Autoboxes to Integer - Integer x = (Integer)h2.get(); - } -} diff --git a/code/generics/OrdinaryArguments.java b/code/generics/OrdinaryArguments.java deleted file mode 100644 index 6e50550d..00000000 --- a/code/generics/OrdinaryArguments.java +++ /dev/null @@ -1,31 +0,0 @@ -// generics/OrdinaryArguments.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class OrdinarySetter { - void set(Base base) { - System.out.println("OrdinarySetter.set(Base)"); - } -} - -class DerivedSetter extends OrdinarySetter { - void set(Derived derived) { - System.out.println("DerivedSetter.set(Derived)"); - } -} - -public class OrdinaryArguments { - public static void main(String[] args) { - Base base = new Base(); - Derived derived = new Derived(); - DerivedSetter ds = new DerivedSetter(); - ds.set(derived); - // Compiles--overloaded, not overridden!: - ds.set(base); - } -} -/* Output: -DerivedSetter.set(Derived) -OrdinarySetter.set(Base) -*/ diff --git a/code/generics/Performs.java b/code/generics/Performs.java deleted file mode 100644 index ace09523..00000000 --- a/code/generics/Performs.java +++ /dev/null @@ -1,9 +0,0 @@ -// generics/Performs.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public interface Performs { - void speak(); - void sit(); -} diff --git a/code/generics/PlainGenericInheritance.java b/code/generics/PlainGenericInheritance.java deleted file mode 100644 index 93eb61c6..00000000 --- a/code/generics/PlainGenericInheritance.java +++ /dev/null @@ -1,30 +0,0 @@ -// generics/PlainGenericInheritance.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class GenericSetter { // Not self-bounded - void set(T arg) { - System.out.println("GenericSetter.set(Base)"); - } -} - -class DerivedGS extends GenericSetter { - void set(Derived derived) { - System.out.println("DerivedGS.set(Derived)"); - } -} - -public class PlainGenericInheritance { - public static void main(String[] args) { - Base base = new Base(); - Derived derived = new Derived(); - DerivedGS dgs = new DerivedGS(); - dgs.set(derived); - dgs.set(base); // Overloaded, not overridden! - } -} -/* Output: -DerivedGS.set(Derived) -GenericSetter.set(Base) -*/ diff --git a/code/generics/PrimitiveGenericTest.java b/code/generics/PrimitiveGenericTest.java deleted file mode 100644 index 79356437..00000000 --- a/code/generics/PrimitiveGenericTest.java +++ /dev/null @@ -1,42 +0,0 @@ -// generics/PrimitiveGenericTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; -import java.util.*; -import java.util.function.*; - -// Fill an array using a generator: -interface FillArray { - static T[] fill(T[] a, Supplier gen) { - Arrays.setAll(a, n -> gen.get()); - return a; - } - static int[] fill(int[] a, IntSupplier gen) { - Arrays.setAll(a, n -> gen.getAsInt()); - return a; - } - static long[] fill(long[] a, LongSupplier gen) { - Arrays.setAll(a, n -> gen.getAsLong()); - return a; - } - static double[] fill(double[] a, DoubleSupplier gen) { - Arrays.setAll(a, n -> gen.getAsDouble()); - return a; - } -} - -public class PrimitiveGenericTest { - public static void main(String[] args) { - String[] strings = FillArray.fill( - new String[5], new Rand.String(9)); - System.out.println(Arrays.toString(strings)); - int[] integers = FillArray.fill( - new int[9], new Rand.Pint()); - System.out.println(Arrays.toString(integers)); - } -} -/* Output: -[btpenpccu, xszgvgmei, nneeloztd, vewcippcy, gpoalkljl] -[635, 8737, 3941, 4720, 6177, 8479, 6656, 3768, 4948] -*/ diff --git a/code/generics/RandomList.java b/code/generics/RandomList.java deleted file mode 100644 index d4f198bc..00000000 --- a/code/generics/RandomList.java +++ /dev/null @@ -1,26 +0,0 @@ -// generics/RandomList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class RandomList extends ArrayList { - private Random rand = new Random(47); - public T select() { - return get(rand.nextInt(size())); - } - public static void main(String[] args) { - RandomList rs = new RandomList<>(); - Arrays.stream( - ("The quick brown fox jumped over " + - "the lazy brown dog").split(" ")) - .forEach(rs::add); - IntStream.range(0, 11).forEach(i -> - System.out.print(rs.select() + " ")); - } -} -/* Output: -brown over fox quick quick dog brown The brown lazy -brown -*/ diff --git a/code/generics/RestrictedComparablePets.java b/code/generics/RestrictedComparablePets.java deleted file mode 100644 index 16146d7b..00000000 --- a/code/generics/RestrictedComparablePets.java +++ /dev/null @@ -1,19 +0,0 @@ -// generics/RestrictedComparablePets.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Hamster extends ComparablePet -implements Comparable { - public int compareTo(ComparablePet arg) { - return 0; - } -} - -// Or just: - -class Gecko extends ComparablePet { - public int compareTo(ComparablePet arg) { - return 0; - } -} diff --git a/code/generics/ReturnGenericType.java b/code/generics/ReturnGenericType.java deleted file mode 100644 index bf46ae15..00000000 --- a/code/generics/ReturnGenericType.java +++ /dev/null @@ -1,10 +0,0 @@ -// generics/ReturnGenericType.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class ReturnGenericType { - private T obj; - ReturnGenericType(T x) { obj = x; } - public T get() { return obj; } -} diff --git a/code/generics/SelfBounding.java b/code/generics/SelfBounding.java deleted file mode 100644 index c8ecf0ff..00000000 --- a/code/generics/SelfBounding.java +++ /dev/null @@ -1,40 +0,0 @@ -// generics/SelfBounding.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class SelfBounded> { - T element; - SelfBounded set(T arg) { - element = arg; - return this; - } - T get() { return element; } -} - -class A extends SelfBounded {} -class B extends SelfBounded {} // Also OK - -class C extends SelfBounded { - C setAndGet(C arg) { set(arg); return get(); } -} - -class D {} -// Can't do this: -// class E extends SelfBounded {} -// Compile error: -// Type parameter D is not within its bound - -// Alas, you can do this, so you cannot force the idiom: -class F extends SelfBounded {} - -public class SelfBounding { - public static void main(String[] args) { - A a = new A(); - a.set(new A()); - a = a.set(new A()).get(); - a = a.get(); - C c = new C(); - c = c.setAndGet(new C()); - } -} diff --git a/code/generics/SelfBoundingAndCovariantArguments.java b/code/generics/SelfBoundingAndCovariantArguments.java deleted file mode 100644 index 34262b0e..00000000 --- a/code/generics/SelfBoundingAndCovariantArguments.java +++ /dev/null @@ -1,31 +0,0 @@ -// generics/SelfBoundingAndCovariantArguments.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface -SelfBoundSetter> { - void set(T arg); -} - -interface Setter extends SelfBoundSetter {} - -public class SelfBoundingAndCovariantArguments { - void - testA(Setter s1, Setter s2, SelfBoundSetter sbs) { - s1.set(s2); - //- s1.set(sbs); - // error: method set in interface SelfBoundSetter - // cannot be applied to given types; - // s1.set(sbs); - // ^ - // required: Setter - // found: SelfBoundSetter - // reason: argument mismatch; - // SelfBoundSetter cannot be converted to Setter - // where T is a type-variable: - // T extends SelfBoundSetter declared in - // interface SelfBoundSetter - // 1 error - } -} diff --git a/code/generics/SelfBoundingMethods.java b/code/generics/SelfBoundingMethods.java deleted file mode 100644 index e6cb7949..00000000 --- a/code/generics/SelfBoundingMethods.java +++ /dev/null @@ -1,13 +0,0 @@ -// generics/SelfBoundingMethods.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SelfBoundingMethods { - static > T f(T arg) { - return arg.set(arg).get(); - } - public static void main(String[] args) { - A a = f(new A()); - } -} diff --git a/code/generics/Shape.java b/code/generics/Shape.java deleted file mode 100644 index dd2458c2..00000000 --- a/code/generics/Shape.java +++ /dev/null @@ -1,19 +0,0 @@ -// generics/Shape.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Shape { - private static long counter = 0; - private final long id = counter++; - @Override - public String toString() { - return getClass().getSimpleName() + " " + id; - } - public void rotate() { - System.out.println(this + " rotate"); - } - public void resize(int newSize) { - System.out.println(this + " resize " + newSize); - } -} diff --git a/code/generics/SimpleDogsAndRobots.java b/code/generics/SimpleDogsAndRobots.java deleted file mode 100644 index b9cee77b..00000000 --- a/code/generics/SimpleDogsAndRobots.java +++ /dev/null @@ -1,25 +0,0 @@ -// generics/SimpleDogsAndRobots.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Removing the generic; code still works - -class CommunicateSimply { - static void perform(Performs performer) { - performer.speak(); - performer.sit(); - } -} - -public class SimpleDogsAndRobots { - public static void main(String[] args) { - CommunicateSimply.perform(new PerformingDog()); - CommunicateSimply.perform(new Robot()); - } -} -/* Output: -Woof! -Sitting -Click! -Clank! -*/ diff --git a/code/generics/SimpleHolder.java b/code/generics/SimpleHolder.java deleted file mode 100644 index a73af0ab..00000000 --- a/code/generics/SimpleHolder.java +++ /dev/null @@ -1,15 +0,0 @@ -// generics/SimpleHolder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SimpleHolder { - private Object obj; - public void set(Object obj) { this.obj = obj; } - public Object get() { return obj; } - public static void main(String[] args) { - SimpleHolder holder = new SimpleHolder(); - holder.set("Item"); - String s = (String)holder.get(); - } -} diff --git a/code/generics/SimpleQueue.java b/code/generics/SimpleQueue.java deleted file mode 100644 index 76fb4f3e..00000000 --- a/code/generics/SimpleQueue.java +++ /dev/null @@ -1,16 +0,0 @@ -// generics/SimpleQueue.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A different kind of Iterable collection -import java.util.*; - -public class SimpleQueue implements Iterable { - private LinkedList storage = new LinkedList<>(); - public void add(T t) { storage.offer(t); } - public T get() { return storage.poll(); } - @Override - public Iterator iterator() { - return storage.iterator(); - } -} diff --git a/code/generics/Square.java b/code/generics/Square.java deleted file mode 100644 index e3bcad93..00000000 --- a/code/generics/Square.java +++ /dev/null @@ -1,5 +0,0 @@ -// generics/Square.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class Square extends Shape {} diff --git a/code/generics/Store.java b/code/generics/Store.java deleted file mode 100644 index c165926a..00000000 --- a/code/generics/Store.java +++ /dev/null @@ -1,90 +0,0 @@ -// generics/Store.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Building a complex model using generic collections -import java.util.*; -import java.util.function.*; -import onjava.*; - -class Product { - private final int id; - private String description; - private double price; - Product(int idNumber, String descr, double price) { - id = idNumber; - description = descr; - this.price = price; - System.out.println(toString()); - } - @Override - public String toString() { - return id + ": " + description + - ", price: $" + price; - } - public void priceChange(double change) { - price += change; - } - public static Supplier generator = - new Supplier() { - private Random rand = new Random(47); - @Override - public Product get() { - return new Product(rand.nextInt(1000), "Test", - Math.round( - rand.nextDouble() * 1000.0) + 0.99); - } - }; -} - -class Shelf extends ArrayList { - Shelf(int nProducts) { - Suppliers.fill(this, Product.generator, nProducts); - } -} - -class Aisle extends ArrayList { - Aisle(int nShelves, int nProducts) { - for(int i = 0; i < nShelves; i++) - add(new Shelf(nProducts)); - } -} - -class CheckoutStand {} -class Office {} - -public class Store extends ArrayList { - private ArrayList checkouts = - new ArrayList<>(); - private Office office = new Office(); - public Store( - int nAisles, int nShelves, int nProducts) { - for(int i = 0; i < nAisles; i++) - add(new Aisle(nShelves, nProducts)); - } - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for(Aisle a : this) - for(Shelf s : a) - for(Product p : s) { - result.append(p); - result.append("\n"); - } - return result.toString(); - } - public static void main(String[] args) { - System.out.println(new Store(5, 4, 3)); - } -} -/* Output: (First 8 Lines) -258: Test, price: $400.99 -861: Test, price: $160.99 -868: Test, price: $417.99 -207: Test, price: $268.99 -551: Test, price: $114.99 -278: Test, price: $804.99 -520: Test, price: $554.99 -140: Test, price: $530.99 - ... -*/ diff --git a/code/generics/SuperTypeWildcards.java b/code/generics/SuperTypeWildcards.java deleted file mode 100644 index f8672a4f..00000000 --- a/code/generics/SuperTypeWildcards.java +++ /dev/null @@ -1,13 +0,0 @@ -// generics/SuperTypeWildcards.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SuperTypeWildcards { - static void writeTo(List apples) { - apples.add(new Apple()); - apples.add(new Jonathan()); - // apples.add(new Fruit()); // Error - } -} diff --git a/code/generics/Templates.cpp b/code/generics/Templates.cpp deleted file mode 100644 index ab2a3b64..00000000 --- a/code/generics/Templates.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// generics/Templates.cpp -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -#include -using namespace std; - -template class Manipulator { - T obj; -public: - Manipulator(T x) { obj = x; } - void manipulate() { obj.f(); } -}; - -class HasF { -public: - void f() { cout << "HasF::f()" << endl; } -}; - -int main() { - HasF hf; - Manipulator manipulator(hf); - manipulator.manipulate(); -} -/* Output: -HasF::f() -*/ diff --git a/code/generics/ThrowGenericException.java b/code/generics/ThrowGenericException.java deleted file mode 100644 index 994c7f88..00000000 --- a/code/generics/ThrowGenericException.java +++ /dev/null @@ -1,82 +0,0 @@ -// generics/ThrowGenericException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -interface Processor { - void process(List resultCollector) throws E; -} - -class ProcessRunner -extends ArrayList> { - List processAll() throws E { - List resultCollector = new ArrayList<>(); - for(Processor processor : this) - processor.process(resultCollector); - return resultCollector; - } -} - -class Failure1 extends Exception {} - -class Processor1 -implements Processor { - static int count = 3; - @Override - public void process(List resultCollector) - throws Failure1 { - if(count-- > 1) - resultCollector.add("Hep!"); - else - resultCollector.add("Ho!"); - if(count < 0) - throw new Failure1(); - } -} - -class Failure2 extends Exception {} - -class Processor2 -implements Processor { - static int count = 2; - @Override - public void process(List resultCollector) - throws Failure2 { - if(count-- == 0) - resultCollector.add(47); - else { - resultCollector.add(11); - } - if(count < 0) - throw new Failure2(); - } -} - -public class ThrowGenericException { - public static void main(String[] args) { - ProcessRunner runner = - new ProcessRunner<>(); - for(int i = 0; i < 3; i++) - runner.add(new Processor1()); - try { - System.out.println(runner.processAll()); - } catch(Failure1 e) { - System.out.println(e); - } - - ProcessRunner runner2 = - new ProcessRunner<>(); - for(int i = 0; i < 3; i++) - runner2.add(new Processor2()); - try { - System.out.println(runner2.processAll()); - } catch(Failure2 e) { - System.out.println(e); - } - } -} -/* Output: -[Hep!, Hep!, Ho!] -Failure2 -*/ diff --git a/code/generics/TupleList.java b/code/generics/TupleList.java deleted file mode 100644 index fe93330b..00000000 --- a/code/generics/TupleList.java +++ /dev/null @@ -1,23 +0,0 @@ -// generics/TupleList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Combining generic types to make complex generic types -import java.util.*; -import onjava.*; -import java.util.stream.*; - -public class TupleList -extends ArrayList> { - public static void main(String[] args) { - TupleList tl = - new TupleList<>(); - tl.add(TupleTest2.h()); - tl.add(TupleTest2.h()); - tl.forEach(System.out::println); - } -} -/* Output: -(Vehicle@7cca494b, Amphibian@7ba4f24f, hi, 47) -(Vehicle@3b9a45b3, Amphibian@7699a589, hi, 47) -*/ diff --git a/code/generics/TupleTest.java b/code/generics/TupleTest.java deleted file mode 100644 index e207da40..00000000 --- a/code/generics/TupleTest.java +++ /dev/null @@ -1,42 +0,0 @@ -// generics/TupleTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; - -public class TupleTest { - static Tuple2 f() { - // Autoboxing converts the int to Integer: - return new Tuple2<>("hi", 47); - } - static Tuple3 g() { - return new Tuple3<>(new Amphibian(), "hi", 47); - } - static - Tuple4 h() { - return - new Tuple4<>( - new Vehicle(), new Amphibian(), "hi", 47); - } - static - Tuple5 k() { - return new - Tuple5<>( - new Vehicle(), new Amphibian(), "hi", 47, 11.1); - } - public static void main(String[] args) { - Tuple2 ttsi = f(); - System.out.println(ttsi); - // ttsi.a1 = "there"; // Compile error: final - System.out.println(g()); - System.out.println(h()); - System.out.println(k()); - } -} -/* Output: -(hi, 47) -(Amphibian@1540e19d, hi, 47) -(Vehicle@7f31245a, Amphibian@6d6f6e28, hi, 47) -(Vehicle@330bedb4, Amphibian@2503dbd3, hi, 47, 11.1) -*/ diff --git a/code/generics/TupleTest2.java b/code/generics/TupleTest2.java deleted file mode 100644 index 3a0c8d14..00000000 --- a/code/generics/TupleTest2.java +++ /dev/null @@ -1,42 +0,0 @@ -// generics/TupleTest2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; -import static onjava.Tuple.*; - -public class TupleTest2 { - static Tuple2 f() { - return tuple("hi", 47); - } - static Tuple2 f2() { return tuple("hi", 47); } - static Tuple3 g() { - return tuple(new Amphibian(), "hi", 47); - } - static - Tuple4 h() { - return tuple( - new Vehicle(), new Amphibian(), "hi", 47); - } - static - Tuple5 k() { - return tuple(new Vehicle(), new Amphibian(), - "hi", 47, 11.1); - } - public static void main(String[] args) { - Tuple2 ttsi = f(); - System.out.println(ttsi); - System.out.println(f2()); - System.out.println(g()); - System.out.println(h()); - System.out.println(k()); - } -} -/* Output: -(hi, 47) -(hi, 47) -(Amphibian@14ae5a5, hi, 47) -(Vehicle@135fbaa4, Amphibian@45ee12a7, hi, 47) -(Vehicle@4b67cf4d, Amphibian@7ea987ac, hi, 47, 11.1) -*/ diff --git a/code/generics/UnboundedWildcards1.java b/code/generics/UnboundedWildcards1.java deleted file mode 100644 index 6b163a4c..00000000 --- a/code/generics/UnboundedWildcards1.java +++ /dev/null @@ -1,58 +0,0 @@ -// generics/UnboundedWildcards1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class UnboundedWildcards1 { - static List list1; - static List list2; - static List list3; - static void assign1(List list) { - list1 = list; - list2 = list; - //- list3 = list; - // warning: [unchecked] unchecked conversion - // list3 = list; - // ^ - // required: List - // found: List - } - static void assign2(List list) { - list1 = list; - list2 = list; - list3 = list; - } - static void assign3(List list) { - list1 = list; - list2 = list; - list3 = list; - } - public static void main(String[] args) { - assign1(new ArrayList()); - assign2(new ArrayList()); - //- assign3(new ArrayList()); - // warning: [unchecked] unchecked method invocation: - // method assign3 in class UnboundedWildcards1 - // is applied to given types - // assign3(new ArrayList()); - // ^ - // required: List - // found: ArrayList - // warning: [unchecked] unchecked conversion - // assign3(new ArrayList()); - // ^ - // required: List - // found: ArrayList - // 2 warnings - assign1(new ArrayList<>()); - assign2(new ArrayList<>()); - assign3(new ArrayList<>()); - // Both forms are acceptable as List: - List wildList = new ArrayList(); - wildList = new ArrayList<>(); - assign1(wildList); - assign2(wildList); - assign3(wildList); - } -} diff --git a/code/generics/UnboundedWildcards2.java b/code/generics/UnboundedWildcards2.java deleted file mode 100644 index ee80d555..00000000 --- a/code/generics/UnboundedWildcards2.java +++ /dev/null @@ -1,35 +0,0 @@ -// generics/UnboundedWildcards2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class UnboundedWildcards2 { - static Map map1; - static Map map2; - static Map map3; - static void assign1(Map map) { map1 = map; } - static void assign2(Map map) { map2 = map; } - static void assign3(Map map) { map3 = map; } - public static void main(String[] args) { - assign1(new HashMap()); - assign2(new HashMap()); - //- assign3(new HashMap()); - // warning: [unchecked] unchecked method invocation: - // method assign3 in class UnboundedWildcards2 - // is applied to given types - // assign3(new HashMap()); - // ^ - // required: Map - // found: HashMap - // warning: [unchecked] unchecked conversion - // assign3(new HashMap()); - // ^ - // required: Map - // found: HashMap - // 2 warnings - assign1(new HashMap<>()); - assign2(new HashMap<>()); - assign3(new HashMap<>()); - } -} diff --git a/code/generics/Unconstrained.java b/code/generics/Unconstrained.java deleted file mode 100644 index f683d53f..00000000 --- a/code/generics/Unconstrained.java +++ /dev/null @@ -1,20 +0,0 @@ -// generics/Unconstrained.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Other {} -class BasicOther extends BasicHolder {} - -public class Unconstrained { - public static void main(String[] args) { - BasicOther b = new BasicOther(); - BasicOther b2 = new BasicOther(); - b.set(new Other()); - Other other = b.get(); - b.f(); - } -} -/* Output: -Other -*/ diff --git a/code/generics/UseList.java b/code/generics/UseList.java deleted file mode 100644 index 924d3b56..00000000 --- a/code/generics/UseList.java +++ /dev/null @@ -1,11 +0,0 @@ -// generics/UseList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -import java.util.*; - -public class UseList { - void f(List v) {} - void f(List v) {} -} diff --git a/code/generics/UseList2.java b/code/generics/UseList2.java deleted file mode 100644 index 83d3b5d3..00000000 --- a/code/generics/UseList2.java +++ /dev/null @@ -1,10 +0,0 @@ -// generics/UseList2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class UseList2 { - void f1(List v) {} - void f2(List v) {} -} diff --git a/code/generics/Vehicle.java b/code/generics/Vehicle.java deleted file mode 100644 index 301a84e4..00000000 --- a/code/generics/Vehicle.java +++ /dev/null @@ -1,5 +0,0 @@ -// generics/Vehicle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class Vehicle {} diff --git a/code/generics/WatercolorSets.java b/code/generics/WatercolorSets.java deleted file mode 100644 index 7956778d..00000000 --- a/code/generics/WatercolorSets.java +++ /dev/null @@ -1,54 +0,0 @@ -// generics/WatercolorSets.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import generics.watercolors.*; -import java.util.*; -import static onjava.Sets.*; -import static generics.watercolors.Watercolors.*; - -public class WatercolorSets { - public static void main(String[] args) { - Set set1 = - EnumSet.range(BRILLIANT_RED, VIRIDIAN_HUE); - Set set2 = - EnumSet.range(CERULEAN_BLUE_HUE, BURNT_UMBER); - System.out.println("set1: " + set1); - System.out.println("set2: " + set2); - System.out.println( - "union(set1, set2): " + union(set1, set2)); - Set subset = intersection(set1, set2); - System.out.println( - "intersection(set1, set2): " + subset); - System.out.println("difference(set1, subset): " + - difference(set1, subset)); - System.out.println("difference(set2, subset): " + - difference(set2, subset)); - System.out.println("complement(set1, set2): " + - complement(set1, set2)); - } -} -/* Output: -set1: [BRILLIANT_RED, CRIMSON, MAGENTA, ROSE_MADDER, -VIOLET, CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, -COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE] -set2: [CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, -COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE, -SAP_GREEN, YELLOW_OCHRE, BURNT_SIENNA, RAW_UMBER, -BURNT_UMBER] -union(set1, set2): [BURNT_SIENNA, BRILLIANT_RED, -YELLOW_OCHRE, MAGENTA, SAP_GREEN, CERULEAN_BLUE_HUE, -ULTRAMARINE, VIRIDIAN_HUE, VIOLET, RAW_UMBER, -ROSE_MADDER, PERMANENT_GREEN, BURNT_UMBER, -PHTHALO_BLUE, CRIMSON, COBALT_BLUE_HUE] -intersection(set1, set2): [PERMANENT_GREEN, -CERULEAN_BLUE_HUE, ULTRAMARINE, VIRIDIAN_HUE, -PHTHALO_BLUE, COBALT_BLUE_HUE] -difference(set1, subset): [BRILLIANT_RED, MAGENTA, -VIOLET, CRIMSON, ROSE_MADDER] -difference(set2, subset): [BURNT_SIENNA, YELLOW_OCHRE, -BURNT_UMBER, SAP_GREEN, RAW_UMBER] -complement(set1, set2): [BURNT_SIENNA, BRILLIANT_RED, -YELLOW_OCHRE, MAGENTA, SAP_GREEN, VIOLET, RAW_UMBER, -ROSE_MADDER, BURNT_UMBER, CRIMSON] -*/ diff --git a/code/generics/Wildcards.java b/code/generics/Wildcards.java deleted file mode 100644 index 65348ecb..00000000 --- a/code/generics/Wildcards.java +++ /dev/null @@ -1,285 +0,0 @@ -// generics/Wildcards.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Exploring the meaning of wildcards - -public class Wildcards { - // Raw argument: - static void rawArgs(Holder holder, Object arg) { - //- holder.set(arg); - // warning: [unchecked] unchecked call to set(T) - // as a member of the raw type Holder - // holder.set(arg); - // ^ - // where T is a type-variable: - // T extends Object declared in class Holder - // 1 warning - - // Can't do this; don't have any 'T': - // T t = holder.get(); - - // OK, but type information is lost: - Object obj = holder.get(); - } - // Like rawArgs(), but errors instead of warnings: - static void - unboundedArg(Holder holder, Object arg) { - //- holder.set(arg); - // error: method set in class Holder - // cannot be applied to given types; - // holder.set(arg); - // ^ - // required: CAP#1 - // found: Object - // reason: argument mismatch; - // Object cannot be converted to CAP#1 - // where T is a type-variable: - // T extends Object declared in class Holder - // where CAP#1 is a fresh type-variable: - // CAP#1 extends Object from capture of ? - // 1 error - - // Can't do this; don't have any 'T': - // T t = holder.get(); - - // OK, but type information is lost: - Object obj = holder.get(); - } - static T exact1(Holder holder) { - return holder.get(); - } - static T exact2(Holder holder, T arg) { - holder.set(arg); - return holder.get(); - } - static - T wildSubtype(Holder holder, T arg) { - //- holder.set(arg); - // error: method set in class Holder - // cannot be applied to given types; - // holder.set(arg); - // ^ - // required: CAP#1 - // found: T#1 - // reason: argument mismatch; - // T#1 cannot be converted to CAP#1 - // where T#1,T#2 are type-variables: - // T#1 extends Object declared in method - // wildSubtype(Holder,T#1) - // T#2 extends Object declared in class Holder - // where CAP#1 is a fresh type-variable: - // CAP#1 extends T#1 from - // capture of ? extends T#1 - // 1 error - - return holder.get(); - } - static - void wildSupertype(Holder holder, T arg) { - holder.set(arg); - //- T t = holder.get(); - // error: incompatible types: - // CAP#1 cannot be converted to T - // T t = holder.get(); - // ^ - // where T is a type-variable: - // T extends Object declared in method - // wildSupertype(Holder,T) - // where CAP#1 is a fresh type-variable: - // CAP#1 extends Object super: - // T from capture of ? super T - // 1 error - - // OK, but type information is lost: - Object obj = holder.get(); - } - public static void main(String[] args) { - Holder raw = new Holder<>(); - // Or: - raw = new Holder(); - Holder qualified = new Holder<>(); - Holder unbounded = new Holder<>(); - Holder bounded = new Holder<>(); - Long lng = 1L; - - rawArgs(raw, lng); - rawArgs(qualified, lng); - rawArgs(unbounded, lng); - rawArgs(bounded, lng); - - unboundedArg(raw, lng); - unboundedArg(qualified, lng); - unboundedArg(unbounded, lng); - unboundedArg(bounded, lng); - - //- Object r1 = exact1(raw); - // warning: [unchecked] unchecked method invocation: - // method exact1 in class Wildcards is applied - // to given types - // Object r1 = exact1(raw); - // ^ - // required: Holder - // found: Holder - // where T is a type-variable: - // T extends Object declared in - // method exact1(Holder) - // warning: [unchecked] unchecked conversion - // Object r1 = exact1(raw); - // ^ - // required: Holder - // found: Holder - // where T is a type-variable: - // T extends Object declared in - // method exact1(Holder) - // 2 warnings - - Long r2 = exact1(qualified); - Object r3 = exact1(unbounded); // Must return Object - Long r4 = exact1(bounded); - - //- Long r5 = exact2(raw, lng); - // warning: [unchecked] unchecked method invocation: - // method exact2 in class Wildcards is - // applied to given types - // Long r5 = exact2(raw, lng); - // ^ - // required: Holder,T - // found: Holder,Long - // where T is a type-variable: - // T extends Object declared in - // method exact2(Holder,T) - // warning: [unchecked] unchecked conversion - // Long r5 = exact2(raw, lng); - // ^ - // required: Holder - // found: Holder - // where T is a type-variable: - // T extends Object declared in - // method exact2(Holder,T) - // 2 warnings - - Long r6 = exact2(qualified, lng); - - //- Long r7 = exact2(unbounded, lng); - // error: method exact2 in class Wildcards - // cannot be applied to given types; - // Long r7 = exact2(unbounded, lng); - // ^ - // required: Holder,T - // found: Holder,Long - // reason: inference variable T has - // incompatible bounds - // equality constraints: CAP#1 - // lower bounds: Long - // where T is a type-variable: - // T extends Object declared in - // method exact2(Holder,T) - // where CAP#1 is a fresh type-variable: - // CAP#1 extends Object from capture of ? - // 1 error - - //- Long r8 = exact2(bounded, lng); - // error: method exact2 in class Wildcards - // cannot be applied to given types; - // Long r8 = exact2(bounded, lng); - // ^ - // required: Holder,T - // found: Holder,Long - // reason: inference variable T - // has incompatible bounds - // equality constraints: CAP#1 - // lower bounds: Long - // where T is a type-variable: - // T extends Object declared in - // method exact2(Holder,T) - // where CAP#1 is a fresh type-variable: - // CAP#1 extends Long from - // capture of ? extends Long - // 1 error - - //- Long r9 = wildSubtype(raw, lng); - // warning: [unchecked] unchecked method invocation: - // method wildSubtype in class Wildcards - // is applied to given types - // Long r9 = wildSubtype(raw, lng); - // ^ - // required: Holder,T - // found: Holder,Long - // where T is a type-variable: - // T extends Object declared in - // method wildSubtype(Holder,T) - // warning: [unchecked] unchecked conversion - // Long r9 = wildSubtype(raw, lng); - // ^ - // required: Holder - // found: Holder - // where T is a type-variable: - // T extends Object declared in - // method wildSubtype(Holder,T) - // 2 warnings - - Long r10 = wildSubtype(qualified, lng); - // OK, but can only return Object: - Object r11 = wildSubtype(unbounded, lng); - Long r12 = wildSubtype(bounded, lng); - - //- wildSupertype(raw, lng); - // warning: [unchecked] unchecked method invocation: - // method wildSupertype in class Wildcards - // is applied to given types - // wildSupertype(raw, lng); - // ^ - // required: Holder,T - // found: Holder,Long - // where T is a type-variable: - // T extends Object declared in - // method wildSupertype(Holder,T) - // warning: [unchecked] unchecked conversion - // wildSupertype(raw, lng); - // ^ - // required: Holder - // found: Holder - // where T is a type-variable: - // T extends Object declared in - // method wildSupertype(Holder,T) - // 2 warnings - - wildSupertype(qualified, lng); - - //- wildSupertype(unbounded, lng); - // error: method wildSupertype in class Wildcards - // cannot be applied to given types; - // wildSupertype(unbounded, lng); - // ^ - // required: Holder,T - // found: Holder,Long - // reason: cannot infer type-variable(s) T - // (argument mismatch; Holder - // cannot be converted to Holder) - // where T is a type-variable: - // T extends Object declared in - // method wildSupertype(Holder,T) - // where CAP#1 is a fresh type-variable: - // CAP#1 extends Object from capture of ? - // 1 error - - //- wildSupertype(bounded, lng); - // error: method wildSupertype in class Wildcards - // cannot be applied to given types; - // wildSupertype(bounded, lng); - // ^ - // required: Holder,T - // found: Holder,Long - // reason: cannot infer type-variable(s) T - // (argument mismatch; Holder - // cannot be converted to Holder) - // where T is a type-variable: - // T extends Object declared in - // method wildSupertype(Holder,T) - // where CAP#1 is a fresh type-variable: - // CAP#1 extends Long from capture of - // ? extends Long - // 1 error - } -} diff --git a/code/generics/coffee/Americano.java b/code/generics/coffee/Americano.java deleted file mode 100644 index 96cd4a1f..00000000 --- a/code/generics/coffee/Americano.java +++ /dev/null @@ -1,6 +0,0 @@ -// generics/coffee/Americano.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package generics.coffee; -public class Americano extends Coffee {} diff --git a/code/generics/coffee/Breve.java b/code/generics/coffee/Breve.java deleted file mode 100644 index 329c406b..00000000 --- a/code/generics/coffee/Breve.java +++ /dev/null @@ -1,6 +0,0 @@ -// generics/coffee/Breve.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package generics.coffee; -public class Breve extends Coffee {} diff --git a/code/generics/coffee/Cappuccino.java b/code/generics/coffee/Cappuccino.java deleted file mode 100644 index 3ce89b50..00000000 --- a/code/generics/coffee/Cappuccino.java +++ /dev/null @@ -1,6 +0,0 @@ -// generics/coffee/Cappuccino.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package generics.coffee; -public class Cappuccino extends Coffee {} diff --git a/code/generics/coffee/Coffee.java b/code/generics/coffee/Coffee.java deleted file mode 100644 index c90d88c1..00000000 --- a/code/generics/coffee/Coffee.java +++ /dev/null @@ -1,14 +0,0 @@ -// generics/coffee/Coffee.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package generics.coffee; - -public class Coffee { - private static long counter = 0; - private final long id = counter++; - @Override - public String toString() { - return getClass().getSimpleName() + " " + id; - } -} diff --git a/code/generics/coffee/CoffeeSupplier.java b/code/generics/coffee/CoffeeSupplier.java deleted file mode 100644 index fe5dced8..00000000 --- a/code/generics/coffee/CoffeeSupplier.java +++ /dev/null @@ -1,72 +0,0 @@ -// generics/coffee/CoffeeSupplier.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java generics.coffee.CoffeeSupplier} -package generics.coffee; -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import java.lang.reflect.InvocationTargetException; - -public class CoffeeSupplier -implements Supplier, Iterable { - private Class[] types = { Latte.class, Mocha.class, - Cappuccino.class, Americano.class, Breve.class, }; - private static Random rand = new Random(47); - public CoffeeSupplier() {} - // For iteration: - private int size = 0; - public CoffeeSupplier(int sz) { size = sz; } - @Override - public Coffee get() { - try { - return (Coffee) - types[rand.nextInt(types.length)] - .getConstructor().newInstance(); - // Report programmer errors at run time: - } catch(InstantiationException | - NoSuchMethodException | - InvocationTargetException | - IllegalAccessException e) { - throw new RuntimeException(e); - } - } - class CoffeeIterator implements Iterator { - int count = size; - @Override - public boolean hasNext() { return count > 0; } - @Override - public Coffee next() { - count--; - return CoffeeSupplier.this.get(); - } - @Override - public void remove() { // Not implemented - throw new UnsupportedOperationException(); - } - } - @Override - public Iterator iterator() { - return new CoffeeIterator(); - } - public static void main(String[] args) { - Stream.generate(new CoffeeSupplier()) - .limit(5) - .forEach(System.out::println); - for(Coffee c : new CoffeeSupplier(5)) - System.out.println(c); - } -} -/* Output: -Americano 0 -Latte 1 -Americano 2 -Mocha 3 -Mocha 4 -Breve 5 -Americano 6 -Latte 7 -Cappuccino 8 -Cappuccino 9 -*/ diff --git a/code/generics/coffee/Latte.java b/code/generics/coffee/Latte.java deleted file mode 100644 index d735cc87..00000000 --- a/code/generics/coffee/Latte.java +++ /dev/null @@ -1,6 +0,0 @@ -// generics/coffee/Latte.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package generics.coffee; -public class Latte extends Coffee {} diff --git a/code/generics/coffee/Mocha.java b/code/generics/coffee/Mocha.java deleted file mode 100644 index cc567be1..00000000 --- a/code/generics/coffee/Mocha.java +++ /dev/null @@ -1,6 +0,0 @@ -// generics/coffee/Mocha.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package generics.coffee; -public class Mocha extends Coffee {} diff --git a/code/generics/decorator/Decoration.java b/code/generics/decorator/Decoration.java deleted file mode 100644 index 96611a75..00000000 --- a/code/generics/decorator/Decoration.java +++ /dev/null @@ -1,51 +0,0 @@ -// generics/decorator/Decoration.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java generics.decorator.Decoration} -package generics.decorator; -import java.util.*; - -class Basic { - private String value; - public void set(String val) { value = val; } - public String get() { return value; } -} - -class Decorator extends Basic { - protected Basic basic; - Decorator(Basic basic) { this.basic = basic; } - @Override - public void set(String val) { basic.set(val); } - @Override - public String get() { return basic.get(); } -} - -class TimeStamped extends Decorator { - private final long timeStamp; - TimeStamped(Basic basic) { - super(basic); - timeStamp = new Date().getTime(); - } - public long getStamp() { return timeStamp; } -} - -class SerialNumbered extends Decorator { - private static long counter = 1; - private final long serialNumber = counter++; - SerialNumbered(Basic basic) { super(basic); } - public long getSerialNumber() { return serialNumber; } -} - -public class Decoration { - public static void main(String[] args) { - TimeStamped t = new TimeStamped(new Basic()); - TimeStamped t2 = new TimeStamped( - new SerialNumbered(new Basic())); - //- t2.getSerialNumber(); // Not available - SerialNumbered s = new SerialNumbered(new Basic()); - SerialNumbered s2 = new SerialNumbered( - new TimeStamped(new Basic())); - //- s2.getStamp(); // Not available - } -} diff --git a/code/generics/dogsandrobots.go b/code/generics/dogsandrobots.go deleted file mode 100644 index f65b9c18..00000000 --- a/code/generics/dogsandrobots.go +++ /dev/null @@ -1,32 +0,0 @@ -// generics/dogsandrobots.go -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package main -import "fmt" - -type Dog struct {} -func (this Dog) speak() { fmt.Printf("Arf!\n")} -func (this Dog) sit() { fmt.Printf("Sitting\n")} -func (this Dog) reproduce() {} - -type Robot struct {} -func (this Robot) speak() { fmt.Printf("Click!\n") } -func (this Robot) sit() { fmt.Printf("Clank!\n") } -func (this Robot) oilChange() {} - -func perform(speaker interface { speak(); sit() }) { - speaker.speak(); - speaker.sit(); -} - -func main() { - perform(Dog{}) - perform(Robot{}) -} -/* Output: -Arf! -Sitting -Click! -Clank! -*/ diff --git a/code/generics/watercolors/Watercolors.java b/code/generics/watercolors/Watercolors.java deleted file mode 100644 index 0625e532..00000000 --- a/code/generics/watercolors/Watercolors.java +++ /dev/null @@ -1,15 +0,0 @@ -// generics/watercolors/Watercolors.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package generics.watercolors; - -public enum Watercolors { - ZINC, LEMON_YELLOW, MEDIUM_YELLOW, DEEP_YELLOW, - ORANGE, BRILLIANT_RED, CRIMSON, MAGENTA, - ROSE_MADDER, VIOLET, CERULEAN_BLUE_HUE, - PHTHALO_BLUE, ULTRAMARINE, COBALT_BLUE_HUE, - PERMANENT_GREEN, VIRIDIAN_HUE, SAP_GREEN, - YELLOW_OCHRE, BURNT_SIENNA, RAW_UMBER, - BURNT_UMBER, PAYNES_GRAY, IVORY_BLACK -} diff --git a/code/gradle.properties b/code/gradle.properties deleted file mode 100644 index f97ebb7d..00000000 --- a/code/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.parallel=true diff --git a/code/gradle/checkstyle.gradle b/code/gradle/checkstyle.gradle deleted file mode 100644 index 0f0e6086..00000000 --- a/code/gradle/checkstyle.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply plugin: 'checkstyle' - -checkstyle { - ignoreFailures = true - configFile = new File(rootProject.projectDir, 'checkstyle.xml') - sourceSets = [sourceSets.main] -} - -tasks.withType(Checkstyle) { - reports { - xml.enabled = false - html.enabled = true - } -} diff --git a/code/gradle/findbugs.gradle b/code/gradle/findbugs.gradle deleted file mode 100644 index ac628cb2..00000000 --- a/code/gradle/findbugs.gradle +++ /dev/null @@ -1,15 +0,0 @@ -/* -apply plugin: 'findbugs' - -findbugs { - ignoreFailures = true - sourceSets = [sourceSets.main] -} - -tasks.withType(FindBugs) { - reports { - xml.enabled = false - html.enabled = true - } -} -*/ diff --git a/code/gradle/java.gradle b/code/gradle/java.gradle deleted file mode 100644 index eadc4ef9..00000000 --- a/code/gradle/java.gradle +++ /dev/null @@ -1,39 +0,0 @@ -apply plugin: 'java' - -sourceCompatibility = '1.8' -targetCompatibility = '1.8' - -compileJava { - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" -} - -sourceSets { - main { - java { - srcDir projectDir - exclude "tests/**" - } - resources { - srcDir projectDir - include '*.xml' - } - } - - test { - java { - srcDir file("tests") - } - } -} - -repositories { - jcenter() -} - -dependencies { - // Logging: - compile 'org.slf4j:slf4j-api:1.7.21' - compile 'ch.qos.logback:logback-classic:1.1.7' - // You can also use the JDK's built-in logging as the back end: - // compile group: 'org.slf4j:slf4j-jdk14:1.7.21' -} \ No newline at end of file diff --git a/code/gradle/jmh.gradle b/code/gradle/jmh.gradle deleted file mode 100644 index ce61db4b..00000000 --- a/code/gradle/jmh.gradle +++ /dev/null @@ -1,17 +0,0 @@ -apply plugin: 'me.champeau.gradle.jmh' - -sourceSets { - jmh { - java { - srcDir projectDir - } - } -} - -jmh { - jmhVersion = '1.17.4' - duplicateClassesStrategy = 'warn' - failOnError = true - // See https://github.com/melix/jmh-gradle-plugin - // for other options -} diff --git a/code/gradle/junit-jupiter.gradle b/code/gradle/junit-jupiter.gradle deleted file mode 100644 index 98a77843..00000000 --- a/code/gradle/junit-jupiter.gradle +++ /dev/null @@ -1,72 +0,0 @@ -import org.apache.tools.ant.util.TeeOutputStream - -dependencies { - testImplementation(platform('org.junit:junit-bom:5.7.0')) - testImplementation('org.junit.jupiter:junit-jupiter') -} - -test { - useJUnitPlatform() - testLogging { - events "passed", "skipped", "failed" - } -} - -/* NEW: (REQUIRES CODE REWRITES IN BOOK AND TEST CODE) --> http://junit.org/junit5/docs/current/user-guide/ - -ext { - junitJupiterVersion = '5.0.0-M3' -} - -dependencies { - testCompile "org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}" - testRuntime "org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}" -} - - -junitPlatform { - platformVersion '1.0.0-M3' - - filters { - packages { - exclude 'collectiontopics.jmh' - } - includeClassNamePattern '.*' - } -} -*/ - -/* Store test output in $projectName/tests - JUnit 5's junitPlatformTest runs as a "javaExec" rather than a "test", - so we can't hook into the before/after test behavior. -*/ -tasks.findByPath(":$name:test").configure { - File testDir = file("tests") - if(testDir.exists()) { - File outFile = new File(testDir, 'report.txt') - - Writer taskOutput - - doFirst { - taskOutput = project.file(outFile).newWriter() - } - - testLogging.showStandardStreams = true - - onOutput { descriptor, event -> - taskOutput.append(event.message) - } - - doLast { - // WARNING: if the task fails, this won't be executed and the file remains open. - // The memory cache version doesn't have this problem. - taskOutput.close() - - if(outFile.size() == 0) - outFile.delete() - else if(outFile.text.contains("0 tests found")) - outFile.delete() - } - } -} diff --git a/code/gradle/subprojects.gradle b/code/gradle/subprojects.gradle deleted file mode 100644 index e9d857d8..00000000 --- a/code/gradle/subprojects.gradle +++ /dev/null @@ -1,67 +0,0 @@ -project(':validating') { - jmh { - include = 'validating.jmh.*' - } -} - -project(':equalshashcode') { - dependencies { - compile project(':typeinfo') - compile project(':collections') - } -} - -project(':lowlevel') { - dependencies { - compile project(':enums') - } -} - -project(':strings') { - dependencies { - compile project(':generics') - } -} - -project(':serialization') { - configurations.all { - resolutionStrategy { - force 'xml-apis:xml-apis:1.0.b2' - } - } - dependencies { - compile 'com.io7m.xom:xom:1.2.10' - } -} - -project(':interfaces') { - dependencies { - compile project(':polymorphism') - } -} - -project(':hiding') { - dependencies { - compile project(':com') - } -} - -project(':generics') { - dependencies { - compile project(':typeinfo') - } -} - -project(':collections') { - dependencies { - compile project(':typeinfo') - } -} - -configure(subprojects - project(':onjava')) { - dependencies { - compile project(':onjava') - compile 'com.google.guava:guava:21.0' - compileOnly "org.openjdk.jmh:jmh-core:${jmh.jmhVersion}" - } -} diff --git a/code/gradle/wrapper/gradle-wrapper.jar b/code/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59203 zcma&O1CT9Y(k9%tZQHhO+qUh#ZQHhO+qmuS+qP|E@9xZO?0h@l{(r>DQ>P;GjjD{w zH}lENr;dU&FbEU?00aa80D$0M0RRB{U*7-#kbjS|qAG&4l5%47zyJ#WrfA#1$1Ctx zf&Z_d{GW=lf^w2#qRJ|CvSJUi(^E3iv~=^Z(zH}F)3Z%V3`@+rNB7gTVU{Bb~90p|f+0(v;nz01EG7yDMX9@S~__vVgv%rS$+?IH+oZ03D5zYrv|^ zC1J)SruYHmCki$jLBlTaE5&dFG9-kq3!^i>^UQL`%gn6)jz54$WDmeYdsBE9;PqZ_ zoGd=P4+|(-u4U1dbAVQrFWoNgNd;0nrghPFbQrJctO>nwDdI`Q^i0XJDUYm|T|RWc zZ3^Qgo_Qk$%Fvjj-G}1NB#ZJqIkh;kX%V{THPqOyiq)d)0+(r9o(qKlSp*hmK#iIY zA^)Vr$-Hz<#SF=0@tL@;dCQsm`V9s1vYNq}K1B)!XSK?=I1)tX+bUV52$YQu*0%fnWEukW>mxkz+%3-S!oguE8u#MGzST8_Dy^#U?fA@S#K$S@9msUiX!gd_ow>08w5)nX{-KxqMOo7d?k2&?Vf z&diGDtZr(0cwPe9z9FAUSD9KC)7(n^lMWuayCfxzy8EZsns%OEblHFSzP=cL6}?J| z0U$H!4S_TVjj<`6dy^2j`V`)mC;cB%* z8{>_%E1^FH!*{>4a7*C1v>~1*@TMcLK{7nEQ!_igZC}ikJ$*<$yHy>7)oy79A~#xE zWavoJOIOC$5b6*q*F_qN1>2#MY)AXVyr$6x4b=$x^*aqF*L?vmj>Mgv+|ITnw_BoW zO?jwHvNy^prH{9$rrik1#fhyU^MpFqF2fYEt(;4`Q&XWOGDH8k6M=%@fics4ajI;st# zCU^r1CK&|jzUhRMv;+W~6N;u<;#DI6cCw-otsc@IsN3MoSD^O`eNflIoR~l4*&-%RBYk@gb^|-JXs&~KuSEmMxB}xSb z@K76cXD=Y|=I&SNC2E+>Zg?R6E%DGCH5J1nU!A|@eX9oS(WPaMm==k2s_ueCqdZw| z&hqHp)47`c{BgwgvY2{xz%OIkY1xDwkw!<0veB#yF4ZKJyabhyyVS`gZepcFIk%e2 zTcrmt2@-8`7i-@5Nz>oQWFuMC_KlroCl(PLSodswHqJ3fn<;gxg9=}~3x_L3P`9Sn zChIf}8vCHvTriz~T2~FamRi?rh?>3bX1j}%bLH+uFX+p&+^aXbOK7clZxdU~6Uxgy z8R=obwO4dL%pmVo*Ktf=lH6hnlz_5k3cG;m8lgaPp~?eD!Yn2kf)tU6PF{kLyn|oI@eQ`F z3IF7~Blqg8-uwUuWZScRKn%c2_}dXB6Dx_&xR*n9M9LXasJhtZdr$vBY!rP{c@=)& z#!?L$2UrkvClwQO>U*fSMs67oSj2mxiJ$t;E|>q%Kh_GzzWWO&3;ufU%2z%ucBU8H z3WIwr$n)cfCXR&>tyB7BcSInK>=ByZA%;cVEJhcg<#6N{aZC4>K41XF>ZgjG`z_u& zGY?;Ad?-sgiOnI`oppF1o1Gurqbi*;#x2>+SSV6|1^G@ooVy@fg?wyf@0Y!UZ4!}nGuLeC^l)6pwkh|oRY`s1Pm$>zZ3u-83T|9 zGaKJIV3_x+u1>cRibsaJpJqhcm%?0-L;2 zitBrdRxNmb0OO2J%Y&Ym(6*`_P3&&5Bw157{o7LFguvxC$4&zTy#U=W*l&(Q2MNO} zfaUwYm{XtILD$3864IA_nn34oVa_g^FRuHL5wdUd)+W-p-iWCKe8m_cMHk+=? zeKX)M?Dt(|{r5t7IenkAXo%&EXIb-i^w+0CX0D=xApC=|Xy(`xy+QG^UyFe z+#J6h_&T5i#sV)hj3D4WN%z;2+jJcZxcI3*CHXGmOF3^)JD5j&wfX)e?-|V0GPuA+ zQFot%aEqGNJJHn$!_}#PaAvQ^{3-Ye7b}rWwrUmX53(|~i0v{}G_sI9uDch_brX&6 zWl5Ndj-AYg(W9CGfQf<6!YmY>Ey)+uYd_JNXH=>|`OH-CDCmcH(0%iD_aLlNHKH z7bcW-^5+QV$jK?R*)wZ>r9t}loM@XN&M-Pw=F#xn(;u3!(3SXXY^@=aoj70;_=QE9 zGghsG3ekq#N||u{4We_25U=y#T*S{4I{++Ku)> zQ!DZW;pVcn>b;&g2;YE#+V`v*Bl&Y-i@X6D*OpNA{G@JAXho&aOk(_j^weW{#3X5Y z%$q_wpb07EYPdmyH(1^09i$ca{O<}7) zRWncXdSPgBE%BM#by!E>tdnc$8RwUJg1*x($6$}ae$e9Knj8gvVZe#bLi!<+&BkFj zg@nOpDneyc+hU9P-;jmOSMN|*H#>^Ez#?;%C3hg_65leSUm;iz)UkW)jX#p)e&S&M z1|a?wDzV5NVnlhRBCd_;F87wp>6c<&nkgvC+!@KGiIqWY4l}=&1w7|r6{oBN8xyzh zG$b#2=RJp_iq6)#t5%yLkKx(0@D=C3w+oiXtSuaQ%I1WIb-eiE$d~!)b@|4XLy!CZ z9p=t=%3ad@Ep+<9003D2KZ5VyP~_n$=;~r&YUg5UZ0KVD&tR1DHy9x)qWtKJp#Kq# zP*8p#W(8JJ_*h_3W}FlvRam?<4Z+-H77^$Lvi+#vmhL9J zJ<1SV45xi;SrO2f=-OB(7#iNA5)x1uNC-yNxUw|!00vcW2PufRm>e~toH;M0Q85MQLWd?3O{i8H+5VkR@l9Dg-ma ze2fZ%>G(u5(k9EHj2L6!;(KZ8%8|*-1V|B#EagbF(rc+5iL_5;Eu)L4Z-V;0HfK4d z*{utLse_rvHZeQ>V5H=f78M3Ntg1BPxFCVD{HbNA6?9*^YIq;B-DJd{Ca2L#)qWP? zvX^NhFmX?CTWw&Ns}lgs;r3i+Bq@y}Ul+U%pzOS0Fcv9~aB(0!>GT0)NO?p=25LjN z2bh>6RhgqD7bQj#k-KOm@JLgMa6>%-ok1WpOe)FS^XOU{c?d5shG(lIn3GiVBxmg`u%-j=)^v&pX1JecJics3&jvPI)mDut52? z3jEA)DM%}BYbxxKrizVYwq?(P&19EXlwD9^-6J+4!}9{ywR9Gk42jjAURAF&EO|~N z)?s>$Da@ikI4|^z0e{r`J8zIs>SpM~Vn^{3fArRu;?+43>lD+^XtUcY1HidJwnR6+ z!;oG2=B6Z_=M%*{z-RaHc(n|1RTKQdNjjV!Pn9lFt^4w|AeN06*j}ZyhqZ^!-=cyGP_ShV1rGxkx8t zB;8`h!S{LD%ot``700d0@Grql(DTt4Awgmi+Yr0@#jbe=2#UkK%rv=OLqF)9D7D1j z!~McAwMYkeaL$~kI~90)5vBhBzWYc3Cj1WI0RS`z000R8-@ET0dA~*r(gSiCJmQMN&4%1D zyVNf0?}sBH8zNbBLn>~(W{d3%@kL_eQ6jEcR{l>C|JK z(R-fA!z|TTRG40|zv}7E@PqCAXP3n`;%|SCQ|ZS%ym$I{`}t3KPL&^l5`3>yah4*6 zifO#{VNz3)?ZL$be;NEaAk9b#{tV?V7 zP|wf5YA*1;s<)9A4~l3BHzG&HH`1xNr#%){4xZ!jq%o=7nN*wMuXlFV{HaiQLJ`5G zBhDi#D(m`Q1pLh@Tq+L;OwuC52RdW7b8}~60WCOK5iYMUad9}7aWBuILb({5=z~YF zt?*Jr5NG+WadM{mDL>GyiByCuR)hd zA=HM?J6l1Xv0Dl+LW@w$OTcEoOda^nFCw*Sy^I@$sSuneMl{4ys)|RY#9&NxW4S)9 zq|%83IpslTLoz~&vTo!Ga@?rj_kw{|k{nv+w&Ku?fyk4Ki4I?);M|5Axm)t+BaE)D zm(`AQ#k^DWrjbuXoJf2{Aj^KT zFb1zMSqxq|vceV+Mf-)$oPflsO$@*A0n0Z!R{&(xh8s}=;t(lIy zv$S8x>m;vQNHuRzoaOo?eiWFe{0;$s`Bc+Osz~}Van${u;g(su`3lJ^TEfo~nERfP z)?aFzpDgnLYiERsKPu|0tq4l2wT)Atr6Qb%m-AUn6HnCue*yWICp7TjW$@sO zm5rm4aTcPQ(rfi7a`xP7cKCFrJD}*&_~xgLyr^-bmsL}y;A5P|al8J3WUoBSjqu%v zxC;mK!g(7r6RRJ852Z~feoC&sD3(6}^5-uLK8o)9{8L_%%rItZK9C){UxB|;G>JbP zsRRtS4-3B*5c+K2kvmgZK8472%l>3cntWUOVHxB|{Ay~aOg5RN;{PJgeVD*H%ac+y!h#wi%o2bF2Ca8IyMyH{>4#{E_8u^@+l-+n=V}Sq?$O z{091@v%Bd*3pk0^2UtiF9Z+(a@wy6 zUdw8J*ze$K#=$48IBi1U%;hmhO>lu!uU;+RS}p&6@rQila7WftH->*A4=5W|Fmtze z)7E}jh@cbmr9iup^i%*(uF%LG&!+Fyl@LFA-}Ca#bxRfDJAiR2dt6644TaYw1Ma79 zt8&DYj31j^5WPNf5P&{)J?WlCe@<3u^78wnd(Ja4^a>{^Tw}W>|Cjt^If|7l^l)^Q zbz|7~CF(k_9~n|h;ysZ+jHzkXf(*O*@5m zLzUmbHp=x!Q|!9NVXyipZ3)^GuIG$k;D)EK!a5=8MFLI_lpf`HPKl=-Ww%z8H_0$j ztJ||IfFG1lE9nmQ0+jPQy zCBdKkjArH@K7jVcMNz);Q(Q^R{d5G?-kk;Uu_IXSyWB)~KGIizZL(^&qF;|1PI7!E zTP`%l)gpX|OFn&)M%txpQ2F!hdA~hX1Cm5)IrdljqzRg!f{mN%G~H1&oqe`5eJCIF zHdD7O;AX-{XEV(a`gBFJ9ews#CVS2y!&>Cm_dm3C8*n3MA*e67(WC?uP@8TXuMroq z{#w$%z@CBIkRM7?}Xib+>hRjy?%G!fiw8! z8(gB+8J~KOU}yO7UGm&1g_MDJ$IXS!`+*b*QW2x)9>K~Y*E&bYMnjl6h!{17_8d!%&9D`a7r&LKZjC<&XOvTRaKJ1 zUY@hl5^R&kZl3lU3njk`3dPzxj$2foOL26r(9zsVF3n_F#v)s5vv3@dgs|lP#eylq62{<-vczqP!RpVBTgI>@O6&sU>W|do17+#OzQ7o5A$ICH z?GqwqnK^n2%LR;$^oZM;)+>$X3s2n}2jZ7CdWIW0lnGK-b#EG01)P@aU`pg}th&J-TrU`tIpb5t((0eu|!u zQz+3ZiOQ^?RxxK4;zs=l8q!-n7X{@jSwK(iqNFiRColuEOg}!7cyZi`iBX4g1pNBj zAPzL?P^Ljhn;1$r8?bc=#n|Ed7wB&oHcw()&*k#SS#h}jO?ZB246EGItsz*;^&tzp zu^YJ0=lwsi`eP_pU8}6JA7MS;9pfD;DsSsLo~ogzMNP70@@;Fm8f0^;>$Z>~}GWRw!W5J3tNX*^2+1f3hz{~rIzJo z6W%J(H!g-eI_J1>0juX$X4Cl6i+3wbc~k146UIX&G22}WE>0ga#WLsn9tY(&29zBvH1$`iWtTe zG2jYl@P!P)eb<5DsR72BdI7-zP&cZNI{7q3e@?N8IKc4DE#UVr->|-ryuJXk^u^>4 z$3wE~=q390;XuOQP~TNoDR?#|NSPJ%sTMInA6*rJ%go|=YjGe!B>z6u$IhgQSwoV* zjy3F2#I>uK{42{&IqP59)Y(1*Z>>#W8rCf4_eVsH)`v!P#^;BgzKDR`ARGEZzkNX+ zJUQu=*-ol=Xqqt5=`=pA@BIn@6a9G8C{c&`i^(i+BxQO9?YZ3iu%$$da&Kb?2kCCo zo7t$UpSFWqmydXf@l3bVJ=%K?SSw)|?srhJ-1ZdFu*5QhL$~-IQS!K1s@XzAtv6*Y zl8@(5BlWYLt1yAWy?rMD&bwze8bC3-GfNH=p zynNFCdxyX?K&G(ZZ)afguQ2|r;XoV^=^(;Cku#qYn4Lus`UeKt6rAlFo_rU`|Rq z&G?~iWMBio<78of-2X(ZYHx~=U0Vz4btyXkctMKdc9UM!vYr~B-(>)(Hc|D zMzkN4!PBg%tZoh+=Gba!0++d193gbMk2&krfDgcbx0jI92cq?FFESVg0D$>F+bil} zY~$)|>1HZsX=5sAZ2WgPB5P=8X#TI+NQ(M~GqyVB53c6IdX=k>Wu@A0Svf5#?uHaF zsYn|koIi3$(%GZ2+G+7Fv^lHTb#5b8sAHSTnL^qWZLM<(1|9|QFw9pnRU{svj}_Al zL)b9>fN{QiA($8peNEJyy`(a{&uh-T4_kdZFIVsKKVM(?05}76EEz?#W za^fiZOAd14IJ4zLX-n7Lq0qlQ^lW8Cvz4UKkV9~P}>sq0?xD3vg+$4vLm~C(+ zM{-3Z#qnZ09bJ>}j?6ry^h+@PfaD7*jZxBEY4)UG&daWb??6)TP+|3#Z&?GL?1i+280CFsE|vIXQbm| zM}Pk!U`U5NsNbyKzkrul-DzwB{X?n3E6?TUHr{M&+R*2%yOiXdW-_2Yd6?38M9Vy^ z*lE%gA{wwoSR~vN0=no}tP2Ul5Gk5M(Xq`$nw#ndFk`tcpd5A=Idue`XZ!FS>Q zG^0w#>P4pPG+*NC9gLP4x2m=cKP}YuS!l^?sHSFftZy{4CoQrb_ z^20(NnG`wAhMI=eq)SsIE~&Gp9Ne0nD4%Xiu|0Fj1UFk?6avDqjdXz{O1nKao*46y zT8~iA%Exu=G#{x=KD;_C&M+Zx4+n`sHT>^>=-1YM;H<72k>$py1?F3#T1*ef9mLZw z5naLQr?n7K;2l+{_uIw*_1nsTn~I|kkCgrn;|G~##hM;9l7Jy$yJfmk+&}W@JeKcF zx@@Woiz8qdi|D%aH3XTx5*wDlbs?dC1_nrFpm^QbG@wM=i2?Zg;$VK!c^Dp8<}BTI zyRhAq@#%2pGV49*Y5_mV4+OICP|%I(dQ7x=6Ob}>EjnB_-_18*xrY?b%-yEDT(wrO z9RY2QT0`_OpGfMObKHV;QLVnrK%mc?$WAdIT`kJQT^n%GuzE7|9@k3ci5fYOh(287 zuIbg!GB3xLg$YN=n)^pHGB0jH+_iIiC=nUcD;G6LuJsjn2VI1cyZx=a?ShCsF==QK z;q~*m&}L<-cb+mDDXzvvrRsybcgQ;Vg21P(uLv5I+eGc7o7tc6`;OA9{soHFOz zT~2?>Ts}gprIX$wRBb4yE>ot<8+*Bv`qbSDv*VtRi|cyWS>)Fjs>fkNOH-+PX&4(~ z&)T8Zam2L6puQl?;5zg9h<}k4#|yH9czHw;1jw-pwBM*O2hUR6yvHATrI%^mvs9q_ z&ccT0>f#eDG<^WG^q@oVqlJrhxH)dcq2cty@l3~|5#UDdExyXUmLQ}f4#;6fI{f^t zDCsgIJ~0`af%YR%Ma5VQq-p21k`vaBu6WE?66+5=XUd%Ay%D$irN>5LhluRWt7 zov-=f>QbMk*G##&DTQyou$s7UqjjW@k6=!I@!k+S{pP8R(2=e@io;N8E`EOB;OGoI zw6Q+{X1_I{OO0HPpBz!X!@`5YQ2)t{+!?M_iH25X(d~-Zx~cXnS9z>u?+If|iNJbx zyFU2d1!ITX64D|lE0Z{dLRqL1Ajj=CCMfC4lD3&mYR_R_VZ>_7_~|<^o*%_&jevU+ zQ4|qzci=0}Jydw|LXLCrOl1_P6Xf@c0$ieK2^7@A9UbF{@V_0p%lqW|L?5k>bVM8|p5v&2g;~r>B8uo<4N+`B zH{J)h;SYiIVx@#jI&p-v3dwL5QNV1oxPr8J%ooezTnLW>i*3Isb49%5i!&ac_dEXv zvXmVUck^QHmyrF8>CGXijC_R-y(Qr{3Zt~EmW)-nC!tiH`wlw5D*W7Pip;T?&j%kX z6DkZX4&}iw>hE(boLyjOoupf6JpvBG8}jIh!!VhnD0>}KSMMo{1#uU6kiFcA04~|7 zVO8eI&x1`g4CZ<2cYUI(n#wz2MtVFHx47yE5eL~8bot~>EHbevSt}LLMQX?odD{Ux zJMnam{d)W4da{l7&y-JrgiU~qY3$~}_F#G7|MxT)e;G{U`In&?`j<5D->}cb{}{T(4DF0BOk-=1195KB-E*o@c?`>y#4=dMtYtSY=&L{!TAjFVcq0y@AH`vH! z$41+u!Ld&}F^COPgL(EE{0X7LY&%D7-(?!kjFF7=qw<;`V{nwWBq<)1QiGJgUc^Vz ztMUlq1bZqKn17|6x6iAHbWc~l1HcmAxr%$Puv!znW)!JiukwIrqQ00|H$Z)OmGG@= zv%A8*4cq}(?qn4rN6o`$Y))(MyXr8R<2S^J+v(wmFmtac!%VOfN?&(8Nr!T@kV`N; z*Q33V3t`^rN&aBiHet)18wy{*wi1=W!B%B-Q6}SCrUl$~Hl{@!95ydml@FK8P=u4s z4e*7gV2s=YxEvskw2Ju!2%{8h01rx-3`NCPc(O zH&J0VH5etNB2KY6k4R@2Wvl^Ck$MoR3=)|SEclT2ccJ!RI9Nuter7u9@;sWf-%um;GfI!=eEIQ2l2p_YWUd{|6EG ze{yO6;lMc>;2tPrsNdi@&1K6(1;|$xe8vLgiouj%QD%gYk`4p{Ktv9|j+!OF-P?@p z;}SV|oIK)iwlBs+`ROXkhd&NK zzo__r!B>tOXpBJMDcv!Mq54P+n4(@dijL^EpO1wdg~q+!DT3lB<>9AANSe!T1XgC=J^)IP0XEZ()_vpu!!3HQyJhwh?r`Ae%Yr~b% zO*NY9t9#qWa@GCPYOF9aron7thfWT`eujS4`t2uG6)~JRTI;f(ZuoRQwjZjp5Pg34 z)rp$)Kr?R+KdJ;IO;pM{$6|2y=k_siqvp%)2||cHTe|b5Ht8&A{wazGNca zX$Ol?H)E_R@SDi~4{d-|8nGFhZPW;Cts1;08TwUvLLv&_2$O6Vt=M)X;g%HUr$&06 zISZb(6)Q3%?;3r~*3~USIg=HcJhFtHhIV(siOwV&QkQe#J%H9&E21!C*d@ln3E@J* zVqRO^<)V^ky-R|%{(9`l-(JXq9J)1r$`uQ8a}$vr9E^nNiI*thK8=&UZ0dsFN_eSl z(q~lnD?EymWLsNa3|1{CRPW60>DSkY9YQ;$4o3W7Ms&@&lv9eH!tk~N&dhqX&>K@} zi1g~GqglxkZ5pEFkllJ)Ta1I^c&Bt6#r(QLQ02yHTaJB~- zCcE=5tmi`UA>@P=1LBfBiqk)HB4t8D?02;9eXj~kVPwv?m{5&!&TFYhu>3=_ zsGmYZ^mo*-j69-42y&Jj0cBLLEulNRZ9vXE)8~mt9C#;tZs;=#M=1*hebkS;7(aGf zcs7zH(I8Eui9UU4L--))yy`&d&$In&VA2?DAEss4LAPCLd>-$i?lpXvn!gu^JJ$(DoUlc6wE98VLZ*z`QGQov5l4Fm_h?V-;mHLYDVOwKz7>e4+%AzeO>P6v}ndPW| zM>m#6Tnp7K?0mbK=>gV}=@k*0Mr_PVAgGMu$j+pWxzq4MAa&jpCDU&-5eH27Iz>m^ zax1?*HhG%pJ((tkR(V(O(L%7v7L%!_X->IjS3H5kuXQT2!ow(;%FDE>16&3r){!ex zhf==oJ!}YU89C9@mfDq!P3S4yx$aGB?rbtVH?sHpg?J5C->!_FHM%Hl3#D4eplxzQ zRA+<@LD%LKSkTk2NyWCg7u=$%F#;SIL44~S_OGR}JqX}X+=bc@swpiClB`Zbz|f!4 z7Ysah7OkR8liXfI`}IIwtEoL}(URrGe;IM8%{>b1SsqXh)~w}P>yiFRaE>}rEnNkT z!HXZUtxUp1NmFm)Dm@-{FI^aRQqpSkz}ZSyKR%Y}YHNzBk)ZIp} zMtS=aMvkgWKm9&oTcU0?S|L~CDqA+sHpOxwnswF-fEG)cXCzUR?ps@tZa$=O)=L+5 zf%m58cq8g_o}3?Bhh+c!w4(7AjxwQ3>WnVi<{{38g7yFboo>q|+7qs<$8CPXUFAN< zG&}BHbbyQ5n|qqSr?U~GY{@GJ{(Jny{bMaOG{|IkUj7tj^9pa9|FB_<+KHLxSxR;@ zHpS$4V)PP+tx}22fWx(Ku9y+}Ap;VZqD0AZW4gCDTPCG=zgJmF{|x;(rvdM|2|9a}cex6xrMkERnkE;}jvU-kmzd%_J50$M`lIPCKf+^*zL=@LW`1SaEc%=m zQ+lT06Gw+wVwvQ9fZ~#qd430v2HndFsBa9WjD0P}K(rZYdAt^5WQIvb%D^Q|pkVE^ zte$&#~zmULFACGfS#g=2OLOnIf2Of-k!(BIHjs77nr!5Q1*I9 z1%?=~#Oss!rV~?-6Gm~BWJiA4mJ5TY&iPm_$)H1_rTltuU1F3I(qTQ^U$S>%$l z)Wx1}R?ij0idp@8w-p!Oz{&*W;v*IA;JFHA9%nUvVDy7Q8woheC#|8QuDZb-L_5@R zOqHwrh|mVL9b=+$nJxM`3eE{O$sCt$UK^2@L$R(r^-_+z?lOo+me-VW=Zw z-Bn>$4ovfWd%SPY`ab-u9{INc*k2h+yH%toDHIyqQ zO68=u`N}RIIs7lsn1D){)~%>ByF<>i@qFb<-axvu(Z+6t7v<^z&gm9McRB~BIaDn$ z#xSGT!rzgad8o>~kyj#h1?7g96tOcCJniQ+*#=b7wPio>|6a1Z?_(TS{)KrPe}(8j z!#&A=k(&Pj^F;r)CI=Z{LVu>uj!_W1q4b`N1}E(i%;BWjbEcnD=mv$FL$l?zS6bW!{$7j1GR5ocn94P2u{ z70tAAcpqtQo<@cXw~@i-@6B23;317|l~S>CB?hR5qJ%J3EFgyBdJd^fHZu7AzHF(BQ!tyAz^L0`X z23S4Fe{2X$W0$zu9gm%rg~A>ijaE#GlYlrF9$ds^QtaszE#4M(OLVP2O-;XdT(XIC zatwzF*)1c+t~c{L=fMG8Z=k5lv>U0;C{caN1NItnuSMp)6G3mbahu>E#sj&oy94KC zpH}8oEw{G@N3pvHhp{^-YaZeH;K+T_1AUv;IKD<=mv^&Ueegrb!yf`4VlRl$M?wsl zZyFol(2|_QM`e_2lYSABpKR{{NlxlDSYQNkS;J66aT#MSiTx~;tUmvs-b*CrR4w=f z8+0;*th6kfZ3|5!Icx3RV11sp=?`0Jy3Fs0N4GZQMN=8HmT6%x9@{Dza)k}UwL6JT zHRDh;%!XwXr6yuuy`4;Xsn0zlR$k%r%9abS1;_v?`HX_hI|+EibVnlyE@3aL5vhQq zlIG?tN^w@0(v9M*&L+{_+RQZw=o|&BRPGB>e5=ys7H`nc8nx)|-g;s7mRc7hg{GJC zAe^vCIJhajmm7C6g! zL&!WAQ~5d_5)00?w_*|*H>3$loHrvFbitw#WvLB!JASO?#5Ig5$Ys10n>e4|3d;tS zELJ0|R4n3Az(Fl3-r^QiV_C;)lQ1_CW{5bKS15U|E9?ZgLec@%kXr84>5jV2a5v=w z?pB1GPdxD$IQL4)G||B_lI+A=08MUFFR4MxfGOu07vfIm+j=z9tp~5i_6jb`tR>qV z$#`=BQ*jpCjm$F0+F)L%xRlnS%#&gro6PiRfu^l!EVan|r3y}AHJQOORGx4~ z&<)3=K-tx518DZyp%|!EqpU!+X3Et7n2AaC5(AtrkW>_57i}$eqs$rupubg0a1+WO zGHZKLN2L0D;ab%{_S1Plm|hx8R?O14*w*f&2&bB050n!R2by zw!@XOQx$SqZ5I<(Qu$V6g>o#A!JVwErWv#(Pjx=KeS0@hxr4?13zj#oWwPS(7Ro|v z>Mp@Kmxo79q|}!5qtX2-O@U&&@6s~!I&)1WQIl?lTnh6UdKT_1R640S4~f=_xoN3- zI+O)$R@RjV$F=>Ti7BlnG1-cFKCC(t|Qjm{SalS~V-tX#+2ekRhwmN zZr`8{QF6y~Z!D|{=1*2D-JUa<(1Z=;!Ei!KiRNH?o{p5o3crFF=_pX9O-YyJchr$~ zRC`+G+8kx~fD2k*ZIiiIGR<8r&M@3H?%JVOfE>)})7ScOd&?OjgAGT@WVNSCZ8N(p zuQG~76GE3%(%h1*vUXg$vH{ua0b`sQ4f0*y=u~lgyb^!#CcPJa2mkSEHGLsnO^kb$ zru5_l#nu=Y{rSMWiYx?nO{8I!gH+?wEj~UM?IrG}E|bRIBUM>UlY<`T1EHpRr36vv zBi&dG8oxS|J$!zoaq{+JpJy+O^W(nt*|#g32bd&K^w-t>!Vu9N!k9eA8r!Xc{utY> zg9aZ(D2E0gL#W0MdjwES-7~Wa8iubPrd?8-$C4BP?*wok&O8+ykOx{P=Izx+G~hM8 z*9?BYz!T8~dzcZr#ux8kS7u7r@A#DogBH8km8Ry4slyie^n|GrTbO|cLhpqgMdsjX zJ_LdmM#I&4LqqsOUIXK8gW;V0B(7^$y#h3h>J0k^WJfAMeYek%Y-Dcb_+0zPJez!GM zAmJ1u;*rK=FNM0Nf}Y!!P9c4)HIkMnq^b;JFd!S3?_Qi2G#LIQ)TF|iHl~WKK6JmK zbv7rPE6VkYr_%_BT}CK8h=?%pk@3cz(UrZ{@h40%XgThP*-Oeo`T0eq9 zA8BnWZKzCy5e&&_GEsU4*;_k}(8l_&al5K-V*BFM=O~;MgRkYsOs%9eOY6s6AtE*<7GQAR2ulC3RAJrG_P1iQK5Z~&B z&f8X<>yJV6)oDGIlS$Y*D^Rj(cszTy5c81a5IwBr`BtnC6_e`ArI8CaTX_%rx7;cn zR-0?J_LFg*?(#n~G8cXut(1nVF0Oka$A$1FGcERU<^ggx;p@CZc?3UB41RY+wLS`LWFNSs~YP zuw1@DNN3lTd|jDL7gjBsd9}wIw}4xT2+8dBQzI00m<@?c2L%>}QLfK5%r!a-iII`p zX@`VEUH)uj^$;7jVUYdADQ2k*!1O3WdfgF?OMtUXNpQ1}QINamBTKDuv19^{$`8A1 zeq%q*O0mi@(%sZU>Xdb0Ru96CFqk9-L3pzLVsMQ`Xpa~N6CR{9Rm2)A|CI21L(%GW zh&)Y$BNHa=FD+=mBw3{qTgw)j0b!Eahs!rZnpu)z!!E$*eXE~##yaXz`KE5(nQM`s zD!$vW9XH)iMxu9R>r$VlLk9oIR%HxpUiW=BK@4U)|1WNQ=mz9a z^!KkO=>GaJ!GBXm{KJj^;kh-MkUlEQ%lza`-G&}C5y1>La1sR6hT=d*NeCnuK%_LV zOXt$}iP6(YJKc9j-Fxq~*ItVUqljQ8?oaysB-EYtFQp9oxZ|5m0^Hq(qV!S+hq#g( z?|i*H2MIr^Kxgz+3vIljQ*Feejy6S4v~jKEPTF~Qhq!(ms5>NGtRgO5vfPPc4Z^AM zTj!`5xEreIN)vaNxa|q6qWdg>+T`Ol0Uz)ckXBXEGvPNEL3R8hB3=C5`@=SYgAju1 z!)UBr{2~=~xa{b8>x2@C7weRAEuatC)3pkRhT#pMPTpSbA|tan%U7NGMvzmF?c!V8 z=pEWxbdXbTAGtWTyI?Fml%lEr-^AE}w#l(<7OIw;ctw}imYax&vR4UYNJZK6P7ZOd zP87XfhnUHxCUHhM@b*NbTi#(-8|wcv%3BGNs#zRCVV(W?1Qj6^PPQa<{yaBwZ`+<`w|;rqUY_C z&AeyKwwf*q#OW-F()lir=T^<^wjK65Lif$puuU5+tk$;e_EJ;Lu+pH>=-8=PDhkBg z8cWt%@$Sc#C6F$Vd+0507;{OOyT7Hs%nKS88q-W!$f~9*WGBpHGgNp}=C*7!RiZ5s zn1L_DbKF@B8kwhDiLKRB@lsXVVLK|ph=w%_`#owlf@s@V(pa`GY$8h%;-#h@TsO|Y8V=n@*!Rog7<7Cid%apR|x zOjhHCyfbIt%+*PCveTEcuiDi%Wx;O;+K=W?OFUV%)%~6;gl?<0%)?snDDqIvkHF{ zyI02)+lI9ov42^hL>ZRrh*HhjF9B$A@=H94iaBESBF=eC_KT$8A@uB^6$~o?3Wm5t1OIaqF^~><2?4e3c&)@wKn9bD? zoeCs;H>b8DL^F&>Xw-xjZEUFFTv>JD^O#1E#)CMBaG4DX9bD(Wtc8Rzq}9soQ8`jf zeSnHOL}<+WVSKp4kkq&?SbETjq6yr@4%SAqOG=9E(3YeLG9dtV+8vmzq+6PFPk{L; z(&d++iu=^F%b+ea$i2UeTC{R*0Isk;vFK!no<;L+(`y`3&H-~VTdKROkdyowo1iqR zbVW(3`+(PQ2>TKY>N!jGmGo7oeoB8O|P_!Ic@ zZ^;3dnuXo;WJ?S+)%P>{Hcg!Jz#2SI(s&dY4QAy_vRlmOh)QHvs_7c&zkJCmJGVvV zX;Mtb>QE+xp`KyciG$Cn*0?AK%-a|=o!+7x&&yzHQOS>8=B*R=niSnta^Pxp1`=md z#;$pS$4WCT?mbiCYU?FcHGZ#)kHVJTTBt^%XE(Q};aaO=Zik0UgLcc0I(tUpt(>|& zcxB_|fxCF7>&~5eJ=Dpn&5Aj{A^cV^^}(7w#p;HG&Q)EaN~~EqrE1qKrMAc&WXIE;>@<&)5;gD2?={Xf@Mvn@OJKw=8Mgn z!JUFMwD+s==JpjhroT&d{$kQAy%+d`a*XxDEVxy3`NHzmITrE`o!;5ClXNPb4t*8P zzAivdr{j_v!=9!^?T3y?gzmqDWX6mkzhIzJ-3S{T5bcCFMr&RPDryMcdwbBuZbsgN zGrp@^i?rcfN7v0NKGzDPGE#4yszxu=I_`MI%Z|10nFjU-UjQXXA?k8Pk|OE<(?ae) zE%vG#eZAlj*E7_3dx#Zz4kMLj>H^;}33UAankJiDy5ZvEhrjr`!9eMD8COp}U*hP+ zF}KIYx@pkccIgyxFm#LNw~G&`;o&5)2`5aogs`1~7cMZQ7zj!%L4E`2yzlQN6REX20&O<9 zKV6fyr)TScJPPzNTC2gL+0x#=u>(({{D7j)c-%tvqls3#Y?Z1m zV5WUE)zdJ{$p>yX;^P!UcXP?UD~YM;IRa#Rs5~l+*$&nO(;Ers`G=0D!twR(0GF@c zHl9E5DQI}Oz74n zfKP>&$q0($T4y$6w(p=ERAFh+>n%iaeRA%!T%<^+pg?M)@ucY<&59$x9M#n+V&>}=nO9wCV{O~lg&v#+jcUj(tQ z`0u1YH)-`U$15a{pBkGyPL0THv1P|4e@pf@3IBZS4dVJPo#H>pWq%Lr0YS-SeWash z8R7=jb28KPMI|_lo#GEO|5B?N_e``H*23{~a!AmUJ+fb4HX-%QI@lSEUxKlGV7z7Q zSKw@-TR>@1RL%w{x}dW#k1NgW+q4yt2Xf1J62Bx*O^WG8OJ|FqI4&@d3_o8Id@*)4 zYrk=>@!wv~mh7YWv*bZhxqSmFh2Xq)o=m;%n$I?GSz49l1$xRpPu_^N(vZ>*>Z<04 z2+rP70oM=NDysd!@fQdM2OcyT?3T^Eb@lIC-UG=Bw{BjQ&P`KCv$AcJ;?`vdZ4){d z&gkoUK{$!$$K`3*O-jyM1~p-7T*qb)Ys>Myt^;#1&a%O@x8A+E>! zY8=eD`ZG)LVagDLBeHg>=atOG?Kr%h4B%E6m@J^C+U|y)XX@f z8oyJDW|9g=<#f<{JRr{y#~euMnv)`7j=%cHWLc}ngjq~7k**6%4u>Px&W%4D94(r* z+akunK}O0DC2A%Xo9jyF;DobX?!1I(7%}@7F>i%&nk*LMO)bMGg2N+1iqtg+r(70q zF5{Msgsm5GS7DT`kBsjMvOrkx&|EU!{{~gL4d2MWrAT=KBQ-^zQCUq{5PD1orxlIL zq;CvlWx#f1NWvh`hg011I%?T_s!e38l*lWVt|~z-PO4~~1g)SrJ|>*tXh=QfXT)%( z+ex+inPvD&O4Ur;JGz>$sUOnWdpSLcm1X%aQDw4{dB!cnj`^muI$CJ2%p&-kULVCE z>$eMR36kN$wCPR+OFDM3-U(VOrp9k3)lI&YVFqd;Kpz~K)@Fa&FRw}L(SoD z9B4a+hQzZT-BnVltst&=kq6Y(f^S4hIGNKYBgMxGJ^;2yrO}P3;r)(-I-CZ)26Y6? z&rzHI_1GCvGkgy-t1E;r^3Le30|%$ebDRu2+gdLG)r=A~Qz`}~&L@aGJ{}vVs_GE* zVUjFnzHiXfKQbpv&bR&}l2bzIjAooB)=-XNcYmrGmBh(&iu@o!^hn0^#}m2yZZUK8 zufVm7Gq0y`Mj;9b>`c?&PZkU0j4>IL=UL&-Lp3j&47B5pAW4JceG{!XCA)kT<%2nqCxj<)uy6XR_uws~>_MEKPOpAQ!H zkn>FKh)<9DwwS*|Y(q?$^N!6(51O0 z^JM~Ax{AI1Oj$fs-S5d4T7Z_i1?{%0SsIuQ&r8#(JA=2iLcTN+?>wOL532%&dMYkT z*T5xepC+V6zxhS@vNbMoi|i)=rpli@R9~P!39tWbSSb904ekv7D#quKbgFEMTb48P zuq(VJ+&L8aWU(_FCD$3^uD!YM%O^K(dvy~Wm2hUuh6bD|#(I39Xt>N1Y{ZqXL`Fg6 zKQ?T2htHN!(Bx;tV2bfTtIj7e)liN-29s1kew>v(D^@)#v;}C4-G=7x#;-dM4yRWm zyY`cS21ulzMK{PoaQ6xChEZ}o_#}X-o}<&0)$1#3we?+QeLt;aVCjeA)hn!}UaKt< zat1fHEx13y-rXNMvpUUmCVzocPmN~-Y4(YJvQ#db)4|%B!rBsgAe+*yor~}FrNH08 z3V!97S}D7d$zbSD{$z;@IYMxM6aHdypIuS*pr_U6;#Y!_?0i|&yU*@16l z*dcMqDQgfNBf}?quiu4e>H)yTVfsp#f+Du0@=Kc41QockXkCkvu>FBd6Q+@FL!(Yx z2`YuX#eMEiLEDhp+9uFqME_E^faV&~9qjBHJkIp~%$x^bN=N)K@kvSVEMdDuzA0sn z88CBG?`RX1@#hQNd`o^V{37)!w|nA)QfiYBE^m=yQKv-fQF+UCMcuEe1d4BH7$?>b zJl-r9@0^Ie=)guO1vOd=i$_4sz>y3x^R7n4ED!5oXL3@5**h(xr%Hv)_gILarO46q+MaDOF%ChaymKoI6JU5Pg;7#2n9-18|S1;AK+ zgsn6;k6-%!QD>D?cFy}8F;r@z8H9xN1jsOBw2vQONVqBVEbkiNUqgw~*!^##ht>w0 zUOykwH=$LwX2j&nLy=@{hr)2O&-wm-NyjW7n~Zs9UlH;P7iP3 zI}S(r0YFVYacnKH(+{*)Tbw)@;6>%=&Th=+Z6NHo_tR|JCI8TJiXv2N7ei7M^Q+RM z?9o`meH$5Yi;@9XaNR#jIK^&{N|DYNNbtdb)XW1Lv2k{E>;?F`#Pq|&_;gm~&~Zc9 zf+6ZE%{x4|{YdtE?a^gKyzr}dA>OxQv+pq|@IXL%WS0CiX!V zm$fCePA%lU{%pTKD7|5NJHeXg=I0jL@$tOF@K*MI$)f?om)D63K*M|r`gb9edD1~Y zc|w7N)Y%do7=0{RC|AziW7#am$)9jciRJ?IWl9PE{G3U+$%FcyKs_0Cgq`=K3@ttV z9g;M!3z~f_?P%y3-ph%vBMeS@p7P&Ea8M@97+%XEj*(1E6vHj==d zjsoviB>j^$_^OI_DEPvFkVo(BGRo%cJeD){6Uckei=~1}>sp299|IRjhXe)%?uP0I zF5+>?0#Ye}T^Y$u_rc4=lPcq4K^D(TZG-w30-YiEM=dcK+4#o*>lJ8&JLi+3UcpZk z!^?95S^C0ja^jwP`|{<+3cBVog$(mRdQmadS+Vh~z zS@|P}=|z3P6uS+&@QsMp0no9Od&27O&14zHXGAOEy zh~OKpymK5C%;LLb467@KgIiVwYbYd6wFxI{0-~MOGfTq$nBTB!{SrWmL9Hs}C&l&l#m?s*{tA?BHS4mVKHAVMqm63H<|c5n0~k)-kbg zXidai&9ZUy0~WFYYKT;oe~rytRk?)r8bptITsWj(@HLI;@=v5|XUnSls7$uaxFRL+ zRVMGuL3w}NbV1`^=Pw*0?>bm8+xfeY(1PikW*PB>>Tq(FR`91N0c2&>lL2sZo5=VD zQY{>7dh_TX98L2)n{2OV=T10~*YzX27i2Q7W86M4$?gZIXZaBq#sA*{PH8){|GUi;oM>e?ua7eF4WFuFYZSG| zze?srg|5Ti8Og{O zeFxuw9!U+zhyk?@w zjsA6(oKD=Ka;A>Ca)oPORxK+kxH#O@zhC!!XS4@=swnuMk>t+JmLmFiE^1aX3f<)D@`%K0FGK^gg1a1j>zi z2KhV>sjU7AX3F$SEqrXSC}fRx64GDoc%!u2Yag68Lw@w9v;xOONf@o)Lc|Uh3<21ctTYu-mFZuHk*+R{GjXHIGq3p)tFtQp%TYqD=j1&y)>@zxoxUJ!G@ zgI0XKmP6MNzw>nRxK$-Gbzs}dyfFzt>#5;f6oR27ql!%+{tr+(`(>%51|k`ML} zY4eE)Lxq|JMas(;JibNQds1bUB&r}ydMQXBY4x(^&fY_&LlQC)3hylc$~8&~|06-D z#T+%66rYbHX%^KuqJED_wuGB+=h`nWA!>1n0)3wZrBG3%`b^Ozv6__dNa@%V14|!D zQ?o$z5u0^8`giv%qE!BzZ!3j;BlDlJDk)h@9{nSQeEk!z9RGW) z${RSF3phEM*ce*>Xdp}585vj$|40=&S{S-GTiE?Op*vY&Lvr9}BO$XWy80IF+6@%n z5*2ueT_g@ofP#u5pxb7n*fv^Xtt7&?SRc{*2Ka-*!BuOpf}neHGCiHy$@Ka1^Dint z;DkmIL$-e)rj4o2WQV%Gy;Xg(_Bh#qeOsTM2f@KEe~4kJ8kNLQ+;(!j^bgJMcNhvklP5Z6I+9Fq@c&D~8Fb-4rmDT!MB5QC{Dsb;BharP*O;SF4& zc$wj-7Oep7#$WZN!1nznc@Vb<_Dn%ga-O#J(l=OGB`dy=Sy&$(5-n3zzu%d7E#^8`T@}V+5B;PP8J14#4cCPw-SQTdGa2gWL0*zKM z#DfSXs_iWOMt)0*+Y>Lkd=LlyoHjublNLefhKBv@JoC>P7N1_#> zv=mLWe96%EY;!ZGSQDbZWb#;tzqAGgx~uk+-$+2_8U`!ypbwXl z^2E-FkM1?lY@yt8=J3%QK+xaZ6ok=-y%=KXCD^0r!5vUneW>95PzCkOPO*t}p$;-> ze5j-BLT_;)cZQzR2CEsm@rU7GZfFtdp*a|g4wDr%8?2QkIGasRfDWT-Dvy*U{?IHT z*}wGnzdlSptl#ZF^sf)KT|BJs&kLG91^A6ls{CzFprZ6-Y!V0Xysh%9p%iMd7HLsS zN+^Un$tDV)T@i!v?3o0Fsx2qI(AX_$dDkBzQ@fRM%n zRXk6hb9Py#JXUs+7)w@eo;g%QQ95Yq!K_d=z{0dGS+pToEI6=Bo8+{k$7&Z zo4>PH(`ce8E-Ps&uv`NQ;U$%t;w~|@E3WVOCi~R4oj5wP?%<*1C%}Jq%a^q~T7u>K zML5AKfQDv6>PuT`{SrKHRAF+^&edg6+5R_#H?Lz3iGoWo#PCEd0DS;)2U({{X#zU^ zw_xv{4x7|t!S)>44J;KfA|DC?;uQ($l+5Vp7oeqf7{GBF9356nx|&B~gs+@N^gSdd zvb*>&W)|u#F{Z_b`f#GVtQ`pYv3#||N{xj1NgB<#=Odt6{eB%#9RLt5v zIi|0u70`#ai}9fJjKv7dE!9ZrOIX!3{$z_K5FBd-Kp-&e4(J$LD-)NMTp^_pB`RT; zftVVlK2g@+1Ahv2$D){@Y#cL#dUj9*&%#6 zd2m9{1NYp>)6=oAvqdCn5#cx{AJ%S8skUgMglu2*IAtd+z1>B&`MuEAS(D(<6X#Lj z?f4CFx$)M&$=7*>9v1ER4b6!SIz-m0e{o0BfkySREchp?WdVPpQCh!q$t>?rL!&Jg zd#heM;&~A}VEm8Dvy&P|J*eAV&w!&Nx6HFV&B8jJFVTmgLaswn!cx$&%JbTsloz!3 zMEz1d`k==`Ueub_JAy_&`!ogbwx27^ZXgFNAbx=g_I~5nO^r)}&myw~+yY*cJl4$I znNJ32M&K=0(2Dj_>@39`3=FX!v3nZHno_@q^!y}%(yw0PqOo=);6Y@&ylVe>nMOZ~ zd>j#QQSBn3oaWd;qy$&5(5H$Ayi)0haAYO6TH>FR?rhqHmNOO+(})NB zLI@B@v0)eq!ug`>G<@htRlp3n!EpU|n+G+AvXFrWSUsLMBfL*ZB`CRsIVHNTR&b?K zxBgsN0BjfB>UVcJ|x%=-zb%OV7lmZc& zxiupadZVF7)6QuhoY;;FK2b*qL0J-Rn-8!X4ZY$-ZSUXV5DFd7`T41c(#lAeLMoeT z4%g655v@7AqT!i@)Edt5JMbN(=Q-6{=L4iG8RA%}w;&pKmtWvI4?G9pVRp|RTw`g0 zD5c12B&A2&P6Ng~8WM2eIW=wxd?r7A*N+&!Be7PX3s|7~z=APxm=A?5 zt>xB4WG|*Td@VX{Rs)PV0|yK`oI3^xn(4c_j&vgxk_Y3o(-`_5o`V zRTghg6%l@(qodXN;dB#+OKJEEvhfcnc#BeO2|E(5df-!fKDZ!%9!^BJ_4)9P+9Dq5 zK1=(v?KmIp34r?z{NEWnLB3Px{XYwy-akun4F7xTRr2^zeYW{gcK9)>aJDdU5;w5@ zak=<+-PLH-|04pelTb%ULpuuuJC7DgyT@D|p{!V!0v3KpDnRjANN12q6SUR3mb9<- z>2r~IApQGhstZ!3*?5V z8#)hJ0TdZg0M-BK#nGFP>$i=qk82DO z7h;Ft!D5E15OgW)&%lej*?^1~2=*Z5$2VX>V{x8SC+{i10BbtUk9@I#Vi&hX)q

Q!LwySI{Bnv%Sm)yh{^sSVJ8&h_D-BJ_YZe5eCaAWU9b$O2c z$T|{vWVRtOL!xC0DTc(Qbe`ItNtt5hr<)VijD0{U;T#bUEp381_y`%ZIav?kuYG{iyYdEBPW=*xNSc;Rlt6~F4M`5G+VtOjc z*0qGzCb@gME5udTjJA-9O<&TWd~}ysBd(eVT1-H82-doyH9RST)|+Pb{o*;$j9Tjs zhU!IlsPsj8=(x3bAKJTopW3^6AKROHR^7wZ185wJGVhA~hEc|LP;k7NEz-@4p5o}F z`AD6naG3(n=NF9HTH81=F+Q|JOz$7wm9I<+#BSmB@o_cLt2GkW9|?7mM;r!JZp89l zbo!Hp8=n!XH1{GwaDU+k)pGp`C|cXkCU5%vcH)+v@0eK>%7gWxmuMu9YLlChA|_D@ zi#5zovN_!a-0?~pUV-Rj*1P)KwdU-LguR>YM&*Nen+ln8Q$?WFCJg%DY%K}2!!1FE zDv-A%Cbwo^p(lzac&_TZ-l#9kq`mhLcY3h9ZTUVCM(Ad&=EriQY5{jJv<5K&g|*Lk zgV%ILnf1%8V2B0E&;Sp4sYbYOvvMebLwYwzkRQ#F8GpTQq#uv=J`uaSJ34OWITeSGo6+-8Xw znCk*n{kdDEi)Hi&u^)~cs@iyCkFWB2SWZU|Uc%^43ZIZQ-vWNExCCtDWjqHs;;tWf$v{}0{p0Rvxkq``)*>+Akq%|Na zA`@~-Vfe|+(AIlqru+7Ceh4nsVmO9p9jc8}HX^W&ViBDXT+uXbT#R#idPn&L>+#b6 zflC-4C5-X;kUnR~L>PSLh*gvL68}RBsu#2l`s_9KjUWRhiqF`j)`y`2`YU(>3bdBj z?>iyjEhe-~$^I5!nn%B6Wh+I`FvLNvauve~eX<+Ipl&04 zT}};W&1a3%W?dJ2=N#0t?e+aK+%t}5q%jSLvp3jZ%?&F}nOOWr>+{GFIa%wO_2`et z=JzoRR~}iKuuR+azPI8;Gf9)z3kyA4EIOSl!sRR$DlW}0>&?GbgPojmjmnln;cTqCt=ADbE zZ8GAnoM+S1(5$i8^O4t`ue;vO4i}z0wz-QEIVe5_u03;}-!G1NyY8;h^}y;tzY}i5 zqQr#Ur3Fy8sSa$Q0ys+f`!`+>9WbvU_I`Sj;$4{S>O3?#inLHCrtLy~!s#WXV=oVP zeE93*Nc`PBi4q@%Ao$x4lw9vLHM!6mn3-b_cebF|n-2vt-zYVF_&sDE--J-P;2WHo z+@n2areE0o$LjvjlV2X7ZU@j+`{*8zq`JR3gKF#EW|#+{nMyo-a>nFFTg&vhyT=b} zDa8+v0(Dgx0yRL@ZXOYIlVSZ0|MFizy0VPW8;AfA5|pe!#j zX}Py^8fl5SyS4g1WSKKtnyP+_PoOwMMwu`(i@Z)diJp~U54*-miOchy7Z35eL>^M z4p<-aIxH4VUZgS783@H%M7P9hX>t{|RU7$n4T(brCG#h9e9p! z+o`i;EGGq3&pF;~5V~eBD}lC)>if$w%Vf}AFxGqO88|ApfHf&Bvu+xdG)@vuF}Yvk z)o;~k-%+0K0g+L`Wala!$=ZV|z$e%>f0%XoLib%)!R^RoS+{!#X?h-6uu zF&&KxORdZU&EwQFITIRLo(7TA3W}y6X{?Y%y2j0It!ekU#<)$qghZtpcS>L3uh`Uj z7GY;6f$9qKynP#oS3$$a{p^{D+0oJQ71`1?OAn_m8)UGZmj3l*ZI)`V-a>MKGGFG< z&^jg#Ok%(hhm>hSrZ5;Qga4u(?^i>GiW_j9%_7M>j(^|Om$#{k+^*ULnEgzW_1gCICtAD^WpC`A z{9&DXkG#01Xo)U$OC(L5Y$DQ|Q4C6CjUKk1UkPj$nXH##J{c8e#K|&{mA*;b$r0E4 zUNo0jthwA(c&N1l=PEe8Rw_8cEl|-eya9z&H3#n`B$t#+aJ03RFMzrV@gowbe8v(c zIFM60^0&lCFO10NU4w@|61xiZ4CVXeaKjd;d?sv52XM*lS8XiVjgWpRB;&U_C0g+`6B5V&w|O6B*_q zsATxL!M}+$He)1eOWECce#eS@2n^xhlB4<_Nn?yCVEQWDs(r`|@2GqLe<#(|&P0U? z$7V5IgpWf09uIf_RazRwC?qEqRaHyL?iiS05UiGesJy%^>-C{{ypTBI&B0-iUYhk> zIk<5xpsuV@g|z(AZD+C-;A!fTG=df1=<%nxy(a(IS+U{ME4ZbDEBtcD_3V=icT6*_ z)>|J?>&6%nvHhZERBtjK+s4xnut*@>GAmA5m*OTp$!^CHTr}vM4n(X1Q*;{e-Rd2BCF-u@1ZGm z!S8hJ6L=Gl4T_SDa7Xx|-{4mxveJg=ctf`BJ*fy!yF6Dz&?w(Q_6B}WQVtNI!BVBC zKfX<>7vd6C96}XAQmF-Jd?1Q4eTfRB3q7hCh0f!(JkdWT5<{iAE#dKy*Jxq&3a1@~ z8C||Dn2mFNyrUV|<-)C^_y7@8c2Fz+2jrae9deBDu;U}tJ{^xAdxCD248(k;dCJ%o z`y3sADe>U%suxwwv~8A1+R$VB=Q?%U?4joI$um;aH+eCrBqpn- z%79D_7rb;R-;-9RTrwi9dPlg8&@tfWhhZ(Vx&1PQ+6(huX`;M9x~LrW~~#3{j0Bh2kDU$}@!fFQej4VGkJv?M4rU^x!RU zEwhu$!CA_iDjFjrJa`aocySDX16?~;+wgav;}Zut6Mg%C4>}8FL?8)Kgwc(Qlj{@#2Pt0?G`$h7P#M+qoXtlV@d}%c&OzO+QYKK`kyXaK{U(O^2DyIXCZlNQjt0^8~8JzNGrIxhj}}M z&~QZlbx%t;MJ(Vux;2tgNKGlAqphLq%pd}JG9uoVHUo?|hN{pLQ6Em%r*+7t^<);X zm~6=qChlNAVXNN*Sow->*4;}T;l;D1I-5T{Bif@4_}=>l`tK;qqDdt5zvisCKhMAH z#r}`)7VW?LZqfdmXQ%zo5bJ00{Xb9^YKrk0Nf|oIW*K@(=`o2Vndz}ZDyk{!u}PVx zzd--+_WC*U{~DH3{?GI64IB+@On&@9X>EUAo&L+G{L^dozaI4C3G#2wr~hseW@K&g zKWs{uHu-9Je!3;4pE>eBltKUXb^*hG8I&413)$J&{D4N%7PcloU6bn%jPxJyQL?g* z9g+YFFEDiE`8rW^laCNzQmi7CTnPfwyg3VDHRAl>h=In6jeaVOP@!-CP60j3+#vpL zEYmh_oP0{-gTe7Or`L6x)6w?77QVi~jD8lWN@3RHcm80iV%M1A!+Y6iHM)05iC64tb$X2lV_%Txk@0l^hZqi^%Z?#- zE;LE0uFx)R08_S-#(wC=dS&}vj6P4>5ZWjhthP=*Hht&TdLtKDR;rXEX4*z0h74FA zMCINqrh3Vq;s%3MC1YL`{WjIAPkVL#3rj^9Pj9Ss7>7duy!9H0vYF%>1jh)EPqvlr6h%R%CxDsk| z!BACz7E%j?bm=pH6Eaw{+suniuY7C9Ut~1cWfOX9KW9=H><&kQlinPV3h9R>3nJvK z4L9(DRM=x;R&d#a@oFY7mB|m8h4692U5eYfcw|QKwqRsshN(q^v$4$)HgPpAJDJ`I zkqjq(8Cd!K!+wCd=d@w%~e$=gdUgD&wj$LQ1r>-E=O@c ze+Z$x{>6(JA-fNVr)X;*)40Eym1TtUZI1Pwwx1hUi+G1Jlk~vCYeXMNYtr)1?qwyg zsX_e*$h?380O00ou?0R@7-Fc59o$UvyVs4cUbujHUA>sH!}L54>`e` zHUx#Q+Hn&Og#YVOuo*niy*GU3rH;%f``nk#NN5-xrZ34NeH$l`4@t);4(+0|Z#I>Y z)~Kzs#exIAaf--65L0UHT_SvV8O2WYeD>Mq^Y6L!Xu8%vnpofG@w!}R7M28?i1*T&zp3X4^OMCY6(Dg<-! zXmcGQrRgHXGYre7GfTJ)rhl|rs%abKT_Nt24_Q``XH{88NVPW+`x4ZdrMuO0iZ0g` z%p}y};~T5gbb9SeL8BSc`SO#ixC$@QhXxZ=B}L`tP}&k?1oSPS=4%{UOHe0<_XWln zwbl5cn(j-qK`)vGHY5B5C|QZd5)W7c@{bNVXqJ!!n$^ufc?N9C-BF2QK1(kv++h!>$QbAjq)_b$$PcJdV+F7hz0Hu@ zqj+}m0qn{t^tD3DfBb~0B36|Q`bs*xs|$i^G4uNUEBl4g;op-;Wl~iThgga?+dL7s zUP(8lMO?g{GcYpDS{NM!UA8Hco?#}eNEioRBHy4`mq!Pd-9@-97|k$hpEX>xoX+dY zDr$wfm^P&}Wu{!%?)U_(%Mn79$(ywvu*kJ9r4u|MyYLI_67U7%6Gd_vb##Nerf@>& z8W11z$$~xEZt$dPG}+*IZky+os5Ju2eRi;1=rUEeIn>t-AzC_IGM-IXWK3^6QNU+2pe=MBn4I*R@A%-iLDCOHTE-O^wo$sL_h{dcPl=^muAQb`_BRm};=cy{qSkui;`WSsj9%c^+bIDQ z0`_?KX0<-=o!t{u(Ln)v>%VGL z0pC=GB7*AQ?N7N{ut*a%MH-tdtNmNC+Yf$|KS)BW(gQJ*z$d{+{j?(e&hgTy^2|AR9vx1Xre2fagGv0YXWqtNkg*v%40v?BJBt|f9wX5 z{QTlCM}b-0{mV?IG>TW_BdviUKhtosrBqdfq&Frdz>cF~yK{P@(w{Vr7z2qKFwLhc zQuogKO@~YwyS9%+d-zD7mJG~@?EFJLSn!a&mhE5$_4xBl&6QHMzL?CdzEnC~C3$X@ zvY!{_GR06ep5;<#cKCSJ%srxX=+pn?ywDwtJ2{TV;0DKBO2t++B(tIO4)Wh`rD13P z4fE$#%zkd=UzOB74gi=-*CuID&Z3zI^-`4U^S?dHxK8fP*;fE|a(KYMgMUo`THIS1f!*6dOI2 zFjC3O=-AL`6=9pp;`CYPTdVX z8(*?V&%QoipuH0>WKlL8A*zTKckD!paN@~hh zmXzm~qZhMGVdQGd=AG8&20HW0RGV8X{$9LldFZYm zE?}`Q3i?xJRz43S?VFMmqRyvWaS#(~Lempg9nTM$EFDP(Gzx#$r)W&lpFKqcAoJh-AxEw$-bjW>`_+gEi z2w`99#UbFZGiQjS8kj~@PGqpsPX`T{YOj`CaEqTFag;$jY z8_{Wzz>HXx&G*Dx<5skhpETxIdhKH?DtY@b9l8$l?UkM#J-Snmts7bd7xayKTFJ(u zyAT&@6cAYcs{PBfpqZa%sxhJ5nSZBPji?Zlf&}#L?t)vC4X5VLp%~fz2Sx<*oN<7` z?ge=k<=X7r<~F7Tvp9#HB{!mA!QWBOf%EiSJ6KIF8QZNjg&x~-%e*tflL(ji_S^sO ztmib1rp09uon}RcsFi#k)oLs@$?vs(i>5k3YN%$T(5Or(TZ5JW9mA6mIMD08=749$ z!d+l*iu{Il7^Yu}H;lgw=En1sJpCKPSqTCHy4(f&NPelr31^*l%KHq^QE>z>Ks_bH zjbD?({~8Din7IvZeJ>8Ey=e;I?thpzD=zE5UHeO|neioJwG;IyLk?xOz(yO&0DTU~ z^#)xcs|s>Flgmp;SmYJ4g(|HMu3v7#;c*Aa8iF#UZo7CvDq4>8#qLJ|YdZ!AsH%^_7N1IQjCro

K7UpUK$>l@ zw`1S}(D?mUXu_C{wupRS-jiX~w=Uqqhf|Vb3Cm9L=T+w91Cu^ z*&Ty%sN?x*h~mJc4g~k{xD4ZmF%FXZNC;oVDwLZ_WvrnzY|{v8hc1nmx4^}Z;yriXsAf+Lp+OFLbR!&Ox?xABwl zu8w&|5pCxmu#$?Cv2_-Vghl2LZ6m7}VLEfR5o2Ou$x02uA-%QB2$c(c1rH3R9hesc zfpn#oqpbKuVsdfV#cv@5pV4^f_!WS+F>SV6N0JQ9E!T90EX((_{bSSFv9ld%I0&}9 zH&Jd4MEX1e0iqDtq~h?DBrxQX1iI0lIs<|kB$Yrh&cpeK0-^K%=FBsCBT46@h#yi!AyDq1V(#V}^;{{V*@T4WJ&U-NTq43w=|K>z8%pr_nC>%C(Wa_l78Ufib$r8Od)IIN=u>417 z`Hl{9A$mI5A(;+-Q&$F&h-@;NR>Z<2U;Y21>>Z;s@0V@SbkMQQj%_;~+qTuQ?c|AV zcWm3XZQHhP&R%QWarS%mJ!9R^&!_)*s(v+VR@I#QrAT}`17Y+l<`b-nvmDNW`De%y zrwTZ9EJrj1AFA>B`1jYDow}~*dfPs}IZMO3=a{Fy#IOILc8F0;JS4x(k-NSpbN@qM z`@aE_e}5{!$v3+qVs7u?sOV(y@1Os*Fgu`fCW9=G@F_#VQ%xf$hj0~wnnP0$hFI+@ zkQj~v#V>xn)u??YutKsX>pxKCl^p!C-o?+9;!Nug^ z{rP!|+KsP5%uF;ZCa5F;O^9TGac=M|=V z_H(PfkV1rz4jl?gJ(ArXMyWT4y(86d3`$iI4^l9`vLdZkzpznSd5Ikfrs8qcSy&>z zTIZgWZGXw0n9ibQxYWE@gI0(3#KA-dAdPcsL_|hg2@~C!VZDM}5;v_Nykfq!*@*Zf zE_wVgx82GMDryKO{U{D>vSzSc%B~|cjDQrt5BN=Ugpsf8H8f1lR4SGo#hCuXPL;QQ z#~b?C4MoepT3X`qdW2dNn& zo8)K}%Lpu>0tQei+{>*VGErz|qjbK#9 zvtd8rcHplw%YyQCKR{kyo6fgg!)6tHUYT(L>B7er5)41iG`j$qe*kSh$fY!PehLcD zWeKZHn<492B34*JUQh=CY1R~jT9Jt=k=jCU2=SL&&y5QI2uAG2?L8qd2U(^AW#{(x zThSy=C#>k+QMo^7caQcpU?Qn}j-`s?1vXuzG#j8(A+RUAY})F@=r&F(8nI&HspAy4 z4>(M>hI9c7?DCW8rw6|23?qQMSq?*Vx?v30U%luBo)B-k2mkL)Ljk5xUha3pK>EEj z@(;tH|M@xkuN?gsz;*bygizwYR!6=(Xgcg^>WlGtRYCozY<rFX2E>kaZo)O<^J7a`MX8Pf`gBd4vrtD|qKn&B)C&wp0O-x*@-|m*0egT=-t@%dD zgP2D+#WPptnc;_ugD6%zN}Z+X4=c61XNLb7L1gWd8;NHrBXwJ7s0ce#lWnnFUMTR& z1_R9Fin4!d17d4jpKcfh?MKRxxQk$@)*hradH2$3)nyXep5Z;B z?yX+-Bd=TqO2!11?MDtG0n(*T^!CIiF@ZQymqq1wPM_X$Iu9-P=^}v7npvvPBu!d$ z7K?@CsA8H38+zjA@{;{kG)#AHME>Ix<711_iQ@WWMObXyVO)a&^qE1GqpP47Q|_AG zP`(AD&r!V^MXQ^e+*n5~Lp9!B+#y3#f8J^5!iC@3Y@P`;FoUH{G*pj*q7MVV)29+j z>BC`a|1@U_v%%o9VH_HsSnM`jZ-&CDvbiqDg)tQEnV>b%Ptm)T|1?TrpIl)Y$LnG_ zzKi5j2Fx^K^PG1=*?GhK;$(UCF-tM~^=Z*+Wp{FSuy7iHt9#4n(sUuHK??@v+6*|10Csdnyg9hAsC5_OrSL;jVkLlf zHXIPukLqbhs~-*oa^gqgvtpgTk_7GypwH><53riYYL*M=Q@F-yEPLqQ&1Sc zZB%w}T~RO|#jFjMWcKMZccxm-SL)s_ig?OC?y_~gLFj{n8D$J_Kw%{r0oB8?@dWzn zB528d-wUBQzrrSSLq?fR!K%59Zv9J4yCQhhDGwhptpA5O5U?Hjqt>8nOD zi{)0CI|&Gu%zunGI*XFZh(ix)q${jT8wnnzbBMPYVJc4HX*9d^mz|21$=R$J$(y7V zo0dxdbX3N#=F$zjstTf*t8vL)2*{XH!+<2IJ1VVFa67|{?LP&P41h$2i2;?N~RA30LV`BsUcj zfO9#Pg1$t}7zpv#&)8`mis3~o+P(DxOMgz-V*(?wWaxi?R=NhtW}<#^Z?(BhSwyar zG|A#Q7wh4OfK<|DAcl9THc-W4*>J4nTevsD%dkj`U~wSUCh15?_N@uMdF^Kw+{agk zJ`im^wDqj`Ev)W3k3stasP`88-M0ZBs7;B6{-tSm3>I@_e-QfT?7|n0D~0RRqDb^G zyHb=is;IwuQ&ITzL4KsP@Z`b$d%B0Wuhioo1CWttW8yhsER1ZUZzA{F*K=wmi-sb#Ju+j z-l@In^IKnb{bQG}Ps>+Vu_W#grNKNGto+yjA)?>0?~X`4I3T@5G1)RqGUZuP^NJCq&^HykuYtMDD8qq+l8RcZNJsvN(10{ zQ1$XcGt}QH-U^WU!-wRR1d--{B$%vY{JLWIV%P4-KQuxxDeJaF#{eu&&r!3Qu{w}0f--8^H|KwE>)ORrcR+2Qf zb})DRcH>k0zWK8@{RX}NYvTF;E~phK{+F;MkIP$)T$93Ba2R2TvKc>`D??#mv9wg$ zd~|-`Qx5LwwsZ2hb*Rt4S9dsF%Cny5<1fscy~)d;0m2r$f=83<->c~!GNyb!U)PA; zq^!`@@)UaG)Ew(9V?5ZBq#c%dCWZrplmuM`o~TyHjAIMh0*#1{B>K4po-dx$Tk-Cq z=WZDkP5x2W&Os`N8KiYHRH#UY*n|nvd(U>yO=MFI-2BEp?x@=N<~CbLJBf6P)}vLS?xJXYJ2^<3KJUdrwKnJnTp{ zjIi|R=L7rn9b*D#Xxr4*R<3T5AuOS+#U8hNlfo&^9JO{VbH!v9^JbK=TCGR-5EWR@ zN8T-_I|&@A}(hKeL4_*eb!1G8p~&_Im8|wc>Cdir+gg90n1dw?QaXcx6Op_W1r=axRw>4;rM*UOpT#Eb9xU1IiWo@h?|5uP zka>-XW0Ikp@dIe;MN8B01a7+5V@h3WN{J=HJ*pe0uwQ3S&MyWFni47X32Q7SyCTNQ z+sR!_9IZa5!>f&V$`q!%H8ci!a|RMx5}5MA_kr+bhtQy{-^)(hCVa@I!^TV4RBi zAFa!Nsi3y37I5EK;0cqu|9MRj<^r&h1lF}u0KpKQD^5Y+LvFEwM zLU@@v4_Na#Axy6tn3P%sD^5P#<7F;sd$f4a7LBMk zGU^RZHBcxSA%kCx*eH&wgA?Qwazm8>9SCSz_!;MqY-QX<1@p$*T8lc?@`ikEqJ>#w zcG``^CoFMAhdEXT9qt47g0IZkaU)4R7wkGs^Ax}usqJ5HfDYAV$!=6?>J6+Ha1I<5 z|6=9soU4>E))tW$<#>F ziZ$6>KJf0bPfbx_)7-}tMINlc=}|H+$uX)mhC6-Hz+XZxsKd^b?RFB6et}O#+>Wmw9Ec9) z{q}XFWp{3@qmyK*Jvzpyqv57LIR;hPXKsrh{G?&dRjF%Zt5&m20Ll?OyfUYC3WRn{cgQ?^V~UAv+5 z&_m#&nIwffgX1*Z2#5^Kl4DbE#NrD&Hi4|7SPqZ}(>_+JMz=s|k77aEL}<=0Zfb)a z%F(*L3zCA<=xO)2U3B|pcTqDbBoFp>QyAEU(jMu8(jLA61-H!ucI804+B!$E^cQQa z)_ERrW3g!B9iLb3nn3dlkvD7KsY?sRvls3QC0qPi>o<)GHx%4Xb$5a3GBTJ(k@`e@ z$RUa^%S15^1oLEmA=sayrP5;9qtf!Z1*?e$ORVPsXpL{jL<6E)0sj&swP3}NPmR%FM?O>SQgN5XfHE< zo(4#Cv11(%Nnw_{_Ro}r6=gKd{k?NebJ~<~Kv0r(r0qe4n3LFx$5%x(BKvrz$m?LG zjLIc;hbj0FMdb9aH9Lpsof#yG$(0sG2%RL;d(n>;#jb!R_+dad+K;Ccw!|RY?uS(a zj~?=&M!4C(5LnlH6k%aYvz@7?xRa^2gml%vn&eKl$R_lJ+e|xsNfXzr#xuh(>`}9g zLHSyiFwK^-p!;p$yt7$F|3*IfO3Mlu9e>Dpx8O`37?fA`cj`C0B-m9uRhJjs^mRp# zWB;Aj6|G^1V6`jg7#7V9UFvnB4((nIwG?k%c7h`?0tS8J3Bn0t#pb#SA}N-|45$-j z$R>%7cc2ebAClXc(&0UtHX<>pd)akR3Kx_cK+n<}FhzmTx!8e9^u2e4%x{>T6pQ`6 zO182bh$-W5A3^wos0SV_TgPmF4WUP-+D25KjbC{y_6W_9I2_vNKwU(^qSdn&>^=*t z&uvp*@c8#2*paD!ZMCi3;K{Na;I4Q35zw$YrW5U@Kk~)&rw;G?d7Q&c9|x<Hg|CNMsxovmfth*|E*GHezPTWa^Hd^F4!B3sF;)? z(NaPyAhocu1jUe(!5Cy|dh|W2=!@fNmuNOzxi^tE_jAtzNJ0JR-avc_H|ve#KO}#S z#a(8secu|^Tx553d4r@3#6^MHbH)vmiBpn0X^29xEv!Vuh1n(Sr5I0V&`jA2;WS|Y zbf0e}X|)wA-Pf5gBZ>r4YX3Mav1kKY(ulAJ0Q*jB)YhviHK)w!TJsi3^dMa$L@^{` z_De`fF4;M87vM3Ph9SzCoCi$#Fsd38u!^0#*sPful^p5oI(xGU?yeYjn;Hq1!wzFk zG&2w}W3`AX4bxoVm03y>ts{KaDf!}b&7$(P4KAMP=vK5?1In^-YYNtx1f#}+2QK@h zeSeAI@E6Z8a?)>sZ`fbq9_snl6LCu6g>o)rO;ijp3|$vig+4t} zylEo7$SEW<_U+qgVcaVhk+4k+C9THI5V10qV*dOV6pPtAI$)QN{!JRBKh-D zk2^{j@bZ}yqW?<#VVuI_27*cI-V~sJiqQv&m07+10XF+#ZnIJdr8t`9s_EE;T2V;B z4UnQUH9EdX%zwh-5&wflY#ve!IWt0UE-My3?L#^Bh%kcgP1q{&26eXLn zTkjJ*w+(|_>Pq0v8{%nX$QZbf)tbJaLY$03;MO=Ic-uqYUmUCuXD>J>o6BCRF=xa% z3R4SK9#t1!K4I_d>tZgE>&+kZ?Q}1qo4&h%U$GfY058s%*=!kac{0Z+4Hwm!)pFLR zJ+5*OpgWUrm0FPI2ib4NPJ+Sk07j(`diti^i#kh&f}i>P4~|d?RFb#!JN)~D@)beox}bw?4VCf^y*`2{4`-@%SFTry2h z>9VBc9#JxEs1+0i2^LR@B1J`B9Ac=#FW=(?2;5;#U$0E0UNag_!jY$&2diQk_n)bT zl5Me_SUvqUjwCqmVcyb`igygB_4YUB*m$h5oeKv3uIF0sk}~es!{D>4r%PC*F~FN3owq5e0|YeUTSG#Vq%&Gk7uwW z0lDo#_wvflqHeRm*}l?}o;EILszBt|EW*zNPmq#?4A+&i0xx^?9obLyY4xx=Y9&^G;xYXYPxG)DOpPg!i_Ccl#3L}6xAAZzNhPK1XaC_~ z!A|mlo?Be*8Nn=a+FhgpOj@G7yYs(Qk(8&|h@_>w8Y^r&5nCqe0V60rRz?b5%J;GYeBqSAjo|K692GxD4` zRZyM2FdI+-jK2}WAZTZ()w_)V{n5tEb@>+JYluDozCb$fA4H)$bzg(Ux{*hXurjO^ zwAxc+UXu=&JV*E59}h3kzQPG4M)X8E*}#_&}w*KEgtX)cU{vm9b$atHa;s>| z+L6&cn8xUL*OSjx4YGjf6{Eq+Q3{!ZyhrL&^6Vz@jGbI%cAM9GkmFlamTbcQGvOlL zmJ?(FI)c86=JEs|*;?h~o)88>12nXlpMR4@yh%qdwFNpct;vMlc=;{FSo*apJ;p}! zAX~t;3tb~VuP|ZW;z$=IHf->F@Ml)&-&Bnb{iQyE#;GZ@C$PzEf6~q}4D>9jic@mTO5x76ulDz@+XAcm35!VSu zT*Gs>;f0b2TNpjU_BjHZ&S6Sqk6V1370+!eppV2H+FY!q*n=GHQ!9Rn6MjY!Jc77A zG7Y!lFp8?TIHN!LXO?gCnsYM-gQxsm=Ek**VmZu7vnuufD7K~GIxfxbsQ@qv2T zPa`tvHB$fFCyZl>3oYg?_wW)C>^_iDOc^B7klnTOoytQH18WkOk)L2BSD0r%xgRSW zQS9elF^?O=_@|58zKLK;(f77l-Zzu}4{fXed2saq!5k#UZAoDBqYQS{sn@j@Vtp|$ zG%gnZ$U|9@u#w1@11Sjl8ze^Co=)7yS(}=;68a3~g;NDe_X^}yJj;~s8xq9ahQ5_r zxAlTMnep*)w1e(TG%tWsjo3RR;yVGPEO4V{Zp?=a_0R#=V^ioQu4YL=BO4r0$$XTX zZfnw#_$V}sDAIDrezGQ+h?q24St0QNug_?{s-pI(^jg`#JRxM1YBV;a@@JQvH8*>> zIJvku74E0NlXkYe_624>znU0J@L<-c=G#F3k4A_)*;ky!C(^uZfj%WB3-*{*B$?9+ zDm$WFp=0(xnt6`vDQV3Jl5f&R(Mp};;q8d3I%Kn>Kx=^;uSVCw0L=gw53%Bp==8Sw zxtx=cs!^-_+i{2OK`Q;913+AXc_&Z5$@z3<)So0CU3;JAv=H?@Zpi~riQ{z-zLtVL z!oF<}@IgJp)Iyz1zVJ42!SPHSkjYNS4%ulVVIXdRuiZ@5Mx8LJS}J#qD^Zi_xQ@>DKDr-_e#>5h3dtje*NcwH_h;i{Sx7}dkdpuW z(yUCjckQsagv*QGMSi9u1`Z|V^}Wjf7B@q%j2DQXyd0nOyqg%m{CK_lAoKlJ7#8M} z%IvR?Vh$6aDWK2W!=i?*<77q&B8O&3?zP(Cs@kapc)&p7En?J;t-TX9abGT#H?TW? ztO5(lPKRuC7fs}zwcUKbRh=7E8wzTsa#Z{a`WR}?UZ%!HohN}d&xJ=JQhpO1PI#>X zHkb>pW04pU%Bj_mf~U}1F1=wxdBZu1790>3Dm44bQ#F=T4V3&HlOLsGH)+AK$cHk6 zia$=$kog?)07HCL*PI6}DRhpM^*%I*kHM<#1Se+AQ!!xyhcy6j7`iDX7Z-2i73_n# zas*?7LkxS-XSqv;YBa zW_n*32D(HTYQ0$feV_Fru1ZxW0g&iwqixPX3=9t4o)o|kOo79V$?$uh?#8Q8e>4e)V6;_(x&ViUVxma+i25qea;d-oK7ouuDsB^ab{ zu1qjQ%`n56VtxBE#0qAzb7lph`Eb-}TYpXB!H-}3Ykqyp`otprp7{VEuW*^IR2n$Fb99*nAtqT&oOFIf z@w*6>YvOGw@Ja?Pp1=whZqydzx@9X4n^2!n83C5{C?G@|E?&$?p*g68)kNvUTJ)I6 z1Q|(#UuP6pj78GUxq11m-GSszc+)X{C2eo-?8ud9sB=3(D47v?`JAa{V(IF zPZQ_0AY*9M97>Jf<o%#O_%Wq}8>YM=q0|tGY+hlXcpE=Z4Od z`NT7Hu2hnvRoqOw@g1f=bv`+nba{GwA$Ak0INlqI1k<9!x_!sL()h?hEWoWrdU3w` zZ%%)VR+Bc@_v!C#koM1p-3v_^L6)_Ktj4HE>aUh%2XZE@JFMOn)J~c`_7VWNb9c-N z2b|SZMR4Z@E7j&q&9(6H3yjEu6HV7{2!1t0lgizD;mZ9$r(r7W5G$ky@w(T_dFnOD z*p#+z$@pKE+>o@%eT(2-p_C}wbQ5s(%Sn_{$HDN@MB+Ev?t@3dPy`%TZ!z}AThZSu zN<1i$siJhXFdjV zP*y|V<`V8t=h#XTRUR~5`c`Z9^-`*BZf?WAehGdg)E2Je)hqFa!k{V(u+(hTf^Yq& zoruUh2(^3pe)2{bvt4&4Y9CY3js)PUHtd4rVG57}uFJL)D(JfSIo^{P=7liFXG zq5yqgof0V8paQcP!gy+;^pp-DA5pj=gbMN0eW=-eY+N8~y+G>t+x}oa!5r>tW$xhI zPQSv=pi;~653Gvf6~*JcQ%t1xOrH2l3Zy@8AoJ+wz@daW@m7?%LXkr!bw9GY@ns3e zSfuWF_gkWnesv?s3I`@}NgE2xwgs&rj?kH-FEy82=O8`+szN ziHch`vvS`zNfap14!&#i9H@wF7}yIPm=UB%(o(}F{wsZ(wA0nJ2aD^@B41>>o-_U6 zUqD~vdo48S8~FTb^+%#zcbQiiYoDKYcj&$#^;Smmb+Ljp(L=1Kt_J!;0s%1|JK}Wi z;={~oL!foo5n8=}rs6MmUW~R&;SIJO3TL4Ky?kh+b2rT9B1Jl4>#Uh-Bec z`Hsp<==#UEW6pGPhNk8H!!DUQR~#F9jEMI6T*OWfN^Ze&X(4nV$wa8QUJ>oTkruH# zm~O<`J7Wxseo@FqaZMl#Y(mrFW9AHM9Kb|XBMqaZ2a)DvJgYipkDD_VUF_PKd~dT7 z#02}bBfPn9a!X!O#83=lbJSK#E}K&yx-HI#T6ua)6o0{|={*HFusCkHzs|Fn&|C3H zBck1cmfcWVUN&i>X$YU^Sn6k2H;r3zuXbJFz)r5~3$d$tUj(l1?o={MM){kjgqXRO zc5R*#{;V7AQh|G|)jLM@wGAK&rm2~@{Pewv#06pHbKn#wL0P6F1!^qw9g&cW3Z=9} zj)POhOlwsh@eF=>z?#sIs*C-Nl(yU!#DaiaxhEs#iJqQ8w%(?+6lU02MYSeDkr!B- zPjMv+on6OLXgGnAtl(ao>|X2Y8*Hb}GRW5}-IzXnoo-d0!m4Vy$GS!XOLy>3_+UGs z2D|YcQx@M#M|}TDOetGi{9lGo9m-=0-^+nKE^*?$^uHkxZh}I{#UTQd;X!L+W@jm( zDg@N4+lUqI92o_rNk{3P>1gxAL=&O;x)ZT=q1mk0kLlE$WeWuY_$0`0jY-Kkt zP*|m3AF}Ubd=`<>(Xg0har*_@x2YH}bn0Wk*OZz3*e5;Zc;2uBdnl8?&XjupbkOeNZsNh6pvsq_ydmJI+*z**{I{0K)-;p1~k8cpJXL$^t!-`E}=*4G^-E8>H!LjTPxSx zcF+cS`ommfKMhNSbas^@YbTpH1*RFrBuATUR zt{oFWSk^$xU&kbFQ;MCX22RAN5F6eq9UfR$ut`Jw--p2YX)A*J69m^!oYfj2y7NYcH6&r+0~_sH^c^nzeN1AU4Ga7=FlR{S|Mm~MpzY0$Z+p2W(a={b-pR9EO1Rs zB%KY|@wLcAA@)KXi!d2_BxrkhDn`DT1=Dec}V!okd{$+wK z4E{n8R*xKyci1(CnNdhf$Dp2(Jpof0-0%-38X=Dd9PQgT+w%Lshx9+loPS~MOm%ZT zt%2B2iL_KU_ita%N>xjB!#71_3=3c}o zgeW~^U_ZTJQ2!PqXulQd=3b=XOQhwATK$y(9$#1jOQ4}4?~l#&nek)H(04f(Sr=s| zWv7Lu1=%WGk4FSw^;;!8&YPM)pQDCY9DhU`hMty1@sq1=Tj7bFsOOBZOFlpR`W>-J$-(kezWJj;`?x-v>ev{*8V z8p|KXJPV$HyQr1A(9LVrM47u-XpcrIyO`yWvx1pVYc&?154aneRpLqgx)EMvRaa#|9?Wwqs2+W8n5~79G z(}iCiLk;?enn}ew`HzhG+tu+Ru@T+K5juvZN)wY;x6HjvqD!&!)$$;1VAh~7fg0K| zEha#aN=Yv|3^~YFH}cc38ovVb%L|g@9W6fo(JtT6$fa?zf@Ct88e}m?i)b*Jgc{fl zExfdvw-BYDmH6>(4QMt#p0;FUIQqkhD}aH?a7)_%JtA~soqj{ppP_82yi9kaxuK>~ ze_)Zt>1?q=ZH*kF{1iq9sr*tVuy=u>Zev}!gEZx@O6-fjyu9X00gpIl-fS_pzjpqJ z1yqBmf9NF!jaF<+YxgH6oXBdK)sH(>VZ)1siyA$P<#KDt;8NT*l_0{xit~5j1P)FN zI8hhYKhQ)i z37^aP13B~u65?sg+_@2Kr^iWHN=U;EDSZ@2W2!5ALhGNWXnFBY%7W?1 z=HI9JzQ-pLKZDYTv<0-lt|6c-RwhxZ)mU2Os{bsX_i^@*fKUj8*aDO5pks=qn3Dv6 zwggpKLuyRCTVPwmw1r}B#AS}?X7b837UlXwp~E2|PJw2SGVueL7){Y&z!jL!XN=0i zU^Eig`S2`{+gU$68aRdWx?BZ{sU_f=8sn~>s~M?GU~`fH5kCc; z8ICp+INM3(3{#k32RZdv6b9MQYdZXNuk7ed8;G?S2nT+NZBG=Tar^KFl2SvhW$bGW#kdWL-I)s_IqVnCDDM9fm8g;P;8 z7t4yZn3^*NQfx7SwmkzP$=fwdC}bafQSEF@pd&P8@H#`swGy_rz;Z?Ty5mkS%>m#% zp_!m9e<()sfKiY(nF<1zBz&&`ZlJf6QLvLhl`_``%RW&{+O>Xhp;lwSsyRqGf=RWd zpftiR`={2(siiPAS|p}@q=NhVc0ELprt%=fMXO3B)4ryC2LT(o=sLM7hJC!}T1@)E zA3^J$3&1*M6Xq>03FX`R&w*NkrZE?FwU+Muut;>qNhj@bX17ZJxnOlPSZ=Zeiz~T_ zOu#yc3t6ONHB;?|r4w+pI)~KGN;HOGC)txxiUN8#mexj+W(cz%9a4sx|IRG=}ia zuEBuba3AHsV2feqw-3MvuL`I+2|`Ud4~7ZkN=JZ;L20|Oxna5vx1qbIh#k2O4$RQF zo`tL()zxaqibg^GbB+BS5#U{@K;WWQj~GcB1zb}zJkPwH|5hZ9iH2308!>_;%msji zJHSL~s)YHBR=Koa1mLEOHos*`gp=s8KA-C zu0aE+W!#iJ*0xqKm3A`fUGy#O+X+5W36myS>Uh2!R*s$aCU^`K&KKLCCDkejX2p=5 z%o7-fl03x`gaSNyr?3_JLv?2RLS3F*8ub>Jd@^Cc17)v8vYEK4aqo?OS@W9mt%ITJ z9=S2%R8M){CugT@k~~0x`}Vl!svYqX=E)c_oU6o}#Hb^%G1l3BudxA{F*tbjG;W_>=xV73pKY53v%>I)@D36I_@&p$h|Aw zonQS`07z_F#@T-%@-Tb|)7;;anoD_WH>9ewFy(ZcEOM$#Y)8>qi7rCnsH9GO-_7zF zu*C87{Df1P4TEOsnzZ@H%&lvV(3V@;Q!%+OYRp`g05PjY^gL$^$-t0Y>H*CDDs?FZly*oZ&dxvsxaUWF!{em4{A>n@vpXg$dwvt@_rgmHF z-MER`ABa8R-t_H*kv>}CzOpz;!>p^^9ztHMsHL|SRnS<-y5Z*r(_}c4=fXF`l^-i}>e7v!qs_jv zqvWhX^F=2sDNWA9c@P0?lUlr6ecrTKM%pNQ^?*Lq?p-0~?_j50xV%^(+H>sMul#Tw zeciF*1=?a7cI(}352%>LO96pD+?9!fNyl^9v3^v&Y4L)mNGK0FN43&Xf8jUlxW1Bw zyiu2;qW-aGNhs=zbuoxnxiwZ3{PFZM#Kw)9H@(hgX23h(`Wm~m4&TvoZoYp{plb^> z_#?vXcxd>r7K+1HKJvhed>gtK`TAbJUazUWQY6T~t2af%#<+Veyr%7-#*A#@&*;@g58{i|E%6yC_InGXCOd{L0;$)z#?n7M`re zh!kO{6=>7I?*}czyF7_frt#)s1CFJ_XE&VrDA?Dp3XbvF{qsEJgb&OLSNz_5g?HpK z9)8rsr4JN!Af3G9!#Qn(6zaUDqLN(g2g8*M)Djap?WMK9NKlkC)E2|-g|#-rp%!Gz zAHd%`iq|81efi93m3yTBw3g0j#;Yb2X{mhRAI?&KDmbGqou(2xiRNb^sV}%%Wu0?< z?($L>(#BO*)^)rSgyNRni$i`R4v;GhlCZ8$@e^ROX(p=2_v6Y!%^As zu022)fHdv_-~Yu_H6WVPLpHQx!W%^6j)cBhS`O3QBW#x(eX54d&I22op(N59b*&$v zFiSRY6rOc^(dgSV1>a7-5C;(5S5MvKcM2Jm-LD9TGqDpP097%52V+0>Xqq!! zq4e3vj53SE6i8J`XcQB|MZPP8j;PAOnpGnllH6#Ku~vS42xP*Nz@~y%db7Xi8s09P z1)e%8ys6&M8D=Dt6&t`iKG_4X=!kgRQoh%Z`dc&mlOUqXk-k`jKv9@(a^2-Upw>?< zt5*^DV~6Zedbec4NVl($2T{&b)zA@b#dUyd>`2JC0=xa_fIm8{5um zr-!ApXZhC8@=vC2WyxO|!@0Km)h8ep*`^he92$@YwP>VcdoS5OC^s38e#7RPsg4j+ zbVGG}WRSET&ZfrcR(x~k8n1rTP%CnfUNKUonD$P?FtNFF#cn!wEIab-;jU=B1dHK@ z(;(yAQJ`O$sMn>h;pf^8{JISW%d+@v6@CnXh9n5TXGC}?FI9i-D0OMaIg&mAg=0Kn zNJ7oz5*ReJukD55fUsMuaP+H4tDN&V9zfqF@ zr=#ecUk9wu{0;!+gl;3Bw=Vn^)z$ahVhhw)io!na&9}LmWurLb0zubxK=UEnU*{5P z+SP}&*(iBKSO4{alBHaY^)5Q=mZ+2OwIooJ7*Q5XJ+2|q`9#f?6myq!&oz?klihLq z4C)$XP!BNS0G_Z1&TM>?Jk{S~{F3n83ioli=IO6f%wkvCl(RFFw~j0tb{GvXTx>*sB0McY0s&SNvj4+^h`9nJ_wM>F!Uc>X}9PifQekn0sKI2SAJP!a4h z5cyGTuCj3ZBM^&{dRelIlT^9zcfaAuL5Y~bl!ppSf`wZbK$z#6U~rdclk``e+!qhe z6Qspo*%<)eu6?C;Bp<^VuW6JI|Ncvyn+LlSl;Mp22Bl7ARQ0Xc24%29(ZrdsIPw&-=yHQ7_Vle|5h>AST0 zUGX2Zk34vp?U~IHT|;$U86T+UUHl_NE4m|}>E~6q``7hccCaT^#y+?wD##Q%HwPd8 zV3x4L4|qqu`B$4(LXqDJngNy-{&@aFBvVsywt@X^}iH7P%>bR?ciC$I^U-4Foa`YKI^qDyGK7k%E%c_P=yzAi`YnxGA%DeNd++j3*h^ z=rn>oBd0|~lZ<6YvmkKY*ZJlJ;Im0tqgWu&E92eqt;+NYdxx`eS(4Hw_Jb5|yVvBg z*tbdY^!AN;luEyN4VRhS@-_DC{({ziH{&Z}iGElSV~qvT>L-8G%+yEL zX#MFOhj{InyKG=mvW-<1B@c-}x$vA(nU?>S>0*eN#!SLzQ)Ex7fvQ)S4D<8|I#N$3 zT5Ei`Z?cxBODHX8(Xp73v`IsAYC@9b;t}z0wxVuQSY1J^GRwDPN@qbM-ZF48T$GZ< z8WU+;Pqo?{ghI-KZ-i*ydXu`Ep0Xw^McH_KE9J0S7G;x8Fe`DVG?j3Pv=0YzJ}yZR z%2=oqHiUjvuk0~Ca>Kol4CFi0_xQT~;_F?=u+!kIDl-9g`#ZNZ9HCy17Ga1v^Jv9# z{T4Kb1-AzUxq*MutfOWWZgD*HnFfyYg0&e9f(5tZ>krPF6{VikNeHoc{linPPt#Si z&*g>(c54V8rT_AX!J&bNm-!umPvOR}vDai#`CX___J#=zeB*{4<&2WpaDncZsOkp* zsg<%@@rbrMkR_ux9?LsQxzoBa1s%$BBn6vk#{&&zUwcfzeCBJUwFYSF$08qDsB;gWQN*g!p8pxjofWbqNSZOEKOaTx@+* zwdt5*Q47@EOZ~EZL9s?1o?A%9TJT=Ob_13yyugvPg*e&ZU(r6^k4=2+D-@n=Hv5vu zSXG|hM(>h9^zn=eQ=$6`JO&70&2|%V5Lsx>)(%#;pcOfu>*nk_3HB_BNaH$`jM<^S zcSftDU1?nL;jy)+sfonQN}(}gUW?d_ikr*3=^{G)=tjBtEPe>TO|0ddVB zTklrSHiW+!#26frPXQQ(YN8DG$PZo?(po(QUCCf_OJC`pw*uey00%gmH!`WJkrKXj2!#6?`T25mTu9OJp2L8z3! z=arrL$ZqxuE{%yV)14Kd>k}j7pxZ6#$Dz8$@WV5p8kTqN<-7W)Q7Gt2{KoOPK_tZ| zf2WG~O5@{qPI+W<4f_;reuFVdO^5`ADC1!JQE|N`s3cq@(0WB!n0uh@*c{=LAd;~} zyGK@hbF-Oo+!nN)@i*O(`@FA#u?o=~e{`4O#5}z&=UkU*50fOrzi11D^&FOqe>wii z?*k+2|EcUs;Gx{!@KBT~>PAwLrIDT7Th=Utu?~?np@t^gFs?zgX=D${RwOY^WGh-+ z+#4$066ISh8eYW#FXWp~S`<*%O^ZuItL1Tyqt8#tZ zY120E;^VG`!lZn&3sPd$RkdHpU#|w+bYV)pJC|SH9g%|5IkxVTQcBA4CL0}$&}ef@ zW^Vtj%M;;_1xxP9x#ex17&4N*{ksO*_4O}xYu(p*JkL#yr}@7b)t5X?%CY<+s5_MJ zuiqt+N_;A(_)%lumoyRFixWa-M7qK_9s6<1X?JDa9fP!+_6u~~M$5L=ipB=7(j#f< zZ34J%=bs549%~_mA(|={uZNs_0?o7;-LBP(ZRnkd{-^|2|=4vUTmtByHL8 zEph`(LSEzQj68a+`d$V<45J7cyv^#|^|%fD#si1Nx!4NW*`l*{->HEWNh6-|g>-=r zXmQ|-i}Ku$ndUeHQ^&ieT!Lf}vf6GaqW9$DJ2NWrqwPY%%4nip$@vK$nRp*_C-v<| zuKz~ZyN&<%!NS26&x?jhy+@awJipMQ-8(X4#Ae5??U<1QMt1l9R=w9fAnEF}NYu$2 z>6}Vkc zIb*A?G*z8^IvibmBKn_u^5&T_1oey0gZS2~obf(#xk=erZGTEdQnt3DMGM+0oPwss zj5zXD;(oWhB_T@~Ig#9@v)AKtXu3>Inmgf@A|-lD-1U>cNyl3h?ADD9)GG4}zUGPk zZzaXe!~Kf?<~@$G?Uql3t8jy9{2!doq4=J}j9ktTxss{p6!9UdjyDERlA*xZ!=Q)KDs5O)phz>Vq3BNGoM(H|=1*Q4$^2fTZw z(%nq1P|5Rt81}SYJpEEzMPl5VJsV5&4e)ZWKDyoZ>1EwpkHx-AQVQc8%JMz;{H~p{=FXV>jIxvm4X*qv52e?Y-f%DJ zxEA165GikEASQ^fH6K#d!Tpu2HP{sFs%E=e$gYd$aj$+xue6N+Wc(rAz~wUsk2`(b z8Kvmyz%bKQxpP}~baG-rwYcYCvkHOi zlkR<=>ZBTU*8RF_d#Bl@zZsRIhx<%~Z@Z=ik z>adw3!DK(8R|q$vy{FTxw%#xliD~6qXmY^7_9kthVPTF~Xy1CfBqbU~?1QmxmU=+k z(ggxvEuA;0e&+ci-zQR{-f7aO{O(Pz_OsEjLh_K>MbvoZ4nxtk5u{g@nPv)cgW_R} z9}EA4K4@z0?7ue}Z(o~R(X&FjejUI2g~08PH1E4w>9o{)S(?1>Z0XMvTb|;&EuyOE zGvWNpYX)Nv<8|a^;1>bh#&znEcl-r!T#pn= z4$?Yudha6F%4b>*8@=BdtXXY4N+`U4Dmx$}>HeVJk-QdTG@t!tVT#0(LeV0gvqyyw z2sEp^9eY0N`u10Tm4n8No&A=)IeEC|gnmEXoNSzu!1<4R<%-9kY_8~5Ej?zRegMn78wuMs#;i&eUA0Zk_RXQ3b&TT} z;SCI=7-FUB@*&;8|n>(_g^HGf3@QODE3LpmX~ELnymQm{Sx9xrKS zK29p~?v@R$0=v6Dr5aW>-!{+h@?Q58|Kz8{{W`%J+lDAdb&M5VHrX_mDY;1-JLnf)ezmPau$)1;=`-FU=-r-83tX=C`S#}GZufju zQ>sXNT0Ny=k@nc%cFnvA_i4SC)?_ORXHq8B4D%el1uPX`c~uG#S1M7C+*MMqLw78E zhY2dI8@+N^qrMI1+;TUda(vGqGSRyU{Fnm`aqrr7bz42c5xsOO-~oZpkzorD1g}Y<6rk&3>PsSGy}W?MtqFky@A(X# zIuNZK0cK?^=;PUAu>j0#HtjbHCV*6?jzA&OoE$*Jlga*}LF`SF?WLhv1O|zqC<>*> zYB;#lsYKx0&kH@BFpW8n*yDcc6?;_zaJs<-jPSkCsSX-!aV=P5kUgF@Nu<{a%#K*F z134Q{9|YX7X(v$62_cY3^G%t~rD>Q0z@)1|zs)vjJ6Jq9;7#Ki`w+eS**En?7;n&7 zu==V3T&eFboN3ZiMx3D8qYc;VjFUk_H-WWCau(VFXSQf~viH0L$gwD$UfFHqNcgN`x}M+YQ6RnN<+@t>JUp#)9YOkqst-Ga?{FsDpEeX0(5v{0J~SEbWiL zXC2}M4?UH@u&|;%0y`eb33ldo4~z-x8zY!oVmV=c+f$m?RfDC35mdQ2E>Pze7KWP- z>!Bh<&57I+O_^s}9Tg^k)h7{xx@0a0IA~GAOt2yy!X%Q$1rt~LbTB6@Du!_0%HV>N zlf)QI1&gvERKwso23mJ!Ou6ZS#zCS5W`gxE5T>C#E|{i<1D35C222I33?Njaz`On7 zi<+VWFP6D{e-{yiN#M|Jgk<44u1TiMI78S5W`Sdb5f+{zu34s{CfWN7a3Cf^@L%!& zN$?|!!9j2c)j$~+R6n#891w-z8(!oBpL2K=+%a$r2|~8-(vQj5_XT`<0Ksf;oP+tz z9CObS!0m)Tgg`K#xBM8B(|Z)Wb&DYL{WTYv`;A=q6~Nnx2+!lTIXtj8J7dZE!P_{z z#f8w6F}^!?^KE#+ZDv+xd5O&3EmomZzsv?>E-~ygGum45fk!SBN&|eo1rKw^?aZJ4 E2O(~oYXATM diff --git a/code/gradle/wrapper/gradle-wrapper.properties b/code/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 6c9a2247..00000000 --- a/code/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/code/gradlew b/code/gradlew deleted file mode 100644 index 4f906e0c..00000000 --- a/code/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/code/gradlew.bat b/code/gradlew.bat deleted file mode 100644 index 107acd32..00000000 --- a/code/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/code/hiding/Cake.java b/code/hiding/Cake.java deleted file mode 100644 index d20e2cbf..00000000 --- a/code/hiding/Cake.java +++ /dev/null @@ -1,15 +0,0 @@ -// hiding/Cake.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Accesses a class in a separate compilation unit - -class Cake { - public static void main(String[] args) { - Pie x = new Pie(); - x.f(); - } -} -/* Output: -Pie.f() -*/ diff --git a/code/hiding/ChocolateChip.java b/code/hiding/ChocolateChip.java deleted file mode 100644 index 1467fff4..00000000 --- a/code/hiding/ChocolateChip.java +++ /dev/null @@ -1,23 +0,0 @@ -// hiding/ChocolateChip.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Can't use package-access member from another package -import hiding.dessert.*; - -public class ChocolateChip extends Cookie { - public ChocolateChip() { - System.out.println("ChocolateChip constructor"); - } - public void chomp() { - //- bite(); // Can't access bite - } - public static void main(String[] args) { - ChocolateChip x = new ChocolateChip(); - x.chomp(); - } -} -/* Output: -Cookie constructor -ChocolateChip constructor -*/ diff --git a/code/hiding/ChocolateChip2.java b/code/hiding/ChocolateChip2.java deleted file mode 100644 index 03c9d1ab..00000000 --- a/code/hiding/ChocolateChip2.java +++ /dev/null @@ -1,21 +0,0 @@ -// hiding/ChocolateChip2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import hiding.cookie2.*; - -public class ChocolateChip2 extends Cookie { - public ChocolateChip2() { - System.out.println("ChocolateChip2 constructor"); - } - public void chomp() { bite(); } // Protected method - public static void main(String[] args) { - ChocolateChip2 x = new ChocolateChip2(); - x.chomp(); - } -} -/* Output: -Cookie constructor -ChocolateChip2 constructor -bite -*/ diff --git a/code/hiding/CreatePackageAccessObject.java b/code/hiding/CreatePackageAccessObject.java deleted file mode 100644 index 8442b51f..00000000 --- a/code/hiding/CreatePackageAccessObject.java +++ /dev/null @@ -1,12 +0,0 @@ -// hiding/CreatePackageAccessObject.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} -import hiding.packageaccess.*; - -public class CreatePackageAccessObject { - public static void main(String[] args) { - new PublicConstructor(); - } -} diff --git a/code/hiding/Dinner.java b/code/hiding/Dinner.java deleted file mode 100644 index 7a7b97d5..00000000 --- a/code/hiding/Dinner.java +++ /dev/null @@ -1,16 +0,0 @@ -// hiding/Dinner.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Uses the library -import hiding.dessert.*; - -public class Dinner { - public static void main(String[] args) { - Cookie x = new Cookie(); - //- x.bite(); // Can't access - } -} -/* Output: -Cookie constructor -*/ diff --git a/code/hiding/FullQualification.java b/code/hiding/FullQualification.java deleted file mode 100644 index 2fadb28c..00000000 --- a/code/hiding/FullQualification.java +++ /dev/null @@ -1,11 +0,0 @@ -// hiding/FullQualification.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class FullQualification { - public static void main(String[] args) { - java.util.ArrayList list = - new java.util.ArrayList(); - } -} diff --git a/code/hiding/IceCream.java b/code/hiding/IceCream.java deleted file mode 100644 index d91619a2..00000000 --- a/code/hiding/IceCream.java +++ /dev/null @@ -1,19 +0,0 @@ -// hiding/IceCream.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates "private" keyword - -class Sundae { - private Sundae() {} - static Sundae makeASundae() { - return new Sundae(); - } -} - -public class IceCream { - public static void main(String[] args) { - //- Sundae x = new Sundae(); - Sundae x = Sundae.makeASundae(); - } -} diff --git a/code/hiding/ImportedMyClass.java b/code/hiding/ImportedMyClass.java deleted file mode 100644 index a644f5d8..00000000 --- a/code/hiding/ImportedMyClass.java +++ /dev/null @@ -1,11 +0,0 @@ -// hiding/ImportedMyClass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import hiding.mypackage.*; - -public class ImportedMyClass { - public static void main(String[] args) { - MyClass m = new MyClass(); - } -} diff --git a/code/hiding/LibTest.java b/code/hiding/LibTest.java deleted file mode 100644 index c439352a..00000000 --- a/code/hiding/LibTest.java +++ /dev/null @@ -1,17 +0,0 @@ -// hiding/LibTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Uses the library -import com.mindviewinc.simple.*; - -public class LibTest { - public static void main(String[] args) { - Vector v = new Vector(); - List l = new List(); - } -} -/* Output: -com.mindviewinc.simple.Vector -com.mindviewinc.simple.List -*/ diff --git a/code/hiding/Lunch.java b/code/hiding/Lunch.java deleted file mode 100644 index eca4baf0..00000000 --- a/code/hiding/Lunch.java +++ /dev/null @@ -1,36 +0,0 @@ -// hiding/Lunch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates class access specifiers. Make a class -// effectively private with private constructors: - -class Soup1 { - private Soup1() {} - public static Soup1 makeSoup() { // [1] - return new Soup1(); - } -} - -class Soup2 { - private Soup2() {} - private static Soup2 ps1 = new Soup2(); // [2] - public static Soup2 access() { - return ps1; - } - public void f() {} -} - -// Only one public class allowed per file: -public class Lunch { - void testPrivate() { - // Can't do this! Private constructor: - //- Soup1 soup = new Soup1(); - } - void testStatic() { - Soup1 soup = Soup1.makeSoup(); - } - void testSingleton() { - Soup2.access().f(); - } -} diff --git a/code/hiding/OrganizedByAccess.java b/code/hiding/OrganizedByAccess.java deleted file mode 100644 index 46af158f..00000000 --- a/code/hiding/OrganizedByAccess.java +++ /dev/null @@ -1,15 +0,0 @@ -// hiding/OrganizedByAccess.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class OrganizedByAccess { - public void pub1() { /* ... */ } - public void pub2() { /* ... */ } - public void pub3() { /* ... */ } - private void priv1() { /* ... */ } - private void priv2() { /* ... */ } - private void priv3() { /* ... */ } - private int i; - // ... -} diff --git a/code/hiding/Pie.java b/code/hiding/Pie.java deleted file mode 100644 index 1470fbc3..00000000 --- a/code/hiding/Pie.java +++ /dev/null @@ -1,9 +0,0 @@ -// hiding/Pie.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The other class - -class Pie { - void f() { System.out.println("Pie.f()"); } -} diff --git a/code/hiding/QualifiedMyClass.java b/code/hiding/QualifiedMyClass.java deleted file mode 100644 index 58a097cc..00000000 --- a/code/hiding/QualifiedMyClass.java +++ /dev/null @@ -1,11 +0,0 @@ -// hiding/QualifiedMyClass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class QualifiedMyClass { - public static void main(String[] args) { - hiding.mypackage.MyClass m = - new hiding.mypackage.MyClass(); - } -} diff --git a/code/hiding/SingleImport.java b/code/hiding/SingleImport.java deleted file mode 100644 index 5168ebe8..00000000 --- a/code/hiding/SingleImport.java +++ /dev/null @@ -1,11 +0,0 @@ -// hiding/SingleImport.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.ArrayList; - -public class SingleImport { - public static void main(String[] args) { - ArrayList list = new ArrayList(); - } -} diff --git a/code/hiding/cookie2/Cookie.java b/code/hiding/cookie2/Cookie.java deleted file mode 100644 index aff5bb17..00000000 --- a/code/hiding/cookie2/Cookie.java +++ /dev/null @@ -1,14 +0,0 @@ -// hiding/cookie2/Cookie.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package hiding.cookie2; - -public class Cookie { - public Cookie() { - System.out.println("Cookie constructor"); - } - protected void bite() { - System.out.println("bite"); - } -} diff --git a/code/hiding/dessert/Cookie.java b/code/hiding/dessert/Cookie.java deleted file mode 100644 index 803e504c..00000000 --- a/code/hiding/dessert/Cookie.java +++ /dev/null @@ -1,13 +0,0 @@ -// hiding/dessert/Cookie.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creates a library -package hiding.dessert; - -public class Cookie { - public Cookie() { - System.out.println("Cookie constructor"); - } - void bite() { System.out.println("bite"); } -} diff --git a/code/hiding/mypackage/MyClass.java b/code/hiding/mypackage/MyClass.java deleted file mode 100644 index 5245d479..00000000 --- a/code/hiding/mypackage/MyClass.java +++ /dev/null @@ -1,9 +0,0 @@ -// hiding/mypackage/MyClass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package hiding.mypackage; - -public class MyClass { - // ... -} diff --git a/code/hiding/packageaccess/PublicConstructor.java b/code/hiding/packageaccess/PublicConstructor.java deleted file mode 100644 index 533c28a0..00000000 --- a/code/hiding/packageaccess/PublicConstructor.java +++ /dev/null @@ -1,9 +0,0 @@ -// hiding/packageaccess/PublicConstructor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package hiding.packageaccess; - -class PublicConstructor { - public PublicConstructor() {} -} diff --git a/code/housekeeping/Apricot.java b/code/housekeeping/Apricot.java deleted file mode 100644 index dae8f33d..00000000 --- a/code/housekeeping/Apricot.java +++ /dev/null @@ -1,8 +0,0 @@ -// housekeeping/Apricot.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class Apricot { - void pick() { /* ... */ } - void pit() { pick(); /* ... */ } -} diff --git a/code/housekeeping/ArrayClassObj.java b/code/housekeeping/ArrayClassObj.java deleted file mode 100644 index 44e31b59..00000000 --- a/code/housekeeping/ArrayClassObj.java +++ /dev/null @@ -1,22 +0,0 @@ -// housekeeping/ArrayClassObj.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating an array of nonprimitive objects -import java.util.*; - -public class ArrayClassObj { - public static void main(String[] args) { - Random rand = new Random(47); - Integer[] a = new Integer[rand.nextInt(20)]; - System.out.println("length of a = " + a.length); - for(int i = 0; i < a.length; i++) - a[i] = rand.nextInt(500); // Autoboxing - System.out.println(Arrays.toString(a)); - } -} -/* Output: -length of a = 18 -[55, 193, 361, 461, 429, 368, 200, 22, 207, 288, 128, -51, 89, 309, 278, 498, 361, 20] -*/ diff --git a/code/housekeeping/ArrayInit.java b/code/housekeeping/ArrayInit.java deleted file mode 100644 index 4186bd24..00000000 --- a/code/housekeeping/ArrayInit.java +++ /dev/null @@ -1,25 +0,0 @@ -// housekeeping/ArrayInit.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Array initialization -import java.util.*; - -public class ArrayInit { - public static void main(String[] args) { - Integer[] a = { - 1, 2, - 3, // Autoboxing - }; - Integer[] b = new Integer[]{ - 1, 2, - 3, // Autoboxing - }; - System.out.println(Arrays.toString(a)); - System.out.println(Arrays.toString(b)); - } -} -/* Output: -[1, 2, 3] -[1, 2, 3] -*/ diff --git a/code/housekeeping/ArrayNew.java b/code/housekeeping/ArrayNew.java deleted file mode 100644 index 022cec16..00000000 --- a/code/housekeeping/ArrayNew.java +++ /dev/null @@ -1,20 +0,0 @@ -// housekeeping/ArrayNew.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating arrays with new -import java.util.*; - -public class ArrayNew { - public static void main(String[] args) { - int[] a; - Random rand = new Random(47); - a = new int[rand.nextInt(20)]; - System.out.println("length of a = " + a.length); - System.out.println(Arrays.toString(a)); - } -} -/* Output: -length of a = 18 -[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -*/ diff --git a/code/housekeeping/ArraysOfPrimitives.java b/code/housekeeping/ArraysOfPrimitives.java deleted file mode 100644 index 165afe89..00000000 --- a/code/housekeeping/ArraysOfPrimitives.java +++ /dev/null @@ -1,23 +0,0 @@ -// housekeeping/ArraysOfPrimitives.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ArraysOfPrimitives { - public static void main(String[] args) { - int[] a1 = { 1, 2, 3, 4, 5 }; - int[] a2; - a2 = a1; - for(int i = 0; i < a2.length; i++) - a2[i] += 1; - for(int i = 0; i < a1.length; i++) - System.out.println("a1[" + i + "] = " + a1[i]); - } -} -/* Output: -a1[0] = 2 -a1[1] = 3 -a1[2] = 4 -a1[3] = 5 -a1[4] = 6 -*/ diff --git a/code/housekeeping/AutoboxingVarargs.java b/code/housekeeping/AutoboxingVarargs.java deleted file mode 100644 index c670fa67..00000000 --- a/code/housekeeping/AutoboxingVarargs.java +++ /dev/null @@ -1,22 +0,0 @@ -// housekeeping/AutoboxingVarargs.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class AutoboxingVarargs { - public static void f(Integer... args) { - for(Integer i : args) - System.out.print(i + " "); - System.out.println(); - } - public static void main(String[] args) { - f(1, 2); - f(4, 5, 6, 7, 8, 9); - f(10, 11, 12); - } -} -/* Output: -1 2 -4 5 6 7 8 9 -10 11 12 -*/ diff --git a/code/housekeeping/BananaPeel.java b/code/housekeeping/BananaPeel.java deleted file mode 100644 index b3e01b27..00000000 --- a/code/housekeeping/BananaPeel.java +++ /dev/null @@ -1,15 +0,0 @@ -// housekeeping/BananaPeel.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Banana { void peel(int i) { /* ... */ } } - -public class BananaPeel { - public static void main(String[] args) { - Banana a = new Banana(), - b = new Banana(); - a.peel(1); - b.peel(2); - } -} diff --git a/code/housekeeping/Burrito.java b/code/housekeeping/Burrito.java deleted file mode 100644 index e3fd028b..00000000 --- a/code/housekeeping/Burrito.java +++ /dev/null @@ -1,39 +0,0 @@ -// housekeeping/Burrito.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Burrito { - Spiciness degree; - public Burrito(Spiciness degree) { - this.degree = degree; - } - public void describe() { - System.out.print("This burrito is "); - switch(degree) { - case NOT: System.out.println( - "not spicy at all."); - break; - case MILD: - case MEDIUM: System.out.println("a little hot."); - break; - case HOT: - case FLAMING: - default: System.out.println("maybe too hot."); - } - } - public static void main(String[] args) { - Burrito - plain = new Burrito(Spiciness.NOT), - greenChile = new Burrito(Spiciness.MEDIUM), - jalapeno = new Burrito(Spiciness.HOT); - plain.describe(); - greenChile.describe(); - jalapeno.describe(); - } -} -/* Output: -This burrito is not spicy at all. -This burrito is a little hot. -This burrito is maybe too hot. -*/ diff --git a/code/housekeeping/Counter.java b/code/housekeeping/Counter.java deleted file mode 100644 index d0a58ecc..00000000 --- a/code/housekeeping/Counter.java +++ /dev/null @@ -1,9 +0,0 @@ -// housekeeping/Counter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class Counter { - int i; - Counter() { i = 7; } - // ... -} diff --git a/code/housekeeping/DefaultConstructor.java b/code/housekeeping/DefaultConstructor.java deleted file mode 100644 index 22e3787d..00000000 --- a/code/housekeeping/DefaultConstructor.java +++ /dev/null @@ -1,12 +0,0 @@ -// housekeeping/DefaultConstructor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Bird {} - -public class DefaultConstructor { - public static void main(String[] args) { - Bird b = new Bird(); // Default! - } -} diff --git a/code/housekeeping/Demotion.java b/code/housekeeping/Demotion.java deleted file mode 100644 index ad2c4e86..00000000 --- a/code/housekeeping/Demotion.java +++ /dev/null @@ -1,43 +0,0 @@ -// housekeeping/Demotion.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demotion of primitives - -public class Demotion { - void f1(double x) { - System.out.println("f1(double)"); - } - void f2(float x) { System.out.println("f2(float)"); } - void f3(long x) { System.out.println("f3(long)"); } - void f4(int x) { System.out.println("f4(int)"); } - void f5(short x) { System.out.println("f5(short)"); } - void f6(byte x) { System.out.println("f6(byte)"); } - void f7(char x) { System.out.println("f7(char)"); } - - void testDouble() { - double x = 0; - System.out.println("double argument:"); - f1(x); - f2((float)x); - f3((long)x); - f4((int)x); - f5((short)x); - f6((byte)x); - f7((char)x); - } - public static void main(String[] args) { - Demotion p = new Demotion(); - p.testDouble(); - } -} -/* Output: -double argument: -f1(double) -f2(float) -f3(long) -f4(int) -f5(short) -f6(byte) -f7(char) -*/ diff --git a/code/housekeeping/DynamicArray.java b/code/housekeeping/DynamicArray.java deleted file mode 100644 index 726ec034..00000000 --- a/code/housekeeping/DynamicArray.java +++ /dev/null @@ -1,21 +0,0 @@ -// housekeeping/DynamicArray.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Array initialization - -public class DynamicArray { - public static void main(String[] args) { - Other.main(new String[]{ "fiddle", "de", "dum" }); - } -} - -class Other { - public static void main(String[] args) { - for(String s : args) - System.out.print(s + " "); - } -} -/* Output: -fiddle de dum -*/ diff --git a/code/housekeeping/EnumOrder.java b/code/housekeeping/EnumOrder.java deleted file mode 100644 index a3c96284..00000000 --- a/code/housekeeping/EnumOrder.java +++ /dev/null @@ -1,19 +0,0 @@ -// housekeeping/EnumOrder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class EnumOrder { - public static void main(String[] args) { - for(Spiciness s : Spiciness.values()) - System.out.println( - s + ", ordinal " + s.ordinal()); - } -} -/* Output: -NOT, ordinal 0 -MILD, ordinal 1 -MEDIUM, ordinal 2 -HOT, ordinal 3 -FLAMING, ordinal 4 -*/ diff --git a/code/housekeeping/ExplicitStatic.java b/code/housekeeping/ExplicitStatic.java deleted file mode 100644 index 7d9cb31a..00000000 --- a/code/housekeeping/ExplicitStatic.java +++ /dev/null @@ -1,41 +0,0 @@ -// housekeeping/ExplicitStatic.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Explicit static initialization with "static" clause - -class Cup { - Cup(int marker) { - System.out.println("Cup(" + marker + ")"); - } - void f(int marker) { - System.out.println("f(" + marker + ")"); - } -} - -class Cups { - static Cup cup1; - static Cup cup2; - static { - cup1 = new Cup(1); - cup2 = new Cup(2); - } - Cups() { - System.out.println("Cups()"); - } -} - -public class ExplicitStatic { - public static void main(String[] args) { - System.out.println("Inside main()"); - Cups.cup1.f(99); // [1] - } - // static Cups cups1 = new Cups(); // [2] - // static Cups cups2 = new Cups(); // [2] -} -/* Output: -Inside main() -Cup(1) -Cup(2) -f(99) -*/ diff --git a/code/housekeeping/Flower.java b/code/housekeeping/Flower.java deleted file mode 100644 index a62d7cbe..00000000 --- a/code/housekeeping/Flower.java +++ /dev/null @@ -1,46 +0,0 @@ -// housekeeping/Flower.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Calling constructors with "this" - -public class Flower { - int petalCount = 0; - String s = "initial value"; - Flower(int petals) { - petalCount = petals; - System.out.println( - "Constructor w/ int arg only, petalCount= " - + petalCount); - } - Flower(String ss) { - System.out.println( - "Constructor w/ String arg only, s = " + ss); - s = ss; - } - Flower(String s, int petals) { - this(petals); - //- this(s); // Can't call two! - this.s = s; // Another use of "this" - System.out.println("String & int args"); - } - Flower() { - this("hi", 47); - System.out.println("no-arg constructor"); - } - void printPetalCount() { - //- this(11); // Not inside non-constructor! - System.out.println( - "petalCount = " + petalCount + " s = "+ s); - } - public static void main(String[] args) { - Flower x = new Flower(); - x.printPetalCount(); - } -} -/* Output: -Constructor w/ int arg only, petalCount= 47 -String & int args -no-arg constructor -petalCount = 47 s = hi -*/ diff --git a/code/housekeeping/InitialValues.java b/code/housekeeping/InitialValues.java deleted file mode 100644 index dced4dd2..00000000 --- a/code/housekeeping/InitialValues.java +++ /dev/null @@ -1,44 +0,0 @@ -// housekeeping/InitialValues.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Shows default initial values - -public class InitialValues { - boolean t; - char c; - byte b; - short s; - int i; - long l; - float f; - double d; - InitialValues reference; - void printInitialValues() { - System.out.println("Data type Initial value"); - System.out.println("boolean " + t); - System.out.println("char [" + c + "]"); - System.out.println("byte " + b); - System.out.println("short " + s); - System.out.println("int " + i); - System.out.println("long " + l); - System.out.println("float " + f); - System.out.println("double " + d); - System.out.println("reference " + reference); - } - public static void main(String[] args) { - new InitialValues().printInitialValues(); - } -} -/* Output: -Data type Initial value -boolean false -char [NUL] -byte 0 -short 0 -int 0 -long 0 -float 0.0 -double 0.0 -reference null -*/ diff --git a/code/housekeeping/InitialValues2.java b/code/housekeeping/InitialValues2.java deleted file mode 100644 index 1cb50974..00000000 --- a/code/housekeeping/InitialValues2.java +++ /dev/null @@ -1,16 +0,0 @@ -// housekeeping/InitialValues2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Providing explicit initial values - -public class InitialValues2 { - boolean bool = true; - char ch = 'x'; - byte b = 47; - short s = 0xff; - int i = 999; - long lng = 1; - float f = 3.14f; - double d = 3.14159; -} diff --git a/code/housekeeping/Leaf.java b/code/housekeeping/Leaf.java deleted file mode 100644 index f9c560b2..00000000 --- a/code/housekeeping/Leaf.java +++ /dev/null @@ -1,23 +0,0 @@ -// housekeeping/Leaf.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple use of the "this" keyword - -public class Leaf { - int i = 0; - Leaf increment() { - i++; - return this; - } - void print() { - System.out.println("i = " + i); - } - public static void main(String[] args) { - Leaf x = new Leaf(); - x.increment().increment().increment().print(); - } -} -/* Output: -i = 3 -*/ diff --git a/code/housekeeping/Measurement.java b/code/housekeeping/Measurement.java deleted file mode 100644 index 8a920779..00000000 --- a/code/housekeeping/Measurement.java +++ /dev/null @@ -1,10 +0,0 @@ -// housekeeping/Measurement.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -class Depth {} - -public class Measurement { - Depth d = new Depth(); - // ... -} diff --git a/code/housekeeping/MethodInit.java b/code/housekeeping/MethodInit.java deleted file mode 100644 index 84e15fce..00000000 --- a/code/housekeeping/MethodInit.java +++ /dev/null @@ -1,8 +0,0 @@ -// housekeeping/MethodInit.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class MethodInit { - int i = f(); - int f() { return 11; } -} diff --git a/code/housekeeping/MethodInit2.java b/code/housekeeping/MethodInit2.java deleted file mode 100644 index 24750fb2..00000000 --- a/code/housekeeping/MethodInit2.java +++ /dev/null @@ -1,10 +0,0 @@ -// housekeeping/MethodInit2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class MethodInit2 { - int i = f(); - int j = g(i); - int f() { return 11; } - int g(int n) { return n * 10; } -} diff --git a/code/housekeeping/MethodInit3.java b/code/housekeeping/MethodInit3.java deleted file mode 100644 index 2a6524ab..00000000 --- a/code/housekeeping/MethodInit3.java +++ /dev/null @@ -1,10 +0,0 @@ -// housekeeping/MethodInit3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class MethodInit3 { - //- int j = g(i); // Illegal forward reference - int i = f(); - int f() { return 11; } - int g(int n) { return n * 10; } -} diff --git a/code/housekeeping/Mugs.java b/code/housekeeping/Mugs.java deleted file mode 100644 index e4ebba69..00000000 --- a/code/housekeeping/Mugs.java +++ /dev/null @@ -1,47 +0,0 @@ -// housekeeping/Mugs.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Instance initialization - -class Mug { - Mug(int marker) { - System.out.println("Mug(" + marker + ")"); - } -} - -public class Mugs { - Mug mug1; - Mug mug2; - { // [1] - mug1 = new Mug(1); - mug2 = new Mug(2); - System.out.println("mug1 & mug2 initialized"); - } - Mugs() { - System.out.println("Mugs()"); - } - Mugs(int i) { - System.out.println("Mugs(int)"); - } - public static void main(String[] args) { - System.out.println("Inside main()"); - new Mugs(); - System.out.println("new Mugs() completed"); - new Mugs(1); - System.out.println("new Mugs(1) completed"); - } -} -/* Output: -Inside main() -Mug(1) -Mug(2) -mug1 & mug2 initialized -Mugs() -new Mugs() completed -Mug(1) -Mug(2) -mug1 & mug2 initialized -Mugs(int) -new Mugs(1) completed -*/ diff --git a/code/housekeeping/NewVarArgs.java b/code/housekeeping/NewVarArgs.java deleted file mode 100644 index 291dd134..00000000 --- a/code/housekeeping/NewVarArgs.java +++ /dev/null @@ -1,30 +0,0 @@ -// housekeeping/NewVarArgs.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using array syntax to create variable argument lists - -public class NewVarArgs { - static void printArray(Object... args) { - for(Object obj : args) - System.out.print(obj + " "); - System.out.println(); - } - public static void main(String[] args) { - // Can take individual elements: - printArray(47, (float) 3.14, 11.11); - printArray(47, 3.14F, 11.11); - printArray("one", "two", "three"); - printArray(new A(), new A(), new A()); - // Or an array: - printArray((Object[])new Integer[]{ 1, 2, 3, 4 }); - printArray(); // Empty list is OK - } -} -/* Output: -47 3.14 11.11 -47 3.14 11.11 -one two three -A@15db9742 A@6d06d69c A@7852e922 -1 2 3 4 -*/ diff --git a/code/housekeeping/NoSynthesis.java b/code/housekeeping/NoSynthesis.java deleted file mode 100644 index 217c2023..00000000 --- a/code/housekeeping/NoSynthesis.java +++ /dev/null @@ -1,17 +0,0 @@ -// housekeeping/NoSynthesis.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Bird2 { - Bird2(int i) {} - Bird2(double d) {} -} - -public class NoSynthesis { - public static void main(String[] args) { - //- Bird2 b = new Bird2(); // No default - Bird2 b2 = new Bird2(1); - Bird2 b3 = new Bird2(1.0); - } -} diff --git a/code/housekeeping/OptionalTrailingArguments.java b/code/housekeeping/OptionalTrailingArguments.java deleted file mode 100644 index d7ee9fbb..00000000 --- a/code/housekeeping/OptionalTrailingArguments.java +++ /dev/null @@ -1,23 +0,0 @@ -// housekeeping/OptionalTrailingArguments.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class OptionalTrailingArguments { - static void f(int required, String... trailing) { - System.out.print("required: " + required + " "); - for(String s : trailing) - System.out.print(s + " "); - System.out.println(); - } - public static void main(String[] args) { - f(1, "one"); - f(2, "two", "three"); - f(0); - } -} -/* Output: -required: 1 one -required: 2 two three -required: 0 -*/ diff --git a/code/housekeeping/OrderOfInitialization.java b/code/housekeeping/OrderOfInitialization.java deleted file mode 100644 index c715ed7c..00000000 --- a/code/housekeeping/OrderOfInitialization.java +++ /dev/null @@ -1,40 +0,0 @@ -// housekeeping/OrderOfInitialization.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates initialization order - -// When the constructor is called to create a -// Window object, you'll see a message: -class Window { - Window(int marker) { - System.out.println("Window(" + marker + ")"); - } -} - -class House { - Window w1 = new Window(1); // Before constructor - House() { - // Show that we're in the constructor: - System.out.println("House()"); - w3 = new Window(33); // Reinitialize w3 - } - Window w2 = new Window(2); // After constructor - void f() { System.out.println("f()"); } - Window w3 = new Window(3); // At end -} - -public class OrderOfInitialization { - public static void main(String[] args) { - House h = new House(); - h.f(); // Shows that construction is done - } -} -/* Output: -Window(1) -Window(2) -Window(3) -House() -Window(33) -f() -*/ diff --git a/code/housekeeping/Overloading.java b/code/housekeeping/Overloading.java deleted file mode 100644 index 99d21bf8..00000000 --- a/code/housekeeping/Overloading.java +++ /dev/null @@ -1,56 +0,0 @@ -// housekeeping/Overloading.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Both constructor and ordinary method overloading - -class Tree { - int height; - Tree() { - System.out.println("Planting a seedling"); - height = 0; - } - Tree(int initialHeight) { - height = initialHeight; - System.out.println("Creating new Tree that is " + - height + " feet tall"); - } - void info() { - System.out.println( - "Tree is " + height + " feet tall"); - } - void info(String s) { - System.out.println( - s + ": Tree is " + height + " feet tall"); - } -} - -public class Overloading { - public static void main(String[] args) { - for(int i = 0; i < 5; i++) { - Tree t = new Tree(i); - t.info(); - t.info("overloaded method"); - } - // Overloaded constructor: - new Tree(); - } -} -/* Output: -Creating new Tree that is 0 feet tall -Tree is 0 feet tall -overloaded method: Tree is 0 feet tall -Creating new Tree that is 1 feet tall -Tree is 1 feet tall -overloaded method: Tree is 1 feet tall -Creating new Tree that is 2 feet tall -Tree is 2 feet tall -overloaded method: Tree is 2 feet tall -Creating new Tree that is 3 feet tall -Tree is 3 feet tall -overloaded method: Tree is 3 feet tall -Creating new Tree that is 4 feet tall -Tree is 4 feet tall -overloaded method: Tree is 4 feet tall -Planting a seedling -*/ diff --git a/code/housekeeping/OverloadingOrder.java b/code/housekeeping/OverloadingOrder.java deleted file mode 100644 index 42f6466e..00000000 --- a/code/housekeeping/OverloadingOrder.java +++ /dev/null @@ -1,22 +0,0 @@ -// housekeeping/OverloadingOrder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Overloading based on the order of the arguments - -public class OverloadingOrder { - static void f(String s, int i) { - System.out.println("String: " + s + ", int: " + i); - } - static void f(int i, String s) { - System.out.println("int: " + i + ", String: " + s); - } - public static void main(String[] args) { - f("String first", 11); - f(99, "Int first"); - } -} -/* Output: -String: String first, int: 11 -int: 99, String: Int first -*/ diff --git a/code/housekeeping/OverloadingVarargs.java b/code/housekeeping/OverloadingVarargs.java deleted file mode 100644 index c13b7406..00000000 --- a/code/housekeeping/OverloadingVarargs.java +++ /dev/null @@ -1,37 +0,0 @@ -// housekeeping/OverloadingVarargs.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class OverloadingVarargs { - static void f(Character... args) { - System.out.print("first"); - for(Character c : args) - System.out.print(" " + c); - System.out.println(); - } - static void f(Integer... args) { - System.out.print("second"); - for(Integer i : args) - System.out.print(" " + i); - System.out.println(); - } - static void f(Long... args) { - System.out.println("third"); - } - public static void main(String[] args) { - f('a', 'b', 'c'); - f(1); - f(2, 1); - f(0); - f(0L); - //- f(); // Won't compile -- ambiguous - } -} -/* Output: -first a b c -second 1 -second 2 1 -second 0 -third -*/ diff --git a/code/housekeeping/OverloadingVarargs2.java b/code/housekeeping/OverloadingVarargs2.java deleted file mode 100644 index c3a09845..00000000 --- a/code/housekeeping/OverloadingVarargs2.java +++ /dev/null @@ -1,18 +0,0 @@ -// housekeeping/OverloadingVarargs2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} - -public class OverloadingVarargs2 { - static void f(float i, Character... args) { - System.out.println("first"); - } - static void f(Character... args) { - System.out.print("second"); - } - public static void main(String[] args) { - f(1, 'a'); - f('a', 'b'); - } -} diff --git a/code/housekeeping/OverloadingVarargs3.java b/code/housekeeping/OverloadingVarargs3.java deleted file mode 100644 index 23e757ec..00000000 --- a/code/housekeeping/OverloadingVarargs3.java +++ /dev/null @@ -1,21 +0,0 @@ -// housekeeping/OverloadingVarargs3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class OverloadingVarargs3 { - static void f(float i, Character... args) { - System.out.println("first"); - } - static void f(char c, Character... args) { - System.out.println("second"); - } - public static void main(String[] args) { - f(1, 'a'); - f('a', 'b'); - } -} -/* Output: -first -second -*/ diff --git a/code/housekeeping/PassingThis.java b/code/housekeeping/PassingThis.java deleted file mode 100644 index ce725eab..00000000 --- a/code/housekeeping/PassingThis.java +++ /dev/null @@ -1,31 +0,0 @@ -// housekeeping/PassingThis.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Person { - public void eat(Apple apple) { - Apple peeled = apple.getPeeled(); - System.out.println("Yummy"); - } -} - -class Peeler { - static Apple peel(Apple apple) { - // ... remove peel - return apple; // Peeled - } -} - -class Apple { - Apple getPeeled() { return Peeler.peel(this); } -} - -public class PassingThis { - public static void main(String[] args) { - new Person().eat(new Apple()); - } -} -/* Output: -Yummy -*/ diff --git a/code/housekeeping/PrimitiveOverloading.java b/code/housekeeping/PrimitiveOverloading.java deleted file mode 100644 index 1d8c1e2c..00000000 --- a/code/housekeeping/PrimitiveOverloading.java +++ /dev/null @@ -1,120 +0,0 @@ -// housekeeping/PrimitiveOverloading.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Promotion of primitives and overloading - -public class PrimitiveOverloading { - void f1(char x) { System.out.print("f1(char) "); } - void f1(byte x) { System.out.print("f1(byte) "); } - void f1(short x) { System.out.print("f1(short) "); } - void f1(int x) { System.out.print("f1(int) "); } - void f1(long x) { System.out.print("f1(long) "); } - void f1(float x) { System.out.print("f1(float) "); } - void f1(double x) { System.out.print("f1(double) "); } - - void f2(byte x) { System.out.print("f2(byte) "); } - void f2(short x) { System.out.print("f2(short) "); } - void f2(int x) { System.out.print("f2(int) "); } - void f2(long x) { System.out.print("f2(long) "); } - void f2(float x) { System.out.print("f2(float) "); } - void f2(double x) { System.out.print("f2(double) "); } - - void f3(short x) { System.out.print("f3(short) "); } - void f3(int x) { System.out.print("f3(int) "); } - void f3(long x) { System.out.print("f3(long) "); } - void f3(float x) { System.out.print("f3(float) "); } - void f3(double x) { System.out.print("f3(double) "); } - - void f4(int x) { System.out.print("f4(int) "); } - void f4(long x) { System.out.print("f4(long) "); } - void f4(float x) { System.out.print("f4(float) "); } - void f4(double x) { System.out.print("f4(double) "); } - - void f5(long x) { System.out.print("f5(long) "); } - void f5(float x) { System.out.print("f5(float) "); } - void f5(double x) { System.out.print("f5(double) "); } - - void f6(float x) { System.out.print("f6(float) "); } - void f6(double x) { System.out.print("f6(double) "); } - - void f7(double x) { System.out.print("f7(double) "); } - - void testConstVal() { - System.out.print("5: "); - f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5); - System.out.println(); - } - void testChar() { - char x = 'x'; - System.out.print("char: "); - f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); - System.out.println(); - } - void testByte() { - byte x = 0; - System.out.print("byte: "); - f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); - System.out.println(); - } - void testShort() { - short x = 0; - System.out.print("short: "); - f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); - System.out.println(); - } - void testInt() { - int x = 0; - System.out.print("int: "); - f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); - System.out.println(); - } - void testLong() { - long x = 0; - System.out.print("long: "); - f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); - System.out.println(); - } - void testFloat() { - float x = 0; - System.out.print("float: "); - f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); - System.out.println(); - } - void testDouble() { - double x = 0; - System.out.print("double: "); - f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); - System.out.println(); - } - public static void main(String[] args) { - PrimitiveOverloading p = - new PrimitiveOverloading(); - p.testConstVal(); - p.testChar(); - p.testByte(); - p.testShort(); - p.testInt(); - p.testLong(); - p.testFloat(); - p.testDouble(); - } -} -/* Output: -5: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) -f7(double) -char: f1(char) f2(int) f3(int) f4(int) f5(long) -f6(float) f7(double) -byte: f1(byte) f2(byte) f3(short) f4(int) f5(long) -f6(float) f7(double) -short: f1(short) f2(short) f3(short) f4(int) f5(long) -f6(float) f7(double) -int: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) -f7(double) -long: f1(long) f2(long) f3(long) f4(long) f5(long) -f6(float) f7(double) -float: f1(float) f2(float) f3(float) f4(float) -f5(float) f6(float) f7(double) -double: f1(double) f2(double) f3(double) f4(double) -f5(double) f6(double) f7(double) -*/ diff --git a/code/housekeeping/SimpleConstructor.java b/code/housekeeping/SimpleConstructor.java deleted file mode 100644 index c6917c33..00000000 --- a/code/housekeeping/SimpleConstructor.java +++ /dev/null @@ -1,21 +0,0 @@ -// housekeeping/SimpleConstructor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of a simple constructor - -class Rock { - Rock() { // This is the constructor - System.out.print("Rock "); - } -} - -public class SimpleConstructor { - public static void main(String[] args) { - for(int i = 0; i < 10; i++) - new Rock(); - } -} -/* Output: -Rock Rock Rock Rock Rock Rock Rock Rock Rock Rock -*/ diff --git a/code/housekeeping/SimpleConstructor2.java b/code/housekeeping/SimpleConstructor2.java deleted file mode 100644 index 4a191af7..00000000 --- a/code/housekeeping/SimpleConstructor2.java +++ /dev/null @@ -1,21 +0,0 @@ -// housekeeping/SimpleConstructor2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Constructors can have arguments - -class Rock2 { - Rock2(int i) { - System.out.print("Rock " + i + " "); - } -} - -public class SimpleConstructor2 { - public static void main(String[] args) { - for(int i = 0; i < 8; i++) - new Rock2(i); - } -} -/* Output: -Rock 0 Rock 1 Rock 2 Rock 3 Rock 4 Rock 5 Rock 6 Rock 7 -*/ diff --git a/code/housekeeping/SimpleEnumUse.java b/code/housekeeping/SimpleEnumUse.java deleted file mode 100644 index cc0de33b..00000000 --- a/code/housekeeping/SimpleEnumUse.java +++ /dev/null @@ -1,14 +0,0 @@ -// housekeeping/SimpleEnumUse.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SimpleEnumUse { - public static void main(String[] args) { - Spiciness howHot = Spiciness.MEDIUM; - System.out.println(howHot); - } -} -/* Output: -MEDIUM -*/ diff --git a/code/housekeeping/Spiciness.java b/code/housekeeping/Spiciness.java deleted file mode 100644 index a134a822..00000000 --- a/code/housekeeping/Spiciness.java +++ /dev/null @@ -1,8 +0,0 @@ -// housekeeping/Spiciness.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public enum Spiciness { - NOT, MILD, MEDIUM, HOT, FLAMING -} diff --git a/code/housekeeping/Spoon.java b/code/housekeeping/Spoon.java deleted file mode 100644 index fd344815..00000000 --- a/code/housekeeping/Spoon.java +++ /dev/null @@ -1,10 +0,0 @@ -// housekeeping/Spoon.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class Spoon { - static int i; - static { - i = 47; - } -} diff --git a/code/housekeeping/StaticInitialization.java b/code/housekeeping/StaticInitialization.java deleted file mode 100644 index 0cfe99ae..00000000 --- a/code/housekeeping/StaticInitialization.java +++ /dev/null @@ -1,73 +0,0 @@ -// housekeeping/StaticInitialization.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Specifying initial values in a class definition - -class Bowl { - Bowl(int marker) { - System.out.println("Bowl(" + marker + ")"); - } - void f1(int marker) { - System.out.println("f1(" + marker + ")"); - } -} - -class Table { - static Bowl bowl1 = new Bowl(1); - Table() { - System.out.println("Table()"); - bowl2.f1(1); - } - void f2(int marker) { - System.out.println("f2(" + marker + ")"); - } - static Bowl bowl2 = new Bowl(2); -} - -class Cupboard { - Bowl bowl3 = new Bowl(3); - static Bowl bowl4 = new Bowl(4); - Cupboard() { - System.out.println("Cupboard()"); - bowl4.f1(2); - } - void f3(int marker) { - System.out.println("f3(" + marker + ")"); - } - static Bowl bowl5 = new Bowl(5); -} - -public class StaticInitialization { - public static void main(String[] args) { - System.out.println("main creating new Cupboard()"); - new Cupboard(); - System.out.println("main creating new Cupboard()"); - new Cupboard(); - table.f2(1); - cupboard.f3(1); - } - static Table table = new Table(); - static Cupboard cupboard = new Cupboard(); -} -/* Output: -Bowl(1) -Bowl(2) -Table() -f1(1) -Bowl(4) -Bowl(5) -Bowl(3) -Cupboard() -f1(2) -main creating new Cupboard() -Bowl(3) -Cupboard() -f1(2) -main creating new Cupboard() -Bowl(3) -Cupboard() -f1(2) -f2(1) -f3(1) -*/ diff --git a/code/housekeeping/TerminationCondition.java b/code/housekeeping/TerminationCondition.java deleted file mode 100644 index dc8d347b..00000000 --- a/code/housekeeping/TerminationCondition.java +++ /dev/null @@ -1,41 +0,0 @@ -// housekeeping/TerminationCondition.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using finalize() to detect an object that -// hasn't been properly cleaned up -import onjava.*; - -class Book { - boolean checkedOut = false; - Book(boolean checkOut) { - checkedOut = checkOut; - } - void checkIn() { - checkedOut = false; - } - @SuppressWarnings("deprecation") - @Override - public void finalize() { - if(checkedOut) - System.out.println("Error: checked out"); - // Normally, you'll also do this: - // super.finalize(); // Call the base-class version - } -} - -public class TerminationCondition { - public static void main(String[] args) { - Book novel = new Book(true); - // Proper cleanup: - novel.checkIn(); - // Drop the reference, forget to clean up: - new Book(true); - // Force garbage collection & finalization: - System.gc(); - new Nap(1); // One second delay - } -} -/* Output: -Error: checked out -*/ diff --git a/code/housekeeping/VarArgs.java b/code/housekeeping/VarArgs.java deleted file mode 100644 index 73a94c39..00000000 --- a/code/housekeeping/VarArgs.java +++ /dev/null @@ -1,26 +0,0 @@ -// housekeeping/VarArgs.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using array syntax to create variable argument lists - -class A {} - -public class VarArgs { - static void printArray(Object[] args) { - for(Object obj : args) - System.out.print(obj + " "); - System.out.println(); - } - public static void main(String[] args) { - printArray(new Object[]{ - 47, (float) 3.14, 11.11}); - printArray(new Object[]{"one", "two", "three" }); - printArray(new Object[]{new A(), new A(), new A()}); - } -} -/* Output: -47 3.14 11.11 -one two three -A@15db9742 A@6d06d69c A@7852e922 -*/ diff --git a/code/housekeeping/VarargType.java b/code/housekeeping/VarargType.java deleted file mode 100644 index 5b25b053..00000000 --- a/code/housekeeping/VarargType.java +++ /dev/null @@ -1,30 +0,0 @@ -// housekeeping/VarargType.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class VarargType { - static void f(Character... args) { - System.out.print(args.getClass()); - System.out.println(" length " + args.length); - } - static void g(int... args) { - System.out.print(args.getClass()); - System.out.println(" length " + args.length); - } - public static void main(String[] args) { - f('a'); - f(); - g(1); - g(); - System.out.println("int[]: " + - new int[0].getClass()); - } -} -/* Output: -class [Ljava.lang.Character; length 1 -class [Ljava.lang.Character; length 0 -class [I length 1 -class [I length 0 -int[]: class [I -*/ diff --git a/code/innerclasses/AnonymousConstructor.java b/code/innerclasses/AnonymousConstructor.java deleted file mode 100644 index d8e08e7c..00000000 --- a/code/innerclasses/AnonymousConstructor.java +++ /dev/null @@ -1,34 +0,0 @@ -// innerclasses/AnonymousConstructor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating a constructor for an anonymous inner class - -abstract class Base { - Base(int i) { - System.out.println("Base constructor, i = " + i); - } - public abstract void f(); -} - -public class AnonymousConstructor { - public static Base getBase(int i) { - return new Base(i) { - { System.out.println( - "Inside instance initializer"); } - @Override - public void f() { - System.out.println("In anonymous f()"); - } - }; - } - public static void main(String[] args) { - Base base = getBase(47); - base.f(); - } -} -/* Output: -Base constructor, i = 47 -Inside instance initializer -In anonymous f() -*/ diff --git a/code/innerclasses/BigEgg.java b/code/innerclasses/BigEgg.java deleted file mode 100644 index 7b2c3624..00000000 --- a/code/innerclasses/BigEgg.java +++ /dev/null @@ -1,33 +0,0 @@ -// innerclasses/BigEgg.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An inner class cannot be overridden like a method - -class Egg { - private Yolk y; - protected class Yolk { - public Yolk() { - System.out.println("Egg.Yolk()"); - } - } - Egg() { - System.out.println("New Egg()"); - y = new Yolk(); - } -} - -public class BigEgg extends Egg { - public class Yolk { - public Yolk() { - System.out.println("BigEgg.Yolk()"); - } - } - public static void main(String[] args) { - new BigEgg(); - } -} -/* Output: -New Egg() -Egg.Yolk() -*/ diff --git a/code/innerclasses/BigEgg2.java b/code/innerclasses/BigEgg2.java deleted file mode 100644 index 1631008d..00000000 --- a/code/innerclasses/BigEgg2.java +++ /dev/null @@ -1,44 +0,0 @@ -// innerclasses/BigEgg2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Proper inheritance of an inner class - -class Egg2 { - protected class Yolk { - public Yolk() { - System.out.println("Egg2.Yolk()"); - } - public void f() { - System.out.println("Egg2.Yolk.f()"); - } - } - private Yolk y = new Yolk(); - Egg2() { System.out.println("New Egg2()"); } - public void insertYolk(Yolk yy) { y = yy; } - public void g() { y.f(); } -} - -public class BigEgg2 extends Egg2 { - public class Yolk extends Egg2.Yolk { - public Yolk() { - System.out.println("BigEgg2.Yolk()"); - } - @Override - public void f() { - System.out.println("BigEgg2.Yolk.f()"); - } - } - public BigEgg2() { insertYolk(new Yolk()); } - public static void main(String[] args) { - Egg2 e2 = new BigEgg2(); - e2.g(); - } -} -/* Output: -Egg2.Yolk() -New Egg2() -Egg2.Yolk() -BigEgg2.Yolk() -BigEgg2.Yolk.f() -*/ diff --git a/code/innerclasses/Callbacks.java b/code/innerclasses/Callbacks.java deleted file mode 100644 index d1659332..00000000 --- a/code/innerclasses/Callbacks.java +++ /dev/null @@ -1,84 +0,0 @@ -// innerclasses/Callbacks.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using inner classes for callbacks -// {java innerclasses.Callbacks} -package innerclasses; - -interface Incrementable { - void increment(); -} - -// Very simple to just implement the interface: -class Callee1 implements Incrementable { - private int i = 0; - @Override - public void increment() { - i++; - System.out.println(i); - } -} - -class MyIncrement { - public void increment() { - System.out.println("Other operation"); - } - static void f(MyIncrement mi) { mi.increment(); } -} - -// If your class must implement increment() in -// some other way, you must use an inner class: -class Callee2 extends MyIncrement { - private int i = 0; - @Override - public void increment() { - super.increment(); - i++; - System.out.println(i); - } - private class Closure implements Incrementable { - @Override - public void increment() { - // Specify outer-class method, otherwise - // you'll get an infinite recursion: - Callee2.this.increment(); - } - } - Incrementable getCallbackReference() { - return new Closure(); - } -} - -class Caller { - private Incrementable callbackReference; - Caller(Incrementable cbh) { - callbackReference = cbh; - } - void go() { callbackReference.increment(); } -} - -public class Callbacks { - public static void main(String[] args) { - Callee1 c1 = new Callee1(); - Callee2 c2 = new Callee2(); - MyIncrement.f(c2); - Caller caller1 = new Caller(c1); - Caller caller2 = - new Caller(c2.getCallbackReference()); - caller1.go(); - caller1.go(); - caller2.go(); - caller2.go(); - } -} -/* Output: -Other operation -1 -1 -2 -Other operation -2 -Other operation -3 -*/ diff --git a/code/innerclasses/ClassInInterface.java b/code/innerclasses/ClassInInterface.java deleted file mode 100644 index c3cc0589..00000000 --- a/code/innerclasses/ClassInInterface.java +++ /dev/null @@ -1,21 +0,0 @@ -// innerclasses/ClassInInterface.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java ClassInInterface$Test} - -public interface ClassInInterface { - void howdy(); - class Test implements ClassInInterface { - @Override - public void howdy() { - System.out.println("Howdy!"); - } - public static void main(String[] args) { - new Test().howdy(); - } - } -} -/* Output: -Howdy! -*/ diff --git a/code/innerclasses/Contents.java b/code/innerclasses/Contents.java deleted file mode 100644 index 0cebe1a0..00000000 --- a/code/innerclasses/Contents.java +++ /dev/null @@ -1,7 +0,0 @@ -// innerclasses/Contents.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public interface Contents { - int value(); -} diff --git a/code/innerclasses/Destination.java b/code/innerclasses/Destination.java deleted file mode 100644 index bf221526..00000000 --- a/code/innerclasses/Destination.java +++ /dev/null @@ -1,7 +0,0 @@ -// innerclasses/Destination.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public interface Destination { - String readLabel(); -} diff --git a/code/innerclasses/DotNew.java b/code/innerclasses/DotNew.java deleted file mode 100644 index 317400e8..00000000 --- a/code/innerclasses/DotNew.java +++ /dev/null @@ -1,13 +0,0 @@ -// innerclasses/DotNew.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating an inner class directly using .new syntax - -public class DotNew { - public class Inner {} - public static void main(String[] args) { - DotNew dn = new DotNew(); - DotNew.Inner dni = dn.new Inner(); - } -} diff --git a/code/innerclasses/DotThis.java b/code/innerclasses/DotThis.java deleted file mode 100644 index b87cb1f4..00000000 --- a/code/innerclasses/DotThis.java +++ /dev/null @@ -1,24 +0,0 @@ -// innerclasses/DotThis.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Accessing the outer-class object - -public class DotThis { - void f() { System.out.println("DotThis.f()"); } - public class Inner { - public DotThis outer() { - return DotThis.this; - // A plain "this" would be Inner's "this" - } - } - public Inner inner() { return new Inner(); } - public static void main(String[] args) { - DotThis dt = new DotThis(); - DotThis.Inner dti = dt.inner(); - dti.outer().f(); - } -} -/* Output: -DotThis.f() -*/ diff --git a/code/innerclasses/GreenhouseController.java b/code/innerclasses/GreenhouseController.java deleted file mode 100644 index cf3ec653..00000000 --- a/code/innerclasses/GreenhouseController.java +++ /dev/null @@ -1,54 +0,0 @@ -// innerclasses/GreenhouseController.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Configure and execute the greenhouse system -import innerclasses.controller.*; - -public class GreenhouseController { - public static void main(String[] args) { - GreenhouseControls gc = new GreenhouseControls(); - // Instead of using code, you could parse - // configuration information from a text file: - gc.addEvent(gc.new Bell(900)); - Event[] eventList = { - gc.new ThermostatNight(0), - gc.new LightOn(200), - gc.new LightOff(400), - gc.new WaterOn(600), - gc.new WaterOff(800), - gc.new ThermostatDay(1400) - }; - gc.addEvent(gc.new Restart(2000, eventList)); - gc.addEvent( - new GreenhouseControls.Terminate(5000)); - gc.run(); - } -} -/* Output: -Thermostat on night setting -Light is on -Light is off -Greenhouse water is on -Greenhouse water is off -Bing! -Thermostat on day setting -Bing! -Restarting system -Thermostat on night setting -Light is on -Light is off -Greenhouse water is on -Bing! -Greenhouse water is off -Thermostat on day setting -Bing! -Restarting system -Thermostat on night setting -Light is on -Light is off -Bing! -Greenhouse water is on -Greenhouse water is off -Terminating -*/ diff --git a/code/innerclasses/GreenhouseControls.java b/code/innerclasses/GreenhouseControls.java deleted file mode 100644 index 57458d66..00000000 --- a/code/innerclasses/GreenhouseControls.java +++ /dev/null @@ -1,150 +0,0 @@ -// innerclasses/GreenhouseControls.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// This produces a specific application of the -// control system, all in a single class. Inner -// classes allow you to encapsulate different -// functionality for each type of event. -import innerclasses.controller.*; - -public class GreenhouseControls extends Controller { - private boolean light = false; - public class LightOn extends Event { - public LightOn(long delayTime) { - super(delayTime); - } - @Override - public void action() { - // Put hardware control code here to - // physically turn on the light. - light = true; - } - @Override - public String toString() { - return "Light is on"; - } - } - public class LightOff extends Event { - public LightOff(long delayTime) { - super(delayTime); - } - @Override - public void action() { - // Put hardware control code here to - // physically turn off the light. - light = false; - } - @Override - public String toString() { - return "Light is off"; - } - } - private boolean water = false; - public class WaterOn extends Event { - public WaterOn(long delayTime) { - super(delayTime); - } - @Override - public void action() { - // Put hardware control code here. - water = true; - } - @Override - public String toString() { - return "Greenhouse water is on"; - } - } - public class WaterOff extends Event { - public WaterOff(long delayTime) { - super(delayTime); - } - @Override - public void action() { - // Put hardware control code here. - water = false; - } - @Override - public String toString() { - return "Greenhouse water is off"; - } - } - private String thermostat = "Day"; - public class ThermostatNight extends Event { - public ThermostatNight(long delayTime) { - super(delayTime); - } - @Override - public void action() { - // Put hardware control code here. - thermostat = "Night"; - } - @Override - public String toString() { - return "Thermostat on night setting"; - } - } - public class ThermostatDay extends Event { - public ThermostatDay(long delayTime) { - super(delayTime); - } - @Override - public void action() { - // Put hardware control code here. - thermostat = "Day"; - } - @Override - public String toString() { - return "Thermostat on day setting"; - } - } - // An example of an action() that inserts a - // new one of itself into the event list: - public class Bell extends Event { - public Bell(long delayTime) { - super(delayTime); - } - @Override - public void action() { - addEvent(new Bell(delayTime.toMillis())); - } - @Override - public String toString() { - return "Bing!"; - } - } - public class Restart extends Event { - private Event[] eventList; - public - Restart(long delayTime, Event[] eventList) { - super(delayTime); - this.eventList = eventList; - for(Event e : eventList) - addEvent(e); - } - @Override - public void action() { - for(Event e : eventList) { - e.start(); // Rerun each event - addEvent(e); - } - start(); // Rerun this Event - addEvent(this); - } - @Override - public String toString() { - return "Restarting system"; - } - } - public static class Terminate extends Event { - public Terminate(long delayTime) { - super(delayTime); - } - @Override - public void action() { System.exit(0); } - @Override - public String toString() { - return "Terminating"; - } - } -} diff --git a/code/innerclasses/InheritInner.java b/code/innerclasses/InheritInner.java deleted file mode 100644 index ffc86894..00000000 --- a/code/innerclasses/InheritInner.java +++ /dev/null @@ -1,20 +0,0 @@ -// innerclasses/InheritInner.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Inheriting an inner class - -class WithInner { - class Inner {} -} - -public class InheritInner extends WithInner.Inner { - //- InheritInner() {} // Won't compile - InheritInner(WithInner wi) { - wi.super(); - } - public static void main(String[] args) { - WithInner wi = new WithInner(); - InheritInner ii = new InheritInner(wi); - } -} diff --git a/code/innerclasses/LocalInnerClass.java b/code/innerclasses/LocalInnerClass.java deleted file mode 100644 index 01510854..00000000 --- a/code/innerclasses/LocalInnerClass.java +++ /dev/null @@ -1,67 +0,0 @@ -// innerclasses/LocalInnerClass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Holds a sequence of Objects - -interface Counter { - int next(); -} - -public class LocalInnerClass { - private int count = 0; - Counter getCounter(final String name) { - // A local inner class: - class LocalCounter implements Counter { - LocalCounter() { - // Local inner class can have a constructor - System.out.println("LocalCounter()"); - } - @Override - public int next() { - System.out.print(name); // Access local final - return count++; - } - } - return new LocalCounter(); - } - // Repeat, but with an anonymous inner class: - Counter getCounter2(final String name) { - return new Counter() { - // Anonymous inner class cannot have a named - // constructor, only an instance initializer: - { - System.out.println("Counter()"); - } - @Override - public int next() { - System.out.print(name); // Access local final - return count++; - } - }; - } - public static void main(String[] args) { - LocalInnerClass lic = new LocalInnerClass(); - Counter - c1 = lic.getCounter("Local inner "), - c2 = lic.getCounter2("Anonymous inner "); - for(int i = 0; i < 5; i++) - System.out.println(c1.next()); - for(int i = 0; i < 5; i++) - System.out.println(c2.next()); - } -} -/* Output: -LocalCounter() -Counter() -Local inner 0 -Local inner 1 -Local inner 2 -Local inner 3 -Local inner 4 -Anonymous inner 5 -Anonymous inner 6 -Anonymous inner 7 -Anonymous inner 8 -Anonymous inner 9 -*/ diff --git a/code/innerclasses/MultiImplementation.java b/code/innerclasses/MultiImplementation.java deleted file mode 100644 index 6eb6c494..00000000 --- a/code/innerclasses/MultiImplementation.java +++ /dev/null @@ -1,25 +0,0 @@ -// innerclasses/MultiImplementation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// For concrete or abstract classes, inner classes -// produce "multiple implementation inheritance" -// {java innerclasses.MultiImplementation} -package innerclasses; - -class D {} -abstract class E {} - -class Z extends D { - E makeE() { return new E() {}; } -} - -public class MultiImplementation { - static void takesD(D d) {} - static void takesE(E e) {} - public static void main(String[] args) { - Z z = new Z(); - takesD(z); - takesE(z.makeE()); - } -} diff --git a/code/innerclasses/MultiNestingAccess.java b/code/innerclasses/MultiNestingAccess.java deleted file mode 100644 index bf9e3cb0..00000000 --- a/code/innerclasses/MultiNestingAccess.java +++ /dev/null @@ -1,28 +0,0 @@ -// innerclasses/MultiNestingAccess.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Nested classes can access all members of all -// levels of the classes they are nested within - -class MNA { - private void f() {} - class A { - private void g() {} - public class B { - void h() { - g(); - f(); - } - } - } -} - -public class MultiNestingAccess { - public static void main(String[] args) { - MNA mna = new MNA(); - MNA.A mnaa = mna.new A(); - MNA.A.B mnaab = mnaa.new B(); - mnaab.h(); - } -} diff --git a/code/innerclasses/Parcel1.java b/code/innerclasses/Parcel1.java deleted file mode 100644 index 94464cbc..00000000 --- a/code/innerclasses/Parcel1.java +++ /dev/null @@ -1,33 +0,0 @@ -// innerclasses/Parcel1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating inner classes - -public class Parcel1 { - class Contents { - private int i = 11; - public int value() { return i; } - } - class Destination { - private String label; - Destination(String whereTo) { - label = whereTo; - } - String readLabel() { return label; } - } - // Using inner classes looks just like - // using any other class, within Parcel1: - public void ship(String dest) { - Contents c = new Contents(); - Destination d = new Destination(dest); - System.out.println(d.readLabel()); - } - public static void main(String[] args) { - Parcel1 p = new Parcel1(); - p.ship("Tasmania"); - } -} -/* Output: -Tasmania -*/ diff --git a/code/innerclasses/Parcel10.java b/code/innerclasses/Parcel10.java deleted file mode 100644 index 7150c192..00000000 --- a/code/innerclasses/Parcel10.java +++ /dev/null @@ -1,31 +0,0 @@ -// innerclasses/Parcel10.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using "instance initialization" to perform -// construction on an anonymous inner class - -public class Parcel10 { - public Destination - destination(final String dest, final float price) { - return new Destination() { - private int cost; - // Instance initialization for each object: - { - cost = Math.round(price); - if(cost > 100) - System.out.println("Over budget!"); - } - private String label = dest; - @Override - public String readLabel() { return label; } - }; - } - public static void main(String[] args) { - Parcel10 p = new Parcel10(); - Destination d = p.destination("Tasmania", 101.395F); - } -} -/* Output: -Over budget! -*/ diff --git a/code/innerclasses/Parcel11.java b/code/innerclasses/Parcel11.java deleted file mode 100644 index 720981f0..00000000 --- a/code/innerclasses/Parcel11.java +++ /dev/null @@ -1,40 +0,0 @@ -// innerclasses/Parcel11.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Nested classes (static inner classes) - -public class Parcel11 { - private static class - ParcelContents implements Contents { - private int i = 11; - @Override - public int value() { return i; } - } - protected static final class ParcelDestination - implements Destination { - private String label; - private ParcelDestination(String whereTo) { - label = whereTo; - } - @Override - public String readLabel() { return label; } - // Nested classes can contain other static elements: - public static void f() {} - static int x = 10; - static class AnotherLevel { - public static void f() {} - static int x = 10; - } - } - public static Destination destination(String s) { - return new ParcelDestination(s); - } - public static Contents contents() { - return new ParcelContents(); - } - public static void main(String[] args) { - Contents c = contents(); - Destination d = destination("Tasmania"); - } -} diff --git a/code/innerclasses/Parcel2.java b/code/innerclasses/Parcel2.java deleted file mode 100644 index 1eca5cba..00000000 --- a/code/innerclasses/Parcel2.java +++ /dev/null @@ -1,41 +0,0 @@ -// innerclasses/Parcel2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Returning a reference to an inner class - -public class Parcel2 { - class Contents { - private int i = 11; - public int value() { return i; } - } - class Destination { - private String label; - Destination(String whereTo) { - label = whereTo; - } - String readLabel() { return label; } - } - public Destination to(String s) { - return new Destination(s); - } - public Contents contents() { - return new Contents(); - } - public void ship(String dest) { - Contents c = contents(); - Destination d = to(dest); - System.out.println(d.readLabel()); - } - public static void main(String[] args) { - Parcel2 p = new Parcel2(); - p.ship("Tasmania"); - Parcel2 q = new Parcel2(); - // Defining references to inner classes: - Parcel2.Contents c = q.contents(); - Parcel2.Destination d = q.to("Borneo"); - } -} -/* Output: -Tasmania -*/ diff --git a/code/innerclasses/Parcel3.java b/code/innerclasses/Parcel3.java deleted file mode 100644 index 2e0733e0..00000000 --- a/code/innerclasses/Parcel3.java +++ /dev/null @@ -1,25 +0,0 @@ -// innerclasses/Parcel3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using .new to create instances of inner classes - -public class Parcel3 { - class Contents { - private int i = 11; - public int value() { return i; } - } - class Destination { - private String label; - Destination(String whereTo) { label = whereTo; } - String readLabel() { return label; } - } - public static void main(String[] args) { - Parcel3 p = new Parcel3(); - // Must use instance of outer class - // to create an instance of the inner class: - Parcel3.Contents c = p.new Contents(); - Parcel3.Destination d = - p.new Destination("Tasmania"); - } -} diff --git a/code/innerclasses/Parcel5.java b/code/innerclasses/Parcel5.java deleted file mode 100644 index 622b3fd0..00000000 --- a/code/innerclasses/Parcel5.java +++ /dev/null @@ -1,23 +0,0 @@ -// innerclasses/Parcel5.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Nesting a class within a method - -public class Parcel5 { - public Destination destination(String s) { - final class PDestination implements Destination { - private String label; - private PDestination(String whereTo) { - label = whereTo; - } - @Override - public String readLabel() { return label; } - } - return new PDestination(s); - } - public static void main(String[] args) { - Parcel5 p = new Parcel5(); - Destination d = p.destination("Tasmania"); - } -} diff --git a/code/innerclasses/Parcel6.java b/code/innerclasses/Parcel6.java deleted file mode 100644 index 7a2c866e..00000000 --- a/code/innerclasses/Parcel6.java +++ /dev/null @@ -1,28 +0,0 @@ -// innerclasses/Parcel6.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Nesting a class within a scope - -public class Parcel6 { - private void internalTracking(boolean b) { - if(b) { - class TrackingSlip { - private String id; - TrackingSlip(String s) { - id = s; - } - String getSlip() { return id; } - } - TrackingSlip ts = new TrackingSlip("slip"); - String s = ts.getSlip(); - } - // Can't use it here! Out of scope: - //- TrackingSlip ts = new TrackingSlip("x"); - } - public void track() { internalTracking(true); } - public static void main(String[] args) { - Parcel6 p = new Parcel6(); - p.track(); - } -} diff --git a/code/innerclasses/Parcel7.java b/code/innerclasses/Parcel7.java deleted file mode 100644 index 3a4aefbb..00000000 --- a/code/innerclasses/Parcel7.java +++ /dev/null @@ -1,19 +0,0 @@ -// innerclasses/Parcel7.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Returning an instance of an anonymous inner class - -public class Parcel7 { - public Contents contents() { - return new Contents() { // Insert class definition - private int i = 11; - @Override - public int value() { return i; } - }; // Semicolon required - } - public static void main(String[] args) { - Parcel7 p = new Parcel7(); - Contents c = p.contents(); - } -} diff --git a/code/innerclasses/Parcel7b.java b/code/innerclasses/Parcel7b.java deleted file mode 100644 index bee95727..00000000 --- a/code/innerclasses/Parcel7b.java +++ /dev/null @@ -1,20 +0,0 @@ -// innerclasses/Parcel7b.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Expanded version of Parcel7.java - -public class Parcel7b { - class MyContents implements Contents { - private int i = 11; - @Override - public int value() { return i; } - } - public Contents contents() { - return new MyContents(); - } - public static void main(String[] args) { - Parcel7b p = new Parcel7b(); - Contents c = p.contents(); - } -} diff --git a/code/innerclasses/Parcel8.java b/code/innerclasses/Parcel8.java deleted file mode 100644 index 1e615ac5..00000000 --- a/code/innerclasses/Parcel8.java +++ /dev/null @@ -1,21 +0,0 @@ -// innerclasses/Parcel8.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Calling the base-class constructor - -public class Parcel8 { - public Wrapping wrapping(int x) { - // Base constructor call: - return new Wrapping(x) { // [1] - @Override - public int value() { - return super.value() * 47; - } - }; // [2] - } - public static void main(String[] args) { - Parcel8 p = new Parcel8(); - Wrapping w = p.wrapping(10); - } -} diff --git a/code/innerclasses/Parcel9.java b/code/innerclasses/Parcel9.java deleted file mode 100644 index 775390f1..00000000 --- a/code/innerclasses/Parcel9.java +++ /dev/null @@ -1,20 +0,0 @@ -// innerclasses/Parcel9.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Parcel9 { - // Argument must be final or "effectively final" - // to use within the anonymous inner class: - public Destination destination(final String dest) { - return new Destination() { - private String label = dest; - @Override - public String readLabel() { return label; } - }; - } - public static void main(String[] args) { - Parcel9 p = new Parcel9(); - Destination d = p.destination("Tasmania"); - } -} diff --git a/code/innerclasses/Sequence.java b/code/innerclasses/Sequence.java deleted file mode 100644 index b5a870b9..00000000 --- a/code/innerclasses/Sequence.java +++ /dev/null @@ -1,48 +0,0 @@ -// innerclasses/Sequence.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Holds a sequence of Objects - -interface Selector { - boolean end(); - Object current(); - void next(); -} - -public class Sequence { - private Object[] items; - private int next = 0; - public Sequence(int size) { - items = new Object[size]; - } - public void add(Object x) { - if(next < items.length) - items[next++] = x; - } - private class SequenceSelector implements Selector { - private int i = 0; - @Override - public boolean end() { return i == items.length; } - @Override - public Object current() { return items[i]; } - @Override - public void next() { if(i < items.length) i++; } - } - public Selector selector() { - return new SequenceSelector(); - } - public static void main(String[] args) { - Sequence sequence = new Sequence(10); - for(int i = 0; i < 10; i++) - sequence.add(Integer.toString(i)); - Selector selector = sequence.selector(); - while(!selector.end()) { - System.out.print(selector.current() + " "); - selector.next(); - } - } -} -/* Output: -0 1 2 3 4 5 6 7 8 9 -*/ diff --git a/code/innerclasses/TestBed.java b/code/innerclasses/TestBed.java deleted file mode 100644 index d4bc16dd..00000000 --- a/code/innerclasses/TestBed.java +++ /dev/null @@ -1,19 +0,0 @@ -// innerclasses/TestBed.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Putting test code in a nested class -// {java TestBed$Tester} - -public class TestBed { - public void f() { System.out.println("f()"); } - public static class Tester { - public static void main(String[] args) { - TestBed t = new TestBed(); - t.f(); - } - } -} -/* Output: -f() -*/ diff --git a/code/innerclasses/TestParcel.java b/code/innerclasses/TestParcel.java deleted file mode 100644 index f1ec5d47..00000000 --- a/code/innerclasses/TestParcel.java +++ /dev/null @@ -1,37 +0,0 @@ -// innerclasses/TestParcel.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Parcel4 { - private class PContents implements Contents { - private int i = 11; - @Override - public int value() { return i; } - } - protected final class - PDestination implements Destination { - private String label; - private PDestination(String whereTo) { - label = whereTo; - } - @Override - public String readLabel() { return label; } - } - public Destination destination(String s) { - return new PDestination(s); - } - public Contents contents() { - return new PContents(); - } -} - -public class TestParcel { - public static void main(String[] args) { - Parcel4 p = new Parcel4(); - Contents c = p.contents(); - Destination d = p.destination("Tasmania"); - // Illegal -- can't access private class: - //- Parcel4.PContents pc = p.new PContents(); - } -} diff --git a/code/innerclasses/Wrapping.java b/code/innerclasses/Wrapping.java deleted file mode 100644 index 651c0748..00000000 --- a/code/innerclasses/Wrapping.java +++ /dev/null @@ -1,9 +0,0 @@ -// innerclasses/Wrapping.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -public class Wrapping { - private int i; - public Wrapping(int x) { i = x; } - public int value() { return i; } -} diff --git a/code/innerclasses/controller/Controller.java b/code/innerclasses/controller/Controller.java deleted file mode 100644 index 9a3625b3..00000000 --- a/code/innerclasses/controller/Controller.java +++ /dev/null @@ -1,24 +0,0 @@ -// innerclasses/controller/Controller.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The reusable framework for control systems -package innerclasses.controller; -import java.util.*; - -public class Controller { - // A class from java.util to hold Event objects: - private List eventList = new ArrayList<>(); - public void addEvent(Event c) { eventList.add(c); } - public void run() { - while(eventList.size() > 0) - // Make a copy so you're not modifying the list - // while you're selecting the elements in it: - for(Event e : new ArrayList<>(eventList)) - if(e.ready()) { - System.out.println(e); - e.action(); - eventList.remove(e); - } - } -} diff --git a/code/innerclasses/controller/Event.java b/code/innerclasses/controller/Event.java deleted file mode 100644 index 5523168f..00000000 --- a/code/innerclasses/controller/Event.java +++ /dev/null @@ -1,23 +0,0 @@ -// innerclasses/controller/Event.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The common methods for any control event -package innerclasses.controller; -import java.time.*; // Java 8 time classes - -public abstract class Event { - private Instant eventTime; - protected final Duration delayTime; - public Event(long millisecondDelay) { - delayTime = Duration.ofMillis(millisecondDelay); - start(); - } - public void start() { // Allows restarting - eventTime = Instant.now().plus(delayTime); - } - public boolean ready() { - return Instant.now().isAfter(eventTime); - } - public abstract void action(); -} diff --git a/code/innerclasses/mui/MultiInterfaces.java b/code/innerclasses/mui/MultiInterfaces.java deleted file mode 100644 index 127a6c80..00000000 --- a/code/innerclasses/mui/MultiInterfaces.java +++ /dev/null @@ -1,32 +0,0 @@ -// innerclasses/mui/MultiInterfaces.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Two ways a class can implement multiple interfaces -// {java innerclasses.mui.MultiInterfaces} -package innerclasses.mui; - -interface A {} -interface B {} - -class X implements A, B {} - -class Y implements A { - B makeB() { - // Anonymous inner class: - return new B() {}; - } -} - -public class MultiInterfaces { - static void takesA(A a) {} - static void takesB(B b) {} - public static void main(String[] args) { - X x = new X(); - Y y = new Y(); - takesA(x); - takesA(y); - takesB(x); - takesB(y.makeB()); - } -} diff --git a/code/interfaces/AbstractAccess.java b/code/interfaces/AbstractAccess.java deleted file mode 100644 index c2e43da3..00000000 --- a/code/interfaces/AbstractAccess.java +++ /dev/null @@ -1,15 +0,0 @@ -// interfaces/AbstractAccess.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -abstract class AbstractAccess { - private void m1() {} - // private abstract void m1a(); // illegal - protected void m2() {} - protected abstract void m2a(); - void m3() {} - abstract void m3a(); - public void m4() {} - public abstract void m4a(); -} diff --git a/code/interfaces/AbstractWithoutAbstracts.java b/code/interfaces/AbstractWithoutAbstracts.java deleted file mode 100644 index 2e6b700c..00000000 --- a/code/interfaces/AbstractWithoutAbstracts.java +++ /dev/null @@ -1,14 +0,0 @@ -// interfaces/AbstractWithoutAbstracts.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -abstract class Basic3 { - int f() { return 111; } - // No abstract methods -} - -public class AbstractWithoutAbstracts { - // Basic3 b3 = new Basic3(); - // error: Basic3 is abstract; cannot be instantiated -} diff --git a/code/interfaces/AdaptedRandomDoubles.java b/code/interfaces/AdaptedRandomDoubles.java deleted file mode 100644 index 6c786655..00000000 --- a/code/interfaces/AdaptedRandomDoubles.java +++ /dev/null @@ -1,35 +0,0 @@ -// interfaces/AdaptedRandomDoubles.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating an adapter with inheritance -import java.nio.*; -import java.util.*; - -public class AdaptedRandomDoubles -implements RandomDoubles, Readable { - private int count; - public AdaptedRandomDoubles(int count) { - this.count = count; - } - @Override - public int read(CharBuffer cb) { - if(count-- == 0) - return -1; - String result = Double.toString(next()) + " "; - cb.append(result); - return result.length(); - } - public static void main(String[] args) { - Scanner s = - new Scanner(new AdaptedRandomDoubles(7)); - while(s.hasNextDouble()) - System.out.print(s.nextDouble() + " "); - } -} -/* Output: -0.7271157860730044 0.5309454508634242 -0.16020656493302599 0.18847866977771732 -0.5166020801268457 0.2678662084200585 -0.2613610344283964 -*/ diff --git a/code/interfaces/Adventure.java b/code/interfaces/Adventure.java deleted file mode 100644 index 1a7135d1..00000000 --- a/code/interfaces/Adventure.java +++ /dev/null @@ -1,41 +0,0 @@ -// interfaces/Adventure.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Multiple interfaces - -interface CanFight { - void fight(); -} - -interface CanSwim { - void swim(); -} - -interface CanFly { - void fly(); -} - -class ActionCharacter { - public void fight() {} -} - -class Hero extends ActionCharacter - implements CanFight, CanSwim, CanFly { - public void swim() {} - public void fly() {} -} - -public class Adventure { - public static void t(CanFight x) { x.fight(); } - public static void u(CanSwim x) { x.swim(); } - public static void v(CanFly x) { x.fly(); } - public static void w(ActionCharacter x) { x.fight(); } - public static void main(String[] args) { - Hero h = new Hero(); - t(h); // Treat it as a CanFight - u(h); // Treat it as a CanSwim - v(h); // Treat it as a CanFly - w(h); // Treat it as an ActionCharacter - } -} diff --git a/code/interfaces/AnImplementation.java b/code/interfaces/AnImplementation.java deleted file mode 100644 index 3ff13a30..00000000 --- a/code/interfaces/AnImplementation.java +++ /dev/null @@ -1,22 +0,0 @@ -// interfaces/AnImplementation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class AnImplementation implements AnInterface { - public void firstMethod() { - System.out.println("firstMethod"); - } - public void secondMethod() { - System.out.println("secondMethod"); - } - public static void main(String[] args) { - AnInterface i = new AnImplementation(); - i.firstMethod(); - i.secondMethod(); - } -} -/* Output: -firstMethod -secondMethod -*/ diff --git a/code/interfaces/AnInterface.java b/code/interfaces/AnInterface.java deleted file mode 100644 index 30f82b3a..00000000 --- a/code/interfaces/AnInterface.java +++ /dev/null @@ -1,9 +0,0 @@ -// interfaces/AnInterface.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface AnInterface { - void firstMethod(); - void secondMethod(); -} diff --git a/code/interfaces/Applicator.java b/code/interfaces/Applicator.java deleted file mode 100644 index a6aa172f..00000000 --- a/code/interfaces/Applicator.java +++ /dev/null @@ -1,58 +0,0 @@ -// interfaces/Applicator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class Processor { - public String name() { - return getClass().getSimpleName(); - } - public Object process(Object input) { - return input; - } -} - -class Upcase extends Processor { - @Override // Covariant return: - public String process(Object input) { - return ((String)input).toUpperCase(); - } -} - -class Downcase extends Processor { - @Override - public String process(Object input) { - return ((String)input).toLowerCase(); - } -} - -class Splitter extends Processor { - @Override - public String process(Object input) { - // split() divides a String into pieces: - return Arrays.toString(((String)input).split(" ")); - } -} - -public class Applicator { - public static void apply(Processor p, Object s) { - System.out.println("Using Processor " + p.name()); - System.out.println(p.process(s)); - } - public static void main(String[] args) { - String s = - "We are such stuff as dreams are made on"; - apply(new Upcase(), s); - apply(new Downcase(), s); - apply(new Splitter(), s); - } -} -/* Output: -Using Processor Upcase -WE ARE SUCH STUFF AS DREAMS ARE MADE ON -Using Processor Downcase -we are such stuff as dreams are made on -Using Processor Splitter -[We, are, such, stuff, as, dreams, are, made, on] -*/ diff --git a/code/interfaces/AttemptToUseBasic.java b/code/interfaces/AttemptToUseBasic.java deleted file mode 100644 index 0d265527..00000000 --- a/code/interfaces/AttemptToUseBasic.java +++ /dev/null @@ -1,10 +0,0 @@ -// interfaces/AttemptToUseBasic.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} - -public class AttemptToUseBasic { - Basic b = new Basic(); - // error: Basic is abstract; cannot be instantiated -} diff --git a/code/interfaces/Basic.java b/code/interfaces/Basic.java deleted file mode 100644 index 19c1c75b..00000000 --- a/code/interfaces/Basic.java +++ /dev/null @@ -1,8 +0,0 @@ -// interfaces/Basic.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -abstract class Basic { - abstract void unimplemented(); -} diff --git a/code/interfaces/Basic2.java b/code/interfaces/Basic2.java deleted file mode 100644 index 4c8f0c93..00000000 --- a/code/interfaces/Basic2.java +++ /dev/null @@ -1,10 +0,0 @@ -// interfaces/Basic2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -abstract class Basic2 extends Basic { - int f() { return 111; } - abstract void g(); - // unimplemented() still not implemented -} diff --git a/code/interfaces/Factories.java b/code/interfaces/Factories.java deleted file mode 100644 index 87e28251..00000000 --- a/code/interfaces/Factories.java +++ /dev/null @@ -1,67 +0,0 @@ -// interfaces/Factories.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface Service { - void method1(); - void method2(); -} - -interface ServiceFactory { - Service getService(); -} - -class Service1 implements Service { - Service1() {} // Package access - public void method1() { - System.out.println("Service1 method1"); - } - public void method2() { - System.out.println("Service1 method2"); - } -} - -class Service1Factory implements ServiceFactory { - @Override - public Service getService() { - return new Service1(); - } -} - -class Service2 implements Service { - Service2() {} // Package access - public void method1() { - System.out.println("Service2 method1"); - } - public void method2() { - System.out.println("Service2 method2"); - } -} - -class Service2Factory implements ServiceFactory { - @Override - public Service getService() { - return new Service2(); - } -} - -public class Factories { - public static void - serviceConsumer(ServiceFactory fact) { - Service s = fact.getService(); - s.method1(); - s.method2(); - } - public static void main(String[] args) { - serviceConsumer(new Service1Factory()); - // Services are completely interchangeable: - serviceConsumer(new Service2Factory()); - } -} -/* Output: -Service1 method1 -Service1 method2 -Service2 method1 -Service2 method2 -*/ diff --git a/code/interfaces/Games.java b/code/interfaces/Games.java deleted file mode 100644 index 867efe0c..00000000 --- a/code/interfaces/Games.java +++ /dev/null @@ -1,59 +0,0 @@ -// interfaces/Games.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A Game framework using Factory Methods - -interface Game { boolean move(); } -interface GameFactory { Game getGame(); } - -class Checkers implements Game { - private int moves = 0; - private static final int MOVES = 3; - @Override - public boolean move() { - System.out.println("Checkers move " + moves); - return ++moves != MOVES; - } -} - -class CheckersFactory implements GameFactory { - @Override - public Game getGame() { return new Checkers(); } -} - -class Chess implements Game { - private int moves = 0; - private static final int MOVES = 4; - @Override - public boolean move() { - System.out.println("Chess move " + moves); - return ++moves != MOVES; - } -} - -class ChessFactory implements GameFactory { - @Override - public Game getGame() { return new Chess(); } -} - -public class Games { - public static void playGame(GameFactory factory) { - Game s = factory.getGame(); - while(s.move()) - ; - } - public static void main(String[] args) { - playGame(new CheckersFactory()); - playGame(new ChessFactory()); - } -} -/* Output: -Checkers move 0 -Checkers move 1 -Checkers move 2 -Chess move 0 -Chess move 1 -Chess move 2 -Chess move 3 -*/ diff --git a/code/interfaces/HorrorShow.java b/code/interfaces/HorrorShow.java deleted file mode 100644 index b1c687da..00000000 --- a/code/interfaces/HorrorShow.java +++ /dev/null @@ -1,57 +0,0 @@ -// interfaces/HorrorShow.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Extending an interface with inheritance - -interface Monster { - void menace(); -} - -interface DangerousMonster extends Monster { - void destroy(); -} - -interface Lethal { - void kill(); -} - -class DragonZilla implements DangerousMonster { - @Override - public void menace() {} - @Override - public void destroy() {} -} - -interface Vampire extends DangerousMonster, Lethal { - void drinkBlood(); -} - -class VeryBadVampire implements Vampire { - @Override - public void menace() {} - @Override - public void destroy() {} - @Override - public void kill() {} - @Override - public void drinkBlood() {} -} - -public class HorrorShow { - static void u(Monster b) { b.menace(); } - static void v(DangerousMonster d) { - d.menace(); - d.destroy(); - } - static void w(Lethal l) { l.kill(); } - public static void main(String[] args) { - DangerousMonster barney = new DragonZilla(); - u(barney); - v(barney); - Vampire vlad = new VeryBadVampire(); - u(vlad); - v(vlad); - w(vlad); - } -} diff --git a/code/interfaces/Implementation2.java b/code/interfaces/Implementation2.java deleted file mode 100644 index 61c6efa0..00000000 --- a/code/interfaces/Implementation2.java +++ /dev/null @@ -1,26 +0,0 @@ -// interfaces/Implementation2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Implementation2 -implements InterfaceWithDefault { - public void firstMethod() { - System.out.println("firstMethod"); - } - public void secondMethod() { - System.out.println("secondMethod"); - } - public static void main(String[] args) { - InterfaceWithDefault i = - new Implementation2(); - i.firstMethod(); - i.secondMethod(); - i.newMethod(); - } -} -/* Output: -firstMethod -secondMethod -newMethod -*/ diff --git a/code/interfaces/ImplementingAnInterface.java b/code/interfaces/ImplementingAnInterface.java deleted file mode 100644 index 6a13ebb6..00000000 --- a/code/interfaces/ImplementingAnInterface.java +++ /dev/null @@ -1,14 +0,0 @@ -// interfaces/ImplementingAnInterface.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface Concept { // Package access - void idea1(); - void idea2(); -} - -class Implementation implements Concept { - public void idea1() { System.out.println("idea1"); } - public void idea2() { System.out.println("idea2"); } -} diff --git a/code/interfaces/Instantiable.java b/code/interfaces/Instantiable.java deleted file mode 100644 index 427b6ca3..00000000 --- a/code/interfaces/Instantiable.java +++ /dev/null @@ -1,19 +0,0 @@ -// interfaces/Instantiable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -abstract class Uninstantiable { - abstract void f(); - abstract int g(); -} - -public class Instantiable extends Uninstantiable { - @Override - void f() { System.out.println("f()"); } - @Override - int g() { return 22; } - public static void main(String[] args) { - Uninstantiable ui = new Instantiable(); - } -} diff --git a/code/interfaces/InterfaceCollision.java b/code/interfaces/InterfaceCollision.java deleted file mode 100644 index 0f7de1ac..00000000 --- a/code/interfaces/InterfaceCollision.java +++ /dev/null @@ -1,31 +0,0 @@ -// interfaces/InterfaceCollision.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface I1 { void f(); } -interface I2 { int f(int i); } -interface I3 { int f(); } -class C { public int f() { return 1; } } - -class C2 implements I1, I2 { - @Override - public void f() {} - @Override - public int f(int i) { return 1; } // overloaded -} - -class C3 extends C implements I2 { - @Override - public int f(int i) { return 1; } // overloaded -} - -class C4 extends C implements I3 { - // Identical, no problem: - @Override - public int f() { return 1; } -} - -// Methods differ only by return type: -//- class C5 extends C implements I1 {} -//- interface I4 extends I1, I3 {} diff --git a/code/interfaces/InterfaceWithDefault.java b/code/interfaces/InterfaceWithDefault.java deleted file mode 100644 index a87f02db..00000000 --- a/code/interfaces/InterfaceWithDefault.java +++ /dev/null @@ -1,12 +0,0 @@ -// interfaces/InterfaceWithDefault.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface InterfaceWithDefault { - void firstMethod(); - void secondMethod(); - default void newMethod() { - System.out.println("newMethod"); - } -} diff --git a/code/interfaces/Jim.java b/code/interfaces/Jim.java deleted file mode 100644 index 515db6e5..00000000 --- a/code/interfaces/Jim.java +++ /dev/null @@ -1,28 +0,0 @@ -// interfaces/Jim.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -interface Jim1 { - default void jim() { - System.out.println("Jim1::jim"); - } -} - -interface Jim2 { - default void jim() { - System.out.println("Jim2::jim"); - } -} - -public class Jim implements Jim1, Jim2 { - @Override - public void jim() { Jim2.super.jim(); } - public static void main(String[] args) { - new Jim().jim(); - } -} -/* Output: -Jim2::jim -*/ diff --git a/code/interfaces/MICollision.java b/code/interfaces/MICollision.java deleted file mode 100644 index c96e5696..00000000 --- a/code/interfaces/MICollision.java +++ /dev/null @@ -1,60 +0,0 @@ -// interfaces/MICollision.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -interface Bob1 { - default void bob() { - System.out.println("Bob1::bob"); - } -} - -interface Bob2 { - default void bob() { - System.out.println("Bob2::bob"); - } -} - -// class Bob implements Bob1, Bob2 {} -/* Produces: -error: class Bob inherits unrelated defaults -for bob() from types Bob1 and Bob2 -class Bob implements Bob1, Bob2 {} -^ -1 error -*/ - -interface Sam1 { - default void sam() { - System.out.println("Sam1::sam"); - } -} - -interface Sam2 { - default void sam(int i) { - System.out.println(i * 2); - } -} - -// This works because the argument lists are distinct: -class Sam implements Sam1, Sam2 {} - -interface Max1 { - default void max() { - System.out.println("Max1::max"); - } -} - -interface Max2 { - default int max() { return 47; } -} - -// class Max implements Max1, Max2 {} -/* Produces: -error: types Max2 and Max1 are incompatible; -both define max(), but with unrelated return types -class Max implements Max1, Max2 {} -^ -1 error -*/ diff --git a/code/interfaces/Machine.java b/code/interfaces/Machine.java deleted file mode 100644 index 2b1144ae..00000000 --- a/code/interfaces/Machine.java +++ /dev/null @@ -1,36 +0,0 @@ -// interfaces/Machine.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.Operations; - -class Bing implements Operations { - public void execute() { - Operations.show("Bing"); - } -} - -class Crack implements Operations { - public void execute() { - Operations.show("Crack"); - } -} - -class Twist implements Operations { - public void execute() { - Operations.show("Twist"); - } -} - -public class Machine { - public static void main(String[] args) { - Operations.runOps( - new Bing(), new Crack(), new Twist()); - } -} -/* Output: -Bing -Crack -Twist -*/ diff --git a/code/interfaces/Months.java b/code/interfaces/Months.java deleted file mode 100644 index 27317dd5..00000000 --- a/code/interfaces/Months.java +++ /dev/null @@ -1,13 +0,0 @@ -// interfaces/Months.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using interfaces to create groups of constants - -public interface Months { - int - JANUARY = 1, FEBRUARY = 2, MARCH = 3, - APRIL = 4, MAY = 5, JUNE = 6, JULY = 7, - AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10, - NOVEMBER = 11, DECEMBER = 12; -} diff --git a/code/interfaces/MultipleInheritance.java b/code/interfaces/MultipleInheritance.java deleted file mode 100644 index 6ce9c91e..00000000 --- a/code/interfaces/MultipleInheritance.java +++ /dev/null @@ -1,35 +0,0 @@ -// interfaces/MultipleInheritance.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -interface One { - default void first() { System.out.println("first"); } -} - -interface Two { - default void second() { - System.out.println("second"); - } -} - -interface Three { - default void third() { System.out.println("third"); } -} - -class MI implements One, Two, Three {} - -public class MultipleInheritance { - public static void main(String[] args) { - MI mi = new MI(); - mi.first(); - mi.second(); - mi.third(); - } -} -/* Output: -first -second -third -*/ diff --git a/code/interfaces/PureInterface.java b/code/interfaces/PureInterface.java deleted file mode 100644 index 37bf9f0b..00000000 --- a/code/interfaces/PureInterface.java +++ /dev/null @@ -1,11 +0,0 @@ -// interfaces/PureInterface.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Interface only looked like this before Java 8 - -public interface PureInterface { - int m1(); - void m2(); - double m3(); -} diff --git a/code/interfaces/RandVals.java b/code/interfaces/RandVals.java deleted file mode 100644 index 0221c851..00000000 --- a/code/interfaces/RandVals.java +++ /dev/null @@ -1,15 +0,0 @@ -// interfaces/RandVals.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Initializing interface fields with -// non-constant initializers -import java.util.*; - -public interface RandVals { - Random RAND = new Random(47); - int RANDOM_INT = RAND.nextInt(10); - long RANDOM_LONG = RAND.nextLong() * 10; - float RANDOM_FLOAT = RAND.nextLong() * 10; - double RANDOM_DOUBLE = RAND.nextDouble() * 10; -} diff --git a/code/interfaces/RandomDoubles.java b/code/interfaces/RandomDoubles.java deleted file mode 100644 index 99154d95..00000000 --- a/code/interfaces/RandomDoubles.java +++ /dev/null @@ -1,21 +0,0 @@ -// interfaces/RandomDoubles.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public interface RandomDoubles { - Random RAND = new Random(47); - default double next() { return RAND.nextDouble(); } - static void main(String[] args) { - RandomDoubles rd = new RandomDoubles() {}; - for(int i = 0; i < 7; i ++) - System.out.print(rd.next() + " "); - } -} -/* Output: -0.7271157860730044 0.5309454508634242 -0.16020656493302599 0.18847866977771732 -0.5166020801268457 0.2678662084200585 -0.2613610344283964 -*/ diff --git a/code/interfaces/RandomStrings.java b/code/interfaces/RandomStrings.java deleted file mode 100644 index 82f98230..00000000 --- a/code/interfaces/RandomStrings.java +++ /dev/null @@ -1,50 +0,0 @@ -// interfaces/RandomStrings.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Implementing an interface to conform to a method -import java.nio.*; -import java.util.*; - -public class RandomStrings implements Readable { - private static Random rand = new Random(47); - private static final char[] CAPITALS = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); - private static final char[] LOWERS = - "abcdefghijklmnopqrstuvwxyz".toCharArray(); - private static final char[] VOWELS = - "aeiou".toCharArray(); - private int count; - public RandomStrings(int count) { - this.count = count; - } - @Override - public int read(CharBuffer cb) { - if(count-- == 0) - return -1; // Indicates end of input - cb.append(CAPITALS[rand.nextInt(CAPITALS.length)]); - for(int i = 0; i < 4; i++) { - cb.append(VOWELS[rand.nextInt(VOWELS.length)]); - cb.append(LOWERS[rand.nextInt(LOWERS.length)]); - } - cb.append(" "); - return 10; // Number of characters appended - } - public static void main(String[] args) { - Scanner s = new Scanner(new RandomStrings(10)); - while(s.hasNext()) - System.out.println(s.next()); - } -} -/* Output: -Yazeruyac -Fowenucor -Goeazimom -Raeuuacio -Nuoadesiw -Hageaikux -Ruqicibui -Numasetih -Kuuuuozog -Waqizeyoy -*/ diff --git a/code/interfaces/TestRandVals.java b/code/interfaces/TestRandVals.java deleted file mode 100644 index df3490b2..00000000 --- a/code/interfaces/TestRandVals.java +++ /dev/null @@ -1,19 +0,0 @@ -// interfaces/TestRandVals.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class TestRandVals { - public static void main(String[] args) { - System.out.println(RandVals.RANDOM_INT); - System.out.println(RandVals.RANDOM_LONG); - System.out.println(RandVals.RANDOM_FLOAT); - System.out.println(RandVals.RANDOM_DOUBLE); - } -} -/* Output: -8 --32032247016559954 --8.5939291E18 -5.779976127815049 -*/ diff --git a/code/interfaces/filters/BandPass.java b/code/interfaces/filters/BandPass.java deleted file mode 100644 index 7d09ed28..00000000 --- a/code/interfaces/filters/BandPass.java +++ /dev/null @@ -1,17 +0,0 @@ -// interfaces/filters/BandPass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package interfaces.filters; - -public class BandPass extends Filter { - double lowCutoff, highCutoff; - public BandPass(double lowCut, double highCut) { - lowCutoff = lowCut; - highCutoff = highCut; - } - @Override - public Waveform process(Waveform input) { - return input; - } -} diff --git a/code/interfaces/filters/Filter.java b/code/interfaces/filters/Filter.java deleted file mode 100644 index 72e29a9e..00000000 --- a/code/interfaces/filters/Filter.java +++ /dev/null @@ -1,14 +0,0 @@ -// interfaces/filters/Filter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package interfaces.filters; - -public class Filter { - public String name() { - return getClass().getSimpleName(); - } - public Waveform process(Waveform input) { - return input; - } -} diff --git a/code/interfaces/filters/HighPass.java b/code/interfaces/filters/HighPass.java deleted file mode 100644 index 7bf047df..00000000 --- a/code/interfaces/filters/HighPass.java +++ /dev/null @@ -1,16 +0,0 @@ -// interfaces/filters/HighPass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package interfaces.filters; - -public class HighPass extends Filter { - double cutoff; - public HighPass(double cutoff) { - this.cutoff = cutoff; - } - @Override - public Waveform process(Waveform input) { - return input; - } -} diff --git a/code/interfaces/filters/LowPass.java b/code/interfaces/filters/LowPass.java deleted file mode 100644 index e9320a82..00000000 --- a/code/interfaces/filters/LowPass.java +++ /dev/null @@ -1,16 +0,0 @@ -// interfaces/filters/LowPass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package interfaces.filters; - -public class LowPass extends Filter { - double cutoff; - public LowPass(double cutoff) { - this.cutoff = cutoff; - } - @Override - public Waveform process(Waveform input) { - return input; // Dummy processing - } -} diff --git a/code/interfaces/filters/Waveform.java b/code/interfaces/filters/Waveform.java deleted file mode 100644 index 40644677..00000000 --- a/code/interfaces/filters/Waveform.java +++ /dev/null @@ -1,14 +0,0 @@ -// interfaces/filters/Waveform.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package interfaces.filters; - -public class Waveform { - private static long counter; - private final long id = counter++; - @Override - public String toString() { - return "Waveform " + id; - } -} diff --git a/code/interfaces/interfaceprocessor/Applicator.java b/code/interfaces/interfaceprocessor/Applicator.java deleted file mode 100644 index 77d7a9a6..00000000 --- a/code/interfaces/interfaceprocessor/Applicator.java +++ /dev/null @@ -1,12 +0,0 @@ -// interfaces/interfaceprocessor/Applicator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package interfaces.interfaceprocessor; - -public class Applicator { - public static void apply(Processor p, Object s) { - System.out.println("Using Processor " + p.name()); - System.out.println(p.process(s)); - } -} diff --git a/code/interfaces/interfaceprocessor/FilterProcessor.java b/code/interfaces/interfaceprocessor/FilterProcessor.java deleted file mode 100644 index 33689ed4..00000000 --- a/code/interfaces/interfaceprocessor/FilterProcessor.java +++ /dev/null @@ -1,40 +0,0 @@ -// interfaces/interfaceprocessor/FilterProcessor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java interfaces.interfaceprocessor.FilterProcessor} -package interfaces.interfaceprocessor; -import interfaces.filters.*; - -class FilterAdapter implements Processor { - Filter filter; - FilterAdapter(Filter filter) { - this.filter = filter; - } - @Override - public String name() { return filter.name(); } - @Override - public Waveform process(Object input) { - return filter.process((Waveform)input); - } -} - -public class FilterProcessor { - public static void main(String[] args) { - Waveform w = new Waveform(); - Applicator.apply( - new FilterAdapter(new LowPass(1.0)), w); - Applicator.apply( - new FilterAdapter(new HighPass(2.0)), w); - Applicator.apply( - new FilterAdapter(new BandPass(3.0, 4.0)), w); - } -} -/* Output: -Using Processor LowPass -Waveform 0 -Using Processor HighPass -Waveform 0 -Using Processor BandPass -Waveform 0 -*/ diff --git a/code/interfaces/interfaceprocessor/Processor.java b/code/interfaces/interfaceprocessor/Processor.java deleted file mode 100644 index 6315da30..00000000 --- a/code/interfaces/interfaceprocessor/Processor.java +++ /dev/null @@ -1,12 +0,0 @@ -// interfaces/interfaceprocessor/Processor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package interfaces.interfaceprocessor; - -public interface Processor { - default String name() { - return getClass().getSimpleName(); - } - Object process(Object input); -} diff --git a/code/interfaces/interfaceprocessor/StringProcessor.java b/code/interfaces/interfaceprocessor/StringProcessor.java deleted file mode 100644 index 37cb4946..00000000 --- a/code/interfaces/interfaceprocessor/StringProcessor.java +++ /dev/null @@ -1,50 +0,0 @@ -// interfaces/interfaceprocessor/StringProcessor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java interfaces.interfaceprocessor.StringProcessor} -package interfaces.interfaceprocessor; -import java.util.*; - -interface StringProcessor extends Processor { - @Override - String process(Object input); // [1] - String S = // [2] - "If she weighs the same as a duck, " + - "she's made of wood"; - static void main(String[] args) { // [3] - Applicator.apply(new Upcase(), S); - Applicator.apply(new Downcase(), S); - Applicator.apply(new Splitter(), S); - } -} - -class Upcase implements StringProcessor { - @Override // Covariant return: - public String process(Object input) { - return ((String)input).toUpperCase(); - } -} - -class Downcase implements StringProcessor { - @Override - public String process(Object input) { - return ((String)input).toLowerCase(); - } -} - -class Splitter implements StringProcessor { - @Override - public String process(Object input) { - return Arrays.toString(((String)input).split(" ")); - } -} -/* Output: -Using Processor Upcase -IF SHE WEIGHS THE SAME AS A DUCK, SHE'S MADE OF WOOD -Using Processor Downcase -if she weighs the same as a duck, she's made of wood -Using Processor Splitter -[If, she, weighs, the, same, as, a, duck,, she's, made, -of, wood] -*/ diff --git a/code/interfaces/music4/Music4.java b/code/interfaces/music4/Music4.java deleted file mode 100644 index 71034149..00000000 --- a/code/interfaces/music4/Music4.java +++ /dev/null @@ -1,105 +0,0 @@ -// interfaces/music4/Music4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Abstract classes and methods -// {java interfaces.music4.Music4} -package interfaces.music4; -import polymorphism.music.Note; - -abstract class Instrument { - private int i; // Storage allocated for each - public abstract void play(Note n); - public String what() { return "Instrument"; } - public abstract void adjust(); -} - -class Wind extends Instrument { - @Override - public void play(Note n) { - System.out.println("Wind.play() " + n); - } - @Override - public String what() { return "Wind"; } - @Override - public void adjust() { - System.out.println("Adjusting Wind"); - } -} - -class Percussion extends Instrument { - @Override - public void play(Note n) { - System.out.println("Percussion.play() " + n); - } - @Override - public String what() { return "Percussion"; } - @Override - public void adjust() { - System.out.println("Adjusting Percussion"); - } -} - -class Stringed extends Instrument { - @Override - public void play(Note n) { - System.out.println("Stringed.play() " + n); - } - @Override - public String what() { return "Stringed"; } - @Override - public void adjust() { - System.out.println("Adjusting Stringed"); - } -} - -class Brass extends Wind { - @Override - public void play(Note n) { - System.out.println("Brass.play() " + n); - } - @Override - public void adjust() { - System.out.println("Adjusting Brass"); - } -} - -class Woodwind extends Wind { - @Override - public void play(Note n) { - System.out.println("Woodwind.play() " + n); - } - @Override - public String what() { return "Woodwind"; } -} - -public class Music4 { - // Doesn't care about type, so new types - // added to the system still work right: - static void tune(Instrument i) { - // ... - i.play(Note.MIDDLE_C); - } - static void tuneAll(Instrument[] e) { - for(Instrument i : e) - tune(i); - } - public static void main(String[] args) { - // Upcasting during addition to the array: - Instrument[] orchestra = { - new Wind(), - new Percussion(), - new Stringed(), - new Brass(), - new Woodwind() - }; - tuneAll(orchestra); - } -} -/* Output: -Wind.play() MIDDLE_C -Percussion.play() MIDDLE_C -Stringed.play() MIDDLE_C -Brass.play() MIDDLE_C -Woodwind.play() MIDDLE_C -*/ diff --git a/code/interfaces/music5/Music5.java b/code/interfaces/music5/Music5.java deleted file mode 100644 index 2326bdbc..00000000 --- a/code/interfaces/music5/Music5.java +++ /dev/null @@ -1,74 +0,0 @@ -// interfaces/music5/Music5.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java interfaces.music5.Music5} -package interfaces.music5; -import polymorphism.music.Note; - -interface Instrument { - // Compile-time constant: - int VALUE = 5; // static & final - default void play(Note n) { // Automatically public - System.out.println(this + ".play() " + n); - } - default void adjust() { - System.out.println("Adjusting " + this); - } -} - -class Wind implements Instrument { - @Override - public String toString() { return "Wind"; } -} - -class Percussion implements Instrument { - @Override - public String toString() { return "Percussion"; } -} - -class Stringed implements Instrument { - @Override - public String toString() { return "Stringed"; } -} - -class Brass extends Wind { - @Override - public String toString() { return "Brass"; } -} - -class Woodwind extends Wind { - @Override - public String toString() { return "Woodwind"; } -} - -public class Music5 { - // Doesn't care about type, so new types - // added to the system still work right: - static void tune(Instrument i) { - // ... - i.play(Note.MIDDLE_C); - } - static void tuneAll(Instrument[] e) { - for(Instrument i : e) - tune(i); - } - public static void main(String[] args) { - // Upcasting during addition to the array: - Instrument[] orchestra = { - new Wind(), - new Percussion(), - new Stringed(), - new Brass(), - new Woodwind() - }; - tuneAll(orchestra); - } -} -/* Output: -Wind.play() MIDDLE_C -Percussion.play() MIDDLE_C -Stringed.play() MIDDLE_C -Brass.play() MIDDLE_C -Woodwind.play() MIDDLE_C -*/ diff --git a/code/interfaces/nesting/NestingInterfaces.java b/code/interfaces/nesting/NestingInterfaces.java deleted file mode 100644 index 99b466bb..00000000 --- a/code/interfaces/nesting/NestingInterfaces.java +++ /dev/null @@ -1,105 +0,0 @@ -// interfaces/nesting/NestingInterfaces.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java interfaces.nesting.NestingInterfaces} -package interfaces.nesting; - -class A { - interface B { - void f(); - } - public class BImp implements B { - @Override - public void f() {} - } - private class BImp2 implements B { - @Override - public void f() {} - } - public interface C { - void f(); - } - class CImp implements C { - @Override - public void f() {} - } - private class CImp2 implements C { - @Override - public void f() {} - } - private interface D { - void f(); - } - private class DImp implements D { - @Override - public void f() {} - } - public class DImp2 implements D { - @Override - public void f() {} - } - public D getD() { return new DImp2(); } - private D dRef; - public void receiveD(D d) { - dRef = d; - dRef.f(); - } -} - -interface E { - interface G { - void f(); - } - // Redundant "public": - public interface H { - void f(); - } - void g(); - // Cannot be private within an interface: - //- private interface I {} -} - -public class NestingInterfaces { - public class BImp implements A.B { - @Override - public void f() {} - } - class CImp implements A.C { - @Override - public void f() {} - } - // Cannot implement a private interface except - // within that interface's defining class: - //- class DImp implements A.D { - //- public void f() {} - //- } - class EImp implements E { - @Override - public void g() {} - } - class EGImp implements E.G { - @Override - public void f() {} - } - class EImp2 implements E { - @Override - public void g() {} - class EG implements E.G { - @Override - public void f() {} - } - } - public static void main(String[] args) { - A a = new A(); - // Can't access A.D: - //- A.D ad = a.getD(); - // Doesn't return anything but A.D: - //- A.DImp2 di2 = a.getD(); - // Cannot access a member of the interface: - //- a.getD().f(); - // Only another A can do anything with getD(): - A a2 = new A(); - a2.receiveD(a.getD()); - } -} diff --git a/code/iostreams/BasicFileOutput.java b/code/iostreams/BasicFileOutput.java deleted file mode 100644 index 1da5c6fd..00000000 --- a/code/iostreams/BasicFileOutput.java +++ /dev/null @@ -1,26 +0,0 @@ -// iostreams/BasicFileOutput.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.io.*; - -public class BasicFileOutput { - static String file = "BasicFileOutput.dat"; - public static void main(String[] args) { - try( - BufferedReader in = new BufferedReader( - new StringReader( - BufferedInputFile.read( - "BasicFileOutput.java"))); - PrintWriter out = new PrintWriter( - new BufferedWriter(new FileWriter(file))) - ) { - in.lines().forEach(out::println); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Show the stored file: - System.out.println(BufferedInputFile.read(file)); - } -} diff --git a/code/iostreams/BufferedInputFile.java b/code/iostreams/BufferedInputFile.java deleted file mode 100644 index bfe6396f..00000000 --- a/code/iostreams/BufferedInputFile.java +++ /dev/null @@ -1,23 +0,0 @@ -// iostreams/BufferedInputFile.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.io.*; -import java.util.stream.*; - -public class BufferedInputFile { - public static String read(String filename) { - try(BufferedReader in = new BufferedReader( - new FileReader(filename))) { - return in.lines() - .collect(Collectors.joining("\n")); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) { - System.out.print( - read("BufferedInputFile.java")); - } -} diff --git a/code/iostreams/FileOutputShortcut.java b/code/iostreams/FileOutputShortcut.java deleted file mode 100644 index 5a160ec0..00000000 --- a/code/iostreams/FileOutputShortcut.java +++ /dev/null @@ -1,24 +0,0 @@ -// iostreams/FileOutputShortcut.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.io.*; - -public class FileOutputShortcut { - static String file = "FileOutputShortcut.dat"; - public static void main(String[] args) { - try( - BufferedReader in = new BufferedReader( - new StringReader(BufferedInputFile.read( - "FileOutputShortcut.java"))); - // Here's the shortcut: - PrintWriter out = new PrintWriter(file) - ) { - in.lines().forEach(out::println); - } catch(IOException e) { - throw new RuntimeException(e); - } - System.out.println(BufferedInputFile.read(file)); - } -} diff --git a/code/iostreams/FormattedMemoryInput.java b/code/iostreams/FormattedMemoryInput.java deleted file mode 100644 index 055dd882..00000000 --- a/code/iostreams/FormattedMemoryInput.java +++ /dev/null @@ -1,25 +0,0 @@ -// iostreams/FormattedMemoryInput.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.io.*; - -public class FormattedMemoryInput { - public static void main(String[] args) { - try( - DataInputStream in = new DataInputStream( - new ByteArrayInputStream( - BufferedInputFile.read( - "FormattedMemoryInput.java") - .getBytes())) - ) { - while(true) - System.out.write((char)in.readByte()); - } catch(EOFException e) { - System.out.println("\nEnd of stream"); - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/iostreams/MemoryInput.java b/code/iostreams/MemoryInput.java deleted file mode 100644 index 1326965c..00000000 --- a/code/iostreams/MemoryInput.java +++ /dev/null @@ -1,17 +0,0 @@ -// iostreams/MemoryInput.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {VisuallyInspectOutput} -import java.io.*; - -public class MemoryInput { - public static void - main(String[] args) throws IOException { - StringReader in = new StringReader( - BufferedInputFile.read("MemoryInput.java")); - int c; - while((c = in.read()) != -1) - System.out.print((char)c); - } -} diff --git a/code/iostreams/StoringAndRecoveringData.java b/code/iostreams/StoringAndRecoveringData.java deleted file mode 100644 index 761f022e..00000000 --- a/code/iostreams/StoringAndRecoveringData.java +++ /dev/null @@ -1,42 +0,0 @@ -// iostreams/StoringAndRecoveringData.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; - -public class StoringAndRecoveringData { - public static void main(String[] args) { - try( - DataOutputStream out = new DataOutputStream( - new BufferedOutputStream( - new FileOutputStream("Data.txt"))) - ) { - out.writeDouble(3.14159); - out.writeUTF("That was pi"); - out.writeDouble(1.41413); - out.writeUTF("Square root of 2"); - } catch(IOException e) { - throw new RuntimeException(e); - } - try( - DataInputStream in = new DataInputStream( - new BufferedInputStream( - new FileInputStream("Data.txt"))) - ) { - System.out.println(in.readDouble()); - // Only readUTF() will recover the - // Java-UTF String properly: - System.out.println(in.readUTF()); - System.out.println(in.readDouble()); - System.out.println(in.readUTF()); - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} -/* Output: -3.14159 -That was pi -1.41413 -Square root of 2 -*/ diff --git a/code/iostreams/TestEOF.java b/code/iostreams/TestEOF.java deleted file mode 100644 index 956cb1a0..00000000 --- a/code/iostreams/TestEOF.java +++ /dev/null @@ -1,22 +0,0 @@ -// iostreams/TestEOF.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Testing for end of file -// {VisuallyInspectOutput} -import java.io.*; - -public class TestEOF { - public static void main(String[] args) { - try( - DataInputStream in = new DataInputStream( - new BufferedInputStream( - new FileInputStream("TestEOF.java"))) - ) { - while(in.available() != 0) - System.out.write(in.readByte()); - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/iostreams/UsingRandomAccessFile.java b/code/iostreams/UsingRandomAccessFile.java deleted file mode 100644 index dde6d1ee..00000000 --- a/code/iostreams/UsingRandomAccessFile.java +++ /dev/null @@ -1,65 +0,0 @@ -// iostreams/UsingRandomAccessFile.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; - -public class UsingRandomAccessFile { - static String file = "rtest.dat"; - public static void display() { - try( - RandomAccessFile rf = - new RandomAccessFile(file, "r") - ) { - for(int i = 0; i < 7; i++) - System.out.println( - "Value " + i + ": " + rf.readDouble()); - System.out.println(rf.readUTF()); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) { - try( - RandomAccessFile rf = - new RandomAccessFile(file, "rw") - ) { - for(int i = 0; i < 7; i++) - rf.writeDouble(i*1.414); - rf.writeUTF("The end of the file"); - rf.close(); - display(); - } catch(IOException e) { - throw new RuntimeException(e); - } - try( - RandomAccessFile rf = - new RandomAccessFile(file, "rw") - ) { - rf.seek(5*8); - rf.writeDouble(47.0001); - rf.close(); - display(); - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} -/* Output: -Value 0: 0.0 -Value 1: 1.414 -Value 2: 2.828 -Value 3: 4.242 -Value 4: 5.656 -Value 5: 7.069999999999999 -Value 6: 8.484 -The end of the file -Value 0: 0.0 -Value 1: 1.414 -Value 2: 2.828 -Value 3: 4.242 -Value 4: 5.656 -Value 5: 47.0001 -Value 6: 8.484 -The end of the file -*/ diff --git a/code/javadoc/Documentation1.java b/code/javadoc/Documentation1.java deleted file mode 100644 index 7838fbd9..00000000 --- a/code/javadoc/Documentation1.java +++ /dev/null @@ -1,11 +0,0 @@ -// javadoc/Documentation1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -/** A class comment */ -public class Documentation1 { - /** A field comment */ - public int i; - /** A method comment */ - public void f() {} -} diff --git a/code/javadoc/Documentation2.java b/code/javadoc/Documentation2.java deleted file mode 100644 index 237755f4..00000000 --- a/code/javadoc/Documentation2.java +++ /dev/null @@ -1,9 +0,0 @@ -// javadoc/Documentation2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -/**

- * System.out.println(new Date());
- * 
- */ -public class Documentation2 {} diff --git a/code/javadoc/Documentation3.java b/code/javadoc/Documentation3.java deleted file mode 100644 index a3063c3d..00000000 --- a/code/javadoc/Documentation3.java +++ /dev/null @@ -1,12 +0,0 @@ -// javadoc/Documentation3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -/** You can even insert a list: - *
    - *
  1. Item one - *
  2. Item two - *
  3. Item three - *
- */ -public class Documentation3 {} diff --git a/code/javadoc/HelloDateDoc.java b/code/javadoc/HelloDateDoc.java deleted file mode 100644 index 54b505a4..00000000 --- a/code/javadoc/HelloDateDoc.java +++ /dev/null @@ -1,26 +0,0 @@ -// javadoc/HelloDateDoc.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -/** The first On Java 8 example program. - * Displays a String and today's date. - * @author Bruce Eckel - * @author www.MindviewInc.com - * @version 5.0 - */ -public class HelloDateDoc { - /** Entry point to class & application. - * @param args array of String arguments - * @throws exceptions No exceptions thrown - */ - public static void main(String[] args) { - System.out.println("Hello, it's: "); - System.out.println(new Date()); - } -} -/* Output: -Hello, it's: -Tue May 09 06:07:27 MDT 2017 -*/ diff --git a/code/lowlevel/AtomicEvenProducer.java b/code/lowlevel/AtomicEvenProducer.java deleted file mode 100644 index 8c45b61c..00000000 --- a/code/lowlevel/AtomicEvenProducer.java +++ /dev/null @@ -1,21 +0,0 @@ -// lowlevel/AtomicEvenProducer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Atomic classes: occasionally useful in regular code -import java.util.concurrent.atomic.*; - -public class AtomicEvenProducer extends IntGenerator { - private AtomicInteger currentEvenValue = - new AtomicInteger(0); - @Override - public int next() { - return currentEvenValue.addAndGet(2); - } - public static void main(String[] args) { - EvenChecker.test(new AtomicEvenProducer()); - } -} -/* Output: -No odd numbers discovered -*/ diff --git a/code/lowlevel/AtomicIntegerTest.java b/code/lowlevel/AtomicIntegerTest.java deleted file mode 100644 index 09db1ca8..00000000 --- a/code/lowlevel/AtomicIntegerTest.java +++ /dev/null @@ -1,20 +0,0 @@ -// lowlevel/AtomicIntegerTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.*; -import onjava.*; - -public class AtomicIntegerTest extends IntTestable { - private AtomicInteger i = new AtomicInteger(0); - public int getAsInt() { return i.get(); } - public void evenIncrement() { i.addAndGet(2); } - public static void main(String[] args) { - Atomicity.test(new AtomicIntegerTest()); - } -} -/* Output: -No failures found -*/ diff --git a/code/lowlevel/AtomicSerialNumbers.java b/code/lowlevel/AtomicSerialNumbers.java deleted file mode 100644 index 2e30e9c4..00000000 --- a/code/lowlevel/AtomicSerialNumbers.java +++ /dev/null @@ -1,21 +0,0 @@ -// lowlevel/AtomicSerialNumbers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.atomic.*; - -public class -AtomicSerialNumbers extends SerialNumbers { - private AtomicInteger serialNumber = - new AtomicInteger(); - public int nextSerialNumber() { - return serialNumber.getAndIncrement(); - } - public static void main(String[] args) { - SerialNumberChecker.test( - new AtomicSerialNumbers()); - } -} -/* Output: -No duplicates detected -*/ diff --git a/code/lowlevel/Atomicity.java b/code/lowlevel/Atomicity.java deleted file mode 100644 index 632631bf..00000000 --- a/code/lowlevel/Atomicity.java +++ /dev/null @@ -1,20 +0,0 @@ -// lowlevel/Atomicity.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; -import onjava.TimedAbort; - -public class Atomicity { - public static void test(IntTestable it) { - new TimedAbort(4, "No failures found"); - CompletableFuture.runAsync(it); - while(true) { - int val = it.getAsInt(); - if(val % 2 != 0) { - System.out.println("failed with: " + val); - System.exit(0); - } - } - } -} diff --git a/code/lowlevel/AttemptLocking.java b/code/lowlevel/AttemptLocking.java deleted file mode 100644 index 9dbe2b28..00000000 --- a/code/lowlevel/AttemptLocking.java +++ /dev/null @@ -1,57 +0,0 @@ -// lowlevel/AttemptLocking.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Locks in the concurrent library allow you -// to give up on trying to acquire a lock -import java.util.concurrent.*; -import java.util.concurrent.locks.*; -import onjava.Nap; - -public class AttemptLocking { - private ReentrantLock lock = new ReentrantLock(); - public void untimed() { - boolean captured = lock.tryLock(); - try { - System.out.println("tryLock(): " + captured); - } finally { - if(captured) - lock.unlock(); - } - } - public void timed() { - boolean captured = false; - try { - captured = lock.tryLock(2, TimeUnit.SECONDS); - } catch(InterruptedException e) { - throw new RuntimeException(e); - } - try { - System.out.println( - "tryLock(2, TimeUnit.SECONDS): " + captured); - } finally { - if(captured) - lock.unlock(); - } - } - public static void main(String[] args) { - final AttemptLocking al = new AttemptLocking(); - al.untimed(); // True -- lock is available - al.timed(); // True -- lock is available - // Now create a second task to grab the lock: - CompletableFuture.runAsync( () -> { - al.lock.lock(); - System.out.println("acquired"); - }); - new Nap(0.1); // Give the second task a chance - al.untimed(); // False -- lock grabbed by task - al.timed(); // False -- lock grabbed by task - } -} -/* Output: -tryLock(): true -tryLock(2, TimeUnit.SECONDS): true -acquired -tryLock(): false -tryLock(2, TimeUnit.SECONDS): false -*/ diff --git a/code/lowlevel/CaptureUncaughtException.java b/code/lowlevel/CaptureUncaughtException.java deleted file mode 100644 index 33261667..00000000 --- a/code/lowlevel/CaptureUncaughtException.java +++ /dev/null @@ -1,56 +0,0 @@ -// lowlevel/CaptureUncaughtException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -class ExceptionThread2 implements Runnable { - @Override - public void run() { - Thread t = Thread.currentThread(); - System.out.println("run() by " + t.getName()); - System.out.println( - "eh = " + t.getUncaughtExceptionHandler()); - throw new RuntimeException(); - } -} - -class MyUncaughtExceptionHandler implements -Thread.UncaughtExceptionHandler { - @Override - public void uncaughtException(Thread t, Throwable e) { - System.out.println("caught " + e); - } -} - -class HandlerThreadFactory implements ThreadFactory { - @Override - public Thread newThread(Runnable r) { - System.out.println(this + " creating new Thread"); - Thread t = new Thread(r); - System.out.println("created " + t); - t.setUncaughtExceptionHandler( - new MyUncaughtExceptionHandler()); - System.out.println( - "eh = " + t.getUncaughtExceptionHandler()); - return t; - } -} - -public class CaptureUncaughtException { - public static void main(String[] args) { - ExecutorService exec = - Executors.newCachedThreadPool( - new HandlerThreadFactory()); - exec.execute(new ExceptionThread2()); - exec.shutdown(); - } -} -/* Output: -HandlerThreadFactory@4e25154f creating new Thread -created Thread[Thread-0,5,main] -eh = MyUncaughtExceptionHandler@70dea4e -run() by Thread-0 -eh = MyUncaughtExceptionHandler@70dea4e -caught java.lang.RuntimeException -*/ diff --git a/code/lowlevel/CircularSet.java b/code/lowlevel/CircularSet.java deleted file mode 100644 index 225eaeca..00000000 --- a/code/lowlevel/CircularSet.java +++ /dev/null @@ -1,29 +0,0 @@ -// lowlevel/CircularSet.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Reuses storage so we don't run out of memory -import java.util.*; - -public class CircularSet { - private int[] array; - private int size; - private int index = 0; - public CircularSet(int size) { - this.size = size; - array = new int[size]; - // Initialize to a value not produced - // by SerialNumbers: - Arrays.fill(array, -1); - } - public synchronized void add(int i) { - array[index] = i; - // Wrap index and write over old elements: - index = ++index % size; - } - public synchronized boolean contains(int val) { - for(int i = 0; i < size; i++) - if(array[i] == val) return true; - return false; - } -} diff --git a/code/lowlevel/DelayQueueDemo.java b/code/lowlevel/DelayQueueDemo.java deleted file mode 100644 index c5575c68..00000000 --- a/code/lowlevel/DelayQueueDemo.java +++ /dev/null @@ -1,99 +0,0 @@ -// lowlevel/DelayQueueDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import static java.util.concurrent.TimeUnit.*; - -class DelayedTask implements Runnable, Delayed { - private static int counter = 0; - private final int id = counter++; - private final int delta; - private final long trigger; - protected static List sequence = - new ArrayList<>(); - DelayedTask(int delayInMilliseconds) { - delta = delayInMilliseconds; - trigger = System.nanoTime() + - NANOSECONDS.convert(delta, MILLISECONDS); - sequence.add(this); - } - @Override - public long getDelay(TimeUnit unit) { - return unit.convert( - trigger - System.nanoTime(), NANOSECONDS); - } - @Override - public int compareTo(Delayed arg) { - DelayedTask that = (DelayedTask)arg; - if(trigger < that.trigger) return -1; - if(trigger > that.trigger) return 1; - return 0; - } - @Override - public void run() { - System.out.print(this + " "); - } - @Override - public String toString() { - return - String.format("[%d] Task %d", delta, id); - } - public String summary() { - return String.format("(%d:%d)", id, delta); - } - public static class EndTask extends DelayedTask { - EndTask(int delay) { super(delay); } - @Override - public void run() { - sequence.forEach(dt -> - System.out.println(dt.summary())); - } - } -} - -public class DelayQueueDemo { - public static void - main(String[] args) throws Exception { - DelayQueue tasks = - Stream.concat( // Random delays: - new Random(47).ints(20, 0, 4000) - .mapToObj(DelayedTask::new), - // Add the summarizing task: - Stream.of(new DelayedTask.EndTask(4000))) - .collect(Collectors - .toCollection(DelayQueue::new)); - while(tasks.size() > 0) - tasks.take().run(); - } -} -/* Output: -[128] Task 12 [429] Task 6 [551] Task 13 [555] Task 2 -[693] Task 3 [809] Task 15 [961] Task 5 [1258] Task 1 -[1258] Task 20 [1520] Task 19 [1861] Task 4 [1998] Task -17 [2200] Task 8 [2207] Task 10 [2288] Task 11 [2522] -Task 9 [2589] Task 14 [2861] Task 18 [2868] Task 7 -[3278] Task 16 (0:4000) -(1:1258) -(2:555) -(3:693) -(4:1861) -(5:961) -(6:429) -(7:2868) -(8:2200) -(9:2522) -(10:2207) -(11:2288) -(12:128) -(13:551) -(14:2589) -(15:809) -(16:3278) -(17:1998) -(18:2861) -(19:1520) -(20:1258) -*/ diff --git a/code/lowlevel/EvenChecker.java b/code/lowlevel/EvenChecker.java deleted file mode 100644 index 5e27a39e..00000000 --- a/code/lowlevel/EvenChecker.java +++ /dev/null @@ -1,41 +0,0 @@ -// lowlevel/EvenChecker.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import onjava.TimedAbort; - -public class EvenChecker implements Runnable { - private IntGenerator generator; - private final int id; - public EvenChecker(IntGenerator generator, int id) { - this.generator = generator; - this.id = id; - } - @Override - public void run() { - while(!generator.isCanceled()) { - int val = generator.next(); - if(val % 2 != 0) { - System.out.println(val + " not even!"); - generator.cancel(); // Cancels all EvenCheckers - } - } - } - // Test any IntGenerator: - public static void test(IntGenerator gp, int count) { - List> checkers = - IntStream.range(0, count) - .mapToObj(i -> new EvenChecker(gp, i)) - .map(CompletableFuture::runAsync) - .collect(Collectors.toList()); - checkers.forEach(CompletableFuture::join); - } - // Default value for count: - public static void test(IntGenerator gp) { - new TimedAbort(4, "No odd numbers discovered"); - test(gp, 10); - } -} diff --git a/code/lowlevel/EvenProducer.java b/code/lowlevel/EvenProducer.java deleted file mode 100644 index 30157755..00000000 --- a/code/lowlevel/EvenProducer.java +++ /dev/null @@ -1,26 +0,0 @@ -// lowlevel/EvenProducer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// When threads collide -// {VisuallyInspectOutput} - -public class EvenProducer extends IntGenerator { - private int currentEvenValue = 0; - @Override - public int next() { - ++currentEvenValue; // [1] - ++currentEvenValue; - return currentEvenValue; - } - public static void main(String[] args) { - EvenChecker.test(new EvenProducer()); - } -} -/* Output: -419 not even! -425 not even! -423 not even! -421 not even! -417 not even! -*/ diff --git a/code/lowlevel/ExceptionThread.java b/code/lowlevel/ExceptionThread.java deleted file mode 100644 index 518b9f5f..00000000 --- a/code/lowlevel/ExceptionThread.java +++ /dev/null @@ -1,30 +0,0 @@ -// lowlevel/ExceptionThread.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ThrowsException} -import java.util.concurrent.*; - -public class ExceptionThread implements Runnable { - @Override - public void run() { - throw new RuntimeException(); - } - public static void main(String[] args) { - ExecutorService es = - Executors.newCachedThreadPool(); - es.execute(new ExceptionThread()); - es.shutdown(); - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "pool-1-thread-1" -java.lang.RuntimeException - at ExceptionThread.run(ExceptionThread.java:8) - at java.util.concurrent.ThreadPoolExecutor.runW -orker(ThreadPoolExecutor.java:1142) - at java.util.concurrent.ThreadPoolExecutor$Work -er.run(ThreadPoolExecutor.java:617) - at java.lang.Thread.run(Thread.java:745) -*/ diff --git a/code/lowlevel/IntGenerator.java b/code/lowlevel/IntGenerator.java deleted file mode 100644 index e1dd0f62..00000000 --- a/code/lowlevel/IntGenerator.java +++ /dev/null @@ -1,15 +0,0 @@ -// lowlevel/IntGenerator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.atomic.AtomicBoolean; - -public abstract class IntGenerator { - private AtomicBoolean canceled = - new AtomicBoolean(); - public abstract int next(); - public void cancel() { canceled.set(true); } - public boolean isCanceled() { - return canceled.get(); - } -} diff --git a/code/lowlevel/IntTestable.java b/code/lowlevel/IntTestable.java deleted file mode 100644 index 1989ff4d..00000000 --- a/code/lowlevel/IntTestable.java +++ /dev/null @@ -1,15 +0,0 @@ -// lowlevel/IntTestable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public abstract class -IntTestable implements Runnable, IntSupplier { - abstract void evenIncrement(); - @Override - public void run() { - while(true) - evenIncrement(); - } -} diff --git a/code/lowlevel/MutexEvenProducer.java b/code/lowlevel/MutexEvenProducer.java deleted file mode 100644 index ae82df82..00000000 --- a/code/lowlevel/MutexEvenProducer.java +++ /dev/null @@ -1,30 +0,0 @@ -// lowlevel/MutexEvenProducer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Preventing thread collisions with mutexes -import java.util.concurrent.locks.*; -import onjava.Nap; - -public class MutexEvenProducer extends IntGenerator { - private int currentEvenValue = 0; - private Lock lock = new ReentrantLock(); - @Override - public int next() { - lock.lock(); - try { - ++currentEvenValue; - new Nap(0.01); // Cause failure faster - ++currentEvenValue; - return currentEvenValue; - } finally { - lock.unlock(); - } - } - public static void main(String[] args) { - EvenChecker.test(new MutexEvenProducer()); - } -} -/* -No odd numbers discovered -*/ diff --git a/code/lowlevel/NaiveExceptionHandling.java b/code/lowlevel/NaiveExceptionHandling.java deleted file mode 100644 index 3681337e..00000000 --- a/code/lowlevel/NaiveExceptionHandling.java +++ /dev/null @@ -1,32 +0,0 @@ -// lowlevel/NaiveExceptionHandling.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ThrowsException} -import java.util.concurrent.*; - -public class NaiveExceptionHandling { - public static void main(String[] args) { - ExecutorService es = - Executors.newCachedThreadPool(); - try { - es.execute(new ExceptionThread()); - } catch(RuntimeException ue) { - // This statement will NOT execute! - System.out.println("Exception was handled!"); - } finally { - es.shutdown(); - } - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "pool-1-thread-1" -java.lang.RuntimeException - at ExceptionThread.run(ExceptionThread.java:8) - at java.util.concurrent.ThreadPoolExecutor.runW -orker(ThreadPoolExecutor.java:1142) - at java.util.concurrent.ThreadPoolExecutor$Work -er.run(ThreadPoolExecutor.java:617) - at java.lang.Thread.run(Thread.java:745) -*/ diff --git a/code/lowlevel/NotAtomic.java b/code/lowlevel/NotAtomic.java deleted file mode 100644 index c6c6c321..00000000 --- a/code/lowlevel/NotAtomic.java +++ /dev/null @@ -1,49 +0,0 @@ -// lowlevel/NotAtomic.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// javap -c NotAtomic -// {ExcludeFromGradle} -// {VisuallyInspectOutput} - -public class NotAtomic { - int i; - void f1() { i++; } - void f2() { i += 3; } -} -/* Output: -Compiled from "NotAtomic.java" -public class NotAtomic { - int i; - - public NotAtomic(); - Code: - 0: aload_0 - 1: invokespecial #1 // Method java/lang/Object."":()V - 4: return - - void f1(); - Code: - 0: aload_0 - 1: dup - 2: getfield #2 // Field -i:I - 5: iconst_1 - 6: iadd - 7: putfield #2 // Field -i:I - 10: return - - void f2(); - Code: - 0: aload_0 - 1: dup - 2: getfield #2 // Field -i:I - 5: iconst_3 - 6: iadd - 7: putfield #2 // Field -i:I - 10: return -} -*/ diff --git a/code/lowlevel/NumberOfProcessors.java b/code/lowlevel/NumberOfProcessors.java deleted file mode 100644 index 44abeb5d..00000000 --- a/code/lowlevel/NumberOfProcessors.java +++ /dev/null @@ -1,14 +0,0 @@ -// lowlevel/NumberOfProcessors.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class NumberOfProcessors { - public static void main(String[] args) { - System.out.println( - Runtime.getRuntime().availableProcessors()); - } -} -/* Output: -8 -*/ diff --git a/code/lowlevel/PriorityBlockingQueueDemo.java b/code/lowlevel/PriorityBlockingQueueDemo.java deleted file mode 100644 index 099a5349..00000000 --- a/code/lowlevel/PriorityBlockingQueueDemo.java +++ /dev/null @@ -1,139 +0,0 @@ -// lowlevel/PriorityBlockingQueueDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import onjava.Nap; - -class Prioritized implements Comparable { - private static AtomicInteger counter = - new AtomicInteger(); - private final int id = counter.getAndIncrement(); - private final int priority; - private static List sequence = - new CopyOnWriteArrayList<>(); - Prioritized(int priority) { - this.priority = priority; - sequence.add(this); - } - @Override - public int compareTo(Prioritized arg) { - return priority < arg.priority ? 1 : - (priority > arg.priority ? -1 : 0); - } - @Override - public String toString() { - return String.format( - "[%d] Prioritized %d", priority, id); - } - public void displaySequence() { - int count = 0; - for(Prioritized pt : sequence) { - System.out.printf("(%d:%d)", pt.id, pt.priority); - if(++count % 5 == 0) - System.out.println(); - } - } - public static class EndSentinel extends Prioritized { - EndSentinel() { super(-1); } - } -} - -class Producer implements Runnable { - private static AtomicInteger seed = - new AtomicInteger(47); - private SplittableRandom rand = - new SplittableRandom(seed.getAndAdd(10)); - private Queue queue; - Producer(Queue q) { - queue = q; - } - @Override - public void run() { - rand.ints(10, 0, 20) - .mapToObj(Prioritized::new) - .peek(p -> new Nap(rand.nextDouble() / 10)) - .forEach(p -> queue.add(p)); - queue.add(new Prioritized.EndSentinel()); - } -} - -class Consumer implements Runnable { - private PriorityBlockingQueue q; - private SplittableRandom rand = - new SplittableRandom(47); - Consumer(PriorityBlockingQueue q) { - this.q = q; - } - @Override - public void run() { - while(true) { - try { - Prioritized pt = q.take(); - System.out.println(pt); - if(pt instanceof Prioritized.EndSentinel) { - pt.displaySequence(); - break; - } - new Nap(rand.nextDouble() / 10); - } catch(InterruptedException e) { - throw new RuntimeException(e); - } - } - } -} - -public class PriorityBlockingQueueDemo { - public static void main(String[] args) { - PriorityBlockingQueue queue = - new PriorityBlockingQueue<>(); - CompletableFuture.runAsync(new Producer(queue)); - CompletableFuture.runAsync(new Producer(queue)); - CompletableFuture.runAsync(new Producer(queue)); - CompletableFuture.runAsync(new Consumer(queue)) - .join(); - } -} -/* Output: -[15] Prioritized 2 -[17] Prioritized 1 -[17] Prioritized 5 -[16] Prioritized 6 -[14] Prioritized 9 -[12] Prioritized 0 -[11] Prioritized 4 -[11] Prioritized 12 -[13] Prioritized 13 -[12] Prioritized 16 -[14] Prioritized 18 -[15] Prioritized 23 -[18] Prioritized 26 -[16] Prioritized 29 -[12] Prioritized 17 -[11] Prioritized 30 -[11] Prioritized 24 -[10] Prioritized 15 -[10] Prioritized 22 -[8] Prioritized 25 -[8] Prioritized 11 -[8] Prioritized 10 -[6] Prioritized 31 -[3] Prioritized 7 -[2] Prioritized 20 -[1] Prioritized 3 -[0] Prioritized 19 -[0] Prioritized 8 -[0] Prioritized 14 -[0] Prioritized 21 -[-1] Prioritized 28 -(0:12)(2:15)(1:17)(3:1)(4:11) -(5:17)(6:16)(7:3)(8:0)(9:14) -(10:8)(11:8)(12:11)(13:13)(14:0) -(15:10)(16:12)(17:12)(18:14)(19:0) -(20:2)(21:0)(22:10)(23:15)(24:11) -(25:8)(26:18)(27:-1)(28:-1)(29:16) -(30:11)(31:6)(32:-1) -*/ diff --git a/code/lowlevel/ReOrdering.java b/code/lowlevel/ReOrdering.java deleted file mode 100644 index 8209ac40..00000000 --- a/code/lowlevel/ReOrdering.java +++ /dev/null @@ -1,19 +0,0 @@ -// lowlevel/ReOrdering.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ReOrdering implements Runnable { - int one, two, three, four, five, six; - volatile int volaTile; - @Override - public void run() { - one = 1; - two = 2; - three = 3; - volaTile = 92; - int x = four; - int y = five; - int z = six; - } -} diff --git a/code/lowlevel/SafeReturn.java b/code/lowlevel/SafeReturn.java deleted file mode 100644 index 751c96be..00000000 --- a/code/lowlevel/SafeReturn.java +++ /dev/null @@ -1,20 +0,0 @@ -// lowlevel/SafeReturn.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; -import java.util.concurrent.*; - -public class SafeReturn extends IntTestable { - private int i = 0; - public synchronized int getAsInt() { return i; } - public synchronized void evenIncrement() { - i++; i++; - } - public static void main(String[] args) { - Atomicity.test(new SafeReturn()); - } -} -/* Output: -No failures found -*/ diff --git a/code/lowlevel/SerialNumberChecker.java b/code/lowlevel/SerialNumberChecker.java deleted file mode 100644 index 9c2b92ad..00000000 --- a/code/lowlevel/SerialNumberChecker.java +++ /dev/null @@ -1,32 +0,0 @@ -// lowlevel/SerialNumberChecker.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Test SerialNumbers implementations for thread-safety -import java.util.concurrent.*; -import onjava.Nap; - -public class SerialNumberChecker implements Runnable { - private CircularSet serials = new CircularSet(1000); - private SerialNumbers producer; - public SerialNumberChecker(SerialNumbers producer) { - this.producer = producer; - } - @Override - public void run() { - while(true) { - int serial = producer.nextSerialNumber(); - if(serials.contains(serial)) { - System.out.println("Duplicate: " + serial); - System.exit(0); - } - serials.add(serial); - } - } - static void test(SerialNumbers producer) { - for(int i = 0; i < 10; i++) - CompletableFuture.runAsync( - new SerialNumberChecker(producer)); - new Nap(4, "No duplicates detected"); - } -} diff --git a/code/lowlevel/SerialNumberTest.java b/code/lowlevel/SerialNumberTest.java deleted file mode 100644 index cdeddcd9..00000000 --- a/code/lowlevel/SerialNumberTest.java +++ /dev/null @@ -1,13 +0,0 @@ -// lowlevel/SerialNumberTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SerialNumberTest { - public static void main(String[] args) { - SerialNumberChecker.test(new SerialNumbers()); - } -} -/* Output: -Duplicate: 148044 -*/ diff --git a/code/lowlevel/SerialNumbers.java b/code/lowlevel/SerialNumbers.java deleted file mode 100644 index 3f6101c7..00000000 --- a/code/lowlevel/SerialNumbers.java +++ /dev/null @@ -1,11 +0,0 @@ -// lowlevel/SerialNumbers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SerialNumbers { - private volatile int serialNumber = 0; - public int nextSerialNumber() { - return serialNumber++; // Not thread-safe - } -} diff --git a/code/lowlevel/SettingDefaultHandler.java b/code/lowlevel/SettingDefaultHandler.java deleted file mode 100644 index 56a04642..00000000 --- a/code/lowlevel/SettingDefaultHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -// lowlevel/SettingDefaultHandler.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class SettingDefaultHandler { - public static void main(String[] args) { - Thread.setDefaultUncaughtExceptionHandler( - new MyUncaughtExceptionHandler()); - ExecutorService es = - Executors.newCachedThreadPool(); - es.execute(new ExceptionThread()); - es.shutdown(); - } -} -/* Output: -caught java.lang.RuntimeException -*/ diff --git a/code/lowlevel/SwallowedException.java b/code/lowlevel/SwallowedException.java deleted file mode 100644 index 60edd0d6..00000000 --- a/code/lowlevel/SwallowedException.java +++ /dev/null @@ -1,17 +0,0 @@ -// lowlevel/SwallowedException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public class SwallowedException { - public static void main(String[] args) - throws InterruptedException { - ExecutorService exec = - Executors.newSingleThreadExecutor(); - exec.submit(() -> { - throw new RuntimeException(); - }); - exec.shutdown(); - } -} diff --git a/code/lowlevel/SyncOnObject.java b/code/lowlevel/SyncOnObject.java deleted file mode 100644 index 846c5573..00000000 --- a/code/lowlevel/SyncOnObject.java +++ /dev/null @@ -1,70 +0,0 @@ -// lowlevel/SyncOnObject.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Synchronizing on another object -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import onjava.Nap; - -class DualSynch { - ConcurrentLinkedQueue trace = - new ConcurrentLinkedQueue<>(); - public synchronized void f(boolean nap) { - for(int i = 0; i < 5; i++) { - trace.add(String.format("f() " + i)); - if(nap) new Nap(0.01); - } - } - private Object syncObject = new Object(); - public void g(boolean nap) { - synchronized(syncObject) { - for(int i = 0; i < 5; i++) { - trace.add(String.format("g() " + i)); - if(nap) new Nap(0.01); - } - } - } -} - -public class SyncOnObject { - static void test(boolean fNap, boolean gNap) { - DualSynch ds = new DualSynch(); - List> cfs = - Arrays.stream(new Runnable[] { - () -> ds.f(fNap), () -> ds.g(gNap) }) - .map(CompletableFuture::runAsync) - .collect(Collectors.toList()); - cfs.forEach(CompletableFuture::join); - ds.trace.forEach(System.out::println); - } - public static void main(String[] args) { - test(true, false); - System.out.println("****"); - test(false, true); - } -} -/* Output: -f() 0 -g() 0 -g() 1 -g() 2 -g() 3 -g() 4 -f() 1 -f() 2 -f() 3 -f() 4 -**** -f() 0 -g() 0 -f() 1 -f() 2 -f() 3 -f() 4 -g() 1 -g() 2 -g() 3 -g() 4 -*/ diff --git a/code/lowlevel/SynchronizedComparison.java b/code/lowlevel/SynchronizedComparison.java deleted file mode 100644 index 6fbcd1f3..00000000 --- a/code/lowlevel/SynchronizedComparison.java +++ /dev/null @@ -1,89 +0,0 @@ -// lowlevel/SynchronizedComparison.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Synchronizing blocks instead of entire methods -// speeds up access. -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import onjava.Nap; - -abstract class Guarded { - AtomicLong callCount = new AtomicLong(); - public abstract void method(); - @Override - public String toString() { - return getClass().getSimpleName() + - ": " + callCount.get(); - } -} - -class SynchronizedMethod extends Guarded { - public synchronized void method() { - new Nap(0.01); - callCount.incrementAndGet(); - } -} - -class CriticalSection extends Guarded { - public void method() { - new Nap(0.01); - synchronized(this) { - callCount.incrementAndGet(); - } - } -} - -class Caller implements Runnable { - private Guarded g; - Caller(Guarded g) { this.g = g; } - private AtomicLong successfulCalls = - new AtomicLong(); - private AtomicBoolean stop = - new AtomicBoolean(false); - @Override - public void run() { - new Timer().schedule(new TimerTask() { - public void run() { stop.set(true); } - }, 2500); - while(!stop.get()) { - g.method(); - successfulCalls.getAndIncrement(); - } - System.out.println( - "-> " + successfulCalls.get()); - } -} - -public class SynchronizedComparison { - static void test(Guarded g) { - List> callers = - Stream.of( - new Caller(g), - new Caller(g), - new Caller(g), - new Caller(g)) - .map(CompletableFuture::runAsync) - .collect(Collectors.toList()); - callers.forEach(CompletableFuture::join); - System.out.println(g); - } - public static void main(String[] args) { - test(new CriticalSection()); - test(new SynchronizedMethod()); - } -} -/* Output: --> 243 --> 243 --> 243 --> 243 -CriticalSection: 972 --> 69 --> 61 --> 83 --> 36 -SynchronizedMethod: 249 -*/ diff --git a/code/lowlevel/SynchronizedEvenProducer.java b/code/lowlevel/SynchronizedEvenProducer.java deleted file mode 100644 index 377aeecb..00000000 --- a/code/lowlevel/SynchronizedEvenProducer.java +++ /dev/null @@ -1,24 +0,0 @@ -// lowlevel/SynchronizedEvenProducer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simplifying mutexes with the synchronized keyword -import onjava.Nap; - -public class -SynchronizedEvenProducer extends IntGenerator { - private int currentEvenValue = 0; - @Override - public synchronized int next() { - ++currentEvenValue; - new Nap(0.01); // Cause failure faster - ++currentEvenValue; - return currentEvenValue; - } - public static void main(String[] args) { - EvenChecker.test(new SynchronizedEvenProducer()); - } -} -/* Output: -No odd numbers discovered -*/ diff --git a/code/lowlevel/SynchronizedSerialNumbers.java b/code/lowlevel/SynchronizedSerialNumbers.java deleted file mode 100644 index 1739d840..00000000 --- a/code/lowlevel/SynchronizedSerialNumbers.java +++ /dev/null @@ -1,19 +0,0 @@ -// lowlevel/SynchronizedSerialNumbers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class -SynchronizedSerialNumbers extends SerialNumbers { - private int serialNumber = 0; - public synchronized int nextSerialNumber() { - return serialNumber++; - } - public static void main(String[] args) { - SerialNumberChecker.test( - new SynchronizedSerialNumbers()); - } -} -/* Output: -No duplicates detected -*/ diff --git a/code/lowlevel/TestAbort.java b/code/lowlevel/TestAbort.java deleted file mode 100644 index a9efe528..00000000 --- a/code/lowlevel/TestAbort.java +++ /dev/null @@ -1,17 +0,0 @@ -// lowlevel/TestAbort.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; - -public class TestAbort { - public static void main(String[] args) { - new TimedAbort(1); - System.out.println("Napping for 4"); - new Nap(4); - } -} -/* Output: -Napping for 4 -TimedAbort 1.0 -*/ diff --git a/code/lowlevel/ThreadSize.java b/code/lowlevel/ThreadSize.java deleted file mode 100644 index 0f00023d..00000000 --- a/code/lowlevel/ThreadSize.java +++ /dev/null @@ -1,31 +0,0 @@ -// lowlevel/ThreadSize.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromGradle} Takes a long time or hangs -import java.util.concurrent.*; -import onjava.Nap; - -public class ThreadSize { - static class Dummy extends Thread { - @Override - public void run() { new Nap(1); } - } - public static void main(String[] args) { - ExecutorService exec = - Executors.newCachedThreadPool(); - int count = 0; - try { - while(true) { - exec.execute(new Dummy()); - count++; - } - } catch(Error e) { - System.out.println( - e.getClass().getSimpleName() + ": " + count); - System.exit(0); - } finally { - exec.shutdown(); - } - } -} diff --git a/code/lowlevel/UnsafeReturn.java b/code/lowlevel/UnsafeReturn.java deleted file mode 100644 index c2481fc0..00000000 --- a/code/lowlevel/UnsafeReturn.java +++ /dev/null @@ -1,20 +0,0 @@ -// lowlevel/UnsafeReturn.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; -import java.util.concurrent.*; - -public class UnsafeReturn extends IntTestable { - private int i = 0; - public int getAsInt() { return i; } - public synchronized void evenIncrement() { - i++; i++; - } - public static void main(String[] args) { - Atomicity.test(new UnsafeReturn()); - } -} -/* Output: -failed with: 79 -*/ diff --git a/code/lowlevel/WorkStealingPool.java b/code/lowlevel/WorkStealingPool.java deleted file mode 100644 index 984de706..00000000 --- a/code/lowlevel/WorkStealingPool.java +++ /dev/null @@ -1,41 +0,0 @@ -// lowlevel/WorkStealingPool.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; -import java.util.concurrent.*; - -class ShowThread implements Runnable { - @Override - public void run() { - System.out.println( - Thread.currentThread().getName()); - } -} - -public class WorkStealingPool { - public static void main(String[] args) - throws InterruptedException { - System.out.println( - Runtime.getRuntime().availableProcessors()); - ExecutorService exec = - Executors.newWorkStealingPool(); - IntStream.range(0, 10) - .mapToObj(n -> new ShowThread()) - .forEach(exec::execute); - exec.awaitTermination(1, TimeUnit.SECONDS); - } -} -/* Output: -8 -ForkJoinPool-1-worker-2 -ForkJoinPool-1-worker-1 -ForkJoinPool-1-worker-2 -ForkJoinPool-1-worker-3 -ForkJoinPool-1-worker-2 -ForkJoinPool-1-worker-1 -ForkJoinPool-1-worker-3 -ForkJoinPool-1-worker-1 -ForkJoinPool-1-worker-4 -ForkJoinPool-1-worker-2 -*/ diff --git a/code/newio/AvailableCharSets.java b/code/newio/AvailableCharSets.java deleted file mode 100644 index eda3b93c..00000000 --- a/code/newio/AvailableCharSets.java +++ /dev/null @@ -1,43 +0,0 @@ -// newio/AvailableCharSets.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Displays Charsets and aliases -import java.nio.charset.*; -import java.util.*; - -public class AvailableCharSets { - public static void main(String[] args) { - SortedMap charSets = - Charset.availableCharsets(); - for(String csName : charSets.keySet()) { - System.out.print(csName); - Iterator aliases = charSets.get(csName) - .aliases().iterator(); - if(aliases.hasNext()) - System.out.print(": "); - while(aliases.hasNext()) { - System.out.print(aliases.next()); - if(aliases.hasNext()) - System.out.print(", "); - } - System.out.println(); - } - } -} -/* Output: (First 7 Lines) -Big5: csBig5 -Big5-HKSCS: big5-hkscs, big5hk, Big5_HKSCS, big5hkscs -CESU-8: CESU8, csCESU-8 -EUC-JP: csEUCPkdFmtjapanese, x-euc-jp, eucjis, -Extended_UNIX_Code_Packed_Format_for_Japanese, euc_jp, -eucjp, x-eucjp -EUC-KR: ksc5601-1987, csEUCKR, ksc5601_1987, ksc5601, -5601, -euc_kr, ksc_5601, ks_c_5601-1987, euckr -GB18030: gb18030-2000 -GB2312: gb2312, euc-cn, x-EUC-CN, euccn, EUC_CN, -gb2312-80, -gb2312-1980 - ... -*/ diff --git a/code/newio/BufferToText.java b/code/newio/BufferToText.java deleted file mode 100644 index 2f38c2c6..00000000 --- a/code/newio/BufferToText.java +++ /dev/null @@ -1,93 +0,0 @@ -// newio/BufferToText.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Converting text to and from ByteBuffers -import java.nio.*; -import java.nio.channels.*; -import java.nio.charset.*; -import java.io.*; - -public class BufferToText { - private static final int BSIZE = 1024; - public static void main(String[] args) { - try( - FileChannel fc = new FileOutputStream( - "data2.txt").getChannel() - ) { - fc.write(ByteBuffer.wrap("Some text".getBytes())); - } catch(IOException e) { - throw new RuntimeException(e); - } - ByteBuffer buff = ByteBuffer.allocate(BSIZE); - try( - FileChannel fc = new FileInputStream( - "data2.txt").getChannel() - ) { - fc.read(buff); - } catch(IOException e) { - throw new RuntimeException(e); - } - buff.flip(); - // Doesn't work: - System.out.println(buff.asCharBuffer()); - // Decode using this system's default Charset: - buff.rewind(); - String encoding = - System.getProperty("file.encoding"); - System.out.println("Decoded using " + - encoding + ": " - + Charset.forName(encoding).decode(buff)); - // Encode with something that prints: - try( - FileChannel fc = new FileOutputStream( - "data2.txt").getChannel() - ) { - fc.write(ByteBuffer.wrap( - "Some text".getBytes("UTF-16BE"))); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Now try reading again: - buff.clear(); - try( - FileChannel fc = new FileInputStream( - "data2.txt").getChannel() - ) { - fc.read(buff); - } catch(IOException e) { - throw new RuntimeException(e); - } - buff.flip(); - System.out.println(buff.asCharBuffer()); - // Use a CharBuffer to write through: - buff = ByteBuffer.allocate(24); - buff.asCharBuffer().put("Some text"); - try( - FileChannel fc = new FileOutputStream( - "data2.txt").getChannel() - ) { - fc.write(buff); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Read and display: - buff.clear(); - try( - FileChannel fc = new FileInputStream( - "data2.txt").getChannel() - ) { - fc.read(buff); - } catch(IOException e) { - throw new RuntimeException(e); - } - buff.flip(); - System.out.println(buff.asCharBuffer()); - } -} -/* Output: -???? -Decoded using windows-1252: Some text -Some text -Some textNULNULNUL -*/ diff --git a/code/newio/ChannelCopy.java b/code/newio/ChannelCopy.java deleted file mode 100644 index 84696131..00000000 --- a/code/newio/ChannelCopy.java +++ /dev/null @@ -1,35 +0,0 @@ -// newio/ChannelCopy.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Copying a file using channels and buffers -// {java ChannelCopy ChannelCopy.java test.txt} -import java.nio.*; -import java.nio.channels.*; -import java.io.*; - -public class ChannelCopy { - private static final int BSIZE = 1024; - public static void main(String[] args) { - if(args.length != 2) { - System.out.println( - "arguments: sourcefile destfile"); - System.exit(1); - } - try( - FileChannel in = new FileInputStream( - args[0]).getChannel(); - FileChannel out = new FileOutputStream( - args[1]).getChannel() - ) { - ByteBuffer buffer = ByteBuffer.allocate(BSIZE); - while(in.read(buffer) != -1) { - buffer.flip(); // Prepare for writing - out.write(buffer); - buffer.clear(); // Prepare for reading - } - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/newio/Endians.java b/code/newio/Endians.java deleted file mode 100644 index 11d66076..00000000 --- a/code/newio/Endians.java +++ /dev/null @@ -1,28 +0,0 @@ -// newio/Endians.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Endian differences and data storage -import java.nio.*; -import java.util.*; - -public class Endians { - public static void main(String[] args) { - ByteBuffer bb = ByteBuffer.wrap(new byte[12]); - bb.asCharBuffer().put("abcdef"); - System.out.println(Arrays.toString(bb.array())); - bb.rewind(); - bb.order(ByteOrder.BIG_ENDIAN); - bb.asCharBuffer().put("abcdef"); - System.out.println(Arrays.toString(bb.array())); - bb.rewind(); - bb.order(ByteOrder.LITTLE_ENDIAN); - bb.asCharBuffer().put("abcdef"); - System.out.println(Arrays.toString(bb.array())); - } -} -/* Output: -[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102] -[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102] -[97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0] -*/ diff --git a/code/newio/FileLocking.java b/code/newio/FileLocking.java deleted file mode 100644 index e8c74d2a..00000000 --- a/code/newio/FileLocking.java +++ /dev/null @@ -1,30 +0,0 @@ -// newio/FileLocking.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.channels.*; -import java.util.concurrent.*; -import java.io.*; - -public class FileLocking { - public static void main(String[] args) { - try( - FileOutputStream fos = - new FileOutputStream("file.txt"); - FileLock fl = fos.getChannel().tryLock() - ) { - if(fl != null) { - System.out.println("Locked File"); - TimeUnit.MILLISECONDS.sleep(100); - fl.release(); - System.out.println("Released Lock"); - } - } catch(IOException | InterruptedException e) { - throw new RuntimeException(e); - } - } -} -/* Output: -Locked File -Released Lock -*/ diff --git a/code/newio/GetChannel.java b/code/newio/GetChannel.java deleted file mode 100644 index 16caa340..00000000 --- a/code/newio/GetChannel.java +++ /dev/null @@ -1,53 +0,0 @@ -// newio/GetChannel.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Getting channels from streams -import java.nio.*; -import java.nio.channels.*; -import java.io.*; - -public class GetChannel { - private static String name = "data.txt"; - private static final int BSIZE = 1024; - public static void main(String[] args) { - // Write a file: - try( - FileChannel fc = new FileOutputStream(name) - .getChannel() - ) { - fc.write(ByteBuffer - .wrap("Some text ".getBytes())); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Add to the end of the file: - try( - FileChannel fc = new RandomAccessFile( - name, "rw").getChannel() - ) { - fc.position(fc.size()); // Move to the end - fc.write(ByteBuffer - .wrap("Some more".getBytes())); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Read the file: - try( - FileChannel fc = new FileInputStream(name) - .getChannel() - ) { - ByteBuffer buff = ByteBuffer.allocate(BSIZE); - fc.read(buff); - buff.flip(); - while(buff.hasRemaining()) - System.out.write(buff.get()); - } catch(IOException e) { - throw new RuntimeException(e); - } - System.out.flush(); - } -} -/* Output: -Some text Some more -*/ diff --git a/code/newio/GetData.java b/code/newio/GetData.java deleted file mode 100644 index b2518b10..00000000 --- a/code/newio/GetData.java +++ /dev/null @@ -1,56 +0,0 @@ -// newio/GetData.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Getting different representations from a ByteBuffer -import java.nio.*; - -public class GetData { - private static final int BSIZE = 1024; - public static void main(String[] args) { - ByteBuffer bb = ByteBuffer.allocate(BSIZE); - // Allocation automatically zeroes the ByteBuffer: - int i = 0; - while(i++ < bb.limit()) - if(bb.get() != 0) - System.out.println("nonzero"); - System.out.println("i = " + i); - bb.rewind(); - // Store and read a char array: - bb.asCharBuffer().put("Howdy!"); - char c; - while((c = bb.getChar()) != 0) - System.out.print(c + " "); - System.out.println(); - bb.rewind(); - // Store and read a short: - bb.asShortBuffer().put((short)471142); - System.out.println(bb.getShort()); - bb.rewind(); - // Store and read an int: - bb.asIntBuffer().put(99471142); - System.out.println(bb.getInt()); - bb.rewind(); - // Store and read a long: - bb.asLongBuffer().put(99471142); - System.out.println(bb.getLong()); - bb.rewind(); - // Store and read a float: - bb.asFloatBuffer().put(99471142); - System.out.println(bb.getFloat()); - bb.rewind(); - // Store and read a double: - bb.asDoubleBuffer().put(99471142); - System.out.println(bb.getDouble()); - bb.rewind(); - } -} -/* Output: -i = 1025 -H o w d y ! -12390 -99471142 -99471142 -9.9471144E7 -9.9471142E7 -*/ diff --git a/code/newio/IntBufferDemo.java b/code/newio/IntBufferDemo.java deleted file mode 100644 index 31ffaa8f..00000000 --- a/code/newio/IntBufferDemo.java +++ /dev/null @@ -1,35 +0,0 @@ -// newio/IntBufferDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Manipulating ints in a ByteBuffer with an IntBuffer -import java.nio.*; - -public class IntBufferDemo { - private static final int BSIZE = 1024; - public static void main(String[] args) { - ByteBuffer bb = ByteBuffer.allocate(BSIZE); - IntBuffer ib = bb.asIntBuffer(); - // Store an array of int: - ib.put(new int[]{ 11, 42, 47, 99, 143, 811, 1016 }); - // Absolute location read and write: - System.out.println(ib.get(3)); - ib.put(3, 1811); - // Setting a new limit before rewinding the buffer. - ib.flip(); - while(ib.hasRemaining()) { - int i = ib.get(); - System.out.println(i); - } - } -} -/* Output: -99 -11 -42 -47 -1811 -143 -811 -1016 -*/ diff --git a/code/newio/LargeMappedFiles.java b/code/newio/LargeMappedFiles.java deleted file mode 100644 index c4976e45..00000000 --- a/code/newio/LargeMappedFiles.java +++ /dev/null @@ -1,31 +0,0 @@ -// newio/LargeMappedFiles.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating a very large file using mapping -import java.nio.*; -import java.nio.channels.*; -import java.io.*; - -public class LargeMappedFiles { - static int length = 0x8000000; // 128 MB - public static void - main(String[] args) throws Exception { - try( - RandomAccessFile tdat = - new RandomAccessFile("test.dat", "rw") - ) { - MappedByteBuffer out = tdat.getChannel().map( - FileChannel.MapMode.READ_WRITE, 0, length); - for(int i = 0; i < length; i++) - out.put((byte)'x'); - System.out.println("Finished writing"); - for(int i = length/2; i < length/2 + 6; i++) - System.out.print((char)out.get(i)); - } - } -} -/* Output: -Finished writing -xxxxxx -*/ diff --git a/code/newio/LockingMappedFiles.java b/code/newio/LockingMappedFiles.java deleted file mode 100644 index 6fe8fee5..00000000 --- a/code/newio/LockingMappedFiles.java +++ /dev/null @@ -1,60 +0,0 @@ -// newio/LockingMappedFiles.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Locking portions of a mapped file -import java.nio.*; -import java.nio.channels.*; -import java.io.*; - -public class LockingMappedFiles { - static final int LENGTH = 0x8FFFFFF; // 128 MB - static FileChannel fc; - public static void - main(String[] args) throws Exception { - fc = new RandomAccessFile("test.dat", "rw") - .getChannel(); - MappedByteBuffer out = fc.map( - FileChannel.MapMode.READ_WRITE, 0, LENGTH); - for(int i = 0; i < LENGTH; i++) - out.put((byte)'x'); - new LockAndModify(out, 0, 0 + LENGTH/3); - new LockAndModify( - out, LENGTH/2, LENGTH/2 + LENGTH/4); - } - private static class LockAndModify extends Thread { - private ByteBuffer buff; - private int start, end; - LockAndModify(ByteBuffer mbb, int start, int end) { - this.start = start; - this.end = end; - mbb.limit(end); - mbb.position(start); - buff = mbb.slice(); - start(); - } - @Override - public void run() { - try { - // Exclusive lock with no overlap: - FileLock fl = fc.lock(start, end, false); - System.out.println( - "Locked: "+ start +" to "+ end); - // Perform modification: - while(buff.position() < buff.limit() - 1) - buff.put((byte)(buff.get() + 1)); - fl.release(); - System.out.println( - "Released: " + start + " to " + end); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - } -} -/* Output: -Locked: 75497471 to 113246206 -Locked: 0 to 50331647 -Released: 75497471 to 113246206 -Released: 0 to 50331647 -*/ diff --git a/code/newio/MappedIO.java b/code/newio/MappedIO.java deleted file mode 100644 index 93b4ddf3..00000000 --- a/code/newio/MappedIO.java +++ /dev/null @@ -1,145 +0,0 @@ -// newio/MappedIO.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromGradle} Runs too long under WSL2 -import java.util.*; -import java.nio.*; -import java.nio.channels.*; -import java.io.*; - -public class MappedIO { - private static int numOfInts = 4_000_000; - private static int numOfUbuffInts = 100_000; - private abstract static class Tester { - private String name; - Tester(String name) { - this.name = name; - } - public void runTest() { - System.out.print(name + ": "); - long start = System.nanoTime(); - test(); - double duration = System.nanoTime() - start; - System.out.format("%.3f%n", duration/1.0e9); - } - public abstract void test(); - } - private static Tester[] tests = { - new Tester("Stream Write") { - @Override - public void test() { - try( - DataOutputStream dos = - new DataOutputStream( - new BufferedOutputStream( - new FileOutputStream( - new File("temp.tmp")))) - ) { - for(int i = 0; i < numOfInts; i++) - dos.writeInt(i); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - }, - new Tester("Mapped Write") { - @Override - public void test() { - try( - FileChannel fc = - new RandomAccessFile("temp.tmp", "rw") - .getChannel() - ) { - IntBuffer ib = - fc.map(FileChannel.MapMode.READ_WRITE, - 0, fc.size()).asIntBuffer(); - for(int i = 0; i < numOfInts; i++) - ib.put(i); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - }, - new Tester("Stream Read") { - @Override - public void test() { - try( - DataInputStream dis = - new DataInputStream( - new BufferedInputStream( - new FileInputStream("temp.tmp"))) - ) { - for(int i = 0; i < numOfInts; i++) - dis.readInt(); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - }, - new Tester("Mapped Read") { - @Override - public void test() { - try( - FileChannel fc = new FileInputStream( - new File("temp.tmp")).getChannel() - ) { - IntBuffer ib = - fc.map(FileChannel.MapMode.READ_ONLY, - 0, fc.size()).asIntBuffer(); - while(ib.hasRemaining()) - ib.get(); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - }, - new Tester("Stream Read/Write") { - @Override - public void test() { - try( - RandomAccessFile raf = - new RandomAccessFile( - new File("temp.tmp"), "rw") - ) { - raf.writeInt(1); - for(int i = 0; i < numOfUbuffInts; i++) { - raf.seek(raf.length() - 4); - raf.writeInt(raf.readInt()); - } - } catch(IOException e) { - throw new RuntimeException(e); - } - } - }, - new Tester("Mapped Read/Write") { - @Override - public void test() { - try( - FileChannel fc = new RandomAccessFile( - new File("temp.tmp"), "rw").getChannel() - ) { - IntBuffer ib = - fc.map(FileChannel.MapMode.READ_WRITE, - 0, fc.size()).asIntBuffer(); - ib.put(0); - for(int i = 1; i < numOfUbuffInts; i++) - ib.put(ib.get(i - 1)); - } catch(IOException e) { - throw new RuntimeException(e); - } - } - } - }; - public static void main(String[] args) { - Arrays.stream(tests).forEach(Tester::runTest); - } -} -/* Output: -Stream Write: 0.615 -Mapped Write: 0.050 -Stream Read: 0.577 -Mapped Read: 0.015 -Stream Read/Write: 4.069 -Mapped Read/Write: 0.013 -*/ diff --git a/code/newio/TransferTo.java b/code/newio/TransferTo.java deleted file mode 100644 index f3095b71..00000000 --- a/code/newio/TransferTo.java +++ /dev/null @@ -1,30 +0,0 @@ -// newio/TransferTo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using transferTo() between channels -// {java TransferTo TransferTo.java TransferTo.txt} -import java.nio.channels.*; -import java.io.*; - -public class TransferTo { - public static void main(String[] args) { - if(args.length != 2) { - System.out.println( - "arguments: sourcefile destfile"); - System.exit(1); - } - try( - FileChannel in = new FileInputStream( - args[0]).getChannel(); - FileChannel out = new FileOutputStream( - args[1]).getChannel() - ) { - in.transferTo(0, in.size(), out); - // Or: - // out.transferFrom(in, 0, in.size()); - } catch(IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/newio/UsingBuffers.java b/code/newio/UsingBuffers.java deleted file mode 100644 index 3f3a6bd1..00000000 --- a/code/newio/UsingBuffers.java +++ /dev/null @@ -1,35 +0,0 @@ -// newio/UsingBuffers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.*; - -public class UsingBuffers { - private static - void symmetricScramble(CharBuffer buffer) { - while(buffer.hasRemaining()) { - buffer.mark(); - char c1 = buffer.get(); - char c2 = buffer.get(); - buffer.reset(); - buffer.put(c2).put(c1); - } - } - public static void main(String[] args) { - char[] data = "UsingBuffers".toCharArray(); - ByteBuffer bb = - ByteBuffer.allocate(data.length * 2); - CharBuffer cb = bb.asCharBuffer(); - cb.put(data); - System.out.println(cb.rewind()); - symmetricScramble(cb); - System.out.println(cb.rewind()); - symmetricScramble(cb); - System.out.println(cb.rewind()); - } -} -/* Output: -UsingBuffers -sUniBgfuefsr -UsingBuffers -*/ diff --git a/code/newio/ViewBuffers.java b/code/newio/ViewBuffers.java deleted file mode 100644 index d7bb1adf..00000000 --- a/code/newio/ViewBuffers.java +++ /dev/null @@ -1,69 +0,0 @@ -// newio/ViewBuffers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.*; - -public class ViewBuffers { - public static void main(String[] args) { - ByteBuffer bb = ByteBuffer.wrap( - new byte[]{ 0, 0, 0, 0, 0, 0, 0, 'a' }); - bb.rewind(); - System.out.print("Byte Buffer "); - while(bb.hasRemaining()) - System.out.print( - bb.position()+ " -> " + bb.get() + ", "); - System.out.println(); - CharBuffer cb = - ((ByteBuffer)bb.rewind()).asCharBuffer(); - System.out.print("Char Buffer "); - while(cb.hasRemaining()) - System.out.print( - cb.position() + " -> " + cb.get() + ", "); - System.out.println(); - FloatBuffer fb = - ((ByteBuffer)bb.rewind()).asFloatBuffer(); - System.out.print("Float Buffer "); - while(fb.hasRemaining()) - System.out.print( - fb.position()+ " -> " + fb.get() + ", "); - System.out.println(); - IntBuffer ib = - ((ByteBuffer)bb.rewind()).asIntBuffer(); - System.out.print("Int Buffer "); - while(ib.hasRemaining()) - System.out.print( - ib.position()+ " -> " + ib.get() + ", "); - System.out.println(); - LongBuffer lb = - ((ByteBuffer)bb.rewind()).asLongBuffer(); - System.out.print("Long Buffer "); - while(lb.hasRemaining()) - System.out.print( - lb.position()+ " -> " + lb.get() + ", "); - System.out.println(); - ShortBuffer sb = - ((ByteBuffer)bb.rewind()).asShortBuffer(); - System.out.print("Short Buffer "); - while(sb.hasRemaining()) - System.out.print( - sb.position()+ " -> " + sb.get() + ", "); - System.out.println(); - DoubleBuffer db = - ((ByteBuffer)bb.rewind()).asDoubleBuffer(); - System.out.print("Double Buffer "); - while(db.hasRemaining()) - System.out.print( - db.position()+ " -> " + db.get() + ", "); - } -} -/* Output: -Byte Buffer 0 -> 0, 1 -> 0, 2 -> 0, 3 -> 0, 4 -> 0, 5 --> 0, 6 -> 0, 7 -> 97, -Char Buffer 0 -> NUL, 1 -> NUL, 2 -> NUL, 3 -> a, -Float Buffer 0 -> 0.0, 1 -> 1.36E-43, -Int Buffer 0 -> 0, 1 -> 97, -Long Buffer 0 -> 97, -Short Buffer 0 -> 0, 1 -> 0, 2 -> 0, 3 -> 97, -Double Buffer 0 -> 4.8E-322, -*/ diff --git a/code/objects/HelloDate.java b/code/objects/HelloDate.java deleted file mode 100644 index 1f613e8e..00000000 --- a/code/objects/HelloDate.java +++ /dev/null @@ -1,12 +0,0 @@ -// objects/HelloDate.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class HelloDate { - public static void main(String[] args) { - System.out.println("Hello, it's: "); - System.out.println(new Date()); - } -} diff --git a/code/objects/ShowProperties.java b/code/objects/ShowProperties.java deleted file mode 100644 index ac2bf41e..00000000 --- a/code/objects/ShowProperties.java +++ /dev/null @@ -1,39 +0,0 @@ -// objects/ShowProperties.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class ShowProperties { - public static void main(String[] args) { - System.getProperties().list(System.out); - System.out.println(System.getProperty("user.name")); - System.out.println( - System.getProperty("java.library.path")); - } -} -/* Output: (First 20 Lines) --- listing properties -- -java.runtime.name=Java(TM) SE Runtime Environment -sun.boot.library.path=C:\Program -Files\Java\jdk1.8.0_112\jr... -java.vm.version=25.112-b15 -java.vm.vendor=Oracle Corporation -java.vendor.url=http://java.oracle.com/ -path.separator=; -java.vm.name=Java HotSpot(TM) 64-Bit Server VM -file.encoding.pkg=sun.io -user.script= -user.country=US -sun.java.launcher=SUN_STANDARD -sun.os.patch.level= -java.vm.specification.name=Java Virtual Machine -Specification -user.dir=C:\Users\Bruce\Documents\GitHub\on-ja... -java.runtime.version=1.8.0_112-b15 -java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment -java.endorsed.dirs=C:\Program -Files\Java\jdk1.8.0_112\jr... -os.arch=amd64 -java.io.tmpdir=C:\Users\Bruce\AppData\Local\Temp\ - ... -*/ diff --git a/code/onjava/ArrayShow.java b/code/onjava/ArrayShow.java deleted file mode 100644 index 6edd148f..00000000 --- a/code/onjava/ArrayShow.java +++ /dev/null @@ -1,73 +0,0 @@ -// onjava/ArrayShow.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.util.*; - -public interface ArrayShow { - static void show(Object[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(boolean[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(byte[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(char[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(short[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(int[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(long[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(float[] a) { - System.out.println(Arrays.toString(a)); - } - static void show(double[] a) { - System.out.println(Arrays.toString(a)); - } - // Start with a description: - static void show(String info, Object[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, boolean[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, byte[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, char[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, short[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, int[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, long[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, float[] a) { - System.out.print(info + ": "); - show(a); - } - static void show(String info, double[] a) { - System.out.print(info + ": "); - show(a); - } -} diff --git a/code/onjava/BasicSupplier.java b/code/onjava/BasicSupplier.java deleted file mode 100644 index d4bf3b3d..00000000 --- a/code/onjava/BasicSupplier.java +++ /dev/null @@ -1,31 +0,0 @@ -// onjava/BasicSupplier.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Supplier from a class with a no-arg constructor -package onjava; -import java.util.function.*; -import java.lang.reflect.InvocationTargetException; - -public class BasicSupplier implements Supplier { - private Class type; - public BasicSupplier(Class type) { - this.type = type; - } - @Override - public T get() { - try { - // Assumes type is a public class: - return type.getConstructor().newInstance(); - } catch(InstantiationException | - NoSuchMethodException | - InvocationTargetException | - IllegalAccessException e) { - throw new RuntimeException(e); - } - } - // Produce a default Supplier from a type token: - public static Supplier create(Class type) { - return new BasicSupplier<>(type); - } -} diff --git a/code/onjava/CollectionMethodDifferences.java b/code/onjava/CollectionMethodDifferences.java deleted file mode 100644 index 375d4e41..00000000 --- a/code/onjava/CollectionMethodDifferences.java +++ /dev/null @@ -1,117 +0,0 @@ -// onjava/CollectionMethodDifferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.CollectionMethodDifferences} -package onjava; -import java.lang.reflect.*; -import java.util.*; -import java.util.stream.*; - -public class CollectionMethodDifferences { - static Set methodSet(Class type) { - return Arrays.stream(type.getMethods()) - .map(Method::getName) - .collect(Collectors.toCollection(TreeSet::new)); - } - static void interfaces(Class type) { - System.out.print("Interfaces in " + - type.getSimpleName() + ": "); - System.out.println( - Arrays.stream(type.getInterfaces()) - .map(Class::getSimpleName) - .collect(Collectors.toList())); - } - static Set object = methodSet(Object.class); - static { object.add("clone"); } - static void - difference(Class superset, Class subset) { - System.out.print(superset.getSimpleName() + - " extends " + subset.getSimpleName() + - ", adds: "); - Set comp = Sets.difference( - methodSet(superset), methodSet(subset)); - comp.removeAll(object); // Ignore 'Object' methods - System.out.println(comp); - interfaces(superset); - } - public static void main(String[] args) { - System.out.println("Collection: " + - methodSet(Collection.class)); - interfaces(Collection.class); - difference(Set.class, Collection.class); - difference(HashSet.class, Set.class); - difference(LinkedHashSet.class, HashSet.class); - difference(TreeSet.class, Set.class); - difference(List.class, Collection.class); - difference(ArrayList.class, List.class); - difference(LinkedList.class, List.class); - difference(Queue.class, Collection.class); - difference(PriorityQueue.class, Queue.class); - System.out.println("Map: " + methodSet(Map.class)); - difference(HashMap.class, Map.class); - difference(LinkedHashMap.class, HashMap.class); - difference(SortedMap.class, Map.class); - difference(TreeMap.class, Map.class); - } -} -/* Output: -Collection: [add, addAll, clear, contains, containsAll, -equals, forEach, hashCode, isEmpty, iterator, -parallelStream, remove, removeAll, removeIf, retainAll, -size, spliterator, stream, toArray] -Interfaces in Collection: [Iterable] -Set extends Collection, adds: [] -Interfaces in Set: [Collection] -HashSet extends Set, adds: [] -Interfaces in HashSet: [Set, Cloneable, Serializable] -LinkedHashSet extends HashSet, adds: [] -Interfaces in LinkedHashSet: [Set, Cloneable, -Serializable] -TreeSet extends Set, adds: [headSet, -descendingIterator, descendingSet, pollLast, subSet, -floor, tailSet, ceiling, last, lower, comparator, -pollFirst, first, higher] -Interfaces in TreeSet: [NavigableSet, Cloneable, -Serializable] -List extends Collection, adds: [replaceAll, get, -indexOf, subList, set, sort, lastIndexOf, listIterator] -Interfaces in List: [Collection] -ArrayList extends List, adds: [trimToSize, -ensureCapacity] -Interfaces in ArrayList: [List, RandomAccess, -Cloneable, Serializable] -LinkedList extends List, adds: [offerFirst, poll, -getLast, offer, getFirst, removeFirst, element, -removeLastOccurrence, peekFirst, peekLast, push, -pollFirst, removeFirstOccurrence, descendingIterator, -pollLast, removeLast, pop, addLast, peek, offerLast, -addFirst] -Interfaces in LinkedList: [List, Deque, Cloneable, -Serializable] -Queue extends Collection, adds: [poll, peek, offer, -element] -Interfaces in Queue: [Collection] -PriorityQueue extends Queue, adds: [comparator] -Interfaces in PriorityQueue: [Serializable] -Map: [clear, compute, computeIfAbsent, -computeIfPresent, containsKey, containsValue, entrySet, -equals, forEach, get, getOrDefault, hashCode, isEmpty, -keySet, merge, put, putAll, putIfAbsent, remove, -replace, replaceAll, size, values] -HashMap extends Map, adds: [] -Interfaces in HashMap: [Map, Cloneable, Serializable] -LinkedHashMap extends HashMap, adds: [] -Interfaces in LinkedHashMap: [Map] -SortedMap extends Map, adds: [lastKey, subMap, -comparator, firstKey, headMap, tailMap] -Interfaces in SortedMap: [Map] -TreeMap extends Map, adds: [descendingKeySet, -navigableKeySet, higherEntry, higherKey, floorKey, -subMap, ceilingKey, pollLastEntry, firstKey, lowerKey, -headMap, tailMap, lowerEntry, ceilingEntry, -descendingMap, pollFirstEntry, lastKey, firstEntry, -floorEntry, comparator, lastEntry] -Interfaces in TreeMap: [NavigableMap, Cloneable, -Serializable] -*/ diff --git a/code/onjava/ConvertTo.java b/code/onjava/ConvertTo.java deleted file mode 100644 index cc8febd7..00000000 --- a/code/onjava/ConvertTo.java +++ /dev/null @@ -1,105 +0,0 @@ -// onjava/ConvertTo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; - -public interface ConvertTo { - static boolean[] primitive(Boolean[] in) { - boolean[] result = new boolean[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; // Autounboxing - return result; - } - static char[] primitive(Character[] in) { - char[] result = new char[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static byte[] primitive(Byte[] in) { - byte[] result = new byte[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static short[] primitive(Short[] in) { - short[] result = new short[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static int[] primitive(Integer[] in) { - int[] result = new int[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static long[] primitive(Long[] in) { - long[] result = new long[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static float[] primitive(Float[] in) { - float[] result = new float[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static double[] primitive(Double[] in) { - double[] result = new double[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - // Convert from primitive array to wrapped array: - static Boolean[] boxed(boolean[] in) { - Boolean[] result = new Boolean[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; // Autoboxing - return result; - } - static Character[] boxed(char[] in) { - Character[] result = new Character[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static Byte[] boxed(byte[] in) { - Byte[] result = new Byte[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static Short[] boxed(short[] in) { - Short[] result = new Short[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static Integer[] boxed(int[] in) { - Integer[] result = new Integer[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static Long[] boxed(long[] in) { - Long[] result = new Long[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static Float[] boxed(float[] in) { - Float[] result = new Float[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } - static Double[] boxed(double[] in) { - Double[] result = new Double[in.length]; - for(int i = 0; i < in.length; i++) - result[i] = in[i]; - return result; - } -} diff --git a/code/onjava/Count.java b/code/onjava/Count.java deleted file mode 100644 index 1f380f87..00000000 --- a/code/onjava/Count.java +++ /dev/null @@ -1,220 +0,0 @@ -// onjava/Count.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Generate incremental values of different types -package onjava; -import java.util.*; -import java.util.function.*; -import static onjava.ConvertTo.*; - -public interface Count { - class Boolean - implements Supplier { - private boolean b = true; - @Override - public java.lang.Boolean get() { - b = !b; - return java.lang.Boolean.valueOf(b); - } - public java.lang.Boolean get(int n) { - return get(); - } - public java.lang.Boolean[] array(int sz) { - java.lang.Boolean[] result = - new java.lang.Boolean[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pboolean { - private boolean b = true; - public boolean get() { - b = !b; - return b; - } - public boolean get(int n) { return get(); } - public boolean[] array(int sz) { - return primitive(new Boolean().array(sz)); - } - } - class Byte - implements Supplier { - private byte b; - @Override - public java.lang.Byte get() { return b++; } - public java.lang.Byte get(int n) { - return get(); - } - public java.lang.Byte[] array(int sz) { - java.lang.Byte[] result = - new java.lang.Byte[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pbyte { - private byte b; - public byte get() { return b++; } - public byte get(int n) { return get(); } - public byte[] array(int sz) { - return primitive(new Byte().array(sz)); - } - } - char[] CHARS = - "abcdefghijklmnopqrstuvwxyz".toCharArray(); - class Character - implements Supplier { - private int i; - @Override - public java.lang.Character get() { - i = (i + 1) % CHARS.length; - return CHARS[i]; - } - public java.lang.Character get(int n) { - return get(); - } - public java.lang.Character[] array(int sz) { - java.lang.Character[] result = - new java.lang.Character[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pchar { - private int i; - public char get() { - i = (i + 1) % CHARS.length; - return CHARS[i]; - } - public char get(int n) { return get(); } - public char[] array(int sz) { - return primitive(new Character().array(sz)); - } - } - class Short - implements Supplier { - short s; - @Override - public java.lang.Short get() { return s++; } - public java.lang.Short get(int n) { - return get(); - } - public java.lang.Short[] array(int sz) { - java.lang.Short[] result = - new java.lang.Short[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pshort { - short s; - public short get() { return s++; } - public short get(int n) { return get(); } - public short[] array(int sz) { - return primitive(new Short().array(sz)); - } - } - class Integer - implements Supplier { - int i; - @Override - public java.lang.Integer get() { return i++; } - public java.lang.Integer get(int n) { - return get(); - } - public java.lang.Integer[] array(int sz) { - java.lang.Integer[] result = - new java.lang.Integer[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pint implements IntSupplier { - int i; - public int get() { return i++; } - public int get(int n) { return get(); } - @Override - public int getAsInt() { return get(); } - public int[] array(int sz) { - return primitive(new Integer().array(sz)); - } - } - class Long - implements Supplier { - private long l; - @Override - public java.lang.Long get() { return l++; } - public java.lang.Long get(int n) { - return get(); - } - public java.lang.Long[] array(int sz) { - java.lang.Long[] result = - new java.lang.Long[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Plong implements LongSupplier { - private long l; - public long get() { return l++; } - public long get(int n) { return get(); } - @Override - public long getAsLong() { return get(); } - public long[] array(int sz) { - return primitive(new Long().array(sz)); - } - } - class Float - implements Supplier { - private int i; - @Override - public java.lang.Float get() { - return java.lang.Float.valueOf(i++); - } - public java.lang.Float get(int n) { - return get(); - } - public java.lang.Float[] array(int sz) { - java.lang.Float[] result = - new java.lang.Float[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pfloat { - private int i; - public float get() { return i++; } - public float get(int n) { return get(); } - public float[] array(int sz) { - return primitive(new Float().array(sz)); - } - } - class Double - implements Supplier { - private int i; - @Override - public java.lang.Double get() { - return java.lang.Double.valueOf(i++); - } - public java.lang.Double get(int n) { - return get(); - } - public java.lang.Double[] array(int sz) { - java.lang.Double[] result = - new java.lang.Double[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pdouble implements DoubleSupplier { - private int i; - public double get() { return i++; } - public double get(int n) { return get(); } - @Override - public double getAsDouble() { return get(0); } - public double[] array(int sz) { - return primitive(new Double().array(sz)); - } - } -} diff --git a/code/onjava/CountMap.java b/code/onjava/CountMap.java deleted file mode 100644 index e3759053..00000000 --- a/code/onjava/CountMap.java +++ /dev/null @@ -1,97 +0,0 @@ -// onjava/CountMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Unlimited-length Map containing sample data -// {java onjava.CountMap} -package onjava; -import java.util.*; -import java.util.stream.*; - -public class CountMap -extends AbstractMap { - private int size; - private static char[] chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); - private static String value(int key) { - return - chars[key % chars.length] + - Integer.toString(key / chars.length); - } - public CountMap(int size) { - this.size = size < 0 ? 0 : size; - } - @Override - public String get(Object key) { - return value((Integer)key); - } - private static class Entry - implements Map.Entry { - int index; - Entry(int index) { this.index = index; } - @Override - public boolean equals(Object o) { - return o instanceof Entry && - Objects.equals(index, ((Entry)o).index); - } - @Override - public Integer getKey() { return index; } - @Override - public String getValue() { - return value(index); - } - @Override - public String setValue(String value) { - throw new UnsupportedOperationException(); - } - @Override - public int hashCode() { - return Objects.hashCode(index); - } - } - @Override - public Set> entrySet() { - // LinkedHashSet retains initialization order: - return IntStream.range(0, size) - .mapToObj(Entry::new) - .collect(Collectors - .toCollection(LinkedHashSet::new)); - } - public static void main(String[] args) { - final int size = 6; - CountMap cm = new CountMap(60); - System.out.println(cm); - System.out.println(cm.get(500)); - cm.values().stream() - .limit(size) - .forEach(System.out::println); - System.out.println(); - new Random(47).ints(size, 0, 1000) - .mapToObj(cm::get) - .forEach(System.out::println); - } -} -/* Output: -{0=A0, 1=B0, 2=C0, 3=D0, 4=E0, 5=F0, 6=G0, 7=H0, 8=I0, -9=J0, 10=K0, 11=L0, 12=M0, 13=N0, 14=O0, 15=P0, 16=Q0, -17=R0, 18=S0, 19=T0, 20=U0, 21=V0, 22=W0, 23=X0, 24=Y0, -25=Z0, 26=A1, 27=B1, 28=C1, 29=D1, 30=E1, 31=F1, 32=G1, -33=H1, 34=I1, 35=J1, 36=K1, 37=L1, 38=M1, 39=N1, 40=O1, -41=P1, 42=Q1, 43=R1, 44=S1, 45=T1, 46=U1, 47=V1, 48=W1, -49=X1, 50=Y1, 51=Z1, 52=A2, 53=B2, 54=C2, 55=D2, 56=E2, -57=F2, 58=G2, 59=H2} -G19 -A0 -B0 -C0 -D0 -E0 -F0 - -Y9 -J21 -R26 -D33 -Z36 -N16 -*/ diff --git a/code/onjava/CountingIntegerList.java b/code/onjava/CountingIntegerList.java deleted file mode 100644 index 7d5d4f79..00000000 --- a/code/onjava/CountingIntegerList.java +++ /dev/null @@ -1,34 +0,0 @@ -// onjava/CountingIntegerList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// List of any length, containing sample data -// {java onjava.CountingIntegerList} -package onjava; -import java.util.*; - -public class CountingIntegerList -extends AbstractList { - private int size; - public CountingIntegerList() { size = 0; } - public CountingIntegerList(int size) { - this.size = size < 0 ? 0 : size; - } - @Override - public Integer get(int index) { - return index; - } - @Override - public int size() { return size; } - public static void main(String[] args) { - List cil = - new CountingIntegerList(30); - System.out.println(cil); - System.out.println(cil.get(500)); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] -500 -*/ diff --git a/code/onjava/Countries.java b/code/onjava/Countries.java deleted file mode 100644 index ec42b592..00000000 --- a/code/onjava/Countries.java +++ /dev/null @@ -1,351 +0,0 @@ -// onjava/Countries.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// "Flyweight" Maps and Lists of sample data -// {java onjava.Countries} -package onjava; -import java.util.*; - -public class Countries { - public static final String[][] DATA = { - // Africa - {"ALGERIA","Algiers"}, - {"ANGOLA","Luanda"}, - {"BENIN","Porto-Novo"}, - {"BOTSWANA","Gaberone"}, - {"BURKINA FASO","Ouagadougou"}, - {"BURUNDI","Bujumbura"}, - {"CAMEROON","Yaounde"}, - {"CAPE VERDE","Praia"}, - {"CENTRAL AFRICAN REPUBLIC","Bangui"}, - {"CHAD","N'djamena"}, - {"COMOROS","Moroni"}, - {"CONGO","Brazzaville"}, - {"DJIBOUTI","Dijibouti"}, - {"EGYPT","Cairo"}, - {"EQUATORIAL GUINEA","Malabo"}, - {"ERITREA","Asmara"}, - {"ETHIOPIA","Addis Ababa"}, - {"GABON","Libreville"}, - {"THE GAMBIA","Banjul"}, - {"GHANA","Accra"}, - {"GUINEA","Conakry"}, - {"BISSAU","Bissau"}, - {"COTE D'IVOIR (IVORY COAST)","Yamoussoukro"}, - {"KENYA","Nairobi"}, - {"LESOTHO","Maseru"}, - {"LIBERIA","Monrovia"}, - {"LIBYA","Tripoli"}, - {"MADAGASCAR","Antananarivo"}, - {"MALAWI","Lilongwe"}, - {"MALI","Bamako"}, - {"MAURITANIA","Nouakchott"}, - {"MAURITIUS","Port Louis"}, - {"MOROCCO","Rabat"}, - {"MOZAMBIQUE","Maputo"}, - {"NAMIBIA","Windhoek"}, - {"NIGER","Niamey"}, - {"NIGERIA","Abuja"}, - {"RWANDA","Kigali"}, - {"SAO TOME E PRINCIPE","Sao Tome"}, - {"SENEGAL","Dakar"}, - {"SEYCHELLES","Victoria"}, - {"SIERRA LEONE","Freetown"}, - {"SOMALIA","Mogadishu"}, - {"SOUTH AFRICA","Pretoria/Cape Town"}, - {"SUDAN","Khartoum"}, - {"SWAZILAND","Mbabane"}, - {"TANZANIA","Dodoma"}, - {"TOGO","Lome"}, - {"TUNISIA","Tunis"}, - {"UGANDA","Kampala"}, - {"DEMOCRATIC REPUBLIC OF THE CONGO (ZAIRE)", - "Kinshasa"}, - {"ZAMBIA","Lusaka"}, - {"ZIMBABWE","Harare"}, - // Asia - {"AFGHANISTAN","Kabul"}, - {"BAHRAIN","Manama"}, - {"BANGLADESH","Dhaka"}, - {"BHUTAN","Thimphu"}, - {"BRUNEI","Bandar Seri Begawan"}, - {"CAMBODIA","Phnom Penh"}, - {"CHINA","Beijing"}, - {"CYPRUS","Nicosia"}, - {"INDIA","New Delhi"}, - {"INDONESIA","Jakarta"}, - {"IRAN","Tehran"}, - {"IRAQ","Baghdad"}, - {"ISRAEL","Jerusalem"}, - {"JAPAN","Tokyo"}, - {"JORDAN","Amman"}, - {"KUWAIT","Kuwait City"}, - {"LAOS","Vientiane"}, - {"LEBANON","Beirut"}, - {"MALAYSIA","Kuala Lumpur"}, - {"THE MALDIVES","Male"}, - {"MONGOLIA","Ulan Bator"}, - {"MYANMAR (BURMA)","Rangoon"}, - {"NEPAL","Katmandu"}, - {"NORTH KOREA","P'yongyang"}, - {"OMAN","Muscat"}, - {"PAKISTAN","Islamabad"}, - {"PHILIPPINES","Manila"}, - {"QATAR","Doha"}, - {"SAUDI ARABIA","Riyadh"}, - {"SINGAPORE","Singapore"}, - {"SOUTH KOREA","Seoul"}, - {"SRI LANKA","Colombo"}, - {"SYRIA","Damascus"}, - {"TAIWAN (REPUBLIC OF CHINA)","Taipei"}, - {"THAILAND","Bangkok"}, - {"TURKEY","Ankara"}, - {"UNITED ARAB EMIRATES","Abu Dhabi"}, - {"VIETNAM","Hanoi"}, - {"YEMEN","Sana'a"}, - // Australia and Oceania - {"AUSTRALIA","Canberra"}, - {"FIJI","Suva"}, - {"KIRIBATI","Bairiki"}, - {"MARSHALL ISLANDS","Dalap-Uliga-Darrit"}, - {"MICRONESIA","Palikir"}, - {"NAURU","Yaren"}, - {"NEW ZEALAND","Wellington"}, - {"PALAU","Koror"}, - {"PAPUA NEW GUINEA","Port Moresby"}, - {"SOLOMON ISLANDS","Honaira"}, - {"TONGA","Nuku'alofa"}, - {"TUVALU","Fongafale"}, - {"VANUATU","Port Vila"}, - {"WESTERN SAMOA","Apia"}, - // Eastern Europe and former USSR - {"ARMENIA","Yerevan"}, - {"AZERBAIJAN","Baku"}, - {"BELARUS (BYELORUSSIA)","Minsk"}, - {"BULGARIA","Sofia"}, - {"GEORGIA","Tbilisi"}, - {"KAZAKSTAN","Almaty"}, - {"KYRGYZSTAN","Alma-Ata"}, - {"MOLDOVA","Chisinau"}, - {"RUSSIA","Moscow"}, - {"TAJIKISTAN","Dushanbe"}, - {"TURKMENISTAN","Ashkabad"}, - {"UKRAINE","Kyiv"}, - {"UZBEKISTAN","Tashkent"}, - // Europe - {"ALBANIA","Tirana"}, - {"ANDORRA","Andorra la Vella"}, - {"AUSTRIA","Vienna"}, - {"BELGIUM","Brussels"}, - {"BOSNIA-HERZEGOVINA","Sarajevo"}, - {"CROATIA","Zagreb"}, - {"CZECH REPUBLIC","Prague"}, - {"DENMARK","Copenhagen"}, - {"ESTONIA","Tallinn"}, - {"FINLAND","Helsinki"}, - {"FRANCE","Paris"}, - {"GERMANY","Berlin"}, - {"GREECE","Athens"}, - {"HUNGARY","Budapest"}, - {"ICELAND","Reykjavik"}, - {"IRELAND","Dublin"}, - {"ITALY","Rome"}, - {"LATVIA","Riga"}, - {"LIECHTENSTEIN","Vaduz"}, - {"LITHUANIA","Vilnius"}, - {"LUXEMBOURG","Luxembourg"}, - {"MACEDONIA","Skopje"}, - {"MALTA","Valletta"}, - {"MONACO","Monaco"}, - {"MONTENEGRO","Podgorica"}, - {"THE NETHERLANDS","Amsterdam"}, - {"NORWAY","Oslo"}, - {"POLAND","Warsaw"}, - {"PORTUGAL","Lisbon"}, - {"ROMANIA","Bucharest"}, - {"SAN MARINO","San Marino"}, - {"SERBIA","Belgrade"}, - {"SLOVAKIA","Bratislava"}, - {"SLOVENIA","Ljuijana"}, - {"SPAIN","Madrid"}, - {"SWEDEN","Stockholm"}, - {"SWITZERLAND","Berne"}, - {"UNITED KINGDOM","London"}, - {"VATICAN CITY","Vatican City"}, - // North and Central America - {"ANTIGUA AND BARBUDA","Saint John's"}, - {"BAHAMAS","Nassau"}, - {"BARBADOS","Bridgetown"}, - {"BELIZE","Belmopan"}, - {"CANADA","Ottawa"}, - {"COSTA RICA","San Jose"}, - {"CUBA","Havana"}, - {"DOMINICA","Roseau"}, - {"DOMINICAN REPUBLIC","Santo Domingo"}, - {"EL SALVADOR","San Salvador"}, - {"GRENADA","Saint George's"}, - {"GUATEMALA","Guatemala City"}, - {"HAITI","Port-au-Prince"}, - {"HONDURAS","Tegucigalpa"}, - {"JAMAICA","Kingston"}, - {"MEXICO","Mexico City"}, - {"NICARAGUA","Managua"}, - {"PANAMA","Panama City"}, - {"ST. KITTS AND NEVIS","Basseterre"}, - {"ST. LUCIA","Castries"}, - {"ST. VINCENT AND THE GRENADINES","Kingstown"}, - {"UNITED STATES OF AMERICA","Washington, D.C."}, - // South America - {"ARGENTINA","Buenos Aires"}, - {"BOLIVIA","Sucre (legal)/La Paz(administrative)"}, - {"BRAZIL","Brasilia"}, - {"CHILE","Santiago"}, - {"COLOMBIA","Bogota"}, - {"ECUADOR","Quito"}, - {"GUYANA","Georgetown"}, - {"PARAGUAY","Asuncion"}, - {"PERU","Lima"}, - {"SURINAME","Paramaribo"}, - {"TRINIDAD AND TOBAGO","Port of Spain"}, - {"URUGUAY","Montevideo"}, - {"VENEZUELA","Caracas"}, - }; - // Use AbstractMap by implementing entrySet() - private static class FlyweightMap - extends AbstractMap { - private static class Entry - implements Map.Entry { - int index; - Entry(int index) { this.index = index; } - @Override - public boolean equals(Object o) { - return o instanceof FlyweightMap && - Objects.equals(DATA[index][0], o); - } - @Override - public int hashCode() { - return Objects.hashCode(DATA[index][0]); - } - @Override - public String getKey() { return DATA[index][0]; } - @Override - public String getValue() { - return DATA[index][1]; - } - @Override - public String setValue(String value) { - throw new UnsupportedOperationException(); - } - } - // Implement size() & iterator() for AbstractSet: - static class EntrySet - extends AbstractSet> { - private int size; - EntrySet(int size) { - if(size < 0) - this.size = 0; - // Can't be any bigger than the array: - else if(size > DATA.length) - this.size = DATA.length; - else - this.size = size; - } - @Override - public int size() { return size; } - private class Iter - implements Iterator> { - // Only one Entry object per Iterator: - private Entry entry = new Entry(-1); - @Override - public boolean hasNext() { - return entry.index < size - 1; - } - @Override - public Map.Entry next() { - entry.index++; - return entry; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - @Override - public - Iterator> iterator() { - return new Iter(); - } - } - private static - Set> entries = - new EntrySet(DATA.length); - @Override - public Set> entrySet() { - return entries; - } - } - // Create a partial map of 'size' countries: - static Map select(final int size) { - return new FlyweightMap() { - @Override - public Set> entrySet() { - return new EntrySet(size); - } - }; - } - static Map map = new FlyweightMap(); - public static Map capitals() { - return map; // The entire map - } - public static Map capitals(int size) { - return select(size); // A partial map - } - static List names = - new ArrayList<>(map.keySet()); - // All the names: - public static List names() { return names; } - // A partial list: - public static List names(int size) { - return new ArrayList<>(select(size).keySet()); - } - public static void main(String[] args) { - System.out.println(capitals(10)); - System.out.println(names(10)); - System.out.println(new HashMap<>(capitals(3))); - System.out.println( - new LinkedHashMap<>(capitals(3))); - System.out.println(new TreeMap<>(capitals(3))); - System.out.println(new Hashtable<>(capitals(3))); - System.out.println(new HashSet<>(names(6))); - System.out.println(new LinkedHashSet<>(names(6))); - System.out.println(new TreeSet<>(names(6))); - System.out.println(new ArrayList<>(names(6))); - System.out.println(new LinkedList<>(names(6))); - System.out.println(capitals().get("BRAZIL")); - } -} -/* Output: -{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo, -BOTSWANA=Gaberone, BURKINA FASO=Ouagadougou, -BURUNDI=Bujumbura, CAMEROON=Yaounde, CAPE VERDE=Praia, -CENTRAL AFRICAN REPUBLIC=Bangui, CHAD=N'djamena} -[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, -BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN -REPUBLIC, CHAD] -{BENIN=Porto-Novo, ANGOLA=Luanda, ALGERIA=Algiers} -{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo} -{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo} -{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo} -[BENIN, BOTSWANA, ANGOLA, BURKINA FASO, ALGERIA, -BURUNDI] -[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, -BURUNDI] -[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, -BURUNDI] -[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, -BURUNDI] -[ALGERIA, ANGOLA, BENIN, BOTSWANA, BURKINA FASO, -BURUNDI] -Brasilia -*/ diff --git a/code/onjava/Enums.java b/code/onjava/Enums.java deleted file mode 100644 index 0440802f..00000000 --- a/code/onjava/Enums.java +++ /dev/null @@ -1,17 +0,0 @@ -// onjava/Enums.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.util.*; - -public class Enums { - private static Random rand = new Random(47); - public static - > T random(Class ec) { - return random(ec.getEnumConstants()); - } - public static T random(T[] values) { - return values[rand.nextInt(values.length)]; - } -} diff --git a/code/onjava/FillMap.java b/code/onjava/FillMap.java deleted file mode 100644 index eadc5495..00000000 --- a/code/onjava/FillMap.java +++ /dev/null @@ -1,38 +0,0 @@ -// onjava/FillMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -public class FillMap { - public static Map - basic(Supplier> pairGen, int size) { - return Stream.generate(pairGen) - .limit(size) - .collect(Collectors - .toMap(Pair::key, Pair::value)); - } - public static Map - basic(Supplier keyGen, - Supplier valueGen, int size) { - return Stream.generate( - () -> Pair.make(keyGen.get(), valueGen.get())) - .limit(size) - .collect(Collectors - .toMap(Pair::key, Pair::value)); - } - public static > - M create(Supplier keyGen, - Supplier valueGen, - Supplier mapSupplier, int size) { - return Stream.generate( () -> - Pair.make(keyGen.get(), valueGen.get())) - .limit(size) - .collect(Collectors - .toMap(Pair::key, Pair::value, - (k, v) -> k, mapSupplier)); - } -} diff --git a/code/onjava/HTMLColors.java b/code/onjava/HTMLColors.java deleted file mode 100644 index bdc3458f..00000000 --- a/code/onjava/HTMLColors.java +++ /dev/null @@ -1,236 +0,0 @@ -// onjava/HTMLColors.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Sample data for collection examples -package onjava; -import java.util.*; -import java.util.stream.*; -import java.util.concurrent.*; - -public class HTMLColors { - public static final Object[][] ARRAY = { - { 0xF0F8FF, "AliceBlue" }, - { 0xFAEBD7, "AntiqueWhite" }, - { 0x7FFFD4, "Aquamarine" }, - { 0xF0FFFF, "Azure" }, - { 0xF5F5DC, "Beige" }, - { 0xFFE4C4, "Bisque" }, - { 0x000000, "Black" }, - { 0xFFEBCD, "BlanchedAlmond" }, - { 0x0000FF, "Blue" }, - { 0x8A2BE2, "BlueViolet" }, - { 0xA52A2A, "Brown" }, - { 0xDEB887, "BurlyWood" }, - { 0x5F9EA0, "CadetBlue" }, - { 0x7FFF00, "Chartreuse" }, - { 0xD2691E, "Chocolate" }, - { 0xFF7F50, "Coral" }, - { 0x6495ED, "CornflowerBlue" }, - { 0xFFF8DC, "Cornsilk" }, - { 0xDC143C, "Crimson" }, - { 0x00FFFF, "Cyan" }, - { 0x00008B, "DarkBlue" }, - { 0x008B8B, "DarkCyan" }, - { 0xB8860B, "DarkGoldenRod" }, - { 0xA9A9A9, "DarkGray" }, - { 0x006400, "DarkGreen" }, - { 0xBDB76B, "DarkKhaki" }, - { 0x8B008B, "DarkMagenta" }, - { 0x556B2F, "DarkOliveGreen" }, - { 0xFF8C00, "DarkOrange" }, - { 0x9932CC, "DarkOrchid" }, - { 0x8B0000, "DarkRed" }, - { 0xE9967A, "DarkSalmon" }, - { 0x8FBC8F, "DarkSeaGreen" }, - { 0x483D8B, "DarkSlateBlue" }, - { 0x2F4F4F, "DarkSlateGray" }, - { 0x00CED1, "DarkTurquoise" }, - { 0x9400D3, "DarkViolet" }, - { 0xFF1493, "DeepPink" }, - { 0x00BFFF, "DeepSkyBlue" }, - { 0x696969, "DimGray" }, - { 0x1E90FF, "DodgerBlue" }, - { 0xB22222, "FireBrick" }, - { 0xFFFAF0, "FloralWhite" }, - { 0x228B22, "ForestGreen" }, - { 0xDCDCDC, "Gainsboro" }, - { 0xF8F8FF, "GhostWhite" }, - { 0xFFD700, "Gold" }, - { 0xDAA520, "GoldenRod" }, - { 0x808080, "Gray" }, - { 0x008000, "Green" }, - { 0xADFF2F, "GreenYellow" }, - { 0xF0FFF0, "HoneyDew" }, - { 0xFF69B4, "HotPink" }, - { 0xCD5C5C, "IndianRed" }, - { 0x4B0082, "Indigo" }, - { 0xFFFFF0, "Ivory" }, - { 0xF0E68C, "Khaki" }, - { 0xE6E6FA, "Lavender" }, - { 0xFFF0F5, "LavenderBlush" }, - { 0x7CFC00, "LawnGreen" }, - { 0xFFFACD, "LemonChiffon" }, - { 0xADD8E6, "LightBlue" }, - { 0xF08080, "LightCoral" }, - { 0xE0FFFF, "LightCyan" }, - { 0xFAFAD2, "LightGoldenRodYellow" }, - { 0xD3D3D3, "LightGray" }, - { 0x90EE90, "LightGreen" }, - { 0xFFB6C1, "LightPink" }, - { 0xFFA07A, "LightSalmon" }, - { 0x20B2AA, "LightSeaGreen" }, - { 0x87CEFA, "LightSkyBlue" }, - { 0x778899, "LightSlateGray" }, - { 0xB0C4DE, "LightSteelBlue" }, - { 0xFFFFE0, "LightYellow" }, - { 0x00FF00, "Lime" }, - { 0x32CD32, "LimeGreen" }, - { 0xFAF0E6, "Linen" }, - { 0xFF00FF, "Magenta" }, - { 0x800000, "Maroon" }, - { 0x66CDAA, "MediumAquaMarine" }, - { 0x0000CD, "MediumBlue" }, - { 0xBA55D3, "MediumOrchid" }, - { 0x9370DB, "MediumPurple" }, - { 0x3CB371, "MediumSeaGreen" }, - { 0x7B68EE, "MediumSlateBlue" }, - { 0x00FA9A, "MediumSpringGreen" }, - { 0x48D1CC, "MediumTurquoise" }, - { 0xC71585, "MediumVioletRed" }, - { 0x191970, "MidnightBlue" }, - { 0xF5FFFA, "MintCream" }, - { 0xFFE4E1, "MistyRose" }, - { 0xFFE4B5, "Moccasin" }, - { 0xFFDEAD, "NavajoWhite" }, - { 0x000080, "Navy" }, - { 0xFDF5E6, "OldLace" }, - { 0x808000, "Olive" }, - { 0x6B8E23, "OliveDrab" }, - { 0xFFA500, "Orange" }, - { 0xFF4500, "OrangeRed" }, - { 0xDA70D6, "Orchid" }, - { 0xEEE8AA, "PaleGoldenRod" }, - { 0x98FB98, "PaleGreen" }, - { 0xAFEEEE, "PaleTurquoise" }, - { 0xDB7093, "PaleVioletRed" }, - { 0xFFEFD5, "PapayaWhip" }, - { 0xFFDAB9, "PeachPuff" }, - { 0xCD853F, "Peru" }, - { 0xFFC0CB, "Pink" }, - { 0xDDA0DD, "Plum" }, - { 0xB0E0E6, "PowderBlue" }, - { 0x800080, "Purple" }, - { 0xFF0000, "Red" }, - { 0xBC8F8F, "RosyBrown" }, - { 0x4169E1, "RoyalBlue" }, - { 0x8B4513, "SaddleBrown" }, - { 0xFA8072, "Salmon" }, - { 0xF4A460, "SandyBrown" }, - { 0x2E8B57, "SeaGreen" }, - { 0xFFF5EE, "SeaShell" }, - { 0xA0522D, "Sienna" }, - { 0xC0C0C0, "Silver" }, - { 0x87CEEB, "SkyBlue" }, - { 0x6A5ACD, "SlateBlue" }, - { 0x708090, "SlateGray" }, - { 0xFFFAFA, "Snow" }, - { 0x00FF7F, "SpringGreen" }, - { 0x4682B4, "SteelBlue" }, - { 0xD2B48C, "Tan" }, - { 0x008080, "Teal" }, - { 0xD8BFD8, "Thistle" }, - { 0xFF6347, "Tomato" }, - { 0x40E0D0, "Turquoise" }, - { 0xEE82EE, "Violet" }, - { 0xF5DEB3, "Wheat" }, - { 0xFFFFFF, "White" }, - { 0xF5F5F5, "WhiteSmoke" }, - { 0xFFFF00, "Yellow" }, - { 0x9ACD32, "YellowGreen" }, - }; - public static final Map MAP = - Arrays.stream(ARRAY) - .collect(Collectors.toMap( - element -> (Integer)element[0], - element -> (String)element[1], - (v1, v2) -> { // Merge function - throw new IllegalStateException(); - }, - LinkedHashMap::new - )); - // Inversion only works if values are unique: - public static Map - invert(Map map) { - return map.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getValue, - Map.Entry::getKey, - (v1, v2) -> { - throw new IllegalStateException(); - }, - LinkedHashMap::new - )); - } - public static final Map - INVMAP = invert(MAP); - // Look up RGB value given a name: - public static Integer rgb(String colorName) { - return INVMAP.get(colorName); - } - public static final List LIST = - Arrays.stream(ARRAY) - .map(item -> (String)item[1]) - .collect(Collectors.toList()); - public static final List RGBLIST = - Arrays.stream(ARRAY) - .map(item -> (Integer)item[0]) - .collect(Collectors.toList()); - public static - void show(Map.Entry e) { - System.out.format( - "0x%06X: %s%n", e.getKey(), e.getValue()); - } - public static void - show(Map m, int count) { - m.entrySet().stream() - .limit(count) - .forEach(e -> show(e)); - } - public static void show(Map m) { - show(m, m.size()); - } - public static - void show(Collection lst, int count) { - lst.stream() - .limit(count) - .forEach(System.out::println); - } - public static void show(Collection lst) { - show(lst, lst.size()); - } - public static - void showrgb(Collection lst, int count) { - lst.stream() - .limit(count) - .forEach(n -> System.out.format("0x%06X%n", n)); - } - public static void showrgb(Collection lst) { - showrgb(lst, lst.size()); - } - public static - void showInv(Map m, int count) { - m.entrySet().stream() - .limit(count) - .forEach(e -> - System.out.format( - "%-20s 0x%06X%n", e.getKey(), e.getValue())); - } - public static void showInv(Map m) { - showInv(m, m.size()); - } - public static void border() { - System.out.println( - "******************************"); - } -} diff --git a/code/onjava/MouseClick.java b/code/onjava/MouseClick.java deleted file mode 100644 index 70d982f7..00000000 --- a/code/onjava/MouseClick.java +++ /dev/null @@ -1,19 +0,0 @@ -// onjava/MouseClick.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Helper interface to allow lambda expressions -package onjava; -import java.awt.event.*; - -// Default everything except mouseClicked(): -public interface MouseClick extends MouseListener { - @Override - default void mouseEntered(MouseEvent e) {} - @Override - default void mouseExited(MouseEvent e) {} - @Override - default void mousePressed(MouseEvent e) {} - @Override - default void mouseReleased(MouseEvent e) {} -} diff --git a/code/onjava/Nap.java b/code/onjava/Nap.java deleted file mode 100644 index 2b89745b..00000000 --- a/code/onjava/Nap.java +++ /dev/null @@ -1,20 +0,0 @@ -// onjava/Nap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.util.concurrent.*; - -public class Nap { - public Nap(double t) { // Seconds - try { - TimeUnit.MILLISECONDS.sleep((int)(1000 * t)); - } catch(InterruptedException e) { - throw new RuntimeException(e); - } - } - public Nap(double t, String msg) { - this(t); - System.out.println(msg); - } -} diff --git a/code/onjava/Null.java b/code/onjava/Null.java deleted file mode 100644 index f3bb70d6..00000000 --- a/code/onjava/Null.java +++ /dev/null @@ -1,6 +0,0 @@ -// onjava/Null.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -public interface Null {} diff --git a/code/onjava/OSExecute.java b/code/onjava/OSExecute.java deleted file mode 100644 index 25ac7f0c..00000000 --- a/code/onjava/OSExecute.java +++ /dev/null @@ -1,37 +0,0 @@ -// onjava/OSExecute.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Run an operating system command -// and send the output to the console -package onjava; -import java.io.*; - -public class OSExecute { - public static void command(String command) { - boolean err = false; - try { - Process process = new ProcessBuilder( - command.split(" ")).start(); - try( - BufferedReader results = new BufferedReader( - new InputStreamReader( - process.getInputStream())); - BufferedReader errors = new BufferedReader( - new InputStreamReader( - process.getErrorStream())) - ) { - results.lines() - .forEach(System.out::println); - err = errors.lines() - .peek(System.err::println) - .count() > 0; - } - } catch(IOException e) { - throw new RuntimeException(e); - } - if(err) - throw new OSExecuteException( - "Errors executing " + command); - } -} diff --git a/code/onjava/OSExecuteException.java b/code/onjava/OSExecuteException.java deleted file mode 100644 index 17d803e1..00000000 --- a/code/onjava/OSExecuteException.java +++ /dev/null @@ -1,12 +0,0 @@ -// onjava/OSExecuteException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; - -public class -OSExecuteException extends RuntimeException { - public OSExecuteException(String why) { - super(why); - } -} diff --git a/code/onjava/Operations.java b/code/onjava/Operations.java deleted file mode 100644 index 33b644c6..00000000 --- a/code/onjava/Operations.java +++ /dev/null @@ -1,17 +0,0 @@ -// onjava/Operations.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.util.*; - -public interface Operations { - void execute(); - static void runOps(Operations... ops) { - for(Operations op : ops) - op.execute(); - } - static void show(String msg) { - System.out.println(msg); - } -} diff --git a/code/onjava/Pair.java b/code/onjava/Pair.java deleted file mode 100644 index 784ef8ac..00000000 --- a/code/onjava/Pair.java +++ /dev/null @@ -1,19 +0,0 @@ -// onjava/Pair.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; - -public class Pair { - public final K key; - public final V value; - public Pair(K k, V v) { - key = k; - value = v; - } - public K key() { return key; } - public V value() { return value; } - public static Pair make(K k, V v) { - return new Pair(k, v); - } -} diff --git a/code/onjava/ProcessFiles.java b/code/onjava/ProcessFiles.java deleted file mode 100644 index edcea73a..00000000 --- a/code/onjava/ProcessFiles.java +++ /dev/null @@ -1,48 +0,0 @@ -// onjava/ProcessFiles.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.io.*; -import java.nio.file.*; - -public class ProcessFiles { - public interface Strategy { - void process(File file); - } - private Strategy strategy; - private String ext; - public ProcessFiles(Strategy strategy, String ext) { - this.strategy = strategy; - this.ext = ext; - } - public void start(String[] args) { - try { - if(args.length == 0) - processDirectoryTree(new File(".")); - else - for(String arg : args) { - File fileArg = new File(arg); - if(fileArg.isDirectory()) - processDirectoryTree(fileArg); - else { - // Allow user to leave off extension: - if(!arg.endsWith("." + ext)) - arg += "." + ext; - strategy.process( - new File(arg).getCanonicalFile()); - } - } - } catch(IOException e) { - throw new RuntimeException(e); - } - } - public void - processDirectoryTree(File root) throws IOException { - PathMatcher matcher = FileSystems.getDefault() - .getPathMatcher("glob:**/*.{" + ext + "}"); - Files.walk(root.toPath()) - .filter(matcher::matches) - .forEach(p -> strategy.process(p.toFile())); - } -} diff --git a/code/onjava/Rand.java b/code/onjava/Rand.java deleted file mode 100644 index d21c0e2b..00000000 --- a/code/onjava/Rand.java +++ /dev/null @@ -1,248 +0,0 @@ -// onjava/Rand.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Generate random values of different types -package onjava; -import java.util.*; -import java.util.function.*; -import static onjava.ConvertTo.*; - -public interface Rand { - int MOD = 10_000; - class Boolean - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Boolean get() { - return r.nextBoolean(); - } - public java.lang.Boolean get(int n) { - return get(); - } - public java.lang.Boolean[] array(int sz) { - java.lang.Boolean[] result = - new java.lang.Boolean[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pboolean { - public boolean[] array(int sz) { - return primitive(new Boolean().array(sz)); - } - } - class Byte - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Byte get() { - return (byte)r.nextInt(MOD); - } - public java.lang.Byte get(int n) { - return get(); - } - public java.lang.Byte[] array(int sz) { - java.lang.Byte[] result = - new java.lang.Byte[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pbyte { - public byte[] array(int sz) { - return primitive(new Byte().array(sz)); - } - } - class Character - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Character get() { - return (char)r.nextInt('a', 'z' + 1); - } - public java.lang.Character get(int n) { - return get(); - } - public java.lang.Character[] array(int sz) { - java.lang.Character[] result = - new java.lang.Character[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pchar { - public char[] array(int sz) { - return primitive(new Character().array(sz)); - } - } - class Short - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Short get() { - return (short)r.nextInt(MOD); - } - public java.lang.Short get(int n) { - return get(); - } - public java.lang.Short[] array(int sz) { - java.lang.Short[] result = - new java.lang.Short[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pshort { - public short[] array(int sz) { - return primitive(new Short().array(sz)); - } - } - class Integer - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Integer get() { - return r.nextInt(MOD); - } - public java.lang.Integer get(int n) { - return get(); - } - public java.lang.Integer[] array(int sz) { - int[] primitive = new Pint().array(sz); - java.lang.Integer[] result = - new java.lang.Integer[sz]; - for(int i = 0; i < sz; i++) - result[i] = primitive[i]; - return result; - } - } - class Pint implements IntSupplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public int getAsInt() { - return r.nextInt(MOD); - } - public int get(int n) { return getAsInt(); } - public int[] array(int sz) { - return r.ints(sz, 0, MOD).toArray(); - } - } - class Long - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Long get() { - return r.nextLong(MOD); - } - public java.lang.Long get(int n) { - return get(); - } - public java.lang.Long[] array(int sz) { - long[] primitive = new Plong().array(sz); - java.lang.Long[] result = - new java.lang.Long[sz]; - for(int i = 0; i < sz; i++) - result[i] = primitive[i]; - return result; - } - } - class Plong implements LongSupplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public long getAsLong() { - return r.nextLong(MOD); - } - public long get(int n) { return getAsLong(); } - public long[] array(int sz) { - return r.longs(sz, 0, MOD).toArray(); - } - } - class Float - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Float get() { - return (float)trim(r.nextDouble()); - } - public java.lang.Float get(int n) { - return get(); - } - public java.lang.Float[] array(int sz) { - java.lang.Float[] result = - new java.lang.Float[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } - class Pfloat { - public float[] array(int sz) { - return primitive(new Float().array(sz)); - } - } - static double trim(double d) { - return - ((double)Math.round(d * 1000.0)) / 100.0; - } - class Double - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public java.lang.Double get() { - return trim(r.nextDouble()); - } - public java.lang.Double get(int n) { - return get(); - } - public java.lang.Double[] array(int sz) { - double[] primitive = - new Rand.Pdouble().array(sz); - java.lang.Double[] result = - new java.lang.Double[sz]; - for(int i = 0; i < sz; i++) - result[i] = primitive[i]; - return result; - } - } - class Pdouble implements DoubleSupplier { - SplittableRandom r = new SplittableRandom(47); - @Override - public double getAsDouble() { - return trim(r.nextDouble()); - } - public double get(int n) { - return getAsDouble(); - } - public double[] array(int sz) { - double[] result = r.doubles(sz).toArray(); - Arrays.setAll(result, - n -> result[n] = trim(result[n])); - return result; - } - } - class String - implements Supplier { - SplittableRandom r = new SplittableRandom(47); - private int strlen = 7; // Default length - public String() {} - public String(int strLength) { - strlen = strLength; - } - @Override - public java.lang.String get() { - return r.ints(strlen, 'a', 'z' + 1) - .collect(StringBuilder::new, - StringBuilder::appendCodePoint, - StringBuilder::append).toString(); - } - public java.lang.String get(int n) { - return get(); - } - public java.lang.String[] array(int sz) { - java.lang.String[] result = - new java.lang.String[sz]; - Arrays.setAll(result, n -> get()); - return result; - } - } -} diff --git a/code/onjava/Range.java b/code/onjava/Range.java deleted file mode 100644 index e075c9ba..00000000 --- a/code/onjava/Range.java +++ /dev/null @@ -1,34 +0,0 @@ -// onjava/Range.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Array creation methods that can be used without -// qualifiers, using static imports: -package onjava; - -public class Range { - // Produce a sequence [0..n) - public static int[] range(int n) { - int[] result = new int[n]; - for(int i = 0; i < n; i++) - result[i] = i; - return result; - } - // Produce a sequence [start..end) - public static int[] range(int start, int end) { - int sz = end - start; - int[] result = new int[sz]; - for(int i = 0; i < sz; i++) - result[i] = start + i; - return result; - } - // Produce sequence [start..end) incrementing by step - public static - int[] range(int start, int end, int step) { - int sz = (end - start)/step; - int[] result = new int[sz]; - for(int i = 0; i < sz; i++) - result[i] = start + (i * step); - return result; - } -} diff --git a/code/onjava/Repeat.java b/code/onjava/Repeat.java deleted file mode 100644 index 7ab61fac..00000000 --- a/code/onjava/Repeat.java +++ /dev/null @@ -1,12 +0,0 @@ -// onjava/Repeat.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import static java.util.stream.IntStream.*; - -public class Repeat { - public static void repeat(int n, Runnable action) { - range(0, n).forEach(i -> action.run()); - } -} diff --git a/code/onjava/RmDir.java b/code/onjava/RmDir.java deleted file mode 100644 index be7ea494..00000000 --- a/code/onjava/RmDir.java +++ /dev/null @@ -1,31 +0,0 @@ -// onjava/RmDir.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; -import java.io.IOException; - -public class RmDir { - public static void rmdir(Path dir) - throws IOException { - Files.walkFileTree(dir, - new SimpleFileVisitor() { - @Override - public FileVisitResult - visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - @Override - public FileVisitResult - postVisitDirectory(Path dir, IOException exc) - throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); - } -} diff --git a/code/onjava/Sets.java b/code/onjava/Sets.java deleted file mode 100644 index 62258f15..00000000 --- a/code/onjava/Sets.java +++ /dev/null @@ -1,32 +0,0 @@ -// onjava/Sets.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import java.util.*; - -public class Sets { - public static Set union(Set a, Set b) { - Set result = new HashSet<>(a); - result.addAll(b); - return result; - } - public static - Set intersection(Set a, Set b) { - Set result = new HashSet<>(a); - result.retainAll(b); - return result; - } - // Subtract subset from superset: - public static Set - difference(Set superset, Set subset) { - Set result = new HashSet<>(superset); - result.removeAll(subset); - return result; - } - // Reflexive--everything not in the intersection: - public static - Set complement(Set a, Set b) { - return difference(union(a, b), intersection(a, b)); - } -} diff --git a/code/onjava/Stack.java b/code/onjava/Stack.java deleted file mode 100644 index a5108176..00000000 --- a/code/onjava/Stack.java +++ /dev/null @@ -1,20 +0,0 @@ -// onjava/Stack.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A Stack class built with an ArrayDeque -package onjava; -import java.util.Deque; -import java.util.ArrayDeque; - -public class Stack { - private Deque storage = new ArrayDeque<>(); - public void push(T v) { storage.push(v); } - public T peek() { return storage.peek(); } - public T pop() { return storage.pop(); } - public boolean isEmpty() { return storage.isEmpty(); } - @Override - public String toString() { - return storage.toString(); - } -} diff --git a/code/onjava/Suppliers.java b/code/onjava/Suppliers.java deleted file mode 100644 index 226a70cb..00000000 --- a/code/onjava/Suppliers.java +++ /dev/null @@ -1,36 +0,0 @@ -// onjava/Suppliers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A utility to use with Suppliers -package onjava; -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -public class Suppliers { - // Create a collection and fill it: - public static > C - create(Supplier factory, Supplier gen, int n) { - return Stream.generate(gen) - .limit(n) - .collect(factory, C::add, C::addAll); - } - // Fill an existing collection: - public static > - C fill(C coll, Supplier gen, int n) { - Stream.generate(gen) - .limit(n) - .forEach(coll::add); - return coll; - } - // Use an unbound method reference to - // produce a more general method: - public static H fill(H holder, - BiConsumer adder, Supplier
gen, int n) { - Stream.generate(gen) - .limit(n) - .forEach(a -> adder.accept(holder, a)); - return holder; - } -} diff --git a/code/onjava/TimedAbort.java b/code/onjava/TimedAbort.java deleted file mode 100644 index 3715cf2e..00000000 --- a/code/onjava/TimedAbort.java +++ /dev/null @@ -1,30 +0,0 @@ -// onjava/TimedAbort.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Terminate a program after t seconds -package onjava; -import java.util.concurrent.*; - -public class TimedAbort { - private volatile boolean restart = true; - public TimedAbort(double t, String msg) { - CompletableFuture.runAsync(() -> { - try { - while(restart) { - restart = false; - TimeUnit.MILLISECONDS - .sleep((int)(1000 * t)); - } - } catch(InterruptedException e) { - throw new RuntimeException(e); - } - System.out.println(msg); - System.exit(0); - }); - } - public TimedAbort(double t) { - this(t, "TimedAbort " + t); - } - public void restart() { restart = true; } -} diff --git a/code/onjava/Timer.java b/code/onjava/Timer.java deleted file mode 100644 index a695f79f..00000000 --- a/code/onjava/Timer.java +++ /dev/null @@ -1,19 +0,0 @@ -// onjava/Timer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; -import static java.util.concurrent.TimeUnit.*; - -public class Timer { - private long start = System.nanoTime(); - public long duration() { - return NANOSECONDS.toMillis( - System.nanoTime() - start); - } - public static long duration(Runnable test) { - Timer timer = new Timer(); - test.run(); - return timer.duration(); - } -} diff --git a/code/onjava/Tuple.java b/code/onjava/Tuple.java deleted file mode 100644 index 73cfaa3c..00000000 --- a/code/onjava/Tuple.java +++ /dev/null @@ -1,24 +0,0 @@ -// onjava/Tuple.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Tuple library using type argument inference -package onjava; - -public class Tuple { - public static Tuple2 tuple(A a, B b) { - return new Tuple2<>(a, b); - } - public static Tuple3 - tuple(A a, B b, C c) { - return new Tuple3<>(a, b, c); - } - public static Tuple4 - tuple(A a, B b, C c, D d) { - return new Tuple4<>(a, b, c, d); - } - public static - Tuple5 tuple(A a, B b, C c, D d, E e) { - return new Tuple5<>(a, b, c, d, e); - } -} diff --git a/code/onjava/Tuple2.java b/code/onjava/Tuple2.java deleted file mode 100644 index 7ca8d199..00000000 --- a/code/onjava/Tuple2.java +++ /dev/null @@ -1,16 +0,0 @@ -// onjava/Tuple2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; - -public class Tuple2 { - public final A a1; - public final B a2; - public Tuple2(A a, B b) { a1 = a; a2 = b; } - public String rep() { return a1 + ", " + a2; } - @Override - public String toString() { - return "(" + rep() + ")"; - } -} diff --git a/code/onjava/Tuple3.java b/code/onjava/Tuple3.java deleted file mode 100644 index 26780642..00000000 --- a/code/onjava/Tuple3.java +++ /dev/null @@ -1,17 +0,0 @@ -// onjava/Tuple3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; - -public class Tuple3 extends Tuple2 { - public final C a3; - public Tuple3(A a, B b, C c) { - super(a, b); - a3 = c; - } - @Override - public String rep() { - return super.rep() + ", " + a3; - } -} diff --git a/code/onjava/Tuple4.java b/code/onjava/Tuple4.java deleted file mode 100644 index 5ab51dc9..00000000 --- a/code/onjava/Tuple4.java +++ /dev/null @@ -1,18 +0,0 @@ -// onjava/Tuple4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; - -public class Tuple4 - extends Tuple3 { - public final D a4; - public Tuple4(A a, B b, C c, D d) { - super(a, b, c); - a4 = d; - } - @Override - public String rep() { - return super.rep() + ", " + a4; - } -} diff --git a/code/onjava/Tuple5.java b/code/onjava/Tuple5.java deleted file mode 100644 index 1df88bfd..00000000 --- a/code/onjava/Tuple5.java +++ /dev/null @@ -1,18 +0,0 @@ -// onjava/Tuple5.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package onjava; - -public class Tuple5 -extends Tuple4 { - public final E a5; - public Tuple5(A a, B b, C c, D d, E e) { - super(a, b, c, d); - a5 = e; - } - @Override - public String rep() { - return super.rep() + ", " + a5; - } -} diff --git a/code/onjava/TypeCounter.java b/code/onjava/TypeCounter.java deleted file mode 100644 index d8b262b7..00000000 --- a/code/onjava/TypeCounter.java +++ /dev/null @@ -1,41 +0,0 @@ -// onjava/TypeCounter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Counts instances of a type family -package onjava; -import java.util.*; -import java.util.stream.*; - -public class -TypeCounter extends HashMap, Integer> { - private Class baseType; - public TypeCounter(Class baseType) { - this.baseType = baseType; - } - public void count(Object obj) { - Class type = obj.getClass(); - if(!baseType.isAssignableFrom(type)) - throw new RuntimeException( - obj + " incorrect type: " + type + - ", should be type or subtype of " + baseType); - countClass(type); - } - private void countClass(Class type) { - Integer quantity = get(type); - put(type, quantity == null ? 1 : quantity + 1); - Class superClass = type.getSuperclass(); - if(superClass != null && - baseType.isAssignableFrom(superClass)) - countClass(superClass); - } - @Override - public String toString() { - String result = entrySet().stream() - .map(pair -> String.format("%s=%s", - pair.getKey().getSimpleName(), - pair.getValue())) - .collect(Collectors.joining(", ")); - return "{" + result + "}"; - } -} diff --git a/code/onjava/atunit/AtUnit.java b/code/onjava/atunit/AtUnit.java deleted file mode 100644 index b1688cbd..00000000 --- a/code/onjava/atunit/AtUnit.java +++ /dev/null @@ -1,177 +0,0 @@ -// onjava/atunit/AtUnit.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An annotation-based unit-test framework -// {java onjava.atunit.AtUnit} -package onjava.atunit; -import java.lang.reflect.*; -import java.io.*; -import java.util.*; -import java.nio.file.*; -import java.util.stream.*; -import onjava.*; - -public class AtUnit implements ProcessFiles.Strategy { - static Class testClass; - static List failedTests= new ArrayList<>(); - static long testsRun = 0; - static long failures = 0; - public static void - main(String[] args) throws Exception { - ClassLoader.getSystemClassLoader() - .setDefaultAssertionStatus(true); // Enable assert - new ProcessFiles(new AtUnit(), "class").start(args); - if(failures == 0) - System.out.println("OK (" + testsRun + " tests)"); - else { - System.out.println("(" + testsRun + " tests)"); - System.out.println( - "\n>>> " + failures + " FAILURE" + - (failures > 1 ? "S" : "") + " <<<"); - for(String failed : failedTests) - System.out.println(" " + failed); - } - } - @Override - public void process(File cFile) { - try { - String cName = ClassNameFinder.thisClass( - Files.readAllBytes(cFile.toPath())); - if(!cName.startsWith("public:")) - return; - cName = cName.split(":")[1]; - if(!cName.contains(".")) - return; // Ignore unpackaged classes - testClass = Class.forName(cName); - } catch(IOException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - TestMethods testMethods = new TestMethods(); - Method creator = null; - Method cleanup = null; - for(Method m : testClass.getDeclaredMethods()) { - testMethods.addIfTestMethod(m); - if(creator == null) - creator = checkForCreatorMethod(m); - if(cleanup == null) - cleanup = checkForCleanupMethod(m); - } - if(testMethods.size() > 0) { - if(creator == null) - try { - if(!Modifier.isPublic(testClass - .getDeclaredConstructor() - .getModifiers())) { - System.out.println("Error: " + testClass + - " no-arg constructor must be public"); - System.exit(1); - } - } catch(NoSuchMethodException e) { - // Synthesized no-arg constructor; OK - } - System.out.println(testClass.getName()); - } - for(Method m : testMethods) { - System.out.print(" . " + m.getName() + " "); - try { - Object testObject = createTestObject(creator); - boolean success = false; - try { - if(m.getReturnType().equals(boolean.class)) - success = (Boolean)m.invoke(testObject); - else { - m.invoke(testObject); - success = true; // If no assert fails - } - } catch(InvocationTargetException e) { - // Actual exception is inside e: - System.out.println(e.getCause()); - } - System.out.println(success ? "" : "(failed)"); - testsRun++; - if(!success) { - failures++; - failedTests.add(testClass.getName() + - ": " + m.getName()); - } - if(cleanup != null) - cleanup.invoke(testObject, testObject); - } catch(IllegalAccessException | - IllegalArgumentException | - InvocationTargetException e) { - throw new RuntimeException(e); - } - } - } - public static - class TestMethods extends ArrayList { - void addIfTestMethod(Method m) { - if(m.getAnnotation(Test.class) == null) - return; - if(!(m.getReturnType().equals(boolean.class) || - m.getReturnType().equals(void.class))) - throw new RuntimeException("@Test method" + - " must return boolean or void"); - m.setAccessible(true); // If it's private, etc. - add(m); - } - } - private static - Method checkForCreatorMethod(Method m) { - if(m.getAnnotation(TestObjectCreate.class) == null) - return null; - if(!m.getReturnType().equals(testClass)) - throw new RuntimeException("@TestObjectCreate " + - "must return instance of Class to be tested"); - if((m.getModifiers() & - java.lang.reflect.Modifier.STATIC) < 1) - throw new RuntimeException("@TestObjectCreate " + - "must be static."); - m.setAccessible(true); - return m; - } - private static - Method checkForCleanupMethod(Method m) { - if(m.getAnnotation(TestObjectCleanup.class) == null) - return null; - if(!m.getReturnType().equals(void.class)) - throw new RuntimeException("@TestObjectCleanup " + - "must return void"); - if((m.getModifiers() & - java.lang.reflect.Modifier.STATIC) < 1) - throw new RuntimeException("@TestObjectCleanup " + - "must be static."); - if(m.getParameterTypes().length == 0 || - m.getParameterTypes()[0] != testClass) - throw new RuntimeException("@TestObjectCleanup " + - "must take an argument of the tested type."); - m.setAccessible(true); - return m; - } - private static Object - createTestObject(Method creator) { - if(creator != null) { - try { - return creator.invoke(testClass); - } catch(IllegalAccessException | - IllegalArgumentException | - InvocationTargetException e) { - throw new RuntimeException("Couldn't run " + - "@TestObject (creator) method."); - } - } else { // Use the no-arg constructor: - try { - return testClass - .getConstructor().newInstance(); - } catch(InstantiationException | - NoSuchMethodException | - InvocationTargetException | - IllegalAccessException e) { - throw new RuntimeException( - "Couldn't create a test object. " + - "Try using a @TestObject method."); - } - } - } -} diff --git a/code/onjava/atunit/ClassNameFinder.java b/code/onjava/atunit/ClassNameFinder.java deleted file mode 100644 index 3fef7faf..00000000 --- a/code/onjava/atunit/ClassNameFinder.java +++ /dev/null @@ -1,180 +0,0 @@ -// onjava/atunit/ClassNameFinder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.atunit.ClassNameFinder} -package onjava.atunit; -import java.io.*; -import java.nio.file.*; -import java.util.*; -import onjava.*; - -public class ClassNameFinder { - public static String thisClass(byte[] classBytes) { - Map offsetTable = new HashMap<>(); - Map classNameTable = - new HashMap<>(); - try { - DataInputStream data = new DataInputStream( - new ByteArrayInputStream(classBytes)); - int magic = data.readInt(); // 0xcafebabe - int minorVersion = data.readShort(); - int majorVersion = data.readShort(); - int constantPoolCount = data.readShort(); - int[] constantPool = new int[constantPoolCount]; - for(int i = 1; i < constantPoolCount; i++) { - int tag = data.read(); - // int tableSize; - switch(tag) { - case 1: // UTF - int length = data.readShort(); - char[] bytes = new char[length]; - for(int k = 0; k < bytes.length; k++) - bytes[k] = (char)data.read(); - String className = new String(bytes); - classNameTable.put(i, className); - break; - case 5: // LONG - case 6: // DOUBLE - data.readLong(); // discard 8 bytes - i++; // Special skip necessary - break; - case 7: // CLASS - int offset = data.readShort(); - offsetTable.put(i, offset); - break; - case 8: // STRING - data.readShort(); // discard 2 bytes - break; - case 3: // INTEGER - case 4: // FLOAT - case 9: // FIELD_REF - case 10: // METHOD_REF - case 11: // INTERFACE_METHOD_REF - case 12: // NAME_AND_TYPE - case 18: // Invoke Dynamic - data.readInt(); // discard 4 bytes - break; - case 15: // Method Handle - data.readByte(); - data.readShort(); - break; - case 16: // Method Type - data.readShort(); - break; - default: - throw - new RuntimeException("Bad tag " + tag); - } - } - short accessFlags = data.readShort(); - String access = (accessFlags & 0x0001) == 0 ? - "nonpublic:" : "public:"; - int thisClass = data.readShort(); - int superClass = data.readShort(); - return access + classNameTable.get( - offsetTable.get(thisClass)).replace('/', '.'); - } catch(IOException | RuntimeException e) { - throw new RuntimeException(e); - } - } - // Demonstration: - public static void - main(String[] args) throws Exception { - PathMatcher matcher = FileSystems.getDefault() - .getPathMatcher("glob:**/*.class"); - // Walk the entire tree: - Files.walk(Paths.get(".")) - .filter(matcher::matches) - .map(p -> { - try { - return thisClass(Files.readAllBytes(p)); - } catch(Exception e) { - throw new RuntimeException(e); - } - }) - .filter(s -> s.startsWith("public:")) - // .filter(s -> s.indexOf('$') >= 0) - .map(s -> s.split(":")[1]) - .filter(s -> !s.startsWith("enums.")) - .filter(s -> s.contains(".")) - .forEach(System.out::println); - } -} -/* Output: -onjava.ArrayShow -onjava.atunit.AtUnit$TestMethods -onjava.atunit.AtUnit -onjava.atunit.ClassNameFinder -onjava.atunit.Test -onjava.atunit.TestObjectCleanup -onjava.atunit.TestObjectCreate -onjava.atunit.TestProperty -onjava.BasicSupplier -onjava.CollectionMethodDifferences -onjava.ConvertTo -onjava.Count$Boolean -onjava.Count$Byte -onjava.Count$Character -onjava.Count$Double -onjava.Count$Float -onjava.Count$Integer -onjava.Count$Long -onjava.Count$Pboolean -onjava.Count$Pbyte -onjava.Count$Pchar -onjava.Count$Pdouble -onjava.Count$Pfloat -onjava.Count$Pint -onjava.Count$Plong -onjava.Count$Pshort -onjava.Count$Short -onjava.Count -onjava.CountingIntegerList -onjava.CountMap -onjava.Countries -onjava.Enums -onjava.FillMap -onjava.HTMLColors -onjava.MouseClick -onjava.Nap -onjava.Null -onjava.Operations -onjava.OSExecute -onjava.OSExecuteException -onjava.Pair -onjava.ProcessFiles$Strategy -onjava.ProcessFiles -onjava.Rand$Boolean -onjava.Rand$Byte -onjava.Rand$Character -onjava.Rand$Double -onjava.Rand$Float -onjava.Rand$Integer -onjava.Rand$Long -onjava.Rand$Pboolean -onjava.Rand$Pbyte -onjava.Rand$Pchar -onjava.Rand$Pdouble -onjava.Rand$Pfloat -onjava.Rand$Pint -onjava.Rand$Plong -onjava.Rand$Pshort -onjava.Rand$Short -onjava.Rand$String -onjava.Rand -onjava.Range -onjava.Repeat -onjava.RmDir -onjava.Sets -onjava.Stack -onjava.Suppliers -onjava.TimedAbort -onjava.Timer -onjava.Tuple -onjava.Tuple2 -onjava.Tuple3 -onjava.Tuple4 -onjava.Tuple5 -onjava.TypeCounter -*/ diff --git a/code/onjava/atunit/Test.java b/code/onjava/atunit/Test.java deleted file mode 100644 index 314dce9b..00000000 --- a/code/onjava/atunit/Test.java +++ /dev/null @@ -1,11 +0,0 @@ -// onjava/atunit/Test.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The @Test tag -package onjava.atunit; -import java.lang.annotation.*; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Test {} diff --git a/code/onjava/atunit/TestObjectCleanup.java b/code/onjava/atunit/TestObjectCleanup.java deleted file mode 100644 index 52231177..00000000 --- a/code/onjava/atunit/TestObjectCleanup.java +++ /dev/null @@ -1,11 +0,0 @@ -// onjava/atunit/TestObjectCleanup.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The @Unit @TestObjectCleanup tag -package onjava.atunit; -import java.lang.annotation.*; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface TestObjectCleanup {} diff --git a/code/onjava/atunit/TestObjectCreate.java b/code/onjava/atunit/TestObjectCreate.java deleted file mode 100644 index f8b43a09..00000000 --- a/code/onjava/atunit/TestObjectCreate.java +++ /dev/null @@ -1,11 +0,0 @@ -// onjava/atunit/TestObjectCreate.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The @Unit @TestObjectCreate tag -package onjava.atunit; -import java.lang.annotation.*; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface TestObjectCreate {} diff --git a/code/onjava/atunit/TestProperty.java b/code/onjava/atunit/TestProperty.java deleted file mode 100644 index 4e09cf95..00000000 --- a/code/onjava/atunit/TestProperty.java +++ /dev/null @@ -1,12 +0,0 @@ -// onjava/atunit/TestProperty.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The @Unit @TestProperty tag -package onjava.atunit; -import java.lang.annotation.*; - -// Both fields and methods can be tagged as properties: -@Target({ElementType.FIELD, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface TestProperty {} diff --git a/code/operators/AllOps.java b/code/operators/AllOps.java deleted file mode 100644 index bb94e870..00000000 --- a/code/operators/AllOps.java +++ /dev/null @@ -1,411 +0,0 @@ -// operators/AllOps.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Tests all operators on all primitive data types -// to show which ones are accepted by the Java compiler - -public class AllOps { - // To accept the results of a boolean test: - void f(boolean b) {} - void boolTest(boolean x, boolean y) { - // Arithmetic operators: - //- x = x * y; - //- x = x / y; - //- x = x % y; - //- x = x + y; - //- x = x - y; - //- x++; - //- x--; - //- x = +y; - //- x = -y; - // Relational and logical: - //- f(x > y); - //- f(x >= y); - //- f(x < y); - //- f(x <= y); - f(x == y); - f(x != y); - f(!y); - x = x && y; - x = x || y; - // Bitwise operators: - //- x = ~y; - x = x & y; - x = x | y; - x = x ^ y; - //- x = x << 1; - //- x = x >> 1; - //- x = x >>> 1; - // Compound assignment: - //- x += y; - //- x -= y; - //- x *= y; - //- x /= y; - //- x %= y; - //- x <<= 1; - //- x >>= 1; - //- x >>>= 1; - x &= y; - x ^= y; - x |= y; - // Casting: - //- char c = (char)x; - //- byte b = (byte)x; - //- short s = (short)x; - //- int i = (int)x; - //- long l = (long)x; - //- float f = (float)x; - //- double d = (double)x; - } - void charTest(char x, char y) { - // Arithmetic operators: - x = (char)(x * y); - x = (char)(x / y); - x = (char)(x % y); - x = (char)(x + y); - x = (char)(x - y); - x++; - x--; - x = (char) + y; - x = (char) - y; - // Relational and logical: - f(x > y); - f(x >= y); - f(x < y); - f(x <= y); - f(x == y); - f(x != y); - //- f(!x); - //- f(x && y); - //- f(x || y); - // Bitwise operators: - x= (char)~y; - x = (char)(x & y); - x = (char)(x | y); - x = (char)(x ^ y); - x = (char)(x << 1); - x = (char)(x >> 1); - x = (char)(x >>> 1); - // Compound assignment: - x += y; - x -= y; - x *= y; - x /= y; - x %= y; - x <<= 1; - x >>= 1; - x >>>= 1; - x &= y; - x ^= y; - x |= y; - // Casting: - //- boolean bl = (boolean)x; - byte b = (byte)x; - short s = (short)x; - int i = (int)x; - long l = (long)x; - float f = (float)x; - double d = (double)x; - } - void byteTest(byte x, byte y) { - // Arithmetic operators: - x = (byte)(x* y); - x = (byte)(x / y); - x = (byte)(x % y); - x = (byte)(x + y); - x = (byte)(x - y); - x++; - x--; - x = (byte) + y; - x = (byte) - y; - // Relational and logical: - f(x > y); - f(x >= y); - f(x < y); - f(x <= y); - f(x == y); - f(x != y); - //- f(!x); - //- f(x && y); - //- f(x || y); - // Bitwise operators: - x = (byte)~y; - x = (byte)(x & y); - x = (byte)(x | y); - x = (byte)(x ^ y); - x = (byte)(x << 1); - x = (byte)(x >> 1); - x = (byte)(x >>> 1); - // Compound assignment: - x += y; - x -= y; - x *= y; - x /= y; - x %= y; - x <<= 1; - x >>= 1; - x >>>= 1; - x &= y; - x ^= y; - x |= y; - // Casting: - //- boolean bl = (boolean)x; - char c = (char)x; - short s = (short)x; - int i = (int)x; - long l = (long)x; - float f = (float)x; - double d = (double)x; - } - void shortTest(short x, short y) { - // Arithmetic operators: - x = (short)(x * y); - x = (short)(x / y); - x = (short)(x % y); - x = (short)(x + y); - x = (short)(x - y); - x++; - x--; - x = (short) + y; - x = (short) - y; - // Relational and logical: - f(x > y); - f(x >= y); - f(x < y); - f(x <= y); - f(x == y); - f(x != y); - //- f(!x); - //- f(x && y); - //- f(x || y); - // Bitwise operators: - x = (short) ~ y; - x = (short)(x & y); - x = (short)(x | y); - x = (short)(x ^ y); - x = (short)(x << 1); - x = (short)(x >> 1); - x = (short)(x >>> 1); - // Compound assignment: - x += y; - x -= y; - x *= y; - x /= y; - x %= y; - x <<= 1; - x >>= 1; - x >>>= 1; - x &= y; - x ^= y; - x |= y; - // Casting: - //- boolean bl = (boolean)x; - char c = (char)x; - byte b = (byte)x; - int i = (int)x; - long l = (long)x; - float f = (float)x; - double d = (double)x; - } - void intTest(int x, int y) { - // Arithmetic operators: - x = x * y; - x = x / y; - x = x % y; - x = x + y; - x = x - y; - x++; - x--; - x = +y; - x = -y; - // Relational and logical: - f(x > y); - f(x >= y); - f(x < y); - f(x <= y); - f(x == y); - f(x != y); - //- f(!x); - //- f(x && y); - //- f(x || y); - // Bitwise operators: - x = ~y; - x = x & y; - x = x | y; - x = x ^ y; - x = x << 1; - x = x >> 1; - x = x >>> 1; - // Compound assignment: - x += y; - x -= y; - x *= y; - x /= y; - x %= y; - x <<= 1; - x >>= 1; - x >>>= 1; - x &= y; - x ^= y; - x |= y; - // Casting: - //- boolean bl = (boolean)x; - char c = (char)x; - byte b = (byte)x; - short s = (short)x; - long l = (long)x; - float f = (float)x; - double d = (double)x; - } - void longTest(long x, long y) { - // Arithmetic operators: - x = x * y; - x = x / y; - x = x % y; - x = x + y; - x = x - y; - x++; - x--; - x = +y; - x = -y; - // Relational and logical: - f(x > y); - f(x >= y); - f(x < y); - f(x <= y); - f(x == y); - f(x != y); - //- f(!x); - //- f(x && y); - //- f(x || y); - // Bitwise operators: - x = ~y; - x = x & y; - x = x | y; - x = x ^ y; - x = x << 1; - x = x >> 1; - x = x >>> 1; - // Compound assignment: - x += y; - x -= y; - x *= y; - x /= y; - x %= y; - x <<= 1; - x >>= 1; - x >>>= 1; - x &= y; - x ^= y; - x |= y; - // Casting: - //- boolean bl = (boolean)x; - char c = (char)x; - byte b = (byte)x; - short s = (short)x; - int i = (int)x; - float f = (float)x; - double d = (double)x; - } - void floatTest(float x, float y) { - // Arithmetic operators: - x = x * y; - x = x / y; - x = x % y; - x = x + y; - x = x - y; - x++; - x--; - x = +y; - x = -y; - // Relational and logical: - f(x > y); - f(x >= y); - f(x < y); - f(x <= y); - f(x == y); - f(x != y); - //- f(!x); - //- f(x && y); - //- f(x || y); - // Bitwise operators: - //- x = ~y; - //- x = x & y; - //- x = x | y; - //- x = x ^ y; - //- x = x << 1; - //- x = x >> 1; - //- x = x >>> 1; - // Compound assignment: - x += y; - x -= y; - x *= y; - x /= y; - x %= y; - //- x <<= 1; - //- x >>= 1; - //- x >>>= 1; - //- x &= y; - //- x ^= y; - //- x |= y; - // Casting: - //- boolean bl = (boolean)x; - char c = (char)x; - byte b = (byte)x; - short s = (short)x; - int i = (int)x; - long l = (long)x; - double d = (double)x; - } - void doubleTest(double x, double y) { - // Arithmetic operators: - x = x * y; - x = x / y; - x = x % y; - x = x + y; - x = x - y; - x++; - x--; - x = +y; - x = -y; - // Relational and logical: - f(x > y); - f(x >= y); - f(x < y); - f(x <= y); - f(x == y); - f(x != y); - //- f(!x); - //- f(x && y); - //- f(x || y); - // Bitwise operators: - //- x = ~y; - //- x = x & y; - //- x = x | y; - //- x = x ^ y; - //- x = x << 1; - //- x = x >> 1; - //- x = x >>> 1; - // Compound assignment: - x += y; - x -= y; - x *= y; - x /= y; - x %= y; - //- x <<= 1; - //- x >>= 1; - //- x >>>= 1; - //- x &= y; - //- x ^= y; - //- x |= y; - // Casting: - //- boolean bl = (boolean)x; - char c = (char)x; - byte b = (byte)x; - short s = (short)x; - int i = (int)x; - long l = (long)x; - float f = (float)x; - } -} diff --git a/code/operators/Assignment.java b/code/operators/Assignment.java deleted file mode 100644 index 7a573a39..00000000 --- a/code/operators/Assignment.java +++ /dev/null @@ -1,31 +0,0 @@ -// operators/Assignment.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Assignment with objects is a bit tricky - -class Tank { - int level; -} - -public class Assignment { - public static void main(String[] args) { - Tank t1 = new Tank(); - Tank t2 = new Tank(); - t1.level = 9; - t2.level = 47; - System.out.println("1: t1.level: " + t1.level + - ", t2.level: " + t2.level); - t1 = t2; - System.out.println("2: t1.level: " + t1.level + - ", t2.level: " + t2.level); - t1.level = 27; - System.out.println("3: t1.level: " + t1.level + - ", t2.level: " + t2.level); - } -} -/* Output: -1: t1.level: 9, t2.level: 47 -2: t1.level: 47, t2.level: 47 -3: t1.level: 27, t2.level: 27 -*/ diff --git a/code/operators/AutoInc.java b/code/operators/AutoInc.java deleted file mode 100644 index 835875de..00000000 --- a/code/operators/AutoInc.java +++ /dev/null @@ -1,27 +0,0 @@ -// operators/AutoInc.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates the ++ and -- operators - -public class AutoInc { - public static void main(String[] args) { - int i = 1; - System.out.println("i: " + i); - System.out.println("++i: " + ++i); // Pre-increment - System.out.println("i++: " + i++); // Post-increment - System.out.println("i: " + i); - System.out.println("--i: " + --i); // Pre-decrement - System.out.println("i--: " + i--); // Post-decrement - System.out.println("i: " + i); - } -} -/* Output: -i: 1 -++i: 2 -i++: 2 -i: 3 ---i: 2 -i--: 2 -i: 1 -*/ diff --git a/code/operators/BitManipulation.java b/code/operators/BitManipulation.java deleted file mode 100644 index dc30c442..00000000 --- a/code/operators/BitManipulation.java +++ /dev/null @@ -1,98 +0,0 @@ -// operators/BitManipulation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using the bitwise operators -import java.util.*; - -public class BitManipulation { - public static void main(String[] args) { - Random rand = new Random(47); - int i = rand.nextInt(); - int j = rand.nextInt(); - printBinaryInt("-1", -1); - printBinaryInt("+1", +1); - int maxpos = 2147483647; - printBinaryInt("maxpos", maxpos); - int maxneg = -2147483648; - printBinaryInt("maxneg", maxneg); - printBinaryInt("i", i); - printBinaryInt("~i", ~i); - printBinaryInt("-i", -i); - printBinaryInt("j", j); - printBinaryInt("i & j", i & j); - printBinaryInt("i | j", i | j); - printBinaryInt("i ^ j", i ^ j); - printBinaryInt("i << 5", i << 5); - printBinaryInt("i >> 5", i >> 5); - printBinaryInt("(~i) >> 5", (~i) >> 5); - printBinaryInt("i >>> 5", i >>> 5); - printBinaryInt("(~i) >>> 5", (~i) >>> 5); - - long l = rand.nextLong(); - long m = rand.nextLong(); - printBinaryLong("-1L", -1L); - printBinaryLong("+1L", +1L); - long ll = 9223372036854775807L; - printBinaryLong("maxpos", ll); - long lln = -9223372036854775808L; - printBinaryLong("maxneg", lln); - printBinaryLong("l", l); - printBinaryLong("~l", ~l); - printBinaryLong("-l", -l); - printBinaryLong("m", m); - printBinaryLong("l & m", l & m); - printBinaryLong("l | m", l | m); - printBinaryLong("l ^ m", l ^ m); - printBinaryLong("l << 5", l << 5); - printBinaryLong("l >> 5", l >> 5); - printBinaryLong("(~l) >> 5", (~l) >> 5); - printBinaryLong("l >>> 5", l >>> 5); - printBinaryLong("(~l) >>> 5", (~l) >>> 5); - } - static void printBinaryInt(String s, int i) { - System.out.println( - s + ", int: " + i + ", binary:\n " + - Integer.toBinaryString(i)); - } - static void printBinaryLong(String s, long l) { - System.out.println( - s + ", long: " + l + ", binary:\n " + - Long.toBinaryString(l)); - } -} -/* Output: (First 32 Lines) --1, int: -1, binary: - 11111111111111111111111111111111 -+1, int: 1, binary: - 1 -maxpos, int: 2147483647, binary: - 1111111111111111111111111111111 -maxneg, int: -2147483648, binary: - 10000000000000000000000000000000 -i, int: -1172028779, binary: - 10111010001001000100001010010101 -~i, int: 1172028778, binary: - 1000101110110111011110101101010 --i, int: 1172028779, binary: - 1000101110110111011110101101011 -j, int: 1717241110, binary: - 1100110010110110000010100010110 -i & j, int: 570425364, binary: - 100010000000000000000000010100 -i | j, int: -25213033, binary: - 11111110011111110100011110010111 -i ^ j, int: -595638397, binary: - 11011100011111110100011110000011 -i << 5, int: 1149784736, binary: - 1000100100010000101001010100000 -i >> 5, int: -36625900, binary: - 11111101110100010010001000010100 -(~i) >> 5, int: 36625899, binary: - 10001011101101110111101011 -i >>> 5, int: 97591828, binary: - 101110100010010001000010100 -(~i) >>> 5, int: 36625899, binary: - 10001011101101110111101011 - ... -*/ diff --git a/code/operators/Bool.java b/code/operators/Bool.java deleted file mode 100644 index e9984adb..00000000 --- a/code/operators/Bool.java +++ /dev/null @@ -1,42 +0,0 @@ -// operators/Bool.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Relational and logical operators -import java.util.*; - -public class Bool { - public static void main(String[] args) { - Random rand = new Random(47); - int i = rand.nextInt(100); - int j = rand.nextInt(100); - System.out.println("i = " + i); - System.out.println("j = " + j); - System.out.println("i > j is " + (i > j)); - System.out.println("i < j is " + (i < j)); - System.out.println("i >= j is " + (i >= j)); - System.out.println("i <= j is " + (i <= j)); - System.out.println("i == j is " + (i == j)); - System.out.println("i != j is " + (i != j)); - // Treating an int as a boolean is not legal Java: - //- System.out.println("i && j is " + (i && j)); - //- System.out.println("i || j is " + (i || j)); - //- System.out.println("!i is " + !i); - System.out.println("(i < 10) && (j < 10) is " - + ((i < 10) && (j < 10)) ); - System.out.println("(i < 10) || (j < 10) is " - + ((i < 10) || (j < 10)) ); - } -} -/* Output: -i = 58 -j = 55 -i > j is true -i < j is false -i >= j is true -i <= j is false -i == j is false -i != j is true -(i < 10) && (j < 10) is false -(i < 10) || (j < 10) is false -*/ diff --git a/code/operators/Casting.java b/code/operators/Casting.java deleted file mode 100644 index 337b24fd..00000000 --- a/code/operators/Casting.java +++ /dev/null @@ -1,16 +0,0 @@ -// operators/Casting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Casting { - public static void main(String[] args) { - int i = 200; - long lng = (long)i; - lng = i; // "Widening," so a cast is not required - long lng2 = (long)200; - lng2 = 200; - // A "narrowing conversion": - i = (int)lng2; // Cast required - } -} diff --git a/code/operators/CastingNumbers.java b/code/operators/CastingNumbers.java deleted file mode 100644 index a6c04c6e..00000000 --- a/code/operators/CastingNumbers.java +++ /dev/null @@ -1,23 +0,0 @@ -// operators/CastingNumbers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// What happens when you cast a float -// or double to an integral value? - -public class CastingNumbers { - public static void main(String[] args) { - double above = 0.7, below = 0.4; - float fabove = 0.7f, fbelow = 0.4f; - System.out.println("(int)above: " + (int)above); - System.out.println("(int)below: " + (int)below); - System.out.println("(int)fabove: " + (int)fabove); - System.out.println("(int)fbelow: " + (int)fbelow); - } -} -/* Output: -(int)above: 0 -(int)below: 0 -(int)fabove: 0 -(int)fbelow: 0 -*/ diff --git a/code/operators/EqualsMethod.java b/code/operators/EqualsMethod.java deleted file mode 100644 index f55b1b57..00000000 --- a/code/operators/EqualsMethod.java +++ /dev/null @@ -1,15 +0,0 @@ -// operators/EqualsMethod.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class EqualsMethod { - public static void main(String[] args) { - Integer n1 = 47; - Integer n2 = 47; - System.out.println(n1.equals(n2)); - } -} -/* Output: -true -*/ diff --git a/code/operators/EqualsMethod2.java b/code/operators/EqualsMethod2.java deleted file mode 100644 index 21393060..00000000 --- a/code/operators/EqualsMethod2.java +++ /dev/null @@ -1,21 +0,0 @@ -// operators/EqualsMethod2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Default equals() does not compare contents - -class Value { - int i; -} - -public class EqualsMethod2 { - public static void main(String[] args) { - Value v1 = new Value(); - Value v2 = new Value(); - v1.i = v2.i = 100; - System.out.println(v1.equals(v2)); - } -} -/* Output: -false -*/ diff --git a/code/operators/Equivalence.java b/code/operators/Equivalence.java deleted file mode 100644 index cef07d64..00000000 --- a/code/operators/Equivalence.java +++ /dev/null @@ -1,17 +0,0 @@ -// operators/Equivalence.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Equivalence { - public static void main(String[] args) { - Integer n1 = 47; - Integer n2 = 47; - System.out.println(n1 == n2); - System.out.println(n1 != n2); - } -} -/* Output: -true -false -*/ diff --git a/code/operators/Exponents.java b/code/operators/Exponents.java deleted file mode 100644 index 924340df..00000000 --- a/code/operators/Exponents.java +++ /dev/null @@ -1,21 +0,0 @@ -// operators/Exponents.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// "e" means "10 to the power." - -public class Exponents { - public static void main(String[] args) { - // Uppercase and lowercase 'e' are the same: - float expFloat = 1.39e-43f; - expFloat = 1.39E-43f; - System.out.println(expFloat); - double expDouble = 47e47d; // 'd' is optional - double expDouble2 = 47e47; // Automatically double - System.out.println(expDouble); - } -} -/* Output: -1.39E-43 -4.7E48 -*/ diff --git a/code/operators/Literals.java b/code/operators/Literals.java deleted file mode 100644 index ad00e0b8..00000000 --- a/code/operators/Literals.java +++ /dev/null @@ -1,61 +0,0 @@ -// operators/Literals.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Literals { - public static void main(String[] args) { - int i1 = 0x2f; // Hexadecimal (lowercase) - System.out.println( - "i1: " + Integer.toBinaryString(i1)); - int i2 = 0X2F; // Hexadecimal (uppercase) - System.out.println( - "i2: " + Integer.toBinaryString(i2)); - int i3 = 0177; // Octal (leading zero) - System.out.println( - "i3: " + Integer.toBinaryString(i3)); - char c = 0xffff; // max char hex value - System.out.println( - "c: " + Integer.toBinaryString(c)); - byte b = 0x7f; // max byte hex value 10101111; - System.out.println( - "b: " + Integer.toBinaryString(b)); - short s = 0x7fff; // max short hex value - System.out.println( - "s: " + Integer.toBinaryString(s)); - long n1 = 200L; // long suffix - long n2 = 200l; // long suffix (can be confusing) - long n3 = 200; - // Java 7 Binary Literals: - byte blb = (byte)0b00110101; - System.out.println( - "blb: " + Integer.toBinaryString(blb)); - short bls = (short)0B0010111110101111; - System.out.println( - "bls: " + Integer.toBinaryString(bls)); - int bli = 0b00101111101011111010111110101111; - System.out.println( - "bli: " + Integer.toBinaryString(bli)); - long bll = 0b00101111101011111010111110101111; - System.out.println( - "bll: " + Long.toBinaryString(bll)); - float f1 = 1; - float f2 = 1F; // float suffix - float f3 = 1f; // float suffix - double d1 = 1d; // double suffix - double d2 = 1D; // double suffix - // (Hex and Octal also work with long) - } -} -/* Output: -i1: 101111 -i2: 101111 -i3: 1111111 -c: 1111111111111111 -b: 1111111 -s: 111111111111111 -blb: 110101 -bls: 10111110101111 -bli: 101111101011111010111110101111 -bll: 101111101011111010111110101111 -*/ diff --git a/code/operators/MathOps.java b/code/operators/MathOps.java deleted file mode 100644 index a9b08938..00000000 --- a/code/operators/MathOps.java +++ /dev/null @@ -1,75 +0,0 @@ -// operators/MathOps.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The mathematical operators -import java.util.*; - -public class MathOps { - public static void main(String[] args) { - // Create a seeded random number generator: - Random rand = new Random(47); - int i, j, k; - // Choose value from 1 to 100: - j = rand.nextInt(100) + 1; - System.out.println("j : " + j); - k = rand.nextInt(100) + 1; - System.out.println("k : " + k); - i = j + k; - System.out.println("j + k : " + i); - i = j - k; - System.out.println("j - k : " + i); - i = k / j; - System.out.println("k / j : " + i); - i = k * j; - System.out.println("k * j : " + i); - i = k % j; - System.out.println("k % j : " + i); - j %= k; - System.out.println("j %= k : " + j); - // Floating-point number tests: - float u, v, w; // Applies to doubles, too - v = rand.nextFloat(); - System.out.println("v : " + v); - w = rand.nextFloat(); - System.out.println("w : " + w); - u = v + w; - System.out.println("v + w : " + u); - u = v - w; - System.out.println("v - w : " + u); - u = v * w; - System.out.println("v * w : " + u); - u = v / w; - System.out.println("v / w : " + u); - // The following also works for char, - // byte, short, int, long, and double: - u += v; - System.out.println("u += v : " + u); - u -= v; - System.out.println("u -= v : " + u); - u *= v; - System.out.println("u *= v : " + u); - u /= v; - System.out.println("u /= v : " + u); - } -} -/* Output: -j : 59 -k : 56 -j + k : 115 -j - k : 3 -k / j : 0 -k * j : 3304 -k % j : 56 -j %= k : 3 -v : 0.5309454 -w : 0.0534122 -v + w : 0.5843576 -v - w : 0.47753322 -v * w : 0.028358962 -v / w : 9.940527 -u += v : 10.471473 -u -= v : 9.940527 -u *= v : 5.2778773 -u /= v : 9.940527 -*/ diff --git a/code/operators/Overflow.java b/code/operators/Overflow.java deleted file mode 100644 index 851c1456..00000000 --- a/code/operators/Overflow.java +++ /dev/null @@ -1,18 +0,0 @@ -// operators/Overflow.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Surprise! Java lets you overflow - -public class Overflow { - public static void main(String[] args) { - int big = Integer.MAX_VALUE; - System.out.println("big = " + big); - int bigger = big * 4; - System.out.println("bigger = " + bigger); - } -} -/* Output: -big = 2147483647 -bigger = -4 -*/ diff --git a/code/operators/PassObject.java b/code/operators/PassObject.java deleted file mode 100644 index af53ab56..00000000 --- a/code/operators/PassObject.java +++ /dev/null @@ -1,27 +0,0 @@ -// operators/PassObject.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Passing objects to methods might not be -// what you're used to - -class Letter { - char c; -} - -public class PassObject { - static void f(Letter y) { - y.c = 'z'; - } - public static void main(String[] args) { - Letter x = new Letter(); - x.c = 'a'; - System.out.println("1: x.c: " + x.c); - f(x); - System.out.println("2: x.c: " + x.c); - } -} -/* Output: -1: x.c: a -2: x.c: z -*/ diff --git a/code/operators/Precedence.java b/code/operators/Precedence.java deleted file mode 100644 index f0f8140c..00000000 --- a/code/operators/Precedence.java +++ /dev/null @@ -1,18 +0,0 @@ -// operators/Precedence.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Precedence { - public static void main(String[] args) { - int x = 1, y = 2, z = 3; - int a = x + y - 2/2 + z; // [1] - int b = x + (y - 2)/(2 + z); // [2] - System.out.println("a = " + a); - System.out.println("b = " + b); - } -} -/* Output: -a = 5 -b = 1 -*/ diff --git a/code/operators/RoundingNumbers.java b/code/operators/RoundingNumbers.java deleted file mode 100644 index e46a2056..00000000 --- a/code/operators/RoundingNumbers.java +++ /dev/null @@ -1,26 +0,0 @@ -// operators/RoundingNumbers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Rounding floats and doubles - -public class RoundingNumbers { - public static void main(String[] args) { - double above = 0.7, below = 0.4; - float fabove = 0.7f, fbelow = 0.4f; - System.out.println( - "Math.round(above): " + Math.round(above)); - System.out.println( - "Math.round(below): " + Math.round(below)); - System.out.println( - "Math.round(fabove): " + Math.round(fabove)); - System.out.println( - "Math.round(fbelow): " + Math.round(fbelow)); - } -} -/* Output: -Math.round(above): 1 -Math.round(below): 0 -Math.round(fabove): 1 -Math.round(fbelow): 0 -*/ diff --git a/code/operators/ShortCircuit.java b/code/operators/ShortCircuit.java deleted file mode 100644 index 8fc96711..00000000 --- a/code/operators/ShortCircuit.java +++ /dev/null @@ -1,34 +0,0 @@ -// operators/ShortCircuit.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Short-circuiting behavior with logical operators - -public class ShortCircuit { - static boolean test1(int val) { - System.out.println("test1(" + val + ")"); - System.out.println("result: " + (val < 1)); - return val < 1; - } - static boolean test2(int val) { - System.out.println("test2(" + val + ")"); - System.out.println("result: " + (val < 2)); - return val < 2; - } - static boolean test3(int val) { - System.out.println("test3(" + val + ")"); - System.out.println("result: " + (val < 3)); - return val < 3; - } - public static void main(String[] args) { - boolean b = test1(0) && test2(2) && test3(2); - System.out.println("expression is " + b); - } -} -/* Output: -test1(0) -result: true -test2(2) -result: false -expression is false -*/ diff --git a/code/operators/StringOperators.java b/code/operators/StringOperators.java deleted file mode 100644 index b1eb211f..00000000 --- a/code/operators/StringOperators.java +++ /dev/null @@ -1,24 +0,0 @@ -// operators/StringOperators.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class StringOperators { - public static void main(String[] args) { - int x = 0, y = 1, z = 2; - String s = "x, y, z "; - System.out.println(s + x + y + z); - // Converts x to a String: - System.out.println(x + " " + s); - s += "(summed) = "; // Concatenation operator - System.out.println(s + (x + y + z)); - // Shorthand for Integer.toString(): - System.out.println("" + x); - } -} -/* Output: -x, y, z 012 -0 x, y, z -x, y, z (summed) = 3 -0 -*/ diff --git a/code/operators/TernaryIfElse.java b/code/operators/TernaryIfElse.java deleted file mode 100644 index d11d4e24..00000000 --- a/code/operators/TernaryIfElse.java +++ /dev/null @@ -1,28 +0,0 @@ -// operators/TernaryIfElse.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class TernaryIfElse { - static int ternary(int i) { - return i < 10 ? i * 100 : i * 10; - } - static int standardIfElse(int i) { - if(i < 10) - return i * 100; - else - return i * 10; - } - public static void main(String[] args) { - System.out.println(ternary(9)); - System.out.println(ternary(10)); - System.out.println(standardIfElse(9)); - System.out.println(standardIfElse(10)); - } -} -/* Output: -900 -100 -900 -100 -*/ diff --git a/code/operators/URShift.java b/code/operators/URShift.java deleted file mode 100644 index 8d24f94b..00000000 --- a/code/operators/URShift.java +++ /dev/null @@ -1,42 +0,0 @@ -// operators/URShift.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Test of unsigned right shift - -public class URShift { - public static void main(String[] args) { - int i = -1; - System.out.println(Integer.toBinaryString(i)); - i >>>= 10; - System.out.println(Integer.toBinaryString(i)); - long l = -1; - System.out.println(Long.toBinaryString(l)); - l >>>= 10; - System.out.println(Long.toBinaryString(l)); - short s = -1; - System.out.println(Integer.toBinaryString(s)); - s >>>= 10; - System.out.println(Integer.toBinaryString(s)); - byte b = -1; - System.out.println(Integer.toBinaryString(b)); - b >>>= 10; - System.out.println(Integer.toBinaryString(b)); - b = -1; - System.out.println(Integer.toBinaryString(b)); - System.out.println(Integer.toBinaryString(b>>>10)); - } -} -/* Output: -11111111111111111111111111111111 -1111111111111111111111 -1111111111111111111111111111111111111111111111111111111 -111111111 -111111111111111111111111111111111111111111111111111111 -11111111111111111111111111111111 -11111111111111111111111111111111 -11111111111111111111111111111111 -11111111111111111111111111111111 -11111111111111111111111111111111 -1111111111111111111111 -*/ diff --git a/code/operators/Underscores.java b/code/operators/Underscores.java deleted file mode 100644 index 4d78cd50..00000000 --- a/code/operators/Underscores.java +++ /dev/null @@ -1,22 +0,0 @@ -// operators/Underscores.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Underscores { - public static void main(String[] args) { - double d = 341_435_936.445_667; - System.out.println(d); - int bin = 0b0010_1111_1010_1111_1010_1111_1010_1111; - System.out.println(Integer.toBinaryString(bin)); - System.out.printf("%x%n", bin); // [1] - long hex = 0x7f_e9_b7_aa; - System.out.printf("%x%n", hex); - } -} -/* Output: -3.41435936445667E8 -101111101011111010111110101111 -2fafafaf -7fe9b7aa -*/ diff --git a/code/patterns/BoxObserver.java b/code/patterns/BoxObserver.java deleted file mode 100644 index c6f9ec65..00000000 --- a/code/patterns/BoxObserver.java +++ /dev/null @@ -1,94 +0,0 @@ -// patterns/BoxObserver.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of Observer pattern using -// Java's built-in observer classes. -// {ExcludeFromGradle} // Won't work under WSL2 -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import onjava.*; -import onjava.MouseClick; - -// You must inherit a new type of Observable: -@SuppressWarnings("deprecation") -class BoxObservable extends Observable { - @Override - public void notifyObservers(Object b) { - // Otherwise it won't propagate changes: - setChanged(); - super.notifyObservers(b); - } -} - -@SuppressWarnings("deprecation") -public class BoxObserver extends JFrame { - Observable notifier = new BoxObservable(); - public BoxObserver(int grid) { - setTitle("Demonstrates Observer pattern"); - Container cp = getContentPane(); - cp.setLayout(new GridLayout(grid, grid)); - for(int x = 0; x < grid; x++) - for(int y = 0; y < grid; y++) - cp.add(new OCBox(x, y, notifier)); - } - public static void main(String[] args) { - // For automated test runs: - // new TimedAbort(4); - int grid = 8; - if(args.length > 0) - grid = Integer.parseInt(args[0]); - JFrame f = new BoxObserver(grid); - f.setSize(500, 400); - f.setVisible(true); - f.setDefaultCloseOperation(DISPOSE_ON_CLOSE); - } -} - -@SuppressWarnings("deprecation") -class OCBox extends JPanel implements Observer { - Observable notifier; - int x, y; // Locations in grid - Color cColor = newColor(); - static final Color[] COLORS = { - Color.black, Color.blue, Color.cyan, - Color.darkGray, Color.gray, Color.green, - Color.lightGray, Color.magenta, - Color.orange, Color.pink, Color.red, - Color.white, Color.yellow - }; - static Color newColor() { - return COLORS[ - (int)(Math.random() * COLORS.length) - ]; - } - OCBox(int x, int y, Observable notifier) { - this.x = x; - this.y = y; - notifier.addObserver(this); - this.notifier = notifier; - addMouseListener((MouseClick) - e -> notifier.notifyObservers(OCBox.this)); - } - @Override - public void paintComponent(Graphics g) { - super.paintComponent(g); - g.setColor(cColor); - Dimension s = getSize(); - g.fillRect(0, 0, s.width, s.height); - } - @Override - public void update(Observable o, Object arg) { - OCBox clicked = (OCBox)arg; - if(nextTo(clicked)) { - cColor = clicked.cColor; - repaint(); - } - } - private boolean nextTo(OCBox b) { - return Math.abs(x - b.x) <= 1 && - Math.abs(y - b.y) <= 1; - } -} diff --git a/code/patterns/CommandPattern.java b/code/patterns/CommandPattern.java deleted file mode 100644 index f84533aa..00000000 --- a/code/patterns/CommandPattern.java +++ /dev/null @@ -1,19 +0,0 @@ -// patterns/CommandPattern.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class CommandPattern { - public static void main(String[] args) { - List macro = Arrays.asList( - () -> System.out.print("Hello "), - () -> System.out.print("World! "), - () -> System.out.print("I'm the command pattern!") - ); - macro.forEach(Runnable::run); - } -} -/* Output: -Hello World! I'm the command pattern! -*/ diff --git a/code/patterns/Facade.java b/code/patterns/Facade.java deleted file mode 100644 index 0c1accf2..00000000 --- a/code/patterns/Facade.java +++ /dev/null @@ -1,24 +0,0 @@ -// patterns/Facade.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class A { A(int x) {} } -class B { B(long x) {} } -class C { C(double x) {} } - -// Other classes that aren't exposed by the -// facade go here ... - -public class Facade { - static A makeA(int x) { return new A(x); } - static B makeB(long x) { return new B(x); } - static C makeC(double x) { return new C(x); } - public static void main(String[] args) { - // The client programmer gets the objects - // by calling the static methods: - A a = Facade.makeA(1); - B b = Facade.makeB(1); - C c = Facade.makeC(1.0); - } -} diff --git a/code/patterns/PaperScissorsRock.java b/code/patterns/PaperScissorsRock.java deleted file mode 100644 index e7a7c44e..00000000 --- a/code/patterns/PaperScissorsRock.java +++ /dev/null @@ -1,135 +0,0 @@ -// patterns/PaperScissorsRock.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of multiple dispatching -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import onjava.*; -import static onjava.Tuple.*; - -enum Outcome { WIN, LOSE, DRAW } - -interface Item { - Outcome compete(Item it); - Outcome eval(Paper p); - Outcome eval(Scissors s); - Outcome eval(Rock r); -} - -class Paper implements Item { - @Override - public Outcome compete(Item it) { - return it.eval(this); - } - @Override - public Outcome eval(Paper p) { - return Outcome.DRAW; - } - @Override - public Outcome eval(Scissors s) { - return Outcome.WIN; - } - @Override - public Outcome eval(Rock r) { - return Outcome.LOSE; - } - @Override - public String toString() { return "Paper"; } -} - -class Scissors implements Item { - @Override - public Outcome compete(Item it) { - return it.eval(this); - } - @Override - public Outcome eval(Paper p) { - return Outcome.LOSE; - } - @Override - public Outcome eval(Scissors s) { - return Outcome.DRAW; - } - @Override - public Outcome eval(Rock r) { - return Outcome.WIN; - } - @Override - public String toString() { return "Scissors"; } -} - -class Rock implements Item { - @Override - public Outcome compete(Item it) { - return it.eval(this); - } - @Override - public Outcome eval(Paper p) { - return Outcome.WIN; - } - @Override - public Outcome eval(Scissors s) { - return Outcome.LOSE; - } - @Override - public Outcome eval(Rock r) { - return Outcome.DRAW; - } - @Override - public String toString() { return "Rock"; } -} - -class ItemFactory { - static List> items = - Arrays.asList( - Scissors::new, Paper::new, Rock::new); - static final int SZ = items.size(); - private static SplittableRandom rand = - new SplittableRandom(47); - public static Item newItem() { - return items.get(rand.nextInt(SZ)).get(); - } - public static Tuple2 newPair() { - return tuple(newItem(), newItem()); - } -} - -class Compete { - public static Outcome match(Tuple2 p) { - System.out.print(p.a1 + " -> " + p.a2 + " : "); - return p.a1.compete(p.a2); - } -} - -public class PaperScissorsRock { - public static void main(String[] args) { - Stream.generate(ItemFactory::newPair) - .limit(20) - .map(Compete::match) - .forEach(System.out::println); - } -} -/* Output: -Scissors -> Rock : LOSE -Scissors -> Paper : WIN -Rock -> Paper : LOSE -Rock -> Rock : DRAW -Rock -> Paper : LOSE -Paper -> Scissors : LOSE -Rock -> Paper : LOSE -Scissors -> Scissors : DRAW -Scissors -> Rock : LOSE -Scissors -> Paper : WIN -Scissors -> Rock : LOSE -Paper -> Scissors : LOSE -Rock -> Rock : DRAW -Scissors -> Scissors : DRAW -Paper -> Paper : DRAW -Scissors -> Paper : WIN -Scissors -> Rock : LOSE -Scissors -> Paper : WIN -Rock -> Paper : LOSE -Rock -> Scissors : WIN -*/ diff --git a/code/patterns/ProxyDemo.java b/code/patterns/ProxyDemo.java deleted file mode 100644 index 58b0e3a8..00000000 --- a/code/patterns/ProxyDemo.java +++ /dev/null @@ -1,51 +0,0 @@ -// patterns/ProxyDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple demonstration of the Proxy pattern - -interface ProxyBase { - void f(); - void g(); - void h(); -} - -class Proxy implements ProxyBase { - private ProxyBase implementation; - Proxy() { - implementation = new Implementation(); - } - // Pass method calls to the implementation: - @Override - public void f() { implementation.f(); } - @Override - public void g() { implementation.g(); } - @Override - public void h() { implementation.h(); } -} - -class Implementation implements ProxyBase { - public void f() { - System.out.println("Implementation.f()"); - } - public void g() { - System.out.println("Implementation.g()"); - } - public void h() { - System.out.println("Implementation.h()"); - } -} - -public class ProxyDemo { - public static void main(String[] args) { - Proxy p = new Proxy(); - p.f(); - p.g(); - p.h(); - } -} -/* Output: -Implementation.f() -Implementation.g() -Implementation.h() -*/ diff --git a/code/patterns/ShapeFactory1.java b/code/patterns/ShapeFactory1.java deleted file mode 100644 index dc6f8690..00000000 --- a/code/patterns/ShapeFactory1.java +++ /dev/null @@ -1,39 +0,0 @@ -// patterns/ShapeFactory1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A simple static factory method -import java.util.*; -import java.util.stream.*; -import patterns.shapes.*; - -public class ShapeFactory1 implements FactoryMethod { - public Shape create(String type) { - switch(type) { - case "Circle": return new Circle(); - case "Square": return new Square(); - case "Triangle": return new Triangle(); - default: - throw new BadShapeCreation(type); - } - } - public static void main(String[] args) { - FactoryTest.test(new ShapeFactory1()); - } -} -/* Output: -Circle[0] draw -Circle[0] erase -Square[1] draw -Square[1] erase -Triangle[2] draw -Triangle[2] erase -Square[3] draw -Square[3] erase -Circle[4] draw -Circle[4] erase -Circle[5] draw -Circle[5] erase -Triangle[6] draw -Triangle[6] erase -*/ diff --git a/code/patterns/ShapeFactory2.java b/code/patterns/ShapeFactory2.java deleted file mode 100644 index 23881105..00000000 --- a/code/patterns/ShapeFactory2.java +++ /dev/null @@ -1,54 +0,0 @@ -// patterns/ShapeFactory2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.lang.reflect.*; -import java.util.stream.*; -import patterns.shapes.*; - -public class ShapeFactory2 implements FactoryMethod { - Map factories = - new HashMap<>(); - static Constructor load(String id) { - System.out.println("loading " + id); - try { - return Class.forName("patterns.shapes." + id) - .getConstructor(); - } catch(ClassNotFoundException | - NoSuchMethodException e) { - throw new BadShapeCreation(id); - } - } - public Shape create(String id) { - try { - return (Shape)factories - .computeIfAbsent(id, ShapeFactory2::load) - .newInstance(); - } catch(Exception e) { - throw new BadShapeCreation(id); - } - } - public static void main(String[] args) { - FactoryTest.test(new ShapeFactory2()); - } -} -/* Output: -loading Circle -Circle[0] draw -Circle[0] erase -loading Square -Square[1] draw -Square[1] erase -loading Triangle -Triangle[2] draw -Triangle[2] erase -Square[3] draw -Square[3] erase -Circle[4] draw -Circle[4] erase -Circle[5] draw -Circle[5] erase -Triangle[6] draw -Triangle[6] erase -*/ diff --git a/code/patterns/ShapeFactory3.java b/code/patterns/ShapeFactory3.java deleted file mode 100644 index b735a81d..00000000 --- a/code/patterns/ShapeFactory3.java +++ /dev/null @@ -1,52 +0,0 @@ -// patterns/ShapeFactory3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Polymorphic factory methods -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import patterns.shapes.*; - -interface PolymorphicFactory { - Shape create(); -} - -class RandomShapes implements Supplier { - private final PolymorphicFactory[] factories; - private Random rand = new Random(42); - RandomShapes(PolymorphicFactory... factories) { - this.factories = factories; - } - public Shape get() { - return factories[ - rand.nextInt(factories.length)].create(); - } -} - -public class ShapeFactory3 { - public static void main(String[] args) { - RandomShapes rs = new RandomShapes( - Circle::new, Square::new, Triangle::new - ); - Stream.generate(rs) - .limit(6) - .peek(Shape::draw) - .peek(Shape::erase) - .count(); - } -} -/* Output: -Triangle[0] draw -Triangle[0] erase -Circle[1] draw -Circle[1] erase -Circle[2] draw -Circle[2] erase -Triangle[3] draw -Triangle[3] erase -Circle[4] draw -Circle[4] erase -Square[5] draw -Square[5] erase -*/ diff --git a/code/patterns/SingletonPattern.java b/code/patterns/SingletonPattern.java deleted file mode 100644 index c2ca1a5f..00000000 --- a/code/patterns/SingletonPattern.java +++ /dev/null @@ -1,58 +0,0 @@ -// patterns/SingletonPattern.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface Resource { - int getValue(); - void setValue(int x); -} - -// This isn't inherited from a Cloneable -// base class and cloneability isn't added so -// making it final prevents cloneability from -// being added through inheritance. This also -// implements thread-safe lazy initialization: - -final class Singleton { - private static final class - ResourceImpl implements Resource { - private int i; - private ResourceImpl(int i) { - this.i = i; - } - public synchronized int getValue() { - return i; - } - public synchronized void setValue(int x) { - i = x; - } - } - private static class ResourceHolder { - private static Resource resource = - new ResourceImpl(47); - } - public static Resource getResource() { - return ResourceHolder.resource; - } -} - -public class SingletonPattern { - public static void main(String[] args) { - Resource r = Singleton.getResource(); - System.out.println(r.getValue()); - Resource s2 = Singleton.getResource(); - s2.setValue(9); - System.out.println(r.getValue()); - try { - // Can't do this: compile-time error. - // Singleton s3 = (Singleton)s2.clone(); - } catch(Exception e) { - throw new RuntimeException(e); - } - } -} -/* Output: -47 -9 -*/ diff --git a/code/patterns/StateDemo.java b/code/patterns/StateDemo.java deleted file mode 100644 index 9efab5b4..00000000 --- a/code/patterns/StateDemo.java +++ /dev/null @@ -1,87 +0,0 @@ -// patterns/StateDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple demonstration of the State pattern - -interface StateBase { - void f(); - void g(); - void h(); - void changeImp(StateBase newImp); -} - -class State implements StateBase { - private StateBase implementation; - State(StateBase imp) { - implementation = imp; - } - @Override - public void changeImp(StateBase newImp) { - implementation = newImp; - } - // Pass method calls to the implementation: - @Override - public void f() { implementation.f(); } - @Override - public void g() { implementation.g(); } - @Override - public void h() { implementation.h(); } -} - -class Implementation1 implements StateBase { - @Override - public void f() { - System.out.println("Implementation1.f()"); - } - @Override - public void g() { - System.out.println("Implementation1.g()"); - } - @Override - public void h() { - System.out.println("Implementation1.h()"); - } - @Override - public void changeImp(StateBase newImp) {} -} - -class Implementation2 implements StateBase { - @Override - public void f() { - System.out.println("Implementation2.f()"); - } - @Override - public void g() { - System.out.println("Implementation2.g()"); - } - @Override - public void h() { - System.out.println("Implementation2.h()"); - } - @Override - public void changeImp(StateBase newImp) {} -} - -public class StateDemo { - static void test(StateBase b) { - b.f(); - b.g(); - b.h(); - } - public static void main(String[] args) { - StateBase b = - new State(new Implementation1()); - test(b); - b.changeImp(new Implementation2()); - test(b); - } -} -/* Output: -Implementation1.f() -Implementation1.g() -Implementation1.h() -Implementation2.f() -Implementation2.g() -Implementation2.h() -*/ diff --git a/code/patterns/TemplateMethod.java b/code/patterns/TemplateMethod.java deleted file mode 100644 index eff6d279..00000000 --- a/code/patterns/TemplateMethod.java +++ /dev/null @@ -1,44 +0,0 @@ -// patterns/TemplateMethod.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple demonstration of Template Method -import java.util.stream.*; - -abstract class ApplicationFramework { - ApplicationFramework() { - templateMethod(); - } - abstract void customize1(); - abstract void customize2(); - // "private" means automatically "final": - private void templateMethod() { - IntStream.range(0, 5).forEach( - n -> { customize1(); customize2(); }); - } -} - -// Create a new "application": -class MyApp extends ApplicationFramework { - @Override - void customize1() { - System.out.print("Hello "); - } - @Override - void customize2() { - System.out.println("World!"); - } -} - -public class TemplateMethod { - public static void main(String[] args) { - new MyApp(); - } -} -/* Output: -Hello World! -Hello World! -Hello World! -Hello World! -Hello World! -*/ diff --git a/code/patterns/abstractfactory/GameEnvironment.java b/code/patterns/abstractfactory/GameEnvironment.java deleted file mode 100644 index 8c0abf7b..00000000 --- a/code/patterns/abstractfactory/GameEnvironment.java +++ /dev/null @@ -1,96 +0,0 @@ -// patterns/abstractfactory/GameEnvironment.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An example of the Abstract Factory pattern -// {java patterns.abstractfactory.GameEnvironment} -package patterns.abstractfactory; -import java.util.function.*; - -interface Obstacle { - void action(); -} - -interface Player { - void interactWith(Obstacle o); -} - -class Kitty implements Player { - @Override - public void interactWith(Obstacle ob) { - System.out.print("Kitty has encountered a "); - ob.action(); - } -} - -class KungFuGuy implements Player { - @Override - public void interactWith(Obstacle ob) { - System.out.print("KungFuGuy now battles a "); - ob.action(); - } -} - -class Puzzle implements Obstacle { - @Override - public void action() { - System.out.println("Puzzle"); - } -} - -class NastyWeapon implements Obstacle { - @Override - public void action() { - System.out.println("NastyWeapon"); - } -} - -// The Abstract Factory: -class GameElementFactory { - Supplier player; - Supplier obstacle; -} - -// Concrete factories: -class KittiesAndPuzzles -extends GameElementFactory { - KittiesAndPuzzles() { - player = Kitty::new; - obstacle = Puzzle::new; - } -} - -class KillAndDismember -extends GameElementFactory { - KillAndDismember() { - player = KungFuGuy::new; - obstacle = NastyWeapon::new; - } -} - -public class GameEnvironment { - private Player p; - private Obstacle ob; - public - GameEnvironment(GameElementFactory factory) { - p = factory.player.get(); - ob = factory.obstacle.get(); - } - public void play() { - p.interactWith(ob); - } - public static void main(String[] args) { - GameElementFactory - kp = new KittiesAndPuzzles(), - kd = new KillAndDismember(); - GameEnvironment - g1 = new GameEnvironment(kp), - g2 = new GameEnvironment(kd); - g1.play(); - g2.play(); - } -} -/* Output: -Kitty has encountered a Puzzle -KungFuGuy now battles a NastyWeapon -*/ diff --git a/code/patterns/adapt/Adapter.java b/code/patterns/adapt/Adapter.java deleted file mode 100644 index 5bfcd6bf..00000000 --- a/code/patterns/adapt/Adapter.java +++ /dev/null @@ -1,85 +0,0 @@ -// patterns/adapt/Adapter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Variations on the Adapter pattern -// {java patterns.adapt.Adapter} -package patterns.adapt; - -class WhatIHave { - public void g() {} - public void h() {} -} - -interface WhatIWant { - void f(); -} - -class ProxyAdapter implements WhatIWant { - WhatIHave whatIHave; - ProxyAdapter(WhatIHave wih) { - whatIHave = wih; - } - @Override - public void f() { - // Implement behavior using - // methods in WhatIHave: - whatIHave.g(); - whatIHave.h(); - } -} - -class WhatIUse { - public void op(WhatIWant wiw) { - wiw.f(); - } -} - -// Approach 2: build adapter use into op(): -class WhatIUse2 extends WhatIUse { - public void op(WhatIHave wih) { - new ProxyAdapter(wih).f(); - } -} - -// Approach 3: build adapter into WhatIHave: -class WhatIHave2 extends WhatIHave -implements WhatIWant { - @Override - public void f() { - g(); - h(); - } -} - -// Approach 4: use an inner class: -class WhatIHave3 extends WhatIHave { - private class InnerAdapter implements WhatIWant{ - @Override - public void f() { - g(); - h(); - } - } - public WhatIWant whatIWant() { - return new InnerAdapter(); - } -} - -public class Adapter { - public static void main(String[] args) { - WhatIUse whatIUse = new WhatIUse(); - WhatIHave whatIHave = new WhatIHave(); - WhatIWant adapt= new ProxyAdapter(whatIHave); - whatIUse.op(adapt); - // Approach 2: - WhatIUse2 whatIUse2 = new WhatIUse2(); - whatIUse2.op(whatIHave); - // Approach 3: - WhatIHave2 whatIHave2 = new WhatIHave2(); - whatIUse.op(whatIHave2); - // Approach 4: - WhatIHave3 whatIHave3 = new WhatIHave3(); - whatIUse.op(whatIHave3.whatIWant()); - } -} diff --git a/code/patterns/chain/ChainOfResponsibility.java b/code/patterns/chain/ChainOfResponsibility.java deleted file mode 100644 index b733e71c..00000000 --- a/code/patterns/chain/ChainOfResponsibility.java +++ /dev/null @@ -1,90 +0,0 @@ -// patterns/chain/ChainOfResponsibility.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using the Functional interface -// {java patterns.chain.ChainOfResponsibility} -package patterns.chain; -import java.util.*; -import java.util.function.*; - -class Result { - boolean success; - List line; - Result(List data) { - success = true; - line = data; - } - Result() { - success = false; - line = Collections.emptyList(); - } -} - -class Fail extends Result {} - -interface Algorithm { - Result algorithm(List line); -} - -class FindMinima { - public static Result leastSquares(List line) { - System.out.println("LeastSquares.algorithm"); - boolean weSucceed = false; - if(weSucceed) // Actual test/calculation here - return new Result(Arrays.asList(1.1, 2.2)); - else // Try the next one in the chain: - return new Fail(); - } - public static Result perturbation(List line) { - System.out.println("Perturbation.algorithm"); - boolean weSucceed = false; - if(weSucceed) // Actual test/calculation here - return new Result(Arrays.asList(3.3, 4.4)); - else - return new Fail(); - } - public static Result bisection(List line) { - System.out.println("Bisection.algorithm"); - boolean weSucceed = true; - if(weSucceed) // Actual test/calculation here - return new Result(Arrays.asList(5.5, 6.6)); - else - return new Fail(); - } - static List, Result>> - algorithms = Arrays.asList( - FindMinima::leastSquares, - FindMinima::perturbation, - FindMinima::bisection - ); - public static Result minima(List line) { - for(Function, Result> alg : - algorithms) { - Result result = alg.apply(line); - if(result.success) - return result; - } - return new Fail(); - } -} - -public class ChainOfResponsibility { - public static void main(String[] args) { - FindMinima solver = new FindMinima(); - List line = Arrays.asList( - 1.0, 2.0, 1.0, 2.0, -1.0, - 3.0, 4.0, 5.0, 4.0); - Result result = solver.minima(line); - if(result.success) - System.out.println(result.line); - else - System.out.println("No algorithm found"); - } -} -/* Output: -LeastSquares.algorithm -Perturbation.algorithm -Bisection.algorithm -[5.5, 6.6] -*/ diff --git a/code/patterns/doubledispatch/Aluminum.java b/code/patterns/doubledispatch/Aluminum.java deleted file mode 100644 index 5037fac5..00000000 --- a/code/patterns/doubledispatch/Aluminum.java +++ /dev/null @@ -1,18 +0,0 @@ -// patterns/doubledispatch/Aluminum.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Aluminum for double dispatching -package patterns.doubledispatch; -import patterns.trash.*; -import java.util.*; - -public class Aluminum extends patterns.trash.Aluminum - implements TypedBinMember { - public Aluminum(double wt) { super(wt); } - @Override - public boolean addToBin(List tbins) { - return tbins.stream() - .anyMatch(tb -> tb.add(this)); - } -} diff --git a/code/patterns/doubledispatch/Cardboard.java b/code/patterns/doubledispatch/Cardboard.java deleted file mode 100644 index 5046ddaa..00000000 --- a/code/patterns/doubledispatch/Cardboard.java +++ /dev/null @@ -1,18 +0,0 @@ -// patterns/doubledispatch/Cardboard.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Cardboard for double dispatching -package patterns.doubledispatch; -import patterns.trash.*; -import java.util.*; - -public class Cardboard extends patterns.trash.Cardboard - implements TypedBinMember { - public Cardboard(double wt) { super(wt); } - @Override - public boolean addToBin(List tbins) { - return tbins.stream() - .anyMatch(tb -> tb.add(this)); - } -} diff --git a/code/patterns/doubledispatch/DoubleDispatch.java b/code/patterns/doubledispatch/DoubleDispatch.java deleted file mode 100644 index 91bee562..00000000 --- a/code/patterns/doubledispatch/DoubleDispatch.java +++ /dev/null @@ -1,96 +0,0 @@ -// patterns/doubledispatch/DoubleDispatch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using multiple dispatching to handle more -// than one unknown type during a method call -// {java patterns.doubledispatch.DoubleDispatch} -package patterns.doubledispatch; -import patterns.trash.*; -import java.util.*; - -class AluminumBin extends TypedBin { - @Override - public boolean add(Aluminum a) { - return addIt(a); - } -} - -class PaperBin extends TypedBin { - @Override - public boolean add(Paper a) { - return addIt(a); - } -} - -class GlassBin extends TypedBin { - @Override - public boolean add(Glass a) { - return addIt(a); - } -} - -class CardboardBin extends TypedBin { - @Override - public boolean add(Cardboard a) { - return addIt(a); - } -} - -class TrashBinSet { - private List binSet = Arrays.asList( - new AluminumBin(), - new PaperBin(), - new GlassBin(), - new CardboardBin() - ); - @SuppressWarnings("unchecked") - public void sortIntoBins(List bin) { - bin.forEach( aBin -> { - TypedBinMember t = (TypedBinMember)aBin; - if(!t.addToBin(binSet)) - System.err.println("Couldn't add " + t); - }); - } - public List binSet() { return binSet; } -} - -public class DoubleDispatch { - public static void main(String[] args) { - List bin = new ArrayList<>(); - TrashBinSet bins = new TrashBinSet(); - // ParseTrash still works, without changes: - ParseTrash.fillBin("doubledispatch", bin); - // Sort from the master bin into the - // individually-typed bins: - bins.sortIntoBins(bin); - // Perform sumValue for each bin... - bins.binSet() - .forEach(tb -> Trash.sumValue(tb.v)); - // ... and for the master bin - Trash.sumValue(bin); - } -} -/* Output: (First and Last 10 Lines) -Loading patterns.doubledispatch.Glass -Loading patterns.doubledispatch.Paper -Loading patterns.doubledispatch.Aluminum -Loading patterns.doubledispatch.Cardboard -weight of patterns.doubledispatch.Aluminum = 89.0 -weight of patterns.doubledispatch.Aluminum = 76.0 -weight of patterns.doubledispatch.Aluminum = 25.0 -weight of patterns.doubledispatch.Aluminum = 34.0 -weight of patterns.doubledispatch.Aluminum = 27.0 -weight of patterns.doubledispatch.Aluminum = 18.0 -...________...________...________...________... -weight of patterns.doubledispatch.Aluminum = 93.0 -weight of patterns.doubledispatch.Glass = 93.0 -weight of patterns.doubledispatch.Paper = 80.0 -weight of patterns.doubledispatch.Glass = 36.0 -weight of patterns.doubledispatch.Glass = 12.0 -weight of patterns.doubledispatch.Glass = 60.0 -weight of patterns.doubledispatch.Paper = 66.0 -weight of patterns.doubledispatch.Aluminum = 36.0 -weight of patterns.doubledispatch.Cardboard = 22.0 -Total value = 1086.0599818825722 -*/ diff --git a/code/patterns/doubledispatch/Glass.java b/code/patterns/doubledispatch/Glass.java deleted file mode 100644 index 79cf7fa2..00000000 --- a/code/patterns/doubledispatch/Glass.java +++ /dev/null @@ -1,18 +0,0 @@ -// patterns/doubledispatch/Glass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Glass for double dispatching -package patterns.doubledispatch; -import patterns.trash.*; -import java.util.*; - -public class Glass extends patterns.trash.Glass - implements TypedBinMember { - public Glass(double wt) { super(wt); } - @Override - public boolean addToBin(List tbins) { - return tbins.stream() - .anyMatch(tb -> tb.add(this)); - } -} diff --git a/code/patterns/doubledispatch/Paper.java b/code/patterns/doubledispatch/Paper.java deleted file mode 100644 index b542dfd6..00000000 --- a/code/patterns/doubledispatch/Paper.java +++ /dev/null @@ -1,18 +0,0 @@ -// patterns/doubledispatch/Paper.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Paper for double dispatching -package patterns.doubledispatch; -import patterns.trash.*; -import java.util.*; - -public class Paper extends patterns.trash.Paper - implements TypedBinMember { - public Paper(double wt) { super(wt); } - @Override - public boolean addToBin(List tbins) { - return tbins.stream() - .anyMatch(tb -> tb.add(this)); - } -} diff --git a/code/patterns/doubledispatch/TypedBin.java b/code/patterns/doubledispatch/TypedBin.java deleted file mode 100644 index 265874cc..00000000 --- a/code/patterns/doubledispatch/TypedBin.java +++ /dev/null @@ -1,28 +0,0 @@ -// patterns/doubledispatch/TypedBin.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A List that can grab the right type -package patterns.doubledispatch; -import patterns.trash.*; -import java.util.*; - -public class TypedBin { - List v = new ArrayList<>(); - protected boolean addIt(Trash t) { - v.add(t); - return true; - } - public boolean add(Aluminum a) { - return false; - } - public boolean add(Paper a) { - return false; - } - public boolean add(Glass a) { - return false; - } - public boolean add(Cardboard a) { - return false; - } -} diff --git a/code/patterns/doubledispatch/TypedBinMember.java b/code/patterns/doubledispatch/TypedBinMember.java deleted file mode 100644 index c7ce960a..00000000 --- a/code/patterns/doubledispatch/TypedBinMember.java +++ /dev/null @@ -1,14 +0,0 @@ -// patterns/doubledispatch/TypedBinMember.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An interface for adding the double dispatching -// method to the trash hierarchy without -// modifying the original hierarchy -package patterns.doubledispatch; -import java.util.*; - -public interface TypedBinMember { - // The new method: - boolean addToBin(List bins); -} diff --git a/code/patterns/dynatrash/DynaTrash.java b/code/patterns/dynatrash/DynaTrash.java deleted file mode 100644 index 6ce33d8f..00000000 --- a/code/patterns/dynatrash/DynaTrash.java +++ /dev/null @@ -1,74 +0,0 @@ -// patterns/dynatrash/DynaTrash.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using a Map of Lists and RTTI to automatically -// sort trash into Lists. This solution, despite -// the use of RTTI, is extensible. -// {java patterns.dynatrash.DynaTrash} -package patterns.dynatrash; -import patterns.trash.*; -import java.util.*; -import java.util.stream.*; - -// Generic TypeMap works in any situation: -class TypeMap { - private Map> t = new HashMap<>(); - public void add(T o) { - Class type = o.getClass(); - if(t.containsKey(type)) - t.get(type).add(o); - else { - List v = new ArrayList<>(); - v.add(o); - t.put(type,v); - } - } - public Stream> values() { - return t.values().stream(); - } -} - -// Adapter class for callbacks -// from ParseTrash.fillBin(): -class TypeMapAdapter implements Fillable { - TypeMap map; - TypeMapAdapter(TypeMap tm) { - map = tm; - } - @Override - public void addTrash(Trash t) { map.add(t); } -} - -public class DynaTrash { - @SuppressWarnings("unchecked") - public static void main(String[] args) { - TypeMap bin = new TypeMap<>(); - ParseTrash.fillBin( - "trash", new TypeMapAdapter(bin)); - bin.values().forEach(Trash::sumValue); - } -} -/* Output: (First and Last 10 Lines) -Loading patterns.trash.Glass -Loading patterns.trash.Paper -Loading patterns.trash.Aluminum -Loading patterns.trash.Cardboard -weight of patterns.trash.Paper = 22.0 -weight of patterns.trash.Paper = 11.0 -weight of patterns.trash.Paper = 88.0 -weight of patterns.trash.Paper = 91.0 -weight of patterns.trash.Paper = 80.0 -weight of patterns.trash.Paper = 66.0 -...________...________...________...________... -weight of patterns.trash.Aluminum = 81.0 -weight of patterns.trash.Aluminum = 36.0 -weight of patterns.trash.Aluminum = 93.0 -weight of patterns.trash.Aluminum = 36.0 -Total value = 860.0499778985977 -weight of patterns.trash.Cardboard = 96.0 -weight of patterns.trash.Cardboard = 44.0 -weight of patterns.trash.Cardboard = 12.0 -weight of patterns.trash.Cardboard = 22.0 -Total value = 40.02000072598457 -*/ diff --git a/code/patterns/observer/ObservedFlower.java b/code/patterns/observer/ObservedFlower.java deleted file mode 100644 index 009da63e..00000000 --- a/code/patterns/observer/ObservedFlower.java +++ /dev/null @@ -1,125 +0,0 @@ -// patterns/observer/ObservedFlower.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of "Observer" pattern -// {java patterns.observer.ObservedFlower} -package patterns.observer; -import java.util.*; - -@SuppressWarnings("deprecation") -class Flower { - private boolean isOpen; - private boolean alreadyOpen; - private boolean alreadyClosed; - Flower() { isOpen = false; } - OpenNotifier opening = new OpenNotifier(); - CloseNotifier closing = new CloseNotifier(); - public void open() { // Opens its petals - isOpen = true; - opening.notifyObservers(); - alreadyClosed = false; - } - public void close() { // Closes its petals - isOpen = false; - closing.notifyObservers(); - alreadyOpen = false; - } - class OpenNotifier extends Observable { - @Override - public void notifyObservers() { - if(isOpen && !alreadyOpen) { - setChanged(); - super.notifyObservers(); - alreadyOpen = true; - } - } - } - class CloseNotifier extends Observable{ - @Override - public void notifyObservers() { - if(!isOpen && !alreadyClosed) { - setChanged(); - super.notifyObservers(); - alreadyClosed = true; - } - } - } -} - -@SuppressWarnings("deprecation") -class Bee { - private String name; - Bee(String nm) { name = nm; } - // Observe openings: - public Observer openObserver() { - return (ob, a) -> System.out.println( - "Bee " + name + "'s breakfast time!"); - } - // Observe closings: - public Observer closeObserver() { - return (ob, a) -> System.out.println( - "Bee " + name + "'s bed time!"); - } -} - -@SuppressWarnings("deprecation") -class Hummingbird { - private String name; - Hummingbird(String nm) { name = nm; } - public Observer openObserver() { - return (ob, a) -> System.out.println( - "Hummingbird " + name + - "'s breakfast time!"); - } - public Observer closeObserver() { - return (ob, a) -> System.out.println( - "Hummingbird " + name + "'s bed time!"); - } -} - -public class ObservedFlower { - public static void main(String[] args) { - Flower f = new Flower(); - Bee - ba = new Bee("A"), - bb = new Bee("B"); - Hummingbird - ha = new Hummingbird("A"), - hb = new Hummingbird("B"); - f.opening.addObserver(ha.openObserver()); - f.opening.addObserver(hb.openObserver()); - f.opening.addObserver(ba.openObserver()); - f.opening.addObserver(bb.openObserver()); - f.closing.addObserver(ha.closeObserver()); - f.closing.addObserver(hb.closeObserver()); - f.closing.addObserver(ba.closeObserver()); - f.closing.addObserver(bb.closeObserver()); - // Hummingbird B decides to sleep in: - f.opening.deleteObserver(hb.openObserver()); - // A change that interests observers: - f.open(); - f.open(); // It's already open, no change. - // Bee A doesn't want to go to bed: - f.closing.deleteObserver(ba.closeObserver()); - f.close(); - f.close(); // It's already closed; no change - f.opening.deleteObservers(); - f.open(); - f.close(); - } -} -/* Output: -Bee B's breakfast time! -Bee A's breakfast time! -Hummingbird B's breakfast time! -Hummingbird A's breakfast time! -Bee B's bed time! -Bee A's bed time! -Hummingbird B's bed time! -Hummingbird A's bed time! -Bee B's bed time! -Bee A's bed time! -Hummingbird B's bed time! -Hummingbird A's bed time! -*/ diff --git a/code/patterns/recyclea/RecycleA.java b/code/patterns/recyclea/RecycleA.java deleted file mode 100644 index a73f39e7..00000000 --- a/code/patterns/recyclea/RecycleA.java +++ /dev/null @@ -1,127 +0,0 @@ -// patterns/recyclea/RecycleA.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Recycling with RTTI -// {java patterns.recyclea.RecycleA} -package patterns.recyclea; -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -abstract class Trash { - double weight; - Trash(double wt) { weight = wt; } - abstract double value(); - // Sums the value of Trash in a bin: - private static double val; - static void sumValue(List bin) { - val = 0.0f; - bin.forEach( t -> { - // Polymorphism in action: - val += t.weight * t.value(); - System.out.println( - "weight of " + - // Using RTTI to get type - // information about the class: - t.getClass().getSimpleName() + - " = " + t.weight); - }); - System.out.println("Total value = " + val); - } -} - -class Aluminum extends Trash { - static double val = 1.67f; - Aluminum(double wt) { super(wt); } - @Override - double value() { return val; } - static void value(double newval) { - val = newval; - } -} - -class Paper extends Trash { - static double val = 0.10f; - Paper(double wt) { super(wt); } - @Override - double value() { return val; } - static void value(double newval) { - val = newval; - } -} - -class Glass extends Trash { - static double val = 0.23f; - Glass(double wt) { super(wt); } - @Override - double value() { return val; } - static void value(double newval) { - val = newval; - } -} - -class TrashFactory { - static List> ttypes = - Arrays.asList( - Aluminum::new, Paper::new, Glass::new); - static final int SZ = ttypes.size(); - private static SplittableRandom rand = - new SplittableRandom(47); - public static Trash newTrash() { - return ttypes - .get(rand.nextInt(SZ)) - .apply(rand.nextDouble()); - } -} - -public class RecycleA { - public static void main(String[] args) { - List bin = - Stream.generate(TrashFactory::newTrash) - .limit(25) - .collect(Collectors.toList()); - List glassBin = new ArrayList<>(); - List paperBin = new ArrayList<>(); - List alBin = new ArrayList<>(); - // Sort the Trash: - bin.forEach( t -> { - // RTTI to discover Trash type: - if(t instanceof Aluminum) - alBin.add((Aluminum)t); - if(t instanceof Paper) - paperBin.add((Paper)t); - if(t instanceof Glass) - glassBin.add((Glass)t); - }); - Trash.sumValue(alBin); - Trash.sumValue(paperBin); - Trash.sumValue(glassBin); - Trash.sumValue(bin); - } -} -/* Output: (First and Last 11 Lines) -weight of Aluminum = 0.2893030122276371 -weight of Aluminum = 0.1970234961398979 -weight of Aluminum = 0.36295525806274787 -weight of Aluminum = 0.4825532324565849 -weight of Aluminum = 0.8036398273294586 -weight of Aluminum = 0.510430896154935 -weight of Aluminum = 0.6703377164093444 -weight of Aluminum = 0.41477933066243455 -weight of Aluminum = 0.3603022312124007 -weight of Aluminum = 0.43690089841661006 -weight of Aluminum = 0.6708820087907101 -...________...________...________...________... -weight of Aluminum = 0.41477933066243455 -weight of Aluminum = 0.3603022312124007 -weight of Aluminum = 0.43690089841661006 -weight of Glass = 0.5999637765664924 -weight of Glass = 0.7748836191212746 -weight of Paper = 0.5735994548427199 -weight of Glass = 0.5362827750851034 -weight of Aluminum = 0.6708820087907101 -weight of Paper = 0.8370669795210507 -weight of Glass = 0.3397919679731668 -Total value = 9.90671597531968 -*/ diff --git a/code/patterns/recycleb/RecycleB.java b/code/patterns/recycleb/RecycleB.java deleted file mode 100644 index 1ca38314..00000000 --- a/code/patterns/recycleb/RecycleB.java +++ /dev/null @@ -1,56 +0,0 @@ -// patterns/recycleb/RecycleB.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java patterns.recycleb.RecycleB} -package patterns.recycleb; -import patterns.trash.*; -import java.util.*; - -public class RecycleB { - public static void main(String[] args) { - List bin = new ArrayList<>(); - // Fill up the Trash bin: - ParseTrash.fillBin("trash", bin); - List glassBin = new ArrayList<>(); - List paperBin = new ArrayList<>(); - List alBin = new ArrayList<>(); - // Sort the Trash: - bin.forEach( t -> { - // RTTI to discover Trash type: - if(t instanceof Aluminum) - alBin.add((Aluminum)t); - if(t instanceof Paper) - paperBin.add((Paper)t); - if(t instanceof Glass) - glassBin.add((Glass)t); - }); - Trash.sumValue(alBin); - Trash.sumValue(paperBin); - Trash.sumValue(glassBin); - Trash.sumValue(bin); - } -} -/* Output: (First and Last 10 Lines) -Loading patterns.trash.Glass -Loading patterns.trash.Paper -Loading patterns.trash.Aluminum -Loading patterns.trash.Cardboard -weight of patterns.trash.Aluminum = 89.0 -weight of patterns.trash.Aluminum = 76.0 -weight of patterns.trash.Aluminum = 25.0 -weight of patterns.trash.Aluminum = 34.0 -weight of patterns.trash.Aluminum = 27.0 -weight of patterns.trash.Aluminum = 18.0 -...________...________...________...________... -weight of patterns.trash.Aluminum = 93.0 -weight of patterns.trash.Glass = 93.0 -weight of patterns.trash.Paper = 80.0 -weight of patterns.trash.Glass = 36.0 -weight of patterns.trash.Glass = 12.0 -weight of patterns.trash.Glass = 60.0 -weight of patterns.trash.Paper = 66.0 -weight of patterns.trash.Aluminum = 36.0 -weight of patterns.trash.Cardboard = 22.0 -Total value = 1086.0599818825722 -*/ diff --git a/code/patterns/recyclec/RecycleC.java b/code/patterns/recyclec/RecycleC.java deleted file mode 100644 index 239e8e79..00000000 --- a/code/patterns/recyclec/RecycleC.java +++ /dev/null @@ -1,84 +0,0 @@ -// patterns/recyclec/RecycleC.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Adding more objects to the recycling problem -// {java patterns.recyclec.RecycleC} -package patterns.recyclec; -import patterns.trash.*; -import java.util.*; - -// A List that admits only the right type: -class Tbin extends ArrayList { - Class binType; - Tbin(Class type) { - binType = type; - } - @SuppressWarnings("unchecked") - boolean grab(Trash t) { - // Comparing class types: - if(t.getClass().equals(binType)) { - add((T)t); // Downcast to this TBin's type - return true; // Object grabbed - } - return false; // Object not grabbed - } -} - -class TbinList -extends ArrayList> { // [1] - boolean sort(T t) { - for(Tbin ts : this) - if(ts.grab(t)) - return true; - return false; // bin not found for t - } - void sortBin(Tbin bin) { // [2] - for(T aBin : bin) - if(!sort(aBin)) - System.err.println("Bin not found"); - } -} - -public class RecycleC { - static Tbin bin = new Tbin<>(Trash.class); - public static void main(String[] args) { - // Fill up the Trash bin: - ParseTrash.fillBin("trash", bin); - - TbinList trashBins = new TbinList<>(); - trashBins.add(new Tbin<>(Aluminum.class)); - trashBins.add(new Tbin<>(Paper.class)); - trashBins.add(new Tbin<>(Glass.class)); - // add one line here: [*3*] - trashBins.add(new Tbin<>(Cardboard.class)); - - trashBins.sortBin(bin); // [4] - - trashBins.forEach(Trash::sumValue); - Trash.sumValue(bin); - } -} -/* Output: (First and Last 10 Lines) -Loading patterns.trash.Glass -Loading patterns.trash.Paper -Loading patterns.trash.Aluminum -Loading patterns.trash.Cardboard -weight of patterns.trash.Aluminum = 89.0 -weight of patterns.trash.Aluminum = 76.0 -weight of patterns.trash.Aluminum = 25.0 -weight of patterns.trash.Aluminum = 34.0 -weight of patterns.trash.Aluminum = 27.0 -weight of patterns.trash.Aluminum = 18.0 -...________...________...________...________... -weight of patterns.trash.Aluminum = 93.0 -weight of patterns.trash.Glass = 93.0 -weight of patterns.trash.Paper = 80.0 -weight of patterns.trash.Glass = 36.0 -weight of patterns.trash.Glass = 12.0 -weight of patterns.trash.Glass = 60.0 -weight of patterns.trash.Paper = 66.0 -weight of patterns.trash.Aluminum = 36.0 -weight of patterns.trash.Cardboard = 22.0 -Total value = 1086.0599818825722 -*/ diff --git a/code/patterns/shapes/BadShapeCreation.java b/code/patterns/shapes/BadShapeCreation.java deleted file mode 100644 index 2ebda8e5..00000000 --- a/code/patterns/shapes/BadShapeCreation.java +++ /dev/null @@ -1,12 +0,0 @@ -// patterns/shapes/BadShapeCreation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.shapes; - -public class BadShapeCreation -extends RuntimeException { - public BadShapeCreation(String msg) { - super(msg); - } -} diff --git a/code/patterns/shapes/Circle.java b/code/patterns/shapes/Circle.java deleted file mode 100644 index 461d55e2..00000000 --- a/code/patterns/shapes/Circle.java +++ /dev/null @@ -1,7 +0,0 @@ -// patterns/shapes/Circle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.shapes; - -public class Circle extends Shape {} diff --git a/code/patterns/shapes/FactoryMethod.java b/code/patterns/shapes/FactoryMethod.java deleted file mode 100644 index c3b22b1f..00000000 --- a/code/patterns/shapes/FactoryMethod.java +++ /dev/null @@ -1,9 +0,0 @@ -// patterns/shapes/FactoryMethod.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.shapes; - -public interface FactoryMethod { - Shape create(String type); -} diff --git a/code/patterns/shapes/FactoryTest.java b/code/patterns/shapes/FactoryTest.java deleted file mode 100644 index 301bb1ab..00000000 --- a/code/patterns/shapes/FactoryTest.java +++ /dev/null @@ -1,17 +0,0 @@ -// patterns/shapes/FactoryTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.shapes; -import java.util.stream.*; - -public class FactoryTest { - public static void test(FactoryMethod factory) { - Stream.of("Circle", "Square", "Triangle", - "Square", "Circle", "Circle", "Triangle") - .map(factory::create) - .peek(Shape::draw) - .peek(Shape::erase) - .count(); // Terminal operation - } -} diff --git a/code/patterns/shapes/Shape.java b/code/patterns/shapes/Shape.java deleted file mode 100644 index 12fdf3e7..00000000 --- a/code/patterns/shapes/Shape.java +++ /dev/null @@ -1,21 +0,0 @@ -// patterns/shapes/Shape.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.shapes; - -public class Shape { - private static int counter = 0; - private int id = counter++; - @Override - public String toString() { - return - getClass().getSimpleName() + "[" + id + "]"; - } - public void draw() { - System.out.println(this + " draw"); - } - public void erase() { - System.out.println(this + " erase"); - } -} diff --git a/code/patterns/shapes/Square.java b/code/patterns/shapes/Square.java deleted file mode 100644 index 610dd3e4..00000000 --- a/code/patterns/shapes/Square.java +++ /dev/null @@ -1,7 +0,0 @@ -// patterns/shapes/Square.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.shapes; - -public class Square extends Shape {} diff --git a/code/patterns/shapes/Triangle.java b/code/patterns/shapes/Triangle.java deleted file mode 100644 index 9fed3d93..00000000 --- a/code/patterns/shapes/Triangle.java +++ /dev/null @@ -1,7 +0,0 @@ -// patterns/shapes/Triangle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.shapes; - -public class Triangle extends Shape {} diff --git a/code/patterns/state/StateMachineDemo.java b/code/patterns/state/StateMachineDemo.java deleted file mode 100644 index 29f8a876..00000000 --- a/code/patterns/state/StateMachineDemo.java +++ /dev/null @@ -1,80 +0,0 @@ -// patterns/state/StateMachineDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The StateMachine pattern and Template method -// {java patterns.state.StateMachineDemo} -package patterns.state; -import onjava.Nap; - -interface State { - void run(); -} - -abstract class StateMachine { - protected State currentState; - protected abstract boolean changeState(); - // Template method: - protected final void runAll() { - while(changeState()) // Customizable - currentState.run(); - } -} - -// A different subclass for each state: - -class Wash implements State { - @Override - public void run() { - System.out.println("Washing"); - new Nap(0.5); - } -} - -class Spin implements State { - @Override - public void run() { - System.out.println("Spinning"); - new Nap(0.5); - } -} - -class Rinse implements State { - @Override - public void run() { - System.out.println("Rinsing"); - new Nap(0.5); - } -} - -class Washer extends StateMachine { - private int i = 0; - // The state table: - private State[] states = { - new Wash(), new Spin(), - new Rinse(), new Spin(), - }; - Washer() { runAll(); } - @Override - public boolean changeState() { - if(i < states.length) { - // Change the state by setting the - // surrogate reference to a new object: - currentState = states[i++]; - return true; - } else - return false; - } -} - -public class StateMachineDemo { - public static void main(String[] args) { - new Washer(); - } -} -/* Output: -Washing -Spinning -Rinsing -Spinning -*/ diff --git a/code/patterns/strategy/StrategyPattern.java b/code/patterns/strategy/StrategyPattern.java deleted file mode 100644 index 52561b4b..00000000 --- a/code/patterns/strategy/StrategyPattern.java +++ /dev/null @@ -1,64 +0,0 @@ -// patterns/strategy/StrategyPattern.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java patterns.strategy.StrategyPattern} -package patterns.strategy; -import java.util.function.*; -import java.util.*; - -// The common strategy base type: -class FindMinima { - Function, List> algorithm; -} - -// The various strategies: -class LeastSquares extends FindMinima { - LeastSquares() { - // Line is a sequence of points (Dummy data): - algorithm = (line) -> Arrays.asList(1.1, 2.2); - } -} - -class Perturbation extends FindMinima { - Perturbation() { - algorithm = (line) -> Arrays.asList(3.3, 4.4); - } -} - -class Bisection extends FindMinima { - Bisection() { - algorithm = (line) -> Arrays.asList(5.5, 6.6); - } -} - -// The "Context" controls the strategy: -class MinimaSolver { - private FindMinima strategy; - MinimaSolver(FindMinima strat) { - strategy = strat; - } - List minima(List line) { - return strategy.algorithm.apply(line); - } - void changeAlgorithm(FindMinima newAlgorithm) { - strategy = newAlgorithm; - } -} - -public class StrategyPattern { - public static void main(String[] args) { - MinimaSolver solver = - new MinimaSolver(new LeastSquares()); - List line = Arrays.asList( - 1.0, 2.0, 1.0, 2.0, -1.0, - 3.0, 4.0, 5.0, 4.0 ); - System.out.println(solver.minima(line)); - solver.changeAlgorithm(new Bisection()); - System.out.println(solver.minima(line)); - } -} -/* Output: -[1.1, 2.2] -[5.5, 6.6] -*/ diff --git a/code/patterns/strategy/StrategyPattern2.java b/code/patterns/strategy/StrategyPattern2.java deleted file mode 100644 index 09465f3a..00000000 --- a/code/patterns/strategy/StrategyPattern2.java +++ /dev/null @@ -1,43 +0,0 @@ -// patterns/strategy/StrategyPattern2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java patterns.strategy.StrategyPattern2} -package patterns.strategy; -import java.util.function.*; -import java.util.*; - -// "Context" is now incorporated: -class FindMinima2 { - Function, List> algorithm; - FindMinima2() { leastSquares(); } // default - // The various strategies: - void leastSquares() { - algorithm = (line) -> Arrays.asList(1.1, 2.2); - } - void perturbation() { - algorithm = (line) -> Arrays.asList(3.3, 4.4); - } - void bisection() { - algorithm = (line) -> Arrays.asList(5.5, 6.6); - } - List minima(List line) { - return algorithm.apply(line); - } -} - -public class StrategyPattern2 { - public static void main(String[] args) { - FindMinima2 solver = new FindMinima2(); - List line = Arrays.asList( - 1.0, 2.0, 1.0, 2.0, -1.0, - 3.0, 4.0, 5.0, 4.0 ); - System.out.println(solver.minima(line)); - solver.bisection(); - System.out.println(solver.minima(line)); - } -} -/* Output: -[1.1, 2.2] -[5.5, 6.6] -*/ diff --git a/code/patterns/trash/Aluminum.java b/code/patterns/trash/Aluminum.java deleted file mode 100644 index 0065e964..00000000 --- a/code/patterns/trash/Aluminum.java +++ /dev/null @@ -1,15 +0,0 @@ -// patterns/trash/Aluminum.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.trash; - -public class Aluminum extends Trash { - private static double val = 1.67f; - public Aluminum(double wt) { super(wt); } - @Override - public double value() { return val; } - public static void value(double newVal) { - val = newVal; - } -} diff --git a/code/patterns/trash/Cardboard.java b/code/patterns/trash/Cardboard.java deleted file mode 100644 index 0b54d135..00000000 --- a/code/patterns/trash/Cardboard.java +++ /dev/null @@ -1,15 +0,0 @@ -// patterns/trash/Cardboard.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.trash; - -public class Cardboard extends Trash { - private static double val = 0.23f; - public Cardboard(double wt) { super(wt); } - @Override - public double value() { return val; } - public static void value(double newVal) { - val = newVal; - } -} diff --git a/code/patterns/trash/Fillable.java b/code/patterns/trash/Fillable.java deleted file mode 100644 index a61cb111..00000000 --- a/code/patterns/trash/Fillable.java +++ /dev/null @@ -1,10 +0,0 @@ -// patterns/trash/Fillable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Any object that can be filled with Trash -package patterns.trash; - -public interface Fillable { - void addTrash(T t); -} diff --git a/code/patterns/trash/FillableList.java b/code/patterns/trash/FillableList.java deleted file mode 100644 index 989a33ec..00000000 --- a/code/patterns/trash/FillableList.java +++ /dev/null @@ -1,17 +0,0 @@ -// patterns/trash/FillableList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Adapter that makes a List Fillable -package patterns.trash; -import java.util.*; - -public class FillableList -implements Fillable { - private List v; - public FillableList(List vv) { - v = vv; - } - @Override - public void addTrash(T t) { v.add(t); } -} diff --git a/code/patterns/trash/Glass.java b/code/patterns/trash/Glass.java deleted file mode 100644 index f7563dc4..00000000 --- a/code/patterns/trash/Glass.java +++ /dev/null @@ -1,15 +0,0 @@ -// patterns/trash/Glass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.trash; - -public class Glass extends Trash { - private static double val = 0.23f; - public Glass(double wt) { super(wt); } - @Override - public double value() { return val; } - public static void value(double newVal) { - val = newVal; - } -} diff --git a/code/patterns/trash/Paper.java b/code/patterns/trash/Paper.java deleted file mode 100644 index 2f0b3666..00000000 --- a/code/patterns/trash/Paper.java +++ /dev/null @@ -1,15 +0,0 @@ -// patterns/trash/Paper.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package patterns.trash; - -public class Paper extends Trash { - private static double val = 0.10f; - public Paper(double wt) { super(wt); } - @Override - public double value() { return val; } - public static void value(double newVal) { - val = newVal; - } -} diff --git a/code/patterns/trash/ParseTrash.java b/code/patterns/trash/ParseTrash.java deleted file mode 100644 index fc0c0416..00000000 --- a/code/patterns/trash/ParseTrash.java +++ /dev/null @@ -1,91 +0,0 @@ -// patterns/trash/ParseTrash.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Open a file and parse its contents into -// Trash objects, placing each into a List -// {java patterns.trash.ParseTrash} -package patterns.trash; -import java.util.*; -import java.util.stream.*; -import java.io.*; -import java.nio.file.*; -import java.nio.file.Files; - -public class ParseTrash { - public static void - fillBin(String pckg, Fillable bin) { - try { - Files.lines(Paths.get("trash", "Trash.dat")) - // Remove empty lines and comment lines: - .filter(line -> line.trim().length() != 0) - .filter(line -> !line.startsWith("//")) - .forEach( line -> { - String type = "patterns." + pckg + "." + - line.substring( - 0, line.indexOf(':')).trim(); - double weight = Double.valueOf( - line.substring(line.indexOf(':') + 1) - .trim()); - bin.addTrash(Trash.factory( - new Trash.Info(type, weight))); - }); - } catch(IOException | - NumberFormatException | - Trash.TrashClassNotFoundException | - Trash.CannotCreateTrashException e) { - throw new RuntimeException(e); - } - } - // Special case to handle List: - public static void - fillBin(String pckg, List bin) { - fillBin(pckg, new FillableList<>(bin)); - } - // Basic test: - public static void main(String[] args) { - List t = new ArrayList<>(); - fillBin("trash", t); - t.forEach(System.out::println); - } -} -/* Output: -Loading patterns.trash.Glass -Loading patterns.trash.Paper -Loading patterns.trash.Aluminum -Loading patterns.trash.Cardboard -patterns.trash.Glass w:54.0 v:0.23 -patterns.trash.Paper w:22.0 v:0.10 -patterns.trash.Paper w:11.0 v:0.10 -patterns.trash.Glass w:17.0 v:0.23 -patterns.trash.Aluminum w:89.0 v:1.67 -patterns.trash.Paper w:88.0 v:0.10 -patterns.trash.Aluminum w:76.0 v:1.67 -patterns.trash.Cardboard w:96.0 v:0.23 -patterns.trash.Aluminum w:25.0 v:1.67 -patterns.trash.Aluminum w:34.0 v:1.67 -patterns.trash.Glass w:11.0 v:0.23 -patterns.trash.Glass w:68.0 v:0.23 -patterns.trash.Glass w:43.0 v:0.23 -patterns.trash.Aluminum w:27.0 v:1.67 -patterns.trash.Cardboard w:44.0 v:0.23 -patterns.trash.Aluminum w:18.0 v:1.67 -patterns.trash.Paper w:91.0 v:0.10 -patterns.trash.Glass w:63.0 v:0.23 -patterns.trash.Glass w:50.0 v:0.23 -patterns.trash.Glass w:80.0 v:0.23 -patterns.trash.Aluminum w:81.0 v:1.67 -patterns.trash.Cardboard w:12.0 v:0.23 -patterns.trash.Glass w:12.0 v:0.23 -patterns.trash.Glass w:54.0 v:0.23 -patterns.trash.Aluminum w:36.0 v:1.67 -patterns.trash.Aluminum w:93.0 v:1.67 -patterns.trash.Glass w:93.0 v:0.23 -patterns.trash.Paper w:80.0 v:0.10 -patterns.trash.Glass w:36.0 v:0.23 -patterns.trash.Glass w:12.0 v:0.23 -patterns.trash.Glass w:60.0 v:0.23 -patterns.trash.Paper w:66.0 v:0.10 -patterns.trash.Aluminum w:36.0 v:1.67 -patterns.trash.Cardboard w:22.0 v:0.23 -*/ diff --git a/code/patterns/trash/Trash.dat b/code/patterns/trash/Trash.dat deleted file mode 100644 index 436a7a71..00000000 --- a/code/patterns/trash/Trash.dat +++ /dev/null @@ -1,35 +0,0 @@ -// patterns/trash/Trash.dat -Glass:54 -Paper:22 -Paper:11 -Glass:17 -Aluminum:89 -Paper:88 -Aluminum:76 -Cardboard:96 -Aluminum:25 -Aluminum:34 -Glass:11 -Glass:68 -Glass:43 -Aluminum:27 -Cardboard:44 -Aluminum:18 -Paper:91 -Glass:63 -Glass:50 -Glass:80 -Aluminum:81 -Cardboard:12 -Glass:12 -Glass:54 -Aluminum:36 -Aluminum:93 -Glass:93 -Paper:80 -Glass:36 -Glass:12 -Glass:60 -Paper:66 -Aluminum:36 -Cardboard:22 diff --git a/code/patterns/trash/Trash.java b/code/patterns/trash/Trash.java deleted file mode 100644 index 7d01de8c..00000000 --- a/code/patterns/trash/Trash.java +++ /dev/null @@ -1,92 +0,0 @@ -// patterns/trash/Trash.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Base class for Trash recycling examples -package patterns.trash; -import java.util.*; -import java.lang.reflect.*; - -public abstract class Trash { - private double weight; - public Trash(double wt) { weight = wt; } - public Trash() {} - public abstract double value(); - public double weight() { return weight; } - // Sums the value of Trash in a bin: - static double val; - public static - void sumValue(List bin) { - val = 0.0f; - bin.forEach( t -> { - val += t.weight() * t.value(); - System.out.println("weight of " + - // RTTI gets type information - // about the class: - t.getClass().getName() + - " = " + t.weight()); - }); - System.out.println("Total value = " + val); - } - @Override - public String toString() { - // Print correct subclass name: - return getClass().getName() + - " w:" + weight() + " v:" + - String.format("%.2f", value()); - } - // Remainder of class supports dynamic creation: - public static class CannotCreateTrashException - extends RuntimeException { - public CannotCreateTrashException(Exception why) { - super(why); - } - } - public static class TrashClassNotFoundException - extends RuntimeException { - public TrashClassNotFoundException(Exception why) { - super(why); - } - } - public static class Info { - public String id; - public double data; - public Info(String name, double data) { - id = name; - this.data = data; - } - } - private static List trashTypes = - new ArrayList<>(); - @SuppressWarnings("unchecked") - public static T factory(Info info) { - for(Class trashType : trashTypes) { - // Determine the type and create one: - if(trashType.getName().contains(info.id)) { - try { - // Get the dynamic constructor method - // that takes a double argument: - Constructor ctor = - trashType.getConstructor(double.class); - // Call the constructor to create a - // new object: - return - (T)ctor.newInstance(info.data); - } catch(Exception e) { - throw new CannotCreateTrashException(e); - } - } - } - // The necessary Class was not in the list. Try to - // load it, but it must be in your class path! - try { - System.out.println("Loading " + info.id); - trashTypes.add(Class.forName(info.id)); - } catch(Exception e) { - throw new TrashClassNotFoundException(e); - } - // Loaded successfully. Recursive call - // should work this time: - return factory(info); - } -} diff --git a/code/patterns/trashvisitor/Aluminum.java b/code/patterns/trashvisitor/Aluminum.java deleted file mode 100644 index 85d5fa14..00000000 --- a/code/patterns/trashvisitor/Aluminum.java +++ /dev/null @@ -1,16 +0,0 @@ -// patterns/trashvisitor/Aluminum.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Aluminum for the visitor pattern -package patterns.trashvisitor; -import patterns.trash.*; - -public class Aluminum extends patterns.trash.Aluminum - implements Visitable { - public Aluminum(double wt) { super(wt); } - @Override - public void accept(Visitor v) { - v.visit(this); - } -} diff --git a/code/patterns/trashvisitor/Cardboard.java b/code/patterns/trashvisitor/Cardboard.java deleted file mode 100644 index 978202ef..00000000 --- a/code/patterns/trashvisitor/Cardboard.java +++ /dev/null @@ -1,16 +0,0 @@ -// patterns/trashvisitor/Cardboard.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Cardboard for the visitor pattern -package patterns.trashvisitor; -import patterns.trash.*; - -public class Cardboard extends patterns.trash.Cardboard - implements Visitable { - public Cardboard(double wt) { super(wt); } - @Override - public void accept(Visitor v) { - v.visit(this); - } -} diff --git a/code/patterns/trashvisitor/Glass.java b/code/patterns/trashvisitor/Glass.java deleted file mode 100644 index fbcf4949..00000000 --- a/code/patterns/trashvisitor/Glass.java +++ /dev/null @@ -1,16 +0,0 @@ -// patterns/trashvisitor/Glass.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Glass for the visitor pattern -package patterns.trashvisitor; -import patterns.trash.*; - -public class Glass extends patterns.trash.Glass - implements Visitable { - public Glass(double wt) { super(wt); } - @Override - public void accept(Visitor v) { - v.visit(this); - } -} diff --git a/code/patterns/trashvisitor/Paper.java b/code/patterns/trashvisitor/Paper.java deleted file mode 100644 index 6e9999f1..00000000 --- a/code/patterns/trashvisitor/Paper.java +++ /dev/null @@ -1,16 +0,0 @@ -// patterns/trashvisitor/Paper.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Paper for the visitor pattern -package patterns.trashvisitor; -import patterns.trash.*; - -public class Paper extends patterns.trash.Paper - implements Visitable { - public Paper(double wt) { super(wt); } - @Override - public void accept(Visitor v) { - v.visit(this); - } -} diff --git a/code/patterns/trashvisitor/TrashVisitor.java b/code/patterns/trashvisitor/TrashVisitor.java deleted file mode 100644 index 8f956623..00000000 --- a/code/patterns/trashvisitor/TrashVisitor.java +++ /dev/null @@ -1,127 +0,0 @@ -// patterns/trashvisitor/TrashVisitor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java patterns.trashvisitor.TrashVisitor} -package patterns.trashvisitor; -import patterns.trash.*; -import java.util.*; - -// Specific group of algorithms packaged -// in each implementation of Visitor: -class PriceVisitor implements Visitor { - private double alSum; // Aluminum - private double pSum; // Paper - private double gSum; // Glass - private double cSum; // Cardboard - public static void show(String s) { - System.out.println(s); - } - @Override - public void visit(Aluminum al) { - double v = al.weight() * al.value(); - show("value of Aluminum= " + v); - alSum += v; - } - @Override - public void visit(Paper p) { - double v = p.weight() * p.value(); - show("value of Paper= " + v); - pSum += v; - } - @Override - public void visit(Glass g) { - double v = g.weight() * g.value(); - show("value of Glass= " + v); - gSum += v; - } - @Override - public void visit(Cardboard c) { - double v = c.weight() * c.value(); - show("value of Cardboard = " + v); - cSum += v; - } - @Override - public void total() { - show( - "Total Aluminum: $" + alSum + "\n" + - "Total Paper: $" + pSum + "\n" + - "Total Glass: $" + gSum + "\n" + - "Total Cardboard: $" + cSum); - } -} - -class WeightVisitor implements Visitor { - private double alSum; // Aluminum - private double pSum; // Paper - private double gSum; // Glass - private double cSum; // Cardboard - public static void show(String s) { - System.out.println(s); - } - @Override - public void visit(Aluminum al) { - alSum += al.weight(); - show("Aluminum weight = " + al.weight()); - } - @Override - public void visit(Paper p) { - pSum += p.weight(); - show("Paper weight = " + p.weight()); - } - @Override - public void visit(Glass g) { - gSum += g.weight(); - show("Glass weight = " + g.weight()); - } - @Override - public void visit(Cardboard c) { - cSum += c.weight(); - show("Cardboard weight = " + c.weight()); - } - @Override - public void total() { - show("Total weight Aluminum:" + alSum); - show("Total weight Paper:" + pSum); - show("Total weight Glass:" + gSum); - show("Total weight Cardboard:" + cSum); - } -} - -public class TrashVisitor { - public static void main(String[] args) { - List bin = new ArrayList<>(); - // ParseTrash still works, without changes: - ParseTrash.fillBin("trashvisitor", bin); - List visitors = Arrays.asList( - new PriceVisitor(), new WeightVisitor()); - bin.forEach( t -> { - Visitable v = (Visitable) t; - visitors.forEach(visitor -> v.accept(visitor)); - }); - visitors.forEach(Visitor::total); - } -} -/* Output: (First and Last 10 Lines) -Loading patterns.trashvisitor.Glass -Loading patterns.trashvisitor.Paper -Loading patterns.trashvisitor.Aluminum -Loading patterns.trashvisitor.Cardboard -value of Glass= 12.420000225305557 -Glass weight = 54.0 -value of Paper= 2.2000000327825546 -Paper weight = 22.0 -value of Paper= 1.1000000163912773 -Paper weight = 11.0 -...________...________...________...________... -value of Cardboard = 5.060000091791153 -Cardboard weight = 22.0 -Total Aluminum: $860.0499778985977 -Total Paper: $35.80000053346157 -Total Glass: $150.1900027245283 -Total Cardboard: $40.02000072598457 -Total weight Aluminum:515.0 -Total weight Paper:358.0 -Total weight Glass:653.0 -Total weight Cardboard:174.0 -*/ diff --git a/code/patterns/trashvisitor/Visitable.java b/code/patterns/trashvisitor/Visitable.java deleted file mode 100644 index f1f9f1da..00000000 --- a/code/patterns/trashvisitor/Visitable.java +++ /dev/null @@ -1,12 +0,0 @@ -// patterns/trashvisitor/Visitable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An interface to add visitor functionality to the -// Trash hierarchy without modifying the base class -package patterns.trashvisitor; - -public interface Visitable { - // The new method: - void accept(Visitor v); -} diff --git a/code/patterns/trashvisitor/Visitor.java b/code/patterns/trashvisitor/Visitor.java deleted file mode 100644 index 07ef4622..00000000 --- a/code/patterns/trashvisitor/Visitor.java +++ /dev/null @@ -1,14 +0,0 @@ -// patterns/trashvisitor/Visitor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The base interface for visitors -package patterns.trashvisitor; - -public interface Visitor { - void visit(Aluminum a); - void visit(Paper p); - void visit(Glass g); - void visit(Cardboard c); - void total(); -} diff --git a/code/patterns/visitor/BeeAndFlowers.java b/code/patterns/visitor/BeeAndFlowers.java deleted file mode 100644 index aa86ebfc..00000000 --- a/code/patterns/visitor/BeeAndFlowers.java +++ /dev/null @@ -1,122 +0,0 @@ -// patterns/visitor/BeeAndFlowers.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of "visitor" pattern -// {java patterns.visitor.BeeAndFlowers} -package patterns.visitor; -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -interface Visitor { - void visit(Gladiolus g); - void visit(Renuculus r); - void visit(Chrysanthemum c); -} - -// The Flower hierarchy cannot be changed: -interface Flower { - void accept(Visitor v); -} - -class Gladiolus implements Flower { - @Override - public void accept(Visitor v) { v.visit(this);} -} - -class Renuculus implements Flower { - @Override - public void accept(Visitor v) { v.visit(this);} -} - -class Chrysanthemum implements Flower { - @Override - public void accept(Visitor v) { v.visit(this);} -} - -// Add the ability to produce a String: -class StringVal implements Visitor { - String s; - @Override - public String toString() { return s; } - @Override - public void visit(Gladiolus g) { - s = "Gladiolus"; - } - @Override - public void visit(Renuculus r) { - s = "Renuculus"; - } - @Override - public void visit(Chrysanthemum c) { - s = "Chrysanthemum"; - } -} - -// Add the ability to do "Bee" activities: -class Bee implements Visitor { - @Override - public void visit(Gladiolus g) { - System.out.println("Bee and Gladiolus"); - } - @Override - public void visit(Renuculus r) { - System.out.println("Bee and Renuculus"); - } - @Override - public void visit(Chrysanthemum c) { - System.out.println("Bee and Chrysanthemum"); - } -} - -class FlowerFactory { - static List> flowers = - Arrays.asList(Gladiolus::new, - Renuculus::new, Chrysanthemum::new); - static final int SZ = flowers.size(); - private static SplittableRandom rand = - new SplittableRandom(47); - public static Flower newFlower() { - return flowers.get(rand.nextInt(SZ)).get(); - } -} - -public class BeeAndFlowers { - public static void main(String[] args) { - List flowers = - Stream.generate(FlowerFactory::newFlower) - .limit(10) - .collect(Collectors.toList()); - StringVal sval = new StringVal(); - flowers.forEach(f -> { - f.accept(sval); - System.out.println(sval); - }); - // Perform "Bee" operation on all Flowers: - Bee bee = new Bee(); - flowers.forEach(f -> f.accept(bee)); - } -} -/* Output: -Gladiolus -Chrysanthemum -Gladiolus -Renuculus -Chrysanthemum -Renuculus -Chrysanthemum -Chrysanthemum -Chrysanthemum -Renuculus -Bee and Gladiolus -Bee and Chrysanthemum -Bee and Gladiolus -Bee and Renuculus -Bee and Chrysanthemum -Bee and Renuculus -Bee and Chrysanthemum -Bee and Chrysanthemum -Bee and Chrysanthemum -Bee and Renuculus -*/ diff --git a/code/polymorphism/CovariantReturn.java b/code/polymorphism/CovariantReturn.java deleted file mode 100644 index e88fe590..00000000 --- a/code/polymorphism/CovariantReturn.java +++ /dev/null @@ -1,38 +0,0 @@ -// polymorphism/CovariantReturn.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Grain { - @Override - public String toString() { return "Grain"; } -} - -class Wheat extends Grain { - @Override - public String toString() { return "Wheat"; } -} - -class Mill { - Grain process() { return new Grain(); } -} - -class WheatMill extends Mill { - @Override - Wheat process() { return new Wheat(); } -} - -public class CovariantReturn { - public static void main(String[] args) { - Mill m = new Mill(); - Grain g = m.process(); - System.out.println(g); - m = new WheatMill(); - g = m.process(); - System.out.println(g); - } -} -/* Output: -Grain -Wheat -*/ diff --git a/code/polymorphism/FieldAccess.java b/code/polymorphism/FieldAccess.java deleted file mode 100644 index 95e47c5e..00000000 --- a/code/polymorphism/FieldAccess.java +++ /dev/null @@ -1,36 +0,0 @@ -// polymorphism/FieldAccess.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Direct field access is determined at compile time - -class Super { - public int field = 0; - public int getField() { return field; } -} - -class Sub extends Super { - public int field = 1; - @Override - public int getField() { return field; } - public int getSuperField() { return super.field; } -} - -public class FieldAccess { - public static void main(String[] args) { - Super sup = new Sub(); // Upcast - System.out.println("sup.field = " + sup.field + - ", sup.getField() = " + sup.getField()); - Sub sub = new Sub(); - System.out.println("sub.field = " + - sub.field + ", sub.getField() = " + - sub.getField() + - ", sub.getSuperField() = " + - sub.getSuperField()); - } -} -/* Output: -sup.field = 0, sup.getField() = 1 -sub.field = 1, sub.getField() = 1, sub.getSuperField() -= 0 -*/ diff --git a/code/polymorphism/Frog.java b/code/polymorphism/Frog.java deleted file mode 100644 index 9226910d..00000000 --- a/code/polymorphism/Frog.java +++ /dev/null @@ -1,122 +0,0 @@ -// polymorphism/Frog.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Cleanup and inheritance -// {java polymorphism.Frog} -package polymorphism; - -class Characteristic { - private String s; - Characteristic(String s) { - this.s = s; - System.out.println("Creating Characteristic " + s); - } - protected void dispose() { - System.out.println("disposing Characteristic " + s); - } -} - -class Description { - private String s; - Description(String s) { - this.s = s; - System.out.println("Creating Description " + s); - } - protected void dispose() { - System.out.println("disposing Description " + s); - } -} - -class LivingCreature { - private Characteristic p = - new Characteristic("is alive"); - private Description t = - new Description("Basic Living Creature"); - LivingCreature() { - System.out.println("LivingCreature()"); - } - protected void dispose() { - System.out.println("LivingCreature dispose"); - t.dispose(); - p.dispose(); - } -} - -class Animal extends LivingCreature { - private Characteristic p = - new Characteristic("has heart"); - private Description t = - new Description("Animal not Vegetable"); - Animal() { System.out.println("Animal()"); } - @Override - protected void dispose() { - System.out.println("Animal dispose"); - t.dispose(); - p.dispose(); - super.dispose(); - } -} - -class Amphibian extends Animal { - private Characteristic p = - new Characteristic("can live in water"); - private Description t = - new Description("Both water and land"); - Amphibian() { - System.out.println("Amphibian()"); - } - @Override - protected void dispose() { - System.out.println("Amphibian dispose"); - t.dispose(); - p.dispose(); - super.dispose(); - } -} - -public class Frog extends Amphibian { - private Characteristic p = - new Characteristic("Croaks"); - private Description t = new Description("Eats Bugs"); - public Frog() { System.out.println("Frog()"); } - @Override - protected void dispose() { - System.out.println("Frog dispose"); - t.dispose(); - p.dispose(); - super.dispose(); - } - public static void main(String[] args) { - Frog frog = new Frog(); - System.out.println("Bye!"); - frog.dispose(); - } -} -/* Output: -Creating Characteristic is alive -Creating Description Basic Living Creature -LivingCreature() -Creating Characteristic has heart -Creating Description Animal not Vegetable -Animal() -Creating Characteristic can live in water -Creating Description Both water and land -Amphibian() -Creating Characteristic Croaks -Creating Description Eats Bugs -Frog() -Bye! -Frog dispose -disposing Description Eats Bugs -disposing Characteristic Croaks -Amphibian dispose -disposing Description Both water and land -disposing Characteristic can live in water -Animal dispose -disposing Description Animal not Vegetable -disposing Characteristic has heart -LivingCreature dispose -disposing Description Basic Living Creature -disposing Characteristic is alive -*/ diff --git a/code/polymorphism/PolyConstructors.java b/code/polymorphism/PolyConstructors.java deleted file mode 100644 index 3a99f08b..00000000 --- a/code/polymorphism/PolyConstructors.java +++ /dev/null @@ -1,41 +0,0 @@ -// polymorphism/PolyConstructors.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Constructors and polymorphism -// don't produce what you might expect - -class Glyph { - void draw() { System.out.println("Glyph.draw()"); } - Glyph() { - System.out.println("Glyph() before draw()"); - draw(); - System.out.println("Glyph() after draw()"); - } -} - -class RoundGlyph extends Glyph { - private int radius = 1; - RoundGlyph(int r) { - radius = r; - System.out.println( - "RoundGlyph.RoundGlyph(), radius = " + radius); - } - @Override - void draw() { - System.out.println( - "RoundGlyph.draw(), radius = " + radius); - } -} - -public class PolyConstructors { - public static void main(String[] args) { - new RoundGlyph(5); - } -} -/* Output: -Glyph() before draw() -RoundGlyph.draw(), radius = 0 -Glyph() after draw() -RoundGlyph.RoundGlyph(), radius = 5 -*/ diff --git a/code/polymorphism/PrivateOverride.java b/code/polymorphism/PrivateOverride.java deleted file mode 100644 index 9873e03d..00000000 --- a/code/polymorphism/PrivateOverride.java +++ /dev/null @@ -1,24 +0,0 @@ -// polymorphism/PrivateOverride.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Trying to override a private method -// {java polymorphism.PrivateOverride} -package polymorphism; - -public class PrivateOverride { - private void f() { - System.out.println("private f()"); - } - public static void main(String[] args) { - PrivateOverride po = new Derived(); - po.f(); - } -} - -class Derived extends PrivateOverride { - public void f() { System.out.println("public f()"); } -} -/* Output: -private f() -*/ diff --git a/code/polymorphism/PrivateOverride2.java b/code/polymorphism/PrivateOverride2.java deleted file mode 100644 index 664672bc..00000000 --- a/code/polymorphism/PrivateOverride2.java +++ /dev/null @@ -1,22 +0,0 @@ -// polymorphism/PrivateOverride2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Detecting a mistaken override using @Override -// {WillNotCompile} -package polymorphism; - -public class PrivateOverride2 { - private void f() { - System.out.println("private f()"); - } - public static void main(String[] args) { - PrivateOverride2 po = new Derived2(); - po.f(); - } -} - -class Derived2 extends PrivateOverride2 { - @Override - public void f() { System.out.println("public f()"); } -} diff --git a/code/polymorphism/RTTI.java b/code/polymorphism/RTTI.java deleted file mode 100644 index 39c9029b..00000000 --- a/code/polymorphism/RTTI.java +++ /dev/null @@ -1,43 +0,0 @@ -// polymorphism/RTTI.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Downcasting & Runtime type information (RTTI) -// {ThrowsException} - -class Useful { - public void f() {} - public void g() {} -} - -class MoreUseful extends Useful { - @Override - public void f() {} - @Override - public void g() {} - public void u() {} - public void v() {} - public void w() {} -} - -public class RTTI { - public static void main(String[] args) { - Useful[] x = { - new Useful(), - new MoreUseful() - }; - x[0].f(); - x[1].g(); - // Compile time: method not found in Useful: - //- x[1].u(); - ((MoreUseful)x[1]).u(); // Downcast/RTTI - ((MoreUseful)x[0]).u(); // Exception thrown - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "main" -java.lang.ClassCastException: Useful cannot be cast to -MoreUseful - at RTTI.main(RTTI.java:31) -*/ diff --git a/code/polymorphism/ReferenceCounting.java b/code/polymorphism/ReferenceCounting.java deleted file mode 100644 index b378117f..00000000 --- a/code/polymorphism/ReferenceCounting.java +++ /dev/null @@ -1,71 +0,0 @@ -// polymorphism/ReferenceCounting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Cleaning up shared member objects - -class Shared { - private int refcount = 0; - private static long counter = 0; - private final long id = counter++; - Shared() { - System.out.println("Creating " + this); - } - public void addRef() { refcount++; } - protected void dispose() { - if(--refcount == 0) - System.out.println("Disposing " + this); - } - @Override - public String toString() { - return "Shared " + id; - } -} - -class Composing { - private Shared shared; - private static long counter = 0; - private final long id = counter++; - Composing(Shared shared) { - System.out.println("Creating " + this); - this.shared = shared; - this.shared.addRef(); - } - protected void dispose() { - System.out.println("disposing " + this); - shared.dispose(); - } - @Override - public String toString() { - return "Composing " + id; - } -} - -public class ReferenceCounting { - public static void main(String[] args) { - Shared shared = new Shared(); - Composing[] composing = { - new Composing(shared), - new Composing(shared), - new Composing(shared), - new Composing(shared), - new Composing(shared) - }; - for(Composing c : composing) - c.dispose(); - } -} -/* Output: -Creating Shared 0 -Creating Composing 0 -Creating Composing 1 -Creating Composing 2 -Creating Composing 3 -Creating Composing 4 -disposing Composing 0 -disposing Composing 1 -disposing Composing 2 -disposing Composing 3 -disposing Composing 4 -Disposing Shared 0 -*/ diff --git a/code/polymorphism/Sandwich.java b/code/polymorphism/Sandwich.java deleted file mode 100644 index 97f80d53..00000000 --- a/code/polymorphism/Sandwich.java +++ /dev/null @@ -1,54 +0,0 @@ -// polymorphism/Sandwich.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Order of constructor calls -// {java polymorphism.Sandwich} -package polymorphism; - -class Meal { - Meal() { System.out.println("Meal()"); } -} - -class Bread { - Bread() { System.out.println("Bread()"); } -} - -class Cheese { - Cheese() { System.out.println("Cheese()"); } -} - -class Lettuce { - Lettuce() { System.out.println("Lettuce()"); } -} - -class Lunch extends Meal { - Lunch() { System.out.println("Lunch()"); } -} - -class PortableLunch extends Lunch { - PortableLunch() { - System.out.println("PortableLunch()"); - } -} - -public class Sandwich extends PortableLunch { - private Bread b = new Bread(); - private Cheese c = new Cheese(); - private Lettuce l = new Lettuce(); - public Sandwich() { - System.out.println("Sandwich()"); - } - public static void main(String[] args) { - new Sandwich(); - } -} -/* Output: -Meal() -Lunch() -PortableLunch() -Bread() -Cheese() -Lettuce() -Sandwich() -*/ diff --git a/code/polymorphism/Shapes.java b/code/polymorphism/Shapes.java deleted file mode 100644 index 4d051e70..00000000 --- a/code/polymorphism/Shapes.java +++ /dev/null @@ -1,26 +0,0 @@ -// polymorphism/Shapes.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Polymorphism in Java -import polymorphism.shape.*; - -public class Shapes { - public static void main(String[] args) { - RandomShapes gen = new RandomShapes(); - // Make polymorphic method calls: - for(Shape shape : gen.array(9)) - shape.draw(); - } -} -/* Output: -Triangle.draw() -Triangle.draw() -Square.draw() -Triangle.draw() -Square.draw() -Triangle.draw() -Square.draw() -Triangle.draw() -Circle.draw() -*/ diff --git a/code/polymorphism/StaticPolymorphism.java b/code/polymorphism/StaticPolymorphism.java deleted file mode 100644 index 1ebe733b..00000000 --- a/code/polymorphism/StaticPolymorphism.java +++ /dev/null @@ -1,36 +0,0 @@ -// polymorphism/StaticPolymorphism.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Static methods are not polymorphic - -class StaticSuper { - public static String staticGet() { - return "Base staticGet()"; - } - public String dynamicGet() { - return "Base dynamicGet()"; - } -} - -class StaticSub extends StaticSuper { - public static String staticGet() { - return "Derived staticGet()"; - } - @Override - public String dynamicGet() { - return "Derived dynamicGet()"; - } -} - -public class StaticPolymorphism { - public static void main(String[] args) { - StaticSuper sup = new StaticSub(); // Upcast - System.out.println(StaticSuper.staticGet()); - System.out.println(sup.dynamicGet()); - } -} -/* Output: -Base staticGet() -Derived dynamicGet() -*/ diff --git a/code/polymorphism/Transmogrify.java b/code/polymorphism/Transmogrify.java deleted file mode 100644 index 09877d53..00000000 --- a/code/polymorphism/Transmogrify.java +++ /dev/null @@ -1,43 +0,0 @@ -// polymorphism/Transmogrify.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Dynamically changing the behavior of an object -// via composition (the "State" design pattern) - -class Actor { - public void act() {} -} - -class HappyActor extends Actor { - @Override - public void act() { - System.out.println("HappyActor"); - } -} - -class SadActor extends Actor { - @Override - public void act() { - System.out.println("SadActor"); - } -} - -class Stage { - private Actor actor = new HappyActor(); - public void change() { actor = new SadActor(); } - public void performPlay() { actor.act(); } -} - -public class Transmogrify { - public static void main(String[] args) { - Stage stage = new Stage(); - stage.performPlay(); - stage.change(); - stage.performPlay(); - } -} -/* Output: -HappyActor -SadActor -*/ diff --git a/code/polymorphism/music/Instrument.java b/code/polymorphism/music/Instrument.java deleted file mode 100644 index fb6c77e3..00000000 --- a/code/polymorphism/music/Instrument.java +++ /dev/null @@ -1,11 +0,0 @@ -// polymorphism/music/Instrument.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package polymorphism.music; - -class Instrument { - public void play(Note n) { - System.out.println("Instrument.play()"); - } -} diff --git a/code/polymorphism/music/Music.java b/code/polymorphism/music/Music.java deleted file mode 100644 index 8e903ec0..00000000 --- a/code/polymorphism/music/Music.java +++ /dev/null @@ -1,21 +0,0 @@ -// polymorphism/music/Music.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Inheritance & upcasting -// {java polymorphism.music.Music} -package polymorphism.music; - -public class Music { - public static void tune(Instrument i) { - // ... - i.play(Note.MIDDLE_C); - } - public static void main(String[] args) { - Wind flute = new Wind(); - tune(flute); // Upcasting - } -} -/* Output: -Wind.play() MIDDLE_C -*/ diff --git a/code/polymorphism/music/Music2.java b/code/polymorphism/music/Music2.java deleted file mode 100644 index a5bff54b..00000000 --- a/code/polymorphism/music/Music2.java +++ /dev/null @@ -1,46 +0,0 @@ -// polymorphism/music/Music2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Overloading instead of upcasting -// {java polymorphism.music.Music2} -package polymorphism.music; - -class Stringed extends Instrument { - @Override - public void play(Note n) { - System.out.println("Stringed.play() " + n); - } -} - -class Brass extends Instrument { - @Override - public void play(Note n) { - System.out.println("Brass.play() " + n); - } -} - -public class Music2 { - public static void tune(Wind i) { - i.play(Note.MIDDLE_C); - } - public static void tune(Stringed i) { - i.play(Note.MIDDLE_C); - } - public static void tune(Brass i) { - i.play(Note.MIDDLE_C); - } - public static void main(String[] args) { - Wind flute = new Wind(); - Stringed violin = new Stringed(); - Brass frenchHorn = new Brass(); - tune(flute); // No upcasting - tune(violin); - tune(frenchHorn); - } -} -/* Output: -Wind.play() MIDDLE_C -Stringed.play() MIDDLE_C -Brass.play() MIDDLE_C -*/ diff --git a/code/polymorphism/music/Note.java b/code/polymorphism/music/Note.java deleted file mode 100644 index 414367a9..00000000 --- a/code/polymorphism/music/Note.java +++ /dev/null @@ -1,10 +0,0 @@ -// polymorphism/music/Note.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Notes to play on musical instruments -package polymorphism.music; - -public enum Note { - MIDDLE_C, C_SHARP, B_FLAT; // Etc. -} diff --git a/code/polymorphism/music/Wind.java b/code/polymorphism/music/Wind.java deleted file mode 100644 index c38ac497..00000000 --- a/code/polymorphism/music/Wind.java +++ /dev/null @@ -1,15 +0,0 @@ -// polymorphism/music/Wind.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package polymorphism.music; - -// Wind objects are instruments -// because they have the same interface: -public class Wind extends Instrument { - // Redefine interface method: - @Override - public void play(Note n) { - System.out.println("Wind.play() " + n); - } -} diff --git a/code/polymorphism/music3/Music3.java b/code/polymorphism/music3/Music3.java deleted file mode 100644 index da3eb364..00000000 --- a/code/polymorphism/music3/Music3.java +++ /dev/null @@ -1,108 +0,0 @@ -// polymorphism/music3/Music3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// An extensible program -// {java polymorphism.music3.Music3} -package polymorphism.music3; -import polymorphism.music.Note; - -class Instrument { - void play(Note n) { - System.out.println("Instrument.play() " + n); - } - String what() { return "Instrument"; } - void adjust() { - System.out.println("Adjusting Instrument"); - } -} - -class Wind extends Instrument { - @Override - void play(Note n) { - System.out.println("Wind.play() " + n); - } - @Override - String what() { return "Wind"; } - @Override - void adjust() { - System.out.println("Adjusting Wind"); - } -} - -class Percussion extends Instrument { - @Override - void play(Note n) { - System.out.println("Percussion.play() " + n); - } - @Override - String what() { return "Percussion"; } - @Override - void adjust() { - System.out.println("Adjusting Percussion"); - } -} - -class Stringed extends Instrument { - @Override - void play(Note n) { - System.out.println("Stringed.play() " + n); - } - @Override - String what() { return "Stringed"; } - @Override - void adjust() { - System.out.println("Adjusting Stringed"); - } -} - -class Brass extends Wind { - @Override - void play(Note n) { - System.out.println("Brass.play() " + n); - } - @Override - void adjust() { - System.out.println("Adjusting Brass"); - } -} - -class Woodwind extends Wind { - @Override - void play(Note n) { - System.out.println("Woodwind.play() " + n); - } - @Override - String what() { return "Woodwind"; } -} - -public class Music3 { - // Doesn't care about type, so new types - // added to the system still work right: - public static void tune(Instrument i) { - // ... - i.play(Note.MIDDLE_C); - } - public static void tuneAll(Instrument[] e) { - for(Instrument i : e) - tune(i); - } - public static void main(String[] args) { - // Upcasting during addition to the array: - Instrument[] orchestra = { - new Wind(), - new Percussion(), - new Stringed(), - new Brass(), - new Woodwind() - }; - tuneAll(orchestra); - } -} -/* Output: -Wind.play() MIDDLE_C -Percussion.play() MIDDLE_C -Stringed.play() MIDDLE_C -Brass.play() MIDDLE_C -Woodwind.play() MIDDLE_C -*/ diff --git a/code/polymorphism/shape/Circle.java b/code/polymorphism/shape/Circle.java deleted file mode 100644 index fc857950..00000000 --- a/code/polymorphism/shape/Circle.java +++ /dev/null @@ -1,16 +0,0 @@ -// polymorphism/shape/Circle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package polymorphism.shape; - -public class Circle extends Shape { - @Override - public void draw() { - System.out.println("Circle.draw()"); - } - @Override - public void erase() { - System.out.println("Circle.erase()"); - } -} diff --git a/code/polymorphism/shape/RandomShapes.java b/code/polymorphism/shape/RandomShapes.java deleted file mode 100644 index c1419f4e..00000000 --- a/code/polymorphism/shape/RandomShapes.java +++ /dev/null @@ -1,26 +0,0 @@ -// polymorphism/shape/RandomShapes.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A "factory" that randomly creates shapes -package polymorphism.shape; -import java.util.*; - -public class RandomShapes { - private Random rand = new Random(47); - public Shape get() { - switch(rand.nextInt(3)) { - default: - case 0: return new Circle(); - case 1: return new Square(); - case 2: return new Triangle(); - } - } - public Shape[] array(int sz) { - Shape[] shapes = new Shape[sz]; - // Fill up the array with shapes: - for(int i = 0; i < shapes.length; i++) - shapes[i] = get(); - return shapes; - } -} diff --git a/code/polymorphism/shape/Shape.java b/code/polymorphism/shape/Shape.java deleted file mode 100644 index 4be93c86..00000000 --- a/code/polymorphism/shape/Shape.java +++ /dev/null @@ -1,10 +0,0 @@ -// polymorphism/shape/Shape.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package polymorphism.shape; - -public class Shape { - public void draw() {} - public void erase() {} -} diff --git a/code/polymorphism/shape/Square.java b/code/polymorphism/shape/Square.java deleted file mode 100644 index 4938335b..00000000 --- a/code/polymorphism/shape/Square.java +++ /dev/null @@ -1,16 +0,0 @@ -// polymorphism/shape/Square.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package polymorphism.shape; - -public class Square extends Shape { - @Override - public void draw() { - System.out.println("Square.draw()"); - } - @Override - public void erase() { - System.out.println("Square.erase()"); - } -} diff --git a/code/polymorphism/shape/Triangle.java b/code/polymorphism/shape/Triangle.java deleted file mode 100644 index db7394a3..00000000 --- a/code/polymorphism/shape/Triangle.java +++ /dev/null @@ -1,16 +0,0 @@ -// polymorphism/shape/Triangle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package polymorphism.shape; - -public class Triangle extends Shape { - @Override - public void draw() { - System.out.println("Triangle.draw()"); - } - @Override - public void erase() { - System.out.println("Triangle.erase()"); - } -} diff --git a/code/references/AddingClone.java b/code/references/AddingClone.java deleted file mode 100644 index 4f03cf06..00000000 --- a/code/references/AddingClone.java +++ /dev/null @@ -1,67 +0,0 @@ -// references/AddingClone.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// You must go through a few gyrations -// to add cloning to your own class -import java.util.*; -import java.util.stream.*; - -class Int2 implements Cloneable { - private int i; - Int2(int ii) { i = ii; } - public void increment() { i++; } - @Override - public String toString() { - return Integer.toString(i); - } - @Override - public Int2 clone() { - try { - return (Int2)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } -} - -// Inheritance doesn't remove cloneability: -class Int3 extends Int2 { - private int j; // Automatically duplicated - Int3(int i) { super(i); } -} - -public class AddingClone { - @SuppressWarnings("unchecked") - public static void main(String[] args) { - Int2 x = new Int2(10); - Int2 x2 = x.clone(); - x2.increment(); - System.out.println( - "x = " + x + ", x2 = " + x2); - // Anything inherited is also cloneable: - Int3 x3 = new Int3(7); - x3 = (Int3)x3.clone(); - ArrayList v = IntStream.range(0, 10) - .mapToObj(Int2::new) - .collect(Collectors - .toCollection(ArrayList::new)); - System.out.println("v: " + v); - ArrayList v2 = - (ArrayList)v.clone(); - // Now clone each element: - IntStream.range(0, v.size()) - .forEach(i -> v2.set(i, v.get(i).clone())); - // Increment all v2's elements: - v2.forEach(Int2::increment); - System.out.println("v2: " + v2); - // See if it changed v's elements: - System.out.println("v: " + v); - } -} -/* Output: -x = 10, x2 = 11 -v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -v2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -*/ diff --git a/code/references/Alias1.java b/code/references/Alias1.java deleted file mode 100644 index 1af594ec..00000000 --- a/code/references/Alias1.java +++ /dev/null @@ -1,27 +0,0 @@ -// references/Alias1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Aliasing two references to one object - -public class Alias1 { - private int i; - public Alias1(int ii) { i = ii; } - public static void main(String[] args) { - Alias1 x = new Alias1(7); - Alias1 y = x; // Assign the reference (1) - System.out.println("x: " + x.i); - System.out.println("y: " + y.i); - System.out.println("Incrementing x"); - x.i++; // [2] - System.out.println("x: " + x.i); - System.out.println("y: " + y.i); - } -} -/* Output: -x: 7 -y: 7 -Incrementing x -x: 8 -y: 8 -*/ diff --git a/code/references/Alias2.java b/code/references/Alias2.java deleted file mode 100644 index aa37e1a2..00000000 --- a/code/references/Alias2.java +++ /dev/null @@ -1,25 +0,0 @@ -// references/Alias2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Method calls implicitly alias their arguments - -public class Alias2 { - private int i; - public Alias2(int i) { this.i = i; } - public static void f(Alias2 reference) { - reference.i++; - } - public static void main(String[] args) { - Alias2 x = new Alias2(7); - System.out.println("x: " + x.i); - System.out.println("Calling f(x)"); - f(x); - System.out.println("x: " + x.i); - } -} -/* Output: -x: 7 -Calling f(x) -x: 8 -*/ diff --git a/code/references/CheckCloneable.java b/code/references/CheckCloneable.java deleted file mode 100644 index 137937a9..00000000 --- a/code/references/CheckCloneable.java +++ /dev/null @@ -1,113 +0,0 @@ -// references/CheckCloneable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Check to see if a reference can be cloned - -// Can't clone this -- doesn't override clone(): -class Ordinary {} - -// Overrides clone, doesn't implement Cloneable: -class WrongClone extends Ordinary { - @Override public Object clone() - throws CloneNotSupportedException { - return super.clone(); // Throws exception - } -} - -// Does all the right things for cloning: -class IsCloneable extends Ordinary -implements Cloneable { - @Override public Object clone() - throws CloneNotSupportedException { - return super.clone(); - } -} - -// Turn off cloning by throwing the exception: -class NoMore extends IsCloneable { - @Override public Object clone() - throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } -} - -class TryMore extends NoMore { - @Override public Object clone() - throws CloneNotSupportedException { - // Calls NoMore.clone(), throws exception: - return super.clone(); - } -} - -class BackOn extends NoMore { - private BackOn duplicate(BackOn b) { - // Somehow make a copy of b and return that - // copy. A dummy copy, just to make a point: - return new BackOn(); - } - @Override - public Object clone() { - // Doesn't call NoMore.clone(): - return duplicate(this); - } -} - -// You can't inherit from this, so you can't -// override clone() as you can in BackOn: -final class ReallyNoMore extends NoMore {} - -public class CheckCloneable { - public static - Ordinary tryToClone(Ordinary ord) { - String id = ord.getClass().getName(); - System.out.println("Attempting " + id); - Ordinary x = null; - if(ord instanceof Cloneable) { - try { - x = (Ordinary)((IsCloneable)ord).clone(); - System.out.println("Cloned " + id); - } catch(CloneNotSupportedException e) { - System.out.println( - "Could not clone " + id); - } - } else { - System.out.println("Doesn't implement Cloneable"); - } - return x; - } - public static void main(String[] args) { - // Upcasting: - Ordinary[] ord = { - new IsCloneable(), - new WrongClone(), - new NoMore(), - new TryMore(), - new BackOn(), - new ReallyNoMore(), - }; - Ordinary x = new Ordinary(); - // This won't compile because - // clone() is protected in Object: - //- x = (Ordinary)x.clone(); - // Checks first to see if the class - // implements Cloneable: - for(Ordinary ord1 : ord) { - tryToClone(ord1); - } - } -} -/* Output: -Attempting IsCloneable -Cloned IsCloneable -Attempting WrongClone -Doesn't implement Cloneable -Attempting NoMore -Could not clone NoMore -Attempting TryMore -Could not clone TryMore -Attempting BackOn -Cloned BackOn -Attempting ReallyNoMore -Could not clone ReallyNoMore -*/ diff --git a/code/references/CloneArrayList.java b/code/references/CloneArrayList.java deleted file mode 100644 index 601673c2..00000000 --- a/code/references/CloneArrayList.java +++ /dev/null @@ -1,38 +0,0 @@ -// references/CloneArrayList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The clone() operation works for only a few -// items in the standard Java library -import java.util.*; -import java.util.stream.*; - -class Int { - private int i; - Int(int ii) { i = ii; } - public void increment() { i++; } - @Override - public String toString() { - return Integer.toString(i); - } -} - -public class CloneArrayList { - public static void main(String[] args) { - ArrayList v = IntStream.range(0, 10) - .mapToObj(Int::new) - .collect(Collectors - .toCollection(ArrayList::new)); - System.out.println("v: " + v); - @SuppressWarnings("unchecked") - ArrayList v2 = (ArrayList)v.clone(); - // Increment all v2's elements: - v2.forEach(Int::increment); - // See if it changed v's elements: - System.out.println("v: " + v); - } -} -/* Output: -v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -v: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -*/ diff --git a/code/references/Compete.java b/code/references/Compete.java deleted file mode 100644 index 9e77f3a7..00000000 --- a/code/references/Compete.java +++ /dev/null @@ -1,89 +0,0 @@ -// references/Compete.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import onjava.Timer; - -class Thing1 implements Serializable {} -class Thing2 implements Serializable { - Thing1 t1 = new Thing1(); -} - -class Thing3 implements Cloneable { - @Override - public Thing3 clone() { - try { - return (Thing3)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } -} - -class Thing4 implements Cloneable { - private Thing3 t3 = new Thing3(); - @Override - public Thing4 clone() { - Thing4 t4 = null; - try { - t4 = (Thing4)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - // Clone the field, too: - t4.t3 = t3.clone(); - return t4; - } -} - -public class Compete { - public static final int SIZE = 100000; - public static void - main(String[] args) throws Exception { - Thing2[] a = new Thing2[SIZE]; - for(int i = 0; i < SIZE; i++) - a[i] = new Thing2(); - Thing4[] b = new Thing4[SIZE]; - for(int i = 0; i < SIZE; i++) - b[i] = new Thing4(); - Timer timer = new Timer(); - try( - ByteArrayOutputStream buf = - new ByteArrayOutputStream(); - ObjectOutputStream oos = - new ObjectOutputStream(buf) - ) { - for(Thing2 a1 : a) { - oos.writeObject(a1); - } - // Now get copies: - try( - ObjectInputStream in = - new ObjectInputStream( - new ByteArrayInputStream( - buf.toByteArray())) - ) { - Thing2[] c = new Thing2[SIZE]; - for(int i = 0; i < SIZE; i++) - c[i] = (Thing2)in.readObject(); - } - } - System.out.println( - "Duplication via serialization: " + - timer.duration() + " Milliseconds"); - - // Now try cloning: - timer = new Timer(); - Thing4[] d = new Thing4[SIZE]; - for(int i = 0; i < SIZE; i++) - d[i] = b[i].clone(); - System.out.println( - "Duplication via cloning: " + - timer.duration() + " Milliseconds"); - } -} -/* Output: -Duplication via serialization: 516 Milliseconds -Duplication via cloning: 71 Milliseconds -*/ diff --git a/code/references/CopyConstructor.java b/code/references/CopyConstructor.java deleted file mode 100644 index 2617f48b..00000000 --- a/code/references/CopyConstructor.java +++ /dev/null @@ -1,188 +0,0 @@ -// references/CopyConstructor.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A constructor to copy an object of the same -// type, as an attempt to create a local copy -import java.lang.reflect.*; - -class FruitQualities { - private int weight; - private int color; - private int firmness; - private int ripeness; - private int smell; - // etc. - // No-arg constructor: - FruitQualities() { - // Do something meaningful... - } - // Other constructors: - // ... - // Copy constructor: - FruitQualities(FruitQualities f) { - weight = f.weight; - color = f.color; - firmness = f.firmness; - ripeness = f.ripeness; - smell = f.smell; - // etc. - } -} - -class Seed { - // Members... - Seed() { /* No-arg constructor */ } - Seed(Seed s) { /* Copy constructor */ } -} - -class Fruit { - private FruitQualities fq; - private int seeds; - private Seed[] s; - Fruit(FruitQualities q, int seedCount) { - fq = q; - seeds = seedCount; - s = new Seed[seeds]; - for(int i = 0; i < seeds; i++) - s[i] = new Seed(); - } - // Other constructors: - // ... - // Copy constructor: - Fruit(Fruit f) { - fq = new FruitQualities(f.fq); - seeds = f.seeds; - s = new Seed[seeds]; - // Call all Seed copy-constructors: - for(int i = 0; i < seeds; i++) - s[i] = new Seed(f.s[i]); - // Other copy-construction activities... - } - // This allows derived constructors (or other - // methods) to put in different qualities: - protected void addQualities(FruitQualities q) { - fq = q; - } - protected FruitQualities getQualities() { - return fq; - } -} - -class Tomato extends Fruit { - Tomato() { - super(new FruitQualities(), 100); - } - Tomato(Tomato t) { // Copy-constructor - super(t); // Upcast to base copy-constructor - // Other copy-construction activities... - } -} - -class ZebraQualities extends FruitQualities { - private int stripedness; - // No-arg constructor: - ZebraQualities() { - super(); - // do something meaningful... - } - ZebraQualities(ZebraQualities z) { - super(z); - stripedness = z.stripedness; - } -} - -class GreenZebra extends Tomato { - GreenZebra() { - addQualities(new ZebraQualities()); - } - GreenZebra(GreenZebra g) { - super(g); // Calls Tomato(Tomato) - // Restore the right qualities: - addQualities(new ZebraQualities()); - } - public void evaluate() { - ZebraQualities zq = - (ZebraQualities)getQualities(); - // Do something with the qualities - // ... - } -} - -public class CopyConstructor { - public static void ripen(Tomato t) { - // Use the "copy constructor": - t = new Tomato(t); // [1] - System.out.println("In ripen, t is a " + - t.getClass().getName()); - } - public static void slice(Fruit f) { - f = new Fruit(f); // [2] Hmmm... will this work? - System.out.println("In slice, f is a " + - f.getClass().getName()); - } - @SuppressWarnings("unchecked") - public static void ripen2(Tomato t) { - try { - Class c = t.getClass(); - // Use the "copy constructor": - Constructor ct = - c.getConstructor(new Class[] { c }); - Object obj = - ct.newInstance(new Object[] { t }); - System.out.println("In ripen2, t is a " + - obj.getClass().getName()); - } catch(NoSuchMethodException | - SecurityException | - InstantiationException | - IllegalAccessException | - IllegalArgumentException | - InvocationTargetException e) { - System.out.println(e); - } - } - @SuppressWarnings("unchecked") - public static void slice2(Fruit f) { - try { - Class c = f.getClass(); - Constructor ct = - c.getConstructor(new Class[] { c }); - Object obj = - ct.newInstance(new Object[] { f }); - System.out.println("In slice2, f is a " + - obj.getClass().getName()); - } catch(NoSuchMethodException | - SecurityException | - InstantiationException | - IllegalAccessException | - IllegalArgumentException | - InvocationTargetException e) { - System.out.println(e); - } - } - public static void main(String[] args) { - Tomato tomato = new Tomato(); - ripen(tomato); // OK - slice(tomato); // OOPS! - ripen2(tomato); // OK - slice2(tomato); // OK - GreenZebra g = new GreenZebra(); - ripen(g); // OOPS! - slice(g); // OOPS! - ripen2(g); // OK - slice2(g); // OK - g.evaluate(); - } -} -/* Output: -In ripen, t is a Tomato -In slice, f is a Fruit -java.lang.NoSuchMethodException: Tomato.(Tomato) -java.lang.NoSuchMethodException: Tomato.(Tomato) -In ripen, t is a Tomato -In slice, f is a Fruit -java.lang.NoSuchMethodException: -GreenZebra.(GreenZebra) -java.lang.NoSuchMethodException: -GreenZebra.(GreenZebra) -*/ diff --git a/code/references/DepthReading.java b/code/references/DepthReading.java deleted file mode 100644 index 00d9dfda..00000000 --- a/code/references/DepthReading.java +++ /dev/null @@ -1,29 +0,0 @@ -// references/DepthReading.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Cloning a composed object -package references; - -public class DepthReading implements Cloneable { - private double depth; - public DepthReading(double depth) { - this.depth = depth; - } - @Override - public DepthReading clone() { - try { - return (DepthReading)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - public double getDepth() { return depth; } - public void setDepth(double depth) { - this.depth = depth; - } - @Override - public String toString() { - return String.valueOf(depth); - } -} diff --git a/code/references/HorrorFlick.java b/code/references/HorrorFlick.java deleted file mode 100644 index 709d15bf..00000000 --- a/code/references/HorrorFlick.java +++ /dev/null @@ -1,35 +0,0 @@ -// references/HorrorFlick.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Insert Cloneability at any level of inheritance - -class Person {} - -class Hero extends Person {} - -class Scientist extends Person implements Cloneable { - @Override - public Scientist clone() { - try { - return (Scientist)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } -} - -class MadScientist extends Scientist {} - -public class HorrorFlick { - public static void main(String[] args) { - Person p = new Person(); - Hero h = new Hero(); - Scientist s = new Scientist(); - MadScientist m = new MadScientist(); - //- p = (Person)p.clone(); // Compile error - //- h = (Hero)h.clone(); // Compile error - s = s.clone(); - m = (MadScientist)m.clone(); - } -} diff --git a/code/references/Immutable1.java b/code/references/Immutable1.java deleted file mode 100644 index 55ac1f6a..00000000 --- a/code/references/Immutable1.java +++ /dev/null @@ -1,34 +0,0 @@ -// references/Immutable1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Immutable objects are immune to aliasing - -public class Immutable1 { - private int data; - public Immutable1(int initVal) { - data = initVal; - } - public int read() { return data; } - public boolean nonzero() { return data != 0; } - public Immutable1 multiply(int multiplier) { - return new Immutable1(data * multiplier); - } - public static void f(Immutable1 i1) { - Immutable1 quad = i1.multiply(4); - System.out.println("i1 = " + i1.read()); - System.out.println("quad = " + quad.read()); - } - public static void main(String[] args) { - Immutable1 x = new Immutable1(47); - System.out.println("x = " + x.read()); - f(x); - System.out.println("x = " + x.read()); - } -} -/* Output: -x = 47 -i1 = 47 -quad = 188 -x = 47 -*/ diff --git a/code/references/Immutable2.java b/code/references/Immutable2.java deleted file mode 100644 index a565f86a..00000000 --- a/code/references/Immutable2.java +++ /dev/null @@ -1,71 +0,0 @@ -// references/Immutable2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A companion class to modify immutable objects - -class Mutable { - private int data; - Mutable(int initVal) { - data = initVal; - } - public Mutable add(int x) { - data += x; - return this; - } - public Mutable multiply(int x) { - data *= x; - return this; - } - public Immutable2 makeImmutable2() { - return new Immutable2(data); - } -} - -public class Immutable2 { - private int data; - public Immutable2(int initVal) { - data = initVal; - } - public int read() { return data; } - public boolean nonzero() { - return data != 0; - } - public Immutable2 add(int x) { - return new Immutable2(data + x); - } - public Immutable2 multiply(int x) { - return new Immutable2(data * x); - } - public Mutable makeMutable() { - return new Mutable(data); - } - public static - Immutable2 modify1(Immutable2 y) { - Immutable2 val = y.add(12); - val = val.multiply(3); - val = val.add(11); - val = val.multiply(2); - return val; - } - // This produces the same result: - public static - Immutable2 modify2(Immutable2 y) { - Mutable m = y.makeMutable(); - m.add(12).multiply(3).add(11).multiply(2); - return m.makeImmutable2(); - } - public static void main(String[] args) { - Immutable2 i2 = new Immutable2(47); - Immutable2 r1 = modify1(i2); - Immutable2 r2 = modify2(i2); - System.out.println("i2 = " + i2.read()); - System.out.println("r1 = " + r1.read()); - System.out.println("r2 = " + r2.read()); - } -} -/* Output: -i2 = 47 -r1 = 376 -r2 = 376 -*/ diff --git a/code/references/ImmutableInteger.java b/code/references/ImmutableInteger.java deleted file mode 100644 index 906aa7ef..00000000 --- a/code/references/ImmutableInteger.java +++ /dev/null @@ -1,22 +0,0 @@ -// references/ImmutableInteger.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The Integer class cannot be changed -import java.util.*; -import java.util.stream.*; - -public class ImmutableInteger { - public static void main(String[] args) { - @SuppressWarnings("deprecation") - List v = IntStream.range(0, 10) - .mapToObj(Integer::new) - .collect(Collectors.toList()); - System.out.println(v); - // But how do you change the int - // inside the Integer? - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -*/ diff --git a/code/references/ImmutableStrings.java b/code/references/ImmutableStrings.java deleted file mode 100644 index ad954e3f..00000000 --- a/code/references/ImmutableStrings.java +++ /dev/null @@ -1,25 +0,0 @@ -// references/ImmutableStrings.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrating StringBuilder - -public class ImmutableStrings { - public static void main(String[] args) { - String foo = "foo"; - String s = "abc" + foo + "def" - + Integer.toString(47); - System.out.println(s); - // The "equivalent" using StringBuilder: - StringBuilder sb = - new StringBuilder("abc"); // Creates String - sb.append(foo); - sb.append("def"); // Creates String - sb.append(Integer.toString(47)); - System.out.println(sb); - } -} -/* Output: -abcfoodef47 -abcfoodef47 -*/ diff --git a/code/references/LocalCopy.java b/code/references/LocalCopy.java deleted file mode 100644 index 9c01c09e..00000000 --- a/code/references/LocalCopy.java +++ /dev/null @@ -1,57 +0,0 @@ -// references/LocalCopy.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creating local copies with clone() - -class Duplo implements Cloneable { - private int n; - Duplo(int n) { this.n = n; } - @Override - public Duplo clone() { // [1] - try { - return (Duplo)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - public int getValue() { return n; } - public void setValue(int n) { this.n = n; } - public void increment() { n++; } - @Override - public String toString() { - return Integer.toString(n); - } -} - -public class LocalCopy { - public static Duplo g(Duplo v) { - // Passing a reference, modifies outside object: - v.increment(); - return v; - } - public static Duplo f(Duplo v) { - v = v.clone(); // [2] Local copy - v.increment(); - return v; - } - public static void main(String[] args) { - Duplo a = new Duplo(11); - Duplo b = g(a); - // Reference equivalence, not object equivalence: - System.out.println("a == b: " + (a == b) + - "\na = " + a + "\nb = " + b); - Duplo c = new Duplo(47); - Duplo d = f(c); - System.out.println("c == d: " + (c == d) + - "\nc = " + c + "\nd = " + d); - } -} -/* Output: -a == b: true -a = 12 -b = 12 -c == d: false -c = 47 -d = 48 -*/ diff --git a/code/references/MutableInteger.java b/code/references/MutableInteger.java deleted file mode 100644 index dfe0cc7b..00000000 --- a/code/references/MutableInteger.java +++ /dev/null @@ -1,34 +0,0 @@ -// references/MutableInteger.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A changeable wrapper class -import java.util.*; -import java.util.stream.*; - -class IntValue { - private int n; - IntValue(int x) { n = x; } - public int getValue() { return n; } - public void setValue(int n) { this.n = n; } - public void increment() { n++; } - @Override - public String toString() { - return Integer.toString(n); - } -} - -public class MutableInteger { - public static void main(String[] args) { - List v = IntStream.range(0, 10) - .mapToObj(IntValue::new) - .collect(Collectors.toList()); - System.out.println(v); - v.forEach(IntValue::increment); - System.out.println(v); - } -} -/* Output: -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -*/ diff --git a/code/references/OceanReading.java b/code/references/OceanReading.java deleted file mode 100644 index b89f1b04..00000000 --- a/code/references/OceanReading.java +++ /dev/null @@ -1,48 +0,0 @@ -// references/OceanReading.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Cloning a composed object -package references; - -public class OceanReading implements Cloneable { - private DepthReading depth; - private TemperatureReading temperature; - public - OceanReading(double tdata, double ddata) { - temperature = new TemperatureReading(tdata); - depth = new DepthReading(ddata); - } - @Override - public OceanReading clone() { - OceanReading or = null; - try { - or = (OceanReading)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - // Must clone references: - or.depth = (DepthReading)or.depth.clone(); - or.temperature = - (TemperatureReading)or.temperature.clone(); - return or; - } - public TemperatureReading getTemperatureReading() { - return temperature; - } - public void - setTemperatureReading(TemperatureReading tr) { - temperature = tr; - } - public DepthReading getDepthReading() { - return depth; - } - public void setDepthReading(DepthReading dr) { - this.depth = dr; - } - @Override - public String toString() { - return "temperature: " + temperature + - ", depth: " + depth; - } -} diff --git a/code/references/PassReferences.java b/code/references/PassReferences.java deleted file mode 100644 index 2a163008..00000000 --- a/code/references/PassReferences.java +++ /dev/null @@ -1,19 +0,0 @@ -// references/PassReferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class PassReferences { - public static void f(PassReferences h) { - System.out.println("h inside f(): " + h); - } - public static void main(String[] args) { - PassReferences p = new PassReferences(); - System.out.println("p inside main(): " + p); - f(p); - } -} -/* Output: -p inside main(): PassReferences@15db9742 -h inside f(): PassReferences@15db9742 -*/ diff --git a/code/references/SimplerMutableInteger.java b/code/references/SimplerMutableInteger.java deleted file mode 100644 index 191068ca..00000000 --- a/code/references/SimplerMutableInteger.java +++ /dev/null @@ -1,30 +0,0 @@ -// references/SimplerMutableInteger.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A trivial wrapper class -import java.util.*; -import java.util.stream.*; - -class IntValue2 { - public int n; - IntValue2(int n) { this.n = n; } -} - -public class SimplerMutableInteger { - public static void main(String[] args) { - List v = IntStream.range(0, 10) - .mapToObj(IntValue2::new) - .collect(Collectors.toList()); - v.forEach(iv2 -> - System.out.print(iv2.n + " ")); - System.out.println(); - v.forEach(iv2 -> iv2.n += 1); - v.forEach(iv2 -> - System.out.print(iv2.n + " ")); - } -} -/* Output: -0 1 2 3 4 5 6 7 8 9 -1 2 3 4 5 6 7 8 9 10 -*/ diff --git a/code/references/Snake.java b/code/references/Snake.java deleted file mode 100644 index 004f7e76..00000000 --- a/code/references/Snake.java +++ /dev/null @@ -1,51 +0,0 @@ -// references/Snake.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Tests cloning to see if reference -// destinations are also cloned - -public class Snake implements Cloneable { - private Snake next; - private char c; - // Value of i == number of segments - public Snake(int i, char x) { - c = x; - if(--i > 0) - next = new Snake(i, (char)(x + 1)); - } - public void increment() { - c++; - if(next != null) - next.increment(); - } - @Override - public String toString() { - String s = ":" + c; - if(next != null) - s += next.toString(); - return s; - } - @Override - public Snake clone() { - try { - return (Snake)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) { - Snake s = new Snake(5, 'a'); - System.out.println("s = " + s); - Snake s2 = s.clone(); - System.out.println("s2 = " + s2); - s.increment(); - System.out.println( - "after s.increment, s2 = " + s2); - } -} -/* Output: -s = :a:b:c:d:e -s2 = :a:b:c:d:e -after s.increment, s2 = :a:c:d:e:f -*/ diff --git a/code/references/Stringer.java b/code/references/Stringer.java deleted file mode 100644 index 72663bb5..00000000 --- a/code/references/Stringer.java +++ /dev/null @@ -1,22 +0,0 @@ -// references/Stringer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Stringer { - public static String upcase(String s) { - return s.toUpperCase(); - } - public static void main(String[] args) { - String q = new String("howdy"); - System.out.println(q); // howdy - String qq = upcase(q); - System.out.println(qq); // HOWDY - System.out.println(q); // howdy - } -} -/* Output: -howdy -HOWDY -howdy -*/ diff --git a/code/references/TemperatureReading.java b/code/references/TemperatureReading.java deleted file mode 100644 index 9b77cfb2..00000000 --- a/code/references/TemperatureReading.java +++ /dev/null @@ -1,33 +0,0 @@ -// references/TemperatureReading.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Cloning a composed object -package references; - -public class TemperatureReading implements Cloneable { - private long time; - private double temperature; - public TemperatureReading(double temperature) { - time = System.currentTimeMillis(); - this.temperature = temperature; - } - @Override - public TemperatureReading clone() { - try { - return (TemperatureReading)super.clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - public double getTemperature() { - return temperature; - } - public void setTemperature(double temp) { - this.temperature = temp; - } - @Override - public String toString() { - return String.valueOf(temperature); - } -} diff --git a/code/references/tests/DeepCopyTest.java b/code/references/tests/DeepCopyTest.java deleted file mode 100644 index b65a8d89..00000000 --- a/code/references/tests/DeepCopyTest.java +++ /dev/null @@ -1,28 +0,0 @@ -// references/tests/DeepCopyTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package references; -import org.junit.jupiter.api.*; -import static org.junit.jupiter.api.Assertions.*; - -public class DeepCopyTest { - @Test - public void testClone() { - OceanReading reading = - new OceanReading(33.9, 100.5); - // Now clone it: - OceanReading clone = reading.clone(); - TemperatureReading tr = - clone.getTemperatureReading(); - tr.setTemperature(tr.getTemperature() + 1); - clone.setTemperatureReading(tr); - DepthReading dr = clone.getDepthReading(); - dr.setDepth(dr.getDepth() + 1); - clone.setDepthReading(dr); - assertEquals(reading.toString(), - "temperature: 33.9, depth: 100.5"); - assertEquals(clone.toString(), - "temperature: 34.9, depth: 101.5"); - } -} diff --git a/code/reuse/Bath.java b/code/reuse/Bath.java deleted file mode 100644 index 38e5e819..00000000 --- a/code/reuse/Bath.java +++ /dev/null @@ -1,61 +0,0 @@ -// reuse/Bath.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Constructor initialization with composition - -class Soap { - private String s; - Soap() { - System.out.println("Soap()"); - s = "Constructed"; - } - @Override - public String toString() { return s; } -} - -public class Bath { - private String // Initializing at point of definition: - s1 = "Happy", - s2 = "Happy", - s3, s4; - private Soap castille; - private int i; - private float toy; - public Bath() { - System.out.println("Inside Bath()"); - s3 = "Joy"; - toy = 3.14f; - castille = new Soap(); - } - // Instance initialization: - { i = 47; } - @Override - public String toString() { - if(s4 == null) // Delayed initialization: - s4 = "Joy"; - return - "s1 = " + s1 + "\n" + - "s2 = " + s2 + "\n" + - "s3 = " + s3 + "\n" + - "s4 = " + s4 + "\n" + - "i = " + i + "\n" + - "toy = " + toy + "\n" + - "castille = " + castille; - } - public static void main(String[] args) { - Bath b = new Bath(); - System.out.println(b); - } -} -/* Output: -Inside Bath() -Soap() -s1 = Happy -s2 = Happy -s3 = Joy -s4 = Joy -i = 47 -toy = 3.14 -castille = Constructed -*/ diff --git a/code/reuse/Beetle.java b/code/reuse/Beetle.java deleted file mode 100644 index 0a41bc17..00000000 --- a/code/reuse/Beetle.java +++ /dev/null @@ -1,43 +0,0 @@ -// reuse/Beetle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The full process of initialization - -class Insect { - private int i = 9; - protected int j; - Insect() { - System.out.println("i = " + i + ", j = " + j); - j = 39; - } - private static int x1 = - printInit("static Insect.x1 initialized"); - static int printInit(String s) { - System.out.println(s); - return 47; - } -} - -public class Beetle extends Insect { - private int k = printInit("Beetle.k initialized"); - public Beetle() { - System.out.println("k = " + k); - System.out.println("j = " + j); - } - private static int x2 = - printInit("static Beetle.x2 initialized"); - public static void main(String[] args) { - System.out.println("Beetle constructor"); - Beetle b = new Beetle(); - } -} -/* Output: -static Insect.x1 initialized -static Beetle.x2 initialized -Beetle constructor -i = 9, j = 0 -Beetle.k initialized -k = 47 -j = 39 -*/ diff --git a/code/reuse/BlankFinal.java b/code/reuse/BlankFinal.java deleted file mode 100644 index 93818a06..00000000 --- a/code/reuse/BlankFinal.java +++ /dev/null @@ -1,29 +0,0 @@ -// reuse/BlankFinal.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// "Blank" final fields - -class Poppet { - private int i; - Poppet(int ii) { i = ii; } -} - -public class BlankFinal { - private final int i = 0; // Initialized final - private final int j; // Blank final - private final Poppet p; // Blank final reference - // Blank finals MUST be initialized in constructor: - public BlankFinal() { - j = 1; // Initialize blank final - p = new Poppet(1); // Init blank final reference - } - public BlankFinal(int x) { - j = x; // Initialize blank final - p = new Poppet(x); // Init blank final reference - } - public static void main(String[] args) { - new BlankFinal(); - new BlankFinal(47); - } -} diff --git a/code/reuse/CADSystem.java b/code/reuse/CADSystem.java deleted file mode 100644 index 55fbe0d8..00000000 --- a/code/reuse/CADSystem.java +++ /dev/null @@ -1,116 +0,0 @@ -// reuse/CADSystem.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Ensuring proper cleanup -// {java reuse.CADSystem} -package reuse; - -class Shape { - Shape(int i) { - System.out.println("Shape constructor"); - } - void dispose() { - System.out.println("Shape dispose"); - } -} - -class Circle extends Shape { - Circle(int i) { - super(i); - System.out.println("Drawing Circle"); - } - @Override - void dispose() { - System.out.println("Erasing Circle"); - super.dispose(); - } -} - -class Triangle extends Shape { - Triangle(int i) { - super(i); - System.out.println("Drawing Triangle"); - } - @Override - void dispose() { - System.out.println("Erasing Triangle"); - super.dispose(); - } -} - -class Line extends Shape { - private int start, end; - Line(int start, int end) { - super(start); - this.start = start; - this.end = end; - System.out.println( - "Drawing Line: " + start + ", " + end); - } - @Override - void dispose() { - System.out.println( - "Erasing Line: " + start + ", " + end); - super.dispose(); - } -} - -public class CADSystem extends Shape { - private Circle c; - private Triangle t; - private Line[] lines = new Line[3]; - public CADSystem(int i) { - super(i + 1); - for(int j = 0; j < lines.length; j++) - lines[j] = new Line(j, j*j); - c = new Circle(1); - t = new Triangle(1); - System.out.println("Combined constructor"); - } - @Override - public void dispose() { - System.out.println("CADSystem.dispose()"); - // The order of cleanup is the reverse - // of the order of initialization: - t.dispose(); - c.dispose(); - for(int i = lines.length - 1; i >= 0; i--) - lines[i].dispose(); - super.dispose(); - } - public static void main(String[] args) { - CADSystem x = new CADSystem(47); - try { - // Code and exception handling... - } finally { - x.dispose(); - } - } -} -/* Output: -Shape constructor -Shape constructor -Drawing Line: 0, 0 -Shape constructor -Drawing Line: 1, 1 -Shape constructor -Drawing Line: 2, 4 -Shape constructor -Drawing Circle -Shape constructor -Drawing Triangle -Combined constructor -CADSystem.dispose() -Erasing Triangle -Shape dispose -Erasing Circle -Shape dispose -Erasing Line: 2, 4 -Shape dispose -Erasing Line: 1, 1 -Shape dispose -Erasing Line: 0, 0 -Shape dispose -Shape dispose -*/ diff --git a/code/reuse/Car.java b/code/reuse/Car.java deleted file mode 100644 index 1bc4377b..00000000 --- a/code/reuse/Car.java +++ /dev/null @@ -1,43 +0,0 @@ -// reuse/Car.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Composition with public objects - -class Engine { - public void start() {} - public void rev() {} - public void stop() {} -} - -class Wheel { - public void inflate(int psi) {} -} - -class Window { - public void rollup() {} - public void rolldown() {} -} - -class Door { - public Window window = new Window(); - public void open() {} - public void close() {} -} - -public class Car { - public Engine engine = new Engine(); - public Wheel[] wheel = new Wheel[4]; - public Door - left = new Door(), - right = new Door(); // 2-door - public Car() { - for(int i = 0; i < 4; i++) - wheel[i] = new Wheel(); - } - public static void main(String[] args) { - Car car = new Car(); - car.left.window.rollup(); - car.wheel[0].inflate(72); - } -} diff --git a/code/reuse/Cartoon.java b/code/reuse/Cartoon.java deleted file mode 100644 index 48741baf..00000000 --- a/code/reuse/Cartoon.java +++ /dev/null @@ -1,31 +0,0 @@ -// reuse/Cartoon.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Constructor calls during inheritance - -class Art { - Art() { - System.out.println("Art constructor"); - } -} - -class Drawing extends Art { - Drawing() { - System.out.println("Drawing constructor"); - } -} - -public class Cartoon extends Drawing { - public Cartoon() { - System.out.println("Cartoon constructor"); - } - public static void main(String[] args) { - Cartoon x = new Cartoon(); - } -} -/* Output: -Art constructor -Drawing constructor -Cartoon constructor -*/ diff --git a/code/reuse/Chess.java b/code/reuse/Chess.java deleted file mode 100644 index 30f2685b..00000000 --- a/code/reuse/Chess.java +++ /dev/null @@ -1,33 +0,0 @@ -// reuse/Chess.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Inheritance, constructors and arguments - -class Game { - Game(int i) { - System.out.println("Game constructor"); - } -} - -class BoardGame extends Game { - BoardGame(int i) { - super(i); - System.out.println("BoardGame constructor"); - } -} - -public class Chess extends BoardGame { - Chess() { - super(11); - System.out.println("Chess constructor"); - } - public static void main(String[] args) { - Chess x = new Chess(); - } -} -/* Output: -Game constructor -BoardGame constructor -Chess constructor -*/ diff --git a/code/reuse/DerivedSpaceShip.java b/code/reuse/DerivedSpaceShip.java deleted file mode 100644 index dfbe20ac..00000000 --- a/code/reuse/DerivedSpaceShip.java +++ /dev/null @@ -1,19 +0,0 @@ -// reuse/DerivedSpaceShip.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class -DerivedSpaceShip extends SpaceShipControls { - private String name; - public DerivedSpaceShip(String name) { - this.name = name; - } - @Override - public String toString() { return name; } - public static void main(String[] args) { - DerivedSpaceShip protector = - new DerivedSpaceShip("NSEA Protector"); - protector.forward(100); - } -} diff --git a/code/reuse/Detergent.java b/code/reuse/Detergent.java deleted file mode 100644 index 99f4e7cc..00000000 --- a/code/reuse/Detergent.java +++ /dev/null @@ -1,48 +0,0 @@ -// reuse/Detergent.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Inheritance syntax & properties - -class Cleanser { - private String s = "Cleanser"; - public void append(String a) { s += a; } - public void dilute() { append(" dilute()"); } - public void apply() { append(" apply()"); } - public void scrub() { append(" scrub()"); } - @Override - public String toString() { return s; } - public static void main(String[] args) { - Cleanser x = new Cleanser(); - x.dilute(); x.apply(); x.scrub(); - System.out.println(x); - } -} - -public class Detergent extends Cleanser { - // Change a method: - @Override - public void scrub() { - append(" Detergent.scrub()"); - super.scrub(); // Call base-class version - } - // Add methods to the interface: - public void foam() { append(" foam()"); } - // Test the new class: - public static void main(String[] args) { - Detergent x = new Detergent(); - x.dilute(); - x.apply(); - x.scrub(); - x.foam(); - System.out.println(x); - System.out.println("Testing base class:"); - Cleanser.main(args); - } -} -/* Output: -Cleanser dilute() apply() Detergent.scrub() scrub() -foam() -Testing base class: -Cleanser dilute() apply() scrub() -*/ diff --git a/code/reuse/FinalArguments.java b/code/reuse/FinalArguments.java deleted file mode 100644 index 46efed7e..00000000 --- a/code/reuse/FinalArguments.java +++ /dev/null @@ -1,27 +0,0 @@ -// reuse/FinalArguments.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using "final" with method arguments - -class Gizmo { - public void spin() {} -} - -public class FinalArguments { - void with(final Gizmo g) { - //- g = new Gizmo(); // Illegal -- g is final - } - void without(Gizmo g) { - g = new Gizmo(); // OK -- g not final - g.spin(); - } - // void f(final int i) { i++; } // Can't change - // You can only read from a final primitive: - int g(final int i) { return i + 1; } - public static void main(String[] args) { - FinalArguments bf = new FinalArguments(); - bf.without(null); - bf.with(null); - } -} diff --git a/code/reuse/FinalData.java b/code/reuse/FinalData.java deleted file mode 100644 index 4376f5c3..00000000 --- a/code/reuse/FinalData.java +++ /dev/null @@ -1,57 +0,0 @@ -// reuse/FinalData.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The effect of final on fields -import java.util.*; - -class Value { - int i; // Package access - Value(int i) { this.i = i; } -} - -public class FinalData { - private static Random rand = new Random(47); - private String id; - public FinalData(String id) { this.id = id; } - // Can be compile-time constants: - private final int valueOne = 9; - private static final int VALUE_TWO = 99; - // Typical public constant: - public static final int VALUE_THREE = 39; - // Cannot be compile-time constants: - private final int i4 = rand.nextInt(20); - static final int INT_5 = rand.nextInt(20); - private Value v1 = new Value(11); - private final Value v2 = new Value(22); - private static final Value VAL_3 = new Value(33); - // Arrays: - private final int[] a = { 1, 2, 3, 4, 5, 6 }; - @Override - public String toString() { - return id + ": " + "i4 = " + i4 - + ", INT_5 = " + INT_5; - } - public static void main(String[] args) { - FinalData fd1 = new FinalData("fd1"); - //- fd1.valueOne++; // Error: can't change value - fd1.v2.i++; // Object isn't constant! - fd1.v1 = new Value(9); // OK -- not final - for(int i = 0; i < fd1.a.length; i++) - fd1.a[i]++; // Object isn't constant! - //- fd1.v2 = new Value(0); // Error: Can't - //- fd1.VAL_3 = new Value(1); // change reference - //- fd1.a = new int[3]; - System.out.println(fd1); - System.out.println("Creating new FinalData"); - FinalData fd2 = new FinalData("fd2"); - System.out.println(fd1); - System.out.println(fd2); - } -} -/* Output: -fd1: i4 = 15, INT_5 = 18 -Creating new FinalData -fd1: i4 = 15, INT_5 = 18 -fd2: i4 = 13, INT_5 = 18 -*/ diff --git a/code/reuse/FinalOverridingIllusion.java b/code/reuse/FinalOverridingIllusion.java deleted file mode 100644 index e5c19ece..00000000 --- a/code/reuse/FinalOverridingIllusion.java +++ /dev/null @@ -1,56 +0,0 @@ -// reuse/FinalOverridingIllusion.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// It only looks like you can override -// a private or private final method - -class WithFinals { - // Identical to "private" alone: - private final void f() { - System.out.println("WithFinals.f()"); - } - // Also automatically "final": - private void g() { - System.out.println("WithFinals.g()"); - } -} - -class OverridingPrivate extends WithFinals { - private final void f() { - System.out.println("OverridingPrivate.f()"); - } - private void g() { - System.out.println("OverridingPrivate.g()"); - } -} - -class OverridingPrivate2 extends OverridingPrivate { - public final void f() { - System.out.println("OverridingPrivate2.f()"); - } - public void g() { - System.out.println("OverridingPrivate2.g()"); - } -} - -public class FinalOverridingIllusion { - public static void main(String[] args) { - OverridingPrivate2 op2 = new OverridingPrivate2(); - op2.f(); - op2.g(); - // You can upcast: - OverridingPrivate op = op2; - // But you can't call the methods: - //- op.f(); - //- op.g(); - // Same here: - WithFinals wf = op2; - //- wf.f(); - //- wf.g(); - } -} -/* Output: -OverridingPrivate2.f() -OverridingPrivate2.g() -*/ diff --git a/code/reuse/Hide.java b/code/reuse/Hide.java deleted file mode 100644 index f718e4b0..00000000 --- a/code/reuse/Hide.java +++ /dev/null @@ -1,41 +0,0 @@ -// reuse/Hide.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Overloading a base-class method name in a derived -// class does not hide the base-class versions - -class Homer { - char doh(char c) { - System.out.println("doh(char)"); - return 'd'; - } - float doh(float f) { - System.out.println("doh(float)"); - return 1.0f; - } -} - -class Milhouse {} - -class Bart extends Homer { - void doh(Milhouse m) { - System.out.println("doh(Milhouse)"); - } -} - -public class Hide { - public static void main(String[] args) { - Bart b = new Bart(); - b.doh(1); - b.doh('x'); - b.doh(1.0f); - b.doh(new Milhouse()); - } -} -/* Output: -doh(float) -doh(char) -doh(float) -doh(Milhouse) -*/ diff --git a/code/reuse/Jurassic.java b/code/reuse/Jurassic.java deleted file mode 100644 index 04b7d61c..00000000 --- a/code/reuse/Jurassic.java +++ /dev/null @@ -1,26 +0,0 @@ -// reuse/Jurassic.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Making an entire class final - -class SmallBrain {} - -final class Dinosaur { - int i = 7; - int j = 1; - SmallBrain x = new SmallBrain(); - void f() {} -} - -//- class Further extends Dinosaur {} -// error: Cannot extend final class 'Dinosaur' - -public class Jurassic { - public static void main(String[] args) { - Dinosaur n = new Dinosaur(); - n.f(); - n.i = 40; - n.j++; - } -} diff --git a/code/reuse/Lisa.java b/code/reuse/Lisa.java deleted file mode 100644 index 85ec5cc9..00000000 --- a/code/reuse/Lisa.java +++ /dev/null @@ -1,11 +0,0 @@ -// reuse/Lisa.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {WillNotCompile} - -class Lisa extends Homer { - @Override void doh(Milhouse m) { - System.out.println("doh(Milhouse)"); - } -} diff --git a/code/reuse/Orc.java b/code/reuse/Orc.java deleted file mode 100644 index c3ba40a8..00000000 --- a/code/reuse/Orc.java +++ /dev/null @@ -1,41 +0,0 @@ -// reuse/Orc.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The protected keyword - -class Villain { - private String name; - protected void set(String nm) { name = nm; } - Villain(String name) { this.name = name; } - @Override - public String toString() { - return "I'm a Villain and my name is " + name; - } -} - -public class Orc extends Villain { - private int orcNumber; - public Orc(String name, int orcNumber) { - super(name); - this.orcNumber = orcNumber; - } - public void change(String name, int orcNumber) { - set(name); // Available because it's protected - this.orcNumber = orcNumber; - } - @Override - public String toString() { - return "Orc " + orcNumber + ": " + super.toString(); - } - public static void main(String[] args) { - Orc orc = new Orc("Limburger", 12); - System.out.println(orc); - orc.change("Bob", 19); - System.out.println(orc); - } -} -/* Output: -Orc 12: I'm a Villain and my name is Limburger -Orc 19: I'm a Villain and my name is Bob -*/ diff --git a/code/reuse/PlaceSetting.java b/code/reuse/PlaceSetting.java deleted file mode 100644 index b57d6383..00000000 --- a/code/reuse/PlaceSetting.java +++ /dev/null @@ -1,82 +0,0 @@ -// reuse/PlaceSetting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Combining composition & inheritance - -class Plate { - Plate(int i) { - System.out.println("Plate constructor"); - } -} - -class DinnerPlate extends Plate { - DinnerPlate(int i) { - super(i); - System.out.println("DinnerPlate constructor"); - } -} - -class Utensil { - Utensil(int i) { - System.out.println("Utensil constructor"); - } -} - -class Spoon extends Utensil { - Spoon(int i) { - super(i); - System.out.println("Spoon constructor"); - } -} - -class Fork extends Utensil { - Fork(int i) { - super(i); - System.out.println("Fork constructor"); - } -} - -class Knife extends Utensil { - Knife(int i) { - super(i); - System.out.println("Knife constructor"); - } -} - -// A cultural way of doing something: -class Custom { - Custom(int i) { - System.out.println("Custom constructor"); - } -} - -public class PlaceSetting extends Custom { - private Spoon sp; - private Fork frk; - private Knife kn; - private DinnerPlate pl; - public PlaceSetting(int i) { - super(i + 1); - sp = new Spoon(i + 2); - frk = new Fork(i + 3); - kn = new Knife(i + 4); - pl = new DinnerPlate(i + 5); - System.out.println("PlaceSetting constructor"); - } - public static void main(String[] args) { - PlaceSetting x = new PlaceSetting(9); - } -} -/* Output: -Custom constructor -Utensil constructor -Spoon constructor -Utensil constructor -Fork constructor -Utensil constructor -Knife constructor -Plate constructor -DinnerPlate constructor -PlaceSetting constructor -*/ diff --git a/code/reuse/SpaceShipControls.java b/code/reuse/SpaceShipControls.java deleted file mode 100644 index 6fde7086..00000000 --- a/code/reuse/SpaceShipControls.java +++ /dev/null @@ -1,14 +0,0 @@ -// reuse/SpaceShipControls.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SpaceShipControls { - void up(int velocity) {} - void down(int velocity) {} - void left(int velocity) {} - void right(int velocity) {} - void forward(int velocity) {} - void back(int velocity) {} - void turboBoost() {} -} diff --git a/code/reuse/SpaceShipDelegation.java b/code/reuse/SpaceShipDelegation.java deleted file mode 100644 index c31316b2..00000000 --- a/code/reuse/SpaceShipDelegation.java +++ /dev/null @@ -1,40 +0,0 @@ -// reuse/SpaceShipDelegation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SpaceShipDelegation { - private String name; - private SpaceShipControls controls = - new SpaceShipControls(); - public SpaceShipDelegation(String name) { - this.name = name; - } - // Delegated methods: - public void back(int velocity) { - controls.back(velocity); - } - public void down(int velocity) { - controls.down(velocity); - } - public void forward(int velocity) { - controls.forward(velocity); - } - public void left(int velocity) { - controls.left(velocity); - } - public void right(int velocity) { - controls.right(velocity); - } - public void turboBoost() { - controls.turboBoost(); - } - public void up(int velocity) { - controls.up(velocity); - } - public static void main(String[] args) { - SpaceShipDelegation protector = - new SpaceShipDelegation("NSEA Protector"); - protector.forward(100); - } -} diff --git a/code/reuse/SprinklerSystem.java b/code/reuse/SprinklerSystem.java deleted file mode 100644 index e0ccbe66..00000000 --- a/code/reuse/SprinklerSystem.java +++ /dev/null @@ -1,41 +0,0 @@ -// reuse/SprinklerSystem.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Composition for code reuse - -class WaterSource { - private String s; - WaterSource() { - System.out.println("WaterSource()"); - s = "Constructed"; - } - @Override - public String toString() { return s; } -} - -public class SprinklerSystem { - private String valve1, valve2, valve3, valve4; - private WaterSource source = new WaterSource(); - private int i; - private float f; - @Override - public String toString() { - return - "valve1 = " + valve1 + " " + - "valve2 = " + valve2 + " " + - "valve3 = " + valve3 + " " + - "valve4 = " + valve4 + "\n" + - "i = " + i + " " + "f = " + f + " " + - "source = " + source; // [1] - } - public static void main(String[] args) { - SprinklerSystem sprinklers = new SprinklerSystem(); - System.out.println(sprinklers); - } -} -/* Output: -WaterSource() -valve1 = null valve2 = null valve3 = null valve4 = null -i = 0 f = 0.0 source = Constructed -*/ diff --git a/code/reuse/Wind.java b/code/reuse/Wind.java deleted file mode 100644 index 3e9a05f6..00000000 --- a/code/reuse/Wind.java +++ /dev/null @@ -1,22 +0,0 @@ -// reuse/Wind.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Inheritance & upcasting - -class Instrument { - public void play() {} - static void tune(Instrument i) { - // ... - i.play(); - } -} - -// Wind objects are instruments -// because they have the same interface: -public class Wind extends Instrument { - public static void main(String[] args) { - Wind flute = new Wind(); - Instrument.tune(flute); // Upcasting - } -} diff --git a/code/serialization/APerson.java b/code/serialization/APerson.java deleted file mode 100644 index 1f67eb1c..00000000 --- a/code/serialization/APerson.java +++ /dev/null @@ -1,83 +0,0 @@ -// serialization/APerson.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Use the XOM library to write and read XML -// nu.xom.Node comes from http://www.xom.nu -import nu.xom.*; -import java.io.*; -import java.util.*; - -public class APerson { - private String first, last; - public APerson(String first, String last) { - this.first = first; - this.last = last; - } - // Produce an XML Element from this APerson object: - public Element getXML() { - Element person = new Element("person"); - Element firstName = new Element("first"); - firstName.appendChild(first); - Element lastName = new Element("last"); - lastName.appendChild(last); - person.appendChild(firstName); - person.appendChild(lastName); - return person; - } - // Constructor restores a APerson from XML: - public APerson(Element person) { - first = person - .getFirstChildElement("first").getValue(); - last = person - .getFirstChildElement("last").getValue(); - } - @Override - public String toString() { - return first + " " + last; - } - // Make it human-readable: - public static void - format(OutputStream os, Document doc) - throws Exception { - Serializer serializer = - new Serializer(os,"ISO-8859-1"); - serializer.setIndent(4); - serializer.setMaxLength(60); - serializer.write(doc); - serializer.flush(); - } - public static void - main(String[] args) throws Exception { - List people = Arrays.asList( - new APerson("Dr. Bunsen", "Honeydew"), - new APerson("Gonzo", "The Great"), - new APerson("Phillip J.", "Fry")); - System.out.println(people); - Element root = new Element("people"); - for(APerson p : people) - root.appendChild(p.getXML()); - Document doc = new Document(root); - format(System.out, doc); - format(new BufferedOutputStream( - new FileOutputStream("People.xml")), doc); - } -} -/* Output: -[Dr. Bunsen Honeydew, Gonzo The Great, Phillip J. Fry] - - - - Dr. Bunsen - Honeydew - - - Gonzo - The Great - - - Phillip J. - Fry - - -*/ diff --git a/code/serialization/AStoreCADState.java b/code/serialization/AStoreCADState.java deleted file mode 100644 index 0ce8858a..00000000 --- a/code/serialization/AStoreCADState.java +++ /dev/null @@ -1,120 +0,0 @@ -// serialization/AStoreCADState.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Saving the state of a fictitious CAD system -import java.io.*; -import java.util.*; -import java.util.stream.*; - -enum Color { RED, BLUE, GREEN } - -abstract class Shape implements Serializable { - private int xPos, yPos, dimension; - private static Random rand = new Random(47); - private static int counter = 0; - public abstract void setColor(Color newColor); - public abstract Color getColor(); - Shape(int xVal, int yVal, int dim) { - xPos = xVal; - yPos = yVal; - dimension = dim; - } - public String toString() { - return getClass() + "color[" + getColor() + - "] xPos[" + xPos + "] yPos[" + yPos + - "] dim[" + dimension + "]\n"; - } - public static Shape randomFactory() { - int xVal = rand.nextInt(100); - int yVal = rand.nextInt(100); - int dim = rand.nextInt(100); - switch(counter++ % 3) { - default: - case 0: return new Circle(xVal, yVal, dim); - case 1: return new Square(xVal, yVal, dim); - case 2: return new Line(xVal, yVal, dim); - } - } -} - -class Circle extends Shape { - private static Color color = Color.RED; - Circle(int xVal, int yVal, int dim) { - super(xVal, yVal, dim); - } - public void setColor(Color newColor) { - color = newColor; - } - public Color getColor() { return color; } -} - -class Square extends Shape { - private static Color color = Color.RED; - Square(int xVal, int yVal, int dim) { - super(xVal, yVal, dim); - } - public void setColor(Color newColor) { - color = newColor; - } - public Color getColor() { return color; } -} - -class Line extends Shape { - private static Color color = Color.RED; - public static void - serializeStaticState(ObjectOutputStream os) - throws IOException { os.writeObject(color); } - public static void - deserializeStaticState(ObjectInputStream os) - throws IOException, ClassNotFoundException { - color = (Color)os.readObject(); - } - Line(int xVal, int yVal, int dim) { - super(xVal, yVal, dim); - } - public void setColor(Color newColor) { - color = newColor; - } - public Color getColor() { return color; } -} - -public class AStoreCADState { - public static void main(String[] args) { - List> shapeTypes = - Arrays.asList( - Circle.class, Square.class, Line.class); - List shapes = IntStream.range(0, 10) - .mapToObj(i -> Shape.randomFactory()) - .collect(Collectors.toList()); - // Set all the static colors to GREEN: - shapes.forEach(s -> s.setColor(Color.GREEN)); - // Save the state vector: - try( - ObjectOutputStream out = - new ObjectOutputStream( - new FileOutputStream("CADState.dat")) - ) { - out.writeObject(shapeTypes); - Line.serializeStaticState(out); - out.writeObject(shapes); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Display the shapes: - System.out.println(shapes); - } -} -/* Output: -[class Circlecolor[GREEN] xPos[58] yPos[55] dim[93] -, class Squarecolor[GREEN] xPos[61] yPos[61] dim[29] -, class Linecolor[GREEN] xPos[68] yPos[0] dim[22] -, class Circlecolor[GREEN] xPos[7] yPos[88] dim[28] -, class Squarecolor[GREEN] xPos[51] yPos[89] dim[9] -, class Linecolor[GREEN] xPos[78] yPos[98] dim[61] -, class Circlecolor[GREEN] xPos[20] yPos[58] dim[16] -, class Squarecolor[GREEN] xPos[40] yPos[11] dim[22] -, class Linecolor[GREEN] xPos[4] yPos[83] dim[6] -, class Circlecolor[GREEN] xPos[75] yPos[10] dim[42] -] -*/ diff --git a/code/serialization/Alien.java b/code/serialization/Alien.java deleted file mode 100644 index d0b0f5bf..00000000 --- a/code/serialization/Alien.java +++ /dev/null @@ -1,7 +0,0 @@ -// serialization/Alien.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A serializable class -import java.io.*; -public class Alien implements Serializable {} diff --git a/code/serialization/Blip3.java b/code/serialization/Blip3.java deleted file mode 100644 index 6741298c..00000000 --- a/code/serialization/Blip3.java +++ /dev/null @@ -1,75 +0,0 @@ -// serialization/Blip3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Reconstructing an externalizable object -import java.io.*; - -public class Blip3 implements Externalizable { - private int i; - private String s; // No initialization - public Blip3() { - System.out.println("Blip3 Constructor"); - // s, i not initialized - } - public Blip3(String x, int a) { - System.out.println("Blip3(String x, int a)"); - s = x; - i = a; - // s & i initialized only in non-no-arg constructor. - } - @Override - public String toString() { return s + i; } - @Override - public void writeExternal(ObjectOutput out) - throws IOException { - System.out.println("Blip3.writeExternal"); - // You must do this: - out.writeObject(s); - out.writeInt(i); - } - @Override - public void readExternal(ObjectInput in) - throws IOException, ClassNotFoundException { - System.out.println("Blip3.readExternal"); - // You must do this: - s = (String)in.readObject(); - i = in.readInt(); - } - public static void main(String[] args) { - System.out.println("Constructing objects:"); - Blip3 b3 = new Blip3("A String ", 47); - System.out.println(b3); - try( - ObjectOutputStream o = new ObjectOutputStream( - new FileOutputStream("Blip3.serialized")) - ) { - System.out.println("Saving object:"); - o.writeObject(b3); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Now get it back: - System.out.println("Recovering b3:"); - try( - ObjectInputStream in = new ObjectInputStream( - new FileInputStream("Blip3.serialized")) - ) { - b3 = (Blip3)in.readObject(); - } catch(IOException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - System.out.println(b3); - } -} -/* Output: -Constructing objects: -Blip3(String x, int a) -A String 47 -Saving object: -Blip3.writeExternal -Recovering b3: -Blip3 Constructor -Blip3.readExternal -A String 47 -*/ diff --git a/code/serialization/Blips.java b/code/serialization/Blips.java deleted file mode 100644 index 88116d84..00000000 --- a/code/serialization/Blips.java +++ /dev/null @@ -1,80 +0,0 @@ -// serialization/Blips.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple use of Externalizable & a pitfall -import java.io.*; - -class Blip1 implements Externalizable { - public Blip1() { - System.out.println("Blip1 Constructor"); - } - @Override - public void writeExternal(ObjectOutput out) - throws IOException { - System.out.println("Blip1.writeExternal"); - } - @Override - public void readExternal(ObjectInput in) - throws IOException, ClassNotFoundException { - System.out.println("Blip1.readExternal"); - } -} - -class Blip2 implements Externalizable { - Blip2() { - System.out.println("Blip2 Constructor"); - } - @Override - public void writeExternal(ObjectOutput out) - throws IOException { - System.out.println("Blip2.writeExternal"); - } - @Override - public void readExternal(ObjectInput in) - throws IOException, ClassNotFoundException { - System.out.println("Blip2.readExternal"); - } -} - -public class Blips { - public static void main(String[] args) { - System.out.println("Constructing objects:"); - Blip1 b1 = new Blip1(); - Blip2 b2 = new Blip2(); - try( - ObjectOutputStream o = new ObjectOutputStream( - new FileOutputStream("Blips.serialized")) - ) { - System.out.println("Saving objects:"); - o.writeObject(b1); - o.writeObject(b2); - } catch(IOException e) { - throw new RuntimeException(e); - } - // Now get them back: - System.out.println("Recovering b1:"); - try( - ObjectInputStream in = new ObjectInputStream( - new FileInputStream("Blips.serialized")) - ) { - b1 = (Blip1)in.readObject(); - } catch(IOException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - // OOPS! Throws an exception: - //- System.out.println("Recovering b2:"); - //- b2 = (Blip2)in.readObject(); - } -} -/* Output: -Constructing objects: -Blip1 Constructor -Blip2 Constructor -Saving objects: -Blip1.writeExternal -Blip2.writeExternal -Recovering b1: -Blip1 Constructor -Blip1.readExternal -*/ diff --git a/code/serialization/FreezeAlien.java b/code/serialization/FreezeAlien.java deleted file mode 100644 index 0fe8e831..00000000 --- a/code/serialization/FreezeAlien.java +++ /dev/null @@ -1,19 +0,0 @@ -// serialization/FreezeAlien.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Create a serialized output file -import java.io.*; - -public class FreezeAlien { - public static void - main(String[] args) throws Exception { - try( - ObjectOutputStream out = new ObjectOutputStream( - new FileOutputStream("X.file")); - ) { - Alien quellek = new Alien(); - out.writeObject(quellek); - } - } -} diff --git a/code/serialization/Logon.java b/code/serialization/Logon.java deleted file mode 100644 index 3b910968..00000000 --- a/code/serialization/Logon.java +++ /dev/null @@ -1,62 +0,0 @@ -// serialization/Logon.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates the "transient" keyword -import java.util.concurrent.*; -import java.io.*; -import java.util.*; -import onjava.Nap; - -public class Logon implements Serializable { - private Date date = new Date(); - private String username; - private transient String password; - public Logon(String name, String pwd) { - username = name; - password = pwd; - } - @Override - public String toString() { - return "logon info: \n username: " + - username + "\n date: " + date + - "\n password: " + password; - } - public static void main(String[] args) { - Logon a = new Logon("Hulk", "myLittlePony"); - System.out.println("logon a = " + a); - try( - ObjectOutputStream o = - new ObjectOutputStream( - new FileOutputStream("Logon.dat")) - ) { - o.writeObject(a); - } catch(IOException e) { - throw new RuntimeException(e); - } - new Nap(1); - // Now get them back: - try( - ObjectInputStream in = new ObjectInputStream( - new FileInputStream("Logon.dat")) - ) { - System.out.println( - "Recovering object at " + new Date()); - a = (Logon)in.readObject(); - } catch(IOException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - System.out.println("logon a = " + a); - } -} -/* Output: -logon a = logon info: - username: Hulk - date: Tue May 09 06:07:47 MDT 2017 - password: myLittlePony -Recovering object at Tue May 09 06:07:49 MDT 2017 -logon a = logon info: - username: Hulk - date: Tue May 09 06:07:47 MDT 2017 - password: null -*/ diff --git a/code/serialization/MyWorld.java b/code/serialization/MyWorld.java deleted file mode 100644 index 99e39de3..00000000 --- a/code/serialization/MyWorld.java +++ /dev/null @@ -1,100 +0,0 @@ -// serialization/MyWorld.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.util.*; - -class House implements Serializable {} - -class Animal implements Serializable { - private String name; - private House preferredHouse; - Animal(String nm, House h) { - name = nm; - preferredHouse = h; - } - @Override - public String toString() { - return name + "[" + super.toString() + - "], " + preferredHouse + "\n"; - } -} - -public class MyWorld { - public static void main(String[] args) { - House house = new House(); - List animals = new ArrayList<>(); - animals.add( - new Animal("Bosco the dog", house)); - animals.add( - new Animal("Ralph the hamster", house)); - animals.add( - new Animal("Molly the cat", house)); - System.out.println("animals: " + animals); - try( - ByteArrayOutputStream buf1 = - new ByteArrayOutputStream(); - ObjectOutputStream o1 = - new ObjectOutputStream(buf1) - ) { - o1.writeObject(animals); - o1.writeObject(animals); // Write a 2nd set - // Write to a different stream: - try( - ByteArrayOutputStream buf2 = - new ByteArrayOutputStream(); - ObjectOutputStream o2 = - new ObjectOutputStream(buf2) - ) { - o2.writeObject(animals); - // Now get them back: - try( - ObjectInputStream in1 = - new ObjectInputStream( - new ByteArrayInputStream( - buf1.toByteArray())); - ObjectInputStream in2 = - new ObjectInputStream( - new ByteArrayInputStream( - buf2.toByteArray())) - ) { - List - animals1 = (List)in1.readObject(), - animals2 = (List)in1.readObject(), - animals3 = (List)in2.readObject(); - System.out.println( - "animals1: " + animals1); - System.out.println( - "animals2: " + animals2); - System.out.println( - "animals3: " + animals3); - } - } - } catch(IOException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - } -} -/* Output: -animals: [Bosco the dog[Animal@15db9742], -House@6d06d69c -, Ralph the hamster[Animal@7852e922], House@6d06d69c -, Molly the cat[Animal@4e25154f], House@6d06d69c -] -animals1: [Bosco the dog[Animal@7ba4f24f], -House@3b9a45b3 -, Ralph the hamster[Animal@7699a589], House@3b9a45b3 -, Molly the cat[Animal@58372a00], House@3b9a45b3 -] -animals2: [Bosco the dog[Animal@7ba4f24f], -House@3b9a45b3 -, Ralph the hamster[Animal@7699a589], House@3b9a45b3 -, Molly the cat[Animal@58372a00], House@3b9a45b3 -] -animals3: [Bosco the dog[Animal@4dd8dc3], -House@6d03e736 -, Ralph the hamster[Animal@568db2f2], House@6d03e736 -, Molly the cat[Animal@378bf509], House@6d03e736 -] -*/ diff --git a/code/serialization/People.java b/code/serialization/People.java deleted file mode 100644 index 0e588749..00000000 --- a/code/serialization/People.java +++ /dev/null @@ -1,28 +0,0 @@ -// serialization/People.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// nu.xom.Node comes from http://www.xom.nu -// {RunFirst: APerson} -import nu.xom.*; -import java.io.File; -import java.util.*; - -public class People extends ArrayList { - public People(String fileName) throws Exception { - Document doc = - new Builder().build(new File(fileName)); - Elements elements = - doc.getRootElement().getChildElements(); - for(int i = 0; i < elements.size(); i++) - add(new APerson(elements.get(i))); - } - public static void - main(String[] args) throws Exception { - People p = new People("People.xml"); - System.out.println(p); - } -} -/* Output: -[Dr. Bunsen Honeydew, Gonzo The Great, Phillip J. Fry] -*/ diff --git a/code/serialization/RecoverCADState.java b/code/serialization/RecoverCADState.java deleted file mode 100644 index 612f501c..00000000 --- a/code/serialization/RecoverCADState.java +++ /dev/null @@ -1,42 +0,0 @@ -// serialization/RecoverCADState.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Restoring the state of the fictitious CAD system -// {RunFirst: AStoreCADState} -import java.io.*; -import java.util.*; - -public class RecoverCADState { - @SuppressWarnings("unchecked") - public static void main(String[] args) { - try( - ObjectInputStream in = - new ObjectInputStream( - new FileInputStream("CADState.dat")) - ) { - // Read in the same order they were written: - List> shapeTypes = - (List>)in.readObject(); - Line.deserializeStaticState(in); - List shapes = - (List)in.readObject(); - System.out.println(shapes); - } catch(IOException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - } -} -/* Output: -[class Circlecolor[RED] xPos[58] yPos[55] dim[93] -, class Squarecolor[RED] xPos[61] yPos[61] dim[29] -, class Linecolor[GREEN] xPos[68] yPos[0] dim[22] -, class Circlecolor[RED] xPos[7] yPos[88] dim[28] -, class Squarecolor[RED] xPos[51] yPos[89] dim[9] -, class Linecolor[GREEN] xPos[78] yPos[98] dim[61] -, class Circlecolor[RED] xPos[20] yPos[58] dim[16] -, class Squarecolor[RED] xPos[40] yPos[11] dim[22] -, class Linecolor[GREEN] xPos[4] yPos[83] dim[6] -, class Circlecolor[RED] xPos[75] yPos[10] dim[42] -] -*/ diff --git a/code/serialization/SerialCtl.java b/code/serialization/SerialCtl.java deleted file mode 100644 index ed891633..00000000 --- a/code/serialization/SerialCtl.java +++ /dev/null @@ -1,60 +0,0 @@ -// serialization/SerialCtl.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Controlling serialization by adding your own -// writeObject() and readObject() methods -import java.io.*; - -public class SerialCtl implements Serializable { - private String a; - private transient String b; - public SerialCtl(String aa, String bb) { - a = "Not Transient: " + aa; - b = "Transient: " + bb; - } - @Override - public String toString() { return a + "\n" + b; } - private void writeObject(ObjectOutputStream stream) - throws IOException { - stream.defaultWriteObject(); - stream.writeObject(b); - } - private void readObject(ObjectInputStream stream) - throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - b = (String)stream.readObject(); - } - public static void main(String[] args) { - SerialCtl sc = new SerialCtl("Test1", "Test2"); - System.out.println("Before:\n" + sc); - try ( - ByteArrayOutputStream buf = - new ByteArrayOutputStream(); - ObjectOutputStream o = - new ObjectOutputStream(buf); - ) { - o.writeObject(sc); - // Now get it back: - try ( - ObjectInputStream in = - new ObjectInputStream( - new ByteArrayInputStream( - buf.toByteArray())); - ) { - SerialCtl sc2 = (SerialCtl)in.readObject(); - System.out.println("After:\n" + sc2); - } - } catch(IOException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - } -} -/* Output: -Before: -Not Transient: Test1 -Transient: Test2 -After: -Not Transient: Test1 -Transient: Test2 -*/ diff --git a/code/serialization/Worm.java b/code/serialization/Worm.java deleted file mode 100644 index 666beb87..00000000 --- a/code/serialization/Worm.java +++ /dev/null @@ -1,102 +0,0 @@ -// serialization/Worm.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates object serialization -import java.io.*; -import java.util.*; - -class Data implements Serializable { - private int n; - Data(int n) { this.n = n; } - @Override - public String toString() { - return Integer.toString(n); - } -} - -public class Worm implements Serializable { - private static Random rand = new Random(47); - private Data[] d = { - new Data(rand.nextInt(10)), - new Data(rand.nextInt(10)), - new Data(rand.nextInt(10)) - }; - private Worm next; - private char c; - // Value of i == number of segments - public Worm(int i, char x) { - System.out.println("Worm constructor: " + i); - c = x; - if(--i > 0) - next = new Worm(i, (char)(x + 1)); - } - public Worm() { - System.out.println("No-arg constructor"); - } - @Override - public String toString() { - StringBuilder result = new StringBuilder(":"); - result.append(c); - result.append("("); - for(Data dat : d) - result.append(dat); - result.append(")"); - if(next != null) - result.append(next); - return result.toString(); - } - public static void - main(String[] args) throws ClassNotFoundException, - IOException { - Worm w = new Worm(6, 'a'); - System.out.println("w = " + w); - try( - ObjectOutputStream out = new ObjectOutputStream( - new FileOutputStream("worm.dat")) - ) { - out.writeObject("Worm storage\n"); - out.writeObject(w); - } - try( - ObjectInputStream in = new ObjectInputStream( - new FileInputStream("worm.dat")) - ) { - String s = (String)in.readObject(); - Worm w2 = (Worm)in.readObject(); - System.out.println(s + "w2 = " + w2); - } - try( - ByteArrayOutputStream bout = - new ByteArrayOutputStream(); - ObjectOutputStream out2 = - new ObjectOutputStream(bout) - ) { - out2.writeObject("Worm storage\n"); - out2.writeObject(w); - out2.flush(); - try( - ObjectInputStream in2 = new ObjectInputStream( - new ByteArrayInputStream( - bout.toByteArray())) - ) { - String s = (String)in2.readObject(); - Worm w3 = (Worm)in2.readObject(); - System.out.println(s + "w3 = " + w3); - } - } - } -} -/* Output: -Worm constructor: 6 -Worm constructor: 5 -Worm constructor: 4 -Worm constructor: 3 -Worm constructor: 2 -Worm constructor: 1 -w = :a(853):b(119):c(802):d(788):e(199):f(881) -Worm storage -w2 = :a(853):b(119):c(802):d(788):e(199):f(881) -Worm storage -w3 = :a(853):b(119):c(802):d(788):e(199):f(881) -*/ diff --git a/code/serialization/xfiles/ThawAlien.java b/code/serialization/xfiles/ThawAlien.java deleted file mode 100644 index 1de6ce6a..00000000 --- a/code/serialization/xfiles/ThawAlien.java +++ /dev/null @@ -1,22 +0,0 @@ -// serialization/xfiles/ThawAlien.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Recover a serialized file -// {java serialization.xfiles.ThawAlien} -// {RunFirst: FreezeAlien} -package serialization.xfiles; -import java.io.*; - -public class ThawAlien { - public static void - main(String[] args) throws Exception { - ObjectInputStream in = new ObjectInputStream( - new FileInputStream(new File("X.file"))); - Object mystery = in.readObject(); - System.out.println(mystery.getClass()); - } -} -/* Output: -class Alien -*/ diff --git a/code/settings.gradle b/code/settings.gradle deleted file mode 100644 index 376ca105..00000000 --- a/code/settings.gradle +++ /dev/null @@ -1,13 +0,0 @@ -def isSubproject = { File file -> - file.isDirectory() && - !file.name.contains('.git') && - !file.name.contains('.gradle') && - !file.name.contains('.idea') && - !file.name.contains('build') && - !file.name.contains('gradle') && - !file.name.contains('test') -} - -String[] subprojects = rootDir.listFiles().findAll(isSubproject).collect { it.name } - -include subprojects diff --git a/code/standardio/ChangeSystemOut.java b/code/standardio/ChangeSystemOut.java deleted file mode 100644 index 2b37acb8..00000000 --- a/code/standardio/ChangeSystemOut.java +++ /dev/null @@ -1,17 +0,0 @@ -// standardio/ChangeSystemOut.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Turn System.out into a PrintWriter -import java.io.*; - -public class ChangeSystemOut { - public static void main(String[] args) { - PrintWriter out = - new PrintWriter(System.out, true); - out.println("Hello, world"); - } -} -/* Output: -Hello, world -*/ diff --git a/code/standardio/Echo.java b/code/standardio/Echo.java deleted file mode 100644 index d1a6103e..00000000 --- a/code/standardio/Echo.java +++ /dev/null @@ -1,20 +0,0 @@ -// standardio/Echo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// How to read from standard input -import java.io.*; -import onjava.TimedAbort; - -public class Echo { - public static void main(String[] args) { - TimedAbort abort = new TimedAbort(2); - new BufferedReader( - new InputStreamReader(System.in)) - .lines() - .peek(ln -> abort.restart()) - .forEach(System.out::println); - // Ctrl-Z or two seconds inactivity - // terminates the program - } -} diff --git a/code/standardio/OSExecuteDemo.java b/code/standardio/OSExecuteDemo.java deleted file mode 100644 index cc2fd4b0..00000000 --- a/code/standardio/OSExecuteDemo.java +++ /dev/null @@ -1,16 +0,0 @@ -// standardio/OSExecuteDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates standard I/O redirection -// javap -cp build/classes/java/main OSExecuteDemo -// {ExcludeFromGradle} -import onjava.*; - -public class OSExecuteDemo {} -/* Output: -Compiled from "OSExecuteDemo.java" -public class OSExecuteDemo { - public OSExecuteDemo(); -} -*/ diff --git a/code/standardio/Redirecting.java b/code/standardio/Redirecting.java deleted file mode 100644 index c2986a2b..00000000 --- a/code/standardio/Redirecting.java +++ /dev/null @@ -1,31 +0,0 @@ -// standardio/Redirecting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates standard I/O redirection -import java.io.*; - -public class Redirecting { - public static void main(String[] args) { - PrintStream console = System.out; - try( - BufferedInputStream in = new BufferedInputStream( - new FileInputStream("Redirecting.java")); - PrintStream out = new PrintStream( - new BufferedOutputStream( - new FileOutputStream("Redirecting.txt"))) - ) { - System.setIn(in); - System.setOut(out); - System.setErr(out); - new BufferedReader( - new InputStreamReader(System.in)) - .lines() - .forEach(System.out::println); - } catch(IOException e) { - throw new RuntimeException(e); - } finally { - System.setOut(console); - } - } -} diff --git a/code/staticchecking/DogsAndRobots.cpp b/code/staticchecking/DogsAndRobots.cpp deleted file mode 100644 index 03b69a96..00000000 --- a/code/staticchecking/DogsAndRobots.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// staticchecking/DogsAndRobots.cpp -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -#include -using namespace std; - -class Dog { -public: - void talk() { cout << "Arf!" << endl; } - void reproduce() {} -}; - -class Robot { -public: - void talk() { cout << "Click!" << endl; } - void oilChange() {} -}; - -template void speak(T speaker) { - speaker.talk(); -} - -int main() { - Dog d; - Robot r; - speak(d); - speak(r); -} -/* Output: -Arf! -Click! -*/ diff --git a/code/staticchecking/DogsAndRobots.py b/code/staticchecking/DogsAndRobots.py deleted file mode 100644 index a6b239da..00000000 --- a/code/staticchecking/DogsAndRobots.py +++ /dev/null @@ -1,26 +0,0 @@ -# staticchecking/DogsAndRobots.py -# (c)2020 MindView LLC: see Copyright.txt -# We make no guarantees that this code is fit for any purpose. -# Visit http://OnJava8.com for more book information. - -def speak(anything): - anything.talk() - -class Dog: - def talk(self): print("Arf!") - def reproduce(self): pass - -class Robot: - def talk(self): print("Click!") - def oilChange(self): pass - -a = Dog() -b = Robot() - -speak(a) -speak(b) - -output = """ -Arf! -Click! -""" diff --git a/code/staticchecking/NoBasePetSpeak.py b/code/staticchecking/NoBasePetSpeak.py deleted file mode 100644 index cbe6c82b..00000000 --- a/code/staticchecking/NoBasePetSpeak.py +++ /dev/null @@ -1,35 +0,0 @@ -# staticchecking/NoBasePetSpeak.py -# (c)2020 MindView LLC: see Copyright.txt -# We make no guarantees that this code is fit for any purpose. -# Visit http://OnJava8.com for more book information. -#- Speaking pets without base classes - -class Cat: - def speak(self): - print("meow!") - -class Dog: - def speak(self): - print("woof!") - -class Bob: - def bow(self): - print("thank you, thank you!") - def speak(self): - print("Welcome to the neighborhood!") - def drive(self): - print("beep, beep!") - -def command(pet): - pet.speak() - -pets = [ Cat(), Dog(), Bob() ] - -for pet in pets: - command(pet) - -output = """ -meow! -woof! -Welcome to the neighborhood! -""" diff --git a/code/staticchecking/PetSpeak.py b/code/staticchecking/PetSpeak.py deleted file mode 100644 index e3734e2f..00000000 --- a/code/staticchecking/PetSpeak.py +++ /dev/null @@ -1,28 +0,0 @@ -# staticchecking/PetSpeak.py -# (c)2020 MindView LLC: see Copyright.txt -# We make no guarantees that this code is fit for any purpose. -# Visit http://OnJava8.com for more book information. -#- Speaking pets in Python - -class Pet: - def speak(self): pass - -class Cat(Pet): - def speak(self): - print("meow!") - -class Dog(Pet): - def speak(self): - print("woof!") - -def command(pet): - pet.speak() - -pets = [ Cat(), Dog() ] # (1) -for pet in pets: # (2) - command(pet) - -output = """ -meow! -woof! -""" diff --git a/code/staticchecking/dogsandrobots.go b/code/staticchecking/dogsandrobots.go deleted file mode 100644 index d3dd10cb..00000000 --- a/code/staticchecking/dogsandrobots.go +++ /dev/null @@ -1,27 +0,0 @@ -// staticchecking/dogsandrobots.go -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package main -import "fmt" - -type Dog struct {} -func (this Dog) talk() { fmt.Printf("woof!\n")} -func (this Dog) reproduce() {} - -type Robot struct {} -func (this Robot) talk() { fmt.Printf("Click!\n") } -func (this Robot) oilChange() {} - -func speak(speaker interface { talk() }) { - speaker.talk(); -} - -func main() { - speak(Dog{}) - speak(Robot{}) -} -/* Output: -woof! -Click! -*/ diff --git a/code/staticchecking/dr/DogsAndRobots.java b/code/staticchecking/dr/DogsAndRobots.java deleted file mode 100644 index 9bede804..00000000 --- a/code/staticchecking/dr/DogsAndRobots.java +++ /dev/null @@ -1,42 +0,0 @@ -// staticchecking/dr/DogsAndRobots.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java staticchecking.dr.DogsAndRobots} -package staticchecking.dr; - -interface Speaks { void talk(); } - -class Dog implements Speaks { - public void talk() { - System.out.println("Woof!"); - } - public void reproduce() { } -} - -class Robot implements Speaks { - public void talk() { - System.out.println("Click!"); - } - public void oilChange() { } -} - -class Communicate { - public static - void speak(T speaker) { - speaker.talk(); - } -} - -public class DogsAndRobots { - public static void main(String[] args) { - Dog d = new Dog(); - Robot r = new Robot(); - Communicate.speak(d); - Communicate.speak(r); - } -} -/* Output: -Woof! -Click! -*/ diff --git a/code/staticchecking/drc/DogAndRobotCollections.java b/code/staticchecking/drc/DogAndRobotCollections.java deleted file mode 100644 index 16a82ed5..00000000 --- a/code/staticchecking/drc/DogAndRobotCollections.java +++ /dev/null @@ -1,58 +0,0 @@ -// staticchecking/drc/DogAndRobotCollections.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java staticchecking.drc.DogAndRobotCollections} -package staticchecking.drc; -import java.util.*; - -class Dog { - public void talk() { - System.out.println("Woof!"); - } - public void reproduce() { } -} - -class Robot { - public void talk() { - System.out.println("Click!"); - } - public void oilChange() { } -} - -public class DogAndRobotCollections { - public static void main(String[] args) { - List dogList = new ArrayList<>(); - List robotList = new ArrayList<>(); - for(int i = 0; i < 10; i++) - dogList.add(new Dog()); - //- dogList.add(new Robot()); // Compile-time error - for(int i = 0; i < 10; i++) - robotList.add(new Robot()); - //- robotList.add(new Dog()); // Compile-time error - dogList.forEach(Dog::talk); - robotList.forEach(Robot::talk); - } -} -/* Output: -Woof! -Woof! -Woof! -Woof! -Woof! -Woof! -Woof! -Woof! -Woof! -Woof! -Click! -Click! -Click! -Click! -Click! -Click! -Click! -Click! -Click! -Click! -*/ diff --git a/code/staticchecking/latent/Latent.java b/code/staticchecking/latent/Latent.java deleted file mode 100644 index 29e53713..00000000 --- a/code/staticchecking/latent/Latent.java +++ /dev/null @@ -1,60 +0,0 @@ -// staticchecking/latent/Latent.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java staticchecking.latent.Latent} -package staticchecking.latent; -import java.lang.reflect.*; - -class Dog { - public void talk() { - System.out.println("Woof!"); - } - public void reproduce() {} -} - -class Robot { - public void talk() { - System.out.println("Click!"); - } - public void oilChange() {} -} - -class Mime { - public void walkAgainstTheWind() {} - public String toString() { return "Mime"; } -} - -class Communicate { - public static void speak(Object speaker) { - try { - Class spkr = - speaker.getClass(); - Method talk = - spkr.getMethod("talk", (Class[])null); - talk.invoke(speaker, new Object[]{}); - } catch(NoSuchMethodException e) { - System.out.println( - speaker + " cannot talk"); - } catch(IllegalAccessException e) { - System.out.println( - speaker + " IllegalAccessException"); - } catch(InvocationTargetException e) { - System.out.println( - speaker + " InvocationTargetException"); - } - } -} - -public class Latent { - public static void main(String[] args) { - Communicate.speak(new Dog()); - Communicate.speak(new Robot()); - Communicate.speak(new Mime()); - } -} -/* Output: -Woof! -Click! -Mime cannot talk -*/ diff --git a/code/staticchecking/petspeak.go b/code/staticchecking/petspeak.go deleted file mode 100644 index 1d5c5e46..00000000 --- a/code/staticchecking/petspeak.go +++ /dev/null @@ -1,51 +0,0 @@ -// staticchecking/petspeak.go -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package main -import "fmt" - -type Cat struct {} -func (this Cat) speak() { fmt.Printf("meow!\n")} - -type Dog struct {} -func (this Dog) speak() { fmt.Printf("woof!\n")} - -type Bob struct {} -func (this Bob) bow() { - fmt.Printf("thank you, thank you!\n") -} -func (this Bob) speak() { - fmt.Printf("Welcome to the neighborhood!\n") -} -func (this Bob) drive() { - fmt.Printf("beep, beep!\n") -} - -type Speaker interface { - speak() -} - -func command(s Speaker) { s.speak() } - -// If "Speaker" is never used -// anywhere else, it can be anonymous: -func command2(s interface { speak() }) { s.speak() } - -func main() { - command(Cat{}) - command(Dog{}) - command(Bob{}) - command2(Cat{}) - command2(Dog{}) - command2(Bob{}) -} - -/* Output: -meow! -woof! -Welcome to the neighborhood! -meow! -woof! -Welcome to the neighborhood! -*/ diff --git a/code/staticchecking/petspeak/PetSpeak.java b/code/staticchecking/petspeak/PetSpeak.java deleted file mode 100644 index 0b850c3b..00000000 --- a/code/staticchecking/petspeak/PetSpeak.java +++ /dev/null @@ -1,36 +0,0 @@ -// staticchecking/petspeak/PetSpeak.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Speaking pets in Java -// {java staticchecking.petspeak.PetSpeak} -package staticchecking.petspeak; - -interface Pet { - void speak(); -} - -class Cat implements Pet { - public void speak() { - System.out.println("meow!"); - } -} - -class Dog implements Pet { - public void speak() { - System.out.println("woof!"); - } -} - -public class PetSpeak { - static void command(Pet p) { p.speak(); } - public static void main(String[] args) { - Pet[] pets = { new Cat(), new Dog() }; - for(Pet pet : pets) - command(pet); - } -} -/* Output: -meow! -woof! -*/ diff --git a/code/streams/ArrayStreams.java b/code/streams/ArrayStreams.java deleted file mode 100644 index dfed6e83..00000000 --- a/code/streams/ArrayStreams.java +++ /dev/null @@ -1,31 +0,0 @@ -// streams/ArrayStreams.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class ArrayStreams { - public static void main(String[] args) { - Arrays.stream( - new double[] { 3.14159, 2.718, 1.618 }) - .forEach(n -> System.out.format("%f ", n)); - System.out.println(); - Arrays.stream(new int[] { 1, 3, 5 }) - .forEach(n -> System.out.format("%d ", n)); - System.out.println(); - Arrays.stream(new long[] { 11, 22, 44, 66 }) - .forEach(n -> System.out.format("%d ", n)); - System.out.println(); - // Select a subrange: - Arrays.stream( - new int[] { 1, 3, 5, 7, 15, 28, 37 }, 3, 6) - .forEach(n -> System.out.format("%d ", n)); - } -} -/* Output: -3.141590 2.718000 1.618000 -1 3 5 -11 22 44 66 -7 15 28 -*/ diff --git a/code/streams/Bubble.java b/code/streams/Bubble.java deleted file mode 100644 index 5650e5ae..00000000 --- a/code/streams/Bubble.java +++ /dev/null @@ -1,18 +0,0 @@ -// streams/Bubble.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class Bubble { - public final int i; - public Bubble(int n) { i = n; } - @Override - public String toString() { - return "Bubble(" + i + ")"; - } - private static int count = 0; - public static Bubble bubbler() { - return new Bubble(count++); - } -} diff --git a/code/streams/Bubbles.java b/code/streams/Bubbles.java deleted file mode 100644 index 1b3bd2b9..00000000 --- a/code/streams/Bubbles.java +++ /dev/null @@ -1,20 +0,0 @@ -// streams/Bubbles.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public class Bubbles { - public static void main(String[] args) { - Stream.generate(Bubble::bubbler) - .limit(5) - .forEach(System.out::println); - } -} -/* Output: -Bubble(0) -Bubble(1) -Bubble(2) -Bubble(3) -Bubble(4) -*/ diff --git a/code/streams/Cheese.dat b/code/streams/Cheese.dat deleted file mode 100644 index 936666ed..00000000 --- a/code/streams/Cheese.dat +++ /dev/null @@ -1,6 +0,0 @@ -// streams/Cheese.dat -Not much of a cheese shop really, is it? -Finest in the district, sir. -And what leads you to that conclusion? -Well, it's so clean. -It's certainly uncontaminated by cheese. diff --git a/code/streams/CollectionToStream.java b/code/streams/CollectionToStream.java deleted file mode 100644 index 93236ef1..00000000 --- a/code/streams/CollectionToStream.java +++ /dev/null @@ -1,39 +0,0 @@ -// streams/CollectionToStream.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class CollectionToStream { - public static void main(String[] args) { - List bubbles = Arrays.asList( - new Bubble(1), new Bubble(2), new Bubble(3)); - System.out.println( - bubbles.stream() - .mapToInt(b -> b.i) - .sum()); - - Set w = new HashSet<>(Arrays.asList( - "It's a wonderful day for pie!".split(" "))); - w.stream() - .map(x -> x + " ") - .forEach(System.out::print); - System.out.println(); - - Map m = new HashMap<>(); - m.put("pi", 3.14159); - m.put("e", 2.718); - m.put("phi", 1.618); - m.entrySet().stream() - .map(e -> e.getKey() + ": " + e.getValue()) - .forEach(System.out::println); - } -} -/* Output: -6 -a pie! It's for wonderful day -phi: 1.618 -e: 2.718 -pi: 3.14159 -*/ diff --git a/code/streams/CreatingOptionals.java b/code/streams/CreatingOptionals.java deleted file mode 100644 index 7e886ddc..00000000 --- a/code/streams/CreatingOptionals.java +++ /dev/null @@ -1,37 +0,0 @@ -// streams/CreatingOptionals.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; - -class CreatingOptionals { - static void - test(String testName, Optional opt) { - System.out.println(" === " + testName + " === "); - System.out.println(opt.orElse("Null")); - } - public static void main(String[] args) { - test("empty", Optional.empty()); - test("of", Optional.of("Howdy")); - try { - test("of", Optional.of(null)); - } catch(Exception e) { - System.out.println(e); - } - test("ofNullable", Optional.ofNullable("Hi")); - test("ofNullable", Optional.ofNullable(null)); - } -} -/* Output: - === empty === -Null - === of === -Howdy -java.lang.NullPointerException - === ofNullable === -Hi - === ofNullable === -Null -*/ diff --git a/code/streams/Duplicator.java b/code/streams/Duplicator.java deleted file mode 100644 index 267279c7..00000000 --- a/code/streams/Duplicator.java +++ /dev/null @@ -1,18 +0,0 @@ -// streams/Duplicator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public class Duplicator { - public static void main(String[] args) { - Stream.generate(() -> "duplicate") - .limit(3) - .forEach(System.out::println); - } -} -/* Output: -duplicate -duplicate -duplicate -*/ diff --git a/code/streams/Fibonacci.java b/code/streams/Fibonacci.java deleted file mode 100644 index fa53c687..00000000 --- a/code/streams/Fibonacci.java +++ /dev/null @@ -1,34 +0,0 @@ -// streams/Fibonacci.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public class Fibonacci { - int x = 1; - Stream numbers() { - return Stream.iterate(0, i -> { - int result = x + i; - x = i; - return result; - }); - } - public static void main(String[] args) { - new Fibonacci().numbers() - .skip(20) // Don't use the first 20 - .limit(10) // Then take 10 of them - .forEach(System.out::println); - } -} -/* Output: -6765 -10946 -17711 -28657 -46368 -75025 -121393 -196418 -317811 -514229 -*/ diff --git a/code/streams/FileToWords.java b/code/streams/FileToWords.java deleted file mode 100644 index 7f7174cb..00000000 --- a/code/streams/FileToWords.java +++ /dev/null @@ -1,17 +0,0 @@ -// streams/FileToWords.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.nio.file.*; -import java.util.stream.*; -import java.util.regex.Pattern; - -public class FileToWords { - public static Stream stream(String filePath) - throws Exception { - return Files.lines(Paths.get(filePath)) - .skip(1) // First (comment) line - .flatMap(line -> - Pattern.compile("\\W+").splitAsStream(line)); - } -} diff --git a/code/streams/FileToWordsBuilder.java b/code/streams/FileToWordsBuilder.java deleted file mode 100644 index d5ac62be..00000000 --- a/code/streams/FileToWordsBuilder.java +++ /dev/null @@ -1,31 +0,0 @@ -// streams/FileToWordsBuilder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.nio.file.*; -import java.util.stream.*; - -public class FileToWordsBuilder { - Stream.Builder builder = Stream.builder(); - public FileToWordsBuilder(String filePath) - throws Exception { - Files.lines(Paths.get(filePath)) - .skip(1) // Skip the comment line at the beginning - .forEach(line -> { - for(String w : line.split("[ .?,]+")) - builder.add(w); - }); - } - Stream stream() { return builder.build(); } - public static void - main(String[] args) throws Exception { - new FileToWordsBuilder("Cheese.dat").stream() - .limit(7) - .map(w -> w + " ") - .forEach(System.out::print); - } -} -/* Output: -Not much of a cheese shop really -*/ diff --git a/code/streams/FileToWordsRegexp.java b/code/streams/FileToWordsRegexp.java deleted file mode 100644 index dfff507e..00000000 --- a/code/streams/FileToWordsRegexp.java +++ /dev/null @@ -1,39 +0,0 @@ -// streams/FileToWordsRegexp.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.nio.file.*; -import java.util.stream.*; -import java.util.regex.Pattern; - -public class FileToWordsRegexp { - private String all; - public FileToWordsRegexp(String filePath) - throws Exception { - all = Files.lines(Paths.get(filePath)) - .skip(1) // First (comment) line - .collect(Collectors.joining(" ")); - } - public Stream stream() { - return Pattern - .compile("[ .,?]+").splitAsStream(all); - } - public static void - main(String[] args) throws Exception { - FileToWordsRegexp fw = - new FileToWordsRegexp("Cheese.dat"); - fw.stream() - .limit(7) - .map(w -> w + " ") - .forEach(System.out::print); - fw.stream() - .skip(7) - .limit(2) - .map(w -> w + " ") - .forEach(System.out::print); - } -} -/* Output: -Not much of a cheese shop really is it -*/ diff --git a/code/streams/FileToWordsTest.java b/code/streams/FileToWordsTest.java deleted file mode 100644 index a81f7209..00000000 --- a/code/streams/FileToWordsTest.java +++ /dev/null @@ -1,23 +0,0 @@ -// streams/FileToWordsTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public class FileToWordsTest { - public static void - main(String[] args) throws Exception { - FileToWords.stream("Cheese.dat") - .limit(7) - .forEach(s -> System.out.format("%s ", s)); - System.out.println(); - FileToWords.stream("Cheese.dat") - .skip(7) - .limit(2) - .forEach(s -> System.out.format("%s ", s)); - } -} -/* Output: -Not much of a cheese shop really -is it -*/ diff --git a/code/streams/FlatMap.java b/code/streams/FlatMap.java deleted file mode 100644 index e2b3137f..00000000 --- a/code/streams/FlatMap.java +++ /dev/null @@ -1,25 +0,0 @@ -// streams/FlatMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public class FlatMap { - public static void main(String[] args) { - Stream.of(1, 2, 3) - .flatMap( - i -> Stream.of("Gonzo", "Fozzie", "Beaker")) - .forEach(System.out::println); - } -} -/* Output: -Gonzo -Fozzie -Beaker -Gonzo -Fozzie -Beaker -Gonzo -Fozzie -Beaker -*/ diff --git a/code/streams/ForEach.java b/code/streams/ForEach.java deleted file mode 100644 index f0abe255..00000000 --- a/code/streams/ForEach.java +++ /dev/null @@ -1,28 +0,0 @@ -// streams/ForEach.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import static streams.RandInts.*; - -public class ForEach { - static final int SZ = 14; - public static void main(String[] args) { - rands().limit(SZ) - .forEach(n -> System.out.format("%d ", n)); - System.out.println(); - rands().limit(SZ) - .parallel() - .forEach(n -> System.out.format("%d ", n)); - System.out.println(); - rands().limit(SZ) - .parallel() - .forEachOrdered(n -> System.out.format("%d ", n)); - } -} -/* Output: -258 555 693 861 961 429 868 200 522 207 288 128 551 589 -551 861 429 589 200 522 555 693 258 128 868 288 961 207 -258 555 693 861 961 429 868 200 522 207 288 128 551 589 -*/ diff --git a/code/streams/FunctionMap.java b/code/streams/FunctionMap.java deleted file mode 100644 index 3c7c90e7..00000000 --- a/code/streams/FunctionMap.java +++ /dev/null @@ -1,60 +0,0 @@ -// streams/FunctionMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; - -class FunctionMap { - static String[] elements = { "12", "", "23", "45" }; - static Stream testStream() { - return Arrays.stream(elements); - } - static void - test(String descr, Function func) { - System.out.println(" ---( " + descr + " )---"); - testStream() - .map(func) - .forEach(System.out::println); - } - public static void main(String[] args) { - - test("add brackets", s -> "[" + s + "]"); - - test("Increment", s -> { - try { - return Integer.parseInt(s) + 1 + ""; - } catch(NumberFormatException e) { - return s; - } - }); - - test("Replace", s -> s.replace("2", "9")); - - test("Take last digit", s -> s.length() > 0 ? - s.charAt(s.length() - 1) + "" : s); - } -} -/* Output: - ---( add brackets )--- -[12] -[] -[23] -[45] - ---( Increment )--- -13 - -24 -46 - ---( Replace )--- -19 - -93 -45 - ---( Take last digit )--- -2 - -3 -5 -*/ diff --git a/code/streams/FunctionMap2.java b/code/streams/FunctionMap2.java deleted file mode 100644 index 4d9f2972..00000000 --- a/code/streams/FunctionMap2.java +++ /dev/null @@ -1,32 +0,0 @@ -// streams/FunctionMap2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Different input and output types -import java.util.*; -import java.util.stream.*; - -class Numbered { - final int n; - Numbered(int n) { this.n = n; } - @Override - public String toString() { - return "Numbered(" + n + ")"; - } -} - -class FunctionMap2 { - public static void main(String[] args) { - Stream.of(1, 5, 7, 9, 11, 13) - .map(Numbered::new) - .forEach(System.out::println); - } -} -/* Output: -Numbered(1) -Numbered(5) -Numbered(7) -Numbered(9) -Numbered(11) -Numbered(13) -*/ diff --git a/code/streams/FunctionMap3.java b/code/streams/FunctionMap3.java deleted file mode 100644 index 74236af3..00000000 --- a/code/streams/FunctionMap3.java +++ /dev/null @@ -1,28 +0,0 @@ -// streams/FunctionMap3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Producing numeric output streams -import java.util.*; -import java.util.stream.*; - -class FunctionMap3 { - public static void main(String[] args) { - Stream.of("5", "7", "9") - .mapToInt(Integer::parseInt) - .forEach(n -> System.out.format("%d ", n)); - System.out.println(); - Stream.of("17", "19", "23") - .mapToLong(Long::parseLong) - .forEach(n -> System.out.format("%d ", n)); - System.out.println(); - Stream.of("17", "1.9", ".23") - .mapToDouble(Double::parseDouble) - .forEach(n -> System.out.format("%f ", n)); - } -} -/* Output: -5 7 9 -17 19 23 -17.000000 1.900000 0.230000 -*/ diff --git a/code/streams/Generator.java b/code/streams/Generator.java deleted file mode 100644 index c9aba740..00000000 --- a/code/streams/Generator.java +++ /dev/null @@ -1,25 +0,0 @@ -// streams/Generator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -public class Generator implements Supplier { - Random rand = new Random(47); - char[] letters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); - public String get() { - return "" + letters[rand.nextInt(letters.length)]; - } - public static void main(String[] args) { - String word = Stream.generate(new Generator()) - .limit(30) - .collect(Collectors.joining()); - System.out.println(word); - } -} -/* Output: -YNZBRNYGCFOWZNTCQRGSEGZMMJMROE -*/ diff --git a/code/streams/ImperativeRandoms.java b/code/streams/ImperativeRandoms.java deleted file mode 100644 index f9baaca5..00000000 --- a/code/streams/ImperativeRandoms.java +++ /dev/null @@ -1,21 +0,0 @@ -// streams/ImperativeRandoms.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ImperativeRandoms { - public static void main(String[] args) { - Random rand = new Random(47); - SortedSet rints = new TreeSet<>(); - while(rints.size() < 7) { - int r = rand.nextInt(20); - if(r < 5) continue; - rints.add(r); - } - System.out.println(rints); - } -} -/* Output: -[7, 8, 9, 11, 13, 15, 18] -*/ diff --git a/code/streams/Informational.java b/code/streams/Informational.java deleted file mode 100644 index dd80585c..00000000 --- a/code/streams/Informational.java +++ /dev/null @@ -1,27 +0,0 @@ -// streams/Informational.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; -import java.util.function.*; - -public class Informational { - public static void - main(String[] args) throws Exception { - System.out.println( - FileToWords.stream("Cheese.dat").count()); - System.out.println( - FileToWords.stream("Cheese.dat") - .min(String.CASE_INSENSITIVE_ORDER) - .orElse("NONE")); - System.out.println( - FileToWords.stream("Cheese.dat") - .max(String.CASE_INSENSITIVE_ORDER) - .orElse("NONE")); - } -} -/* Output: -32 -a -you -*/ diff --git a/code/streams/LastElement.java b/code/streams/LastElement.java deleted file mode 100644 index 398b0488..00000000 --- a/code/streams/LastElement.java +++ /dev/null @@ -1,24 +0,0 @@ -// streams/LastElement.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class LastElement { - public static void main(String[] args) { - OptionalInt last = IntStream.range(10, 20) - .reduce((n1, n2) -> n2); - System.out.println(last.orElse(-1)); - // Non-numeric object: - Optional lastobj = - Stream.of("one", "two", "three") - .reduce((n1, n2) -> n2); - System.out.println( - lastobj.orElse("Nothing there!")); - } -} -/* Output: -19 -three -*/ diff --git a/code/streams/Looping.java b/code/streams/Looping.java deleted file mode 100644 index 715ad052..00000000 --- a/code/streams/Looping.java +++ /dev/null @@ -1,20 +0,0 @@ -// streams/Looping.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import static onjava.Repeat.*; - -public class Looping { - static void hi() { System.out.println("Hi!"); } - public static void main(String[] args) { - repeat(3, () -> System.out.println("Looping!")); - repeat(2, Looping::hi); - } -} -/* Output: -Looping! -Looping! -Looping! -Hi! -Hi! -*/ diff --git a/code/streams/Machine2.java b/code/streams/Machine2.java deleted file mode 100644 index 3d407185..00000000 --- a/code/streams/Machine2.java +++ /dev/null @@ -1,23 +0,0 @@ -// streams/Machine2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import onjava.Operations; - -public class Machine2 { - public static void main(String[] args) { - Arrays.stream(new Operations[] { - () -> Operations.show("Bing"), - () -> Operations.show("Crack"), - () -> Operations.show("Twist"), - () -> Operations.show("Pop") - }).forEach(Operations::execute); - } -} -/* Output: -Bing -Crack -Twist -Pop -*/ diff --git a/code/streams/MapCollector.java b/code/streams/MapCollector.java deleted file mode 100644 index 95811e4b..00000000 --- a/code/streams/MapCollector.java +++ /dev/null @@ -1,48 +0,0 @@ -// streams/MapCollector.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -class Pair { - public final Character c; - public final Integer i; - Pair(Character c, Integer i) { - this.c = c; - this.i = i; - } - public Character getC() { return c; } - public Integer getI() { return i; } - @Override - public String toString() { - return "Pair(" + c + ", " + i + ")"; - } -} - -class RandomPair { - Random rand = new Random(47); - // An infinite iterator of random capital letters: - Iterator capChars = rand.ints(65,91) - .mapToObj(i -> (char)i) - .iterator(); - public Stream stream() { - return rand.ints(100, 1000).distinct() - .mapToObj(i -> new Pair(capChars.next(), i)); - } -} - -public class MapCollector { - public static void main(String[] args) { - Map map = - new RandomPair().stream() - .limit(8) - .collect( - Collectors.toMap(Pair::getI, Pair::getC)); - System.out.println(map); - } -} -/* Output: -{688=W, 309=C, 293=B, 761=N, 858=N, 668=G, 622=F, -751=N} -*/ diff --git a/code/streams/Matching.java b/code/streams/Matching.java deleted file mode 100644 index f5c01bc6..00000000 --- a/code/streams/Matching.java +++ /dev/null @@ -1,38 +0,0 @@ -// streams/Matching.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrates short-circuiting of *Match() operations -import java.util.stream.*; -import java.util.function.*; -import static streams.RandInts.*; - -interface Matcher extends - BiPredicate, Predicate> {} - -public class Matching { - static void show(Matcher match, int val) { - System.out.println( - match.test( - IntStream.rangeClosed(1, 9) - .boxed() - .peek(n -> System.out.format("%d ", n)), - n -> n < val)); - } - public static void main(String[] args) { - show(Stream::allMatch, 10); - show(Stream::allMatch, 4); - show(Stream::anyMatch, 2); - show(Stream::anyMatch, 0); - show(Stream::noneMatch, 5); - show(Stream::noneMatch, 0); - } -} -/* Output: -1 2 3 4 5 6 7 8 9 true -1 2 3 4 false -1 true -1 2 3 4 5 6 7 8 9 false -1 false -1 2 3 4 5 6 7 8 9 true -*/ diff --git a/code/streams/NumericStreamInfo.java b/code/streams/NumericStreamInfo.java deleted file mode 100644 index 0d04b6ef..00000000 --- a/code/streams/NumericStreamInfo.java +++ /dev/null @@ -1,24 +0,0 @@ -// streams/NumericStreamInfo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; -import static streams.RandInts.*; - -public class NumericStreamInfo { - public static void main(String[] args) { - System.out.println(rands().average().getAsDouble()); - System.out.println(rands().max().getAsInt()); - System.out.println(rands().min().getAsInt()); - System.out.println(rands().sum()); - System.out.println(rands().summaryStatistics()); - } -} -/* Output: -507.94 -998 -8 -50794 -IntSummaryStatistics{count=100, sum=50794, min=8, -average=507.940000, max=998} -*/ diff --git a/code/streams/OptionalBasics.java b/code/streams/OptionalBasics.java deleted file mode 100644 index 625c450a..00000000 --- a/code/streams/OptionalBasics.java +++ /dev/null @@ -1,23 +0,0 @@ -// streams/OptionalBasics.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -class OptionalBasics { - static void test(Optional optString) { - if(optString.isPresent()) - System.out.println(optString.get()); - else - System.out.println("Nothing inside!"); - } - public static void main(String[] args) { - test(Stream.of("Epithets").findFirst()); - test(Stream.empty().findFirst()); - } -} -/* Output: -Epithets -Nothing inside! -*/ diff --git a/code/streams/OptionalFilter.java b/code/streams/OptionalFilter.java deleted file mode 100644 index a2095ec3..00000000 --- a/code/streams/OptionalFilter.java +++ /dev/null @@ -1,72 +0,0 @@ -// streams/OptionalFilter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; - -class OptionalFilter { - static String[] elements = { - "Foo", "", "Bar", "Baz", "Bingo" - }; - static Stream testStream() { - return Arrays.stream(elements); - } - static void - test(String descr, Predicate pred) { - System.out.println(" ---( " + descr + " )---"); - for(int i = 0; i <= elements.length; i++) { - System.out.println( - testStream() - .skip(i) - .findFirst() - .filter(pred)); - } - } - public static void main(String[] args) { - test("true", str -> true); - test("false", str -> false); - test("str != \"\"", str -> str != ""); - test("str.length() == 3", str -> str.length() == 3); - test("startsWith(\"B\")", - str -> str.startsWith("B")); - } -} -/* Output: - ---( true )--- -Optional[Foo] -Optional[] -Optional[Bar] -Optional[Baz] -Optional[Bingo] -Optional.empty - ---( false )--- -Optional.empty -Optional.empty -Optional.empty -Optional.empty -Optional.empty -Optional.empty - ---( str != "" )--- -Optional[Foo] -Optional.empty -Optional[Bar] -Optional[Baz] -Optional[Bingo] -Optional.empty - ---( str.length() == 3 )--- -Optional[Foo] -Optional.empty -Optional[Bar] -Optional[Baz] -Optional.empty -Optional.empty - ---( startsWith("B") )--- -Optional.empty -Optional.empty -Optional[Bar] -Optional[Baz] -Optional[Bingo] -Optional.empty -*/ diff --git a/code/streams/OptionalFlatMap.java b/code/streams/OptionalFlatMap.java deleted file mode 100644 index 52e8e81e..00000000 --- a/code/streams/OptionalFlatMap.java +++ /dev/null @@ -1,73 +0,0 @@ -// streams/OptionalFlatMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; - -class OptionalFlatMap { - static String[] elements = { "12", "", "23", "45" }; - static Stream testStream() { - return Arrays.stream(elements); - } - static void test(String descr, - Function> func) { - System.out.println(" ---( " + descr + " )---"); - for(int i = 0; i <= elements.length; i++) { - System.out.println( - testStream() - .skip(i) - .findFirst() - .flatMap(func)); - } - } - public static void main(String[] args) { - - test("Add brackets", - s -> Optional.of("[" + s + "]")); - - test("Increment", s -> { - try { - return Optional.of( - Integer.parseInt(s) + 1 + ""); - } catch(NumberFormatException e) { - return Optional.of(s); - } - }); - - test("Replace", - s -> Optional.of(s.replace("2", "9"))); - - test("Take last digit", - s -> Optional.of(s.length() > 0 ? - s.charAt(s.length() - 1) + "" - : s)); - } -} -/* Output: - ---( Add brackets )--- -Optional[[12]] -Optional[[]] -Optional[[23]] -Optional[[45]] -Optional.empty - ---( Increment )--- -Optional[13] -Optional[] -Optional[24] -Optional[46] -Optional.empty - ---( Replace )--- -Optional[19] -Optional[] -Optional[93] -Optional[45] -Optional.empty - ---( Take last digit )--- -Optional[2] -Optional[] -Optional[3] -Optional[5] -Optional.empty -*/ diff --git a/code/streams/OptionalMap.java b/code/streams/OptionalMap.java deleted file mode 100644 index 83ae4396..00000000 --- a/code/streams/OptionalMap.java +++ /dev/null @@ -1,74 +0,0 @@ -// streams/OptionalMap.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; - -class OptionalMap { - static String[] elements = { "12", "", "23", "45" }; - static Stream testStream() { - return Arrays.stream(elements); - } - static void - test(String descr, Function func) { - System.out.println(" ---( " + descr + " )---"); - for(int i = 0; i <= elements.length; i++) { - System.out.println( - testStream() - .skip(i) - .findFirst() // Produces an Optional - .map(func)); - } - } - public static void main(String[] args) { - - // If Optional is not empty, map() first extracts - // the contents which it then passes - // to the function: - - test("Add brackets", s -> "[" + s + "]"); - - test("Increment", s -> { - try { - return Integer.parseInt(s) + 1 + ""; - } catch(NumberFormatException e) { - return s; - } - }); - - test("Replace", s -> s.replace("2", "9")); - - test("Take last digit", s -> s.length() > 0 ? - s.charAt(s.length() - 1) + "" : s); - } - // After the function is finished, map() wraps the - // result in an Optional before returning it: -} -/* Output: - ---( Add brackets )--- -Optional[[12]] -Optional[[]] -Optional[[23]] -Optional[[45]] -Optional.empty - ---( Increment )--- -Optional[13] -Optional[] -Optional[24] -Optional[46] -Optional.empty - ---( Replace )--- -Optional[19] -Optional[] -Optional[93] -Optional[45] -Optional.empty - ---( Take last digit )--- -Optional[2] -Optional[] -Optional[3] -Optional[5] -Optional.empty -*/ diff --git a/code/streams/Optionals.java b/code/streams/Optionals.java deleted file mode 100644 index 4d0d96cb..00000000 --- a/code/streams/Optionals.java +++ /dev/null @@ -1,63 +0,0 @@ -// streams/Optionals.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; - -public class Optionals { - static void basics(Optional optString) { - if(optString.isPresent()) - System.out.println(optString.get()); - else - System.out.println("Nothing inside!"); - } - static void ifPresent(Optional optString) { - optString.ifPresent(System.out::println); - } - static void orElse(Optional optString) { - System.out.println(optString.orElse("Nada")); - } - static void orElseGet(Optional optString) { - System.out.println( - optString.orElseGet(() -> "Generated")); - } - static void orElseThrow(Optional optString) { - try { - System.out.println(optString.orElseThrow( - () -> new Exception("Supplied"))); - } catch(Exception e) { - System.out.println("Caught " + e); - } - } - static void test(String testName, - Consumer> cos) { - System.out.println(" === " + testName + " === "); - cos.accept(Stream.of("Epithets").findFirst()); - cos.accept(Stream.empty().findFirst()); - } - public static void main(String[] args) { - test("basics", Optionals::basics); - test("ifPresent", Optionals::ifPresent); - test("orElse", Optionals::orElse); - test("orElseGet", Optionals::orElseGet); - test("orElseThrow", Optionals::orElseThrow); - } -} -/* Output: - === basics === -Epithets -Nothing inside! - === ifPresent === -Epithets - === orElse === -Epithets -Nada - === orElseGet === -Epithets -Generated - === orElseThrow === -Epithets -Caught java.lang.Exception: Supplied -*/ diff --git a/code/streams/OptionalsFromEmptyStreams.java b/code/streams/OptionalsFromEmptyStreams.java deleted file mode 100644 index 771a84c0..00000000 --- a/code/streams/OptionalsFromEmptyStreams.java +++ /dev/null @@ -1,31 +0,0 @@ -// streams/OptionalsFromEmptyStreams.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -class OptionalsFromEmptyStreams { - public static void main(String[] args) { - System.out.println(Stream.empty() - .findFirst()); - System.out.println(Stream.empty() - .findAny()); - System.out.println(Stream.empty() - .max(String.CASE_INSENSITIVE_ORDER)); - System.out.println(Stream.empty() - .min(String.CASE_INSENSITIVE_ORDER)); - System.out.println(Stream.empty() - .reduce((s1, s2) -> s1 + s2)); - System.out.println(IntStream.empty() - .average()); - } -} -/* Output: -Optional.empty -Optional.empty -Optional.empty -Optional.empty -Optional.empty -OptionalDouble.empty -*/ diff --git a/code/streams/Peeking.java b/code/streams/Peeking.java deleted file mode 100644 index d8800515..00000000 --- a/code/streams/Peeking.java +++ /dev/null @@ -1,22 +0,0 @@ -// streams/Peeking.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Peeking { - public static void - main(String[] args) throws Exception { - FileToWords.stream("Cheese.dat") - .skip(21) - .limit(4) - .map(w -> w + " ") - .peek(System.out::print) - .map(String::toUpperCase) - .peek(System.out::print) - .map(String::toLowerCase) - .forEach(System.out::print); - } -} -/* Output: -Well WELL well it IT it s S s so SO so -*/ diff --git a/code/streams/Prime.java b/code/streams/Prime.java deleted file mode 100644 index e14459d1..00000000 --- a/code/streams/Prime.java +++ /dev/null @@ -1,31 +0,0 @@ -// streams/Prime.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; -import static java.util.stream.LongStream.*; - -public class Prime { - public static boolean isPrime(long n) { - return rangeClosed(2, (long)Math.sqrt(n)) - .noneMatch(i -> n % i == 0); - } - public LongStream numbers() { - return iterate(2, i -> i + 1) - .filter(Prime::isPrime); - } - public static void main(String[] args) { - new Prime().numbers() - .limit(10) - .forEach(n -> System.out.format("%d ", n)); - System.out.println(); - new Prime().numbers() - .skip(90) - .limit(10) - .forEach(n -> System.out.format("%d ", n)); - } -} -/* Output: -2 3 5 7 11 13 17 19 23 29 -467 479 487 491 499 503 509 521 523 541 -*/ diff --git a/code/streams/RandInts.java b/code/streams/RandInts.java deleted file mode 100644 index 8adfc60e..00000000 --- a/code/streams/RandInts.java +++ /dev/null @@ -1,15 +0,0 @@ -// streams/RandInts.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package streams; -import java.util.*; -import java.util.stream.*; - -public class RandInts { - private static int[] rints = - new Random(47).ints(0, 1000).limit(100).toArray(); - public static IntStream rands() { - return Arrays.stream(rints); - } -} diff --git a/code/streams/RandomGenerators.java b/code/streams/RandomGenerators.java deleted file mode 100644 index 904216ac..00000000 --- a/code/streams/RandomGenerators.java +++ /dev/null @@ -1,86 +0,0 @@ -// streams/RandomGenerators.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class RandomGenerators { - public static void show(Stream stream) { - stream - .limit(4) - .forEach(System.out::println); - System.out.println("++++++++"); - } - public static void main(String[] args) { - Random rand = new Random(47); - show(rand.ints().boxed()); - show(rand.longs().boxed()); - show(rand.doubles().boxed()); - // Control the lower and upper bounds: - show(rand.ints(10, 20).boxed()); - show(rand.longs(50, 100).boxed()); - show(rand.doubles(20, 30).boxed()); - // Control the stream size: - show(rand.ints(2).boxed()); - show(rand.longs(2).boxed()); - show(rand.doubles(2).boxed()); - // Control the stream size and bounds: - show(rand.ints(3, 3, 9).boxed()); - show(rand.longs(3, 12, 22).boxed()); - show(rand.doubles(3, 11.5, 12.3).boxed()); - } -} -/* Output: --1172028779 -1717241110 --2014573909 -229403722 -++++++++ -2955289354441303771 -3476817843704654257 --8917117694134521474 -4941259272818818752 -++++++++ -0.2613610344283964 -0.0508673570556899 -0.8037155449603999 -0.7620665811558285 -++++++++ -16 -10 -11 -12 -++++++++ -65 -99 -54 -58 -++++++++ -29.86777681078574 -24.83968447804611 -20.09247112332014 -24.046793846338723 -++++++++ -1169976606 -1947946283 -++++++++ -2970202997824602425 --2325326920272830366 -++++++++ -0.7024254510631527 -0.6648552384607359 -++++++++ -6 -7 -7 -++++++++ -17 -12 -20 -++++++++ -12.27872414236691 -11.732085449736195 -12.196509449817267 -++++++++ -*/ diff --git a/code/streams/RandomWords.java b/code/streams/RandomWords.java deleted file mode 100644 index 3bf2e51b..00000000 --- a/code/streams/RandomWords.java +++ /dev/null @@ -1,41 +0,0 @@ -// streams/RandomWords.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; -import java.io.*; -import java.nio.file.*; - -public class RandomWords implements Supplier { - List words = new ArrayList<>(); - Random rand = new Random(47); - RandomWords(String fname) throws IOException { - List lines = - Files.readAllLines(Paths.get(fname)); - // Skip the first line: - for(String line : lines.subList(1, lines.size())) { - for(String word : line.split("[ .?,]+")) - words.add(word.toLowerCase()); - } - } - public String get() { - return words.get(rand.nextInt(words.size())); - } - @Override - public String toString() { - return words.stream() - .collect(Collectors.joining(" ")); - } - public static void - main(String[] args) throws Exception { - System.out.println( - Stream.generate(new RandomWords("Cheese.dat")) - .limit(10) - .collect(Collectors.joining(" "))); - } -} -/* Output: -it shop sir the much cheese by conclusion district is -*/ diff --git a/code/streams/Randoms.java b/code/streams/Randoms.java deleted file mode 100644 index f2b5f6a8..00000000 --- a/code/streams/Randoms.java +++ /dev/null @@ -1,25 +0,0 @@ -// streams/Randoms.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class Randoms { - public static void main(String[] args) { - new Random(47) - .ints(5, 20) - .distinct() - .limit(7) - .sorted() - .forEach(System.out::println); - } -} -/* Output: -6 -10 -13 -16 -17 -18 -19 -*/ diff --git a/code/streams/Ranges.java b/code/streams/Ranges.java deleted file mode 100644 index d8fc681a..00000000 --- a/code/streams/Ranges.java +++ /dev/null @@ -1,29 +0,0 @@ -// streams/Ranges.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import static java.util.stream.IntStream.*; - -public class Ranges { - public static void main(String[] args) { - // The traditional way: - int result = 0; - for(int i = 10; i < 20; i++) - result += i; - System.out.println(result); - - // for-in with a range: - result = 0; - for(int i : range(10, 20).toArray()) - result += i; - System.out.println(result); - - // Use streams: - System.out.println(range(10, 20).sum()); - } -} -/* Output: -145 -145 -145 -*/ diff --git a/code/streams/Reduce.java b/code/streams/Reduce.java deleted file mode 100644 index 0e9f07ba..00000000 --- a/code/streams/Reduce.java +++ /dev/null @@ -1,44 +0,0 @@ -// streams/Reduce.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -class Frobnitz { - int size; - Frobnitz(int sz) { size = sz; } - @Override - public String toString() { - return "Frobnitz(" + size + ")"; - } - // Generator: - static Random rand = new Random(47); - static final int BOUND = 100; - static Frobnitz supply() { - return new Frobnitz(rand.nextInt(BOUND)); - } -} - -public class Reduce { - public static void main(String[] args) { - Stream.generate(Frobnitz::supply) - .limit(10) - .peek(System.out::println) - .reduce((fr0, fr1) -> fr0.size < 50 ? fr0 : fr1) - .ifPresent(System.out::println); - } -} -/* Output: -Frobnitz(58) -Frobnitz(55) -Frobnitz(93) -Frobnitz(61) -Frobnitz(61) -Frobnitz(29) -Frobnitz(68) -Frobnitz(0) -Frobnitz(22) -Frobnitz(7) -Frobnitz(29) -*/ diff --git a/code/streams/SelectElement.java b/code/streams/SelectElement.java deleted file mode 100644 index 86846e40..00000000 --- a/code/streams/SelectElement.java +++ /dev/null @@ -1,24 +0,0 @@ -// streams/SelectElement.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import static streams.RandInts.*; - -public class SelectElement { - public static void main(String[] args) { - System.out.println(rands().findFirst().getAsInt()); - System.out.println( - rands().parallel().findFirst().getAsInt()); - System.out.println(rands().findAny().getAsInt()); - System.out.println( - rands().parallel().findAny().getAsInt()); - } -} -/* Output: -258 -258 -258 -242 -*/ diff --git a/code/streams/Signal.java b/code/streams/Signal.java deleted file mode 100644 index 9dc2a9f4..00000000 --- a/code/streams/Signal.java +++ /dev/null @@ -1,29 +0,0 @@ -// streams/Signal.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import java.util.function.*; - -public class Signal { - private final String msg; - public Signal(String msg) { this.msg = msg; } - public String getMsg() { return msg; } - @Override - public String toString() { - return "Signal(" + msg + ")"; - } - static Random rand = new Random(47); - public static Signal morse() { - switch(rand.nextInt(4)) { - case 1: return new Signal("dot"); - case 2: return new Signal("dash"); - default: return null; - } - } - public static Stream> stream() { - return Stream.generate(Signal::morse) - .map(signal -> Optional.ofNullable(signal)); - } -} diff --git a/code/streams/SortedComparator.java b/code/streams/SortedComparator.java deleted file mode 100644 index 070d60a7..00000000 --- a/code/streams/SortedComparator.java +++ /dev/null @@ -1,20 +0,0 @@ -// streams/SortedComparator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SortedComparator { - public static void - main(String[] args) throws Exception { - FileToWords.stream("Cheese.dat") - .skip(10) - .limit(10) - .sorted(Comparator.reverseOrder()) - .map(w -> w + " ") - .forEach(System.out::print); - } -} -/* Output: -you what to the that sir leads in district And -*/ diff --git a/code/streams/SpecialCollector.java b/code/streams/SpecialCollector.java deleted file mode 100644 index 9526a73e..00000000 --- a/code/streams/SpecialCollector.java +++ /dev/null @@ -1,24 +0,0 @@ -// streams/SpecialCollector.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class SpecialCollector { - public static void - main(String[] args) throws Exception { - ArrayList words = - FileToWords.stream("Cheese.dat") - .collect(ArrayList::new, - ArrayList::add, - ArrayList::addAll); - words.stream() - .filter(s -> s.equals("cheese")) - .forEach(System.out::println); - } -} -/* Output: -cheese -cheese -*/ diff --git a/code/streams/StreamOf.java b/code/streams/StreamOf.java deleted file mode 100644 index c143388a..00000000 --- a/code/streams/StreamOf.java +++ /dev/null @@ -1,28 +0,0 @@ -// streams/StreamOf.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public class StreamOf { - public static void main(String[] args) { - Stream.of( - new Bubble(1), new Bubble(2), new Bubble(3)) - .forEach(System.out::println); - Stream.of("It's ", "a ", "wonderful ", - "day ", "for ", "pie!") - .forEach(System.out::print); - System.out.println(); - Stream.of(3.14159, 2.718, 1.618) - .forEach(System.out::println); - } -} -/* Output: -Bubble(1) -Bubble(2) -Bubble(3) -It's a wonderful day for pie! -3.14159 -2.718 -1.618 -*/ diff --git a/code/streams/StreamOfOptionals.java b/code/streams/StreamOfOptionals.java deleted file mode 100644 index f725df57..00000000 --- a/code/streams/StreamOfOptionals.java +++ /dev/null @@ -1,37 +0,0 @@ -// streams/StreamOfOptionals.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class StreamOfOptionals { - public static void main(String[] args) { - Signal.stream() - .limit(10) - .forEach(System.out::println); - System.out.println(" ---"); - Signal.stream() - .limit(10) - .filter(Optional::isPresent) - .map(Optional::get) - .forEach(System.out::println); - } -} -/* Output: -Optional[Signal(dash)] -Optional[Signal(dot)] -Optional[Signal(dash)] -Optional.empty -Optional.empty -Optional[Signal(dash)] -Optional.empty -Optional[Signal(dot)] -Optional[Signal(dash)] -Optional[Signal(dash)] - --- -Signal(dot) -Signal(dot) -Signal(dash) -Signal(dash) -*/ diff --git a/code/streams/StreamOfRandoms.java b/code/streams/StreamOfRandoms.java deleted file mode 100644 index 66bf2bc7..00000000 --- a/code/streams/StreamOfRandoms.java +++ /dev/null @@ -1,20 +0,0 @@ -// streams/StreamOfRandoms.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class StreamOfRandoms { - static Random rand = new Random(47); - public static void main(String[] args) { - Stream.of(1, 2, 3, 4, 5) - .flatMapToInt(i -> IntStream.concat( - rand.ints(0, 100).limit(i), IntStream.of(-1))) - .forEach(n -> System.out.format("%d ", n)); - } -} -/* Output: -58 -1 55 93 -1 61 61 29 -1 68 0 22 7 -1 88 28 51 89 9 --1 -*/ diff --git a/code/streams/StreamOfStreams.java b/code/streams/StreamOfStreams.java deleted file mode 100644 index 973d83a6..00000000 --- a/code/streams/StreamOfStreams.java +++ /dev/null @@ -1,19 +0,0 @@ -// streams/StreamOfStreams.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -public class StreamOfStreams { - public static void main(String[] args) { - Stream.of(1, 2, 3) - .map(i -> Stream.of("Gonzo", "Kermit", "Beaker")) - .map(e-> e.getClass().getName()) - .forEach(System.out::println); - } -} -/* Output: -java.util.stream.ReferencePipeline$Head -java.util.stream.ReferencePipeline$Head -java.util.stream.ReferencePipeline$Head -*/ diff --git a/code/streams/TreeSetOfWords.java b/code/streams/TreeSetOfWords.java deleted file mode 100644 index feaa56a2..00000000 --- a/code/streams/TreeSetOfWords.java +++ /dev/null @@ -1,31 +0,0 @@ -// streams/TreeSetOfWords.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.nio.file.*; -import java.util.stream.*; - -public class TreeSetOfWords { - public static void - main(String[] args) throws Exception { - Set words2 = - Files.lines(Paths.get("TreeSetOfWords.java")) - .flatMap(s -> Arrays.stream(s.split("\\W+"))) - .filter(s -> !s.matches("\\d+")) // No numbers - .map(String::trim) - .filter(s -> s.length() > 2) - .limit(100) - .collect(Collectors.toCollection(TreeSet::new)); - System.out.println(words2); - } -} -/* Output: -[Arrays, Collectors, Exception, Files, Output, Paths, -Set, String, System, TreeSet, TreeSetOfWords, args, -class, collect, file, filter, flatMap, get, import, -java, length, limit, lines, main, map, matches, new, -nio, numbers, out, println, public, split, static, -stream, streams, throws, toCollection, trim, util, -void, words2] -*/ diff --git a/code/strings/ArrayListDisplay.java b/code/strings/ArrayListDisplay.java deleted file mode 100644 index 7b83296f..00000000 --- a/code/strings/ArrayListDisplay.java +++ /dev/null @@ -1,22 +0,0 @@ -// strings/ArrayListDisplay.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; -import generics.coffee.*; - -public class ArrayListDisplay { - public static void main(String[] args) { - List coffees = - Stream.generate(new CoffeeSupplier()) - .limit(10) - .collect(Collectors.toList()); - System.out.println(coffees); - } -} -/* Output: -[Americano 0, Latte 1, Americano 2, Mocha 3, Mocha 4, -Breve 5, Americano 6, Latte 7, Cappuccino 8, Cappuccino -9] -*/ diff --git a/code/strings/BetterRead.java b/code/strings/BetterRead.java deleted file mode 100644 index a3b7aaa2..00000000 --- a/code/strings/BetterRead.java +++ /dev/null @@ -1,37 +0,0 @@ -// strings/BetterRead.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class BetterRead { - public static void main(String[] args) { - Scanner stdin = new Scanner(SimpleRead.input); - System.out.println("What is your name?"); - String name = stdin.nextLine(); - System.out.println(name); - System.out.println( - "How old are you? What is your favorite double?"); - System.out.println("(input: )"); - int age = stdin.nextInt(); - double favorite = stdin.nextDouble(); - System.out.println(age); - System.out.println(favorite); - System.out.format("Hi %s.%n", name); - System.out.format("In 5 years you will be %d.%n", - age + 5); - System.out.format("My favorite double is %f.", - favorite / 2); - } -} -/* Output: -What is your name? -Sir Robin of Camelot -How old are you? What is your favorite double? -(input: ) -22 -1.61803 -Hi Sir Robin of Camelot. -In 5 years you will be 27. -My favorite double is 0.809015. -*/ diff --git a/code/strings/Concatenation.java b/code/strings/Concatenation.java deleted file mode 100644 index 685f4dbb..00000000 --- a/code/strings/Concatenation.java +++ /dev/null @@ -1,15 +0,0 @@ -// strings/Concatenation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Concatenation { - public static void main(String[] args) { - String mango = "mango"; - String s = "abc" + mango + "def" + 47; - System.out.println(s); - } -} -/* Output: -abcmangodef47 -*/ diff --git a/code/strings/Conversion.java b/code/strings/Conversion.java deleted file mode 100644 index f839e81a..00000000 --- a/code/strings/Conversion.java +++ /dev/null @@ -1,113 +0,0 @@ -// strings/Conversion.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.math.*; -import java.util.*; - -public class Conversion { - public static void main(String[] args) { - Formatter f = new Formatter(System.out); - - char u = 'a'; - System.out.println("u = 'a'"); - f.format("s: %s%n", u); - // f.format("d: %d%n", u); - f.format("c: %c%n", u); - f.format("b: %b%n", u); - // f.format("f: %f%n", u); - // f.format("e: %e%n", u); - // f.format("x: %x%n", u); - f.format("h: %h%n", u); - - int v = 121; - System.out.println("v = 121"); - f.format("d: %d%n", v); - f.format("c: %c%n", v); - f.format("b: %b%n", v); - f.format("s: %s%n", v); - // f.format("f: %f%n", v); - // f.format("e: %e%n", v); - f.format("x: %x%n", v); - f.format("h: %h%n", v); - - BigInteger w = new BigInteger("50000000000000"); - System.out.println( - "w = new BigInteger(\"50000000000000\")"); - f.format("d: %d%n", w); - // f.format("c: %c%n", w); - f.format("b: %b%n", w); - f.format("s: %s%n", w); - // f.format("f: %f%n", w); - // f.format("e: %e%n", w); - f.format("x: %x%n", w); - f.format("h: %h%n", w); - - double x = 179.543; - System.out.println("x = 179.543"); - // f.format("d: %d%n", x); - // f.format("c: %c%n", x); - f.format("b: %b%n", x); - f.format("s: %s%n", x); - f.format("f: %f%n", x); - f.format("e: %e%n", x); - // f.format("x: %x%n", x); - f.format("h: %h%n", x); - - Conversion y = new Conversion(); - System.out.println("y = new Conversion()"); - // f.format("d: %d%n", y); - // f.format("c: %c%n", y); - f.format("b: %b%n", y); - f.format("s: %s%n", y); - // f.format("f: %f%n", y); - // f.format("e: %e%n", y); - // f.format("x: %x%n", y); - f.format("h: %h%n", y); - - boolean z = false; - System.out.println("z = false"); - // f.format("d: %d%n", z); - // f.format("c: %c%n", z); - f.format("b: %b%n", z); - f.format("s: %s%n", z); - // f.format("f: %f%n", z); - // f.format("e: %e%n", z); - // f.format("x: %x%n", z); - f.format("h: %h%n", z); - } -} -/* Output: -u = 'a' -s: a -c: a -b: true -h: 61 -v = 121 -d: 121 -c: y -b: true -s: 121 -x: 79 -h: 79 -w = new BigInteger("50000000000000") -d: 50000000000000 -b: true -s: 50000000000000 -x: 2d79883d2000 -h: 8842a1a7 -x = 179.543 -b: true -s: 179.543 -f: 179.543000 -e: 1.795430e+02 -h: 1ef462c -y = new Conversion() -b: true -s: Conversion@15db9742 -h: 15db9742 -z = false -b: false -s: false -h: 4d5 -*/ diff --git a/code/strings/DatabaseException.java b/code/strings/DatabaseException.java deleted file mode 100644 index e8441254..00000000 --- a/code/strings/DatabaseException.java +++ /dev/null @@ -1,22 +0,0 @@ -// strings/DatabaseException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class DatabaseException extends Exception { - public DatabaseException(int transactionID, - int queryID, String message) { - super(String.format("(t%d, q%d) %s", transactionID, - queryID, message)); - } - public static void main(String[] args) { - try { - throw new DatabaseException(3, 7, "Write failed"); - } catch(Exception e) { - System.out.println(e); - } - } -} -/* Output: -DatabaseException: (t3, q7) Write failed -*/ diff --git a/code/strings/Finding.java b/code/strings/Finding.java deleted file mode 100644 index f8d7cbbc..00000000 --- a/code/strings/Finding.java +++ /dev/null @@ -1,27 +0,0 @@ -// strings/Finding.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; - -public class Finding { - public static void main(String[] args) { - Matcher m = Pattern.compile("\\w+") - .matcher( - "Evening is full of the linnet's wings"); - while(m.find()) - System.out.print(m.group() + " "); - System.out.println(); - int i = 0; - while(m.find(i)) { - System.out.print(m.group() + " "); - i++; - } - } -} -/* Output: -Evening is full of the linnet s wings -Evening vening ening ning ing ng g is is s full full -ull ll l of of f the the he e linnet linnet innet nnet -net et t s s wings wings ings ngs gs s -*/ diff --git a/code/strings/Groups.java b/code/strings/Groups.java deleted file mode 100644 index 298caf62..00000000 --- a/code/strings/Groups.java +++ /dev/null @@ -1,40 +0,0 @@ -// strings/Groups.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; - -public class Groups { - public static final String POEM = - "Twas brillig, and the slithy toves\n" + - "Did gyre and gimble in the wabe.\n" + - "All mimsy were the borogoves,\n" + - "And the mome raths outgrabe.\n\n" + - "Beware the Jabberwock, my son,\n" + - "The jaws that bite, the claws that catch.\n" + - "Beware the Jubjub bird, and shun\n" + - "The frumious Bandersnatch."; - public static void main(String[] args) { - Matcher m = Pattern.compile( - "(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$") - .matcher(POEM); - while(m.find()) { - for(int j = 0; j <= m.groupCount(); j++) - System.out.print("[" + m.group(j) + "]"); - System.out.println(); - } - } -} -/* Output: -[the slithy toves][the][slithy toves][slithy][toves] -[in the wabe.][in][the wabe.][the][wabe.] -[were the borogoves,][were][the -borogoves,][the][borogoves,] -[mome raths outgrabe.][mome][raths -outgrabe.][raths][outgrabe.] -[Jabberwock, my son,][Jabberwock,][my son,][my][son,] -[claws that catch.][claws][that catch.][that][catch.] -[bird, and shun][bird,][and shun][and][shun] -[The frumious Bandersnatch.][The][frumious -Bandersnatch.][frumious][Bandersnatch.] -*/ diff --git a/code/strings/Hex.java b/code/strings/Hex.java deleted file mode 100644 index 0fbcea8e..00000000 --- a/code/strings/Hex.java +++ /dev/null @@ -1,44 +0,0 @@ -// strings/Hex.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {java onjava.Hex} -package onjava; -import java.io.*; -import java.nio.file.*; - -public class Hex { - public static String format(byte[] data) { - StringBuilder result = new StringBuilder(); - int n = 0; - for(byte b : data) { - if(n % 16 == 0) - result.append(String.format("%05X: ", n)); - result.append(String.format("%02X ", b)); - n++; - if(n % 16 == 0) result.append("\n"); - } - result.append("\n"); - return result.toString(); - } - public static void - main(String[] args) throws Exception { - if(args.length == 0) - // Test by displaying this class file: - System.out.println(format( - Files.readAllBytes(Paths.get( - "build/classes/java/main/onjava/Hex.class")))); - else - System.out.println(format( - Files.readAllBytes(Paths.get(args[0])))); - } -} -/* Output: (First 6 Lines) -00000: CA FE BA BE 00 00 00 34 00 61 0A 00 05 00 31 07 -00010: 00 32 0A 00 02 00 31 08 00 33 07 00 34 0A 00 35 -00020: 00 36 0A 00 0F 00 37 0A 00 02 00 38 08 00 39 0A -00030: 00 3A 00 3B 08 00 3C 0A 00 02 00 3D 09 00 3E 00 -00040: 3F 08 00 40 07 00 41 0A 00 42 00 43 0A 00 44 00 -00050: 45 0A 00 14 00 46 0A 00 47 00 48 07 00 49 01 00 - ... -*/ diff --git a/code/strings/Immutable.java b/code/strings/Immutable.java deleted file mode 100644 index 4c8b529e..00000000 --- a/code/strings/Immutable.java +++ /dev/null @@ -1,22 +0,0 @@ -// strings/Immutable.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Immutable { - public static String upcase(String s) { - return s.toUpperCase(); - } - public static void main(String[] args) { - String q = "howdy"; - System.out.println(q); // howdy - String qq = upcase(q); - System.out.println(qq); // HOWDY - System.out.println(q); // howdy - } -} -/* Output: -howdy -HOWDY -howdy -*/ diff --git a/code/strings/InfiniteRecursion.java b/code/strings/InfiniteRecursion.java deleted file mode 100644 index 6941490a..00000000 --- a/code/strings/InfiniteRecursion.java +++ /dev/null @@ -1,22 +0,0 @@ -// strings/InfiniteRecursion.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Accidental recursion -// {ThrowsException} -// {VisuallyInspectOutput} Throws very long exception -import java.util.*; -import java.util.stream.*; - -public class InfiniteRecursion { - @Override - public String toString() { - return - " InfiniteRecursion address: " + this + "\n"; - } - public static void main(String[] args) { - Stream.generate(InfiniteRecursion::new) - .limit(10) - .forEach(System.out::println); - } -} diff --git a/code/strings/IntegerMatch.java b/code/strings/IntegerMatch.java deleted file mode 100644 index 5a3a38ac..00000000 --- a/code/strings/IntegerMatch.java +++ /dev/null @@ -1,19 +0,0 @@ -// strings/IntegerMatch.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class IntegerMatch { - public static void main(String[] args) { - System.out.println("-1234".matches("-?\\d+")); - System.out.println("5678".matches("-?\\d+")); - System.out.println("+911".matches("-?\\d+")); - System.out.println("+911".matches("(-|\\+)?\\d+")); - } -} -/* Output: -true -true -false -true -*/ diff --git a/code/strings/JGrep.java b/code/strings/JGrep.java deleted file mode 100644 index 49cec954..00000000 --- a/code/strings/JGrep.java +++ /dev/null @@ -1,36 +0,0 @@ -// strings/JGrep.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// A very simple version of the "grep" program -// {java JGrep -// WhitherStringBuilder.java 'return|for|String'} -import java.util.regex.*; -import java.nio.file.*; -import java.util.stream.*; - -public class JGrep { - public static void - main(String[] args) throws Exception { - if(args.length < 2) { - System.out.println( - "Usage: java JGrep file regex"); - System.exit(0); - } - Pattern p = Pattern.compile(args[1]); - // Iterate through the lines of the input file: - int index = 0; - Matcher m = p.matcher(""); - for(String line : - Files.readAllLines(Paths.get(args[0]))) { - m.reset(line); - while(m.find()) - System.out.println(index++ + ": " + - m.group() + ": " + m.start()); - } - } -} -/* Output: -0: for: 4 -1: for: 4 -*/ diff --git a/code/strings/ReFlags.java b/code/strings/ReFlags.java deleted file mode 100644 index 856806ee..00000000 --- a/code/strings/ReFlags.java +++ /dev/null @@ -1,23 +0,0 @@ -// strings/ReFlags.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; - -public class ReFlags { - public static void main(String[] args) { - Pattern p = Pattern.compile("^java", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - Matcher m = p.matcher( - "java has regex\nJava has regex\n" + - "JAVA has pretty good regular expressions\n" + - "Regular expressions are in Java"); - while(m.find()) - System.out.println(m.group()); - } -} -/* Output: -java -Java -JAVA -*/ diff --git a/code/strings/ReceiptBuilder.java b/code/strings/ReceiptBuilder.java deleted file mode 100644 index 234ca1e6..00000000 --- a/code/strings/ReceiptBuilder.java +++ /dev/null @@ -1,48 +0,0 @@ -// strings/ReceiptBuilder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ReceiptBuilder { - private double total = 0; - private Formatter f = - new Formatter(new StringBuilder()); - public ReceiptBuilder() { - f.format( - "%-15s %5s %10s%n", "Item", "Qty", "Price"); - f.format( - "%-15s %5s %10s%n", "----", "---", "-----"); - } - public void add(String name, int qty, double price) { - f.format("%-15.15s %5d %10.2f%n", name, qty, price); - total += price * qty; - } - public String build() { - f.format("%-15s %5s %10.2f%n", "Tax", "", - total * 0.06); - f.format("%-15s %5s %10s%n", "", "", "-----"); - f.format("%-15s %5s %10.2f%n", "Total", "", - total * 1.06); - return f.toString(); - } - public static void main(String[] args) { - ReceiptBuilder receiptBuilder = - new ReceiptBuilder(); - receiptBuilder.add("Jack's Magic Beans", 4, 4.25); - receiptBuilder.add("Princess Peas", 3, 5.1); - receiptBuilder.add( - "Three Bears Porridge", 1, 14.29); - System.out.println(receiptBuilder.build()); - } -} -/* Output: -Item Qty Price ----- --- ----- -Jack's Magic Be 4 4.25 -Princess Peas 3 5.10 -Three Bears Por 1 14.29 -Tax 2.80 - ----- -Total 49.39 -*/ diff --git a/code/strings/Replacing.java b/code/strings/Replacing.java deleted file mode 100644 index dbc21afe..00000000 --- a/code/strings/Replacing.java +++ /dev/null @@ -1,21 +0,0 @@ -// strings/Replacing.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Replacing { - static String s = Splitting.knights; - public static void main(String[] args) { - System.out.println( - s.replaceFirst("f\\w+", "located")); - System.out.println( - s.replaceAll("shrubbery|tree|herring","banana")); - } -} -/* Output: -Then, when you have located the shrubbery, you must cut -down the mightiest tree in the forest...with... a -herring! -Then, when you have found the banana, you must cut down -the mightiest banana in the forest...with... a banana! -*/ diff --git a/code/strings/ReplacingStringTokenizer.java b/code/strings/ReplacingStringTokenizer.java deleted file mode 100644 index 60fad184..00000000 --- a/code/strings/ReplacingStringTokenizer.java +++ /dev/null @@ -1,26 +0,0 @@ -// strings/ReplacingStringTokenizer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ReplacingStringTokenizer { - public static void main(String[] args) { - String input = - "But I'm not dead yet! I feel happy!"; - StringTokenizer stoke = new StringTokenizer(input); - while(stoke.hasMoreElements()) - System.out.print(stoke.nextToken() + " "); - System.out.println(); - System.out.println( - Arrays.toString(input.split(" "))); - Scanner scanner = new Scanner(input); - while(scanner.hasNext()) - System.out.print(scanner.next() + " "); - } -} -/* Output: -But I'm not dead yet! I feel happy! -[But, I'm, not, dead, yet!, I, feel, happy!] -But I'm not dead yet! I feel happy! -*/ diff --git a/code/strings/Resetting.java b/code/strings/Resetting.java deleted file mode 100644 index f1565390..00000000 --- a/code/strings/Resetting.java +++ /dev/null @@ -1,23 +0,0 @@ -// strings/Resetting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; - -public class Resetting { - public static void - main(String[] args) throws Exception { - Matcher m = Pattern.compile("[frb][aiu][gx]") - .matcher("fix the rug with bags"); - while(m.find()) - System.out.print(m.group() + " "); - System.out.println(); - m.reset("fix the rig with rags"); - while(m.find()) - System.out.print(m.group() + " "); - } -} -/* Output: -fix rug bag -fix rig rag -*/ diff --git a/code/strings/Rudolph.java b/code/strings/Rudolph.java deleted file mode 100644 index 7a338510..00000000 --- a/code/strings/Rudolph.java +++ /dev/null @@ -1,21 +0,0 @@ -// strings/Rudolph.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class Rudolph { - public static void main(String[] args) { - for(String pattern : new String[]{ - "Rudolph", - "[rR]udolph", - "[rR][aeiou][a-z]ol.*", - "R.*" }) - System.out.println("Rudolph".matches(pattern)); - } -} -/* Output: -true -true -true -true -*/ diff --git a/code/strings/ScannerDelimiter.java b/code/strings/ScannerDelimiter.java deleted file mode 100644 index a06ed990..00000000 --- a/code/strings/ScannerDelimiter.java +++ /dev/null @@ -1,21 +0,0 @@ -// strings/ScannerDelimiter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class ScannerDelimiter { - public static void main(String[] args) { - Scanner scanner = new Scanner("12, 42, 78, 99, 42"); - scanner.useDelimiter("\\s*,\\s*"); - while(scanner.hasNextInt()) - System.out.println(scanner.nextInt()); - } -} -/* Output: -12 -42 -78 -99 -42 -*/ diff --git a/code/strings/SimpleFormat.java b/code/strings/SimpleFormat.java deleted file mode 100644 index a3a6e52f..00000000 --- a/code/strings/SimpleFormat.java +++ /dev/null @@ -1,22 +0,0 @@ -// strings/SimpleFormat.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class SimpleFormat { - public static void main(String[] args) { - int x = 5; - double y = 5.332542; - // The old way: - System.out.println("Row 1: [" + x + " " + y + "]"); - // The new way: - System.out.format("Row 1: [%d %f]%n", x, y); - // or - System.out.printf("Row 1: [%d %f]%n", x, y); - } -} -/* Output: -Row 1: [5 5.332542] -Row 1: [5 5.332542] -Row 1: [5 5.332542] -*/ diff --git a/code/strings/SimpleRead.java b/code/strings/SimpleRead.java deleted file mode 100644 index e85a058a..00000000 --- a/code/strings/SimpleRead.java +++ /dev/null @@ -1,43 +0,0 @@ -// strings/SimpleRead.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; - -public class SimpleRead { - public static BufferedReader input = - new BufferedReader(new StringReader( - "Sir Robin of Camelot\n22 1.61803")); - public static void main(String[] args) { - try { - System.out.println("What is your name?"); - String name = input.readLine(); - System.out.println(name); - System.out.println("How old are you? " + - "What is your favorite double?"); - System.out.println("(input: )"); - String numbers = input.readLine(); - System.out.println(numbers); - String[] numArray = numbers.split(" "); - int age = Integer.parseInt(numArray[0]); - double favorite = Double.parseDouble(numArray[1]); - System.out.format("Hi %s.%n", name); - System.out.format("In 5 years you will be %d.%n", - age + 5); - System.out.format("My favorite double is %f.", - favorite / 2); - } catch(IOException e) { - System.err.println("I/O exception"); - } - } -} -/* Output: -What is your name? -Sir Robin of Camelot -How old are you? What is your favorite double? -(input: ) -22 1.61803 -Hi Sir Robin of Camelot. -In 5 years you will be 27. -My favorite double is 0.809015. -*/ diff --git a/code/strings/SplitDemo.java b/code/strings/SplitDemo.java deleted file mode 100644 index 65745392..00000000 --- a/code/strings/SplitDemo.java +++ /dev/null @@ -1,22 +0,0 @@ -// strings/SplitDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; -import java.util.*; - -public class SplitDemo { - public static void main(String[] args) { - String input = - "This!!unusual use!!of exclamation!!points"; - System.out.println(Arrays.toString( - Pattern.compile("!!").split(input))); - // Only do the first three: - System.out.println(Arrays.toString( - Pattern.compile("!!").split(input, 3))); - } -} -/* Output: -[This, unusual use, of exclamation, points] -[This, unusual use, of exclamation!!points] -*/ diff --git a/code/strings/Splitting.java b/code/strings/Splitting.java deleted file mode 100644 index 0afe3a40..00000000 --- a/code/strings/Splitting.java +++ /dev/null @@ -1,32 +0,0 @@ -// strings/Splitting.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class Splitting { - public static String knights = - "Then, when you have found the shrubbery, " + - "you must cut down the mightiest tree in the " + - "forest...with... a herring!"; - public static void split(String regex) { - System.out.println( - Arrays.toString(knights.split(regex))); - } - public static void main(String[] args) { - split(" "); // Doesn't have to contain regex chars - split("\\W+"); // Non-word characters - split("n\\W+"); // 'n' followed by non-words - } -} -/* Output: -[Then,, when, you, have, found, the, shrubbery,, you, -must, cut, down, the, mightiest, tree, in, the, -forest...with..., a, herring!] -[Then, when, you, have, found, the, shrubbery, you, -must, cut, down, the, mightiest, tree, in, the, forest, -with, a, herring] -[The, whe, you have found the shrubbery, you must cut -dow, the mightiest tree i, the forest...with... a -herring!] -*/ diff --git a/code/strings/StartEnd.java b/code/strings/StartEnd.java deleted file mode 100644 index 03caf520..00000000 --- a/code/strings/StartEnd.java +++ /dev/null @@ -1,82 +0,0 @@ -// strings/StartEnd.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; - -public class StartEnd { - public static String input = - "As long as there is injustice, whenever a\n" + - "Targathian baby cries out, wherever a distress\n" + - "signal sounds among the stars " + - "... We'll be there.\n"+ - "This fine ship, and this fine crew ...\n" + - "Never give up! Never surrender!"; - private static class Display { - private boolean regexPrinted = false; - private String regex; - Display(String regex) { this.regex = regex; } - void display(String message) { - if(!regexPrinted) { - System.out.println(regex); - regexPrinted = true; - } - System.out.println(message); - } - } - static void examine(String s, String regex) { - Display d = new Display(regex); - Pattern p = Pattern.compile(regex); - Matcher m = p.matcher(s); - while(m.find()) - d.display("find() '" + m.group() + - "' start = "+ m.start() + " end = " + m.end()); - if(m.lookingAt()) // No reset() necessary - d.display("lookingAt() start = " - + m.start() + " end = " + m.end()); - if(m.matches()) // No reset() necessary - d.display("matches() start = " - + m.start() + " end = " + m.end()); - } - public static void main(String[] args) { - for(String in : input.split("\n")) { - System.out.println("input : " + in); - for(String regex : new String[]{"\\w*ere\\w*", - "\\w*ever", "T\\w+", "Never.*?!"}) - examine(in, regex); - } - } -} -/* Output: -input : As long as there is injustice, whenever a -\w*ere\w* -find() 'there' start = 11 end = 16 -\w*ever -find() 'whenever' start = 31 end = 39 -input : Targathian baby cries out, wherever a distress -\w*ere\w* -find() 'wherever' start = 27 end = 35 -\w*ever -find() 'wherever' start = 27 end = 35 -T\w+ -find() 'Targathian' start = 0 end = 10 -lookingAt() start = 0 end = 10 -input : signal sounds among the stars ... We'll be -there. -\w*ere\w* -find() 'there' start = 43 end = 48 -input : This fine ship, and this fine crew ... -T\w+ -find() 'This' start = 0 end = 4 -lookingAt() start = 0 end = 4 -input : Never give up! Never surrender! -\w*ever -find() 'Never' start = 0 end = 5 -find() 'Never' start = 15 end = 20 -lookingAt() start = 0 end = 5 -Never.*?! -find() 'Never give up!' start = 0 end = 14 -find() 'Never surrender!' start = 15 end = 31 -lookingAt() start = 0 end = 14 -matches() start = 0 end = 31 -*/ diff --git a/code/strings/TestRegularExpression.java b/code/strings/TestRegularExpression.java deleted file mode 100644 index fe79ce8b..00000000 --- a/code/strings/TestRegularExpression.java +++ /dev/null @@ -1,44 +0,0 @@ -// strings/TestRegularExpression.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple regular expression demonstration -// {java TestRegularExpression -// abcabcabcdefabc "abc+" "(abc)+" } -import java.util.regex.*; - -public class TestRegularExpression { - public static void main(String[] args) { - if(args.length < 2) { - System.out.println( - "Usage:\njava TestRegularExpression " + - "characterSequence regularExpression+"); - System.exit(0); - } - System.out.println("Input: \"" + args[0] + "\""); - for(String arg : args) { - System.out.println( - "Regular expression: \"" + arg + "\""); - Pattern p = Pattern.compile(arg); - Matcher m = p.matcher(args[0]); - while(m.find()) { - System.out.println( - "Match \"" + m.group() + "\" at positions " + - m.start() + "-" + (m.end() - 1)); - } - } - } -} -/* Output: -Input: "abcabcabcdefabc" -Regular expression: "abcabcabcdefabc" -Match "abcabcabcdefabc" at positions 0-14 -Regular expression: "abc+" -Match "abc" at positions 0-2 -Match "abc" at positions 3-5 -Match "abc" at positions 6-8 -Match "abc" at positions 12-14 -Regular expression: "(abc)+" -Match "abcabcabc" at positions 0-8 -Match "abc" at positions 12-14 -*/ diff --git a/code/strings/TheReplacements.java b/code/strings/TheReplacements.java deleted file mode 100644 index 2319552f..00000000 --- a/code/strings/TheReplacements.java +++ /dev/null @@ -1,57 +0,0 @@ -// strings/TheReplacements.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; -import java.nio.file.*; -import java.util.stream.*; - -/*! Here's a block of text to use as input to - the regular expression matcher. Note that we - first extract the block of text by looking for - the special delimiters, then process the - extracted block. !*/ - -public class TheReplacements { - public static void - main(String[] args) throws Exception { - String s = Files.lines( - Paths.get("TheReplacements.java")) - .collect(Collectors.joining("\n")); - // Match specially commented block of text above: - Matcher mInput = Pattern.compile( - "/\\*!(.*)!\\*/", Pattern.DOTALL).matcher(s); - if(mInput.find()) - s = mInput.group(1); // Captured by parentheses - // Replace two or more spaces with a single space: - s = s.replaceAll(" {2,}", " "); - // Replace 1+ spaces at the beginning of each - // line with no spaces. Must enable MULTILINE mode: - s = s.replaceAll("(?m)^ +", ""); - System.out.println(s); - s = s.replaceFirst("[aeiou]", "(VOWEL1)"); - StringBuffer sbuf = new StringBuffer(); - Pattern p = Pattern.compile("[aeiou]"); - Matcher m = p.matcher(s); - // Process the find information as you - // perform the replacements: - while(m.find()) - m.appendReplacement( - sbuf, m.group().toUpperCase()); - // Put in the remainder of the text: - m.appendTail(sbuf); - System.out.println(sbuf); - } -} -/* Output: -Here's a block of text to use as input to -the regular expression matcher. Note that we -first extract the block of text by looking for -the special delimiters, then process the -extracted block. -H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO -thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE -fIrst ExtrAct thE blOck Of tExt by lOOkIng fOr -thE spEcIAl dElImItErs, thEn prOcEss thE -ExtrActEd blOck. -*/ diff --git a/code/strings/ThreatAnalyzer.java b/code/strings/ThreatAnalyzer.java deleted file mode 100644 index fc145c86..00000000 --- a/code/strings/ThreatAnalyzer.java +++ /dev/null @@ -1,36 +0,0 @@ -// strings/ThreatAnalyzer.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.regex.*; -import java.util.*; - -public class ThreatAnalyzer { - static String threatData = - "58.27.82.161@08/10/2015\n" + - "204.45.234.40@08/11/2015\n" + - "58.27.82.161@08/11/2015\n" + - "58.27.82.161@08/12/2015\n" + - "58.27.82.161@08/12/2015\n" + - "[Next log section with different data format]"; - public static void main(String[] args) { - Scanner scanner = new Scanner(threatData); - String pattern = "(\\d+[.]\\d+[.]\\d+[.]\\d+)@" + - "(\\d{2}/\\d{2}/\\d{4})"; - while(scanner.hasNext(pattern)) { - scanner.next(pattern); - MatchResult match = scanner.match(); - String ip = match.group(1); - String date = match.group(2); - System.out.format( - "Threat on %s from %s%n", date,ip); - } - } -} -/* Output: -Threat on 08/10/2015 from 58.27.82.161 -Threat on 08/11/2015 from 204.45.234.40 -Threat on 08/11/2015 from 58.27.82.161 -Threat on 08/12/2015 from 58.27.82.161 -Threat on 08/12/2015 from 58.27.82.161 -*/ diff --git a/code/strings/Turtle.java b/code/strings/Turtle.java deleted file mode 100644 index 68977bfc..00000000 --- a/code/strings/Turtle.java +++ /dev/null @@ -1,40 +0,0 @@ -// strings/Turtle.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.io.*; -import java.util.*; - -public class Turtle { - private String name; - private Formatter f; - public Turtle(String name, Formatter f) { - this.name = name; - this.f = f; - } - public void move(int x, int y) { - f.format("%s The Turtle is at (%d,%d)%n", - name, x, y); - } - public static void main(String[] args) { - PrintStream outAlias = System.out; - Turtle tommy = new Turtle("Tommy", - new Formatter(System.out)); - Turtle terry = new Turtle("Terry", - new Formatter(outAlias)); - tommy.move(0,0); - terry.move(4,8); - tommy.move(3,4); - terry.move(2,5); - tommy.move(3,3); - terry.move(3,3); - } -} -/* Output: -Tommy The Turtle is at (0,0) -Terry The Turtle is at (4,8) -Tommy The Turtle is at (3,4) -Terry The Turtle is at (2,5) -Tommy The Turtle is at (3,3) -Terry The Turtle is at (3,3) -*/ diff --git a/code/strings/UsingStringBuilder.java b/code/strings/UsingStringBuilder.java deleted file mode 100644 index 0ff32410..00000000 --- a/code/strings/UsingStringBuilder.java +++ /dev/null @@ -1,37 +0,0 @@ -// strings/UsingStringBuilder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; -import java.util.stream.*; - -public class UsingStringBuilder { - public static String string1() { - Random rand = new Random(47); - StringBuilder result = new StringBuilder("["); - for(int i = 0; i < 25; i++) { - result.append(rand.nextInt(100)); - result.append(", "); - } - result.delete(result.length()-2, result.length()); - result.append("]"); - return result.toString(); - } - public static String string2() { - String result = new Random(47) - .ints(25, 0, 100) - .mapToObj(Integer::toString) - .collect(Collectors.joining(", ")); - return "[" + result + "]"; - } - public static void main(String[] args) { - System.out.println(string1()); - System.out.println(string2()); - } -} -/* Output: -[58, 55, 93, 61, 61, 29, 68, 0, 22, 7, 88, 28, 51, 89, -9, 78, 98, 61, 20, 58, 16, 40, 11, 22, 4] -[58, 55, 93, 61, 61, 29, 68, 0, 22, 7, 88, 28, 51, 89, -9, 78, 98, 61, 20, 58, 16, 40, 11, 22, 4] -*/ diff --git a/code/strings/WhitherStringBuilder.java b/code/strings/WhitherStringBuilder.java deleted file mode 100644 index 0c46cae3..00000000 --- a/code/strings/WhitherStringBuilder.java +++ /dev/null @@ -1,21 +0,0 @@ -// strings/WhitherStringBuilder.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class WhitherStringBuilder { - public String implicit(String[] fields) { - String result = ""; - for(String field : fields) { - result += field; - } - return result; - } - public String explicit(String[] fields) { - StringBuilder result = new StringBuilder(); - for(String field : fields) { - result.append(field); - } - return result.toString(); - } -} diff --git a/code/typeinfo/AnonymousImplementation.java b/code/typeinfo/AnonymousImplementation.java deleted file mode 100644 index 34fa7832..00000000 --- a/code/typeinfo/AnonymousImplementation.java +++ /dev/null @@ -1,50 +0,0 @@ -// typeinfo/AnonymousImplementation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Anonymous inner classes can't hide from reflection -import typeinfo.interfacea.*; - -class AnonymousA { - public static A makeA() { - return new A() { - public void f() { - System.out.println("public C.f()"); - } - public void g() { - System.out.println("public C.g()"); - } - void u() { - System.out.println("package C.u()"); - } - protected void v() { - System.out.println("protected C.v()"); - } - private void w() { - System.out.println("private C.w()"); - } - }; - } -} - -public class AnonymousImplementation { - public static void - main(String[] args) throws Exception { - A a = AnonymousA.makeA(); - a.f(); - System.out.println(a.getClass().getName()); - // Reflection still gets into the anonymous class: - HiddenImplementation.callHiddenMethod(a, "g"); - HiddenImplementation.callHiddenMethod(a, "u"); - HiddenImplementation.callHiddenMethod(a, "v"); - HiddenImplementation.callHiddenMethod(a, "w"); - } -} -/* Output: -public C.f() -AnonymousA$1 -public C.g() -package C.u() -protected C.v() -private C.w() -*/ diff --git a/code/typeinfo/BoundedClassReferences.java b/code/typeinfo/BoundedClassReferences.java deleted file mode 100644 index ed0945e6..00000000 --- a/code/typeinfo/BoundedClassReferences.java +++ /dev/null @@ -1,13 +0,0 @@ -// typeinfo/BoundedClassReferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class BoundedClassReferences { - public static void main(String[] args) { - Class bounded = int.class; - bounded = double.class; - bounded = Number.class; - // Or anything else derived from Number. - } -} diff --git a/code/typeinfo/ClassCasts.java b/code/typeinfo/ClassCasts.java deleted file mode 100644 index fd0e17cf..00000000 --- a/code/typeinfo/ClassCasts.java +++ /dev/null @@ -1,16 +0,0 @@ -// typeinfo/ClassCasts.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -class Building {} -class House extends Building {} - -public class ClassCasts { - public static void main(String[] args) { - Building b = new House(); - Class houseType = House.class; - House h = houseType.cast(b); - h = (House)b; // ... or just do this. - } -} diff --git a/code/typeinfo/ClassInitialization.java b/code/typeinfo/ClassInitialization.java deleted file mode 100644 index ba1d50e8..00000000 --- a/code/typeinfo/ClassInitialization.java +++ /dev/null @@ -1,57 +0,0 @@ -// typeinfo/ClassInitialization.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class Initable { - static final int STATIC_FINAL = 47; - static final int STATIC_FINAL2 = - ClassInitialization.rand.nextInt(1000); - static { - System.out.println("Initializing Initable"); - } -} - -class Initable2 { - static int staticNonFinal = 147; - static { - System.out.println("Initializing Initable2"); - } -} - -class Initable3 { - static int staticNonFinal = 74; - static { - System.out.println("Initializing Initable3"); - } -} - -public class ClassInitialization { - public static Random rand = new Random(47); - public static void - main(String[] args) throws Exception { - Class initable = Initable.class; - System.out.println("After creating Initable ref"); - // Does not trigger initialization: - System.out.println(Initable.STATIC_FINAL); - // Does trigger initialization: - System.out.println(Initable.STATIC_FINAL2); - // Does trigger initialization: - System.out.println(Initable2.staticNonFinal); - Class initable3 = Class.forName("Initable3"); - System.out.println("After creating Initable3 ref"); - System.out.println(Initable3.staticNonFinal); - } -} -/* Output: -After creating Initable ref -47 -Initializing Initable -258 -Initializing Initable2 -147 -Initializing Initable3 -After creating Initable3 ref -74 -*/ diff --git a/code/typeinfo/DynamicSupplier.java b/code/typeinfo/DynamicSupplier.java deleted file mode 100644 index 271af639..00000000 --- a/code/typeinfo/DynamicSupplier.java +++ /dev/null @@ -1,42 +0,0 @@ -// typeinfo/DynamicSupplier.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; -import java.util.stream.*; - -class CountedInteger { - private static long counter; - private final long id = counter++; - @Override - public String toString() { return Long.toString(id); } -} - -public class DynamicSupplier implements Supplier { - private Class type; - public DynamicSupplier(Class type) { - this.type = type; - } - @SuppressWarnings("deprecation") - public T get() { - try { - return type.newInstance(); - } catch(Exception e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) { - Stream.generate( - new DynamicSupplier<>(CountedInteger.class)) - .skip(10) - .limit(5) - .forEach(System.out::println); - } -} -/* Output: -10 -11 -12 -13 -14 -*/ diff --git a/code/typeinfo/FamilyVsExactType.java b/code/typeinfo/FamilyVsExactType.java deleted file mode 100644 index 5981bbe6..00000000 --- a/code/typeinfo/FamilyVsExactType.java +++ /dev/null @@ -1,62 +0,0 @@ -// typeinfo/FamilyVsExactType.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// The difference between instanceof and class -// {java typeinfo.FamilyVsExactType} -package typeinfo; - -class Base {} -class Derived extends Base {} - -public class FamilyVsExactType { - static void test(Object x) { - System.out.println( - "Testing x of type " + x.getClass()); - System.out.println( - "x instanceof Base " + (x instanceof Base)); - System.out.println( - "x instanceof Derived " + (x instanceof Derived)); - System.out.println( - "Base.isInstance(x) " + Base.class.isInstance(x)); - System.out.println( - "Derived.isInstance(x) " + - Derived.class.isInstance(x)); - System.out.println( - "x.getClass() == Base.class " + - (x.getClass() == Base.class)); - System.out.println( - "x.getClass() == Derived.class " + - (x.getClass() == Derived.class)); - System.out.println( - "x.getClass().equals(Base.class)) "+ - (x.getClass().equals(Base.class))); - System.out.println( - "x.getClass().equals(Derived.class)) " + - (x.getClass().equals(Derived.class))); - } - public static void main(String[] args) { - test(new Base()); - test(new Derived()); - } -} -/* Output: -Testing x of type class typeinfo.Base -x instanceof Base true -x instanceof Derived false -Base.isInstance(x) true -Derived.isInstance(x) false -x.getClass() == Base.class true -x.getClass() == Derived.class false -x.getClass().equals(Base.class)) true -x.getClass().equals(Derived.class)) false -Testing x of type class typeinfo.Derived -x instanceof Base true -x instanceof Derived true -Base.isInstance(x) true -Derived.isInstance(x) true -x.getClass() == Base.class false -x.getClass() == Derived.class true -x.getClass().equals(Base.class)) false -x.getClass().equals(Derived.class)) true -*/ diff --git a/code/typeinfo/GenericClassReferences.java b/code/typeinfo/GenericClassReferences.java deleted file mode 100644 index 81ba7f7d..00000000 --- a/code/typeinfo/GenericClassReferences.java +++ /dev/null @@ -1,14 +0,0 @@ -// typeinfo/GenericClassReferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class GenericClassReferences { - public static void main(String[] args) { - Class intClass = int.class; - Class genericIntClass = int.class; - genericIntClass = Integer.class; // Same thing - intClass = double.class; - // genericIntClass = double.class; // Illegal - } -} diff --git a/code/typeinfo/HiddenImplementation.java b/code/typeinfo/HiddenImplementation.java deleted file mode 100644 index 7b41f657..00000000 --- a/code/typeinfo/HiddenImplementation.java +++ /dev/null @@ -1,44 +0,0 @@ -// typeinfo/HiddenImplementation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Sneaking around package hiding -import typeinfo.interfacea.*; -import typeinfo.packageaccess.*; -import java.lang.reflect.*; - -public class HiddenImplementation { - public static void - main(String[] args) throws Exception { - A a = HiddenC.makeA(); - a.f(); - System.out.println(a.getClass().getName()); - // Compile error: cannot find symbol 'C': - /* if(a instanceof C) { - C c = (C)a; - c.g(); - } */ - // Oops! Reflection still allows us to call g(): - callHiddenMethod(a, "g"); - // And even less accessible methods! - callHiddenMethod(a, "u"); - callHiddenMethod(a, "v"); - callHiddenMethod(a, "w"); - } - static void - callHiddenMethod(Object a, String methodName) - throws Exception { - Method g = - a.getClass().getDeclaredMethod(methodName); - g.setAccessible(true); - g.invoke(a); - } -} -/* Output: -public C.f() -typeinfo.packageaccess.C -public C.g() -package C.u() -protected C.v() -private C.w() -*/ diff --git a/code/typeinfo/InnerImplementation.java b/code/typeinfo/InnerImplementation.java deleted file mode 100644 index 2b6541fa..00000000 --- a/code/typeinfo/InnerImplementation.java +++ /dev/null @@ -1,49 +0,0 @@ -// typeinfo/InnerImplementation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Private inner classes can't hide from reflection -import typeinfo.interfacea.*; - -class InnerA { - private static class C implements A { - public void f() { - System.out.println("public C.f()"); - } - public void g() { - System.out.println("public C.g()"); - } - void u() { - System.out.println("package C.u()"); - } - protected void v() { - System.out.println("protected C.v()"); - } - private void w() { - System.out.println("private C.w()"); - } - } - public static A makeA() { return new C(); } -} - -public class InnerImplementation { - public static void - main(String[] args) throws Exception { - A a = InnerA.makeA(); - a.f(); - System.out.println(a.getClass().getName()); - // Reflection still gets into the private class: - HiddenImplementation.callHiddenMethod(a, "g"); - HiddenImplementation.callHiddenMethod(a, "u"); - HiddenImplementation.callHiddenMethod(a, "v"); - HiddenImplementation.callHiddenMethod(a, "w"); - } -} -/* Output: -public C.f() -InnerA$C -public C.g() -package C.u() -protected C.v() -private C.w() -*/ diff --git a/code/typeinfo/InterfaceViolation.java b/code/typeinfo/InterfaceViolation.java deleted file mode 100644 index 06b13f65..00000000 --- a/code/typeinfo/InterfaceViolation.java +++ /dev/null @@ -1,27 +0,0 @@ -// typeinfo/InterfaceViolation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Sneaking around an interface -import typeinfo.interfacea.*; - -class B implements A { - public void f() {} - public void g() {} -} - -public class InterfaceViolation { - public static void main(String[] args) { - A a = new B(); - a.f(); - // a.g(); // Compile error - System.out.println(a.getClass().getName()); - if(a instanceof B) { - B b = (B)a; - b.g(); - } - } -} -/* Output: -B -*/ diff --git a/code/typeinfo/ModifyingPrivateFields.java b/code/typeinfo/ModifyingPrivateFields.java deleted file mode 100644 index fa1a175d..00000000 --- a/code/typeinfo/ModifyingPrivateFields.java +++ /dev/null @@ -1,49 +0,0 @@ -// typeinfo/ModifyingPrivateFields.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.reflect.*; - -class WithPrivateFinalField { - private int i = 1; - private final String s = "I'm totally safe"; - private String s2 = "Am I safe?"; - @Override - public String toString() { - return "i = " + i + ", " + s + ", " + s2; - } -} - -public class ModifyingPrivateFields { - public static void - main(String[] args) throws Exception { - WithPrivateFinalField pf = - new WithPrivateFinalField(); - System.out.println(pf); - Field f = pf.getClass().getDeclaredField("i"); - f.setAccessible(true); - System.out.println( - "f.getInt(pf): " + f.getInt(pf)); - f.setInt(pf, 47); - System.out.println(pf); - f = pf.getClass().getDeclaredField("s"); - f.setAccessible(true); - System.out.println("f.get(pf): " + f.get(pf)); - f.set(pf, "No, you're not!"); - System.out.println(pf); - f = pf.getClass().getDeclaredField("s2"); - f.setAccessible(true); - System.out.println("f.get(pf): " + f.get(pf)); - f.set(pf, "No, you're not!"); - System.out.println(pf); - } -} -/* Output: -i = 1, I'm totally safe, Am I safe? -f.getInt(pf): 1 -i = 47, I'm totally safe, Am I safe? -f.get(pf): I'm totally safe -i = 47, I'm totally safe, Am I safe? -f.get(pf): Am I safe? -i = 47, I'm totally safe, No, you're not! -*/ diff --git a/code/typeinfo/NullRobot.java b/code/typeinfo/NullRobot.java deleted file mode 100644 index d174ca94..00000000 --- a/code/typeinfo/NullRobot.java +++ /dev/null @@ -1,63 +0,0 @@ -// typeinfo/NullRobot.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using a dynamic proxy to create an Optional -import java.lang.reflect.*; -import java.util.*; -import java.util.stream.*; -import onjava.*; - -class NullRobotProxyHandler -implements InvocationHandler { - private String nullName; - private Robot proxied = new NRobot(); - NullRobotProxyHandler(Class type) { - nullName = type.getSimpleName() + " NullRobot"; - } - private class NRobot implements Null, Robot { - @Override - public String name() { return nullName; } - @Override - public String model() { return nullName; } - @Override - public List operations() { - return Collections.emptyList(); - } - } - @Override - public Object - invoke(Object proxy, Method method, Object[] args) - throws Throwable { - return method.invoke(proxied, args); - } -} - -public class NullRobot { - public static Robot - newNullRobot(Class type) { - return (Robot)Proxy.newProxyInstance( - NullRobot.class.getClassLoader(), - new Class[]{ Null.class, Robot.class }, - new NullRobotProxyHandler(type)); - } - public static void main(String[] args) { - Stream.of( - new SnowRemovalRobot("SnowBee"), - newNullRobot(SnowRemovalRobot.class) - ).forEach(Robot::test); - } -} -/* Output: -Robot name: SnowBee -Robot model: SnowBot Series 11 -SnowBee can shovel snow -SnowBee shoveling snow -SnowBee can chip ice -SnowBee chipping ice -SnowBee can clear the roof -SnowBee clearing roof -[Null Robot] -Robot name: SnowRemovalRobot NullRobot -Robot model: SnowRemovalRobot NullRobot -*/ diff --git a/code/typeinfo/Operation.java b/code/typeinfo/Operation.java deleted file mode 100644 index dc872230..00000000 --- a/code/typeinfo/Operation.java +++ /dev/null @@ -1,15 +0,0 @@ -// typeinfo/Operation.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.function.*; - -public class Operation { - public final Supplier description; - public final Runnable command; - public - Operation(Supplier descr, Runnable cmd) { - description = descr; - command = cmd; - } -} diff --git a/code/typeinfo/Person.java b/code/typeinfo/Person.java deleted file mode 100644 index 7a9807c0..00000000 --- a/code/typeinfo/Person.java +++ /dev/null @@ -1,49 +0,0 @@ -// typeinfo/Person.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using Optional with regular classes -import onjava.*; -import java.util.*; - -class Person { - public final Optional first; - public final Optional last; - public final Optional address; - // etc. - public final boolean empty; - Person(String first, String last, String address) { - this.first = Optional.ofNullable(first); - this.last = Optional.ofNullable(last); - this.address = Optional.ofNullable(address); - empty = !this.first.isPresent() - && !this.last.isPresent() - && !this.address.isPresent(); - } - Person(String first, String last) { - this(first, last, null); - } - Person(String last) { this(null, last, null); } - Person() { this(null, null, null); } - @Override - public String toString() { - if(empty) - return ""; - return (first.orElse("") + - " " + last.orElse("") + - " " + address.orElse("")).trim(); - } - public static void main(String[] args) { - System.out.println(new Person()); - System.out.println(new Person("Smith")); - System.out.println(new Person("Bob", "Smith")); - System.out.println(new Person("Bob", "Smith", - "11 Degree Lane, Frostbite Falls, MN")); - } -} -/* Output: - -Smith -Bob Smith -Bob Smith 11 Degree Lane, Frostbite Falls, MN -*/ diff --git a/code/typeinfo/PetCount.java b/code/typeinfo/PetCount.java deleted file mode 100644 index 53438d29..00000000 --- a/code/typeinfo/PetCount.java +++ /dev/null @@ -1,65 +0,0 @@ -// typeinfo/PetCount.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using instanceof -import typeinfo.pets.*; -import java.util.*; - -public class PetCount { - static class Counter extends HashMap { - public void count(String type) { - Integer quantity = get(type); - if(quantity == null) - put(type, 1); - else - put(type, quantity + 1); - } - } - public static void - countPets(PetCreator creator) { - Counter counter = new Counter(); - for(Pet pet : Pets.array(20)) { - // List each individual pet: - System.out.print( - pet.getClass().getSimpleName() + " "); - if(pet instanceof Pet) - counter.count("Pet"); - if(pet instanceof Dog) - counter.count("Dog"); - if(pet instanceof Mutt) - counter.count("Mutt"); - if(pet instanceof Pug) - counter.count("Pug"); - if(pet instanceof Cat) - counter.count("Cat"); - if(pet instanceof EgyptianMau) - counter.count("EgyptianMau"); - if(pet instanceof Manx) - counter.count("Manx"); - if(pet instanceof Cymric) - counter.count("Cymric"); - if(pet instanceof Rodent) - counter.count("Rodent"); - if(pet instanceof Rat) - counter.count("Rat"); - if(pet instanceof Mouse) - counter.count("Mouse"); - if(pet instanceof Hamster) - counter.count("Hamster"); - } - // Show the counts: - System.out.println(); - System.out.println(counter); - } - public static void main(String[] args) { - countPets(new ForNameCreator()); - } -} -/* Output: -Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat -EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse -Pug Mouse Cymric -{EgyptianMau=2, Pug=3, Rat=2, Cymric=5, Mouse=2, Cat=9, -Manx=7, Rodent=5, Mutt=3, Dog=6, Pet=20, Hamster=1} -*/ diff --git a/code/typeinfo/PetCount2.java b/code/typeinfo/PetCount2.java deleted file mode 100644 index c65e0138..00000000 --- a/code/typeinfo/PetCount2.java +++ /dev/null @@ -1,18 +0,0 @@ -// typeinfo/PetCount2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; - -public class PetCount2 { - public static void main(String[] args) { - PetCount.countPets(Pets.CREATOR); - } -} -/* Output: -Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat -EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse -Pug Mouse Cymric -{EgyptianMau=2, Pug=3, Rat=2, Cymric=5, Mouse=2, Cat=9, -Manx=7, Rodent=5, Mutt=3, Dog=6, Pet=20, Hamster=1} -*/ diff --git a/code/typeinfo/PetCount3.java b/code/typeinfo/PetCount3.java deleted file mode 100644 index 5b08fb66..00000000 --- a/code/typeinfo/PetCount3.java +++ /dev/null @@ -1,53 +0,0 @@ -// typeinfo/PetCount3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using isInstance() -import java.util.*; -import java.util.stream.*; -import onjava.*; -import typeinfo.pets.*; - -public class PetCount3 { - static class Counter extends - LinkedHashMap, Integer> { - Counter() { - super(LiteralPetCreator.ALL_TYPES.stream() - .map(lpc -> Pair.make(lpc, 0)) - .collect( - Collectors.toMap(Pair::key, Pair::value))); - } - public void count(Pet pet) { - // Class.isInstance() eliminates instanceofs: - entrySet().stream() - .filter(pair -> pair.getKey().isInstance(pet)) - .forEach(pair -> - put(pair.getKey(), pair.getValue() + 1)); - } - @Override - public String toString() { - String result = entrySet().stream() - .map(pair -> String.format("%s=%s", - pair.getKey().getSimpleName(), - pair.getValue())) - .collect(Collectors.joining(", ")); - return "{" + result + "}"; - } - } - public static void main(String[] args) { - Counter petCount = new Counter(); - Pets.stream() - .limit(20) - .peek(petCount::count) - .forEach(p -> System.out.print( - p.getClass().getSimpleName() + " ")); - System.out.println("\n" + petCount); - } -} -/* Output: -Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat -EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse -Pug Mouse Cymric -{Rat=2, Pug=3, Mutt=3, Mouse=2, Cat=9, Dog=6, Cymric=5, -EgyptianMau=2, Rodent=5, Hamster=1, Manx=7, Pet=20} -*/ diff --git a/code/typeinfo/PetCount4.java b/code/typeinfo/PetCount4.java deleted file mode 100644 index 1ea4873a..00000000 --- a/code/typeinfo/PetCount4.java +++ /dev/null @@ -1,26 +0,0 @@ -// typeinfo/PetCount4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import typeinfo.pets.*; -import onjava.*; - -public class PetCount4 { - public static void main(String[] args) { - TypeCounter counter = new TypeCounter(Pet.class); - Pets.stream() - .limit(20) - .peek(counter::count) - .forEach(p -> System.out.print( - p.getClass().getSimpleName() + " ")); - System.out.println("\n" + counter); - } -} -/* Output: -Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat -EgyptianMau Hamster EgyptianMau Mutt Mutt Cymric Mouse -Pug Mouse Cymric -{Dog=6, Manx=7, Cat=9, Rodent=5, Hamster=1, Rat=2, -Pug=3, Mutt=3, Cymric=5, EgyptianMau=2, Pet=20, -Mouse=2} -*/ diff --git a/code/typeinfo/Position.java b/code/typeinfo/Position.java deleted file mode 100644 index ca81643b..00000000 --- a/code/typeinfo/Position.java +++ /dev/null @@ -1,51 +0,0 @@ -// typeinfo/Position.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -class EmptyTitleException extends RuntimeException {} - -class Position { - private String title; - private Person person; - Position(String jobTitle, Person employee) { - setTitle(jobTitle); - setPerson(employee); - } - Position(String jobTitle) { - this(jobTitle, null); - } - public String getTitle() { return title; } - public void setTitle(String newTitle) { - // Throws EmptyTitleException if newTitle is null: - title = Optional.ofNullable(newTitle) - .orElseThrow(EmptyTitleException::new); - } - public Person getPerson() { return person; } - public void setPerson(Person newPerson) { - // Uses empty Person if newPerson is null: - person = Optional.ofNullable(newPerson) - .orElse(new Person()); - } - @Override - public String toString() { - return "Position: " + title + - ", Employee: " + person; - } - public static void main(String[] args) { - System.out.println(new Position("CEO")); - System.out.println(new Position("Programmer", - new Person("Arthur", "Fonzarelli"))); - try { - new Position(null); - } catch(Exception e) { - System.out.println("caught " + e); - } - } -} -/* Output: -Position: CEO, Employee: -Position: Programmer, Employee: Arthur Fonzarelli -caught EmptyTitleException -*/ diff --git a/code/typeinfo/RegisteredFactories.java b/code/typeinfo/RegisteredFactories.java deleted file mode 100644 index 7708cc4e..00000000 --- a/code/typeinfo/RegisteredFactories.java +++ /dev/null @@ -1,95 +0,0 @@ -// typeinfo/RegisteredFactories.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Registering Factories in the base class -import java.util.*; -import java.util.function.*; -import java.util.stream.*; - -class Part implements Supplier { - @Override - public String toString() { - return getClass().getSimpleName(); - } - static List> prototypes = - Arrays.asList( - new FuelFilter(), - new AirFilter(), - new CabinAirFilter(), - new OilFilter(), - new FanBelt(), - new PowerSteeringBelt(), - new GeneratorBelt() - ); - private static Random rand = new Random(47); - public Part get() { - int n = rand.nextInt(prototypes.size()); - return prototypes.get(n).get(); - } -} - -class Filter extends Part {} - -class FuelFilter extends Filter { - @Override - public FuelFilter get() { return new FuelFilter(); } -} - -class AirFilter extends Filter { - @Override - public AirFilter get() { return new AirFilter(); } -} - -class CabinAirFilter extends Filter { - @Override - public CabinAirFilter get() { - return new CabinAirFilter(); - } -} - -class OilFilter extends Filter { - @Override - public OilFilter get() { return new OilFilter(); } -} - -class Belt extends Part {} - -class FanBelt extends Belt { - @Override - public FanBelt get() { return new FanBelt(); } -} - -class GeneratorBelt extends Belt { - @Override - public GeneratorBelt get() { - return new GeneratorBelt(); - } -} - -class PowerSteeringBelt extends Belt { - @Override - public PowerSteeringBelt get() { - return new PowerSteeringBelt(); - } -} - -public class RegisteredFactories { - public static void main(String[] args) { - Stream.generate(new Part()) - .limit(10) - .forEach(System.out::println); - } -} -/* Output: -GeneratorBelt -CabinAirFilter -GeneratorBelt -AirFilter -PowerSteeringBelt -CabinAirFilter -FuelFilter -PowerSteeringBelt -PowerSteeringBelt -FuelFilter -*/ diff --git a/code/typeinfo/Robot.java b/code/typeinfo/Robot.java deleted file mode 100644 index 803ee9fe..00000000 --- a/code/typeinfo/Robot.java +++ /dev/null @@ -1,22 +0,0 @@ -// typeinfo/Robot.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import onjava.*; -import java.util.*; - -public interface Robot { - String name(); - String model(); - List operations(); - static void test(Robot r) { - if(r instanceof Null) - System.out.println("[Null Robot]"); - System.out.println("Robot name: " + r.name()); - System.out.println("Robot model: " + r.model()); - for(Operation operation : r.operations()) { - System.out.println(operation.description.get()); - operation.command.run(); - } - } -} diff --git a/code/typeinfo/SelectingMethods.java b/code/typeinfo/SelectingMethods.java deleted file mode 100644 index d87e928b..00000000 --- a/code/typeinfo/SelectingMethods.java +++ /dev/null @@ -1,69 +0,0 @@ -// typeinfo/SelectingMethods.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Looking for particular methods in a dynamic proxy -import java.lang.reflect.*; - -class MethodSelector implements InvocationHandler { - private Object proxied; - MethodSelector(Object proxied) { - this.proxied = proxied; - } - @Override - public Object - invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if(method.getName().equals("interesting")) - System.out.println( - "Proxy detected the interesting method"); - return method.invoke(proxied, args); - } -} - -interface SomeMethods { - void boring1(); - void boring2(); - void interesting(String arg); - void boring3(); -} - -class Implementation implements SomeMethods { - @Override - public void boring1() { - System.out.println("boring1"); - } - @Override - public void boring2() { - System.out.println("boring2"); - } - @Override - public void interesting(String arg) { - System.out.println("interesting " + arg); - } - @Override - public void boring3() { - System.out.println("boring3"); - } -} - -class SelectingMethods { - public static void main(String[] args) { - SomeMethods proxy = - (SomeMethods)Proxy.newProxyInstance( - SomeMethods.class.getClassLoader(), - new Class[]{ SomeMethods.class }, - new MethodSelector(new Implementation())); - proxy.boring1(); - proxy.boring2(); - proxy.interesting("bonobo"); - proxy.boring3(); - } -} -/* Output: -boring1 -boring2 -Proxy detected the interesting method -interesting bonobo -boring3 -*/ diff --git a/code/typeinfo/Shapes.java b/code/typeinfo/Shapes.java deleted file mode 100644 index 34a2bc56..00000000 --- a/code/typeinfo/Shapes.java +++ /dev/null @@ -1,39 +0,0 @@ -// typeinfo/Shapes.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.stream.*; - -abstract class Shape { - void draw() { System.out.println(this + ".draw()"); } - @Override - public abstract String toString(); -} - -class Circle extends Shape { - @Override - public String toString() { return "Circle"; } -} - -class Square extends Shape { - @Override - public String toString() { return "Square"; } -} - -class Triangle extends Shape { - @Override - public String toString() { return "Triangle"; } -} - -public class Shapes { - public static void main(String[] args) { - Stream.of( - new Circle(), new Square(), new Triangle()) - .forEach(Shape::draw); - } -} -/* Output: -Circle.draw() -Square.draw() -Triangle.draw() -*/ diff --git a/code/typeinfo/ShowMethods.java b/code/typeinfo/ShowMethods.java deleted file mode 100644 index be1b635b..00000000 --- a/code/typeinfo/ShowMethods.java +++ /dev/null @@ -1,71 +0,0 @@ -// typeinfo/ShowMethods.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using reflection to show all the methods of a class, -// even if the methods are defined in the base class -// {java ShowMethods ShowMethods} -import java.lang.reflect.*; -import java.util.regex.*; - -public class ShowMethods { - private static String usage = - "usage:\n" + - "ShowMethods qualified.class.name\n" + - "To show all methods in class or:\n" + - "ShowMethods qualified.class.name word\n" + - "To search for methods involving 'word'"; - private static Pattern p = Pattern.compile("\\w+\\."); - public static void main(String[] args) { - if(args.length < 1) { - System.out.println(usage); - System.exit(0); - } - int lines = 0; - try { - Class c = Class.forName(args[0]); - Method[] methods = c.getMethods(); - Constructor[] ctors = c.getConstructors(); - if(args.length == 1) { - for(Method method : methods) - System.out.println( - p.matcher( - method.toString()).replaceAll("")); - for(Constructor ctor : ctors) - System.out.println( - p.matcher(ctor.toString()).replaceAll("")); - lines = methods.length + ctors.length; - } else { - for(Method method : methods) - if(method.toString().contains(args[1])) { - System.out.println(p.matcher( - method.toString()).replaceAll("")); - lines++; - } - for(Constructor ctor : ctors) - if(ctor.toString().contains(args[1])) { - System.out.println(p.matcher( - ctor.toString()).replaceAll("")); - lines++; - } - } - } catch(ClassNotFoundException e) { - System.out.println("No such class: " + e); - } - } -} -/* Output: -public static void main(String[]) -public final void wait() throws InterruptedException -public final void wait(long,int) throws -InterruptedException -public final native void wait(long) throws -InterruptedException -public boolean equals(Object) -public String toString() -public native int hashCode() -public final native Class getClass() -public final native void notify() -public final native void notifyAll() -public ShowMethods() -*/ diff --git a/code/typeinfo/SimpleDynamicProxy.java b/code/typeinfo/SimpleDynamicProxy.java deleted file mode 100644 index bece57f8..00000000 --- a/code/typeinfo/SimpleDynamicProxy.java +++ /dev/null @@ -1,53 +0,0 @@ -// typeinfo/SimpleDynamicProxy.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.lang.reflect.*; - -class DynamicProxyHandler implements InvocationHandler { - private Object proxied; - DynamicProxyHandler(Object proxied) { - this.proxied = proxied; - } - @Override - public Object - invoke(Object proxy, Method method, Object[] args) - throws Throwable { - System.out.println( - "**** proxy: " + proxy.getClass() + - ", method: " + method + ", args: " + args); - if(args != null) - for(Object arg : args) - System.out.println(" " + arg); - return method.invoke(proxied, args); - } -} - -class SimpleDynamicProxy { - public static void consumer(Interface iface) { - iface.doSomething(); - iface.somethingElse("bonobo"); - } - public static void main(String[] args) { - RealObject real = new RealObject(); - consumer(real); - // Insert a proxy and call again: - Interface proxy = (Interface)Proxy.newProxyInstance( - Interface.class.getClassLoader(), - new Class[]{ Interface.class }, - new DynamicProxyHandler(real)); - consumer(proxy); - } -} -/* Output: -doSomething -somethingElse bonobo -**** proxy: class $Proxy0, method: public abstract void -Interface.doSomething(), args: null -doSomething -**** proxy: class $Proxy0, method: public abstract void -Interface.somethingElse(java.lang.String), args: -[Ljava.lang.Object;@6bc7c054 - bonobo -somethingElse bonobo -*/ diff --git a/code/typeinfo/SimpleProxyDemo.java b/code/typeinfo/SimpleProxyDemo.java deleted file mode 100644 index 24c3c2c2..00000000 --- a/code/typeinfo/SimpleProxyDemo.java +++ /dev/null @@ -1,57 +0,0 @@ -// typeinfo/SimpleProxyDemo.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -interface Interface { - void doSomething(); - void somethingElse(String arg); -} - -class RealObject implements Interface { - @Override - public void doSomething() { - System.out.println("doSomething"); - } - @Override - public void somethingElse(String arg) { - System.out.println("somethingElse " + arg); - } -} - -class SimpleProxy implements Interface { - private Interface proxied; - SimpleProxy(Interface proxied) { - this.proxied = proxied; - } - @Override - public void doSomething() { - System.out.println("SimpleProxy doSomething"); - proxied.doSomething(); - } - @Override - public void somethingElse(String arg) { - System.out.println( - "SimpleProxy somethingElse " + arg); - proxied.somethingElse(arg); - } -} - -class SimpleProxyDemo { - public static void consumer(Interface iface) { - iface.doSomething(); - iface.somethingElse("bonobo"); - } - public static void main(String[] args) { - consumer(new RealObject()); - consumer(new SimpleProxy(new RealObject())); - } -} -/* Output: -doSomething -somethingElse bonobo -SimpleProxy doSomething -doSomething -SimpleProxy somethingElse bonobo -somethingElse bonobo -*/ diff --git a/code/typeinfo/SnowRemovalRobot.java b/code/typeinfo/SnowRemovalRobot.java deleted file mode 100644 index af5b46cd..00000000 --- a/code/typeinfo/SnowRemovalRobot.java +++ /dev/null @@ -1,42 +0,0 @@ -// typeinfo/SnowRemovalRobot.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class SnowRemovalRobot implements Robot { - private String name; - public SnowRemovalRobot(String name) { - this.name = name; - } - @Override - public String name() { return name; } - @Override - public String model() { return "SnowBot Series 11"; } - private List ops = Arrays.asList( - new Operation( - () -> name + " can shovel snow", - () -> System.out.println( - name + " shoveling snow")), - new Operation( - () -> name + " can chip ice", - () -> System.out.println(name + " chipping ice")), - new Operation( - () -> name + " can clear the roof", - () -> System.out.println( - name + " clearing roof"))); - public List operations() { return ops; } - public static void main(String[] args) { - Robot.test(new SnowRemovalRobot("Slusher")); - } -} -/* Output: -Robot name: Slusher -Robot model: SnowBot Series 11 -Slusher can shovel snow -Slusher shoveling snow -Slusher can chip ice -Slusher chipping ice -Slusher can clear the roof -Slusher clearing roof -*/ diff --git a/code/typeinfo/Staff.java b/code/typeinfo/Staff.java deleted file mode 100644 index 569e598f..00000000 --- a/code/typeinfo/Staff.java +++ /dev/null @@ -1,63 +0,0 @@ -// typeinfo/Staff.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.*; - -public class Staff extends ArrayList { - public void add(String title, Person person) { - add(new Position(title, person)); - } - public void add(String... titles) { - for(String title : titles) - add(new Position(title)); - } - public Staff(String... titles) { add(titles); } - public boolean positionAvailable(String title) { - for(Position position : this) - if(position.getTitle().equals(title) && - position.getPerson().empty) - return true; - return false; - } - public void fillPosition(String title, Person hire) { - for(Position position : this) - if(position.getTitle().equals(title) && - position.getPerson().empty) { - position.setPerson(hire); - return; - } - throw new RuntimeException( - "Position " + title + " not available"); - } - public static void main(String[] args) { - Staff staff = new Staff("President", "CTO", - "Marketing Manager", "Product Manager", - "Project Lead", "Software Engineer", - "Software Engineer", "Software Engineer", - "Software Engineer", "Test Engineer", - "Technical Writer"); - staff.fillPosition("President", - new Person("Me", "Last", "The Top, Lonely At")); - staff.fillPosition("Project Lead", - new Person("Janet", "Planner", "The Burbs")); - if(staff.positionAvailable("Software Engineer")) - staff.fillPosition("Software Engineer", - new Person( - "Bob", "Coder", "Bright Light City")); - System.out.println(staff); - } -} -/* Output: -[Position: President, Employee: Me Last The Top, Lonely -At, Position: CTO, Employee: , Position: -Marketing Manager, Employee: , Position: Product -Manager, Employee: , Position: Project Lead, -Employee: Janet Planner The Burbs, Position: Software -Engineer, Employee: Bob Coder Bright Light City, -Position: Software Engineer, Employee: , -Position: Software Engineer, Employee: , -Position: Software Engineer, Employee: , -Position: Test Engineer, Employee: , Position: -Technical Writer, Employee: ] -*/ diff --git a/code/typeinfo/SweetShop.java b/code/typeinfo/SweetShop.java deleted file mode 100644 index f85b8c3f..00000000 --- a/code/typeinfo/SweetShop.java +++ /dev/null @@ -1,42 +0,0 @@ -// typeinfo/SweetShop.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Examination of the way the class loader works - -class Cookie { - static { System.out.println("Loading Cookie"); } -} - -class Gum { - static { System.out.println("Loading Gum"); } -} - -class Candy { - static { System.out.println("Loading Candy"); } -} - -public class SweetShop { - public static void main(String[] args) { - System.out.println("inside main"); - new Candy(); - System.out.println("After creating Candy"); - try { - Class.forName("Gum"); - } catch(ClassNotFoundException e) { - System.out.println("Couldn't find Gum"); - } - System.out.println("After Class.forName(\"Gum\")"); - new Cookie(); - System.out.println("After creating Cookie"); - } -} -/* Output: -inside main -Loading Candy -After creating Candy -Loading Gum -After Class.forName("Gum") -Loading Cookie -After creating Cookie -*/ diff --git a/code/typeinfo/WildcardClassReferences.java b/code/typeinfo/WildcardClassReferences.java deleted file mode 100644 index 32d75e86..00000000 --- a/code/typeinfo/WildcardClassReferences.java +++ /dev/null @@ -1,11 +0,0 @@ -// typeinfo/WildcardClassReferences.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. - -public class WildcardClassReferences { - public static void main(String[] args) { - Class intClass = int.class; - intClass = double.class; - } -} diff --git a/code/typeinfo/interfacea/A.java b/code/typeinfo/interfacea/A.java deleted file mode 100644 index 2ebb99d3..00000000 --- a/code/typeinfo/interfacea/A.java +++ /dev/null @@ -1,9 +0,0 @@ -// typeinfo/interfacea/A.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.interfacea; - -public interface A { - void f(); -} diff --git a/code/typeinfo/packageaccess/HiddenC.java b/code/typeinfo/packageaccess/HiddenC.java deleted file mode 100644 index 9fb8ffde..00000000 --- a/code/typeinfo/packageaccess/HiddenC.java +++ /dev/null @@ -1,29 +0,0 @@ -// typeinfo/packageaccess/HiddenC.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.packageaccess; -import typeinfo.interfacea.*; - -class C implements A { - @Override - public void f() { - System.out.println("public C.f()"); - } - public void g() { - System.out.println("public C.g()"); - } - void u() { - System.out.println("package C.u()"); - } - protected void v() { - System.out.println("protected C.v()"); - } - private void w() { - System.out.println("private C.w()"); - } -} - -public class HiddenC { - public static A makeA() { return new C(); } -} diff --git a/code/typeinfo/pets/Cat.java b/code/typeinfo/pets/Cat.java deleted file mode 100644 index 75781fd7..00000000 --- a/code/typeinfo/pets/Cat.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Cat.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Cat extends Pet { - public Cat(String name) { super(name); } - public Cat() { super(); } -} diff --git a/code/typeinfo/pets/Cymric.java b/code/typeinfo/pets/Cymric.java deleted file mode 100644 index fd86fa95..00000000 --- a/code/typeinfo/pets/Cymric.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Cymric.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Cymric extends Manx { - public Cymric(String name) { super(name); } - public Cymric() { super(); } -} diff --git a/code/typeinfo/pets/Dog.java b/code/typeinfo/pets/Dog.java deleted file mode 100644 index 68f43a32..00000000 --- a/code/typeinfo/pets/Dog.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Dog.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Dog extends Pet { - public Dog(String name) { super(name); } - public Dog() { super(); } -} diff --git a/code/typeinfo/pets/EgyptianMau.java b/code/typeinfo/pets/EgyptianMau.java deleted file mode 100644 index adbdfbb1..00000000 --- a/code/typeinfo/pets/EgyptianMau.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/EgyptianMau.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class EgyptianMau extends Cat { - public EgyptianMau(String name) { super(name); } - public EgyptianMau() { super(); } -} diff --git a/code/typeinfo/pets/ForNameCreator.java b/code/typeinfo/pets/ForNameCreator.java deleted file mode 100644 index 29351efa..00000000 --- a/code/typeinfo/pets/ForNameCreator.java +++ /dev/null @@ -1,37 +0,0 @@ -// typeinfo/pets/ForNameCreator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; -import java.util.*; - -public class ForNameCreator extends PetCreator { - private static List> types = - new ArrayList<>(); - // Types you want randomly created: - private static String[] typeNames = { - "typeinfo.pets.Mutt", - "typeinfo.pets.Pug", - "typeinfo.pets.EgyptianMau", - "typeinfo.pets.Manx", - "typeinfo.pets.Cymric", - "typeinfo.pets.Rat", - "typeinfo.pets.Mouse", - "typeinfo.pets.Hamster" - }; - @SuppressWarnings("unchecked") - private static void loader() { - try { - for(String name : typeNames) - types.add( - (Class)Class.forName(name)); - } catch(ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - static { loader(); } - @Override - public List> types() { - return types; - } -} diff --git a/code/typeinfo/pets/Hamster.java b/code/typeinfo/pets/Hamster.java deleted file mode 100644 index 8408ef62..00000000 --- a/code/typeinfo/pets/Hamster.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Hamster.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Hamster extends Rodent { - public Hamster(String name) { super(name); } - public Hamster() { super(); } -} diff --git a/code/typeinfo/pets/Individual.java b/code/typeinfo/pets/Individual.java deleted file mode 100644 index e3c87dac..00000000 --- a/code/typeinfo/pets/Individual.java +++ /dev/null @@ -1,46 +0,0 @@ -// typeinfo/pets/Individual.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; -import java.util.*; - -public class -Individual implements Comparable { - private static long counter = 0; - private final long id = counter++; - private String name; - public Individual(String name) { this.name = name; } - // 'name' is optional: - public Individual() {} - @Override - public String toString() { - return getClass().getSimpleName() + - (name == null ? "" : " " + name); - } - public long id() { return id; } - @Override - public boolean equals(Object o) { - return o instanceof Individual && - Objects.equals(id, ((Individual)o).id); - } - @Override - public int hashCode() { - return Objects.hash(name, id); - } - @Override - public int compareTo(Individual arg) { - // Compare by class name first: - String first = getClass().getSimpleName(); - String argFirst = arg.getClass().getSimpleName(); - int firstCompare = first.compareTo(argFirst); - if(firstCompare != 0) - return firstCompare; - if(name != null && arg.name != null) { - int secondCompare = name.compareTo(arg.name); - if(secondCompare != 0) - return secondCompare; - } - return (arg.id < id ? -1 : (arg.id == id ? 0 : 1)); - } -} diff --git a/code/typeinfo/pets/LiteralPetCreator.java b/code/typeinfo/pets/LiteralPetCreator.java deleted file mode 100644 index 398baac8..00000000 --- a/code/typeinfo/pets/LiteralPetCreator.java +++ /dev/null @@ -1,39 +0,0 @@ -// typeinfo/pets/LiteralPetCreator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using class literals -// {java typeinfo.pets.LiteralPetCreator} -package typeinfo.pets; -import java.util.*; - -public class LiteralPetCreator extends PetCreator { - // No try block needed. - @SuppressWarnings("unchecked") - public static - final List> ALL_TYPES = - Collections.unmodifiableList(Arrays.asList( - Pet.class, Dog.class, Cat.class, Rodent.class, - Mutt.class, Pug.class, EgyptianMau.class, - Manx.class, Cymric.class, Rat.class, - Mouse.class, Hamster.class)); - // Types for random creation: - private static final - List> TYPES = - ALL_TYPES.subList(ALL_TYPES.indexOf(Mutt.class), - ALL_TYPES.size()); - @Override - public List> types() { - return TYPES; - } - public static void main(String[] args) { - System.out.println(TYPES); - } -} -/* Output: -[class typeinfo.pets.Mutt, class typeinfo.pets.Pug, -class typeinfo.pets.EgyptianMau, class -typeinfo.pets.Manx, class typeinfo.pets.Cymric, class -typeinfo.pets.Rat, class typeinfo.pets.Mouse, class -typeinfo.pets.Hamster] -*/ diff --git a/code/typeinfo/pets/Manx.java b/code/typeinfo/pets/Manx.java deleted file mode 100644 index 6a5534b1..00000000 --- a/code/typeinfo/pets/Manx.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Manx.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Manx extends Cat { - public Manx(String name) { super(name); } - public Manx() { super(); } -} diff --git a/code/typeinfo/pets/Mouse.java b/code/typeinfo/pets/Mouse.java deleted file mode 100644 index bbb97cda..00000000 --- a/code/typeinfo/pets/Mouse.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Mouse.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Mouse extends Rodent { - public Mouse(String name) { super(name); } - public Mouse() { super(); } -} diff --git a/code/typeinfo/pets/Mutt.java b/code/typeinfo/pets/Mutt.java deleted file mode 100644 index f51814b9..00000000 --- a/code/typeinfo/pets/Mutt.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Mutt.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Mutt extends Dog { - public Mutt(String name) { super(name); } - public Mutt() { super(); } -} diff --git a/code/typeinfo/pets/Person.java b/code/typeinfo/pets/Person.java deleted file mode 100644 index 4dcfff2c..00000000 --- a/code/typeinfo/pets/Person.java +++ /dev/null @@ -1,9 +0,0 @@ -// typeinfo/pets/Person.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Person extends Individual { - public Person(String name) { super(name); } -} diff --git a/code/typeinfo/pets/Pet.java b/code/typeinfo/pets/Pet.java deleted file mode 100644 index dcbfd4ab..00000000 --- a/code/typeinfo/pets/Pet.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Pet.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Pet extends Individual { - public Pet(String name) { super(name); } - public Pet() { super(); } -} diff --git a/code/typeinfo/pets/PetCreator.java b/code/typeinfo/pets/PetCreator.java deleted file mode 100644 index 76909aa9..00000000 --- a/code/typeinfo/pets/PetCreator.java +++ /dev/null @@ -1,28 +0,0 @@ -// typeinfo/pets/PetCreator.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Creates random sequences of Pets -package typeinfo.pets; -import java.util.*; -import java.util.function.*; -import java.lang.reflect.InvocationTargetException; - -public abstract -class PetCreator implements Supplier { - private Random rand = new Random(47); - // The List of the different types of Pet to create: - public abstract List> types(); - public Pet get() { // Create one random Pet - int n = rand.nextInt(types().size()); - try { - return types().get(n) - .getConstructor().newInstance(); - } catch(InstantiationException | - NoSuchMethodException | - InvocationTargetException | - IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/code/typeinfo/pets/Pets.java b/code/typeinfo/pets/Pets.java deleted file mode 100644 index be3037a1..00000000 --- a/code/typeinfo/pets/Pets.java +++ /dev/null @@ -1,30 +0,0 @@ -// typeinfo/pets/Pets.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Facade to produce a default PetCreator -package typeinfo.pets; -import java.util.*; -import java.util.stream.*; - -public class Pets { - public static final PetCreator CREATOR = - new LiteralPetCreator(); - public static Pet get() { - return CREATOR.get(); - } - public static Pet[] array(int size) { - Pet[] result = new Pet[size]; - for(int i = 0; i < size; i++) - result[i] = CREATOR.get(); - return result; - } - public static List list(int size) { - List result = new ArrayList<>(); - Collections.addAll(result, array(size)); - return result; - } - public static Stream stream() { - return Stream.generate(CREATOR); - } -} diff --git a/code/typeinfo/pets/Pug.java b/code/typeinfo/pets/Pug.java deleted file mode 100644 index 9d8ab467..00000000 --- a/code/typeinfo/pets/Pug.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Pug.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Pug extends Dog { - public Pug(String name) { super(name); } - public Pug() { super(); } -} diff --git a/code/typeinfo/pets/Rat.java b/code/typeinfo/pets/Rat.java deleted file mode 100644 index 2ce5534b..00000000 --- a/code/typeinfo/pets/Rat.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Rat.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Rat extends Rodent { - public Rat(String name) { super(name); } - public Rat() { super(); } -} diff --git a/code/typeinfo/pets/Rodent.java b/code/typeinfo/pets/Rodent.java deleted file mode 100644 index 7b998d0a..00000000 --- a/code/typeinfo/pets/Rodent.java +++ /dev/null @@ -1,10 +0,0 @@ -// typeinfo/pets/Rodent.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package typeinfo.pets; - -public class Rodent extends Pet { - public Rodent(String name) { super(name); } - public Rodent() { super(); } -} diff --git a/code/typeinfo/toys/GenericToyTest.java b/code/typeinfo/toys/GenericToyTest.java deleted file mode 100644 index 7dc016cd..00000000 --- a/code/typeinfo/toys/GenericToyTest.java +++ /dev/null @@ -1,23 +0,0 @@ -// typeinfo/toys/GenericToyTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Testing class Class -// {java typeinfo.toys.GenericToyTest} -package typeinfo.toys; - -public class GenericToyTest { - @SuppressWarnings("deprecation") - public static void - main(String[] args) throws Exception { - Class ftClass = FancyToy.class; - // Produces exact type: - FancyToy fancyToy = ftClass.newInstance(); - Class up = - ftClass.getSuperclass(); - // This won't compile: - // Class up2 = ftClass.getSuperclass(); - // Only produces Object: - Object obj = up.newInstance(); - } -} diff --git a/code/typeinfo/toys/ToyTest.java b/code/typeinfo/toys/ToyTest.java deleted file mode 100644 index e4e5e92d..00000000 --- a/code/typeinfo/toys/ToyTest.java +++ /dev/null @@ -1,78 +0,0 @@ -// typeinfo/toys/ToyTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Testing class Class -// {java typeinfo.toys.ToyTest} -package typeinfo.toys; -import java.lang.reflect.InvocationTargetException; - -interface HasBatteries {} -interface Waterproof {} -interface Shoots {} - -class Toy { - // Comment out the following no-arg - // constructor to see NoSuchMethodError - Toy() {} - Toy(int i) {} -} - -class FancyToy extends Toy -implements HasBatteries, Waterproof, Shoots { - FancyToy() { super(1); } -} - -public class ToyTest { - static void printInfo(Class cc) { - System.out.println("Class name: " + cc.getName() + - " is interface? [" + cc.isInterface() + "]"); - System.out.println( - "Simple name: " + cc.getSimpleName()); - System.out.println( - "Canonical name : " + cc.getCanonicalName()); - } - @SuppressWarnings("deprecation") - public static void main(String[] args) { - Class c = null; - try { - c = Class.forName("typeinfo.toys.FancyToy"); - } catch(ClassNotFoundException e) { - System.out.println("Can't find FancyToy"); - System.exit(1); - } - printInfo(c); - for(Class face : c.getInterfaces()) - printInfo(face); - Class up = c.getSuperclass(); - Object obj = null; - try { - // Requires no-arg constructor: - obj = up.newInstance(); - } catch(Exception e) { - throw new - RuntimeException("Cannot instantiate"); - } - printInfo(obj.getClass()); - } -} -/* Output: -Class name: typeinfo.toys.FancyToy is interface? -[false] -Simple name: FancyToy -Canonical name : typeinfo.toys.FancyToy -Class name: typeinfo.toys.HasBatteries is interface? -[true] -Simple name: HasBatteries -Canonical name : typeinfo.toys.HasBatteries -Class name: typeinfo.toys.Waterproof is interface? -[true] -Simple name: Waterproof -Canonical name : typeinfo.toys.Waterproof -Class name: typeinfo.toys.Shoots is interface? [true] -Simple name: Shoots -Canonical name : typeinfo.toys.Shoots -Class name: typeinfo.toys.Toy is interface? [false] -Simple name: Toy -Canonical name : typeinfo.toys.Toy -*/ diff --git a/code/validating/Assert1.java b/code/validating/Assert1.java deleted file mode 100644 index 013a72f6..00000000 --- a/code/validating/Assert1.java +++ /dev/null @@ -1,19 +0,0 @@ -// validating/Assert1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Non-informative style of assert -// Must run using -ea flag: -// {java -ea Assert1} -// {ThrowsException} - -public class Assert1 { - public static void main(String[] args) { - assert false; - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "main" java.lang.AssertionError - at Assert1.main(Assert1.java:9) -*/ diff --git a/code/validating/Assert2.java b/code/validating/Assert2.java deleted file mode 100644 index 61b4827d..00000000 --- a/code/validating/Assert2.java +++ /dev/null @@ -1,20 +0,0 @@ -// validating/Assert2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Assert with an information-expression -// {java Assert2 -ea} -// {ThrowsException} - -public class Assert2 { - public static void main(String[] args) { - assert false: - "Here's a message saying what happened"; - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "main" java.lang.AssertionError: -Here's a message saying what happened - at Assert2.main(Assert2.java:8) -*/ diff --git a/code/validating/BadMicroBenchmark.java b/code/validating/BadMicroBenchmark.java deleted file mode 100644 index 2634e67c..00000000 --- a/code/validating/BadMicroBenchmark.java +++ /dev/null @@ -1,29 +0,0 @@ -// validating/BadMicroBenchmark.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ExcludeFromTravisCI} -import java.util.*; -import onjava.Timer; - -public class BadMicroBenchmark { - static final int SIZE = 250_000_000; - public static void main(String[] args) { - try { // For machines with insufficient memory - long[] la = new long[SIZE]; - System.out.println("setAll: " + - Timer.duration(() -> - Arrays.setAll(la, n -> n))); - System.out.println("parallelSetAll: " + - Timer.duration(() -> - Arrays.parallelSetAll(la, n -> n))); - } catch(OutOfMemoryError e) { - System.out.println("Insufficient memory"); - System.exit(0); - } - } -} -/* Output: -setAll: 272 -parallelSetAll: 301 -*/ diff --git a/code/validating/BadMicroBenchmark2.java b/code/validating/BadMicroBenchmark2.java deleted file mode 100644 index 123036a0..00000000 --- a/code/validating/BadMicroBenchmark2.java +++ /dev/null @@ -1,35 +0,0 @@ -// validating/BadMicroBenchmark2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Relying on a common resource -import java.util.*; -import onjava.Timer; - -public class BadMicroBenchmark2 { - // SIZE reduced to make it run faster: - static final int SIZE = 5_000_000; - public static void main(String[] args) { - long[] la = new long[SIZE]; - Random r = new Random(); - System.out.println("parallelSetAll: " + - Timer.duration(() -> - Arrays.parallelSetAll(la, n -> r.nextLong()))); - System.out.println("setAll: " + - Timer.duration(() -> - Arrays.setAll(la, n -> r.nextLong()))); - SplittableRandom sr = new SplittableRandom(); - System.out.println("parallelSetAll: " + - Timer.duration(() -> - Arrays.parallelSetAll(la, n -> sr.nextLong()))); - System.out.println("setAll: " + - Timer.duration(() -> - Arrays.setAll(la, n -> sr.nextLong()))); - } -} -/* Output: -parallelSetAll: 1147 -setAll: 174 -parallelSetAll: 86 -setAll: 39 -*/ diff --git a/code/validating/CircularQueue.java b/code/validating/CircularQueue.java deleted file mode 100644 index 405e4410..00000000 --- a/code/validating/CircularQueue.java +++ /dev/null @@ -1,91 +0,0 @@ -// validating/CircularQueue.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstration of Design by Contract (DbC) -package validating; -import java.util.*; - -public class CircularQueue { - private Object[] data; - private int - in = 0, // Next available storage space - out = 0; // Next gettable object - // Has it wrapped around the circular queue? - private boolean wrapped = false; - public CircularQueue(int size) { - data = new Object[size]; - // Must be true after construction: - assert invariant(); - } - public boolean empty() { - return !wrapped && in == out; - } - public boolean full() { - return wrapped && in == out; - } - public boolean isWrapped() { return wrapped; } - public void put(Object item) { - precondition(item != null, "put() null item"); - precondition(!full(), - "put() into full CircularQueue"); - assert invariant(); - data[in++] = item; - if(in >= data.length) { - in = 0; - wrapped = true; - } - assert invariant(); - } - public Object get() { - precondition(!empty(), - "get() from empty CircularQueue"); - assert invariant(); - Object returnVal = data[out]; - data[out] = null; - out++; - if(out >= data.length) { - out = 0; - wrapped = false; - } - assert postcondition( - returnVal != null, - "Null item in CircularQueue"); - assert invariant(); - return returnVal; - } - // Design-by-contract support methods: - private static void - precondition(boolean cond, String msg) { - if(!cond) throw new CircularQueueException(msg); - } - private static boolean - postcondition(boolean cond, String msg) { - if(!cond) throw new CircularQueueException(msg); - return true; - } - private boolean invariant() { - // Guarantee that no null values are in the - // region of 'data' that holds objects: - for(int i = out; i != in; i = (i + 1) % data.length) - if(data[i] == null) - throw new CircularQueueException( - "null in CircularQueue"); - // Guarantee that only null values are outside the - // region of 'data' that holds objects: - if(full()) return true; - for(int i = in; i != out; i = (i + 1) % data.length) - if(data[i] != null) - throw new CircularQueueException( - "non-null outside of CircularQueue range: " - + dump()); - return true; - } - public String dump() { - return "in = " + in + - ", out = " + out + - ", full() = " + full() + - ", empty() = " + empty() + - ", CircularQueue = " + Arrays.asList(data); - } -} diff --git a/code/validating/CircularQueueException.java b/code/validating/CircularQueueException.java deleted file mode 100644 index 142b8ece..00000000 --- a/code/validating/CircularQueueException.java +++ /dev/null @@ -1,12 +0,0 @@ -// validating/CircularQueueException.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; - -public class -CircularQueueException extends RuntimeException { - public CircularQueueException(String why) { - super(why); - } -} diff --git a/code/validating/CountedList.java b/code/validating/CountedList.java deleted file mode 100644 index 6c780f21..00000000 --- a/code/validating/CountedList.java +++ /dev/null @@ -1,16 +0,0 @@ -// validating/CountedList.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Keeps track of how many of itself are created. -package validating; -import java.util.*; - -public class CountedList extends ArrayList { - private static int counter = 0; - private int id = counter++; - public CountedList() { - System.out.println("CountedList #" + id); - } - public int getId() { return id; } -} diff --git a/code/validating/GuavaAssertions.java b/code/validating/GuavaAssertions.java deleted file mode 100644 index a499f079..00000000 --- a/code/validating/GuavaAssertions.java +++ /dev/null @@ -1,49 +0,0 @@ -// validating/GuavaAssertions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Assertions that are always enabled. -import com.google.common.base.*; -import static com.google.common.base.Verify.*; - -public class GuavaAssertions { - public static void main(String[] args) { - verify(2 + 2 == 4); - try { - verify(1 + 2 == 4); - } catch(VerifyException e) { - System.out.println(e); - } - try { - verify(1 + 2 == 4, "Bad math"); - } catch(VerifyException e) { - System.out.println(e.getMessage()); - } - try { - verify(1 + 2 == 4, "Bad math: %s", "not 4"); - } catch(VerifyException e) { - System.out.println(e.getMessage()); - } - String s = ""; - s = verifyNotNull(s); - s = null; - try { - verifyNotNull(s); - } catch(VerifyException e) { - System.out.println(e.getMessage()); - } - try { - verifyNotNull( - s, "Shouldn't be null: %s", "arg s"); - } catch(VerifyException e) { - System.out.println(e.getMessage()); - } - } -} -/* Output: -com.google.common.base.VerifyException -Bad math -Bad math: not 4 -expected a non-null reference -Shouldn't be null: arg s -*/ diff --git a/code/validating/GuavaPreconditions.java b/code/validating/GuavaPreconditions.java deleted file mode 100644 index 3cfc66ae..00000000 --- a/code/validating/GuavaPreconditions.java +++ /dev/null @@ -1,125 +0,0 @@ -// validating/GuavaPreconditions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Demonstrating Guava Preconditions -import java.util.function.*; -import static com.google.common.base.Preconditions.*; - -public class GuavaPreconditions { - static void test(Consumer c, String s) { - try { - System.out.println(s); - c.accept(s); - System.out.println("Success"); - } catch(Exception e) { - String type = e.getClass().getSimpleName(); - String msg = e.getMessage(); - System.out.println(type + - (msg == null ? "" : ": " + msg)); - } - } - public static void main(String[] args) { - test(s -> s = checkNotNull(s), "X"); - test(s -> s = checkNotNull(s), null); - test(s -> s = checkNotNull(s, "s was null"), null); - test(s -> s = checkNotNull( - s, "s was null, %s %s", "arg2", "arg3"), null); - - test(s -> checkArgument(s == "Fozzie"), "Fozzie"); - test(s -> checkArgument(s == "Fozzie"), "X"); - test(s -> checkArgument(s == "Fozzie"), null); - test(s -> checkArgument( - s == "Fozzie", "Bear Left!"), null); - test(s -> checkArgument( - s == "Fozzie", "Bear Left! %s Right!", "Frog"), - null); - - test(s -> checkState(s.length() > 6), "Mortimer"); - test(s -> checkState(s.length() > 6), "Mort"); - test(s -> checkState(s.length() > 6), null); - - test(s -> - checkElementIndex(6, s.length()), "Robert"); - test(s -> - checkElementIndex(6, s.length()), "Bob"); - test(s -> - checkElementIndex(6, s.length()), null); - - test(s -> - checkPositionIndex(6, s.length()), "Robert"); - test(s -> - checkPositionIndex(6, s.length()), "Bob"); - test(s -> - checkPositionIndex(6, s.length()), null); - - test(s -> checkPositionIndexes( - 0, 6, s.length()), "Hieronymus"); - test(s -> checkPositionIndexes( - 0, 10, s.length()), "Hieronymus"); - test(s -> checkPositionIndexes( - 0, 11, s.length()), "Hieronymus"); - test(s -> checkPositionIndexes( - -1, 6, s.length()), "Hieronymus"); - test(s -> checkPositionIndexes( - 7, 6, s.length()), "Hieronymus"); - test(s -> checkPositionIndexes( - 0, 6, s.length()), null); - } -} -/* Output: -X -Success -null -NullPointerException -null -NullPointerException: s was null -null -NullPointerException: s was null, arg2 arg3 -Fozzie -Success -X -IllegalArgumentException -null -IllegalArgumentException -null -IllegalArgumentException: Bear Left! -null -IllegalArgumentException: Bear Left! Frog Right! -Mortimer -Success -Mort -IllegalStateException -null -NullPointerException -Robert -IndexOutOfBoundsException: index (6) must be less than -size (6) -Bob -IndexOutOfBoundsException: index (6) must be less than -size (3) -null -NullPointerException -Robert -Success -Bob -IndexOutOfBoundsException: index (6) must not be -greater than size (3) -null -NullPointerException -Hieronymus -Success -Hieronymus -Success -Hieronymus -IndexOutOfBoundsException: end index (11) must not be -greater than size (10) -Hieronymus -IndexOutOfBoundsException: start index (-1) must not be -negative -Hieronymus -IndexOutOfBoundsException: end index (6) must not be -less than start index (7) -null -NullPointerException -*/ diff --git a/code/validating/Inverter1.java b/code/validating/Inverter1.java deleted file mode 100644 index 8ef828d6..00000000 --- a/code/validating/Inverter1.java +++ /dev/null @@ -1,9 +0,0 @@ -// validating/Inverter1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; - -public class Inverter1 implements StringInverter { - public String invert(String str) { return str; } -} diff --git a/code/validating/Inverter2.java b/code/validating/Inverter2.java deleted file mode 100644 index 3fb862fd..00000000 --- a/code/validating/Inverter2.java +++ /dev/null @@ -1,19 +0,0 @@ -// validating/Inverter2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; -import static java.lang.Character.*; - -public class Inverter2 implements StringInverter { - public String invert(String str) { - String result = ""; - for(int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - result += isUpperCase(c) ? - toLowerCase(c) : - toUpperCase(c); - } - return result; - } -} diff --git a/code/validating/Inverter3.java b/code/validating/Inverter3.java deleted file mode 100644 index 4bd53c82..00000000 --- a/code/validating/Inverter3.java +++ /dev/null @@ -1,21 +0,0 @@ -// validating/Inverter3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; -import static java.lang.Character.*; - -public class Inverter3 implements StringInverter { - public String invert(String str) { - if(str.length() > 30) - throw new RuntimeException("argument too long!"); - String result = ""; - for(int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - result += isUpperCase(c) ? - toLowerCase(c) : - toUpperCase(c); - } - return result; - } -} diff --git a/code/validating/Inverter4.java b/code/validating/Inverter4.java deleted file mode 100644 index 0b787059..00000000 --- a/code/validating/Inverter4.java +++ /dev/null @@ -1,26 +0,0 @@ -// validating/Inverter4.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; -import static java.lang.Character.*; - -public class Inverter4 implements StringInverter { - static final String ALLOWED = - "abcdefghijklmnopqrstuvwxyz ,." + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - public String invert(String str) { - if(str.length() > 30) - throw new RuntimeException("argument too long!"); - String result = ""; - for(int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if(ALLOWED.indexOf(c) == -1) - throw new RuntimeException(c + " Not allowed"); - result += isUpperCase(c) ? - toLowerCase(c) : - toUpperCase(c); - } - return result; - } -} diff --git a/code/validating/LoaderAssertions.java b/code/validating/LoaderAssertions.java deleted file mode 100644 index 52cac347..00000000 --- a/code/validating/LoaderAssertions.java +++ /dev/null @@ -1,28 +0,0 @@ -// validating/LoaderAssertions.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Using the class loader to enable assertions -// {ThrowsException} - -public class LoaderAssertions { - public static void main(String[] args) { - ClassLoader.getSystemClassLoader() - .setDefaultAssertionStatus(true); - new Loaded().go(); - } -} - -class Loaded { - public void go() { - assert false: "Loaded.go()"; - } -} -/* Output: -___[ Error Output ]___ -Exception in thread "main" java.lang.AssertionError: -Loaded.go() - at Loaded.go(LoaderAssertions.java:15) - at -LoaderAssertions.main(LoaderAssertions.java:9) -*/ diff --git a/code/validating/NonNullConstruction.java b/code/validating/NonNullConstruction.java deleted file mode 100644 index a95483dd..00000000 --- a/code/validating/NonNullConstruction.java +++ /dev/null @@ -1,18 +0,0 @@ -// validating/NonNullConstruction.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import static com.google.common.base.Preconditions.*; - -public class NonNullConstruction { - private Integer n; - private String s; - NonNullConstruction(Integer n, String s) { - this.n = checkNotNull(n); - this.s = checkNotNull(s); - } - public static void main(String[] args) { - NonNullConstruction nnc = - new NonNullConstruction(3, "Trousers"); - } -} diff --git a/code/validating/SLF4JLevels.java b/code/validating/SLF4JLevels.java deleted file mode 100644 index c851e7c3..00000000 --- a/code/validating/SLF4JLevels.java +++ /dev/null @@ -1,29 +0,0 @@ -// validating/SLF4JLevels.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import org.slf4j.*; - -public class SLF4JLevels { - private static Logger log = - LoggerFactory.getLogger(SLF4JLevels.class); - public static void main(String[] args) { - log.trace("Hello"); - log.debug("Logging"); - log.info("Using"); - log.warn("the SLF4J"); - log.error("Facade"); - } -} -/* Output: -2017-05-09T06:07:52.846 -[main] TRACE SLF4JLevels - Hello -2017-05-09T06:07:52.849 -[main] DEBUG SLF4JLevels - Logging -2017-05-09T06:07:52.849 -[main] INFO SLF4JLevels - Using -2017-05-09T06:07:52.850 -[main] WARN SLF4JLevels - the SLF4J -2017-05-09T06:07:52.851 -[main] ERROR SLF4JLevels - Facade -*/ diff --git a/code/validating/SLF4JLogging.java b/code/validating/SLF4JLogging.java deleted file mode 100644 index f2e94d6e..00000000 --- a/code/validating/SLF4JLogging.java +++ /dev/null @@ -1,17 +0,0 @@ -// validating/SLF4JLogging.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import org.slf4j.*; - -public class SLF4JLogging { - private static Logger log = - LoggerFactory.getLogger(SLF4JLogging.class); - public static void main(String[] args) { - log.info("hello logging"); - } -} -/* Output: -2017-05-09T06:07:53.418 -[main] INFO SLF4JLogging - hello logging -*/ diff --git a/code/validating/SimpleDebugging.java b/code/validating/SimpleDebugging.java deleted file mode 100644 index 863e7de3..00000000 --- a/code/validating/SimpleDebugging.java +++ /dev/null @@ -1,40 +0,0 @@ -// validating/SimpleDebugging.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// {ThrowsException} - -public class SimpleDebugging { - private static void foo1() { - System.out.println("In foo1"); - foo2(); - } - private static void foo2() { - System.out.println("In foo2"); - foo3(); - } - private static void foo3() { - System.out.println("In foo3"); - int j = 1; - j--; - int i = 5 / j; - } - public static void main(String[] args) { - foo1(); - } -} -/* Output: -In foo1 -In foo2 -In foo3 -___[ Error Output ]___ -Exception in thread "main" -java.lang.ArithmeticException: / by zero - at -SimpleDebugging.foo3(SimpleDebugging.java:17) - at -SimpleDebugging.foo2(SimpleDebugging.java:11) - at SimpleDebugging.foo1(SimpleDebugging.java:7) - at -SimpleDebugging.main(SimpleDebugging.java:20) -*/ diff --git a/code/validating/StringInverter.java b/code/validating/StringInverter.java deleted file mode 100644 index 34c933a7..00000000 --- a/code/validating/StringInverter.java +++ /dev/null @@ -1,9 +0,0 @@ -// validating/StringInverter.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; - -interface StringInverter { - String invert(String str); -} diff --git a/code/validating/jmh/JMH1.java b/code/validating/jmh/JMH1.java deleted file mode 100644 index 79eb749a..00000000 --- a/code/validating/jmh/JMH1.java +++ /dev/null @@ -1,31 +0,0 @@ -// validating/jmh/JMH1.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating.jmh; -import java.util.*; -import org.openjdk.jmh.annotations.*; -import java.util.concurrent.TimeUnit; - -@State(Scope.Thread) -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -// Increase these three for more accuracy: -@Warmup(iterations = 5) -@Measurement(iterations = 5) -@Fork(1) -public class JMH1 { - private long[] la; - @Setup - public void setup() { - la = new long[250_000_000]; - } - @Benchmark - public void setAll() { - Arrays.setAll(la, n -> n); - } - @Benchmark - public void parallelSetAll() { - Arrays.parallelSetAll(la, n -> n); - } -} diff --git a/code/validating/jmh/JMH2.java b/code/validating/jmh/JMH2.java deleted file mode 100644 index ae7b56f9..00000000 --- a/code/validating/jmh/JMH2.java +++ /dev/null @@ -1,44 +0,0 @@ -// validating/jmh/JMH2.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating.jmh; -import java.util.*; -import org.openjdk.jmh.annotations.*; -import java.util.concurrent.TimeUnit; - -@State(Scope.Thread) -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@Warmup(iterations = 5) -@Measurement(iterations = 5) -@Fork(1) -public class JMH2 { - private long[] la; - @Param({ - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "250000000" - }) - int size; - - @Setup - public void setup() { - la = new long[size]; - } - @Benchmark - public void setAll() { - Arrays.setAll(la, n -> n); - } - @Benchmark - public void parallelSetAll() { - Arrays.parallelSetAll(la, n -> n); - } -} diff --git a/code/validating/jmh/JMH3.java b/code/validating/jmh/JMH3.java deleted file mode 100644 index 8ce9bb0c..00000000 --- a/code/validating/jmh/JMH3.java +++ /dev/null @@ -1,48 +0,0 @@ -// validating/jmh/JMH3.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating.jmh; -import java.util.*; -import org.openjdk.jmh.annotations.*; -import java.util.concurrent.TimeUnit; - -@State(Scope.Thread) -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@Warmup(iterations = 5) -@Measurement(iterations = 5) -@Fork(1) -public class JMH3 { - private long[] la; - @Param({ - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "250000000" - }) - int size; - - @Setup - public void setup() { - la = new long[size]; - } - public static long f(long x) { - long quadratic = 42 * x * x + 19 * x + 47; - return Long.divideUnsigned(quadratic, x + 1); - } - @Benchmark - public void setAll() { - Arrays.setAll(la, n -> f(n)); - } - @Benchmark - public void parallelSetAll() { - Arrays.parallelSetAll(la, n -> f(n)); - } -} diff --git a/code/validating/logback.xml b/code/validating/logback.xml deleted file mode 100644 index 0a774e44..00000000 --- a/code/validating/logback.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - -%d{yyyy-MM-dd'T'HH:mm:ss.SSS} -[%thread] %-5level %logger - %msg%n - - - - - - - \ No newline at end of file diff --git a/code/validating/tests/CircularQueueTest.java b/code/validating/tests/CircularQueueTest.java deleted file mode 100644 index 8da6dc27..00000000 --- a/code/validating/tests/CircularQueueTest.java +++ /dev/null @@ -1,150 +0,0 @@ -// validating/tests/CircularQueueTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; -import org.junit.jupiter.api.*; -import static org.junit.jupiter.api.Assertions.*; - -public class CircularQueueTest { - private CircularQueue queue = new CircularQueue(10); - private int i = 0; - @BeforeEach - public void initialize() { - while(i < 5) // Pre-load with some data - queue.put(Integer.toString(i++)); - } - // Support methods: - private void showFullness() { - assertTrue(queue.full()); - assertFalse(queue.empty()); - System.out.println(queue.dump()); - } - private void showEmptiness() { - assertFalse(queue.full()); - assertTrue(queue.empty()); - System.out.println(queue.dump()); - } - @Test - public void full() { - System.out.println("testFull"); - System.out.println(queue.dump()); - System.out.println(queue.get()); - System.out.println(queue.get()); - while(!queue.full()) - queue.put(Integer.toString(i++)); - String msg = ""; - try { - queue.put(""); - } catch(CircularQueueException e) { - msg = e.getMessage(); - System.out.println(msg); - } - assertEquals(msg, "put() into full CircularQueue"); - showFullness(); - } - @Test - public void empty() { - System.out.println("testEmpty"); - while(!queue.empty()) - System.out.println(queue.get()); - String msg = ""; - try { - queue.get(); - } catch(CircularQueueException e) { - msg = e.getMessage(); - System.out.println(msg); - } - assertEquals(msg, "get() from empty CircularQueue"); - showEmptiness(); - } - @Test - public void nullPut() { - System.out.println("testNullPut"); - String msg = ""; - try { - queue.put(null); - } catch(CircularQueueException e) { - msg = e.getMessage(); - System.out.println(msg); - } - assertEquals(msg, "put() null item"); - } - @Test - public void circularity() { - System.out.println("testCircularity"); - while(!queue.full()) - queue.put(Integer.toString(i++)); - showFullness(); - assertTrue(queue.isWrapped()); - while(!queue.empty()) - System.out.println(queue.get()); - showEmptiness(); - while(!queue.full()) - queue.put(Integer.toString(i++)); - showFullness(); - while(!queue.empty()) - System.out.println(queue.get()); - showEmptiness(); - } -} -/* Output: -testNullPut -put() null item -testCircularity -in = 0, out = 0, full() = true, empty() = false, -CircularQueue = -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -in = 0, out = 0, full() = false, empty() = true, -CircularQueue = -[null, null, null, null, null, null, null, null, null, -null] -in = 0, out = 0, full() = true, empty() = false, -CircularQueue = -[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -in = 0, out = 0, full() = false, empty() = true, -CircularQueue = -[null, null, null, null, null, null, null, null, null, -null] -testFull -in = 5, out = 0, full() = false, empty() = false, -CircularQueue = -[0, 1, 2, 3, 4, null, null, null, null, null] -0 -1 -put() into full CircularQueue -in = 2, out = 2, full() = true, empty() = false, -CircularQueue = -[10, 11, 2, 3, 4, 5, 6, 7, 8, 9] -testEmpty -0 -1 -2 -3 -4 -get() from empty CircularQueue -in = 5, out = 5, full() = false, empty() = true, -CircularQueue = -[null, null, null, null, null, null, null, null, null, -null] -*/ diff --git a/code/validating/tests/CountedListTest.java b/code/validating/tests/CountedListTest.java deleted file mode 100644 index a9dc0c71..00000000 --- a/code/validating/tests/CountedListTest.java +++ /dev/null @@ -1,101 +0,0 @@ -// validating/tests/CountedListTest.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -// Simple use of JUnit to test CountedList. -package validating; -import java.util.*; -import org.junit.jupiter.api.*; -import static org.junit.jupiter.api.Assertions.*; - -public class CountedListTest { - private CountedList list; - @BeforeAll - static void beforeAllMsg() { - System.out.println(">>> Starting CountedListTest"); - } - @AfterAll - static void afterAllMsg() { - System.out.println(">>> Finished CountedListTest"); - } - @BeforeEach - public void initialize() { - list = new CountedList(); - System.out.println("Set up for " + list.getId()); - for(int i = 0; i < 3; i++) - list.add(Integer.toString(i)); - } - @AfterEach - public void cleanup() { - System.out.println("Cleaning up " + list.getId()); - } - @Test - public void insert() { - System.out.println("Running testInsert()"); - assertEquals(list.size(), 3); - list.add(1, "Insert"); - assertEquals(list.size(), 4); - assertEquals(list.get(1), "Insert"); - } - @Test - public void replace() { - System.out.println("Running testReplace()"); - assertEquals(list.size(), 3); - list.set(1, "Replace"); - assertEquals(list.size(), 3); - assertEquals(list.get(1), "Replace"); - } - // A helper method to simplify the code. As - // long as it's not annotated with @Test, it will - // not be automatically executed by JUnit. - private - void compare(List lst, String[] strs) { - assertArrayEquals(lst.toArray(new String[0]), strs); - } - @Test - public void order() { - System.out.println("Running testOrder()"); - compare(list, new String[] { "0", "1", "2" }); - } - @Test - public void remove() { - System.out.println("Running testRemove()"); - assertEquals(list.size(), 3); - list.remove(1); - assertEquals(list.size(), 2); - compare(list, new String[] { "0", "2" }); - } - @Test - public void addAll() { - System.out.println("Running testAddAll()"); - list.addAll(Arrays.asList(new String[] { - "An", "African", "Swallow"})); - assertEquals(list.size(), 6); - compare(list, new String[] { "0", "1", "2", - "An", "African", "Swallow" }); - } -} -/* Output: ->>> Starting CountedListTest -CountedList #0 -Set up for 0 -Running testRemove() -Cleaning up 0 -CountedList #1 -Set up for 1 -Running testReplace() -Cleaning up 1 -CountedList #2 -Set up for 2 -Running testAddAll() -Cleaning up 2 -CountedList #3 -Set up for 3 -Running testInsert() -Cleaning up 3 -CountedList #4 -Set up for 4 -Running testOrder() -Cleaning up 4 ->>> Finished CountedListTest -*/ diff --git a/code/validating/tests/DynamicStringInverterTests.java b/code/validating/tests/DynamicStringInverterTests.java deleted file mode 100644 index dc980971..00000000 --- a/code/validating/tests/DynamicStringInverterTests.java +++ /dev/null @@ -1,122 +0,0 @@ -// validating/tests/DynamicStringInverterTests.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; -import java.util.*; -import java.util.function.*; -import java.util.stream.*; -import org.junit.jupiter.api.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.DynamicTest.*; - -class DynamicStringInverterTests { - // Combine operations to prevent code duplication: - Stream testVersions(String id, - Function test) { - List versions = Arrays.asList( - new Inverter1(), new Inverter2(), - new Inverter3(), new Inverter4()); - return DynamicTest.stream( - versions.iterator(), - inverter -> inverter.getClass().getSimpleName(), - inverter -> { - System.out.println( - inverter.getClass().getSimpleName() + - ": " + id); - try { - if(test.apply(inverter) != "fail") - System.out.println("Success"); - } catch(Exception | Error e) { - System.out.println( - "Exception: " + e.getMessage()); - } - } - ); - } - String isEqual(String lval, String rval) { - if(lval.equals(rval)) - return "success"; - System.out.println("FAIL: " + lval + " != " + rval); - return "fail"; - } - @BeforeAll - static void startMsg() { - System.out.println( - ">>> Starting DynamicStringInverterTests <<<"); - } - @AfterAll - static void endMsg() { - System.out.println( - ">>> Finished DynamicStringInverterTests <<<"); - } - @TestFactory - Stream basicInversion1() { - String in = "Exit, Pursued by a Bear."; - String out = "eXIT, pURSUED BY A bEAR."; - return testVersions( - "Basic inversion (should succeed)", - inverter -> isEqual(inverter.invert(in), out) - ); - } - @TestFactory - Stream basicInversion2() { - return testVersions( - "Basic inversion (should fail)", - inverter -> isEqual(inverter.invert("X"), "X")); - } - @TestFactory - Stream disallowedCharacters() { - String disallowed = ";-_()*&^%$#@!~`0123456789"; - return testVersions( - "Disallowed characters", - inverter -> { - String result = disallowed.chars() - .mapToObj(c -> { - String cc = Character.toString((char)c); - try { - inverter.invert(cc); - return ""; - } catch(RuntimeException e) { - return cc; - } - }).collect(Collectors.joining("")); - if(result.length() == 0) - return "success"; - System.out.println("Bad characters: " + result); - return "fail"; - } - ); - } - @TestFactory - Stream allowedCharacters() { - String lowcase = "abcdefghijklmnopqrstuvwxyz ,."; - String upcase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ,."; - return testVersions( - "Allowed characters (should succeed)", - inverter -> { - assertEquals(inverter.invert(lowcase), upcase); - assertEquals(inverter.invert(upcase), lowcase); - return "success"; - } - ); - } - @TestFactory - Stream lengthNoGreaterThan30() { - String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - assertTrue(str.length() > 30); - return testVersions( - "Length must be less than 31 (throws exception)", - inverter -> inverter.invert(str) - ); - } - @TestFactory - Stream lengthLessThan31() { - String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - assertTrue(str.length() < 31); - return testVersions( - "Length must be less than 31 (should succeed)", - inverter -> inverter.invert(str) - ); - } -} diff --git a/code/validating/tests/StringInverterTests.java b/code/validating/tests/StringInverterTests.java deleted file mode 100644 index e32873b8..00000000 --- a/code/validating/tests/StringInverterTests.java +++ /dev/null @@ -1,65 +0,0 @@ -// validating/tests/StringInverterTests.java -// (c)2020 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -package validating; -import java.util.*; -import java.util.stream.*; -import org.junit.jupiter.api.*; -import static org.junit.jupiter.api.Assertions.*; - -public class StringInverterTests { - StringInverter inverter = new Inverter4(); - @BeforeAll - static void startMsg() { - System.out.println(">>> StringInverterTests <<<"); - } - @Test - void basicInversion1() { - String in = "Exit, Pursued by a Bear."; - String out = "eXIT, pURSUED BY A bEAR."; - assertEquals(inverter.invert(in), out); - } - @Test - void basicInversion2() { - assertThrows(Error.class, () -> { - assertEquals(inverter.invert("X"), "X"); - }); - } - @Test - void disallowedCharacters() { - String disallowed = ";-_()*&^%$#@!~`0123456789"; - String result = disallowed.chars() - .mapToObj(c -> { - String cc = Character.toString((char)c); - try { - inverter.invert(cc); - return ""; - } catch(RuntimeException e) { - return cc; - } - }).collect(Collectors.joining("")); - assertEquals(result, disallowed); - } - @Test - void allowedCharacters() { - String lowcase = "abcdefghijklmnopqrstuvwxyz ,."; - String upcase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ,."; - assertEquals(inverter.invert(lowcase), upcase); - assertEquals(inverter.invert(upcase), lowcase); - } - @Test - void lengthNoGreaterThan30() { - String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - assertTrue(str.length() > 30); - assertThrows(RuntimeException.class, () -> { - inverter.invert(str); - }); - } - @Test - void lengthLessThan31() { - String str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - assertTrue(str.length() < 31); - inverter.invert(str); - } -} From 7fbae68d1707baae6a54d1ae5e6a55d2e5db2274 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 24 Nov 2020 17:56:01 +0800 Subject: [PATCH 03/68] =?UTF-8?q?=E6=B2=A1=E6=9C=89=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E7=A7=8D=E5=BD=A2=E5=BC=8F=E5=90=A7=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/06-Housekeeping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/06-Housekeeping.md b/docs/book/06-Housekeeping.md index 0a7a5f1c..0248808c 100644 --- a/docs/book/06-Housekeeping.md +++ b/docs/book/06-Housekeeping.md @@ -1379,7 +1379,7 @@ public class ArrayInit { 在这两种形式中,初始化列表的最后一个逗号是可选的(这一特性使维护长列表变得更容易)。 -尽管第一种形式很有用,但是它更加受限,因为它只能用于数组定义处。第二种和第三种形式可以用在任何地方,甚至用在方法的内部。例如,你创建了一个 **String** 数组,将其传递给另一个类的 `main()` 方法,如下: +尽管第一种形式很有用,但是它更加受限,因为它只能用于数组定义处。第二种形式可以用在任何地方,甚至用在方法的内部。例如,你创建了一个 **String** 数组,将其传递给另一个类的 `main()` 方法,如下: ```java // housekeeping/DynamicArray.java From 84e298c79dbb73e850b43ec49a86a7cc06c521b3 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Wed, 25 Nov 2020 17:10:16 +0800 Subject: [PATCH 04/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/08-Reuse.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md index 824d59b9..c3f7abf7 100644 --- a/docs/book/08-Reuse.md +++ b/docs/book/08-Reuse.md @@ -690,7 +690,7 @@ doh(Milhouse) ```` -**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。在下一章中你将看到,使用与基类中完全相同的签名和返回类型覆盖相同名称的方法要常见得多。否则就会令人困惑。 +**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。在下一章中你将看到,使用重写(与基类中完全相同的方法签名和返回类型覆盖相同名称的方法)比起重载会更为常见,否则就会令人困惑。 你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: From 429c653bc4418cded07773a32a56a18d3c5c6230 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Wed, 25 Nov 2020 17:57:35 +0800 Subject: [PATCH 05/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/08-Reuse.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md index c3f7abf7..96bd5b9b 100644 --- a/docs/book/08-Reuse.md +++ b/docs/book/08-Reuse.md @@ -690,9 +690,9 @@ doh(Milhouse) ```` -**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。在下一章中你将看到,使用重写(与基类中完全相同的方法签名和返回类型覆盖相同名称的方法)比起重载会更为常见,否则就会令人困惑。 +**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名(方法名和参数类型)和返回类型。否则会让人感到困惑。 -你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: +你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法(覆盖同名方法)时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: ```java // reuse/Lisa.java @@ -709,7 +709,7 @@ class Lisa extends Homer { ``` -**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:方法不会覆盖超类中的方法, **@Override** 注释防止你意外地重载。 +**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会覆盖(重写)超类中的方法, **@Override** 注释能防止你意外地重载。 From 34e5908b67f226464a98d357aaec517faa212743 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Wed, 25 Nov 2020 18:40:19 +0800 Subject: [PATCH 06/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/08-Reuse.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md index 96bd5b9b..8e4725a6 100644 --- a/docs/book/08-Reuse.md +++ b/docs/book/08-Reuse.md @@ -690,9 +690,10 @@ doh(Milhouse) ```` -**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名(方法名和参数类型)和返回类型。否则会让人感到困惑。 +**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名[^1]和返回类型。否则会让人感到困惑。 + +你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^2]时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: -你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法(覆盖同名方法)时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: ```java // reuse/Lisa.java @@ -709,8 +710,14 @@ class Lisa extends Homer { ``` -**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会覆盖(重写)超类中的方法, **@Override** 注释能防止你意外地重载。 +**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会重写超类中的方法, **@Override** 注释能防止你意外地重载。 + +- **[1]** 方法签名——方法名和参数类型的合称 + +- **[2]** 重写——覆盖同名方法,使用与基类中完全相同的方法签名和返回类型[^3] +- **[3]** 在java 1.4版本以前,重写方法的返回值类型被要求必须与被重写方法一致,但是在java 5.0中放宽了这一个限制,添加了对协变返回类型的支持,在重写的时候,重写方法的返回值类型可以是被重写方法返回值类型的子类。 + ## 组合与继承的选择 From b027cf39e158164c2b1afe3fbec646b732caa077 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 26 Nov 2020 14:16:46 +0800 Subject: [PATCH 07/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/08-Reuse.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md index 8e4725a6..729d4ca3 100644 --- a/docs/book/08-Reuse.md +++ b/docs/book/08-Reuse.md @@ -68,7 +68,7 @@ i = 0 f = 0.0 source = Constructed ``` -这两个类中定义的一个方法是特殊的: `toString()`。每个非基本类型对象都有一个 `toString()` 方法,在编译器需要字符串但它有对象的特殊情况下调用该方法。因此,在 [1] 中,编译器看到你试图“添加”一个 **WaterSource** 类型的字符串对象 。因为字符串只能拼接另一个字符串,所以它就先会调用 `toString()` 将 **source** 转换成一个字符串。然后,它可以拼接这两个字符串并将结果字符串传递给 `System.out.println()`。要对创建的任何类允许这种行为,只需要编写一个 **toString()** 方法。在 `toString()` 上使用 **@Override** 注释来告诉编译器,以确保正确地覆盖。**@Override** 是可选的,但它有助于验证你没有拼写错误 (或者更微妙地说,大小写字母输入错误)。类中的基本类型字段自动初始化为零,正如 **object Everywhere** 一章中所述。但是对象引用被初始化为 **null**,如果你尝试调用其任何一个方法,你将得到一个异常(一个运行时错误)。方便的是,打印 **null** 引用却不会得到异常。 +这两个类中定义的一个方法是特殊的: `toString()`。每个非基本类型对象都有一个 `toString()` 方法,在编译器需要字符串但它有对象的特殊情况下调用该方法。因此,在 [1] 中,编译器看到你试图“添加”一个 **WaterSource** 类型的字符串对象 。因为字符串只能拼接另一个字符串,所以它就先会调用 `toString()` 将 **source** 转换成一个字符串。然后,它可以拼接这两个字符串并将结果字符串传递给 `System.out.println()`。要对创建的任何类允许这种行为,只需要编写一个 **toString()** 方法。在 `toString()` 上使用 **@Override** 注解来告诉编译器,以确保正确地覆盖。**@Override** 是可选的,但它有助于验证你没有拼写错误 (或者更微妙地说,大小写字母输入错误)。类中的基本类型字段自动初始化为零,正如 **object Everywhere** 一章中所述。但是对象引用被初始化为 **null**,如果你尝试调用其任何一个方法,你将得到一个异常(一个运行时错误)。方便的是,打印 **null** 引用却不会得到异常。 编译器不会为每个引用创建一个默认对象,这是有意义的,因为在许多情况下,这会导致不必要的开销。初始化引用有四种方法: @@ -692,7 +692,7 @@ doh(Milhouse) **Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名[^1]和返回类型。否则会让人感到困惑。 -你已经看到了Java 5 **@Override**注释,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^2]时,你可以选择添加这个注释,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: +你已经看到了Java 5 **@Override**注解,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^2]时,你可以选择添加这个注解,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: ```java @@ -710,7 +710,7 @@ class Lisa extends Homer { ``` -**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会重写超类中的方法, **@Override** 注释能防止你意外地重载。 +**{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会重写超类中的方法, **@Override** 注解能防止你意外地重载。 - **[1]** 方法签名——方法名和参数类型的合称 From 7ddf47f41ce98aaaa334015c0f9ef033e4797067 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 26 Nov 2020 17:52:33 +0800 Subject: [PATCH 08/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/08-Reuse.md | 4 +++- docs/book/10-Interfaces.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md index 729d4ca3..e10f8751 100644 --- a/docs/book/08-Reuse.md +++ b/docs/book/08-Reuse.md @@ -1176,12 +1176,14 @@ public class Jurassic { 但请留意你的假设。通常来说,预见一个类如何被复用是很困难的,特别是通用类。如果将一个方法指定为 **final**,可能会防止其他程序员的项目中通过继承来复用你的类,而这仅仅是因为你没有想到它被以那种方式使用。 -Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vector** 类被广泛地使用,如果它的所有方法没有因为从效率考虑(这近乎是个幻想),而被指定为 **final**,可能会更加有用。很容易想到,你可能会继承并覆写这么一个基础类,但是设计者们认为这么做不合适。有两个讽刺的原因。第一,**Stack** 继承自 **Vector**,就是说 **Stack** 是个 **Vector**,但从逻辑上来说不对。尽管如此,Java 设计者们仍然这么做,在用这种方式创建 **Stack** 时,他们应该意识到了 **final** 方法过于约束。 +Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vector** 类被广泛地使用,然而它的所有方法出于"效率"考虑(然而并没有提升效率,只是幻觉)全被指定为 **final** ,如果不指定 **final** 的话,可能会更加有用[^1]。很容易想到,你可能会继承并覆写这么一个基础类,但是设计者们认为这么做不合适。有两个讽刺的原因。第一,**Stack** 继承自 **Vector**,就是说 **Stack** 是个 **Vector**,但从逻辑上来说不对。尽管如此,Java 设计者们仍然这么做,在用这种方式创建 **Stack** 时,他们应该意识到了 **final** 方法过于约束。 第二,**Vector** 中的很多重要方法,比如 `addElement()` 和 `elementAt()` 方法都是同步的。在“并发编程”一章中会看到同步会导致很大的执行开销,可能会抹煞 **final** 带来的好处。这加强了程序员永远无法正确猜到优化应该发生在何处的观点。如此笨拙的设计却出现在每个人都要使用的标准库中,太糟糕了。庆幸的是,现代 Java 容器用 **ArrayList** 代替了 **Vector**,它的行为要合理得多。不幸的是,仍然有很多新代码使用旧的集合类库,其中就包括 **Vector**。 Java 1.0/1.1 标准类库中另一个重要的类是 **Hashtable**(后来被 **HashMap** 取代),它不含任何 **final** 方法。本书中其他地方也提到,很明显不同的类是由不同的人设计的。**Hashtable** 就比 **Vector** 中的方法名简洁得多,这又是一条证据。对于类库的使用者来说,这是一个本不应该如此草率的事情。这种不规则的情况造成用户需要做更多的工作——这是对粗糙的设计和代码的又一讽刺。 +- **[1]** Java 1.4 开始已将 **Vector** 类大多数方法的 **final** 去掉 + ## 类初始化和加载 diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md index f2bc527e..7eb5cf49 100644 --- a/docs/book/10-Interfaces.md +++ b/docs/book/10-Interfaces.md @@ -104,7 +104,7 @@ public class Instantiable extends Uninstantiable { } ``` -留意 `@Override` 的使用。没有这个注解的话,如果你没有定义相同的方法名或签名,抽象机制会认为你没有实现抽象方法从而产生编译时错误。因此,你可能认为这里的 `@Override` 是多余的。但是,`@Override` 还提示了这个方法被覆写——我认为这是有用的,所以我会使用 `@Override`,即使在没有这个注解,编译器告诉我错误的时候。 +留意 `@Override` 的使用。没有这个注解的话,如果你没有定义相同的方法名或签名,抽象机制会认为你没有实现抽象方法从而产生编译时错误。因此,你可能认为这里的 `@Override` 是多余的。但是,`@Override` 还提示了这个方法被覆写——我认为这是有用的,所以我会使用 `@Override`,不仅仅是因为当没有这个注解时,编译器会告诉我出错。 记住,事实上的访问权限是“friendly”。你很快会看到接口自动将其方法指明为 **public**。事实上,接口只允许 **public** 方法,如果不加访问修饰符的话,接口的方法不是 **friendly** 而是 **public**。然而,抽象类允许每件事: From 82aedb03a048b2f785e9a40240e4a11fe0c61f01 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 27 Nov 2020 12:24:29 +0800 Subject: [PATCH 09/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=206?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/09-Polymorphism.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/book/09-Polymorphism.md b/docs/book/09-Polymorphism.md index 63075630..f589aca2 100644 --- a/docs/book/09-Polymorphism.md +++ b/docs/book/09-Polymorphism.md @@ -964,7 +964,7 @@ Disposing Shared 0 **static long counter** 跟踪所创建的 **Shared** 实例数量,还提供了 **id** 的值。**counter** 的类型是 **long** 而不是 **int**,以防溢出(这只是个良好实践,对于本书的所有示例,**counter** 不会溢出)。**id** 是 **final** 的,因为它的值在初始化时确定后不应该变化。 -在将一个 **shared** 对象附着在类上时,必须记住调用 `addRef()`,而 `dispose()` 方法会跟踪引用数,以确定在何时真正地执行清理工作。使用这种技巧需要加倍细心,但是如果正在共享需要被清理的对象,就没有太多选择了。 +在将一个 **shared** 对象附着在类上时,必须记住调用 `addRef()`,而 `dispose()` 方法会跟踪引用数,以确定在何时真正地执行清理工作。使用这种技巧需要加倍细心,但是如果正在共享的对象需要被清理,你没有太多选择。 ### 构造器内部多态方法的行为 @@ -1154,7 +1154,7 @@ HappyActor SadActor ``` -**Stage** 对象中包含了 **Actor** 引用,该引用被初始化为指向一个 **HappyActor** 对象,这意味着 `performPlay()` 会产生一个特殊行为。但是既然引用可以在运行时与其他不同的对象绑定,那么它就可以被替换成对 **SadActor** 的引用,`performPlay()` 的行为随之改变。这样你就获得了运行时的动态灵活性(这被称为状态模式)。与之相反,我们不能在运行时决定继承不同的对象,那在编译时就完全确定下来了。 +**Stage** 对象中包含了 **Actor** 引用,该引用被初始化为指向一个 **HappyActor** 对象,这意味着 `performPlay()` 会产生一个特殊行为。但是既然引用可以在运行时与其他不同的对象绑定,那么它就可以被替换成对 **SadActor** 的引用,`performPlay()` 的行为随之改变。这样你就获得了运行时的动态灵活性(这被称为状态模式)。与之相反,我们不能在运行时才决定继承不同的对象;那在编译时就完全决定好了。 有一条通用准则:使用继承表达行为的差异,使用属性表达状态的变化。在上个例子中,两者都用到了。通过继承得到的两个不同类在 `act()` 方法中表达了不同的行为,**Stage** 通过组合使自己的状态发生变化。这里状态的改变产生了行为的改变。 From 07231d75bae189957c90d3707804f9bc7507902b Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 27 Nov 2020 16:09:05 +0800 Subject: [PATCH 10/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=207?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/10-Interfaces.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md index 7eb5cf49..6af03da0 100644 --- a/docs/book/10-Interfaces.md +++ b/docs/book/10-Interfaces.md @@ -602,7 +602,7 @@ public interface Operations { } ``` -这是模版方法设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模版方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们: +这是*模版*方法设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模版方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们: ```java // interface/Machine.java @@ -768,17 +768,17 @@ Woodwind.play() MIDDLE_C | 状态 | 不能包含属性(除了静态属性,不支持对象状态) | 可以包含属性,非抽象方法可能引用这些属性 | | 默认方法 和 抽象方法 | 不需要在子类中实现默认方法。默认方法可以引用其他接口的方法 | 必须在子类中实现抽象方法 | | 构造器 | 没有构造器 | 可以有构造器 | -| 可见性 | 隐式 **public** | 可以是 **protected** 或友元 | +| 可见性 | 隐式 **public** | 可以是 **protected** 或 "friendly" | 抽象类仍然是一个类,在创建新类时只能继承它一个。而创建类的过程中可以实现多个接口。 -有一条实际经验:尽可能地抽象。因此,更倾向使用接口而不是抽象类。只有当必要时才使用抽象类。除非必须使用,否则不要用接口和抽象类。大多数时候,普通类已经做得很好,如果不行的话,再移动到接口或抽象类中。 +有一条实际经验:在合理的范围内尽可能地抽象。因此,更倾向使用接口而不是抽象类。只有当必要时才使用抽象类。除非必须使用,否则不要用接口和抽象类。大多数时候,普通类已经做得很好,如果不行的话,再移动到接口或抽象类中。 ## 完全解耦 -当方法操纵的是一个类而非接口时,它就只能作用于那个类或其子类。如果想把方法应用于那个继承层级结构之外的类,就会触霉头。接口在很大程度上放宽了这个限制,因而使用接口可以编写复用性更好的代码。 +每当一个方法与一个类而不是接口一起工作时,你只能应用那个类或它的子类。如果你想把这方法应用到一个继承层次之外的类,是做不到的。接口在很大程度上放宽了这个限制,因而使用接口可以编写复用性更好的代码。 例如有一个类 **Processor** 有两个方法 `name()` 和 `process()`。`process()` 方法接受输入,修改并输出。把这个类作为基类用来创建各种不同类型的 **Processor**。下例中,**Processor** 的各个子类修改 String 对象(注意,返回类型可能是协变类型而非参数类型): From b0d16e7d49a38ff1b079308b989148bdf9629ae2 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 27 Nov 2020 17:23:00 +0800 Subject: [PATCH 11/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/10-Interfaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md index 6af03da0..b7cf5cb5 100644 --- a/docs/book/10-Interfaces.md +++ b/docs/book/10-Interfaces.md @@ -778,7 +778,7 @@ Woodwind.play() MIDDLE_C ## 完全解耦 -每当一个方法与一个类而不是接口一起工作时,你只能应用那个类或它的子类。如果你想把这方法应用到一个继承层次之外的类,是做不到的。接口在很大程度上放宽了这个限制,因而使用接口可以编写复用性更好的代码。 +每当一个方法与一个类而不是接口一起工作时(当方法的参数是类而不是接口),你只能应用那个类或它的子类。如果你想把这方法应用到一个继承层次之外的类,是做不到的。接口在很大程度上放宽了这个限制,因而使用接口可以编写复用性更好的代码。 例如有一个类 **Processor** 有两个方法 `name()` 和 `process()`。`process()` 方法接受输入,修改并输出。把这个类作为基类用来创建各种不同类型的 **Processor**。下例中,**Processor** 的各个子类修改 String 对象(注意,返回类型可能是协变类型而非参数类型): From 95a4cbbabd701476a08764120f23dabbcc77fc0a Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 27 Nov 2020 17:56:34 +0800 Subject: [PATCH 12/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/09-Polymorphism.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/book/09-Polymorphism.md b/docs/book/09-Polymorphism.md index f589aca2..ddca482d 100644 --- a/docs/book/09-Polymorphism.md +++ b/docs/book/09-Polymorphism.md @@ -964,7 +964,7 @@ Disposing Shared 0 **static long counter** 跟踪所创建的 **Shared** 实例数量,还提供了 **id** 的值。**counter** 的类型是 **long** 而不是 **int**,以防溢出(这只是个良好实践,对于本书的所有示例,**counter** 不会溢出)。**id** 是 **final** 的,因为它的值在初始化时确定后不应该变化。 -在将一个 **shared** 对象附着在类上时,必须记住调用 `addRef()`,而 `dispose()` 方法会跟踪引用数,以确定在何时真正地执行清理工作。使用这种技巧需要加倍细心,但是如果正在共享的对象需要被清理,你没有太多选择。 +在将一个 **shared** 对象附着在类上时,必须记住调用 `addRef()`,而 `dispose()` 方法会跟踪引用数,以确定在何时真正地执行清理工作。使用这种技巧需要加倍细心,但是如果需要清理正在共享的对象,你没有太多选择。 ### 构造器内部多态方法的行为 @@ -1154,7 +1154,7 @@ HappyActor SadActor ``` -**Stage** 对象中包含了 **Actor** 引用,该引用被初始化为指向一个 **HappyActor** 对象,这意味着 `performPlay()` 会产生一个特殊行为。但是既然引用可以在运行时与其他不同的对象绑定,那么它就可以被替换成对 **SadActor** 的引用,`performPlay()` 的行为随之改变。这样你就获得了运行时的动态灵活性(这被称为状态模式)。与之相反,我们不能在运行时才决定继承不同的对象;那在编译时就完全决定好了。 +**Stage** 对象中包含了 **Actor** 引用,该引用被初始化为指向一个 **HappyActor** 对象,这意味着 `performPlay()` 会产生一个特殊行为。但是既然引用可以在运行时与其他不同的对象绑定,那么它就可以被替换成对 **SadActor** 的引用,`performPlay()` 的行为随之改变。这样你就获得了运行时的动态灵活性(这被称为状态模式)。与之相反,我们无法在运行时才决定继承不同的对象;那在编译时就完全决定好了。 有一条通用准则:使用继承表达行为的差异,使用属性表达状态的变化。在上个例子中,两者都用到了。通过继承得到的两个不同类在 `act()` 方法中表达了不同的行为,**Stage** 通过组合使自己的状态发生变化。这里状态的改变产生了行为的改变。 From 826b9a207cf34fa4fc657ccb0b51719624cc1dcc Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Sun, 29 Nov 2020 22:13:46 +0800 Subject: [PATCH 13/68] =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/11-Inner-Classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md index ea329e45..129ecf61 100755 --- a/docs/book/11-Inner-Classes.md +++ b/docs/book/11-Inner-Classes.md @@ -8,7 +8,7 @@ 内部类是一种非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可见性。然而必须要了解,内部类与组合是完全不同的概念,这一点很重要。在最初,内部类看起来就像是一种代码隐藏机制:将类置于其他类的内部。但是,你将会了解到,内部类远不止如此,它了解外部类,并能与之通信,而且你用内部类写出的代码更加优雅而清晰,尽管并不总是这样(而且 Java 8 的 Lambda 表达式和方法引用减少了编写内部类的需求)。 -最初,内部类可能看起来有些奇怪,而且要花些时间才能在设计中轻松地使用它们。对内部类的需求并非总是很明显的,但是在描述完内部类的基本语法与语义之后,"Why inner classes?"就应该使得内部类的益处明确显现了。 +最初,内部类可能看起来有些奇怪,而且要花些时间才能在设计中轻松地使用它们。对内部类的需求并非总是很明显的,但是在描述完内部类的基本语法与语义之后,就能明白使用内部类的好处了。 本章剩余部分包含了对内部类语法更加详尽的探索,这些特性是为了语言的完备性而设计的,但是你也许不需要使用它们,至少一开始不需要。因此,本章最初的部分也许就是你现在所需的全部,你可以将更详尽的探索当作参考资料。 @@ -170,7 +170,7 @@ public class Sequence { 0 1 2 3 4 5 6 7 8 9 ``` -**Sequence** 类只是一个固定大小的 **Object** 的数组,以类的形式包装了起来。可以调用 `add()` 在序列末尾增加新的 **Object**(只要还有空间),要获取 **Sequence** 中的每一个对象,可以使用 **Selector** 接口。这是“迭代器”设计模式的一个例子,在本书稍后的部分将更多地学习它。**Selector** 允许你检查序列是否到末尾了(`end()`),访问当前对象(`current()`),以及移到序列中的下一个对象(`next()`)。因为 **Selector** 是一个接口,所以别的类可以按它们自己的方式来实现这个接口,并且其他方法能以此接口为参数,来生成更加通用的代码。 +**Sequence** 类只是一个固定大小的 **Object** 的数组,以类的形式包装了起来。可以调用 `add()` 在序列末尾增加新的 **Object**(只要还有空间),要获取 **Sequence** 中的每一个对象,可以使用 **Selector** 接口。这是“*迭代器*”设计模式的一个例子,在本书稍后的部分将更多地学习它。**Selector** 允许你检查序列是否到末尾了(`end()`),访问当前对象(`current()`),以及移到序列中的下一个对象(`next()`)。因为 **Selector** 是一个接口,所以别的类可以按它们自己的方式来实现这个接口,并且其他方法能以此接口为参数,来生成更加通用的代码。 这里,**SequenceSelector** 是提供 **Selector** 功能的 **private** 类。可以看到,在 `main()` 中创建了一个 **Sequence**,并向其中添加了一些 **String** 对象。然后通过调用 `selector()` 获取一个 **Selector**,并用它在 **Sequence** 中移动和选择每一个元素。 最初看到 **SequenceSelector**,可能会觉得它只不过是另一个内部类罢了。但请仔细观察它,注意方法 `end()`,`current()` 和 `next()` 都用到了 **items**,这是一个引用,它并不是 **SequenceSelector** 的一部分,而是外部类中的一个 **private** 字段。然而内部类可以访问其外部类的方法和字段,就像自己拥有它们似的,这带来了很大的方便,就如前面的例子所示。 From ff9d3366bf6f4a7ef074f622e88b4b2e0d4e119c Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Mon, 30 Nov 2020 17:25:54 +0800 Subject: [PATCH 14/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2010?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/10-Interfaces.md | 2 +- docs/book/11-Inner-Classes.md | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md index b7cf5cb5..98a62049 100644 --- a/docs/book/10-Interfaces.md +++ b/docs/book/10-Interfaces.md @@ -602,7 +602,7 @@ public interface Operations { } ``` -这是*模版*方法设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模版方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们: +这是*模板方法*设计模式的一个版本(在“设计模式”一章中详细描述),`runOps()` 是一个模板方法。`runOps()` 使用可变参数列表,因而我们可以传入任意多的 **Operation** 参数并按顺序运行它们: ```java // interface/Machine.java diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md index 129ecf61..03625ffe 100755 --- a/docs/book/11-Inner-Classes.md +++ b/docs/book/11-Inner-Classes.md @@ -325,7 +325,7 @@ public class TestParcel { ## 内部类方法和作用域 -到目前为止,读者所看到的只是内部类的典型用途。通常,如果所读、写的代码包含了内部类,那么它们都是“平凡的”内部类,简单并且容易理解。然而,内部类的语法覆盖了大量其他的更加难以理解的技术。例如,可以在一个方法里面或者在任意的作用域内定义内部类。 +到目前为止,读者所看到的只是内部类的典型用途。通常,如果所读、写的代码包含了内部类,那么它们都是“平凡的”内部类,简单并且容易理解。然而,内部类的语法重写了大量其他的更加难以理解的技术。例如,可以在一个方法里面或者在任意的作用域内定义内部类。 这么做有两个理由: @@ -513,7 +513,7 @@ public class Parcel9 { } ``` -如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用是 **final** 的(也就是说,它在初始化后不会改变,所以可以被当作 **final**),就像你在 `destination()` 的参数中看到的那样。这里省略掉 **final** 也没问题,但是通常最好加上 **final** 作为一种暗示。 +如果在定义一个匿名内部类时,它要使用一个外部环境(在本匿名内部类之外定义)对象,那么编译器会要求其(该对象)参数引用是 **final** 或者是 “effectively final”(也就是说,该参数在初始化后不能被重新赋值,所以可以当作 **final**)的,就像你在 `destination()` 的参数中看到的那样。这里省略掉 **final** 也没问题,但通常加上 **final** 作为提醒比较好。 如果只是简单地给一个字段赋值,那么此例中的方法是很好的。但是,如果想做一些类似构造器的行为,该怎么办呢?在匿名类中不可能有命名构造器(因为它根本没名字!),但通过实例初始化,就能够达到为匿名内部类创建一个构造器的效果,就像这样: @@ -552,7 +552,7 @@ Inside instance initializer In anonymous f() ``` -在此例中,不要求变量一定是 **final** 的。因为被传递给匿名类的基类的构造器,它并不会在匿名类内部被直接使用。 +在此例中,不要求变量 **i** 一定是 **final** 的。因为 **i** 被传递给匿名类的基类的构造器,它并不会在匿名类内部被直接使用。 下例是带实例初始化的"parcel"形式。注意 `destination()` 的参数必须是 **final** 的,因为它们是在匿名类内部使用的(译者注:即使不加 **final**, Java 8 的编译器也会为我们自动加上 **final**,以保证数据的一致性)。 @@ -591,15 +591,15 @@ Over budget! 在实例初始化操作的内部,可以看到有一段代码,它们不能作为字段初始化动作的一部分来执行(就是 **if** 语句)。所以对于匿名类而言,实例初始化的实际效果就是构造器。当然它受到了限制-你不能重载实例初始化方法,所以你仅有一个这样的构造器。 -匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以实现接口,但是不能两者兼备。而且如果是实现接口,也只能实现一个接口。 +匿名内部类与正规的继承相比有些受限,因为匿名内部类要么继承类,要么实现接口,但是不能两者兼备。而且如果是实现接口,也只能实现一个接口。 ## 嵌套类 -如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为 **static**,这通常称为嵌套类。想要理解 **static** 应用于内部类时的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建它的外部类对象。然而,当内部类是 **static** 的时,就不是这样了。嵌套类意味着: +如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为 **static**,这通常称为*嵌套类*。想要理解 **static** 应用于内部类时的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建它的外部类对象。然而,当内部类是 **static** 的时,就不是这样了。嵌套类意味着: -1. 要创建嵌套类的对象,并不需要其外部类的对象。 +1. 创建嵌套类的对象时,不需要其外部类的对象。 2. 不能从嵌套类的对象中访问非静态的外部类对象。 嵌套类与普通的内部类还有一个区别。普通内部类的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有 **static** 数据和 **static** 字段,也不能包含嵌套类。但是嵌套类可以包含所有这些东西: @@ -910,7 +910,7 @@ Other operation 3 ``` -这个例子进一步展示了外部类实现一个接口与内部类实现此接口之间的区别。就代码而言,**Callee1** 是更简单的解决方式。**Callee2** 继承自 **MyIncrement**,后者已经有了一个不同的 `increment()` 方法,并且与 **Incrementable** 接口期望的 `increment()` 方法完全不相关。所以如果 **Callee2** 继承了 **MyIncrement**,就不能为了 **Incrementable** 的用途而覆盖 `increment()` 方法,于是只能使用内部类独立地实现 **Incrementable**,还要注意,当创建了一个内部类时,并没有在外部类的接口中添加东西,也没有修改外部类的接口。 +这个例子进一步展示了外部类实现一个接口与内部类实现此接口之间的区别。就代码而言,**Callee1** 是更简单的解决方式。**Callee2** 继承自 **MyIncrement**,后者已经有了一个不同的 `increment()` 方法,并且与 **Incrementable** 接口期望的 `increment()` 方法完全不相关。所以如果 **Callee2** 继承了 **MyIncrement**,就不能为了 **Incrementable** 的用途而重写 `increment()` 方法,于是只能使用内部类独立地实现 **Incrementable**,还要注意,当创建了一个内部类时,并没有在外部类的接口中添加东西,也没有修改外部类的接口。 注意,在 **Callee2** 中除了 `getCallbackReference()` 以外,其他成员都是 **private** 的。要想建立与外部世界的任何连接,接口 **Incrementable** 都是必需的。在这里可以看到,**interface** 是如何允许接口与接口的实现完全独立的。 内部类 **Closure** 实现了 **Incrementable**,以提供一个返回 **Callee2** 的“钩子”(hook)-而且是一个安全的钩子。无论谁获得此 **Incrementable** 的引用,都只能调用 `increment()`,除此之外没有其他功能(不像指针那样,允许你做很多事情)。 @@ -923,13 +923,13 @@ Other operation 在将要介绍的控制框架(control framework)中,可以看到更多使用内部类的具体例子。 -应用程序框架(application framework)就是被设计用以解决某类特定问题的一个类或一组类。要运用某个应用程序框架,通常是继承一个或多个类,并覆盖某些方法。在覆盖后的方法中,编写代码定制应用程序框架提供的通用解决方案,以解决你的特定问题。这是设计模式中模板方法的一个例子,模板方法包含算法的基本结构,并且会调用一个或多个可覆盖的方法,以完成算法的动作。设计模式总是将变化的事物与保持不变的事物分离开,在这个模式中,模板方法是保持不变的事物,而可覆盖的方法就是变化的事物。 +应用程序框架(application framework)就是被设计用以解决某类特定问题的一个类或一组类。要运用某个应用程序框架,通常是继承一个或多个类,并重写某些方法。你在重写的方法中写的代码定制了该应用程序框架提供的通用解决方案,来解决你的具体问题。这是设计模式中*模板方法*的一个例子,模板方法包含算法的基本结构,而且会调用一个或多个可重写的方法来完成该算法的运算。设计模式总是将变化的事物与保持不变的事物分离开,在这个模式中,模板方法是保持不变的事物,而可重写的方法就是变化的事物。 控制框架是一类特殊的应用程序框架,它用来解决响应事件的需求。主要用来响应事件的系统被称作*事件驱动*系统。应用程序设计中常见的问题之一是图形用户接口(GUI),它几乎完全是事件驱动的系统。 -要理解内部类是如何允许简单的创建过程以及如何使用控制框架的,请考虑这样一个控制框架,它的工作就是在事件“就绪”的时候执行事件。虽然“就绪”可以指任何事,但在本例中是指基于时间触发的事件。接下来的问题就是,对于要控制什么,控制框架并不包含任何具体的信息。那些信息是在实现算法的 `action()` 部分时,通过继承来提供的。 +要理解内部类是如何允许简单的创建过程以及如何使用控制框架的,请考虑这样一个控制框架,它的工作就是在事件“就绪`ready()`”的时候执行事件。虽然“就绪”可以指任何事,但在本例中是指基于时间触发的事件。下面是一个控制框架,它不包含具体的控制信息。那些信息是通过继承(当算法的 `action()` 部分被实现时)来提供的。 -首先,接口描述了要控制的事件。因为其默认的行为是基于时间去执行控制,所以使用抽象类代替实际的接口。下面的例子包含了某些实现: +这里是描述了所有控制事件的接口。之所以用抽象类代替了真正的接口,是因为默认行为都是根据时间来执行控制的。也因此包含了一些具体实现: ```java // innerclasses/controller/Event.java @@ -955,7 +955,7 @@ public abstract class Event { 当希望运行 **Event** 并随后调用 `start()` 时,那么构造器就会捕获(从对象创建的时刻开始的)时间,此时间是这样得来的:`start()` 获取当前时间,然后加上一个延迟时间,这样生成触发事件的时间。`start()` 是一个独立的方法,而没有包含在构造器内,因为这样就可以在事件运行以后重新启动计时器,也就是能够重复使用 **Event** 对象。例如,如果想要重复一个事件,只需简单地在 `action()` 中调用 `start()` 方法。 -`ready()` 告诉你何时可以运行 `action()` 方法了。当然,可以在派生类中覆盖 `ready()` 方法,使得 **Event** 能够基于时间以外的其他因素而触发。 +`ready()` 告诉你何时可以运行 `action()` 方法了。当然,可以在派生类中重写 `ready()` 方法,使得 **Event** 能够基于时间以外的其他因素而触发。 下面的文件包含了一个用来管理并触发事件的实际控制框架。**Event** 对象被保存在 **List**\<**Event**\> 类型(读作“Event 的列表”)的容器对象中,容器会在 [集合 ]() 中详细介绍。目前读者只需要知道 `add()` 方法用来将一个 **Event** 添加到 **List** 的尾端,`size()` 方法用来得到 **List** 中元素的个数,foreach 语法用来连续获取 **List** 中的 **Event**,`remove()` 方法用来从 **List** 中移除指定的 **Event**。 @@ -1150,7 +1150,7 @@ public class GreenhouseControls extends Controller { 一个由 **Event** 对象组成的数组被递交给 **Restart**,该数组要加到控制器上。由于 `Restart()` 也是一个 **Event** 对象,所以同样可以将 **Restart** 对象添加到 `Restart.action()` 中,以使系统能够有规律地重新启动自己。 -下面的类通过创建一个 **GreenhouseControls** 对象,并添加各种不同的 **Event** 对象来配置该系统,这是命令设计模式的一个例子—**eventList** 中的每个对象都被封装成对象的请求: +下面的类通过创建一个 **GreenhouseControls** 对象,并添加各种不同的 **Event** 对象来配置该系统,这是 *命令* 设计模式的一个例子—**eventList** 中的每个对象都被封装成对象的请求: ```java // innerclasses/GreenhouseController.java @@ -1248,9 +1248,9 @@ enclosingClassReference.super(); -## 内部类可以被覆盖么? +## 内部类可以被重写么? -如果创建了一个内部类,然后继承其外部类并重新定义此内部类时,会发生什么呢?也就是说,内部类可以被覆盖吗?这看起来似乎是个很有用的思想,但是“覆盖”内部类就好像它是外部类的一个方法,其实并不起什么作用: +如果创建了一个内部类,然后继承其外部类并重新定义此内部类时,会发生什么呢?也就是说,内部类可以被重写吗?这看起来似乎是个很有用的思想,但是“重写”内部类就好像它是外部类的一个方法,其实并不起什么作用: ```java // innerclasses/BigEgg.java @@ -1286,7 +1286,7 @@ New Egg() Egg.Yolk() ``` -默认的无参构造器是编译器自动生成的,这里是调用基类的默认构造器。你可能认为既然创建了 **BigEgg** 的对象,那么所使用的应该是“覆盖后”的 **Yolk** 版本,但从输出中可以看到实际情况并不是这样的。 +默认的无参构造器是编译器自动生成的,这里是调用基类的默认构造器。你可能认为既然创建了 **BigEgg** 的对象,那么所使用的应该是“重写后”的 **Yolk** 版本,但从输出中可以看到实际情况并不是这样的。 这个例子说明,当继承了某个外部类的时候,内部类并没有发生什么特别神奇的变化。这两个内部类是完全独立的两个实体,各自在自己的命名空间内。当然,明确地继承某个内部类也是可以的: @@ -1335,7 +1335,7 @@ BigEgg2.Yolk() BigEgg2.Yolk.f() ``` -现在 **BigEgg2.Yolk** 通过 **extends Egg2.Yolk** 明确地继承了此内部类,并且覆盖了其中的方法。`insertYolk()` 方法允许 **BigEgg2** 将它自己的 **Yolk** 对象向上转型为 **Egg2** 中的引用 **y**。所以当 `g()` 调用 `y.f()` 时,覆盖后的新版的 `f()` 被执行。第二次调用 `Egg2.Yolk()`,结果是 **BigEgg2.Yolk** 的构造器调用了其基类的构造器。可以看到在调用 `g()` 的时候,新版的 `f()` 被调用了。 +现在 **BigEgg2.Yolk** 通过 **extends Egg2.Yolk** 明确地继承了此内部类,并且重写了其中的方法。`insertYolk()` 方法允许 **BigEgg2** 将它自己的 **Yolk** 对象向上转型为 **Egg2** 中的引用 **y**。所以当 `g()` 调用 `y.f()` 时,重写后的新版的 `f()` 被执行。第二次调用 `Egg2.Yolk()`,结果是 **BigEgg2.Yolk** 的构造器调用了其基类的构造器。可以看到在调用 `g()` 的时候,新版的 `f()` 被调用了。 From 446e2bde7f8a14b16df76fc815f957291af9abdb Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 1 Dec 2020 09:43:26 +0800 Subject: [PATCH 15/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2011?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/11-Inner-Classes.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md index 03625ffe..83376eb8 100755 --- a/docs/book/11-Inner-Classes.md +++ b/docs/book/11-Inner-Classes.md @@ -1426,14 +1426,15 @@ Anonymous inner 9 ```java Counter.class LocalInnerClass$1.class -LocalInnerClass$LocalCounter.class +LocalInnerClass$1LocalCounter.class LocalInnerClass.class ``` 如果内部类是匿名的,编译器会简单地产生一个数字作为其标识符。如果内部类是嵌套在别的内部类之中,只需直接将它们的名字加在其外部类标识符与 **"$"** 的后面。 -虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。) +虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况[^1]。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。) +- **[1]** 另一方面,**$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。 ## 本章小结 From e3e0f50a923dc04496c51caf39ef6114a54a3e66 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 1 Dec 2020 12:00:23 +0800 Subject: [PATCH 16/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2012?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/12-Collections.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md index 269fc785..f0852bd8 100644 --- a/docs/book/12-Collections.md +++ b/docs/book/12-Collections.md @@ -17,12 +17,12 @@ MyType aReference; 集合还有一些其它特性。例如, **Set** 对于每个值都只保存一个对象, **Map** 是一个关联数组,允许将某些对象与其他对象关联起来。Java集合类都可以自动地调整自己的大小。因此,与数组不同,在编程时,可以将任意数量的对象放置在集合中,而不用关心集合应该有多大。 -尽管在 Java 中没有直接的关键字支持,[^1]但集合类仍然是可以显著增强编程能力的基本工具。在本章中,将介绍 Java 集合类库的基本知识,并重点介绍一些典型用法。这里将专注于在日常编程中使用的集合。稍后,在[附录:集合主题]()中,还将学习到其余的那些集合和相关功能,以及如何使用它们的更多详细信息。 +尽管在 Java 中没有直接的关键字支持[^1],但集合类仍然是可以显著增强编程能力的基本工具。在本章中,将介绍 Java 集合类库的基本知识,并重点介绍一些典型用法。这里将专注于在日常编程中使用的集合。稍后,在[附录:集合主题]()中,还将学习到其余的那些集合和相关功能,以及如何使用它们的更多详细信息。 ## 泛型和类型安全的集合 -使用 Java 5 之前的集合的一个主要问题是编译器允许你向集合中插入不正确的类型。例如,考虑一个 **Apple** 对象的集合,这里使用最基本最可靠的 **ArrayList** 。现在,可以把 **ArrayList** 看作“可以自动扩充自身尺寸的数组”来看待。使用 **ArrayList** 相当简单:创建一个实例,用 `add()` 插入对象;然后用 `get()` 来访问这些对象,此时需要使用索引,就像数组那样,但是不需要方括号。[^2] **ArrayList** 还有一个 `size()` 方法,来说明集合中包含了多少个元素,所以不会不小心因数组越界而引发错误(通过抛出*运行时异常*,[异常]()章节介绍了异常)。 +使用 Java 5 之前的集合的一个主要问题是编译器允许你向集合中插入不正确的类型。例如,考虑一个 **Apple** 对象的集合,这里使用最基本最可靠的 **ArrayList** 。现在,可以把 **ArrayList** 看作“可以自动扩充自身尺寸的数组”来看待。使用 **ArrayList** 相当简单:创建一个实例,用 `add()` 插入对象;然后用 `get()` 来访问这些对象,此时需要使用索引,就像数组那样,但是不需要方括号[^2]。 **ArrayList** 还有一个 `size()` 方法,来说明集合中包含了多少个元素,所以不会不小心因数组越界而引发错误(通过抛出*运行时异常*,[异常]()章节介绍了异常)。 在本例中, **Apple** 和 **Orange** 都被放到了集合中,然后将它们取出。正常情况下,Java编译器会给出警告,因为这个示例没有使用泛型。在这里,使用特定的注解来抑制警告信息。注解以“@”符号开头,可以带参数。这里的 `@SuppressWarning` 注解及其参数表示只抑制“unchecked”类型的警告([注解]()章节将介绍更多有关注解的信息): @@ -70,7 +70,7 @@ ndOrangesWithoutGenerics.java:23) 在[泛型]()章节中,你将了解到使用 Java 泛型来创建类可能很复杂。但是,使用预先定义的泛型类却相当简单。例如,要定义一个用于保存 **Apple** 对象的 **ArrayList** ,只需要使用 **ArrayList\** 来代替 **ArrayList** 。尖括号括起来的是*类型参数*(可能会有多个),它指定了这个集合实例可以保存的类型。 -通过使用泛型,就可以在编译期防止将错误类型的对象放置到集合中。[^3]下面还是这个示例,但是使用了泛型: +通过使用泛型,就可以在编译期防止将错误类型的对象放置到集合中[^3]。下面还是这个示例,但是使用了泛型: ```java // collections/ApplesAndOrangesWithGenerics.java import java.util.*; @@ -310,7 +310,7 @@ public class PrintingCollections { */ ``` -这显示了Java集合库中的两个主要类型。它们的区别在于集合中的每个“槽”(slot)保存的元素个数。 **Collection** 类型在每个槽中只能保存一个元素。此类集合包括: **List** ,它以特定的顺序保存一组元素; **Set** ,其中元素不允许重复; **Queue** ,只能在集合一端插入对象,并从另一端移除对象(就本例而言,这只是查看序列的另一种方式,因此并没有显示它)。 **Map** 在每个槽中存放了两个元素,即*键*和与之关联的*值*。 +这显示了Java集合库中的两个主要类型。它们的区别在于集合中的每个“槽”(slot)保存的元素个数。 **Collection** 类型在每个槽中只能保存一个元素。此类集合包括: **List** ,它以特定的顺序保存一组元素; **Set** ,其中元素不允许重复; **Queue** ,只能在集合一端插入对象,并从另一端移除对象(就本例而言,这只是查看序列的另一种方式,因此并没有显示它)。 **Map** 在每个槽中存放了两个元素,即*键* (key)和与之关联的*值* (value)。 默认的打印行为,使用集合提供的 `toString()` 方法即可生成可读性很好的结果。 **Collection** 打印出的内容用方括号括住,每个元素由逗号分隔。 **Map** 则由大括号括住,每个键和值用等号连接(键在左侧,值在右侧)。 @@ -318,7 +318,7 @@ public class PrintingCollections { **ArrayList** 和 **LinkedList** 都是 **List** 的类型,从输出中可以看出,它们都按插入顺序保存元素。两者之间的区别不仅在于执行某些类型的操作时的性能,而且 **LinkedList** 包含的操作多于 **ArrayList** 。本章后面将对这些内容进行更全面的探讨。 -**HashSet** , **TreeSet** 和 **LinkedHashSet** 是 **Set** 的类型。从输出中可以看到, **Set** 仅保存每个相同项中的一个,并且不同的 **Set** 实现存储元素的方式也不同。 **HashSet** 使用相当复杂的方法存储元素,这在[附录:集合主题]()中进行了探讨。现在只需要知道,这种技术是检索元素的最快方法,因此,存储顺序看上去没有什么意义(通常只关心某事物是否是 **Set** 的成员,而存储顺序并不重要)。如果存储顺序很重要,则可以使用 **TreeSet** ,它将按比较结果的升序保存对象)或 **LinkedHashSet** ,它按照被添加的先后顺序保存对象。 +**HashSet** , **TreeSet** 和 **LinkedHashSet** 是 **Set** 的类型。从输出中可以看到, **Set** 仅保存每个相同项中的一个,并且不同的 **Set** 实现存储元素的方式也不同。 **HashSet** 使用相当复杂的方法存储元素,这在[附录:集合主题]()中进行了探讨。现在只需要知道,这种技术是检索元素的最快方法,因此,存储顺序看上去没有什么意义(通常只关心某事物是否是 **Set** 的成员,而存储顺序并不重要)。如果存储顺序很重要,则可以使用 **TreeSet** ,它把对象按照比较规则来排序;还有 **LinkedHashSet** ,它把对象按照被添加的先后顺序来排序。 **Map** (也称为*关联数组*)使用*键*来查找对象,就像一个简单的数据库。所关联的对象称为*值*。 假设有一个 **Map** 将美国州名与它们的首府联系在一起,如果想要俄亥俄州(Ohio)的首府,可以用“Ohio”作为键来查找,几乎就像使用数组下标一样。正是由于这种行为,对于每个键, **Map** 只存储一次。 @@ -328,7 +328,7 @@ public class PrintingCollections { 本例使用了 **Map** 的三种基本风格: **HashMap** , **TreeMap** 和 **LinkedHashMap** 。 -键和值保存在 **HashMap** 中的顺序不是插入顺序,因为 **HashMap** 实现使用了非常快速的算法来控制顺序。 **TreeMap** 通过比较结果的升序来保存键, **LinkedHashMap** 在保持 **HashMap** 查找速度的同时按键的插入顺序保存键。 +键和值保存在 **HashMap** 中的顺序不是插入顺序,因为 **HashMap** 实现使用了非常快速的算法来控制顺序。 **TreeMap** 把所有的键按照比较规则来排序, **LinkedHashMap** 在保持 **HashMap** 查找速度的同时按照键的插入顺序来排序。 @@ -1800,9 +1800,9 @@ Serializable] [^1]: 许多语言,例如 Perl ,Python 和 Ruby ,都有集合的本地支持。 -[^2]: 这里是操作符重载的用武之地,C++和C#的集合类都使用操作符重载生成了更简洁的语法。 +**[2]**: 这里是操作符重载的用武之地,C++和C#的集合类都使用操作符重载生成了更简洁的语法。 -[^3]: 在[泛型]()章节的末尾,有个关于这个问题是否很严重的讨论。但是,[泛型]()章节还将展示Java泛型远不止是类型安全的集合这么简单。 +**[3]**: 在[泛型]()章节的末尾,有个关于这个问题是否很严重的讨论。但是,[泛型]()章节还将展示Java泛型远不止是类型安全的集合这么简单。 [^4]: `remove()` 是一个所谓的“可选”方法(还有一些其它的这种方法),这意味着并非所有的 **Iterator** 实现都必须实现该方法。这个问题将在[附录:集合主题]()中介绍。但是,标准 Java 库集合实现了 `remove()` ,因此在[附录:集合主题]()章节之前,都不必担心这个问题。 From 49dd428d19c17e1bc9b0ca516319ecb8c0b39f49 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 1 Dec 2020 18:09:01 +0800 Subject: [PATCH 17/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2013?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/12-Collections.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md index f0852bd8..3a4cd56d 100644 --- a/docs/book/12-Collections.md +++ b/docs/book/12-Collections.md @@ -729,7 +729,7 @@ pets.removeLast(): Hamster 堆栈是“后进先出”(LIFO)集合。它有时被称为*叠加栈*(pushdown stack),因为最后“压入”(push)栈的元素,第一个被“弹出”(pop)栈。经常用来类比栈的事物是带有弹簧支架的自助餐厅托盘。最后装入的托盘总是最先拿出来使用的。 -Java 1.0 中附带了一个 **Stack** 类,结果设计得很糟糕(为了向后兼容,我们永远坚持 Java 中的旧设计错误)。Java 6 添加了 **ArrayDeque** ,其中包含直接实现堆栈功能的方法: +Java 1.0 中附带了一个 **Stack** 类,结果设计得很糟糕(为了向后兼容,我们被迫一直忍受 Java 中的旧设计错误)。Java 6 添加了 **ArrayDeque** ,其中包含直接实现堆栈功能的方法: ```java // collections/StackTest.java @@ -861,7 +861,7 @@ public class SetOfInteger { 在 0 到 29 之间的 10000 个随机整数被添加到 **Set** 中,因此可以想象每个值都重复了很多次。但是从结果中可以看到,每一个数只有一个实例出现在结果中。 -早期 Java 版本中的 **HashSet** 产生的输出没有可辨别的顺序。这是因为出于对速度的追求, **HashSet** 使用了散列,请参阅[附录:集合主题]()一章。由 **HashSet** 维护的顺序与 **TreeSet** 或 **LinkedHashSet** 不同,因为它们的实现具有不同的元素存储方式。 **TreeSet** 将元素存储在红-黑树数据结构中,而 **HashSet** 使用散列函数。 **LinkedHashSet** 因为查询速度的原因也使用了散列,但是看起来使用了链表来维护元素的插入顺序。看起来散列算法好像已经改变了,现在 **Integer** 按顺序排序。但是,您不应该依赖此行为: +早期 Java 版本中的 **HashSet** 产生的输出没有明显的顺序。这是因为出于对速度的追求, **HashSet** 使用了散列,请参阅[附录:集合主题]()一章。由 **HashSet** 维护的顺序与 **TreeSet** 或 **LinkedHashSet** 不同,因为它们的实现具有不同的元素存储方式。 **TreeSet** 将元素存储在红-黑树数据结构中,而 **HashSet** 使用散列函数。 **LinkedHashSet** 也使用散列来提高查询速度,但是似乎使用了链表来维护元素的插入顺序。显然,散列算法有改动,以至于现在(上述示例中的HashSet ) **Integer** 是有序的。但是,您不应该依赖此行为(下面例子就没有排序): ```java // collections/SetOfString.java @@ -990,7 +990,7 @@ void] */ ``` -我们逐步浏览文件中的每一行,并使用 `String.split()` 将其分解为单词,这里使用正则表达式 **\\\ W +** ,这意味着它会依据一个或多个(即 **+** )非单词字母来拆分字符串(正则表达式将在[字符串]()章节介绍)。每个结果单词都会添加到 **Set words** 中。因为它是 **TreeSet** ,所以对结果进行排序。这里,排序是按*字典顺序*(lexicographically)完成的,因此大写和小写字母位于不同的组中。如果想按*字母顺序*(alphabetically)对其进行排序,可以向 **TreeSet** 构造器传入 **String.CASE_INSENSITIVE_ORDER** 比较器(比较器是一个建立排序顺序的对象): +我们逐步浏览文件中的每一行,并使用 `String.split()` 将其分解为单词,这里使用正则表达式 **\\\ W +** ,这意味着它会依据一个或多个(即 **+** )非单词字母来拆分字符串(正则表达式将在[字符串]()章节介绍)。每个结果单词都会添加到 **Set words** 中。因为它是 **TreeSet** ,所以对结果进行排序。这里,排序是按*字典顺序*(lexicographically)完成的,因此大写字母和小写字母是分开的。如果想按*字母顺序*(alphabetically)对其进行排序,可以向 **TreeSet** 构造器传入 **String.CASE_INSENSITIVE_ORDER** 比较器(比较器是一个建立排序顺序的对象): ```java // collections/UniqueWordsAlphabetic.java @@ -1088,7 +1088,7 @@ true */ ``` -**Map** 与数组和其他的 **Collection** 一样,可以轻松地扩展到多个维度,只需要创建一个值为 **Map** 的 **Map**(这些 **Map** 的值可以是其他集合,甚至是其他 **Map**)。因此,能够很容易地将集合组合起来以快速生成强大的数据结构。例如,假设你正在追踪有多个宠物的人,只需要一个 **Map\>** 即可: +**Map** 与数组和其他的 **Collection** 一样,可以轻松地扩展到多个维度:只需要创建一个 **Map** ,其值也是 **Map** (这些 **Map** 的值可以是其他集合,甚至是其他的 **Map** )。因此,能够很容易地将集合组合起来以快速生成强大的数据结构。例如,假设你正在追踪有多个宠物的人,只需要一个 **Map\>** 即可: ```java From 25992cf3e2fff98b88cd925ccea5692be0827b14 Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Tue, 1 Dec 2020 21:16:19 +0800 Subject: [PATCH 18/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2014?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/08-Reuse.md | 22 ++++++++++++---------- docs/book/11-Inner-Classes.md | 2 +- docs/book/12-Collections.md | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/book/08-Reuse.md b/docs/book/08-Reuse.md index e10f8751..cf27c665 100644 --- a/docs/book/08-Reuse.md +++ b/docs/book/08-Reuse.md @@ -690,9 +690,9 @@ doh(Milhouse) ```` -**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名[^1]和返回类型。否则会让人感到困惑。 +**Homer** 的所有重载方法在 **Bart** 中都是可用的,尽管 **Bart** 引入了一种新的重载方法。正如你将在下一章中看到的那样,比起重载,更常见的是覆盖同名方法,使用与基类中完全相同的方法签名[^2]和返回类型。否则会让人感到困惑。 -你已经看到了Java 5 **@Override**注解,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^2]时,你可以选择添加这个注解,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: +你已经看到了Java 5 **@Override**注解,它不是关键字,但是可以像使用关键字一样使用它。当你打算重写一个方法[^3]时,你可以选择添加这个注解,如果你不小心用了重载而不是重写,编译器会产生一个错误消息: ```java @@ -712,12 +712,7 @@ class Lisa extends Homer { **{WillNotCompile}** 标记将该文件排除在本书的 **Gradle** 构建之外,但是如果你手工编译它,你将看到:method does not override a method from its superclass.方法不会重写超类中的方法, **@Override** 注解能防止你意外地重载。 -- **[1]** 方法签名——方法名和参数类型的合称 - -- **[2]** 重写——覆盖同名方法,使用与基类中完全相同的方法签名和返回类型[^3] - -- **[3]** 在java 1.4版本以前,重写方法的返回值类型被要求必须与被重写方法一致,但是在java 5.0中放宽了这一个限制,添加了对协变返回类型的支持,在重写的时候,重写方法的返回值类型可以是被重写方法返回值类型的子类。 - + ## 组合与继承的选择 @@ -1182,8 +1177,6 @@ Java 标准类库就是一个很好的例子。尤其是 Java 1.0/1.1 的 **Vect Java 1.0/1.1 标准类库中另一个重要的类是 **Hashtable**(后来被 **HashMap** 取代),它不含任何 **final** 方法。本书中其他地方也提到,很明显不同的类是由不同的人设计的。**Hashtable** 就比 **Vector** 中的方法名简洁得多,这又是一条证据。对于类库的使用者来说,这是一个本不应该如此草率的事情。这种不规则的情况造成用户需要做更多的工作——这是对粗糙的设计和代码的又一讽刺。 -- **[1]** Java 1.4 开始已将 **Vector** 类大多数方法的 **final** 去掉 - ## 类初始化和加载 @@ -1267,6 +1260,15 @@ j = 39 当开始设计一个系统时,记住程序开发是一个增量过程,正如人类学习。它依赖实验,你可以尽可能多做分析,然而在项目开始时仍然无法知道所有的答案。如果把项目视作一个有机的,进化着的生命去培养,而不是视为像摩天大楼一样快速见效,就能获得更多的成功和更迅速的反馈。继承和组合正是可以让你执行如此实验的面向对象编程中最基本的两个工具。 +[^1]: Java 1.4 开始已将 **Vector** 类大多数方法的 **final** 去掉 + +[^2]: 方法签名——方法名和参数类型的合称 + +[^3]: 重写——覆盖同名方法,使用与基类中完全相同的方法签名和返回类型[^4] + +[^4]: 在java 1.4版本以前,重写方法的返回值类型被要求必须与被重写方法一致,但是在java 5.0中放宽了这一个限制,添加了对协变返回类型的支持,在重写的时候,重写方法的返回值类型可以是被重写方法返回值类型的子类。 + +
diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md index 83376eb8..caf557e8 100755 --- a/docs/book/11-Inner-Classes.md +++ b/docs/book/11-Inner-Classes.md @@ -1434,7 +1434,7 @@ LocalInnerClass.class 虽然这种命名格式简单而直接,但它还是很健壮的,足以应对绝大多数情况[^1]。因为这是 Java 的标准命名方式,所以产生的文件自动都是平台无关的。(注意,为了保证你的内部类能起作用,Java 编译器会尽可能地转换它们。) -- **[1]** 另一方面,**$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。 +[^1]: 另一方面,**$** 对Unix shell来说是一个元字符,所以当你列出.class文件时,有时会遇到麻烦。这对基于Unix的Sun公司来说有点奇怪。我的猜测是,他们没有考虑这个问题,而是认为你会很自然地关注源代码文件。 ## 本章小结 diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md index 3a4cd56d..f85c9769 100644 --- a/docs/book/12-Collections.md +++ b/docs/book/12-Collections.md @@ -1800,9 +1800,9 @@ Serializable] [^1]: 许多语言,例如 Perl ,Python 和 Ruby ,都有集合的本地支持。 -**[2]**: 这里是操作符重载的用武之地,C++和C#的集合类都使用操作符重载生成了更简洁的语法。 +[^2]: 这里是操作符重载的用武之地,C++和C#的集合类都使用操作符重载生成了更简洁的语法。 -**[3]**: 在[泛型]()章节的末尾,有个关于这个问题是否很严重的讨论。但是,[泛型]()章节还将展示Java泛型远不止是类型安全的集合这么简单。 +[^3]: 在[泛型]()章节的末尾,有个关于这个问题是否很严重的讨论。但是,[泛型]()章节还将展示Java泛型远不止是类型安全的集合这么简单。 [^4]: `remove()` 是一个所谓的“可选”方法(还有一些其它的这种方法),这意味着并非所有的 **Iterator** 实现都必须实现该方法。这个问题将在[附录:集合主题]()中介绍。但是,标准 Java 库集合实现了 `remove()` ,因此在[附录:集合主题]()章节之前,都不必担心这个问题。 From 1633ffd72c1df6f51fc3e5c376af44a85c9bacb5 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Wed, 2 Dec 2020 15:58:50 +0800 Subject: [PATCH 19/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2014?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/12-Collections.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md index f85c9769..63677284 100644 --- a/docs/book/12-Collections.md +++ b/docs/book/12-Collections.md @@ -1164,7 +1164,7 @@ Person Luke has: 队列是一个典型的“先进先出”(FIFO)集合。 即从集合的一端放入事物,再从另一端去获取它们,事物放入集合的顺序和被取出的顺序是相同的。队列通常被当做一种可靠的将对象从程序的某个区域传输到另一个区域的途径。队列在[并发编程]()中尤为重要,因为它们可以安全地将对象从一个任务传输到另一个任务。 -**LinkedList** 实现了 **Queue** 接口,并且提供了一些方法以支持队列行为,因此 **LinkedList** 可以用作 **Queue** 的一种实现。 通过将 **LinkedList** 向上转换为 **Queue** ,下面的示例使用了在 **Queue** 接口中与 **Queue** 相关(Queue-specific)的方法: +**LinkedList** 实现了 **Queue** 接口,并且提供了一些方法以支持队列行为,因此 **LinkedList** 可以用作 **Queue** 的一种实现。 通过将 **LinkedList** 向上转换为 **Queue** ,下面的示例使用了在 **Queue** 接口中的 **Queue** 特有(Queue-specific)方法: ```java // collections/QueueDemo.java @@ -1195,18 +1195,18 @@ B r o n t o s a u r u s */ ``` -`offer()` 是与 **Queue** 相关的方法之一,它在允许的情况下,在队列的尾部插入一个元素,或者返回 **false** 。 `peek()` 和 `element()` 都返回队头元素而不删除它,但是如果队列为空,则 `element()` 抛出 **NoSuchElementException** ,而 `peek()` 返回 **null** 。 `poll()` 和 `remove()`* 都删除并返回队头元素,但如果队列为空,`poll()` 返回 **null** ,而 `remove()` 抛出 **NoSuchElementException** 。 +`offer()` 是 **Queue** 的特有方法之一,它在允许的情况下,在队列的尾部插入一个元素,或者返回 **false** 。 `peek()` 和 `element()` 都返回队头元素而不删除它,但如果队列为空,则 `peek()` 返回 **null** , 而 `element()` 抛出 **NoSuchElementException** 。 `poll()` 和 `remove()` 都删除并返回队头元素,但如果队列为空,则 `poll()` 返回 **null** ,而 `remove()` 抛出 **NoSuchElementException** 。 自动包装机制会自动将 `nextInt()` 的 **int** 结果转换为 **queue** 所需的 **Integer** 对象,并将 **char c** 转换为 **qc** 所需的 **Character** 对象。 **Queue** 接口窄化了对 **LinkedList** 方法的访问权限,因此只有适当的方法才能使用,因此能够访问到的 **LinkedList** 的方法会变少(这里实际上可以将 **Queue** 强制转换回 **LinkedList** ,但至少我们不鼓励这样做)。 -与 **Queue** 相关的方法提供了完整而独立的功能。 也就是说,对于 **Queue** 所继承的 **Collection** ,在不需要使用它的任何方法的情况下,就可以拥有一个可用的 **Queue** 。 +**Queue** 的特有方法提供了独立而完整的功能。 换句话说, **Queue** 无需调用继承自 **Collection** 的方法,(只依靠 **Queue** 的特有方法)就有队列的功能。 ### 优先级队列PriorityQueue -先进先出(FIFO)描述了最典型的*队列规则*(queuing discipline)。队列规则是指在给定队列中的一组元素的情况下,确定下一个弹出队列的元素的规则。先进先出声明的是下一个弹出的元素应该是等待时间最长的元素。 +先进先出(FIFO)描述了最典型的*队列规则*(queuing discipline)。队列规则是指在给定队列中的一组元素的情况下,确定下一个弹出队列的元素的规则。先进先出:下一个弹出的元素应该是等待时间最长的那一个。 -优先级队列声明下一个弹出的元素是最需要的元素(具有最高的优先级)。例如,在机场,当飞机临近起飞时,这架飞机的乘客可以在办理登机手续时排到队头。如果构建了一个消息传递系统,某些消息比其他消息更重要,应该尽快处理,而不管它们何时到达。在Java 5 中添加了 **PriorityQueue** ,以便自动实现这种行为。 +*优先级队列* :下一个弹出的元素是最需要的元素(具有最高的优先级)。例如,在机场,飞机即将起飞的、尚未登机的乘客可能会被拉出队伍(作最优先的处理)。如果构建了一个消息传递系统,某些消息比其他消息更重要,应该尽快处理,而不管它们到达时间先后。在Java 5 中添加了 **PriorityQueue** ,以便自动实现这种行为。 当在 **PriorityQueue** 上调用 `offer()` 方法来插入一个对象时,该对象会在队列中被排序。[^5]默认的排序使用队列中对象的*自然顺序*(natural order),但是可以通过提供自己的 **Comparator** 来修改这个顺序。 **PriorityQueue** 确保在调用 `peek()` , `poll()` 或 `remove()` 方法时,获得的元素将是队列中优先级最高的元素。 @@ -1804,9 +1804,9 @@ Serializable] [^3]: 在[泛型]()章节的末尾,有个关于这个问题是否很严重的讨论。但是,[泛型]()章节还将展示Java泛型远不止是类型安全的集合这么简单。 -[^4]: `remove()` 是一个所谓的“可选”方法(还有一些其它的这种方法),这意味着并非所有的 **Iterator** 实现都必须实现该方法。这个问题将在[附录:集合主题]()中介绍。但是,标准 Java 库集合实现了 `remove()` ,因此在[附录:集合主题]()章节之前,都不必担心这个问题。 +[^4]: `remove()` 是一个所谓的“可选”方法(还有其它这样的方法),这意味着并非所有的 **Iterator** 实现都必须实现该方法。这个问题将在[附录:集合主题]()中介绍。但是,标准 Java 库集合实现了 `remove()` ,因此在[附录:集合主题]()章节之前,都不必担心这个问题。 -[^5]: 这实际上依赖于具体实现。优先级队列算法通常会按插入顺序排序(维护一个*堆*),但它们也可以在删除时选择最重要的元素。 如果对象的优先级在它在队列中等待时可以修改,那么算法的选择就显得很重要了。 +[^5]: 这实际上依赖于具体实现。优先级队列算法通常会按插入顺序排序(维护一个*堆*),但它们也可以在删除时选择最重要的元素。 如果一个对象在队列中等待时,它的优先级会发生变化,那么算法的选择就很重要。 [^6]: 有些人提倡这样一种自动创建机制,即对一个类中所有可能的方法组合都自动创建一个接口,有时候对于单个的类都是如此。 我相信接口的意义不应该仅限于方法组合的机械地复制,因此我在创建接口之前,总是要先看到增加接口带来的价值。 From 8d1651b076ec40fc3235f34a11faa87ab9dc998b Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 3 Dec 2020 10:52:12 +0800 Subject: [PATCH 20/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2015?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/12-Collections.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md index 63677284..131d1771 100644 --- a/docs/book/12-Collections.md +++ b/docs/book/12-Collections.md @@ -1274,9 +1274,9 @@ C B A A ## 集合与迭代器 -**Collection** 是所有序列集合共有的根接口。它可能会被认为是一种“附属接口”(incidental interface),即因为要表示其他若干个接口的共性而出现的接口。此外,**java.util.AbstractCollection** 类提供了 **Collection** 的默认实现,使得你可以创建 **AbstractCollection** 的子类型,而其中没有不必要的代码重复。 +**Collection** 是所有序列集合共有的根接口。它可能会被认为是一种“附属接口”(incidental interface),即因为要表示其他若干个接口的共性而出现的接口。此外,**java.util.AbstractCollection** 类提供了 **Collection** 的默认实现,你可以创建 **AbstractCollection** 的子类型来避免不必要的代码重复。 -使用接口描述的一个理由是它可以使我们创建更通用的代码。通过针对接口而非具体实现来编写代码,我们的代码可以应用于更多类型的对象。[^6]因此,如果所编写的方法接受一个 **Collection** ,那么该方法可以应用于任何实现了 **Collection** 的类——这也就使得一个新类可以选择去实现 **Collection** 接口,以便该方法可以使用它。标准 C++ 类库中的集合并没有共同的基类——集合之间的所有共性都是通过迭代器实现的。在 Java 中,遵循 C++ 的方式看起来似乎很明智,即用迭代器而不是 **Collection** 来表示集合之间的共性。但是,这两种方法绑定在了一起,因为实现 **Collection** 就意味着需要提供 `iterator()` 方法: +使用接口的一个理由是它可以使我们创建更通用的代码。通过针对接口而非具体实现来编写代码,我们的代码可以应用于更多类型的对象。[^6]因此,如果所编写的方法接受一个 **Collection** ,那么该方法可以应用于任何实现了 **Collection** 的类——这也就使得一个新类可以选择去实现 **Collection** 接口,以便该方法可以使用它。标准 C++ 类库中的集合并没有共同的基类——集合之间的所有共性都是通过迭代器实现的。在 Java 中,遵循 C++ 的方式看起来似乎很明智,即用迭代器而不是 **Collection** 来表示集合之间的共性。但是,这两种方法绑定在了一起,因为实现 **Collection** 就意味着需要提供 `iterator()` 方法: ```java // collections/InterfaceVsIterator.java @@ -1337,7 +1337,7 @@ Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx} 在本例中,这两种方式都可以奏效。事实上, **Collection** 要更方便一点,因为它是 **Iterable** 类型,因此在 `display(Collection)` 的实现中可以使用 *for-in* 构造,这使得代码更加清晰。 -当需要实现一个不是 **Collection** 的外部类时,由于让它去实现 **Collection** 接口可能非常困难或麻烦,因此使用 **Iterator** 就会变得非常吸引人。例如,如果我们通过继承一个持有 **Pet** 对象的类来创建一个 **Collection** 的实现,那么我们必须实现 **Collection** 所有的方法,即使我们不在 `display()` 方法中使用它们,也必须这样做。虽然这可以通过继承 **AbstractCollection** 而很容易地实现,但是无论如何还是要被强制去实现 `iterator()` 和 `size()` 方法,这些方法 **AbstractCollection** 没有实现,但是 **AbstractCollection** 中的其它方法会用到: +当需要实现一个不是 **Collection** 的外部类时,由于让它去实现 **Collection** 接口可能非常困难或麻烦,因此使用 **Iterator** 就会变得非常吸引人。例如,如果我们通过继承一个持有 **Pet** 对象的类来创建一个 **Collection** 的实现,那么我们必须实现 **Collection** 所有的方法,纵使我们不会在 `display()` 方法中使用它们,也要这样做。尽管通过继承 **AbstractCollection** 会容易些,但是 **AbstractCollection** 还有 `iterator()` 和 `size()`没有实现(抽象方法),而 **AbstractCollection** 中的其它方法会用到它们,因此必须以自己的方式实现这两个方法: ```java // collections/CollectionSequence.java @@ -1383,7 +1383,7 @@ extends AbstractCollection { - **[1]** 你可能会认为,因为 `iterator()` 返回 **Iterator\** ,匿名内部类定义可以使用菱形语法,Java可以推断出类型。但这不起作用,类型推断仍然非常有限。 -这个例子表明,如果实现了 **Collection** ,就必须实现 `iterator()` ,并且只拿实现 `iterator()` 与继承 **AbstractCollection** 相比,花费的代价只有略微减少。但是,如果类已经继承了其他的类,那么就不能再继承 **AbstractCollection** 了。在这种情况下,要实现 **Collection** ,就必须实现该接口中的所有方法。此时,继承并提供创建迭代器的能力要容易得多: +这个例子表明,如果实现了 **Collection** ,就必须也实现 `iterator()` ,而单独只实现 `iterator()` 和继承 **AbstractCollection** 相比,并没有容易多少。但是,如果类已经继承了其他的类,那么就没法再继承 **AbstractCollection** 了。在这种情况下,要实现 **Collection** ,就必须实现该接口中的所有方法。此时,继承并提供创建迭代器的能力(单独只实现 `iterator()`)要容易得多: ```java // collections/NonCollectionSequence.java @@ -1422,12 +1422,12 @@ public class NonCollectionSequence extends PetSequence { */ ``` -生成 **Iterator** 是将序列与消费该序列的方法连接在一起耦合度最小的方式,并且与实现 **Collection** 相比,它在序列类上所施加的约束也少得多。 +生成 **Iterator** 是将序列与消费该序列的方法连接在一起的耦合度最小的方式,并且与实现 **Collection** 相比,它在序列类上所施加的约束也少得多。 ## for-in和迭代器 -到目前为止,*for-in* 语法主要用于数组,但它也适用于任何 **Collection** 对象。实际上在使用 **ArrayList** 时,已经看到了一些使用它的示例,下面是一个更通用的证明: +到目前为止,*for-in* 语法主要用于数组,但它也适用于任何 **Collection** 对象。实际上在使用 **ArrayList** 时,已经看到了一些使用它的示例,下面是它的通用性的证明: ```java // collections/ForInCollections.java @@ -1508,7 +1508,7 @@ public class EnvironmentVariables { `System.getenv()` [^7]返回一个 **Map** , `entrySet()` 产生一个由 **Map.Entry** 的元素构成的 **Set** ,并且这个 **Set** 是一个 **Iterable** ,因此它可以用于 *for-in* 循环。 -*for-in* 语句适用于数组或其它任何 **Iterable** ,但这并不意味着数组肯定也是个 **Iterable** ,也不会发生任何自动装箱: +*for-in* 语句适用于数组或者其它任何 **Iterable** ,但这并不代表数组一定是 **Iterable** ,也不会发生任何自动装箱: ```java // collections/ArrayIsNotIterable.java @@ -1684,7 +1684,7 @@ array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8] */ ``` -在第一种情况下, `Arrays.asList()` 的输出被传递给了 **ArrayList** 的构造器,这将创建一个引用 **ia** 的元素的 **ArrayList** ,因此打乱这些引用不会修改该数组。但是,如果直接使用 `Arrays.asList(ia)` 的结果,这种打乱就会修改 **ia** 的顺序。重要的是要注意 `Arrays.asList()` 生成一个 **List** 对象,该对象使用底层数组作为其物理实现。如果执行的操作会修改这个 **List** ,并且不希望修改原始数组,那么就应该在另一个集合中创建一个副本。 +在第一种情况下, `Arrays.asList()` 的输出被传递给了 **ArrayList** 的构造器,这将创建一个引用 **ia** 的元素的 **ArrayList** ,因此打乱这些引用不会修改该数组。但是,如果直接使用 `Arrays.asList(ia)` 的结果,这种打乱就会修改 **ia** 的顺序。重要的是要注意 `Arrays.asList()` 生成一个 **List** 对象,该对象使用底层数组作为其物理实现。如果对 **List** 对象做了任何修改,又不想让原始数组被修改,那么就应该在另一个集合中创建一个副本。 ## 本章小结 @@ -1808,7 +1808,7 @@ Serializable] [^5]: 这实际上依赖于具体实现。优先级队列算法通常会按插入顺序排序(维护一个*堆*),但它们也可以在删除时选择最重要的元素。 如果一个对象在队列中等待时,它的优先级会发生变化,那么算法的选择就很重要。 -[^6]: 有些人提倡这样一种自动创建机制,即对一个类中所有可能的方法组合都自动创建一个接口,有时候对于单个的类都是如此。 我相信接口的意义不应该仅限于方法组合的机械地复制,因此我在创建接口之前,总是要先看到增加接口带来的价值。 +[^6]: 有些人鼓吹不加思索地创建接口对应一个类甚至每个类中的所有可能的方法组合。 但我相信接口的意义不应该仅限于机械地重复方法组合,因此我倾向于看到增加接口的价值才创建它。 [^7]: 这在 Java 5 之前是不可用的,因为该方法被认为与操作系统的耦合度过紧,因此违反“一次编写,处处运行”的原则。现在却提供它,这一事实表明, Java 的设计者们更加务实了。 From a4d14ccd4c266ff02fa9a02b2ce27485860d92ba Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 3 Dec 2020 18:08:18 +0800 Subject: [PATCH 21/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2016?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/12-Collections.md | 4 +-- docs/book/13-Functional-Programming.md | 40 +++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/book/12-Collections.md b/docs/book/12-Collections.md index 131d1771..e34688fa 100644 --- a/docs/book/12-Collections.md +++ b/docs/book/12-Collections.md @@ -1538,10 +1538,10 @@ public class ArrayIsNotIterable { ### 适配器方法惯用法 -如果现在有一个 **Iterable** 类,你想要添加一种或多种在 *for-in* 语句中使用这个类的方法,应该怎么做呢?例如,你希望可以选择正向还是反向遍历一个单词列表。如果直接继承这个类,并覆盖 `iterator()` 方法,则只能替换现有的方法,而不能实现遍历顺序的选择。 +如果现在有一个 **Iterable** 类,你想要添加一种或多种在 *for-in* 语句中使用这个类的方法,应该怎么做呢?例如,你希望可以选择正向还是反向遍历一个单词列表。如果直接继承这个类,并重写 `iterator()` 方法,则只能替换现有的方法,而不能实现遍历顺序的选择。 一种解决方案是所谓*适配器方法*(Adapter Method)的惯用法。“适配器”部分来自于设计模式,因为必须要提供特定的接口来满足 *for-in* 语句。如果已经有一个接口并且需要另一个接口时,则编写适配器就可以解决这个问题。 -在这里,若希望在默认的正向迭代器的基础上,添加产生反向迭代器的能力,因此不能使用覆盖,相反,而是添加了一个能够生成 **Iterable** 对象的方法,该对象可以用于 *for-in* 语句。这使得我们可以提供多种使用 *for-in* 语句的方式: +在这里,若希望在默认的正向迭代器的基础上,添加产生反向迭代器的能力,因此不能使用重写,相反,而是添加了一个能够生成 **Iterable** 对象的方法,该对象可以用于 *for-in* 语句。这使得我们可以提供多种使用 *for-in* 语句的方式: ```java // collections/AdapterMethodIdiom.java diff --git a/docs/book/13-Functional-Programming.md b/docs/book/13-Functional-Programming.md index 0f8b5e83..fc4a6818 100644 --- a/docs/book/13-Functional-Programming.md +++ b/docs/book/13-Functional-Programming.md @@ -127,7 +127,7 @@ Hello there Hello there Lambda 表达式是使用**最小可能**语法编写的函数定义: -1. Lambda 表达式产生函数,而不是类。 在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是一个类,因此在幕后执行各种操作使 Lambda 看起来像函数 —— 但作为程序员,你可以高兴地假装它们“只是函数”。 +1. Lambda 表达式产生函数,而不是类。 虽然在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是类,但是幕后有各种操作执行让 Lambda 看起来像函数 —— 作为程序员,你可以高兴地假装它们“就是函数”。 2. Lambda 语法尽可能少,这正是为了使 Lambda 易于编写和使用。 @@ -424,7 +424,7 @@ lambda Go::go() ``` -**Thread** 对象将 **Runnable** 作为其构造函数参数,并具有会调用 `run()` 的方法 `start()`。 **注意**,只有**匿名内部类**才需要具有名为 `run()` 的方法。 +**Thread** 对象将 **Runnable** 作为其构造函数参数,并具有会调用 `run()` 的方法 `start()`。 注意这里只有**匿名内部类**才要求显式声明 `run()` 方法。 @@ -469,11 +469,11 @@ X::f() ``` -截止目前,我们看到了与对应接口签名相同的方法引用。 在 **[1]**,我们尝试把 `X` 的 `f()` 方法引用赋值给 **MakeString**。结果即使 `make()` 与 `f()` 具有相同的签名,编译也会报“invalid method reference”(无效方法引用)错误。 这是因为实际上还有另一个隐藏的参数:我们的老朋友 `this`。 你不能在没有 `X` 对象的前提下调用 `f()`。 因此,`X :: f` 表示未绑定的方法引用,因为它尚未“绑定”到对象。 +到目前为止,我们已经见过了方法引用和对应接口的签名(参数类型和返回类型)一致的几个赋值例子。 在 **[1]** 中,我们尝试同样的做法,把 `X` 的 `f()` 方法引用赋值给 **MakeString**。结果即使 `make()` 与 `f()` 具有相同的签名,编译也会报“invalid method reference”(无效方法引用)错误。 问题在于,这里其实还需要另一个隐藏参数参与:我们的老朋友 `this`。 你不能在没有 `X` 对象的前提下调用 `f()`。 因此,`X :: f` 表示未绑定的方法引用,因为它尚未“绑定”到对象。 -要解决这个问题,我们需要一个 `X` 对象,所以我们的接口实际上需要一个额外的参数,如上例中的 **TransformX**。 如果将 `X :: f` 赋值给 **TransformX**,在 Java 中是允许的。我们必须做第二个心理调整——使用未绑定的引用时,函数式方法的签名(接口中的单个方法)不再与方法引用的签名完全匹配。 原因是:你需要一个对象来调用方法。 +要解决这个问题,我们需要一个 `X` 对象,因此我们的接口实际上需要一个额外的参数,正如在 **TransformX** 中看到的那样。 如果将 `X :: f` 赋值给 **TransformX**,在 Java 中是允许的。我们必须做第二个心理调整——使用未绑定的引用时,函数式方法的签名(接口中的单个方法)不再与方法引用的签名完全匹配。 原因是:你需要一个对象来调用方法。 -**[2]** 的结果有点像脑筋急转弯。我拿到未绑定的方法引用,并且调用它的`transform()`方法,将一个X类的对象传递给它,最后使得 `x.f()` 以某种方式被调用。Java知道它必须拿到第一个参数,该参数实际就是`this`,然后调用方法作用在它之上。 +**[2]** 的结果有点像脑筋急转弯。我拿到未绑定的方法引用,并且调用它的`transform()`方法,将一个X类的对象传递给它,最后使得 `x.f()` 以某种方式被调用。Java知道它必须拿第一个参数,该参数实际就是`this` 对象,然后对此调用方法。 如果你的方法有更多个参数,就以第一个参数接受`this`的模式来处理。 @@ -574,7 +574,7 @@ x -> x.toString() 我们清楚这里返回类型必须是 **String**,但 `x` 是什么类型呢? -Lambda 表达式包含类型推导(编译器会自动推导出类型信息,避免了程序员显式地声明)。编译器必须能够以某种方式推导出 `x` 的类型。 +Lambda 表达式包含 *类型推导* (编译器会自动推导出类型信息,避免了程序员显式地声明)。编译器必须能够以某种方式推导出 `x` 的类型。 下面是第二个代码示例: @@ -586,7 +586,7 @@ Lambda 表达式包含类型推导(编译器会自动推导出类型信息, 该问题也适用于方法引用。 假设你要传递 `System.out :: println` 到你正在编写的方法 ,你怎么知道传递给方法的参数的类型? -为了解决这个问题,Java 8 引入了 `java.util.function` 包。它包含一组接口,这些接口是 Lambda 表达式和方法引用的目标类型。 每个接口只包含一个抽象方法,称为函数式方法。 +为了解决这个问题,Java 8 引入了 `java.util.function` 包。它包含一组接口,这些接口是 Lambda 表达式和方法引用的目标类型。 每个接口只包含一个抽象方法,称为 *函数式方法* 。 在编写接口时,可以使用 `@FunctionalInterface` 注解强制执行此“函数式方法”模式: @@ -630,11 +630,11 @@ public class FunctionalAnnotation { } ``` -`@FunctionalInterface` 注解是可选的; Java 在 `main()` 中把 **Functional** 和 **FunctionalNoAnn** 都当作函数式接口。 在 `NotFunctional` 的定义中可看到`@FunctionalInterface` 的作用:接口中如果有多个抽象方法则会产生编译期错误。 +`@FunctionalInterface` 注解是可选的; Java 会在 `main()` 中把 **Functional** 和 **FunctionalNoAnn** 都当作函数式接口来看待。 在 `NotFunctional` 的定义中可看出`@FunctionalInterface` 的作用:当接口中抽象方法多于一个时产生编译期错误。 -仔细观察在定义 `f` 和 `fna` 时发生了什么。 `Functional` 和 `FunctionalNoAnn` 定义接口,然而被赋值的只是方法 `goodbye()`。首先,这只是一个方法而不是类;其次,它甚至都不是实现了该接口的类中的方法。这是添加到Java 8中的一点小魔法:如果将方法引用或 Lambda 表达式赋值给函数式接口(类型需要匹配),Java 会适配你的赋值到目标接口。 编译器会在后台把方法引用或 Lambda 表达式包装进实现目标接口的类的实例中。 +仔细观察在定义 `f` 和 `fna` 时发生了什么。 `Functional` 和 `FunctionalNoAnn` 声明了是接口,然而被赋值的只是方法 `goodbye()`。首先,这只是一个方法而不是类;其次,它甚至都不是实现了该接口的类中的方法。这是添加到Java 8中的一点小魔法:如果将方法引用或 Lambda 表达式赋值给函数式接口(类型需要匹配),Java 会适配你的赋值到目标接口。 编译器会在后台把方法引用或 Lambda 表达式包装进实现目标接口的类的实例中。 -尽管 `FunctionalAnnotation` 确实适合 `Functional` 模型,但 Java不允许我们像`fac`定义中的那样,将 `FunctionalAnnotation` 直接赋值给 `Functional`,因为 `FunctionalAnnotation` 并没有显式地去实现 `Functional` 接口。唯一的惊喜是,Java 8 允许我们将函数赋值给接口,这样的语法更加简单漂亮。 +虽然 `FunctionalAnnotation` 确实符合 `Functional` 模型,但是 Java不允许我们像`fac`定义的那样,将 `FunctionalAnnotation` 直接赋值给 `Functional`,因为 `FunctionalAnnotation` 并没有显式地去实现 `Functional` 接口。唯一的惊喜是,Java 8 允许我们将函数赋值给接口,这样的语法更加简单漂亮。 `java.util.function` 包旨在创建一组完整的目标接口,使得我们一般情况下不需再定义自己的接口。主要因为基本类型的存在,导致预定义的接口数量有少许增加。 如果你了解命名模式,顾名思义就能知道特定接口的作用。 @@ -646,9 +646,9 @@ public class FunctionalAnnotation { 3. 如果返回值为基本类型,则用 `To` 表示,如 `ToLongFunction ` 和 `IntToLongFunction`。 -4. 如果返回值类型与参数类型一致,则是一个运算符:单个参数使用 `UnaryOperator`,两个参数使用 `BinaryOperator`。 +4. 如果返回值类型与参数类型一致,则是一个 `Operator` :单个参数使用 `UnaryOperator`,两个参数使用 `BinaryOperator`。 -5. 如果接收两个参数且返回值为布尔值,则是一个谓词(Predicate)。 +5. 如果接收两个参数且返回值为布尔值,则是一个 `Predicate`。 6. 如果接收的两个参数类型不同,则名称中有一个 `Bi`。 @@ -661,14 +661,14 @@ public class FunctionalAnnotation { |无参数;
返回类型任意|**Callable**
(java.util.concurrent)
`call()`|**Callable``**| |1 参数;
无返回值|**Consumer**
`accept()`|**`Consumer`
IntConsumer
LongConsumer
DoubleConsumer**| |2 参数 **Consumer**|**BiConsumer**
`accept()`|**`BiConsumer`**| -|2 参数 **Consumer**;
1 引用;
1 基本类型|**Obj类型Consumer**
`accept()`|**`ObjIntConsumer`
`ObjLongConsumer`
`ObjDoubleConsumer`**| +|2 参数 **Consumer**;
第一个参数是 引用;
第二个参数是 基本类型|**Obj类型Consumer**
`accept()`|**`ObjIntConsumer`
`ObjLongConsumer`
`ObjDoubleConsumer`**| |1 参数;
返回类型不同|**Function**
`apply()`
**To类型** 和 **类型To类型**
`applyAs类型()`|**Function``
IntFunction``
`LongFunction`
DoubleFunction``
ToIntFunction``
`ToLongFunction`
`ToDoubleFunction`
IntToLongFunction
IntToDoubleFunction
LongToIntFunction
LongToDoubleFunction
DoubleToIntFunction
DoubleToLongFunction**| |1 参数;
返回类型相同|**UnaryOperator**
`apply()`|**`UnaryOperator`
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator**| -|2 参数类型相同;
返回类型相同|**BinaryOperator**
`apply()`|**`BinaryOperator`
IntBinaryOperator
LongBinaryOperator
DoubleBinaryOperator**| -|2 参数类型相同;
返回整型|Comparator
(java.util)
`compare()`|**`Comparator`**| +|2 参数,类型相同;
返回类型相同|**BinaryOperator**
`apply()`|**`BinaryOperator`
IntBinaryOperator
LongBinaryOperator
DoubleBinaryOperator**| +|2 参数,类型相同;
返回整型|Comparator
(java.util)
`compare()`|**`Comparator`**| |2 参数;
返回布尔型|**Predicate**
`test()`|**`Predicate`
`BiPredicate`
IntPredicate
LongPredicate
DoublePredicate**| |参数基本类型;
返回基本类型|**类型To类型Function**
`applyAs类型()`|**IntToLongFunction
IntToDoubleFunction
LongToIntFunction
LongToDoubleFunction
DoubleToIntFunction
DoubleToLongFunction**| -|2 参数类型不同|**Bi操作**
(不同方法名)|**`BiFunction`
`BiConsumer`
`BiPredicate`
`ToIntBiFunction`
`ToLongBiFunction`
`ToDoubleBiFunction`**| +|2 参数;
类型不同|**Bi操作**
(不同方法名)|**`BiFunction`
`BiConsumer`
`BiPredicate`
`ToIntBiFunction`
`ToLongBiFunction`
`ToDoubleBiFunction`**| 此表仅提供些常规方案。通过上表,你应该或多或少能自行推导出你所需要的函数式接口。 @@ -677,7 +677,7 @@ public class FunctionalAnnotation { 例如,为什么没有 `IntComparator`,`LongComparator` 和 `DoubleComparator` 呢?有 `BooleanSupplier` 却没有其他表示 **Boolean** 的接口;有通用的 `BiConsumer` 却没有用于 **int**,**long** 和 **double** 的 `BiConsumers` 变体(我理解他们为什么放弃这些接口)。这到底是疏忽还是有人认为其他组合使用得很少呢(他们是如何得出这个结论的)? -你还可以看到基本类型给 Java 添加了多少复杂性。基于效率方面的考虑(问题之后有所缓解),该语言的第一版中就包含了基本类型。现在,在语言的生命周期中,我们仍然会受到语言设计选择不佳的影响。 +你还可以看到基本类型给 Java 添加了多少复杂性。该语言的第一版中就包含了基本类型,原因是考虑效率问题(该问题很快就缓解了)。现在,在语言的生命周期里,我们一直忍受语言设计的糟糕选择所带来的影响。 下面枚举了基于 Lambda 表达式的所有不同 **Function** 变体的示例: @@ -747,9 +747,9 @@ public class FunctionVariants { } ``` -这些 Lambda 表达式尝试生成适合函数签名的最简代码。 在某些情况下,有必要进行强制类型转换,否则编译器会报截断错误。 +这些 Lambda 表达式尝试生成适合函数签名的最简代码。 在某些情况下有必要进行强制类型转换,否则编译器会报截断错误。 -主方法中的每个测试都显示了 `Function` 接口中不同类型的 `apply()` 方法。 每个都产生一个与其关联的 Lambda 表达式的调用。 +`main()`中的每个测试都显示了 `Function` 接口中不同类型的 `apply()` 方法。 每个都产生一个与其关联的 Lambda 表达式的调用。 方法引用有自己的小魔法: @@ -788,7 +788,7 @@ accept() someOtherName() ``` -查看 `BiConsumer` 的文档,你会看到 `accept()` 方法。 实际上,如果我们将方法命名为 `accept()`,它就可以作为方法引用。 但是我们也可用不同的名称,比如 `someOtherName()`。只要参数类型、返回类型与 `BiConsumer` 的 `accept()` 相同即可。 +查看 `BiConsumer` 的文档,你会看到它的函数式方法为 `accept()` 。 的确,如果我们将方法命名为 `accept()`,它就可以作为方法引用。 但是我们也可用不同的名称,比如 `someOtherName()`。只要参数类型、返回类型与 `BiConsumer` 的 `accept()` 相同即可。 因此,在使用函数接口时,名称无关紧要——只要参数类型和返回类型相同。 Java 会将你的方法映射到接口方法。 要调用方法,可以调用接口的函数式方法名(在本例中为 `accept()`),而不是你的方法名。 From 1b97c98586d7fd16f2541920910f12a81159614d Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 4 Dec 2020 18:09:14 +0800 Subject: [PATCH 22/68] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=2017?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/13-Functional-Programming.md | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/book/13-Functional-Programming.md b/docs/book/13-Functional-Programming.md index fc4a6818..3a44a81b 100644 --- a/docs/book/13-Functional-Programming.md +++ b/docs/book/13-Functional-Programming.md @@ -876,7 +876,7 @@ public class TriFunctionTest { ### 缺少基本类型的函数 -让我们重温一下 `BiConsumer`,看看我们如何创建缺少的针对 **int**,**long** 和 **double** 的各种排列: +让我们重温一下 `BiConsumer`,看看我们将如何创建各种缺失的预定义组合,涉及 **int**,**long** 和 **double** (基本类型): ```java // functional/BiConsumerPermutations.java @@ -908,7 +908,7 @@ public class BiConsumerPermutations { 这里使用 `System.out.format()` 来显示。它类似于 `System.out.println()` 但提供了更多的显示选项。 这里,`%f` 表示我将 `n` 作为浮点值给出,`%d` 表示 `n` 是一个整数值。 这其中可以包含空格,输入 `%n` 会换行 — 当然使用传统的 `\n` 也能换行,但 `%n` 是自动跨平台的,这是使用 `format()` 的另一个原因。 -上例简单使用了包装类型,装箱和拆箱负责它与基本类型之间的来回转换。 又比如,我们可以将包装类型和`Function`一起使用,而不去用各种针对基本类型的预定义接口。代码示例: +上例只是简单使用了合适的包装类型,而装箱和拆箱负责它与基本类型之间的来回转换。 又比如,我们可以将包装类型和`Function`一起使用,而不去用各种针对基本类型的预定义接口。代码示例: ```java // functional/FunctionWithWrapped.java @@ -932,7 +932,7 @@ public interface IntToDoubleFunction { } ``` -因为我们可以简单地写 `Function ` 并产生正常的结果,所以用基本类型的唯一原因是可以避免传递参数和返回结果过程中的自动装箱和自动拆箱,进而提升性能。 +因为我们可以简单地写 `Function ` 并产生正常的结果,所以用基本类型(`IntToDoubleFunction`)的唯一理由是可以避免传递参数和返回结果过程中的自动拆装箱,进而提升性能。 似乎是考虑到使用频率,某些函数类型并没有预定义。 @@ -1050,7 +1050,7 @@ O **闭包**(Closure)一词总结了这些问题。 它非常重要,利用闭包可以轻松生成函数。 -考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决,那问题将变得非常棘手。 能够解决这个问题的语言被称为**支持闭包**,或者叫作在词法上限定范围( 也使用术语*变量捕获* )。Java 8 提供了有限但合理的闭包支持,我们将用一些简单的例子来研究它。 +考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决,那问题将变得非常棘手。 能够解决这个问题的语言被称作 *支持闭包*,或者称作 *词法定界*(*lexically scoped* ,基于词法作用域的)( 也有用术语 *变量捕获* *variable capture* 称呼的)。Java 8 提供了有限但合理的闭包支持,我们将用一些简单的例子来研究它。 首先,下列方法返回一个函数,该函数访问对象字段和方法参数: @@ -1169,7 +1169,7 @@ public class Closure5 { **等同 final 效果**意味着可以在变量声明前加上 **final** 关键字而不用更改任何其余代码。 实际上它就是具备 `final` 效果的,只是没有明确说明。 -通过在闭包中使用 `final` 关键字提前修饰变量 `x` 和 `i` , 我们解决了 `Closure5.java` 中的问题。代码示例: +在闭包中,在使用 `x` 和 `i` 之前,通过将它们赋值给 `final` 修饰的变量,我们解决了 `Closure5.java` 中遇到的问题。代码示例: ```java @@ -1191,7 +1191,7 @@ public class Closure6 { 上例中 `iFinal` 和 `xFinal` 的值在赋值后并没有改变过,因此在这里使用 `final` 是多余的。 -如果函数式方法中使用的外部局部变量是引用,而不是基本类型的话,会是什么情况呢?我们可以把`int`类型改为`Integer`类型研究一下: +如果改用包装类型会是什么情况呢?我们可以把`int`类型改为`Integer`类型研究一下: ```java // functional/Closure7.java @@ -1208,7 +1208,7 @@ public class Closure7 { } ``` -编译器非常聪明地识别到变量 `i` 的值被更改过。 因为包装类型可能被特殊处理过了,所以我们尝试下 **List**: +编译器非常聪明地识别到变量 `i` 的值被更改过。 包装类型可能是被特殊处理了,我们再尝试下 **List**: ```java // functional/Closure8.java @@ -1250,7 +1250,7 @@ public class Closure8 { 请**注意**我已经声明 `ai` 是 `final` 的了。尽管在这个例子中你可以去掉 `final` 并得到相同的结果(试试吧!)。 应用于对象引用的 `final` 关键字仅表示不会重新赋值引用。 它并不代表你不能修改对象本身。 -下面我们来看看 `Closure7.java` 和 `Closure8.java` 之间的区别。我们看到:在 `Closure7.java` 中变量 `i` 有过重新赋值。 也许这就是触发**等同 final 效果**错误消息的原因。 +我们来看看 `Closure7.java` 和 `Closure8.java` 之间的区别。我们看到:在 `Closure7.java` 中变量 `i` 有过重新赋值。 也许这就是触发**等同 final 效果**错误消息的原因。 ```java // functional/Closure9.java @@ -1270,7 +1270,7 @@ public class Closure9 { 上例,重新赋值引用会触发错误消息。如果只修改指向的对象则没问题,只要没有其他人获得对该对象的引用(这意味着你有多个实体可以修改对象,此时事情会变得非常混乱),基本上就是安全的[^6]。 -让我们回顾一下 `Closure1.java`。那么现在问题来了:为什么变量 `i` 被修改编译器却没有报错呢。 它既不是 `final` 的,也不是**等同 final 效果**的。因为 `i` 是外围类的成员,所以这样做肯定是安全的(除非你正在创建共享可变内存的多个函数)。是的,你可以辩称在这种情况下不会发生变量捕获(Variable Capture)。但可以肯定的是,`Closure3.java` 的错误消息是专门针对局部变量的。因此,规则并非只是“在 Lambda 之外定义的任何变量必须是 `final` 的或**等同 final 效果**那么简单。相反,你必须考虑捕获的变量是否是**等同 final 效果**的。 如果它是对象中的字段,那么它拥有独立的生存周期,并且不需要任何特殊的捕获,以便稍后在调用 Lambda 时存在。 +让我们回顾一下 `Closure1.java`。那么现在问题来了:为什么变量 `i` 被修改编译器却没有报错呢。 它既不是 `final` 的,也不是**等同 final 效果**的。因为 `i` 是外部类的成员,所以这样做肯定是安全的(除非你正在创建共享可变内存的多个函数)。是的,你可以辩称在这种情况下不会发生变量捕获(Variable Capture)。但可以肯定的是,`Closure3.java` 的错误消息是专门针对局部变量的。因此,规则并非只是 “在 Lambda 之外定义的任何变量必须是 `final` 的或**等同 final 效果**” 那么简单。相反,你必须考虑捕获的变量是否是**等同 final 效果**的。 如果它是对象中的字段(实例变量),那么它有独立的生命周期,不需要任何特殊的捕获以便稍后在调用 Lambda 时存在。(注:结论是——Lambda 可以没有限制地引用 实例变量和静态变量。但 局部变量必须显式声明为final,或事实上是final 。) @@ -1302,15 +1302,15 @@ public class AnonymousClosure { ## 函数组合 -函数组合(Function Composition)意为“多个函数组合成新函数”。它通常是函数式编程的基本组成部分。在前面的 `TransformFunction.java` 类中,有一个使用 `andThen()` 的函数组合示例。一些 `java.util.function` 接口中包含支持函数组合的方法 [^7]。 +函数组合(Function Composition)意为“多个函数组合成新函数”。它通常是函数式编程的基本组成部分。在前面的 `TransformFunction.java` 类中,就有一个使用 `andThen()` 的函数组合示例。一些 `java.util.function` 接口中包含支持函数组合的方法 [^7]。 | 组合方法 | 支持接口 | | :----- | :----- | -| `andThen(argument)`
根据参数执行原始操作 | **Function
BiFunction
Consumer
BiConsumer
IntConsumer
LongConsumer
DoubleConsumer
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator
BinaryOperator** | -| `compose(argument)`
根据参数执行原始操作 | **Function
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator** | -| `and(argument)`
短路**逻辑与**原始谓词和参数谓词 | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | -| `or(argument)`
短路**逻辑或**原始谓词和参数谓词 | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | -| `negate()`
该谓词的**逻辑否**谓词| **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | +| `andThen(argument)`
执行原操作,再执行参数操作 | **Function
BiFunction
Consumer
BiConsumer
IntConsumer
LongConsumer
DoubleConsumer
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator
BinaryOperator** | +| `compose(argument)`
执行参数操作,再执行原操作 | **Function
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator** | +| `and(argument)`
原Predicate和参数Predicate的短路**逻辑与** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | +| `or(argument)`
原Predicate和参数Predicate的短路**逻辑或** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | +| `negate()`
原Predicate的**逻辑非**| **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | 下例使用了 `Function` 里的 `compose()`和 `andThen()`。代码示例: @@ -1376,9 +1376,9 @@ foobar foobaz ``` -`p4` 获取到了所有谓词并组合成一个更复杂的谓词。解读:如果字符串中不包含 `bar` 且长度小于 5,或者它包含 `foo` ,则结果为 `true`。 +`p4` 获取到了所有`Predicate`并组合成一个更复杂的`Predicate`。解读:如果字符串中不包含 `bar` 且长度小于 5,或者它包含 `foo` ,则结果为 `true`。 -正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建了一个字符串对象的流,然后将每个对象传递给 `filter()` 操作。 `filter()` 使用 `p4` 的谓词来确定对象的去留。最后我们使用 `forEach()` 将 `println` 方法引用应用在每个留存的对象上。 +正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建了一个字符串对象的流,然后将每个对象传递给 `filter()` 操作。 `filter()` 使用 `p4` 的`Predicate`来确定对象的去留。最后我们使用 `forEach()` 将 `println` 方法引用应用在每个留存的对象上。 从输出结果我们可以看到 `p4` 的工作流程:任何带有 `"foo"` 的字符串都得以保留,即使它的长度大于 5。 `"fongopuckey"` 因长度超出且不包含 `foo` 而被丢弃。 From 952b2fff4321973176c31dbfa07f1e5a4ee6f631 Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Sun, 6 Dec 2020 13:35:27 +0800 Subject: [PATCH 23/68] =?UTF-8?q?=E5=8D=81=E4=B8=89=E7=AB=A0=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=AF=AD=E5=8F=A5=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/13-Functional-Programming.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/book/13-Functional-Programming.md b/docs/book/13-Functional-Programming.md index 3a44a81b..9cef7164 100644 --- a/docs/book/13-Functional-Programming.md +++ b/docs/book/13-Functional-Programming.md @@ -646,9 +646,9 @@ public class FunctionalAnnotation { 3. 如果返回值为基本类型,则用 `To` 表示,如 `ToLongFunction ` 和 `IntToLongFunction`。 -4. 如果返回值类型与参数类型一致,则是一个 `Operator` :单个参数使用 `UnaryOperator`,两个参数使用 `BinaryOperator`。 +4. 如果返回值类型与参数类型相同,则是一个 `Operator` :单个参数使用 `UnaryOperator`,两个参数使用 `BinaryOperator`。 -5. 如果接收两个参数且返回值为布尔值,则是一个 `Predicate`。 +5. 如果接收参数并返回一个布尔值,则是一个 **谓词** (`Predicate`)。 6. 如果接收的两个参数类型不同,则名称中有一个 `Bi`。 @@ -1308,9 +1308,9 @@ public class AnonymousClosure { | :----- | :----- | | `andThen(argument)`
执行原操作,再执行参数操作 | **Function
BiFunction
Consumer
BiConsumer
IntConsumer
LongConsumer
DoubleConsumer
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator
BinaryOperator** | | `compose(argument)`
执行参数操作,再执行原操作 | **Function
UnaryOperator
IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator** | -| `and(argument)`
原Predicate和参数Predicate的短路**逻辑与** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | -| `or(argument)`
原Predicate和参数Predicate的短路**逻辑或** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | -| `negate()`
原Predicate的**逻辑非**| **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | +| `and(argument)`
原谓词(Predicate)和参数谓词的短路**逻辑与** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | +| `or(argument)`
原谓词和参数谓词的短路**逻辑或** | **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | +| `negate()`
该谓词的**逻辑非**| **Predicate
BiPredicate
IntPredicate
LongPredicate
DoublePredicate** | 下例使用了 `Function` 里的 `compose()`和 `andThen()`。代码示例: @@ -1347,7 +1347,7 @@ _fter _ll _mbul_nces 当 `f1` 获得字符串时,它已经被`f2` 剥离了前三个字符。这是因为 `compose(f2)` 表示 `f2` 的调用发生在 `f1` 之前。 -下例是 `Predicate` 的逻辑运算演示.代码示例: +下例是 谓词(`Predicate`) 的逻辑运算演示.代码示例: ```java // functional/PredicateComposition.java @@ -1376,9 +1376,9 @@ foobar foobaz ``` -`p4` 获取到了所有`Predicate`并组合成一个更复杂的`Predicate`。解读:如果字符串中不包含 `bar` 且长度小于 5,或者它包含 `foo` ,则结果为 `true`。 +`p4` 获取到了所有谓词(`Predicate`)并组合成一个更复杂的谓词。解读:如果字符串中不包含 `bar` 且长度小于 5,或者它包含 `foo` ,则结果为 `true`。 -正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建了一个字符串对象的流,然后将每个对象传递给 `filter()` 操作。 `filter()` 使用 `p4` 的`Predicate`来确定对象的去留。最后我们使用 `forEach()` 将 `println` 方法引用应用在每个留存的对象上。 +正因它产生如此清晰的语法,我在主方法中采用了一些小技巧,并借用了下一章的内容。首先,我创建了一个字符串对象的流,然后将每个对象传递给 `filter()` 操作。 `filter()` 使用 `p4` 的谓词来确定对象的去留。最后我们使用 `forEach()` 将 `println` 方法引用应用在每个留存的对象上。 从输出结果我们可以看到 `p4` 的工作流程:任何带有 `"foo"` 的字符串都得以保留,即使它的长度大于 5。 `"fongopuckey"` 因长度超出且不包含 `foo` 而被丢弃。 From 0ee5123b26b2dd0e4bb232af80312f86b83cd40b Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 8 Dec 2020 18:17:17 +0800 Subject: [PATCH 24/68] =?UTF-8?q?13-14=20=E4=BF=AE=E6=94=B9=E8=AF=AD?= =?UTF-8?q?=E5=8F=A5=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=206?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/14-Streams.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md index 253968be..bf370eef 100644 --- a/docs/book/14-Streams.md +++ b/docs/book/14-Streams.md @@ -840,15 +840,15 @@ public class Prime { ### 应用函数到元素 -- `map(Function)`:将函数操作应用在输入流的元素中,并将返回值传递到输出流中。 +- `map(Function)`:将函数`Function`应用在输入流的每一个元素上,并将所有结果值作为输出流。 -- `mapToInt(ToIntFunction)`:操作同上,但结果是 **IntStream**。 +- `mapToInt(ToIntFunction)`:操作同上,但所有结果作为 **IntStream**。 -- `mapToLong(ToLongFunction)`:操作同上,但结果是 **LongStream**。 +- `mapToLong(ToLongFunction)`:操作同上,但所有结果作为 **LongStream**。 -- `mapToDouble(ToDoubleFunction)`:操作同上,但结果是 **DoubleStream**。 +- `mapToDouble(ToDoubleFunction)`:操作同上,但所有结果作为 **DoubleStream**。 -在这里,我们使用 `map()` 映射多种函数到一个字符串流中。代码示例: +在这里,我们使用 `map()` 映射几种不同的函数到一个字符串流中。代码示例: ```java // streams/FunctionMap.java @@ -911,9 +911,9 @@ class FunctionMap { ``` -在上面的自增示例中,我们用 `Integer.parseInt()` 尝试将一个字符串转化为整数。如果字符串不能被转化成为整数就会抛出 `NumberFormatException` 异常,此时我们就回过头来把原始字符串放到输出流中。 +在上面的`Increment`示例中,我们用 `Integer.parseInt()` 尝试将一个字符串转化为整数。如果字符串不能被转化成为整数就会抛出 `NumberFormatException` 异常,此时我们就把原始字符串放回输出流(fallback机制)。 -在以上例子中,`map()` 将一个字符串映射为另一个字符串,但是我们完全可以产生和接收类型完全不同的类型,从而改变流的数据类型。下面代码示例: +在以上例子中,`map()` 将一个字符串映射为另一个字符串,但是我们完全可以产出和入参不同的类型,从而改变流的数据类型。下面代码示例: ```java // streams/FunctionMap2.java @@ -952,7 +952,7 @@ Numbered(13) 我们将获取到的整数通过构造器 `Numbered::new` 转化成为 `Numbered` 类型。 -如果使用 **Function** 返回的结果是数值类型的一种,我们必须使用合适的 `mapTo数值类型` 进行替代。代码示例: +如果使用 **Function** 返回的结果是数值类型的一种,我们必须用合适的 "`mapTo`操作" 替代。代码示例: ```java // streams/FunctionMap3.java @@ -984,11 +984,11 @@ class FunctionMap3 { 17.000000 1.900000 0.230000 ``` -遗憾的是,Java 设计者并没有尽最大努力去消除基本类型。 +遗憾的是,Java 设计者并没有尽一点努力去消除基本类型。 ### 在 `map()` 中组合流 -假设我们现在有了一个传入的元素流,并且打算对流元素使用 `map()` 函数。现在你已经找到了一些可爱并独一无二的函数功能,但是问题来了:这个函数功能是产生一个流。我们想要产生一个元素流,而实际却产生了一个元素流的流。 +假设我们现在有了一个传入的元素流,并且打算对流元素使用 `map()` 函数。现在你已经给`map()` 函数找到了一些可爱并独一无二的功能,但是问题来了:这个函数功能是产生一个流。我们想要产生一个元素流,而实际却产生了一个元素流的流。 `flatMap()` 做了两件事:将产生流的函数应用在每个元素上(与 `map()` 所做的相同),然后将每个流都扁平化为元素,因而最终产生的仅仅是元素。 From c71b518bcc5ff105c91385ba7000ab81dc399283 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Wed, 9 Dec 2020 11:02:09 +0800 Subject: [PATCH 25/68] =?UTF-8?q?14=20=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=207?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/14-Streams.md | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md index bf370eef..838edf2b 100644 --- a/docs/book/14-Streams.md +++ b/docs/book/14-Streams.md @@ -988,19 +988,19 @@ class FunctionMap3 { ### 在 `map()` 中组合流 -假设我们现在有了一个传入的元素流,并且打算对流元素使用 `map()` 函数。现在你已经给`map()` 函数找到了一些可爱并独一无二的功能,但是问题来了:这个函数功能是产生一个流。我们想要产生一个元素流,而实际却产生了一个元素流的流。 +假设我们有一个输入的元素流,并且打算对这些元素使用 `map()` 函数。现在你已经给`map()` 找了一些可爱并独一无二的功能,但是问题来了:这些功能会产生一个流。此时其实我们只想要一个元素输出流,却输出了一个包含着几组元素流的输出流。 -`flatMap()` 做了两件事:将产生流的函数应用在每个元素上(与 `map()` 所做的相同),然后将每个流都扁平化为元素,因而最终产生的仅仅是元素。 +`flatMap()` 做了两件事:1.将产生流的函数应用在每个元素上(这点与 `map()` 所做的相同);2.将每个流都"扁平化"为元素,因而最终产生的只有元素。 -`flatMap(Function)`:当 `Function` 产生流时使用。 +`flatMap(Function)`:当 `Function` 产出流时使用。 -`flatMapToInt(Function)`:当 `Function` 产生 `IntStream` 时使用。 +`flatMapToInt(Function)`:当 `Function` 产出 `IntStream` 时使用。 -`flatMapToLong(Function)`:当 `Function` 产生 `LongStream` 时使用。 +`flatMapToLong(Function)`:当 `Function` 产出 `LongStream` 时使用。 -`flatMapToDouble(Function)`:当 `Function` 产生 `DoubleStream` 时使用。 +`flatMapToDouble(Function)`:当 `Function` 产出 `DoubleStream` 时使用。 -为了弄清它的工作原理,我们从传入一个刻意设计的函数给 `map()` 开始。该函数接受一个整数并产生一个字符串流: +为了弄清它的工作原理,我们从传入一个刻意设计的函数给 `map()` 开始。该函数接受一个整数并产出一个字符串流: ```java // streams/StreamOfStreams.java @@ -1023,7 +1023,7 @@ java.util.stream.ReferencePipeline$Head java.util.stream.ReferencePipeline$Head ``` -我们天真地希望能够得到字符串流,但实际得到的却是“Head”流的流。我们可以使用 `flatMap()` 解决这个问题: +我们天真地希望能够得到一个字符串流,但实际得到的却是一个囊括着“Head”流的流。我们可以使用 `flatMap()` 轻易解决这个问题: ```java // streams/FlatMap.java @@ -1051,7 +1051,7 @@ Fozzie Beaker ``` -从映射返回的每个流都会自动扁平为组成它的字符串。 +从映射(`Mapping`)之后返回的每个流都会自动扁平化,作为最后输出字符串流的一个组件。 下面是另一个演示,我们从一个整数流开始,然后使用每一个整数去创建更多的随机数。 @@ -1076,9 +1076,9 @@ public class StreamOfRandoms { 58 -1 55 93 -1 61 61 29 -1 68 0 22 7 -1 88 28 51 89 9 -1 ``` -在这里我们引入了 `concat()`,它以参数顺序组合两个流。 如此,我们在每个随机 `Integer` 流的末尾添加一个 -1 作为标记。你可以看到最终流确实是从一组扁平流中创建的。 +在这里我们引入了 `concat()`,它以参数顺序合并两个流。 这样做,就能在每个随机 `Integer` 流的末尾添加一个 -1 作为标记。可以看到,最终的流确实是从一组流扁平化得来的。 -因为 `rand.ints()` 产生的是一个 `IntStream`,所以我必须使用 `flatMap()`、`concat()` 和 `of()` 的特定整数形式。 +因为 `rand.ints()` 产生的是一个 `IntStream`,所以我必须使用 `flatMap()`、`concat()` 和 `of()` 的特定整数形式(`IntStream,ToInt`)。 让我们再看一下将文件划分为单词流的任务。我们最后使用到的是 **FileToWordsRegexp.java**,它的问题是需要将整个文件读入行列表中 —— 显然需要存储该列表。而我们真正想要的是创建一个不需要中间存储层的单词流。 @@ -1101,15 +1101,15 @@ public class FileToWords { `stream()` 现在是一个静态方法,因为它可以自己完成整个流创建过程。 -注意:`\\W+` 是一个正则表达式。表示“非单词字符”,`+` 表示“可以出现一次或者多次”。小写形式的 `\\w` 表示“单词字符”。 +注意:`\\W+` 是一个正则表达式。表示“非单词字符”(它等价于" `[^a-zA-Z0-9_]` "),`+` 表示“可以出现一次或者多次”。小写形式的 `\\w` 表示“单词字符” (它等价于" `[A-Za-z0-9_]` ")。 -我们之前遇到的问题是 `Pattern.compile().splitAsStream()` 产生的结果为流,这意味着当我们只是想要一个简单的单词流时,在传入的行流(stream of lines)上调用 `map()` 会产生一个单词流的流。幸运的是,`flatMap()` 可以将元素流的流扁平化为一个简单的元素流。或者,我们可以使用 `String.split()` 生成一个数组,其可以被 `Arrays.stream()` 转化成为流: +我们之前遇到的问题是 `Pattern.compile().splitAsStream()` 产生的是一个流,这意味着当我们只是想要一个简单的单词流时,对输入流调用 `map()` 会产生一个囊括单词流的流。幸运的是,`flatMap()` 可以将囊括元素流的流扁平化为一个简单的元素流。或者,我们还可以用 `String.split()` 生成一个数组,数组又会被 `Arrays.stream()` 转化成为流: ```java .flatMap(line -> Arrays.stream(line.split("\\W+")))) ``` -因为有了真正的流(而不是`FileToWordsRegexp.java` 中基于集合存储的流),所以每次需要一个新的流时,我们都必须从头开始创建,因为流不能被复用: +因为有了真正的流(而不是`FileToWordsRegexp.java` 中基于集合存储的流),所以每次需要一个新的流时都必须从头开始创建,因为流不能被复用: ```java // streams/FileToWordsTest.java @@ -1140,7 +1140,7 @@ is it ## Optional类 -在我们学习终端操作(Terminal Operations)之前,我们必须考虑在一个空流中获取元素会发生什么。我们喜欢沿着“快乐路径”[^1]把流连接起来,同时假设流不会中断。然而,在流中放置 `null` 却会轻易令其中断。那么是否存在某种对象,可以在持有流元素的同时,即使在我们查找的元素不存在时,也能友好地对我们进行提示(也就是说,不会产生异常)? +在我们学习终端操作(Terminal Operations)之前,我们必须考虑在一个没有任何元素的、空的流中获取元素会发生什么。我们喜欢沿着“快乐路径”[^1]把流连接起来,同时认为流不会中断。然而,在流中放置 `null` 却会轻易令其中断。那么是否存在某种对象,可以在持有流元素的同时,即使在我们查找的元素不存在时,也能友好地对我们进行提示(也就是说,不会产生异常)? **Optional** 可以实现这样的功能。一些标准流操作返回 **Optional** 对象,因为它们并不能保证预期结果一定存在。包括: @@ -1148,9 +1148,9 @@ is it - `findAny()` 返回包含任意元素的 **Optional** 对象,如果流为空则返回 **Optional.empty** - `max()` 和 `min()` 返回一个包含最大值或者最小值的 **Optional** 对象,如果流为空则返回 **Optional.empty** - `reduce()` 不再以 `identity` 形式开头,而是将其返回值包装在 **Optional** 中。(`identity` 对象成为其他形式的 `reduce()` 的默认结果,因此不存在空结果的风险) +- `reduce()` 中不以 “标识”对象( “identity” object )开头的,将它的返回值包装在 **Optional** 中。(“标识”对象成为了其它版本 `reduce()` 的默认结果,因此不存在空的风险) -对于数字流 **IntStream**、**LongStream** 和 **DoubleStream**,`average()` 会将结果包装在 **Optional** 以防止流为空。 +- 对于数字流 **IntStream**、**LongStream** 和 **DoubleStream**,`average()` 会将结果包装到 **Optional** ,防止流为空。 以下是对空流进行所有这些操作的简单测试: @@ -1189,7 +1189,7 @@ OptionalDouble.empty 当流为空的时候你会获得一个 **Optional.empty** 对象,而不是抛出异常。**Optional** 拥有 `toString()` 方法可以用于展示有用信息。 -注意,空流是通过 `Stream.empty()` 创建的。如果你在没有任何上下文环境的情况下调用 `Stream.empty()`,Java 并不知道它的数据类型;这个语法解决了这个问题。如果编译器拥有了足够的上下文信息,比如: +注意,如果你在没有任何上下文环境的情况下调用 `Stream.empty()`,Java 并不知道它的数据类型;空流通过 `Stream.empty()` 这个语法创建,解决了这个问题。如果编译器拥有了足够的上下文信息,比如: ```java Stream s = Stream.empty(); @@ -1197,7 +1197,7 @@ Stream s = Stream.empty(); 就可以在调用 `empty()` 时推断类型。 -这个示例展示了 **Optional** 的两个基本用法: +这个示例展示了 **Optional** 的两个基本用法(`isPresent() get()`): ```java // streams/OptionalBasics.java @@ -1232,12 +1232,12 @@ Nothing inside! 有许多便利函数可以解包 **Optional** ,这简化了上述“对所包含的对象的检查和执行操作”的过程: -- `ifPresent(Consumer)`:当值存在时调用 **Consumer**,否则什么也不做。 -- `orElse(otherObject)`:如果值存在则直接返回,否则生成 **otherObject**。 -- `orElseGet(Supplier)`:如果值存在则直接返回,否则使用 **Supplier** 函数生成一个可替代对象。 -- `orElseThrow(Supplier)`:如果值存在直接返回,否则使用 **Supplier** 函数生成一个异常。 +- `ifPresent(Consumer)`:若值存在则调用 **Consumer**,否则什么也不做。 +- `orElse(otherObject)`:若值存在则直接返回,否则生成 **otherObject**。 +- `orElseGet(Supplier)`:若值存在则直接返回,否则通过使用 **Supplier** 函数生成一个替代对象。 +- `orElseThrow(Supplier)`:若值存在则直接返回,否则通过使用 **Supplier** 函数生成一个异常。 -如下是针对不同便利函数的简单演示: +如下是不同便利函数的简单演示: ```java // streams/Optionals.java @@ -1303,7 +1303,7 @@ Epithets Caught java.lang.Exception: Supplied ``` -`test()` 通过传入所有方法都适用的 **Consumer** 来避免重复代码。 +`test()` 通过传入所有方法都适用的 **Consumer** 来避免代码重复。 `orElseThrow()` 通过 **catch** 关键字来捕获抛出的异常。更多细节,将在 [异常](./15-Exceptions.md) 这一章节中学习。 @@ -2146,7 +2146,7 @@ IntSummaryStatistics{count=100, sum=50794, min=8, average=507.940000, max=998} 流式操作改变并极大地提升了 Java 语言的可编程性,并可能极大地阻止了 Java 编程人员向诸如 Scala 这种函数式语言的流转。在本书的剩余部分,我们将尽可能地使用流。 -[^1]: 在软件或信息建模的上下文中,快乐路径(有时称为快乐流)是没有异常或错误条件的默认场景。例如,验证信用卡号的函数的快乐路径应该是任何验证规则都不会出现错误的地方,从而让执行成功地继续到最后,生成一个积极的响应。[见 wikipedia: happy path](https://en.wikipedia.org/wiki/Happy_path) +[^1]: 在软件或信息建模的上下文中,快乐路径(有时称为快乐流)是指没有异常或错误情形导致退出的默认场景。例如,验证信用卡号的函数的快乐路径应该是任何验证规则都不会出现错误而中断,从而让执行成功地延续到最后,生成一个积极的响应让使用者快乐。[见 wikipedia: happy path](https://en.wikipedia.org/wiki/Happy_path) From e4f4af78c584f90077bc3933569ab8ee464c3984 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Wed, 9 Dec 2020 17:54:03 +0800 Subject: [PATCH 26/68] =?UTF-8?q?14=20=E4=BF=AE=E6=94=B9=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E6=8B=97=E5=8F=A3=E9=97=AE=E9=A2=98=20end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/14-Streams.md | 56 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md index 838edf2b..ec88dddc 100644 --- a/docs/book/14-Streams.md +++ b/docs/book/14-Streams.md @@ -1148,7 +1148,7 @@ is it - `findAny()` 返回包含任意元素的 **Optional** 对象,如果流为空则返回 **Optional.empty** - `max()` 和 `min()` 返回一个包含最大值或者最小值的 **Optional** 对象,如果流为空则返回 **Optional.empty** -- `reduce()` 中不以 “标识”对象( “identity” object )开头的,将它的返回值包装在 **Optional** 中。(“标识”对象成为了其它版本 `reduce()` 的默认结果,因此不存在空的风险) +- `reduce()` 几个重载方法中, 没有`identity`参数(该参数充当初始值)的那个方法,其返回值包装在 **Optional** 中。(其它重载 `reduce()` 有初始值作为默认的结果,因此不存在空的风险) - 对于数字流 **IntStream**、**LongStream** 和 **DoubleStream**,`average()` 会将结果包装到 **Optional** ,防止流为空。 @@ -1363,13 +1363,13 @@ Null 当我们的流管道生成了 **Optional** 对象,下面 3 个方法可使得 **Optional** 的后续能做更多的操作: -- `filter(Predicate)`:对 **Optional** 中的内容应用**Predicate** 并将结果返回。如果 **Optional** 不满足 **Predicate** ,将 **Optional** 转化为空 **Optional** 。如果 **Optional** 已经为空,则直接返回空**Optional** 。 +- `filter(Predicate)`:对 **Optional** 对象中的内容应用 **Predicate** 并将结果返回。如果 **Optional** 不满足 **Predicate** ,将 **Optional** 转化为 **Optional.empty** 。如果 **Optional** 已经为空,则直接返回 **Optional.empty** 。 -- `map(Function)`:如果 **Optional** 不为空,应用 **Function** 于 **Optional** 中的内容,并返回结果。否则直接返回 **Optional.empty**。 +- `map(Function)`:如果 **Optional** 不为空,对 **Optional** 中的内容应用 **Function** 并返回结果。否则直接返回 **Optional.empty**。 -- `flatMap(Function)`:同 `map()`,但是提供的映射函数将结果包装在 **Optional** 对象中,因此 `flatMap()` 不会在最后进行任何包装。 +- `flatMap(Function)`:同 `map()`,但提供的映射函数`Function`将结果包装在 **Optional** 对象中,因此 `flatMap()` 不会在最后进行任何包装。 -以上方法都不适用于数值型 **Optional**。一般来说,流的 `filter()` 会在 **Predicate** 返回 `false` 时移除流元素。而 `Optional.filter()` 在失败时不会删除 **Optional**,而是将其保留下来,并转化为空。下面请看代码示例: +以上方法都不适用于数值型 **Optional**。一般来说,在 **Predicate** 返回 `false` 时,流的 `filter()` 会移除流元素;而 `Optional.filter()` 不会删除 **Optional**,而是将其保留下来,并转化为 **Optional.empty** 。下面请看代码示例: ```java @@ -1445,9 +1445,9 @@ Optional[Bingo] Optional.empty ``` -即使输出看起来像流,要特别注意 `test()` 中的 for 循环。每一次的for循环都重新启动流,然后跳过for循环索引指定的数量的元素,这就是流只剩后续元素的原因。然后调用`findFirst()` 获取剩余元素中的第一个元素,并包装在一个 `Optional`对象中。 +尽管打印输出看起来像流,要特别注意这里 `test()` 用的是 for 循环。每一次的for循环都重新启动流,跳过for循环索引设置的数目,这就是打印的“流”的元素看起来连续的原因。之后调用`findFirst()` 获取剩余元素中的第一个元素,并包装在一个 `Optional`对象中。 -**注意**,不同于普通 for 循环,这里的索引值范围并不是 `i < elements.length`, 而是 `i <= elements.length`。所以最后一个元素实际上超出了流。方便的是,这将自动成为 **Optional.empty**,你可以在每一个测试的结尾中看到。 +**注意**,不同于普通 for 循环,这里的索引值范围并不是 `i < elements.length`, 而是 `i <= elements.length`。所以最后一个元素实际上超出了流。很方便的是,这将自动成为 **Optional.empty**,因此你可以在每个`test()`结尾中看到。 同 `map()` 一样 , `Optional.map()` 执行一个函数。它仅在 **Optional** 不为空时才执行这个映射函数。并将 **Optional** 的内容提取出来,传递给映射函数。代码示例: @@ -1525,9 +1525,9 @@ Optional[5] Optional.empty ``` -映射函数的返回结果会自动包装成为 **Optional**。**Optional.empty** 会被直接跳过。 +映射函数的返回结果会自动包装成为 **Optional**。**Optional.empty** 会被直接略过。 -**Optional** 的 `flatMap()` 应用于已生成 **Optional** 的映射函数,所以 `flatMap()` 不会像 `map()` 那样将结果封装在 **Optional** 中。代码示例: +**Optional** 的 `flatMap()` 应用在已生成 **Optional** 的映射函数,所以 `flatMap()` 不会像 `map()` 那样将结果封装到 **Optional** 。代码示例: ```java // streams/OptionalFlatMap.java @@ -1605,7 +1605,7 @@ Optional[5] Optional.empty ``` -同 `map()`,`flatMap()` 将提取非空 **Optional** 的内容并将其应用在映射函数。唯一的区别就是 `flatMap()` 不会把结果包装在 **Optional** 中,因为映射函数已经被包装过了。在如上示例中,我们已经在每一个映射函数中显式地完成了包装,但是很显然 `Optional.flatMap()` 是为那些自己已经生成 **Optional** 的函数而设计的。 +同 `map()`,`flatMap()` 将提取非空 **Optional** 的内容并将其应用在映射函数。唯一的区别就是 `flatMap()` 不会把结果包装到 **Optional** ,因为映射函数已经被包装过了。在如上示例中,我们已经在每一个映射函数中显式地完成了包装,很明显 `Optional.flatMap()` 是为那些自己已经生成 **Optional** 的函数而设计的。 ### Optional 流 @@ -1681,20 +1681,20 @@ Signal(dash) Signal(dash) ``` -在这里,我们使用 `filter()` 来保留那些非空 **Optional**,然后在 `map()` 中使用 `get()` 获取元素。由于每种情况都需要定义“空值”的含义,所以通常我们要为每个应用程序采用不同的方法。 +在这里,我们使用 `filter()` 来保留那些非空 **Optional**,然后在 `map()` 中使用 `get()` 获取元素。由于每一种情况都需要你决定“空值”的含义,所以通常要为每个应用程序采用不同的方法。 ## 终端操作 -以下操作将会获取流的最终结果。至此我们无法再继续往后传递流。可以说,终端操作(Terminal Operations)总是我们在流管道中所做的最后一件事。 +这种操作将会获取流并产生最终结果,不再继续往后传递任何东西。可以说,终端操作(Terminal Operations)总是我们在整条管线所做的最后一件事。 ### 数组 - `toArray()`:将流转换成适当类型的数组。 -- `toArray(generator)`:在特殊情况下,生成自定义类型的数组。 +- `toArray(generator)`:在特殊情况下,生成自定义类型的数组(generator分配数组存储)。 当我们需要得到数组类型的数据以便于后续操作时,上面的方法就很有用。假设我们需要复用流产生的随机数时,就可以这么使用。代码示例: @@ -1755,7 +1755,7 @@ public class ForEach { 258 555 693 861 961 429 868 200 522 207 288 128 551 589 ``` -为了方便测试不同大小的流,我们抽离出了 `SZ` 变量。然而即使 `SZ` 值为14也产生了有趣的结果。在第一个流中,未使用 `parallel()` ,因此以元素从 `rands()`出来的顺序输出结果。在第二个流中,引入`parallel()` ,即便流很小,输出的结果的顺序也和前面不一样。这是由于多处理器并行操作的原因,如果你将程序多运行几次,你会发现输出都不相同,这是多处理器并行操作的不确定性造成的结果。 +为了方便测试不同大小的流,我们抽离出了 `SZ` 变量。可即使 `SZ` 赋值14也产生了有趣的结果。在第一个流中,未使用 `parallel()` ,因此以元素从 `rands()`出来的顺序输出结果。在第二个流中,引入`parallel()` ,即便流很小,输出的结果的顺序也和前面不一样。这是由于多处理器并行操作的原因,如果你将程序多运行几次,你会发现输出都不相同,这是多处理器并行操作的不确定性造成的结果。 在最后一个流中,同时使用了 `parallel()` 和 `forEachOrdered()` 来强制保持原始流顺序。因此,对非并行流使用 `forEachOrdered()` 是没有任何影响的。 @@ -1764,7 +1764,7 @@ public class ForEach { ### 集合 - `collect(Collector)`:使用 **Collector** 收集流元素到结果集合中。 -- `collect(Supplier, BiConsumer, BiConsumer)`:同上,第一个参数 **Supplier** 创建了一个新的结果集合,第二个参数 **BiConsumer** 将下一个元素收集到结果集合中,第三个参数 **BiConsumer** 用于将两个结果集合合并起来。 +- `collect(Supplier, BiConsumer, BiConsumer)`:同上,但第一个参数 **Supplier** 创建了一个新的结果集合,第二个参数 **BiConsumer** 将下一个元素收集到结果集合中,第三个参数 **BiConsumer** 用于合并两个结果集合。 在这里我们只是简单介绍了几个 **Collectors** 的运用示例。实际上,它还有一些非常复杂的操作实现,可通过查看 `java.util.stream.Collectors` 的 API 文档了解。例如,我们可以将元素收集到任意一种特定的集合中。 @@ -1854,11 +1854,11 @@ public class MapCollector { {688=W, 309=C, 293=B, 761=N, 858=N, 668=G, 622=F, 751=N} ``` -**Pair** 只是一个基础的数据对象。**RandomPair** 创建了随机生成的 **Pair** 对象流。在 Java 中,我们不能直接以某种方式组合两个流。所以我创建了一个整数流,并且使用 `mapToObj()` 将整数流转化成为 **Pair** 流。 **capChars**的随机大写字母迭代器创建了流,然后`next()`让我们可以在`stream()`中使用这个流。就我所知,这是将多个流组合成新的对象流的唯一方法。 +**Pair** 只是一个基础的数据对象。**RandomPair** 创建了随机生成的 **Pair** 对象流。在 Java 中,我们不能直接以某种方式组合两个流。所以我创建了一个整数流,并且使用 `mapToObj()` 将整数流转化成为 **Pair** 流。 **capChars**的随机大写字母迭代器创建了流,然后`next()`让我们可以在`stream()`中使用这个流。就我所知,这是将多个流(这里是随机整数流和随机字母流)组合成新的对象流的唯一方法。 在这里,我们只使用最简单形式的 `Collectors.toMap()`,这个方法只需要两个从流中获取键和值的函数。还有其他重载形式,其中一种当是键发生冲突时,使用一个函数来处理冲突。 -大多数情况下,`java.util.stream.Collectors` 中预设的 **Collector** 就能满足我们的要求。除此之外,你还可以使用第二种形式的 `collect()`。 我把它留作更高级的练习,下例给出基本用法: +大多数情况下,`java.util.stream.Collectors` 中预设的 **Collector** 就能满足我们的要求。除此之外,你还可以使用第二种形式的 `collect()`。 我把它留作更高级的练习,下例给出基本概念: ```java // streams/SpecialCollector.java @@ -1942,11 +1942,11 @@ Frobnitz(7) Frobnitz(29) ``` -**Frobnitz** 包含一个可生成自身的生成器 `supply()` ;因为 `supply()` 方法作为一个 `Supplier` 是签名兼容的,我们可以把 `supply()` 作为一个方法引用传递给 `Stream.generate()` (这种签名兼容性被称作结构一致性)。我们使用了没有“初始值”作为第一个参数的 `reduce()`方法,所以产生的结果是 **Optional** 类型。`Optional.ifPresent()` 方法只有在结果非空的时候才会调用 `Consumer` (`println` 方法可以被调用是因为 **Frobnitz** 可以通过 `toString()` 方法转换成 **String**)。 +**Frobnitz** 包含一个可生成自身的生成器 `supply()` ;因为 `supply()` 方法作为一个 `Supplier` 是签名兼容的,所以我们可以把 `supply()` 作为一个方法引用传递给 `Stream.generate()` (这种签名兼容性被称作结构一致性)。我们使用了没有“初始值”作为第一个参数的 `reduce()`方法,所以产生的结果是 **Optional** 类型。`Optional.ifPresent()` 方法只有在结果非空的时候才会调用 `Consumer` (`println` 方法可以被调用是因为 **Frobnitz** 可以通过 `toString()` 方法转换成 **String**)。 Lambda 表达式中的第一个参数 `fr0` 是 `reduce()` 中上一次调用的结果。而第二个参数 `fr1` 是从流传递过来的值。 -`reduce()` 中的 Lambda 表达式使用了三元表达式来获取结果,当 `fr0` 的 `size` 值小于 50 的时候,将 `fr0` 作为结果,否则将序列中的下一个元素即 `fr1`作为结果。当取得第一个 `size` 值小于 50 的 `Frobnitz`,只要得到这个结果就会忽略流中其他元素。这是个非常奇怪的限制, 但也确实让我们对 `reduce()` 有了更多的了解。 +`reduce()` 中的 Lambda 表达式使用了三元表达式来获取结果,当 `fr0` 的 `size` 值小于 50 的时候,将 `fr0` 作为结果,否则将序列中的下一个元素即 `fr1`作为结果。当取得第一个 `size` 值小于 50 的 `Frobnitz`,只要得到这个结果就会忽略流中其他元素。这是个非常奇怪的限制, 但也令我们对 `reduce()` 有更多认识。 ### 匹配 @@ -1955,7 +1955,7 @@ Lambda 表达式中的第一个参数 `fr0` 是 `reduce()` 中上一次调用的 - `anyMatch(Predicate)`:如果流的任意一个元素提供给 **Predicate** 返回 true ,结果返回为 true。在第一个 true 是停止执行计算。 - `noneMatch(Predicate)`:如果流的每个元素提供给 **Predicate** 都返回 false 时,结果返回为 true。在第一个 true 时停止执行计算。 -我们已经在 `Prime.java` 中看到了 `noneMatch()` 的示例;`allMatch()` 和 `anyMatch()` 的用法基本上是等同的。下面我们来探究一下短路行为。为了消除冗余代码,我们创建了 `show()`。首先我们必须知道如何统一地描述这三个匹配器的操作,然后再将其转换为 **Matcher** 接口。代码示例: +我们已经在 `Prime.java` 中看到了 `noneMatch()` 的示例;`allMatch()` 和 `anyMatch()` 的用法基本上是等同的。下面我们来探究一下短路行为。为了消除冗余代码,我们创建了 `show()`。首先我们必须知道如何统一描述上述的这3个匹配器的操作,然后把这描述的概念创建为 **Matcher** 接口。代码示例: ```java // streams/Matching.java @@ -1999,7 +1999,7 @@ public class Matching { **BiPredicate** 是一个二元谓词,它接受两个参数并返回 true 或者 false。第一个参数是我们要测试的流,第二个参数是一个谓词 **Predicate**。**Matcher** 可以匹配所有的 **Stream::\*Match** 方法,所以可以将每一个**Stream::\*Match**方法引用传递到 `show()` 中。对`match.test()` 的调用会被转换成 对方法引用**Stream::\*Match** 的调用。 -`show()` 接受一个**Matcher**和一个 `val` 参数,`val` 在判断测试 `n < val`中指定了最大值。`show()` 方法生成了整数1-9组成的一个流。`peek()`用来展示在测试短路之前测试进行到了哪一步。从输出中可以看到每次都发生了短路。 +`show()` 接受一个**Matcher**和一个 `val` 参数,`val` 在判断测试 `n < val`中指定了最大值。`show()` 方法生成了整数1-9组成的一个流。`peek()`用来展示在测试短路之前测试进行到了哪一步。从输出中可以看到:每次都发生了短路。 ### 查找 @@ -2034,9 +2034,9 @@ public class SelectElement { 242 ``` -无论流是否为并行化,`findFirst()` 总是会选择流中的第一个元素。对于非并行流,`findAny()`会选择流中的第一个元素(即使从定义上来看是选择任意元素)。在这个例子中,用 `parallel()` 将流并行化,以展示 `findAny()` 不选择流的第一个元素的可能性。 +无论流是否并行,`findFirst()` 总是会选择流中的第一个元素。对于非并行流,`findAny()`则会选择流中的第一个元素(即使从语义来看是选择任意元素)。在这个例子中,用 `parallel()` 将流并行化,以展示 `findAny()` 不选择流的第一个元素的可能性。 -如果必须选择流中最后一个元素,那就使用 `reduce()`。代码示例: +如果要选择流中最后一个元素,就使用 `reduce()`。代码示例: ```java // streams/LastElement.java @@ -2064,15 +2064,15 @@ public class LastElement { three ``` -`reduce()` 的参数只是用最后一个元素替换了最后两个元素,最终只生成最后一个元素。如果为数字流,你必须使用相近的数字 **Optional** 类型( numeric optional type),否则使用 **Optional** 类型,就像上例中的 `Optional`。 +`reduce()` 的参数只是用最后一个元素替换了最后两个元素,最终只生成最后一个元素。如果是数字流,你必须使用相近的数字 **Optional** 类型( numeric optional type)(上例中的`OptionalInt`),非数字流则使用 **Optional** 类型(上例中的 `Optional`)。 ### 信息 - `count()`:流中的元素个数。 -- `max(Comparator)`:根据所传入的 **Comparator** 所决定的“最大”元素。 -- `min(Comparator)`:根据所传入的 **Comparator** 所决定的“最小”元素。 +- `max(Comparator)`:根据所传入的 **Comparator** 所定义的“最大”元素。 +- `min(Comparator)`:根据所传入的 **Comparator** 所定义的“最小”元素。 **String** 类型有预设的 **Comparator** 实现。代码示例: @@ -2113,7 +2113,7 @@ you - `average()` :求取流元素平均值。 - `max()` 和 `min()`:数值流操作无需 **Comparator**。 - `sum()`:对所有流元素进行求和。 -- `summaryStatistics()`:生成可能有用的数据。目前并不太清楚这个方法存在的必要性,因为我们其实可以用更直接的方法获得需要的数据。 +- `summaryStatistics()`:生成潜在有用的数据。目前并不太清楚这个方法存在的必要性,因为我们其实可以用更直接的方法获得需要的数据。 ```java // streams/NumericStreamInfo.java @@ -2144,7 +2144,7 @@ IntSummaryStatistics{count=100, sum=50794, min=8, average=507.940000, max=998} ## 本章小结 -流式操作改变并极大地提升了 Java 语言的可编程性,并可能极大地阻止了 Java 编程人员向诸如 Scala 这种函数式语言的流转。在本书的剩余部分,我们将尽可能地使用流。 +流式操作改变并极大地提升了 Java 语言的可编程性,并可能明显阻止了 Java 编程人员向诸如 Scala 这种函数式语言的流转。在本书的剩余部分,我们将尽可能地使用流。 [^1]: 在软件或信息建模的上下文中,快乐路径(有时称为快乐流)是指没有异常或错误情形导致退出的默认场景。例如,验证信用卡号的函数的快乐路径应该是任何验证规则都不会出现错误而中断,从而让执行成功地延续到最后,生成一个积极的响应让使用者快乐。[见 wikipedia: happy path](https://en.wikipedia.org/wiki/Happy_path) From 03009217e334b51e810b3e6eb18061909b4bdd95 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 10 Dec 2020 14:02:06 +0800 Subject: [PATCH 27/68] chapter 15 01 --- docs/book/15-Exceptions.md | 66 +++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/docs/book/15-Exceptions.md b/docs/book/15-Exceptions.md index ecb6ff8f..6ab87f55 100644 --- a/docs/book/15-Exceptions.md +++ b/docs/book/15-Exceptions.md @@ -11,17 +11,17 @@ > 要想创建健壮的系统,它的每一个构件都必须是健壮的。 -Java 使用异常来提供一致的错误报告模型,使得构件能够与客户端代码可靠地沟通问题。 +Java 使用异常来提供一致的错误报告模型,使得组件能够与客户端代码可靠地沟通问题。 -Java 中的异常处理的目的在于通过使用少于目前数量的代码来简化大型、可靠的程序的生成,并且通过这种方式可以使你更加确信:你的应用中没有未处理的错误。异常的相关知识学起来并非艰涩难懂,并且它属于那种可以使你的项目受益明显、立竿见影的特性之一。 +Java 中的异常处理的目的——通过使用比目前更少的代码来简化大型、可靠的程序的生成, 这样做可以让你更有信心,你的应用程序不会有未处理的错误。异常的相关知识学起来并非艰涩难懂,并且它属于那种可以使你的项目受益明显、立竿见影的特性之一。 -因为异常处理是 Java 中唯一官方的错误报告机制,并且通过编译器强制执行,所以不学习异常处理的话,你也就只能写出书中那么些例子了。本章将教你如何编写正确的异常处理程序,以及当方法出问题的时候,如何产生自定义的异常。 +因为异常处理是 Java 中唯一官方的错误报告机制,并且通过编译器执行,所以不学习异常处理的话,对此的认识就到此为止了。本章将教你如何编写正确的异常处理程序,以及当方法出问题的时候,如何产生自定义的异常。 ## 异常概念 -C 以及其他早期语言常常具有多种错误处理模式,这些模式往往建立在约定俗成的基础之上,而并不属于语言的一部分。通常会返回某个特殊值或者设置某个标志,并且假定接收者将对这个返回值或标志进行检查,以判定是否发生了错误。然而,随着时间的推移,人们发现,高傲的程序员们在使用程序库的时候更倾向于认为:“对,错误也许会发生,但那是别人造成的,不关我的事”。所以,程序员不去检查错误情形也就不足为奇了(何况对某些错误情形的检查确实很无聊)。如果的确在每次调用方法的时候都彻底地进行错误检查,代码很可能会变得难以阅读。正是由于程序员还仍然用这些方式拼凑系统,所以他们拒绝承认这样一个事实:对于构造大型、健壮、可维护的程序而言,这种错误处理模式已经成为了主要障碍。 +C 以及其他早期语言常常具有多种错误处理模式,这些模式往往建立在约定俗成的基础之上,而并不属于语言的一部分。通常会返回某个特殊值或者设置某个标志,并且假定接收者将对这个返回值或标志进行检查,以判定是否发生了错误。然而,随着时间的推移,人们发现,使用lib库程序员们会觉得自己无敌:“对,错误也许会发生,但那是别人造成的,不是我的代码问题”。所以,程序员不去检查错误情形也就不足为奇了(何况对某些错误情形的检查确实很无聊)。如果在每次调用方法的时候都彻底进行错误排查,代码很可能会变成难以阅读的噩梦。但由于程序员还仍然用这些语言(C 以及其他早期语言)拼凑系统,所以他们拒绝承认这样一个事实:对于构造大型、健壮、可维护的程序而言,这种错误处理模式已经成为了主要障碍。 解决的办法是,用强制规定的形式来消除错误处理过程中随心所欲的因素。这种做法由来已久,对异常处理的实现可以追溯到 20 世纪 60 年代的操作系统,甚至于 BASIC 语言中的“on error goto”语句。而 C++的异常处理机制基于 Ada,Java 中的异常处理机制则建立在 C++ 的基础之上(尽管看上去更像 Object Pascal)。 @@ -33,11 +33,11 @@ C 以及其他早期语言常常具有多种错误处理模式,这些模式往 ## 基本异常 -异常情形(exceptional condition)是指阻止当前方法或作用域继续执行的问题。把异常情形与普通问题相区分很重要,所谓的普通问题是指,在当前环境下能得到足够的信息,总能处理这个错误。而对于异常情形,就不能继续下去了,因为在当前环境下无法获得必要的信息来解决问题。你所能做的就是从当前环境跳出,并且把问题提交给上一级环境。这就是抛出异常时所发生的事情。 +*异常情形*(exceptional condition)是指阻止当前方法或作用域继续执行的问题。把异常情形与普通问题相区分很重要,所谓的普通问题是指,在当前环境下能得到足够的信息,总能处理这个错误。而对于异常情形,就不能继续下去了,因为在当前环境下无法获得必要的信息来解决问题。你所能做的就是从当前环境跳出,并且把问题提交给上一级环境。这就是抛出异常时所发生的事情。 除法就是一个简单的例子。除数有可能为 0,所以先进行检查很有必要。但除数为 0 代表的究竟是什么意思呢?通过当前正在解决的问题环境,或许能知道该如何处理除数为 0 的情况。但如果这是一个意料之外的值,你也不清楚该如何处理,那就要抛出异常,而不是顺着原来的路径继续执行下去。 -当抛出异常后,有几件事会随之发生。首先,同 Java 中其他对象的创建一样,将使用 new 在堆上创建异常对象。然后,当前的执行路径(它不能继续下去了)被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态中恢复,以使程序能要么换一种方式运行,要么继续运行下去。 +当抛出异常后,有几件事会随之发生。首先,同 Java 中其他对象的创建一样,将使用 new 在堆上创建异常对象(exception object)。然后,当前的执行路径(它不能继续下去了)被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态中恢复,以使程序能要么换一种方式运行,要么继续运行下去。 举一个抛出异常的简单例子。对于对象引用 t,传给你的时候可能尚未被初始化。所以在使用这个对象引用调用其方法之前,会先对引用进行检查。可以创建一个代表错误信息的对象,并且将它从当前环境中“抛出”,这样就把错误信息传播到了“更大”的环境中。这被称为*抛出一个异常*,看起来像这样: @@ -60,13 +60,13 @@ if(t == null) throw new NullPointerException("t = null"); ``` -不久读者将看到,要把这个字符串的内容提取出来可以有多种不同的方法。 +等下读者将看到,要把这个字符串的内容提取出来可以有多种不同的方法。 关键字 **throw** 将产生许多有趣的结果。在使用 **new** 创建了异常对象之后,此对象的引用将传给 **throw**。尽管异常对象的类型通常与方法设计的返回类型不同,但从效果上看,它就像是从方法“返回”的。可以简单地把异常处理看成一种不同的返回机制,当然若过分强调这种类比的话,就会有麻烦了。另外还能用抛出异常的方式从当前的作用域退出。在这两种情况下,将会返回一个异常对象,然后退出方法或作用域。 抛出异常与方法正常返回的相似之处到此为止。因为异常返回的“地点”与普通方法调用返回的“地点”完全不同。(异常将在一个恰当的异常处理程序中得到解决,它的位置可能离异常被抛出的地方很远,也可能会跨越方法调用栈的许多层级。) -此外,能够抛出任意类型的 **Throwable** 对象,它是异常类型的根类。通常,对于不同类型的错误,要抛出相应的异常。错误信息可以保存在异常对象内部或者用异常类的名称来暗示。上一层环境通过这些信息来决定如何处理异常。(通常,唯一的信息只有异常的类型名,而在异常对象内部没有任何有意义的信息。) +此外,能够抛出任意类型的 **Throwable** 对象,它是异常类型的基类。通常,为每个不同类型的错误抛出不同的异常类。错误信息可以保存在异常对象内部或者用异常类的名称来暗示。上一级环境通过这些信息来决定如何处理异常。(通常,唯一的信息只有异常的类型名,而在异常对象内部没有任何有意义的信息。) ## 异常捕获 @@ -113,7 +113,7 @@ try { 另一种称为恢复模型。意思是异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次能成功。对于恢复模型,通常希望异常被处理之后能继续执行程序。如果想要用 Java 实现类似恢复的行为,那么在遇见错误时就不能抛出异常,而是调用方法来修正该错误。或者,把 try 块放在 while 循环里,这样就不断地进入 try 块,直到得到满意的结果。 -在过去,使用支持恢复模型异常处理的操作系统的程序员们最终还是转向使用类似“终止模型”的代码,并且忽略恢复行为。所以虽然恢复模型开始显得很吸引人,但不是很实用。其中的主要原因可能是它所导致的耦合:恢复性的处理程序需要了解异常抛出的地点,这势必要包含依赖于抛出位置的非通用性代码。这增加了代码编写和维护的困难,对于异常可能会从许多地方抛出的大型程序来说,更是如此。 +在过去,使用支持恢复模型异常处理的操作系统的程序员们最终会使用类似“终止模型”的代码并跳过恢复。因此, 虽然恢复模型开始显得很吸引人,但在实践中却没有那么有用。其中的主要原因可能是它所导致的耦合:一个恢复处理程序需要了解异常抛出的位置,并包含根据抛出位置特制的非通用性代码。这增加了代码编写和维护的困难,对于异常可能会从许多地方抛出的大型程序来说,更是如此。 @@ -121,7 +121,7 @@ try { 不必拘泥于 Java 已有的异常类型。Java异常体系不可能预见你将报告的所有错误,所以你可以创建自己的异常类,来表示你的程序中可能遇到的问题。 -要自己定义异常类,必须从已有的异常类继承,最好是选择意思相近的异常类继承(不过这样的异常并不容易找)。建立新的异常类型最简单的方法就是让编译器为你产生无参构造器,所以这几乎不用写多少代码: +要自己定义异常类,必须从已有的异常类继承,最好是选择含义相近的异常类继承(不过这样的异常并不容易找)。建立新的异常类型最简单的方法就是让编译器为你产生无参构造器,所以这几乎不用写多少代码: ```java // exceptions/InheritingExceptions.java @@ -153,9 +153,17 @@ Throw SimpleException from f() Caught it! ``` -编译器创建了无参构造器,它将自动调用基类的无参构造器。本例中不会得到像 SimpleException(String) 这样的构造器,这种构造器也不实用。你将看到,对异常来说,最重要的部分就是类名,所以本例中建立的异常类在大多数情况下已经够用了。 +编译器创建了无参构造器,它将自动调用基类的无参构造器。本例中不会有像 **SimpleException(String)** 这样的构造器,这种构造器也不会应用太多。你将看到,对异常来说,最重要的部分就是类名,所以本例中建立的异常类在大多数情况下已经够用了。 本例的结果被显示在控制台。你也可以通过写入 System.err 而将错误发送给标准错误流。通常这比把错误信息输出到 System.out 要好,因为 System.out 也许会被重定向。如果把结果送到 System.err,它就不会随 System.out 一起被重定向,所以用户就更容易注意到它。 +```java +public static void main(String[] args) throws Exception { + String str = "sout"; + PrintStream out = new PrintStream("c:/test.txt"); + System.setOut(out); + System.out.println(str); //这种情况叫做重定向 +} +``` 你也可以为异常类创建一个接受字符串参数的构造器: @@ -204,13 +212,13 @@ MyException: Originated in g() 新增的代码非常简短:两个构造器定义了 MyException 类型对象的创建方式。对于第二个构造器,使用 super 关键字明确调用了其基类构造器,它接受一个字符串作为参数。 -在异常处理程序中,调用了在 Throwable 类声明(Exception 即从此类继承)的 printStackTrace() 方法。就像从输出中看到的,它将打印“从方法调用处直到异常抛出处”的方法调用序列。这里,信息被发送到了 System.out,并自动地被捕获和显示在输出中。但是,如果调用默认版本: +在异常处理程序中,调用了在 Throwable 类声明(Exception 即从此类继承)的 printStackTrace() 方法。就像从输出中看到的,它将打印“从方法调用处直到异常抛出处”的方法调用序列。这里,信息被发送到了 System.out,并自动地被捕获和显示在输出中(白字)。但是,如果调用默认版本: ```java e.printStackTrace(); ``` -信息就会被输出到标准错误流。 +信息就会被输出到标准错误流(红字)。 ### 异常与记录日志 @@ -263,9 +271,9 @@ LoggingExceptions.main(LoggingExceptions.java:25) Caught LoggingException ``` -静态的 Logger.getLogger() 方法创建了一个 String 参数相关联的 Logger 对象(通常与错误相关的包名和类名),这个 Logger 对象会将其输出发送到 System.err。向 Logger 写入的最简单方式就是直接调用与日志记录消息的级别相关联的方法,这里使用的是 severe()。为了产生日志记录消息,我们欲获取异常抛出处的栈轨迹,但是 printStackTrace() 不会默认地产生字符串。为了获取字符串,我们需要使用重载的 printStackTrace() 方法,它接受一个 java.io.PrintWriter 对象作为参数(PrintWriter 会在 [附录:I/O 流 ](./Appendix-IO-Streams.md) 一章详细介绍)。如果我们将一个 java.io.StringWriter 对象传递给这个 PrintWriter 的构造器,那么通过调用 toString() 方法,就可以将输出抽取为一个 String。 +静态的 Logger.getLogger() 方法创建了一个 String 参数相关联的 Logger 对象(通常与错误相关的包名和类名),这个 Logger 对象会将它的输出发送到 System.err。向 Logger 写入的最简单方式就是直接调用与日志记录消息的级别相关联的方法,这里使用的是 severe()。为了产生日志记录消息,我们欲获取异常抛出处的栈轨迹,但是 printStackTrace() 不会默认地产生字符串。为了获取字符串,我们需要使用重载的 printStackTrace() 方法,它接受一个 java.io.PrintWriter 对象作为参数(PrintWriter 会在 [附录:I/O 流 ](./Appendix-IO-Streams.md) 一章详细介绍)。如果我们将一个 java.io.StringWriter 对象传递给这个 PrintWriter 的构造器,那么通过调用 toString() 方法,就可以将输出抽取为一个 String。 -尽管由于 LoggingException 将所有记录日志的基础设施都构建在异常自身中,使得它所使用的方式非常方便,并因此不需要客户端程序员的干预就可以自动运行,但是更常见的情形是我们需要捕获和记录其他人编写的异常,因此我们必须在异常处理程序中生成日志消息; +尽管由于 LoggingException 将所有记录日志的基础设施都构建在异常自身中,使得它所使用的方式非常方便(new Exception会自动记录日志),并因此不需要客户端程序员的干预就可以自动运行,但是更常见的情形是我们需要捕获和记录其他人编写的异常(因而不能侵入别人的异常代码的构造器),因此我们必须在异常处理程序中手动生成日志消息; ```java // exceptions/LoggingExceptions2.java @@ -376,8 +384,8 @@ at ExtraFeatures.main(ExtraFeatures.java:48) e.val() = 47 ``` -新的异常添加了字段 x 以及设定 x 值的构造器和读取数据的方法。此外,还覆盖了 Throwable. -getMessage() 方法,以产生更详细的信息。对于异常类来说,getMessage() 方法有点类似于 toString() 方法。 +新的异常添加了字段 x 以及设定 x 值的构造器和读取数据的方法。此外,还重写了 Throwable. +getMessage() 方法,以产生更详细的信息。对于异常类来说,getMessage() 方法类似于 toString() 方法。 既然异常也是对象的一种,所以可以继续修改这个异常类,以得到更强的功能。但要记住,使用程序包的客户端程序员可能仅仅只是查看一下抛出的异常类型,其他的就不管了(大多数 Java 库里的异常都是这么用的),所以对异常所添加的其他功能也许根本用不上。 @@ -403,7 +411,7 @@ void f() { // ... 不过还是有个能“作弊”的地方:可以声明方法将抛出异常,实际上却不抛出。编译器相信了这个声明,并强制此方法的用户像真的抛出异常那样使用这个方法。这样做的好处是,为异常先占个位子,以后就可以抛出这种异常而不用修改已有的代码。在定义抽象基类和接口时这种能力很重要,这样派生类或接口实现就能够抛出这些预先声明的异常。 -这种在编译时被强制检查的异常称为被检查的异常。 +这种在编译时被强制检查的异常称为*被检查的异常*(**checked exceptions**)。 ## 捕获所有异常 @@ -692,7 +700,7 @@ at Rethrowing.h(Rethrowing.java:27) at Rethrowing.main(Rethrowing.java:38) ``` -调用 fillInStackTrace() 的那一行就成了异常的新发生地了。 +调用 fillInStackTrace() 的那一行就成了异常的新发生地了。(减少爬栈, 提高效率) 有可能在捕获异常之后抛出另一种异常。这么做的话,得到的效果类似于使用 fillInStackTrace(),有关原来异常发生点的信息会丢失,剩下的是与新的抛出点有关的信息: @@ -745,7 +753,7 @@ at RethrowNew.main(RethrowNew.java:26) 最后那个异常仅知道自己来自 main(),而对 f() 一无所知。 -永远不必为清理前一个异常对象而担心,或者说为异常对象的清理而担心。它们都是用 new 在堆上创建的对象,所以垃圾回收器会自动把它们清理掉。 +永远不必为清理之前的 or 任何的异常对象而担心。它们都是用 new 在堆上创建的对象,所以垃圾回收器会自动把它们清理掉。 ### 精准的重新抛出异常 @@ -766,7 +774,7 @@ public class PreciseRethrow { } ``` -因为 catch 捕获了一个 BaseException,编译器强迫你声明 catcher() 抛出 BaseException,即使它实际上抛出了更具体的 DerivedException。从 Java 7 开始,这段代码就可以编译,这是一个很小但很有用的修复。 +因为 catch 捕获了一个 BaseException,Java7 前的编译器强迫你的方法声明 catcher() 只能抛出 BaseException,即使它实际上抛出了更具体的 DerivedException。从 Java 7 开始,这段代码就可以编译,这是一个很小但很有用的修复。 ### 异常链 @@ -1161,7 +1169,7 @@ Caught FourException in 1st try block finally in 1st try block ``` -当涉及 break 和 continue 语句的时候,finally 子句也会得到执行。请注意,如果把 finally 子句和带标签的 break 及 continue 配合使用,在 Java 里就没必要使用 goto 语句了。 +当涉及 break 和 continue 语句的时候,finally 子句也会得到执行。请注意,如果把 finally 子句和带标签的 break 及 continue 配合使用, 就免去了对 goto 语句的需求了。 ### 在 return 中使用 finally @@ -1290,7 +1298,7 @@ public class ExceptionSilencer { ## 异常限制 -当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。这个限制很有用,因为这意味着与基类一起工作的代码,也能和导出类一起正常工作(这是面向对象的基本概念),异常也不例外。 +当重写方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。这个限制很有用,因为这意味着与基类一起工作的代码,也能和导出类一起正常工作(这是面向对象的基本概念),异常也不例外。 下面例子演示了这种(在编译时)施加在异常上面的限制: @@ -1371,21 +1379,21 @@ public class StormyInning extends Inning implements Storm { } ``` -在 Inning 类中,可以看到构造器和 event() 方法都声明将抛出异常,但实际上没有抛出。这种方式使你能强制用户去捕获可能在覆盖后的 event() 版本中增加的异常,所以它很合理。这对于抽象方法同样成立,比如 atBat()。 +在 Inning 类中,可以看到构造器和 event() 方法都声明将抛出异常,但实际上没有抛出。这种方式使你能强制用户去捕获可能在重写后的 event() 版本中增加的异常,所以它很合理。这对于抽象方法同样成立,比如 atBat()。 接口 Storm 包含了一个在 Inning 中定义的方法 event() 和一个不在 Inning 中定义的方法 rainHard()。这两个方法都抛出新的异常 RainedOut,如果 StormyInning 类在扩展 Inning 类的同时又实现了 Storm 接口,那么 Storm 里的 event() 方法就不能改变在 Inning 中的 event() 方法的异常接口。否则的话,在使用基类的时候就不能判断是否捕获了正确的异常,所以这也很合理。当然,如果接口里定义的方法不是来自于基类,比如 rainHard(),那么此方法抛出什么样的异常都没有问题。 -异常限制对构造器不起作用。你会发现 StormyInning 的构造器可以抛出任何异常,而不必理会基类构造器所抛出的异常。然而,因为基类构造器必须以这样或那样的方式被调用(这里默认构造器将自动被调用),派生类构造器的异常说明必须包含基类构造器的异常说明。 +异常限制对构造器不起作用。你会发现 StormyInning 的构造器可以抛出任何异常,而不必受限于基类构造器所抛出的异常。然而,因为基类构造器必须以这样或那样的方式被调用(这里默认构造器将自动被调用),派生类构造器的异常说明必须包含基类构造器的异常说明。 派生类构造器不能捕获基类构造器抛出的异常。 StormyInning.walk() 不能通过编译是因为它抛出了一个 Inning.walk() 中没有声明的异常。如果编译器允许这么做的话,就可以编写调用Inning.walk()却不处理任何异常的代码。 但是当使用 `Inning`派生类的对象时,就会抛出异常,从而导致程序出现问题。通过强制派生类遵守基类方法的异常说明,对象的可替换性得到了保证。 -覆盖后的 event() 方法表明,派生类版的方法可以不抛出任何异常,即使基类版的方法抛出了异常。因为这样做不会破坏那些假定基类版的方法会抛出异常的代码。类似的情况出现在 `atBat()`上,它抛出的异常`PopFoul`是由基类版`atBat()`抛出的`Foul` 异常派生而来。如果你写的代码同 `Inning` 一起工作,并且调用了 `atBat()`的话,那么肯定能捕获 `Foul` 。又因为 `PopFoul` 是由 `Foul`派生而来,因此异常处理程序也能捕获 `PopFoul`。 +重写后的 event() 方法表明,派生类版的方法可以不抛出任何异常,即使基类版的方法抛出了异常。因为这样做不会破坏那些假定基类版的方法会抛出异常的代码。类似的情况出现在 `atBat()`上,它抛出的异常`PopFoul`是由基类版`atBat()`抛出的`Foul` 异常派生而来。如果你写的代码同 `Inning` 一起工作,并且调用了 `atBat()`的话,那么肯定能捕获 `Foul` 。又因为 `PopFoul` 是由 `Foul`派生而来,因此异常处理程序也能捕获 `PopFoul`。 最后一个有趣的地方在 `main()`。如果处理的刚好是 Stormylnning 对象的话,编译器只要求捕获这个类所抛出的异常。但是如果将它向上转型成基类型,那么编译器就会准确地要求捕获基类的异常。所有这些限制都是为了能产生更为健壮的异常处理代码。 -尽管在继承过程中,编译器会对异常说明做强制要求,但异常说明本身并不属于方法类型的一部分,方法类型是由方法的名字与参数的类型组成的。因此,不能基于异常说明来重载方法。此外,一个出现在基类方法的异常说明中的异常,不一定会出现在派生类方法的异常说明里。这点同继承的规则明显不同,在继承中,基类的方法必须出现在派生类里,换句话说,在继承和覆盖的过程中,某个特定方法的“异常说明的接口”不是变大了而是变小了——这恰好和类接口在继承时的情形相反。 +尽管在继承过程中,编译器会对异常说明做强制要求,但异常说明本身并不属于方法类型的一部分,方法类型是由方法的名字与参数的类型组成的。因此,不能基于异常说明来重载方法。此外,一个出现在基类方法的异常说明中的异常,不一定会出现在派生类方法的异常说明里。(这点与继承的规则明显不同,在继承中,基类的方法必须出现在派生类里。)换句话说,在继承和重写的过程中,子类特定方法的“异常说明的接口” **不能扩大只能减小** ——这与继承时的类接口规则( 访问权限 **不能减小只能扩大** )正好相反。 @@ -1564,7 +1572,7 @@ NeedsCleanup 4 disposed - [2] 为了构造和清理,可以看到将具有不能失败的构造器的对象分组在一起。 - [3] 展示了如何处理那些具有可以失败的构造器,且需要清理的对象。为了正确处理这种情况,事情变得很棘手,因为对于每一个构造,都必须包含在其自己的 try-finally 语句块中,并且每一个对象构造必须都跟随一个 try-finally 语句块以确保清理。 -本例中异常处理的混乱情形,有力的论证了应该创建不会抛出异常的构造器,尽管这并不总会实现。 +本例中异常处理的混乱情形,有力的论证了应该创建不会抛出异常的构造器,尽管这并非总能实现。 注意,如果 dispose() 可以抛出异常,那么你可能需要额外的 try 语句块。基本上,你应该仔细考虑所有的可能性,并确保正确处理每一种情况。 @@ -1945,7 +1953,7 @@ try { ## 其他可选方式 -异常处理系统就像一个活门(trap door),使你能放弃程序的正常执行序列。当“异常情形”发生的时候,正常的执行已变得不可能或者不需要了,这时就要用到这个“活门"。异常代表了当前方法不能继续执行的情形。开发异常处理系统的原因是,如果为每个方法所有可能发生的错误都进行处理的话,任务就显得过于繁重了,程序员也不愿意这么做。结果常常是将错误忽略。应该注意到,开发异常处理的初衷是为了方便程序员处理错误。 +异常处理系统就像一个*活板门*(trapdoor),使你能放弃程序的正常执行序列。当“异常情形”发生的时候,正常的执行已变得不可能或者不需要了,这时就要用到这个“*活板门*"。异常代表了当前方法不能继续执行的情形。开发异常处理系统的原因是,如果为每个方法所有可能发生的错误都进行处理的话,任务就显得过于繁重了,程序员也不愿意这么做。结果常常是将错误忽略。应该注意到,开发异常处理的初衷是为了方便程序员处理错误。 异常处理的一个重要原则是“只有在你知道如何处理的情况下才捕获异常"。实际上,异常处理的一个重要目标就是把处理错误的代码同错误发生的地点相分离。这使你能在一段代码中专注于要完成的事情,至于如何处理错误,则放在另一段代码中完成。这样一来,主要代码就不会与错误处理逻辑混在一起,也更容易理解和维护。通过允许一个处理程序去处理多个出错点,异常处理还使得错误处理代码的数量趋于减少。 From b0b1be5b000a0e16db6f34634c5c83cc2d50356b Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 10 Dec 2020 14:20:29 +0800 Subject: [PATCH 28/68] chapter 15 02 --- docs/book/15-Exceptions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/book/15-Exceptions.md b/docs/book/15-Exceptions.md index 6ab87f55..b8b2da2b 100644 --- a/docs/book/15-Exceptions.md +++ b/docs/book/15-Exceptions.md @@ -2152,8 +2152,8 @@ SomeOtherException: SomeOtherException 3. 解决问题并且重新调用产生异常的方法。 4. 进行少许修补,然后绕过异常发生的地方继续执行。 5. 用别的数据进行计算,以代替方法预计会返回的值。 -6. 把当前运行环境下能做的事情尽量做完,然后把相同的异常重抛到更高层。 -7. 把当前运行环境下能做的事情尽量做完,然后把不同的异常抛到更高层。 +6. 把当前运行环境下能做的事情尽量做完,然后把相同的异常重新抛出到更高层。 +7. 把当前运行环境下能做的事情尽量做完,然后把一个不同的异常抛到更高层。 8. 终止程序。 9. 进行简化。(如果你的异常模式使问题变得太复杂,那用起来会非常痛苦也很烦人。) 10. 让类库和程序更安全。(这既是在为调试做短期投资,也是在为程序的健壮性做长期投资。) From e671356b5889cc4698fa82d1b4c064d0b3fe3878 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 10 Dec 2020 16:13:25 +0800 Subject: [PATCH 29/68] chapter 16 00 --- docs/book/16-Validating-Your-Code.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/book/16-Validating-Your-Code.md b/docs/book/16-Validating-Your-Code.md index 26917eab..46a98e62 100644 --- a/docs/book/16-Validating-Your-Code.md +++ b/docs/book/16-Validating-Your-Code.md @@ -20,9 +20,9 @@ Java是一个静态类型的语言,程序员经常对一种编程语言明显 这个过程是将集成测试构建到你创建的所有代码中,并在每次构建系统时运行这些测试。这样,构建过程不仅能检查语法的错误,同时也能检查语义的错误。 -“单元”是指测试一小部分代码 。通常,每个类都有测试来检查它所有方法的行为。“系统”测试则是不同的,它检查的是整个程序是否满足要求。 +“单元”是指测试一小部分代码 。通常,每个类都有测试来检查它所有方法的行为。“系统”测试则不同,它检查的是整个程序是否满足要求。 -C 风格的语言,尤其是 C++,通常会认为性能比安全更重要。用 Java 编程比 C++(一般认为大概快两倍)快的原因是 Java 的安全性保障:比如垃圾回收以及改良的类型检测等特性。通过将单元测试集成到构建过程中,你扩大了这个安全保障,因而有了更快的开发效率。当发现设计或实现的缺陷时,可以更容易、更大胆地重构你的代码。 +C 风格的语言,尤其是 C++,通常会认为性能比安全更重要。用 Java 开发程序比 C++(一般认为大概快两倍)快的原因是 Java 的安全性保障:比如垃圾回收以及改良的类型检测等特性。通过将单元测试集成到构建过程中,你扩大了这个安全保障,因而有了更快的开发效率。当发现设计或实现的缺陷时,可以更容易、更大胆地重构你的代码。 我自己的测试经历开始于我意识到要确保书中代码的正确性,书中的所有程序必须能够通过合适的构建系统自动提取、编译。这本书所使用的构建系统是 Gradle。 你只要在安装 JDK 后输入 **gradlew compileJava**,就能编译本书的所有代码。自动提取和自动编译的效果对本书代码的质量是如此的直接和引人注目,(在我看来)这会很快成为任何编程书籍的必备条件——你怎么能相信没有编译的代码呢? 我还发现我可以使用搜索和替换在整本书进行大范围的修改,如果引入了一个错误,代码提取器和构建系统就会清除它。随着程序越来越复杂,我在系统中发现了一个严重的漏洞。编译程序毫无疑问是重要的第一步, 对于一本要出版的书而言,这看来是相当具有革命意义的发现(由于出版压力, 你经常打开一本程序设计的书会发现书中代码的错误)。但是,我收到了来自读者反馈代码中存在语义问题。当然,这些问题可以通过运行代码发现。我在早期实现一个自动化执行测试系统时尝试了一些不太有效的方式,但迫于出版压力,我明白我的程序绝对有问题,并会以 bug 报告的方式让我自食恶果。我也经常收到读者的抱怨说,我没有显示足够的代码输出。我需要验证程序的输出,并且在书中显示验证的输出。我以前的意见是读者应该一边看书一边运行代码,许多读者就是这么做的并且从中受益。然而,这种态度背后的原因是,我无法保证书中的输出是正确的。从经验来看,我知道随着时间的推移,会发生一些事情,使得输出不再正确(或者一开始就不正确)。为了解决这个问题,我利用 Python 创建了一个工具(你将在下载的示例中找到此工具)。本书中的大多数程序都产生控制台输出,该工具将该输出与源代码清单末尾的注释中显示的预期输出进行比较,所以读者可以看到预期的输出,并且知道这个输出已经被构建程序验证过。 @@ -160,9 +160,9 @@ Cleaning up 4 */ ``` -**@BeforeAll** 注解是在任何其他测试操作之前运行一次的方法。 **@AfterAll** 是所有其他测试操作之后只运行一次的方法。两个方法都必须是静态的。 +**@BeforeAll** 注解是在任何其他测试操作之前运行一次的方法。 **@AfterAll** 是所有其他测试操作之后只运行一次的方法。两个方法都必须是静态的。(注: junit4里面是 **@BeforeClass** **@AfterClass**) -**@BeforeEach**注解是通常用于创建和初始化公共对象的方法,并在每次测试前运行。可以将所有这样的初始化放在测试类的构造函数中,尽管我认为 **@BeforeEach** 更加清晰。JUnit为每个测试创建一个对象,确保测试运行之间没有副作用。然而,所有测试的所有对象都是同时创建的(而不是在测试之前创建对象),所以使用 **@BeforeEach** 和构造函数之间的唯一区别是 **@BeforeEach** 在测试前直接调用。在大多数情况下,这不是问题,如果你愿意,可以使用构造函数方法。 +**@BeforeEach**注解是通常用于创建和初始化公共对象的方法,并在每次测试前运行。可以将所有这样的初始化放在测试类的构造函数中,尽管我认为 **@BeforeEach** 更加清晰。JUnit为每个测试创建一个对象,确保测试运行之间没有副作用。然而,所有测试的所有对象都是同时创建的(而不是在测试之前创建对象),所以使用 **@BeforeEach** 和构造函数之间的唯一区别是 **@BeforeEach** 在测试前直接调用。在大多数情况下,这不是问题,如果你愿意,可以使用构造函数方法。(注: junit4里面是 **@Before** **@After**) 如果你必须在每次测试后执行清理(如果修改了需要恢复的静态文件,打开文件需要关闭,打开数据库或者网络连接,etc),那就用注解 **@AfterEach**。 @@ -186,13 +186,13 @@ JUnit 是 Java 最流行的单元测试框架,但也有其它可以替代的 #### 测试覆盖率的幻觉 -测试覆盖率,同样也称为代码覆盖率,度量代码的测试百分比。百分比越高,测试的覆盖率越大。这里有很多[方法](https://en.wikipedia.org/wiki/Code_coverage) +测试覆盖率,同样也称为代码覆盖率,度量代码被测试的百分比。百分比越高,测试的覆盖率越大。这里有很多[方法](https://en.wikipedia.org/wiki/Code_coverage) 计算覆盖率,还有有帮助的文章[Java代码覆盖工具](https://en.wikipedia.org/wiki/Java_Code_Coverage_Tools)。 -对于没有知识但处于控制地位的人来说,很容易在没有任何了解的情况下也有概念认为 100% 的测试覆盖是唯一可接受的值。这有一个问题,因为 100% 并不意味着是对测试有效性的良好测量。你可以测试所有需要它的东西,但是只需要 65% 的覆盖率。如果需要 100% 的覆盖,你将浪费大量时间来生成剩余的代码,并且在向项目添加代码时浪费的时间更多。 +对于没有知识但有控制权的人来说,很容易决定100%覆盖是唯一可接受的值。这有一个问题,因为 100% 并不能很好地衡量测试效果。你可以测试所有需要它的东西,但是只需要 65% 的覆盖率。如果需要 100% 的覆盖,你将浪费大量时间来生成剩余的代码,并浪费更多的时间在向项目添加代码。 -当分析一个未知的代码库时,测试覆盖率作为一个粗略的度量是有用的。如果覆盖率工具报告的值特别低(比如,少于百分之40),则说明覆盖不够充分。然而,一个非常高的值也同样值得怀疑,这表明对编程领域了解不足的人迫使团队做出了武断的决定。覆盖工具的最佳用途是发现代码库中未测试的部分。但是,不要依赖覆盖率来得到测试质量的任何信息。 +当分析一个未知的代码库时,测试覆盖率作为一个粗略的度量是有用的。如果覆盖率工具报告的值特别低(比如,少于百分之40),则说明覆盖不够充分。然而,一个非常高的值也同样值得怀疑,这表明对编程领域了解不足的人迫使团队做出了武断的决定。覆盖率工具的最佳用途是发现代码库中未测试的部分。但是,不要依赖覆盖率来得到测试质量的任何信息。 @@ -240,7 +240,7 @@ at Assert1.main(Assert1.java:9) */ ``` -如果你正常运行程序,没有任何特殊的断言标志,则不会发生任何事情。你需要在运行程序时显式启用断言。一种简单的方法是使用 **-ea** 标志, 它也可以表示为: **-enableassertion**, 这将运行程序并执行任何断言语句。 +如果你正常运行程序,没有任何特殊的断言标志,则不会发生任何事情。你需要在运行程序时显式启用断言。一种简单的方法是使用 **-ea** 标志, 它也可以这样拼写: **-enableassertion**, 这将运行程序并执行所有断言语句。 输出中并没有包含多少有用的信息。另一方面,如果你使用 **information-expression** , 将生成一条有用的消息作为异常堆栈跟踪的一部分。最有用的 **information-expression** 通常是一串针对程序员的文本: @@ -373,13 +373,13 @@ Shouldn't be null: arg s #### 使用断言进行契约式设计 -*契约式设计(DbC)*是 Eiffel 语言的发明者 Bertrand Meyer 提出的一个概念,通过确保对象遵循某些规则来帮助创建健壮的程序。这些规则是由正在解决的问题的性质决定的,这超出了编译器可以验证的范围。虽然断言没有直接实现 **DBC**(Eiffel 语言也是如此),但是它们创建了一种非正式的 DbC 编程风格。DbC 假定服务供应者与该服务的消费者或客户之间存在明确指定的契约。在面向对象编程中,服务通常由对象提供,对象的边界 — 供应者和消费者之间的划分 — 是对象类的接口。当客户端调用特定的公共方法时,它们希望该调用具有特定的行为:对象状态改变,以及一个可预测的返回值。 +*契约式设计(Design by Contract DbC)*是 Eiffel 语言的发明者 Bertrand Meyer 提出的一个概念,通过确保对象遵循某些规则来帮助创建健壮的程序。这些规则是由正在解决的问题的性质决定的,这超出了编译器可以验证的范围。虽然断言没有直接实现 **DBC**(Eiffel 语言也是如此),但是它们创建了一种非正式的 DbC 编程风格。DbC 假定服务供应者与该服务的消费者或客户之间存在明确指定的契约。在面向对象编程中,服务通常由对象提供,对象的边界 — 供应者和消费者之间的划分 — 是对象类的接口。当客户端调用特定的公共方法时,它们希望该调用具有特定的行为:对象状态改变,以及一个可预测的返回值。 **Meyer** 认为: 1.应该明确指定行为,就好像它是一个契约一样。 -2.通过实现某些运行时检查来保证这种行为,他将这些检查称为前置条件、后置条件和不变项。 +2.通过实现某些运行时检查来保证这种行为,他将这些检查称为**前置条件**、**后置条件**和**不变项**。 不管你是否同意,第一条总是对的,在大多数情况下,DbC 确实是一种有用的方法。(我认为,与任何解决方案一样,它的有用性也有界限。但如果你知道这些界限,你就知道什么时候去尝试。)尤其是,设计过程中一个有价值的部分是特定类 DbC 约束的表达式;如果无法指定约束,则你可能对要构建的内容了解得不够。 @@ -886,7 +886,7 @@ public class NonNullConstruction { ## 测试驱动开发 -之所以可以有测试驱动开发(TDD)这种开发方式,是因为如果你在设计和编写代码时考虑到了测试,那么你不仅可以写出可测试性更好的代码,而且还可以得到更好的代码设计。 一般情况下这个说法都是正确的。 一旦我想到“我将如何测试我的代码?”,这个想法将使我的代码产生变化,并且往往是从“可测试”转变为“可用”。 +之所以可以有*测试驱动开发(Test-Driven Development TDD)*这种开发方式,是因为如果你在设计和编写代码时考虑到了测试,那么你不仅可以写出可测试性更好的代码,而且还可以得到更好的代码设计。 一般情况下这个说法都是正确的。 一旦我想到“我将如何测试我的代码?”,这个想法将使我的代码产生变化,并且往往是从“可测试”转变为“可用”。 纯粹的 TDD 主义者会在实现新功能之前就为其编写测试,这称为测试优先的开发。 我们采用一个简易的示例程序来进行说明,它的功能是反转 **String** 中字符的大小写。 让我们随意添加一些约束:**String** 必须小于或等于30个字符,并且必须只包含字母,空格,逗号和句号(英文)。 From 79ce2a58df5c946c17fadc2c74003299a92350a7 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 10 Dec 2020 17:59:10 +0800 Subject: [PATCH 30/68] chapter 16 01 --- docs/book/16-Validating-Your-Code.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/book/16-Validating-Your-Code.md b/docs/book/16-Validating-Your-Code.md index 46a98e62..18c9819e 100644 --- a/docs/book/16-Validating-Your-Code.md +++ b/docs/book/16-Validating-Your-Code.md @@ -1037,7 +1037,7 @@ class DynamicStringInverterTests { 每个使用 **@TestFactory** 注释的方法都会生成一个 **DynamicTest** 对象的 **Stream**(通过 **testVersions()** ),每个 JUnit 都像常规的 **@Test** 方法一样执行。 -现在测试都已经准备好了,我们就可以开始实现 **StringInverter **了。 我们从一个仅返回其参数的假的实现类开始: +现在测试都已经准备好了,我们就可以开始实现 **StringInverter **了。 我们从一个仅返回其参数的形同虚设的实现类开始: ```java // validating/Inverter1.java @@ -1118,7 +1118,7 @@ public class Inverter4 implements StringInverter { 你将从测试输出中看到,每个版本的 **Inverter** 都几乎能通过所有测试。 当你在进行测试优先的开发时会有相同的体验。 -**DynamicStringInverterTests.java** 仅是为了显示 TDD 过程中不同 **StringInverter** 实现的开发。 通常,你只需编写一组如下所示的测试,并修改单个 **StringInverter** 类直到它满足所有测试: +**DynamicStringInverterTests.java** 仅是为了展示 TDD 过程中 **StringInverter** 的不同实现的开发。 通常,你只需编写一组如下所示的测试,并修改单个 **StringInverter** 类直到它满足所有测试: ```java // validating/tests/StringInverterTests.java @@ -1311,7 +1311,7 @@ public class SLF4JLevels { ### 使用 JDB 调试 -Java 调试器(JDB)是 JDK 内置的命令行工具。从调试的指令和命令行接口两方面看的话,JDB 至少从概念上是 GNU 调试器(GDB,受 Unix DB 的影响)的继承者。JDB 对于学习调试和执行简单的调试任务来说是有用的,而且知道只要安装了 JDK 就可以使用 JDB 是有帮助的。然而,对于大型项目来说,你可能想要一个图形化的调试器,这在后面会描述。 +Java 调试器(*Java Debugger JDB*)是 JDK 内置的命令行工具。从调试的指令和命令行接口两方面看的话,JDB 至少从概念上是 GNU 调试器(Gnu Debugger GDB,受 Unix DB 的影响)的继承者。JDB 对于学习调试和执行简单的调试任务来说是有用的,而且知道只要安装了 JDK 就可以使用 JDB 是有帮助的。然而,对于大型项目来说,你可能想要一个图形化的调试器,这在后面会描述。 假设你写了如下程序: @@ -1475,7 +1475,7 @@ SimpleDebugging.main(SimpleDebugging.java:20) 如果你发现自己正在过早优化的滑坡上,你可能浪费了几个月的时间(如果你雄心勃勃的话)。通常,一个简单直接的编码方法就足够好了。如果你进行了不必要的优化,就会使你的代码变得无谓的复杂和难以理解。 -基准测试意味着对代码或算法片段进行计时看哪个跑得更快,与下一节的分析和优化截然相反,分析优化是观察整个程序,找到程序中最耗时的部分。 +基准测试 **Benchmarking** 意味着对代码或算法片段进行计时看哪个跑得更快,与下一节的 **剖析和优化** 截然相反,分析优化是观察整个程序,找到程序中最慢的部分。 可以简单地对一个代码片段的执行计时吗?在像 C 这样直接的编程语言中,这个方法的确可行。在像 Java 这样拥有复杂的运行时系统的编程语言中,基准测试变得更有挑战性。为了生成可靠的数据,环境设置必须控制诸如 CPU 频率,节能特性,其他运行在相同机器上的进程,优化器选项等等。 @@ -1569,7 +1569,7 @@ parallelSetAll: 86 setAll: 39 ``` -**SplittableRandom** 是为并行算法设计的,它当然看起来比普通的 **Random** 在 **parallelSetAll()** 中运行得更快。 但是看上去还是比非并发的 **setAll()** 运行时间更长,有点难以置信(也许是真的,但我们不能通过一个坏的微基准测试得到这个结论)。 +**SplittableRandom** 是为并行算法设计的,它当然看起来比普通的 **Random** 在 **parallelSetAll()** 中运行得更快。 但是看上去还是比非并发的 **setAll()** 运行时间更长,有点难以置信(也许是真的,但我们不能通过一个坏的微基准测试来得到此结论)。 这只考虑了微基准测试的问题。Java 虚拟机 Hotspot 也非常影响性能。如果你在测试前没有通过运行代码给 JVM 预热,那么你就会得到“冷”的结果,不能反映出代码在 JVM 预热之后的运行速度(假如你运行的应用没有在预热的 JVM 上运行,你就可能得不到所预期的性能,甚至可能减缓速度)。 @@ -1738,7 +1738,7 @@ public class JMH2 { **setAll()/parallelSetAll()** 中工作的计算量起很大影响吗?在前面的例子中,我们所做的只有对数组的赋值操作,这可能是最简单的任务。所以即使 **N** 值变大,**N*Q** 也仍然没有达到巨大,所以看起来像是我们没有为并行提供足够的机会(JMH 提供了一种模拟变量 Q 的途径;如果想了解更多的话,可搜索 **Blackhole.consumeCPU**)。 -我们通过使方法 **f()** 中的任务变得更加复杂,从而产生更多的并行机会: +我们通过下面的方法 **f()** 中的任务变得更加复杂,从而产生更多的并行机会: ```java // validating/jmh/JMH3.java @@ -1903,7 +1903,7 @@ public class JMH3 { ## 重构 -技术负债是指迭代发展的软件中为了应急而生的丑陋解决方案从而导致设计难以理解,代码难以阅读的部分。特别是当你必须修改和增加新特性的时候,这会造成麻烦。 +技术负债是指迭代发展的软件中使用为了应急而生的丑陋解决方案,从而导致设计难以理解、代码难以阅读的部分。特别是当你必须修改和增加新特性的时候,这会造成麻烦。 重构可以矫正技术负债。重构的关键是它能改善代码设计,结构和可读性(因而减少代码负债),但是它不能改变代码的行为。 From 9e91e356ff721c18f5f0dc9e7d2f3434a9e4f38b Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 10 Dec 2020 18:03:32 +0800 Subject: [PATCH 31/68] chapter 17 00 --- docs/book/17-Files.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/17-Files.md b/docs/book/17-Files.md index 7a22b051..95abddbd 100644 --- a/docs/book/17-Files.md +++ b/docs/book/17-Files.md @@ -8,7 +8,7 @@ 这种"困难方式"的全部细节都在 [Appendix: I/O Streams](./Appendix-IO-Streams.md)。如果你读过这个部分,就会认同 Java 设计者毫不在意他们的使用者的体验这一观念。打开并读取文件对于大多数编程语言来说是非常常用的,由于 I/O 糟糕的设计以至于 很少有人能够在不依赖其他参考代码的情况下完成打开文件的操作。 -好像 Java 设计者终于意识到了 Java 使用者多年来的痛苦,在 Java7 中对此引入了巨大的改进。这些新元素被放在 **java.nio.file** 包下面,过去人们通常把 **nio** 中的 **n** 理解为 **new** 即新的 **io**,现在更应该当成是 **non-blocking** 非阻塞 **io**(**io**就是*input/output输入/输出*)。**java.nio.file** 库终于将 Java 文件操作带到与其他编程语言相同的水平。最重要的是 Java8 新增的 streams 与文件结合使得文件操作编程变得更加优雅。我们将看一下文件操作的两个基本组件: +好像 Java 设计者终于意识到了 Java 使用者多年来的痛苦,在 Java7 中对此引入了巨大的改进。这些新元素被放在 **java.nio.file** 包下面,过去人们通常把 **nio** 中的 **n** 理解为 **new** 即新的 **io**,如今却意味着 **non-blocking** 非阻塞 **io**(**io**就是*input/output输入/输出*)。**java.nio.file** 库终于将 Java 文件操作带到与其他编程语言相同的水平。最重要的是 Java8 新增的 streams 与文件结合使得文件操作编程变得更加优雅。我们将看一下文件操作的两个基本组件: 1. 文件或者目录的路径; 2. 文件本身。 From f2283935ede11f709af18dfafdfff4cb90980d1c Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 11 Dec 2020 14:58:06 +0800 Subject: [PATCH 32/68] chapter 17 01 --- docs/book/17-Files.md | 46 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/docs/book/17-Files.md b/docs/book/17-Files.md index 95abddbd..7351fbce 100644 --- a/docs/book/17-Files.md +++ b/docs/book/17-Files.md @@ -11,7 +11,7 @@ 好像 Java 设计者终于意识到了 Java 使用者多年来的痛苦,在 Java7 中对此引入了巨大的改进。这些新元素被放在 **java.nio.file** 包下面,过去人们通常把 **nio** 中的 **n** 理解为 **new** 即新的 **io**,如今却意味着 **non-blocking** 非阻塞 **io**(**io**就是*input/output输入/输出*)。**java.nio.file** 库终于将 Java 文件操作带到与其他编程语言相同的水平。最重要的是 Java8 新增的 streams 与文件结合使得文件操作编程变得更加优雅。我们将看一下文件操作的两个基本组件: 1. 文件或者目录的路径; -2. 文件本身。 +2. 文件自身。 ## 文件和目录路径 @@ -121,14 +121,14 @@ true */ ``` -我已经在这一章第一个程序的 **main()** 方法添加了第一行用于展示操作系统的名称,因此你可以看到不同操作系统之间存在哪些差异。理想情况下,差别会相对较小,并且使用 **/** 或者 **\\** 路径分隔符进行分隔。你可以看到我运行在Windows 10 上的程序输出。 +我已经在 **main()** 方法的第一行用于展示操作系统的名称,因此你可以看到不同操作系统之间存在哪些差异。理想情况下,差别会相对较小,诸如 **/** 还是 **\\** 路径分隔符进行分隔之类的。你可以看到我运行在Windows 10 上的程序输出。 -当 **toString()** 方法生成完整形式的路径,你可以看到 **getFileName()** 方法总是返回当前文件名。 -通过使用 **Files** 工具类(我们接下来将会更多地使用它),可以测试一个文件是否存在,测试是否是一个"普通"文件还是一个目录等等。"Nofile.txt"这个示例展示我们描述的文件可能并不在指定的位置;这样可以允许你创建一个新的路径。"PathInfo.java"存在于当前目录中,最初它只是没有路径的文件名,但它仍然被检测为"存在"。一旦我们将其转换为绝对路径,我们将会得到一个从"C:"盘(因为我们是在Windows机器下进行测试)开始的完整路径,现在它也拥有一个父路径。“真实”路径的定义在文档中有点模糊,因为它取决于具体的文件系统。例如,如果文件名不区分大小写,即使路径由于大小写的缘故而不是完全相同,也可能得到肯定的匹配结果。在这样的平台上,**toRealPath()** 将返回实际情况下的 **Path**,并且还会删除任何冗余元素。 + **toString()** 生成完整路径, **getFileName()** 方法总是返回当前文件名。 +通过使用 **Files** 工具类(我们接下来将会更多地使用它),可以测试一个文件是否存在、是否"普通"文件、是否目录等等。"Nofile.txt"这个示例展示我们描述的文件可能并不在指定的位置;这样就允许你创建一个新的路径。"PathInfo.java"存在于当前目录中,最初它只是没有路径的文件名,但它仍然被检测为"存在"。一旦我们将其转换为绝对路径,我们将会得到一个从"C:"盘(因为我们是在Windows机器下进行测试)开始的完整路径,现在它也拥有一个父路径。“真实”路径的定义在文档中有点模糊,因为它取决于具体的文件系统。例如,如果文件名不区分大小写,即使路径由于大小写的缘故而不是完全相同,也可能得到肯定的匹配结果。在这样的平台上,**toRealPath()** 将返回实际情况下的 **Path**,并且还会删除任何冗余元素。 这里你会看到 **URI** 看起来只能用于描述文件,实际上 **URI** 可以用于描述更多的东西;通过 [维基百科](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) 可以了解更多细节。现在我们成功地将 **URI** 转为一个 **Path** 对象。 -最后,你会在 **Path** 中看到一些有点欺骗的东西,这就是调用 **toFile()** 方法会生成一个 **File** 对象。听起来似乎可以得到一个类似文件的东西(毕竟被称为 **File** ),但是这个方法的存在仅仅是为了向后兼容。虽然看上去应该被称为"路径",实际上却应该表示目录或者文件本身。这是个非常草率并且令人困惑的命名,但是由于 **java.nio.file** 的存在我们可以安全地忽略它的存在。 +最后,你会在 **Path** 中看到一些有点欺骗性的定义,这就是调用 **toFile()** 生成的 **File** 对象。这听起来好像得到了一个类似文件的东西(毕竟被称为 **File** ),但是这种描述仅仅是为了兼容老版本。**File** 对象 实际上表示文件或目录本身——应该被称为"路径**Path**",这是个非常草率并且令人困惑的命名,但是由于 **java.nio.file** 的存在我们可以安全地忽略它的存在。 (这个 **File** 对象是 **java.io.File**, 不兼容旧版本一般用不上) ### 选取路径部分片段 **Path** 对象可以非常容易地生成路径的某一部分: @@ -143,8 +143,8 @@ public class PartsOfPaths { Path p = Paths.get("PartsOfPaths.java").toAbsolutePath(); for(int i = 0; i < p.getNameCount(); i++) System.out.println(p.getName(i)); - System.out.println("ends with '.java': " + - p.endsWith(".java")); + System.err.println("ends with '.java'1: " + p.endsWith(".java")); //false + System.err.println("ends with '.java'2: " + p.endsWith("PartsOfPaths.java")); //true for(Path pp : p) { System.out.print(pp + ": "); System.out.print(p.startsWith(pp) + " : "); @@ -177,7 +177,7 @@ Starts with C:\ true */ ``` -可以通过 **getName()** 来索引 **Path** 的各个部分,直到达到上限 **getNameCount()**。**Path** 也实现了 **Iterable** 接口,因此我们也可以通过增强的 for-each 进行遍历。请注意,即使路径以 **.java** 结尾,使用 **endsWith()** 方法也会返回 **false**。这是因为使用 **endsWith()** 比较的是整个路径部分,而不会包含文件路径的后缀。通过使用 **startsWith()** 和 **endsWith()** 也可以完成路径的遍历。但是我们可以看到,遍历 **Path** 对象并不包含根路径,只有使用 **startsWith()** 检测根路径时才会返回 **true**。 +对于 **Path** 中的路径分隔符分隔的几个部分的名字(组件名),可通过 **getName(i)** 来索引,直至上限 **getNameCount()**。还可以通过 for-in 循环进行遍历 (**Path** 也实现了 **Iterable** 接口)。请注意,即使路径的确以 **.java** 结尾,使用 **endsWith()** 也返回 **false**。这是因为使用 **endsWith()** 比较的是 **Path** 的各个完整的组件名,而不仅是某个组件名的子串**.java**。这里展示了使用 **startsWith()** 和 **endsWith()** 在 for-in 循环中检测 **Path** 的当前部分。但是我们可以看到,遍历 **Path** 对象没有包含根路径(C盘D盘之类的盘符),只有使用 **startsWith()** 检测 **getRoot()** 时才会返回 **true**。 ### 路径分析 **Files** 工具类包含一系列完整的方法用于获得 **Path** 相关的信息。 @@ -239,10 +239,12 @@ SymbolicLink: false 在调用最后一个测试方法 **getPosixFilePermissions()** 之前我们需要确认一下当前文件系统是否支持 **Posix** 接口,否则会抛出运行时异常。 ### **Paths**的增减修改 -我们必须能通过对 **Path** 对象增加或者删除一部分来构造一个新的 **Path** 对象。我们使用 **relativize()** 移除 **Path** 的根路径,使用 **resolve()** 添加 **Path** 的尾路径(不一定是“可发现”的名称)。 +我们必须能通过对 **Path** 对象增加或者删除一部分来构造一个新的 **Path** 对象。 +删除:使用 **relativize()** 移除 **Path** 的根路径; +添加:使用 **resolve()** 添加到 **Path** 的末尾(不一定是“可发现”的名称)。(可以是不存在的目录和文件) -对于下面代码中的示例,我使用 **relativize()** 方法从所有的输出中移除根路径,部分原因是为了示范,部分原因是为了简化输出结果,这说明你可以使用该方法将绝对路径转为相对路径。 -这个版本的代码中包含 **id**,以便于跟踪输出结果: +对于下面代码中的示例,我使用 **relativize()** 方法从所有的输出中移除根路径,为了示范,也为了简化输出结果。事实证明只有绝对**isAbsolute()**才能使用 **relativize()** 方法。 +这个版本的代码中包含 **id** 以便跟踪输出结果: ```java // files/AddAndSubtractPaths.java @@ -324,7 +326,7 @@ C:\Users\Bruce\Documents\GitHub\onjava\ ExtractedExamples\files\nonexistent */ ``` -我还为 **toRealPath()** 添加了更多的测试,这是为了扩展和规则化,防止路径不存在时抛出运行时异常。 +我还对 **toRealPath()** 做了进一步测试,它会一直扩展和规则化 **Path** ,路径不存在时抛出运行时异常。 @@ -357,16 +359,16 @@ public class RmDir { } } ``` -删除目录树的方法实现依赖于 **Files.walkFileTree()**,"walking" 目录树意味着遍历每个子目录和文件。*Visitor* 设计模式提供了一种标准机制来访问集合中的每个对象,然后你需要提供在每个对象上执行的操作。 +删除目录树的方法实现依赖于 **Files.walkFileTree()**,"walking" 目录树意味着遍历每个子目录和文件。 设计模式—— *访问者模式* *Visitor* 提供了一种标准机制来访问集合中的每个对象,然后需要你提供(实现)在每个对象上执行的操作。 此操作的定义取决于实现的 **FileVisitor** 的四个抽象方法,包括: - 1. **preVisitDirectory()**:在访问目录中条目之前在目录上运行。 + 1. **preVisitDirectory()**:在目录上运行,在其内容被访问之前。 2. **visitFile()**:运行目录中的每一个文件。 3. **visitFileFailed()**:调用无法访问的文件。 - 4. **postVisitDirectory()**:在访问目录中条目之后在目录上运行,包括所有的子目录。 + 4. **postVisitDirectory()**:在目录上运行,在其内容(包括所有的子目录)被访问之后。 -为了简化,**java.nio.file.SimpleFileVisitor** 提供了所有方法的默认实现。这样,在我们的匿名内部类中,我们只需要重写非标准行为的方法:**visitFile()** 和 **postVisitDirectory()** 实现删除文件和删除目录。两者都应该返回标志位决定是否继续访问(这样就可以继续访问,直到找到所需要的)。 -作为探索目录操作的一部分,现在我们可以有条件地删除已存在的目录。在以下例子中,**makeVariant()** 接受基本目录测试,并通过旋转部件列表生成不同的子目录路径。这些旋转与路径分隔符 **sep** 使用 **String.join()** 贴在一起,然后返回一个 **Path** 对象。 +为了简化,**java.nio.file.SimpleFileVisitor** 提供了所有方法的默认实现。这样,在我们的匿名内部类中,我们只需要重写非标准行为的方法:**visitFile()** 和 **postVisitDirectory()** 实现删除文件和删除目录。两者都返回“继续访问”标志(这样就可以一直访问,直至找到所需为止)。 +作为我们探索创建和填充目录的一部分,现在我们可以有条件地删除已存在的目录。在以下例子中,**makeVariant()** 接受基本目录测试,并通过旋转组件名列表生成不同的子目录路径。这些旋转(组件名)和路径分隔符 **sep** 用 **String.join()** 粘贴在一起,然后返回一个 **Path** 对象。 ```java // files/Directories.java @@ -461,13 +463,15 @@ test\foo\bar\baz\bag\File.txt test\Hello.txt */ ``` -首先,**refreshTestDir()** 用于检测 **test** 目录是否已经存在。若存在,则使用我们新工具类 **rmdir()** 删除其整个目录。检查是否 **exists** 是多余的,但我想说明一点,因为如果你对于已经存在的目录调用 **createDirectory()** 将会抛出异常。**createFile()** 使用参数 **Path** 创建一个空文件; **resolve()** 将文件名添加到 **test Path** 的末尾。 +首先,**refreshTestDir()** 用于检测 **test** 目录是否已经存在。若存在,则使用我们新工具类 **rmdir()** 删除其整个目录。在这里检查是否 **exists()** 做了2次,是冗余的,这是因为我是想阐明,如果你对于已存在的目录调用 **createDirectory()** 将会抛出异常。**createFile()** 以 **Path** 为参数创建了一个空文件; **resolve()** 将文件名添加到该目录路径的末尾。 -我们尝试使用 **createDirectory()** 来创建多级路径,但是这样会抛出异常,因为这个方法只能创建单级路径。我已经将 **populateTestDir()** 作为一个单独的方法,因为它将在后面的例子中被重用。对于每一个变量 **variant**,我们都能使用 **createDirectories()** 创建完整的目录路径,然后使用此文件的副本以不同的目标名称填充该终端目录。然后我们使用 **createTempFile()** 生成一个临时文件。 +我们尝试使用 **createDirectory()** 来创建多级路径,但是这样会抛出异常,因为这个方法只能创建单级路径。 -在调用 **populateTestDir()** 之后,我们在 **test** 目录下面创建一个临时目录。请注意,**createTempDirectory()** 只有名称的前缀选项。与 **createTempFile()** 不同,我们再次使用它将临时文件放入新的临时目录中。你可以从输出中看到,如果未指定后缀,它将默认使用".tmp"作为后缀。 +我已经将 **populateTestDir()** 作为一个单独的方法,因为它将在后面的例子中被重用。对于每一个 **variant** ( **Path** 对象),我们都能使用 **createDirectories()** 创建完整的目录路径(目录树),然后使用此文件(Directories.java)的拷贝以另一个的名称(File.txt)填充该目录树的终端。然后我们使用 **createTempFile()** 生成一个临时文件。(这里我们给 **createTempFile()** 传的参数是两个 **null** ) -为了展示结果,我们首次使用看起来很有希望的 **newDirectoryStream()**,但事实证明这个方法只是返回 **test** 目录内容的 Stream 流,并没有更多的内容。要获取目录树的全部内容的流,请使用 **Files.walk()**。 +在调用 **populateTestDir()** 之后,下一步的操作是在 **test** 目录下面创建一个临时目录。请注意,**createTempDirectory()** 只有名称的前缀(设置)选项,这一点和 **createTempFile()** 不同。再下一步,我们使用 **createTempFile()** 将临时文件放入新的临时目录中。你可以从输出中看到,如果未指定后缀,默认使用" **.tmp** "作为后缀。 + +为了列出上述操作的结果,我们开始试用很有前途的 **newDirectoryStream()**,但事实证明这个方法只是流化(stream化) **test** 这一级的目录内容,并没有再深入。要获取目录树的全部内容的流,请使用 **Files.walk()**。 From 4d868367a7adca38dcfd2637fcf359b4400d24bd Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 11 Dec 2020 17:11:34 +0800 Subject: [PATCH 33/68] chapter 17 02 --- docs/book/17-Files.md | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/docs/book/17-Files.md b/docs/book/17-Files.md index 7351fbce..ab24b63a 100644 --- a/docs/book/17-Files.md +++ b/docs/book/17-Files.md @@ -463,7 +463,7 @@ test\foo\bar\baz\bag\File.txt test\Hello.txt */ ``` -首先,**refreshTestDir()** 用于检测 **test** 目录是否已经存在。若存在,则使用我们新工具类 **rmdir()** 删除其整个目录。在这里检查是否 **exists()** 做了2次,是冗余的,这是因为我是想阐明,如果你对于已存在的目录调用 **createDirectory()** 将会抛出异常。**createFile()** 以 **Path** 为参数创建了一个空文件; **resolve()** 将文件名添加到该目录路径的末尾。 +首先,**refreshTestDir()** 用于检测 **test** 目录是否已经存在。若存在,则使用我们新工具类 **rmdir()** 删除其整个目录。在这里检查是否 **exists()** 做了2次,是重复的,这是因为我是想阐明,如果你对于已存在的目录调用 **createDirectory()** 将会抛出异常。**createFile()** 以 **Path** 为参数创建了一个空文件; **resolve()** 将文件名添加到该目录路径的末尾。 我们尝试使用 **createDirectory()** 来创建多级路径,但是这样会抛出异常,因为这个方法只能创建单级路径。 @@ -476,7 +476,11 @@ test\Hello.txt ## 文件系统 -为了完整起见,我们需要一种方法查找文件系统相关的其他信息。在这里,我们使用静态的 **FileSystems** 工具类获取"默认"的文件系统,但你同样也可以在 **Path** 对象上调用 **getFileSystem()** 以获取创建该 **Path** 的文件系统。你可以获得给定 *URI* 的文件系统,还可以构建新的文件系统(对于支持它的操作系统)。 +为了完整性,我们需要一种方法来找出有关文件系统的其余信息。在这里,我们可以: +- 使用静态的 **FileSystems** 工具类获取"默认"的文件系统;`FileSystems.getDefault()` +- 对 **Path** 对象调用 **getFileSystem()** 以获取创建该 **Path** 的文件系统;`xx.getFileSystem()` +- 获得给定 *URI* 对应的文件系统;`FileSystems.getFileSystem(URI)` +- 构建新的文件系统(对于支持该操作的操作系统)。`FileSystems.newFileSystem(URI,map)` ```java // files/FileSystemDemo.java import java.nio.file.*; @@ -518,12 +522,12 @@ sun.nio.fs.WindowsFileSystemProvider@6d06d69c File Attribute Views: [owner, dos, acl, basic, user] */ ``` -一个 **FileSystem** 对象也能生成 **WatchService** 和 **PathMatcher** 对象,将会在接下来两章中详细讲解。 +一个 **FileSystem** 对象也能生成 **WatchService** 和 **PathMatcher** 对象,会在接下来两节中讲解。 ## 路径监听 -通过 **WatchService** 可以设置一个进程对目录中的更改做出响应。在这个例子中,**delTxtFiles()** 作为一个单独的任务执行,该任务将遍历整个目录并删除以 **.txt** 结尾的所有文件,**WatchService** 会对文件删除操作做出反应: +通过 **WatchService** 可以设置一个进程,对目录中的更改做出响应。在这个例子中,**delTxtFiles()** 作为一个单独的任务执行,该任务将遍历整个目录并删除以 **.txt** 结尾的所有文件,**WatchService** 会对文件删除操作做出反应: ```java // files/PathWatcher.java @@ -585,15 +589,17 @@ evt.kind(): ENTRY_DELETE */ ``` -**delTxtFiles()** 中的 **try** 代码块看起来有些多余,因为它们捕获的是同一种类型的异常,外部的 **try** 语句似乎已经足够了。然而出于某种原因,Java 要求两者都必须存在(这也可能是一个 bug)。还要注意的是在 **filter()** 中,我们必须显式地使用 **f.toString()** 转为字符串,否则我们调用 **endsWith()** 将会与整个 **Path** 对象进行比较,而不是路径名称字符串的一部分进行比较。 +**delTxtFiles()** 中的 **try** 代码块看起来有重复,因为它们捕获的是同一种类型的异常,似乎只要外部的 **try** 语句已经足够了。然而出于某种原因,Java 要求两者都在(这也可能是一个 bug)。还要注意的是在 **filter()** 中,我们必须显式地使用 **f.toString()** 转为字符串,否则 **endsWith()** 会与整个 **Path** 对象进行比较,而不是只比较路径的字符串名称这部分。 -一旦我们从 **FileSystem** 中得到了 **WatchService** 对象,我们将其注册到 **test** 路径以及我们感兴趣的项目的变量参数列表中,可以选择 **ENTRY_CREATE**,**ENTRY_DELETE** 或 **ENTRY_MODIFY**(其中创建和删除不属于修改)。 +一旦我们从 **FileSystem** 中得到了 **WatchService** 对象,就将 **WatchService** 对象及感兴趣项的参数列表一起注册到 **test** 对象,参数列表可选 **ENTRY_CREATE**,**ENTRY_DELETE** 或 **ENTRY_MODIFY**(其中创建 *CREATE* 和删除 *DELETE* 不属于修改)。 -因为接下来对 **watcher.take()** 的调用会在发生某些事情之前停止所有操作,所以我们希望 **deltxtfiles()** 能够并行运行以便生成我们感兴趣的事件。为了实现这个目的,我通过调用 **Executors.newSingleThreadScheduledExecutor()** 产生一个 **ScheduledExecutorService** 对象,然后调用 **schedule()** 方法传递所需函数的方法引用,并且设置在运行之前应该等待的时间。 +因为接下来对 **watcher.take()** (开始监听事件)的调用会在监听到增删改之前一直阻塞线程,所以我们希望 **deltxtfiles()** 能够并行运行以便生成我们感兴趣的事件。(删完再监听,晚了,一直监听不到;先监听再删,删操作被阻塞。因此只能多线程并发) + +为了这一目的,我通过调用 **Executors.newSingleThreadScheduledExecutor()** 产生一个 **ScheduledExecutorService** 对象,然后调用 **schedule()** 方法传递所需函数的方法引用,并设置在开始监听 **watcher.take()** 之后延时几秒发生。 此时,**watcher.take()** 将等待并阻塞在这里。当目标事件发生时,会返回一个包含 **WatchEvent** 的 **Watchkey** 对象。展示的这三种方法是能对 **WatchEvent** 执行的全部操作。 -查看输出的具体内容。即使我们正在删除以 **.txt** 结尾的文件,在 **Hello.txt** 被删除之前,**WatchService** 也不会被触发。你可能认为,如果说"监视这个目录",自然会包含整个目录和下面子目录,但实际上:只会监视给定的目录,而不是下面的所有内容。如果需要监视整个树目录,必须在整个树的每个子目录上放置一个 **Watchservice**。 +查看输出的具体内容。即使我们正在删除以 **.txt** 结尾的文件,在 **Hello.txt** 被删除之前,**WatchService** 也不会被触发。你可能认为,如果说"监视这个目录",自然会包含整个目录和下面子目录,但实际上:只会监视给定的目录,不包括下面的。如果需要监视整个树目录,必须在整个树的每个子目录上放置一个 **Watchservice**。 ```java // files/TreeWatcher.java @@ -648,12 +654,12 @@ evt.kind(): ENTRY_DELETE */ ``` -在 **watchDir()** 方法中给 **WatchSevice** 提供参数 **ENTRY_DELETE**,并启动一个独立的线程来监视该**Watchservice**。这里我们没有使用 **schedule()** 进行启动,而是使用 **submit()** 启动线程。我们遍历整个目录树,并将 **watchDir()** 应用于每个子目录。现在,当我们运行 **deltxtfiles()** 时,其中一个 **Watchservice** 会检测到每一次文件删除。 +在 **watchDir()** 方法中给 **WatchSevice** 提供参数 **ENTRY_DELETE**,并启动一个独立的线程来监视该**Watchservice**。这里我们没有使用 **schedule()** 进行启动,而是使用 **submit()** 启动线程。我们遍历整个目录树,并将 **watchDir()** 应用于每个子目录。现在,当我们运行 **deltxtfiles()** 时,其中的一个 **Watchservice** 会检测到最开始的一次删除。 ## 文件查找 -到目前为止,为了找到文件,我们一直使用相当粗糙的方法,在 `path` 上调用 `toString()`,然后使用 `string` 操作查看结果。事实证明,`java.nio.file` 有更好的解决方案:通过在 `FileSystem` 对象上调用 `getPathMatcher()` 获得一个 `PathMatcher`,然后传入您感兴趣的模式。模式有两个选项:`glob` 和 `regex`。`glob` 比较简单,实际上功能非常强大,因此您可以使用 `glob` 解决许多问题。如果您的问题更复杂,可以使用 `regex`,这将在接下来的 `Strings` 一章中解释。 +到目前为止,为了找到文件,我们一直使用相当粗糙的方法,在 `path` 上调用 `toString()`,然后使用 `string` 相关操作查看结果。事实证明,`java.nio.file` 有更好的解决方案:`PathMatcher`。其通过在 `FileSystem` 对象上调用 `getPathMatcher()` 获得,然后传入您感兴趣的模式。模式有两个选项:`glob` 和 `regex`。`glob` 看似简单实际上功能十分强大,因此您可以使用 `glob` 解决许多问题。如果您的问题更复杂,可以使用 `regex`(这将在接下来的 `Strings` 一章中解释)。 在这里,我们使用 `glob` 查找以 `.tmp` 或 `.txt` 结尾的所有 `Path`: @@ -716,11 +722,11 @@ dir.tmp */ ``` -在 `matcher` 中,`glob` 表达式开头的 `**/` 表示“当前目录及所有子目录”,这在当你不仅仅要匹配当前目录下特定结尾的 `Path` 时非常有用。单 `*` 表示“任何东西”,然后是一个点,然后大括号表示一系列的可能性---我们正在寻找以 `.tmp` 或 `.txt` 结尾的东西。您可以在 `getPathMatcher()` 文档中找到更多详细信息。 +在 `matcher` 定义中,`glob` 表达式开头的 `**/` 表示“当前目录及所有子目录”,这在当你不仅仅要匹配当前目录下特定结尾的 `Path` 时非常有用。单 `*` 表示“任何东西”,然后是一个点,然后大括号表示一系列的可能性---我们正在寻找以 `.tmp` 或 `.txt` 结尾的东西。您可以在 `getPathMatcher()` 文档中找到更多详细信息。 -`matcher2` 只使用 `*.tmp`,通常不匹配任何内容,但是添加 `map()` 操作会将完整路径减少到末尾的名称。 +`matcher2` 只使用 `*.tmp`,通常不匹配任何内容,但是添加 `map()` 操作会将完整路径减少到末尾的名称 ( 因此现在有匹配内容了 )。 -注意,在这两种情况下,输出中都会出现 `dir.tmp`,即使它是一个目录而不是一个文件。要只查找文件,必须像在最后 `files.walk()` 中那样对其进行筛选。 +注意,在这两种情况下,输出中都会出现 `dir.tmp`,即使它是目录而不是文件。要只查找文件,必须像在最后 `files.walk()` 中那样对其进行筛选—— `.filter(Files::isRegularFile)`。 ## 文件读写 From 3d9aa3432cfa6662c9edfe399b4d36bd5d0c4c8b Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 11 Dec 2020 17:53:37 +0800 Subject: [PATCH 34/68] chapter 17 03 --- docs/book/17-Files.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/book/17-Files.md b/docs/book/17-Files.md index ab24b63a..4a7df94b 100644 --- a/docs/book/17-Files.md +++ b/docs/book/17-Files.md @@ -471,7 +471,7 @@ test\Hello.txt 在调用 **populateTestDir()** 之后,下一步的操作是在 **test** 目录下面创建一个临时目录。请注意,**createTempDirectory()** 只有名称的前缀(设置)选项,这一点和 **createTempFile()** 不同。再下一步,我们使用 **createTempFile()** 将临时文件放入新的临时目录中。你可以从输出中看到,如果未指定后缀,默认使用" **.tmp** "作为后缀。 -为了列出上述操作的结果,我们开始试用很有前途的 **newDirectoryStream()**,但事实证明这个方法只是流化(stream化) **test** 这一级的目录内容,并没有再深入。要获取目录树的全部内容的流,请使用 **Files.walk()**。 +为了列出上述操作的结果,我们开始试用很有前途的 **newDirectoryStream()**,但事实证明这个方法只是流式处理了(stream化) **test** 这一级的目录内容,并没有再深入。要获取目录树的全部内容的流,请使用 **Files.walk()**。 @@ -730,11 +730,11 @@ dir.tmp ## 文件读写 -此时,我们可以对路径和目录做任何事情。 现在让我们看一下操纵文件本身的内容。 +到此,我们可以对路径和目录做任何事情。 现在让我们看一下如何操纵文件本身的内容。 如果一个文件很“小”,也就是说“它运行得足够快且占用内存小”,那么 `java.nio.file.Files` 类中的实用程序将帮助你轻松读写文本和二进制文件。 -`Files.readAllLines()` 一次读取整个文件(因此,“小”文件很有必要),产生一个`List`。 对于示例文件,我们将重用`streams/Cheese.dat`: +`Files.readAllLines()` 一次读取整个文件(因此,“小”文件很有必要),产生一个`List`。 作为例子,我们又重用`streams/Cheese.dat`: ```java // files/ListOfLines.java @@ -798,13 +798,13 @@ Cheese.txt: 199 一个 `List` 被写入文件,任何 `Iterable` 对象也可以这么做。 -如果文件大小有问题怎么办? 比如说: +如果文件大小有问题怎么办? 比如: 1. 文件太大,如果你一次性读完整个文件,你可能会耗尽内存。 -2. 您只需要在文件的中途工作以获得所需的结果,因此读取整个文件会浪费时间。 +2. 您只需要通过文件进行局部操作就可以得到您想要的结果,因此读取整个文件会浪费时间。 -`Files.lines()` 方便地将文件转换为行的 `Stream`: +`Files.lines()` 方便地将文件转换以"行"为元素的 `Stream`: ```java // files/ReadLineStream.java @@ -823,9 +823,9 @@ public class ReadLineStream { */ ``` -这对本章中第一个示例代码做了流式处理,跳过 13 行,然后选择下一行并将其打印出来。 +这对本章开头的示例代码`PathInfo.java`做了流式处理,跳过 13 行,然后选择下一行并将其打印出来。 -`Files.lines()` 对于把文件处理行的传入流时非常有用,但是如果你想在 `Stream` 中读取,处理或写入怎么办?这就需要稍微复杂的代码: +`Files.lines()` 对于把文件作为传入的行流处理非常有用,但是如果你想读取,处理或写入全在一个 `Stream` 中怎么办?这就需要稍微复杂的代码: ```java // files/StreamInAndOut.java @@ -855,7 +855,7 @@ public class StreamInAndOut { ## 本章小结 -虽然本章对文件和目录操作做了相当全面的介绍,但是仍然有没被介绍的类库中的功能——一定要研究 `java.nio.file` 的 Javadocs,尤其是 `java.nio.file.Files` 这个类。 +尽管本章对文件和目录操作做了相当全面的介绍,但还有类库中的功能未被介绍——一定要研究 `java.nio.file` 的 Javadocs,尤其是 `java.nio.file.Files` 这个类。 Java 7 和 8 对于处理文件和目录的类库做了大量改进。如果您刚刚开始使用 Java,那么您很幸运。在过去,它令人非常不愉快,我确信 Java 设计者以前对于文件操作不够重视才没做简化。对于初学者来说这是一件很棒的事,对于教学者来说也一样。我不明白为什么花了这么长时间来解决这个明显的问题,但不管怎么说它被解决了,我很高兴。使用文件现在很简单,甚至很有趣,这是你以前永远想不到的。 From 5ad7b0ae2aa81011774a0fb33938d87800173a49 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 11 Dec 2020 17:58:02 +0800 Subject: [PATCH 35/68] chapter 17 end --- docs/book/15-Exceptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/15-Exceptions.md b/docs/book/15-Exceptions.md index b8b2da2b..a49b2ff0 100644 --- a/docs/book/15-Exceptions.md +++ b/docs/book/15-Exceptions.md @@ -21,7 +21,7 @@ Java 中的异常处理的目的——通过使用比目前更少的代码来简 ## 异常概念 -C 以及其他早期语言常常具有多种错误处理模式,这些模式往往建立在约定俗成的基础之上,而并不属于语言的一部分。通常会返回某个特殊值或者设置某个标志,并且假定接收者将对这个返回值或标志进行检查,以判定是否发生了错误。然而,随着时间的推移,人们发现,使用lib库程序员们会觉得自己无敌:“对,错误也许会发生,但那是别人造成的,不是我的代码问题”。所以,程序员不去检查错误情形也就不足为奇了(何况对某些错误情形的检查确实很无聊)。如果在每次调用方法的时候都彻底进行错误排查,代码很可能会变成难以阅读的噩梦。但由于程序员还仍然用这些语言(C 以及其他早期语言)拼凑系统,所以他们拒绝承认这样一个事实:对于构造大型、健壮、可维护的程序而言,这种错误处理模式已经成为了主要障碍。 +C 以及其他早期语言常常具有多种错误处理模式,这些模式往往建立在约定俗成的基础之上,而并不属于语言的一部分。通常会返回某个特殊值或者设置某个标志,并且假定接收者将对这个返回值或标志进行检查,以判定是否发生了错误。然而,随着时间的推移,人们发现,使用lib库的程序员们会觉得自己无敌:“对,错误也许会发生,但那是别人造成的,不是我的代码问题”。所以,程序员不去检查错误情形也就不足为奇了(何况对某些错误情形的检查确实很无聊)。如果在每次调用方法的时候都彻底进行错误排查,代码很可能会变成难以阅读的噩梦。但由于程序员还仍然用这些语言(C 以及其他早期语言)拼凑系统,所以他们拒绝承认这样一个事实:对于构造大型、健壮、可维护的程序而言,这种错误处理模式已经成为了主要障碍。 解决的办法是,用强制规定的形式来消除错误处理过程中随心所欲的因素。这种做法由来已久,对异常处理的实现可以追溯到 20 世纪 60 年代的操作系统,甚至于 BASIC 语言中的“on error goto”语句。而 C++的异常处理机制基于 Ada,Java 中的异常处理机制则建立在 C++ 的基础之上(尽管看上去更像 Object Pascal)。 From 1c460fcf267ac166dbd1a8ec1389e534db4172bb Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Mon, 14 Dec 2020 10:00:02 +0800 Subject: [PATCH 36/68] chapter 17 fix 00 --- docs/book/14-Streams.md | 2 +- docs/book/16-Validating-Your-Code.md | 2 +- docs/book/17-Files.md | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md index ec88dddc..fbb7b87b 100644 --- a/docs/book/14-Streams.md +++ b/docs/book/14-Streams.md @@ -984,7 +984,7 @@ class FunctionMap3 { 17.000000 1.900000 0.230000 ``` -遗憾的是,Java 设计者并没有尽一点努力去消除基本类型。 +遗憾的是,Java 设计者并没有尽任何努力去消除基本类型。 ### 在 `map()` 中组合流 diff --git a/docs/book/16-Validating-Your-Code.md b/docs/book/16-Validating-Your-Code.md index 18c9819e..5b41625b 100644 --- a/docs/book/16-Validating-Your-Code.md +++ b/docs/book/16-Validating-Your-Code.md @@ -1618,7 +1618,7 @@ public class JMH1 { } ``` -“forks” 的默认值是 10,意味着每个测试都运行 10 次。为了减少运行时间,这里使用了 **@Fork** 注解来减少这个次数到 1。我还使用了 **@Warmup** 和 **@Measurement** 注解将它们默认的运行次数从 20 减少到 5 次。尽管这降低了整体的准确率,但是结果几乎与使用默认值相同。可以尝试将 **@Warmup**、**@Measurement** 和 **@Fork** 都注释掉然后看使用它们的默认值,结果会有多大显著的差异;一般来说,你应该只能看到长期运行的测试使错误因素减少,而结果没有多大变化。 +“forks” 的默认值是 10,意思是每次测试同时开了 10 个进程运行。为了加速,这里使用了 **@Fork** 注解来减少这个次数到 1 (表示一个进程)。我还使用了 **@Warmup** 和 **@Measurement** 注解,将预热次数和测试次数从默认的 20 减少到 5 次。尽管这降低了整体的准确率,但是结果几乎与使用默认值相同。可以尝试将 **@Warmup**、**@Measurement** 和 **@Fork** 都注释掉然后看使用它们的默认值,看看结果会有多大显著的差异;一般来说,你应该只能看到长期运行的测试减少了误差,而结果变化不大。 需要使用显式的 gradle 命令才能运行基准测试(在示例代码的根目录处运行)。这能防止耗时的基准测试运行其他的 **gradlew** 命令: diff --git a/docs/book/17-Files.md b/docs/book/17-Files.md index 4a7df94b..8184bfee 100644 --- a/docs/book/17-Files.md +++ b/docs/book/17-Files.md @@ -595,7 +595,7 @@ evt.kind(): ENTRY_DELETE 因为接下来对 **watcher.take()** (开始监听事件)的调用会在监听到增删改之前一直阻塞线程,所以我们希望 **deltxtfiles()** 能够并行运行以便生成我们感兴趣的事件。(删完再监听,晚了,一直监听不到;先监听再删,删操作被阻塞。因此只能多线程并发) -为了这一目的,我通过调用 **Executors.newSingleThreadScheduledExecutor()** 产生一个 **ScheduledExecutorService** 对象,然后调用 **schedule()** 方法传递所需函数的方法引用,并设置在开始监听 **watcher.take()** 之后延时几秒发生。 +为了这一目的,我通过调用 **Executors.newSingleThreadScheduledExecutor()** 产生一个 **ScheduledExecutorService** 对象,然后调用 **schedule()** 方法传递所需函数的方法引用,并设置在开始监听( **watcher.take()** )之后延时(250ms)发生。 此时,**watcher.take()** 将等待并阻塞在这里。当目标事件发生时,会返回一个包含 **WatchEvent** 的 **Watchkey** 对象。展示的这三种方法是能对 **WatchEvent** 执行的全部操作。 @@ -804,7 +804,7 @@ Cheese.txt: 199 2. 您只需要通过文件进行局部操作就可以得到您想要的结果,因此读取整个文件会浪费时间。 -`Files.lines()` 方便地将文件转换以"行"为元素的 `Stream`: +`Files.lines()` 方便地将文件转换以 **"行"** 为单位元素的 `Stream`: ```java // files/ReadLineStream.java @@ -823,9 +823,9 @@ public class ReadLineStream { */ ``` -这对本章开头的示例代码`PathInfo.java`做了流式处理,跳过 13 行,然后选择下一行并将其打印出来。 +这对本章开头的示例代码`PathInfo.java`做了流式处理,跳过 13 **行** ,然后选择下一行并将其打印出来。 -`Files.lines()` 对于把文件作为传入的行流处理非常有用,但是如果你想读取,处理或写入全在一个 `Stream` 中怎么办?这就需要稍微复杂的代码: +`Files.lines()` 对于处理文件(转为 **"行"** 为单位元素的输入流)非常有用,但如果你想读取、处理或写入全在一个 `Stream` 中又怎么做呢?这就需要稍微复杂的代码: ```java // files/StreamInAndOut.java From 68be112c6ad98363933c65b74b1f825966b470cf Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Mon, 14 Dec 2020 12:15:48 +0800 Subject: [PATCH 37/68] chapter 18 00 --- docs/book/18-Strings.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/book/18-Strings.md b/docs/book/18-Strings.md index b75429c5..ba25483c 100755 --- a/docs/book/18-Strings.md +++ b/docs/book/18-Strings.md @@ -10,7 +10,7 @@ ## 字符串的不可变 -`String` 对象是不可变的。查看 JDK 文档你就会发现,`String` 类中每一个看起来会修改 `String` 值的方法,实际上都是创建了一个全新的 `String` 对象,以包含修改后的字符串内容。而最初的 `String` 对象则丝毫未动。 +`String` 对象是不可变的。查看 JDK 文档你就会发现,`String` 类中每一个看起来会修改 `String` 值的方法,实际上都是创建了一个全新的 `String` 对象,以包含修改后的字符串内容。而原来的 `String` 对象则丝毫未动。 看看下面的代码: ```java @@ -33,9 +33,9 @@ HOWDY howdy */ ``` -当把 `q` 传递给 `upcase()` 方法时,实际传递的是引用的一个拷贝。其实,每当把 String 对象作为方法的参数时,都会复制一份引用,而该引用所指向的对象其实一直待在单一的物理位置上,从未动过。 +当把对字符串"howdy"的引用—— `q` 被传进给 `upcase()` 方法时,实际上传进的是 `q` 的拷贝(新建了一个栈地址对字符串"howdy"的引用)。该引用所连接的对象(字符串"howdy")停留在单一物理位置上。引用在传递过程中会被复制。 -回到 `upcase()` 的定义,传入其中的引用有了名字 `s`,只有 `upcase()` 运行的时候,局部引用 `s` 才存在。一旦 `upcase()` 运行结束,`s` 就消失了。当然了,`upcase()` 的返回值,其实是最终结果的引用。这足以说明,`upcase()` 返回的引用已经指向了一个新的对象,而 `q` 仍然在原来的位置。 +再看 `upcase()` 的定义,传进的引用有了名字 `s`,只有 `upcase()` 运行的时候,局部引用 `s` 才存在。一旦 `upcase()` 运行结束,局部引用 `s` 就消失了。`upcase()` 返回的引用已经指向了一个新的对象(一个对原字符串的所有字符都设为大写的对象),而 `q` 仍然在原来的位置。 `String` 的这种行为正是我们想要的。例如: @@ -43,7 +43,7 @@ howdy String s = "asdf"; String x = Immutable.upcase(s); ``` -难道你真的希望 `upcase()` 方法改变其参数吗?对于一个方法而言,参数是为该方法提供信息的,而不是想让该方法改变自己的。在阅读这段代码时,读者自然会有这样的感觉。这一点很重要,正是有了这种保障,才使得代码易于编写和阅读。 +难道你真的希望 `upcase()` 方法改变其参数吗?对代码的读者来说,一个参数通常看起来像是提供给方法的一个信息,而不是需要被修改的东西。这是重要的保障,它使代码更易于编写和阅读。 From c76ee2d0a17f345f567ab4b538a5dccb5e3beb06 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 15 Dec 2020 09:42:10 +0800 Subject: [PATCH 38/68] chapter 18 01 --- docs/book/18-Strings.md | 71 ++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/docs/book/18-Strings.md b/docs/book/18-Strings.md index ba25483c..7318a54a 100755 --- a/docs/book/18-Strings.md +++ b/docs/book/18-Strings.md @@ -43,7 +43,7 @@ howdy String s = "asdf"; String x = Immutable.upcase(s); ``` -难道你真的希望 `upcase()` 方法改变其参数吗?对代码的读者来说,一个参数通常看起来像是提供给方法的一个信息,而不是需要被修改的东西。这是重要的保障,它使代码更易于编写和阅读。 +难道你真的希望 `upcase()` 方法改变它的方法参数吗?对代码的读者来说,一个方法的参数通常看起来像是提供给方法的一个信息,而不是需要被修改的东西。这是重要的保障,它使代码更易于编写和阅读。 @@ -67,9 +67,9 @@ public class Concatenation { abcmangodef47 */ ``` -可以想象一下,这段代码是这样工作的:`String` 可能有一个 `append()` 方法,它会生成一个新的 `String` 对象,以包含“abc”与 `mango` 连接后的字符串。该对象会再创建另一个新的 `String` 对象,然后与“def”相连,生成另一个新的对象,依此类推。 +可以想象一下,这段代码是这样工作的:字符串 “abc” 可能用一个 `append()` 方法,它生成一个新的字符串对象来存放 “abc” 与 `mango` 内容的联结结果。而该对象在与 “def” 相连时会再创建另一个新的字符串对象……依此类推。 -这种方式当然是可行的,但是为了生成最终的 `String` 对象,会产生一大堆需要垃圾回收的中间对象。我猜想,Java 设计者一开始就是这么做的(这也是软件设计中的一个教训:除非你用代码将系统实现,并让它运行起来,否则你无法真正了解它会有什么问题),然后他们发现其性能相当糟糕。 +这种方式当然是可行的,但是为了生成最终的 `String` 对象,产生了一大堆需要垃圾回收的中间对象。我猜 Java 设计者先试过这一做法(这也是软件设计中的一条经验:除非你用代码将系统实现,并让它运行起来,否则你无法真正了解它会有什么问题),然后他们发现其性能不可接受。 想看看以上代码到底是如何工作的吗?可以用 JDK 自带的 `javap` 工具来反编译以上代码。命令如下: ```java @@ -236,12 +236,12 @@ public class UsingStringBuilder { `string2()` 使用了 `Stream`,这样代码更加简洁美观。可以证明,`Collectors.joining()` 内部也是使用的 `StringBuilder`,这种写法不会影响性能! -`StringBuilder `是 Java SE5 引入的,在这之前用的是 `StringBuffer`。后者是线程安全的(参见[并发编程](./24-Concurrent-Programming.md)),因此开销也会大些。使用 `StringBuilder` 进行字符串操作更快一点。 +`StringBuilder`是 Java 5 引入的,在此之前,Java使用了`StringBuffer`,它是线程安全的(参见[并发编程](./24-Concurrent-Programming.md)),因此开销也会大些。使用 `StringBuilder` 进行字符串操作更快一点。 ## 意外递归 -Java 中的每个类从根本上都是继承自 `Object`,标准集合类也是如此,它们都有 `toString()` 方法,并且覆盖了该方法,使得它生成的 `String` 结果能够表达集合自身,以及集合包含的对象。例如 `ArrayList.toString()`,它会遍历 `ArrayList` 中包含的所有对象,调用每个元素上的 `toString()` 方法: +Java 中的标准集合类和其它类一样,最终的父类都是 `Object`,因此它们都有 `toString()` 方法。该方法被重写使得生成的 `String` 结果能够表达集合自身,以及集合包含的对象。例如 `ArrayList.toString()`,它会遍历 `ArrayList` 中包含的所有对象,调用每个元素上的 `toString()` 方法: ```java // strings/ArrayListDisplay.java import java.util.*; @@ -282,13 +282,13 @@ public class InfiniteRecursion { } } ``` -当你创建了 `InfiniteRecursion` 对象,并将其打印出来的时候,你会得到一串很长的异常信息。如果你将该 `InfiniteRecursion` 对象存入一个 `ArrayList` 中,然后打印该 `ArrayList`,同样也会抛出异常。其实,当运行到如下代码时: +当你创建一个 `InfiniteRecursion` 对象,并将其打印的时候,你会得到一长串的异常信息(`StackOverflowError`)。如果你将该 `InfiniteRecursion` 对象存入一个 `ArrayList` 中,然后打印该 `ArrayList`(如上),也是如此。其实,当运行到如下代码时: ```java "InfiniteRecursion address: " + this ``` -这里发生了自动类型转换,由 `InfiniteRecursion` 类型转换为 `String` 类型。因为编译器发现一个 `String` 对象后面跟着一个 “+”,而 “+” 后面的对象不是 `String`,于是编译器试着将 `this` 转换成一个 `String`。它怎么转换呢?正是通过调用 `this` 上的 `toString()` 方法,于是就发生了递归调用。 +这里发生了自动类型转换( *automatic type conversion* ),由 `InfiniteRecursion` 类型转换为 `String` 类型。因为编译器发现一个 `String` 对象后面跟着一个 “+”,而 “+” 后面的对象不是 `String`,于是编译器试着将 `this` 转换成一个 `String`。它怎么转换呢?正是通过调用 `this` 上的 `toString()` 方法,于是就发生了递归调用。 -如果你真的想要打印对象的内存地址,应该调用 `Object.toString()` 方法,这才是负责此任务的方法。所以,不要使用 `this`,而是应该调用 `super.toString()` 方法。 +如果你真的想要打印对象的内存地址,应该调用 `Object`类的 `toString()` 方法,这才是负责此任务的方法。所以,不要使用 `this`,而是应该调用 `super.toString()` 方法。 @@ -338,7 +338,7 @@ C 语言的 `printf()` 并不像 Java 那样连接字符串,它使用一个简 ```c System.out.printf("Row 1: [%d %f]%n", x, y); ``` -这一行代码在运行的时候,首先将 `x` 的值插入到 `%d_` 的位置,然后将 `y` 的值插入到 `%f` 的位置。这些占位符叫做*格式修饰符*,它们不仅指明了插入数据的位置,同时还指明了将会插入什么类型的变量,以及如何格式化。在这个例子中 `%d` 表示 `x` 是一个整数,`%f` 表示 `y` 是一个浮点数(`float` 或者 `double`)。 +这一行代码在运行的时候,首先将 `x` 的值插入到 `%d_` 的位置,然后将 `y` 的值插入到 `%f` 的位置。这些占位符叫做*格式修饰符*( format specifiers ),它们不仅指明了插入数据的位置,同时还指明了将会插入什么类型的变量,以及如何格式化。在这个例子中 `%d` 表示 `x` 是一个整数,`%f` 表示 `y` 是一个浮点数(`float` 或者 `double`)。 ### `System.out.format()` Java SE5 引入了 `format()` 方法,可用于 `PrintStream` 或者 `PrintWriter` 对象(你可以在 [附录:流式 I/O](./Appendix-IO-Streams.md) 了解更多内容),其中也包括 `System.out` 对象。`format()` 方法模仿了 C 语言的 `printf()`。如果你比较怀旧的话,也可以使用 `printf()`。以下是一个简单的示例: ```java @@ -409,12 +409,20 @@ Terry The Turtle is at (3,3) ``` 格式化修饰符 `%s` 表明这里需要 `String` 参数。 -所有的 `tommy` 都将输出到 `System.out`,而所有的 `terry` 则都输出到 `System.out` 的一个别名中。`Formatter` 的重载构造器支持输出到多个路径,不过最常用的还是 `PrintStream()`(如上例)、`OutputStream` 和 `File`。你可以在 [附录:流式 I/O](././Appendix-IO-Streams.md) 中了解更多信息。 +所有的 `tommy` 都将输出到 `System.out`,而所有的 `terry` 则都输出到 `System.out` 的一个别名(outAlias)中。`Formatter` 的重载构造器支持输出到多个路径,不过最常用的还是 `PrintStream()`(如上例)、`OutputStream` 和 `File`。你可以在 [附录:流式 I/O](././Appendix-IO-Streams.md) 中了解更多信息。 ### 格式化修饰符 在插入数据时,如果想要优化空格与对齐,你需要更精细复杂的格式修饰符。以下是其通用语法: ```java %[argument_index$][flags][width][.precision]conversion ``` + +- argument_index$:指定对应的内容参数位置,默认按照顺序依次对应。 +- flags:格式控制。 +- width:区域宽度。 +- .precision:对于浮点型数据,表示显示的小数位数;对于字符串数据,表示显示的字符数量。 +- conversion:类型转换字符。 + + 最常见的应用是控制一个字段的最小长度,这可以通过指定 *width* 来实现。`Formatter `对象通过在必要时添加空格,来确保一个字段至少达到设定长度。默认情况下,数据是右对齐的,不过可以通过使用 `-` 标志来改变对齐方向。 与 *width* 相对的是 *precision*,用于指定最大长度。*width* 可以应用于各种类型的数据转换,并且其行为方式都一样。*precision* 则不然,当应用于不同类型的数据转换时,*precision* 的意义也不同。在将 *precision* 应用于 `String` 时,它表示打印 `string` 时输出字符的最大数量。而在将 *precision* 应用于浮点数时,它表示小数部分要显示出来的位数(默认是 6 位小数),如果小数位数过多则舍入,太少则在尾部补零。由于整数没有小数部分,所以 *precision* 无法应用于整数,如果你对整数应用 *precision*,则会触发异常。 @@ -787,7 +795,7 @@ the mightiest banana in the forest...with... a banana! | 表达式 | 含义 | | :---- | :---- | -| `B` | 指定字符`B` | +| `B` | 具体字符`B` | | `\xhh` | 十六进制值为`0xhh`的字符 | | `\uhhhh` | 十六进制表现为`0xhhhh`的Unicode字符 | | `\t` | 制表符Tab | @@ -817,7 +825,7 @@ the mightiest banana in the forest...with... a banana! | 逻辑操作符 | 含义 | | :----: | :---- | -| `XY` | `Y`跟在`X`后面 | +| `XY` | `Y`跟在`X`后面 (X之后是Y)| | `X|Y` | `X`或`Y` | | `(X)` | 捕获组(capturing group)。可以在表达式中用`\i`引用第i个捕获组 | @@ -854,25 +862,25 @@ true ``` 我们的目的并不是编写最难理解的正则表达式,而是尽量编写能够完成任务的、最简单以及最必要的正则表达式。一旦真正开始使用正则表达式了,你就会发现,在编写新的表达式之前,你通常会参考代码中已经用到的正则表达式。 ### 量词 -量词描述了一个模式捕获输入文本的方式: +**量词 quantifier** 描述了一个模式(pattern)捕获输入文本的方式: + **贪婪型**: -量词总是贪婪的,除非有其他的选项被设置。贪婪表达式会为所有可能的模式发现尽可能多的匹配。导致此问题的一个典型理由就是假定我们的模式仅能匹配第一个可能的字符组,如果它是贪婪的,那么它就会继续往下匹配。 +量词总是贪婪的,除非有其他的选项被设置。贪婪表达式会为所有可能的模式发现尽可能多的匹配。问题的一个典型原因:假定在我们的模式只匹配了第一个字符组的时候,如果它是贪婪的,那么它就会继续直到最多匹配为止。 + **勉强型**: 用问号来指定,这个量词匹配满足模式所需的最少字符数。因此也被称作懒惰的、最少匹配的、非贪婪的或不贪婪的。 + **占有型**: -目前,这种类型的量词只有在 Java 语言中才可用(在其他语言中不可用),并且也更高级,因此我们大概不会立刻用到它。当正则表达式被应用于 `String` 时,它会产生相当多的状态,以便在匹配失败时可以回溯。而“占有的”量词并不保存这些中间状态,因此它们可以防止回溯。它们常常用于防止正则表达式失控,因此可以使正则表达式执行起来更高效。 +正则表达式被应用于 `String` 时,会产生相当多的状态,以便在匹配失败时可以回溯。而 **占有型** 量词并不保存这些中间状态,因此它们可以防止回溯。它们常常用于防止正则表达式失控,因此可以使正则表达式执行起来更高效。目前,这种类型的量词只有在 Java 语言中才可用(在其他语言中不可用),并且也更高级,因此我们大概不会立刻用到它。 | 贪婪型 | 勉强型 | 占有型 | 如何匹配 | | ---- | ---- | ---- | ---- | -| `X?` | `X??` | `X?+` | 一个或零个`X` | -| `X*` | `X*?` | `X*+` | 零个或多个`X` | -| `X+` | `X+?` | `X++` | 一个或多个`X` | +| `X?` | `X??` | `X?+` | 零个或一个`X` 相当于{0,1} | +| `X*` | `X*?` | `X*+` | 零个或多个`X` 相当于{0,} | +| `X+` | `X+?` | `X++` | 一个或多个`X` 相当于{1,0} | | `X{n}` | `X{n}?` | `X{n}+` | 恰好`n`次`X` | | `X{n,}` | `X{n,}?` | `X{n,}+` | 至少`n`次`X` | -| `X{n,m}` | `X{n,m}?` | `X{n,m}+` | `X`至少`n`次,但不超过`m`次 | +| `X{n,m}` | `X{n,m}?` | `X{n,m}+` | `X`至少`n`次,但不超过`m`次 (左闭右开)| 应该非常清楚地意识到,表达式 `X` 通常必须要用圆括号括起来,以便它能够按照我们期望的效果去执行。例如: ```java @@ -882,7 +890,7 @@ abc+ ```java (abc)+ ``` -你会发现,在使用正则表达式时很容易混淆,因为它是一种在 Java 之上的新语言。 +你会发现,在使用正则表达式时很容易混淆,因为它是一种在 Java 之上的正交语言。 ### `CharSequence` 接口 `CharSequence` 从 `CharBuffer`、`String`、`StringBuffer`、`StringBuilder` 类中抽象出了字符序列的一般化定义: ```java @@ -897,7 +905,11 @@ interface CharSequence { ### `Pattern` 和 `Matcher` 通常,比起功能有限的 `String` 类,我们更愿意构造功能强大的正则表达式对象。只需导入 `java.util.regex`包,然后用 `static Pattern.compile()` 方法来编译你的正则表达式即可。它会根据你的 `String` 类型的正则表达式生成一个 `Pattern` 对象。接下来,把你想要检索的字符串传入 `Pattern` 对象的 `matcher()` 方法。`matcher()` 方法会生成一个 `Matcher` 对象,它有很多功能可用(可以参考 `java.util.regext.Matcher` 的 JDK 文档)。例如,它的 `replaceAll()` 方法能将所有匹配的部分都替换成你传入的参数。 -作为第一个示例,下面的类可以用来测试正则表达式,看看它们能否匹配一个输入字符串。第一个控制台参数是将要用来搜索匹配的输入字符串,后面的一个或多个参数都是正则表达式,它们将被用来在输入的第一个字符串中查找匹配。在Unix/Linux上,命令行中的正则表达式必须用引号括起来。这个程序在测试正则表达式时很有用,特别是当你想验证它们是否具备你所期待的匹配功能的时候。[^3] +作为第一个示例,下面的类可以用来测试正则表达式,看看它们能否匹配一个输入字符串。 +- 第一个控制台参数(`args[0]`)是将要用来搜索匹配的输入字符串, +- 后面的一个或多个参数都是正则表达式,它们将被用来在输入的第一个字符串中查找匹配。 + +在Unix/Linux上,命令行中的正则表达式必须用引号括起来。这个程序在测试正则表达式时很有用,特别是当你想验证它们是否具备你所期待的匹配功能的时候。[^3] ```java // strings/TestRegularExpression.java // Simple regular expression demonstration @@ -952,12 +964,13 @@ static boolean matches(String regex, CharSequence input) 通过调用 `Pattern.matcher()` 方法,并传入一个字符串参数,我们得到了一个 `Matcher` 对象。使用 `Matcher` 上的方法,我们将能够判断各种不同类型的匹配是否成功: ```java -boolean matches() -boolean lookingAt() -boolean find() -boolean find(int start) +boolean matches() //(整个匹配,只有整个字符序列完全匹配成功,才返回True,否则返回False。但如果部分匹配成功,Matcher下次搜的起始位置为这次匹配的末端位置。) +boolean lookingAt() //(部分匹配,总是从第一个字符进行搜,匹配成功了不再继续匹配,匹配失败了,也不继续匹配。) +boolean find() //(部分匹配,从当前位置开始搜,找到一个匹配的子串,Matcher下次搜的起始位置为这次匹配的末端位置。) +boolean find(int start) //(部分匹配,从入参位置开始搜,找到一个匹配的子串,Matcher下次搜的起始位置为这次匹配的末端位置。) ``` -其中的 `matches()` 方法用来判断整个输入字符串是否匹配正则表达式模式,而 `lookingAt()` 则用来判断该字符串(不必是整个字符串)的起始部分是否能够匹配模式。 +其中的 `matches()` 方法用来判断整个输入字符串是否匹配正则表达式模式。 +而 `lookingAt()` 则用来判断该字符串(不必是整个字符串)的起始部分是否能够匹配模式。 ### `find()` `Matcher.find()` 方法可用来在 `CharSequence` 中查找多个匹配。例如: @@ -982,12 +995,10 @@ public class Finding { } /* Output: Evening is full of the linnet s wings -Evening vening ening ning ing ng g is is s full full -ull ll l of of f the the he e linnet linnet innet nnet -net et t s s wings wings ings ngs gs s +Evening vening ening ning ing ng g is is s full full ull ll l of of f the the he e linnet linnet innet nnet net et t s s wings wings ings ngs gs s */ ``` -模式 `\\w+` 将字符串划分为词。`find()` 方法像迭代器那样向前遍历输入字符串。而第二个重载的 `find()` 接收一个整型参数,该整数表示字符串中字符的位置,并以其作为搜索的起点。从结果可以看出,后一个版本的 `find()` 方法能够根据其参数的值,不断重新设定搜索的起始位置。 +模式 `\\w+` 将输入分组为词语。`find()` 方法像迭代器那样向前遍历这个输入的字符串。而第二个重载的 `find()` 接收一个整型参数,该整数表示字符串中字符的位置,并以其作为搜索的起点。从结果可以看出,后一个版本的 `find()` 方法能够根据其参数的值,不断重新设定搜索的起始位置。 ### 组(Groups) 组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为 0 表示整个表达式,组号 1 表示被第一对括号括起来的组,以此类推。因此,下面这个表达式, ```java From bd452e671fe33ec03a4077c76166172fd1204240 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 15 Dec 2020 15:08:39 +0800 Subject: [PATCH 39/68] chapter 18 02 --- docs/book/18-Strings.md | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/book/18-Strings.md b/docs/book/18-Strings.md index 7318a54a..ac0dccad 100755 --- a/docs/book/18-Strings.md +++ b/docs/book/18-Strings.md @@ -1041,17 +1041,14 @@ public class Groups { } } /* Output: -[the slithy toves][the][slithy toves][slithy][toves] -[in the wabe.][in][the wabe.][the][wabe.] -[were the borogoves,][were][the -borogoves,][the][borogoves,] -[mome raths outgrabe.][mome][raths -outgrabe.][raths][outgrabe.] -[Jabberwock, my son,][Jabberwock,][my son,][my][son,] -[claws that catch.][claws][that catch.][that][catch.] -[bird, and shun][bird,][and shun][and][shun] -[The frumious Bandersnatch.][The][frumious -Bandersnatch.][frumious][Bandersnatch.] +[the slithy toves][the][slithy toves][slithy][toves] +[in the wabe.][in][the wabe.][the][wabe.] +[were the borogoves,][were][the borogoves,][the][borogoves,] +[mome raths outgrabe.][mome][raths outgrabe.][raths][outgrabe.] +[Jabberwock, my son,][Jabberwock,][my son,][my][son,] +[claws that catch.][claws][that catch.][that][catch.] +[bird, and shun][bird,][and shun][and][shun] +[The frumious Bandersnatch.][The][frumious Bandersnatch.][frumious][Bandersnatch.] */ ``` 这首诗来自于 Lewis Carroll 所写的 *Through the Looking Glass* 中的 “Jabberwocky”。可以看到这个正则表达式模式有许多圆括号分组,由任意数目的非空白符(`\\S+`)及随后的任意数目的空白符(`\\s+`)所组成。目的是捕获每行的最后3个词,每行最后以 `\$` 结束。不过,在正常情况下是将 `\$` 与整个输入序列的末端相匹配。所以我们一定要显式地告知正则表达式注意输入序列中的换行符。这可以由序列开头的模式标记 `(?m)` 来完成(模式标记马上就会介绍)。 @@ -1150,13 +1147,13 @@ Pattern Pattern.compile(String regex, int flag) | 编译标记 | 效果 | | ---- |---- | -| `Pattern.CANON_EQ` | 当且仅当两个字符的完全规范分解相匹配时,才认为它们是匹配的。例如,如果我们指定这个标记,表达式`\u003F`就会匹配字符串`?`。默认情况下,匹配不考虑规范的等价性 | +| `Pattern.CANON_EQ` | 开启canonical equivalence。当且仅当两个字符的正规分解(canonical decomposition)都完全相同时,才认为它们是匹配的。例如,如果我们用了这个标记之后,表达式`\u003F`就会匹配字符串`?`。默认情况下,匹配不考虑规范的等价性(canonical equivalence) | | `Pattern.CASE_INSENSITIVE(?i)` | 默认情况下,大小写不敏感的匹配假定只有US-ASCII字符集中的字符才能进行。这个标记允许模式匹配不考虑大小写(大写或小写)。通过指定`UNICODE_CASE`标记及结合此标记。基于Unicode的大小写不敏感的匹配就可以开启了 | -| `Pattern.COMMENTS(?x)` | 在这种模式下,空格符将被忽略掉,并且以`#`开始直到行末的注释也会被忽略掉。通过嵌入的标记表达式也可以开启Unix的行模式 | +| `Pattern.COMMENTS(?x)` | 正则表达式中允许出现空白符(whitespace)和注解(comments),在这种模式下,空格符将被忽略掉,并且以`#`开始直到行末的注释也会被忽略掉。通过嵌入的标记表达式也可以开启Unix的行模式 | | `Pattern.DOTALL(?s)` | 在dotall模式下,表达式`.`匹配所有字符,包括行终止符。默认情况下,`.`不会匹配行终止符 | -| `Pattern.MULTILINE(?m)` | 在多行模式下,表达式`^`和`$`分别匹配一行的开始和结束。`^`还匹配输入字符串的开始,而`$`还匹配输入字符串的结尾。默认情况下,这些表达式仅匹配输入的完整字符串的开始和结束 | +| `Pattern.MULTILINE(?m)` | 启用多行匹配模式。在多行匹配模式下,模式中的`^`和`$`将逐次匹配每一行的行首和行尾。在默认情况下(即未启用多行匹配模式),`^`和`$`将匹配整个字符串的首部和尾部。等价于修饰符(?m)。 | | `Pattern.UNICODE_CASE(?u)` | 当指定这个标记,并且开启`CASE_INSENSITIVE`时,大小写不敏感的匹配将按照与Unicode标准相一致的方式进行。默认情况下,大小写不敏感的匹配假定只能在US-ASCII字符集中的字符才能进行 | -| `Pattern.UNIX_LINES(?d)` | 在这种模式下,在`.`、`^`和`$`的行为中,只识别行终止符`\n` | +| `Pattern.UNIX_LINES(?d)` | 启用Unix换行模式。在这种模式下,在`.`、`^`和`$`的行为中,只识别一种行终止符——`\n` | 在这些标记中,`Pattern.CASE_INSENSITIVE`、`Pattern.MULTILINE` 以及 `Pattern.COMMENTS`(对声明或文档有用)特别有用。请注意,你可以直接在正则表达式中使用其中的大多数标记,只需要将上表中括号括起来的字符插入到正则表达式中,你希望它起作用的位置即可。 @@ -1213,7 +1210,7 @@ public class SplitDemo { [This, unusual use, of exclamation!!points] */ ``` -第二种形式的 `split()` 方法可以限制将输入分割成字符串的数量。 +第二种形式的 `split()` 方法可以限制发生的分割次数。 ### 替换操作 正则表达式在进行文本替换时特别方便,它提供了许多方法: + `replaceFirst(String replacement)` 以参数字符串 `replacement` 替换掉第一个匹配成功的部分。 @@ -1280,7 +1277,7 @@ ExtrActEd blOck. `mInput` 匹配 `/*!` 和 `!*/` 之间的所有文字(注意分组的括号)。接下来,将存在两个或两个以上空格的地方,缩减为一个空格,并且删除每行开头部分的所有空格(为了使每一行都达到这个效果,而不仅仅是删除文本开头部分的空格,这里特意开启了多行模式)。这两个替换操作所使用的的 `replaceAll()` 是 `String` 对象自带的方法,在这里,使用此方法更方便。注意,因为这两个替换操作都只使用了一次 `replaceAll()`,所以,与其编译为 `Pattern`,不如直接使用 `String` 的 `replaceAll()` 方法,而且开销也更小些。 -`replaceFirst()` 只对找到的第一个匹配进行替换。此外,`replaceFirst()` 和 `replaceAll()` 方法用来替换的只是普通字符串,所以,如果想对这些替换字符串进行某些特殊处理,这两个方法时无法胜任的。如果你想要那么做,就应该使用 `appendReplacement()` 方法。该方法允许你在执行替换的过程中,操作用来替换的字符串。在这个例子中,先构造了 `sbuf` 用来保存最终结果,然后用 `group()` 选择一个组,并对其进行处理,将正则表达式找到的元音字母替换成大些字母。一般情况下,你应该遍历执行所有的替换操作,然后再调用 `appendTail()` 方法,但是,如果你想模拟 `replaceFirst()`(或替换n次)的行为,那就只需要执行一次替换,然后调用 `appendTail()` 方法,将剩余未处理的部分存入 `sbuf` 即可。 +`replaceFirst()` 只对找到的第一个匹配进行替换。此外,`replaceFirst()` 和 `replaceAll()` 方法用来替换的只是普通字符串,所以,如果想对这些替换字符串进行某些特殊处理,这两个方法时无法胜任的。如果你想要那么做,就应该使用 `appendReplacement()` 方法。该方法允许你在执行替换的过程中,操作用来替换的字符串。在这个例子中,先构造了 `sbuf` 用来保存最终结果,然后用 `group()` 选择一个组,并对其进行处理,将正则表达式找到的元音字母替换成大些字母。一般情况下,你应该遍历执行所有的替换操作,然后再调用 `appendTail()` 方法,但是,如果你想模拟 `replaceFirst()`(或替换n次)的行为,那就只需要执行一次替换,然后调用 `appendTail()` 方法将其余部分存入 `sbuf` 即可。 同时,`appendReplacement()` 方法还允许你通过 `\$g` 直接找到匹配的某个组,这里的 `g` 就是组号。然而,它只能应付一些简单的处理,无法实现类似前面这个例子中的功能。 ### `reset()` @@ -1308,7 +1305,10 @@ fix rig rag ``` 使用不带参数的 `reset()` 方法,可以将 `Matcher` 对象重新设置到当前字符序列的起始位置。 ### 正则表达式与 Java I/O -到目前为止,我们看到的例子都是将正则表达式用于静态的字符串。下面的例子将向你演示,如何应用正则表达式在一个文件中进行搜索匹配操作。`JGrep.java` 的灵感源自于 Unix 上的 *grep*。它有两个参数:文件名以及要匹配的正则表达式。输出的是每行有匹配的部分以及匹配部分在行中的位置。 +到目前为止,我们看到的例子都是将正则表达式用于静态的字符串。下面的例子将向你演示,如何应用正则表达式在一个文件中进行搜索匹配操作。`JGrep.java` 的灵感源自于 Unix 上的 *grep*。它有两个参数: + +`args[0]`文件名;`args[1]`要匹配的正则表达式。 输出的是每行有匹配的部分以及匹配部分在行中的位置。 + ```java // strings/JGrep.java // A very simple version of the "grep" program @@ -1435,9 +1435,9 @@ My favorite double is 0.809015. ``` `Scanner` 的构造器可以接收任意类型的输入对象,包括 `File`、`InputStream`、`String` 或者像此例中的`Readable` 实现类。`Readable` 是 Java SE5 中新加入的一个接口,表示“具有 `read()` 方法的某种东西”。上一个例子中的 `BufferedReader` 也归于这一类。 -有了 `Scanner`,所有的输入、分词、以及解析的操作都隐藏在不同类型的 `next` 方法中。普通的 `next()` 方法返回下一个 `String`。所有的基本类型(除 `char` 之外)都有对应的 `next` 方法,包括 `BigDecimal` 和 `BigInteger`。所有的 next 方法,只有在找到一个完整的分词之后才会返回。`Scanner` 还有相应的 `hasNext` 方法,用以判断下一个输入分词是否是所需的类型,如果是则返回 `true`。 +有了 `Scanner`,所有的输入、分词、以及解析的操作都隐藏在不同类型的 `next` 方法中。普通的 `next()` 方法返回下一个 `String`。所有的基本类型(除 `char` 之外)以及 `BigDecimal` 和 `BigInteger`都有对应的 `next` 方法。所有的 next 方法,只有在找到一个完整的分词之后才会返回。`Scanner` 还有相应的 `hasNext` 方法,用以判断下一个输入分词是否是所需的类型,如果是则返回 `true`。 -在 `BetterRead.java` 中没有用 `try` 区块捕获`IOException`。因为,`Scanner` 有一个假设,在输入结束时会抛出 `IOException`,所以 `Scanner` 会把 `IOException` 吞掉。不过,通过 `ioException()` 方法,你可以找到最近发生的异常,因此,你可以在必要时检查它。 +在 `BetterRead.java` 中没有用 `try` 区块捕获`IOException`。因为,`Scanner` 有一个假设,抛出 `IOException` 就表示输入结束,所以 `Scanner` 会把 `IOException` 吞掉。不过,通过 `ioException()` 方法,你可以找到最近发生的异常,因此,你可以在必要时检查它。 ### `Scanner` 分隔符 默认情况下,`Scanner` 根据空白字符对输入进行分词,但是你可以用正则表达式指定自己所需的分隔符: ```java @@ -1545,10 +1545,10 @@ But I'm not dead yet! I feel happy! [^3]: 网上还有很多实用并且成熟的正则表达式工具。 -[^4]: input来自于[Galaxy Quest](https://en.wikipedia.org/wiki/Galaxy_Quest)中Taggart司令的一篇演讲。 +[^4]: input来自于电影《惊爆银河系[Galaxy Quest](https://en.wikipedia.org/wiki/Galaxy_Quest)》中Taggart指挥官的一篇演讲。 -[^5]: 我不知道他们是如何想出这个方法名的,或者它到底指的什么。这只是代码审查很重要的原因之一。 +[^5]: 我不知道他们是如何想出这个方法名的,或者它到底指的什么。这就是代码审查很重要的原因之一。 From 4372ded42541ed2364690c8800fb700c38cd707e Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 15 Dec 2020 17:58:12 +0800 Subject: [PATCH 40/68] chapter 19 00 --- docs/book/19-Type-Information.md | 42 +++++++++++++++++--------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/book/19-Type-Information.md b/docs/book/19-Type-Information.md index 6c51d949..191fc3df 100755 --- a/docs/book/19-Type-Information.md +++ b/docs/book/19-Type-Information.md @@ -20,7 +20,7 @@ RTTI 把我们从只能在编译期进行面向类型操作的禁锢中解脱了 ![多态例子Shape的类层次结构图](../images/image-20190409114913825-4781754.png) -这是一个典型的类层次结构图,基类位于顶部,派生类向下扩展。面向对象编程的一个基本目的是:让代码只操纵对基类(这里即 `Shape` )的引用。这样,如果你想添加一个新类(比如从 `Shape` 派生出 `Rhomboid`)来扩展程序,就不会影响原来的代码。在这个例子中,`Shape` 接口中动态绑定了 `draw()` 方法,这样做的目的就是让客户端程序员可以使用泛化的 `Shape` 引用来调用 `draw()`。`draw()` 方法在所有派生类里都会被覆盖,而且由于它是动态绑定的,所以即使通过 `Shape` 引用来调用它,也能产生恰当的行为,这就是多态。 +这是一个典型的类层次结构图,基类位于顶部,派生类向下扩展。面向对象编程的一个基本目的是:让代码只操纵对基类(这里即 `Shape` )的引用。这样,如果你想添加一个新类(比如从 `Shape` 派生出 `Rhomboid`)来扩展程序,就不会影响原来的代码。在这个例子中,`Shape` 接口中动态绑定了 `draw()` 方法,这样做的目的就是让客户端程序员可以使用泛化的 `Shape` 引用来调用 `draw()`。`draw()` 方法在所有派生类里都会被重写,而且由于它是动态绑定的,所以即使通过 `Shape` 引用来调用它,也能产生恰当的行为,这就是多态。 因此,我们通常会创建一个具体的对象(`Circle`、`Square` 或者 `Triangle`),把它向上转型成 `Shape` (忽略对象的具体类型),并且在后面的程序中使用 `Shape` 引用来调用在具体对象中被重载的方法(如 `draw()`)。 @@ -68,7 +68,7 @@ Square.draw() Triangle.draw() ``` -基类中包含 `draw()` 方法,它通过传递 `this` 参数传递给 `System.out.println()`,间接地使用 `toString()` 打印类标识符(注意:这里将 `toString()` 声明为 `abstract`,以此强制继承者覆盖该方法,并防止对 `Shape` 的实例化)。如果某个对象出现在字符串表达式中(涉及"+"和字符串对象的表达式),`toString()` 方法就会被自动调用,以生成表示该对象的 `String`。每个派生类都要覆盖(从 `Object` 继承来的)`toString()` 方法,这样 `draw()` 在不同情况下就打印出不同的消息(多态)。 +基类中包含 `draw()` 方法,它通过传递 `this` 参数传递给 `System.out.println()`,间接地使用 `toString()` 打印类标识符(注意:这里将 `toString()` 声明为 `abstract`,以此强制继承者重写该方法,并防止对 `Shape` 的实例化)。如果某个对象出现在字符串表达式中(涉及"+"和字符串对象的表达式),`toString()` 方法就会被自动调用,以生成表示该对象的 `String`。每个派生类都要重写(从 `Object` 继承来的)`toString()` 方法,这样 `draw()` 在不同情况下就打印出不同的消息(多态)。 这个例子中,在把 `Shape` 对象放入 `Stream` 中时就会进行向上转型(隐式),但在向上转型的时候也丢失了这些对象的具体类型。对 `stream` 而言,它们只是 `Shape` 对象。 @@ -156,7 +156,12 @@ After creating Cookie Class.forName("Gum"); ``` -所有 `Class` 对象都属于 `Class` 类,而且它跟其他普通对象一样,我们可以获取和操控它的引用(这也是类加载器的工作)。`forName()` 是 `Class` 类的一个静态方法,我们可以使用 `forName()` 根据目标类的类名(`String`)得到该类的 `Class` 对象。上面的代码忽略了 `forName()` 的返回值,因为那个调用是为了得到它产生的“副作用”。从结果可以看出,`forName()` 执行的副作用是如果 `Gum` 类没有被加载就加载它,而在加载的过程中,`Gum` 的 `static` 初始化块被执行了。 +所有 `Class` 对象都属于 `Class` 类,而且它跟其他普通对象一样,我们可以获取和操控它的引用(这也是类加载器的工作)。得到`Class` 对象的其中一种做法是使用`forName()`。`forName()` 是 `Class` 类的一个静态方法,我们可以使用 `forName()` 根据目标类的类名(`String`类型,注意拼写和大写)得到目标类的 `Class` 对象。上面的代码忽略了 `forName()` 的返回值,因为那个调用是为了得到它产生的“副作用”。从结果可以看出,`forName()` 执行的副作用是:如果 `Gum` 类没有被加载就加载它,而在加载的过程中,`Gum` 的 `static` 初始化块被执行了。 + +- Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。 +- 而classloader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。 +- Class.forName(name,initialize,loader)带参数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象。 + 还需要注意的是,如果 `Class.forName()` 找不到要加载的类,它就会抛出异常 `ClassNotFoundException`。上面的例子中我们只是简单地报告了问题,但在更严密的程序里,就要考虑在异常处理程序中把问题解决掉(具体例子详见[设计模式](./25-Patterns)章节)。 @@ -228,16 +233,13 @@ public class ToyTest { 输出结果: ``` -Class name: typeinfo.toys.FancyToy is interface? -[false] +Class name: typeinfo.toys.FancyToy is interface? [false] Simple name: FancyToy Canonical name : typeinfo.toys.FancyToy -Class name: typeinfo.toys.HasBatteries is interface? -[true] +Class name: typeinfo.toys.HasBatteries is interface? [true] Simple name: HasBatteries Canonical name : typeinfo.toys.HasBatteries -Class name: typeinfo.toys.Waterproof is interface? -[true] +Class name: typeinfo.toys.Waterproof is interface? [true] Simple name: Waterproof Canonical name : typeinfo.toys.Waterproof Class name: typeinfo.toys.Shoots is interface? [true] @@ -248,11 +250,11 @@ Simple name: Toy Canonical name : typeinfo.toys.Toy ``` -`FancyToy` 继承自 `Toy` 并实现了 `HasBatteries`、`Waterproof` 和 `Shoots` 接口。在 `main` 方法中,我们创建了一个 `Class` 引用,然后在 `try` 语句里边用 `forName()` 方法创建了一个 `FancyToy` 的类对象并赋值给该引用。需要注意的是,传递给 `forName()` 的字符串必须使用类的全限定名(包含包名)。 +`FancyToy` 继承自 `Toy` 并实现了 `HasBatteries`、`Waterproof` 和 `Shoots` 接口。在 `main` 方法中,我们创建了一个 `Class` 引用,然后在 `try` 语句里边用 `forName()` 方法创建了一个 `FancyToy` 的类对象并赋值给该引用。需要注意的是,传递给 `forName()` 的字符串必须使用类的全限定名(由于文件不在根目录,因此需要包含包名)。 `printInfo()` 函数使用 `getName()` 来产生完整类名,使用 `getSimpleName()` 产生不带包名的类名,`getCanonicalName()` 也是产生完整类名(除内部类和数组外,对大部分类产生的结果与 `getName()` 相同)。`isInterface()` 用于判断某个 `Class` 对象代表的是否为一个接口。因此,通过 `Class` 对象,你可以得到关于该类型的所有信息。 -在主方法中调用的 `Class.getInterfaces()` 方法返回的是存放 `Class` 对象的数组,里面的 `Class` 对象表示的是那个类实现的接口。 +在主方法中调用的 `Class.getInterfaces()` 方法返回的是存放 `Class` 对象的数组。该数组里面的每一个 `Class` 对象,都分别是目标类所实现的每一个接口的`Class` 对象。 另外,你还可以调用 `getSuperclass()` 方法来得到父类的 `Class` 对象,再用父类的 `Class` 对象调用该方法,重复多次,你就可以得到一个对象完整的类继承结构。 @@ -312,7 +314,7 @@ Java 还提供了另一种方法来生成类对象的引用:**类字面常量* -我的建议是使用 `.class` 的形式,以保持与普通类的一致性。 +我的建议是最好使用 `.class` 的形式,来保持与普通类的一致性。 注意,有一点很有趣:当使用 `.class` 来创建对 `Class` 对象的引用时,不会自动地初始化该 `Class` 对象。为了使用类而做的准备工作实际包含三个步骤: @@ -322,7 +324,7 @@ Java 还提供了另一种方法来生成类对象的引用:**类字面常量* 3. **初始化**。如果该类具有超类,则先初始化超类,执行 `static` 初始化器和 `static` 初始化块。 -直到第一次引用一个 `static` 方法(构造器隐式地是 `static`)或者非常量的 `static` 字段,才会进行类初始化。 +直到第一次引用一个 `static` 方法(构造器是隐式的 `static`)或者 **非常量** 的 `static` 字段,才会进行类初始化。 ```java // typeinfo/ClassInitialization.java @@ -386,17 +388,17 @@ After creating Initable3 ref 初始化有效地实现了尽可能的“惰性”,从对 `initable` 引用的创建中可以看到,仅使用 `.class` 语法来获得对类对象的引用不会引发初始化。但与此相反,使用 `Class.forName()` 来产生 `Class` 引用会立即就进行初始化,如 `initable3`。 -如果一个 `static final` 值是“编译期常量”(如 `Initable.staticFinal`),那么这个值不需要对 `Initable` 类进行初始化就可以被读取。但是,如果只是将一个字段设置成为 `static` 和 `final`,还不足以确保这种行为。例如,对 `Initable.staticFinal2` 的访问将强制进行类的初始化,因为它不是一个编译期常量。 +如果一个 `static final` 值是“编译期常量”(如 `Initable.staticFinal`),那么这个值不需要对 `Initable` 类进行初始化就可以被读取。但是,如果只是将一个字段设置成为 `static` 和 `final`,并不能保证类初始化一定不会发生。例如,对 `Initable.staticFinal2` 的访问将强制进行类的初始化,因为它不是一个编译期常量。 如果一个 `static` 字段不是 `final` 的,那么在对它访问时,总是要求在它被读取之前,要先进行链接(为这个字段分配存储空间)和初始化(初始化该存储空间),就像在对 `Initable2.staticNonFinal` 的访问中所看到的那样。 ### 泛化的 `Class` 引用 -`Class` 引用总是指向某个 `Class` 对象,而 `Class` 对象可以用于产生类的实例,并且包含可作用于这些实例的所有方法代码。它还包含该类的 `static` 成员,因此 `Class` 引用表明了它所指向对象的确切类型,而该对象便是 `Class` 类的一个对象。 +`Class` 引用总是指向某个 `Class` 对象,该 `Class` 对象可以用于产生类的实例,并且包含可作用于这些实例的所有方法代码。它还包含该类的 `static` 成员,因此 `Class` 引用确实表明了它所指向的确切类型: `Class` 类的一个对象。 -但是,Java 设计者看准机会,将它的类型变得更具体了一些。Java 引入泛型语法之后,我们可以使用泛型对 `Class` 引用所指向的 `Class` 对象的类型进行限定。在下面的实例中,两种语法都是正确的: +但是,Java 设计者看准机会,使“指向”变得更加具体:允许你使用泛型语法来约束`Class`引用指向的`Class`对象的类型。在下面的例子中,两种语法都是正确的: ```java // typeinfo/GenericClassReferences.java @@ -420,7 +422,7 @@ public class GenericClassReferences { Class geenericNumberClass = int.class; ``` -这看起来似乎是起作用的,因为 `Integer` 继承自 `Number`。但事实却是不行,因为 `Integer` 的 `Class` 对象并不是 `Number`的 `Class` 对象的子类(这看起来可能有点诡异,我们将在[泛型](./20-Generics)这一章详细讨论)。 +这看起来似乎是合理的,因为 `Integer` 继承自 `Number`。但事实却是不行,因为 `Integer` 的 `Class` 对象并不是 `Number`的 `Class` 对象的子类(这看起来可能有点诡异,我们将在[泛型](./20-Generics)这一章详细讨论)。 为了在使用 `Class` 引用时放松限制,我们使用了通配符,它是 Java 泛型中的一部分。通配符就是 `?`,表示“任何事物”。因此,我们可以在上例的普通 `Class` 引用中添加通配符,并产生相同的结果: @@ -435,7 +437,7 @@ public class WildcardClassReferences { } ``` -使用 `Class` 比单纯使用 `Class` 要好,虽然它们是等价的,并且单纯使用 `Class` 不会产生编译器警告信息。使用 `Class` 的好处是它表示你并非是碰巧或者由于疏忽才使用了一个非具体的类引用,而是特意为之。 +使用 `Class` 比单纯使用 `Class` 要好,虽然它们是等价的,并且单纯使用 `Class` 不会产生编译器警告信息。使用 `Class` 的好处是它表示你并非是意外或者出于无知才使用了一个非具体的类引用,而是特意为之。 为了创建一个限定指向某种类型或其子类的 `Class` 引用,我们需要将通配符与 `extends` 关键字配合使用,创建一个范围限定。这与仅仅声明 `Class` 不同,现在做如下声明: @@ -452,7 +454,7 @@ public class BoundedClassReferences { } ``` -向 `Class` 引用添加泛型语法的原因只是为了提供编译期类型检查,因此如果你操作有误,稍后就会发现这点。使用普通的 `Class` 引用你要确保自己不会犯错,因为一旦你犯了错误,就要等到运行时才能发现它,很不方便。 +之所以向 `Class` 引用添加泛型语法,只是为了提供编译期类型检查,所以如果你做错了什么,你会更早发现。使用普通的 `Class` 引用你要确保自己不会犯错,因为一旦你犯了错误,就要等到运行时才能发现它,很不方便。 下面的示例使用了泛型语法,它保存了一个类引用,稍后又用 `newInstance()` 方法产生类的对象: @@ -2473,7 +2475,7 @@ RTTI 允许通过匿名类的引用来获取类型信息。初学者极易误用 然而使用多态机制的方法调用,要求我们拥有基类定义的控制权。因为在你扩展程序的时候,可能会发现基类并未包含我们想要的方法。如果基类来自别人的库,这时 RTTI 便是一种解决之道:可继承一个新类,然后添加你需要的方法。在代码的其它地方,可以检查你自己特定的类型,并调用你自己的方法。这样做不会破坏多态性以及程序的扩展能力,因为这样添加一个新的类并不需要修改程序中的 `switch` 语句。但如果想在程序中增加具有新特性的代码,你就必须使用 RTTI 来检查这个特定的类型。 -如果只是为了方便某个特定的类,就将某个特性放进基类里边,这将使得从那个基类派生出的所有其它子类都带有这些可能毫无意义的东西。这会导致接口更加不清晰,因为我们必须覆盖从基类继承而来的所有抽象方法,事情就变得很麻烦。举个例子,现在有一个表示乐器 `Instrument` 的类层次结构。假设我们想清理管弦乐队中某些乐器残留的口水,一种办法是在基类 `Instrument` 中放入 `clearSpitValve()` 方法。但这样做会导致类结构混乱,因为这意味着打击乐器 `Percussion`、弦乐器 `Stringed` 和电子乐器 `Electronic` 也需要清理口水。在这个例子中,RTTI 可以提供一种更合理的解决方案。可以将 `clearSpitValve()` 放在某个合适的类中,在这个例子中是管乐器 `Wind`。不过,在这里你可能会发现还有更好的解决方法,就是将 `prepareInstrument()` 放在基类中,但是初次面对这个问题的读者可能想不到还有这样的解决方案,而误认为必须使用 RTTI。 +如果只是为了方便某个特定的类,就将某个特性放进基类里边,这将使得从那个基类派生出的所有其它子类都带有这些可能毫无意义的东西。这会导致接口更加不清晰,因为我们必须重写从基类继承而来的所有抽象方法,事情就变得很麻烦。举个例子,现在有一个表示乐器 `Instrument` 的类层次结构。假设我们想清理管弦乐队中某些乐器残留的口水,一种办法是在基类 `Instrument` 中放入 `clearSpitValve()` 方法。但这样做会导致类结构混乱,因为这意味着打击乐器 `Percussion`、弦乐器 `Stringed` 和电子乐器 `Electronic` 也需要清理口水。在这个例子中,RTTI 可以提供一种更合理的解决方案。可以将 `clearSpitValve()` 放在某个合适的类中,在这个例子中是管乐器 `Wind`。不过,在这里你可能会发现还有更好的解决方法,就是将 `prepareInstrument()` 放在基类中,但是初次面对这个问题的读者可能想不到还有这样的解决方案,而误认为必须使用 RTTI。 最后一点,RTTI 有时候也能解决效率问题。假设你的代码运用了多态,但是为了实现多态,导致其中某个对象的效率非常低。这时候,你就可以挑出那个类,使用 RTTI 为它编写一段特别的代码以提高效率。然而必须注意的是,不要太早地关注程序的效率问题,这是个诱人的陷阱。最好先让程序能跑起来,然后再去看看程序能不能跑得更快,下一步才是去解决效率问题(比如使用 Profiler)[^5]。 From dd6f28ab008b7f089fe270eee04e317f605a8a92 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 17 Dec 2020 17:35:55 +0800 Subject: [PATCH 41/68] chapter 19 01 --- docs/book/18-Strings.md | 4 +-- docs/book/19-Type-Information.md | 45 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/docs/book/18-Strings.md b/docs/book/18-Strings.md index ac0dccad..83468d36 100755 --- a/docs/book/18-Strings.md +++ b/docs/book/18-Strings.md @@ -812,8 +812,8 @@ the mightiest banana in the forest...with... a banana! | `[abc]` |包含`a`、`b`或`c`的任何字符(和`a|b|c`作用相同)| | `[^abc]` | 除`a`、`b`和`c`之外的任何字符(否定) | | `[a-zA-Z]` | 从`a`到`z`或从`A`到`Z`的任何字符(范围) | -| `[abc[hij]]` | `a`、`b`、`c`、`h`、`i`、`j`中的任意字符(与`a|b|c|h|i|j`作用相同)(合并) | -| `[a-z&&[hij]]` | 任意`h`、`i`或`j`(交) | +| `[abc[hij]]` | `a`、`b`、`c`、`h`、`i`、`j`中的任意字符(与`a|b|c|h|i|j`作用相同)(并集) | +| `[a-z&&[hij]]` | `h`、`i`或`j`(交集) | | `\s` | 空白符(空格、tab、换行、换页、回车) | | `\S` | 非空白符(`[^\s]`) | | `\d` | 数字(`[0-9]`) | diff --git a/docs/book/19-Type-Information.md b/docs/book/19-Type-Information.md index 191fc3df..90954aa6 100755 --- a/docs/book/19-Type-Information.md +++ b/docs/book/19-Type-Information.md @@ -529,7 +529,7 @@ public class GenericToyTest { } ``` -如果你手头的是超类,那编译器将只允许你声明超类引用为“某个类,它是 `FancyToy` 的超类”,就像在表达式 `Class` 中所看到的那样。而不会接收 `Class` 这样的声明。这看上去显得有些怪,因为 `getSuperClass()` 方法返回的是基类(不是接口),并且编译器在编译期就知道它是什么类型了(在本例中就是 `Toy.class`),而不仅仅只是"某个类"。不管怎样,正是由于这种含糊性,`up.newInstance` 的返回值不是精确类型,而只是 `Object`。 +如果你使用 `getSuperclass()`,编译器只允许你将超类引用声明为“某个类,它是 `FancyToy` 的超类”(`Class`)。而不会接收 `Class` 这样的声明。这看上去有些奇怪,因为 `getSuperClass()` 方法返回的是基类(不是接口),而编译器在编译时就知道这个类是什么——是 `Toy.class`,而不仅仅只是"`FancyToy` 的超类"。不管怎样,由于这种模糊不清,`up.newInstance` 的返回值不是精确类型,而只是 `Object`。 ### `cast()` 方法 @@ -551,21 +551,21 @@ public class ClassCasts { } ``` -`cast()` 方法接受参数对象,并将其类型转换为 `Class` 引用的类型。但是,如果观察上面的代码,你就会发现,与实现了相同功能的 `main` 方法中最后一行相比,这种转型好像做了很多额外的工作。 +`cast()` 方法接受参数对象,并将其类型转换为 `Class` 引用的类型。但是,如果观察上面的代码,与实现了相同功能的 `main()` 方法中最后一行相比,这种转型似乎做了很多额外的工作。 `cast()` 在无法使用普通类型转换的情况下会显得非常有用,在你编写泛型代码(你将在[泛型](./20-Generics)这一章学习到)时,如果你保存了 `Class` 引用,并希望以后通过这个引用来执行转型,你就需要用到 `cast()`。但事实却是这种情况非常少见,我发现整个 Java 类库中,只有一处使用了 `cast()`(在 `com.sun.mirror.util.DeclarationFilter` 中)。 -Java 类库中另一个没有任何用处的特性就是 `Class.asSubclass()`,该方法允许你将一个 `Class` 对象转型为更加具体的类型。 +Java 类库中另一个没有任何用处的特性: `Class.asSubclass()`,该方法允许你将一个 `Class` 对象转型为更加具体的类型。 -## 类型转换检测 +## 类型转换前的检测 -直到现在,我们已知的 RTTI 类型包括: +直至目前,我们已知的 RTTI 的几种形式包括: -1. 传统的类型转换,如 “`(Shape)`”,由 RTTI 确保转换的正确性,如果执行了一个错误的类型转换,就会抛出一个 `ClassCastException` 异常。 +1. 传统的类型转换,如 “`(Shape)`”,由 RTTI 确保转换的正确性,如果执行了错误的类型转换,就会抛出一个 `ClassCastException` 异常。 -2. 代表对象类型的 `Class` 对象. 通过查询 `Class` 对象可以获取运行时所需的信息. +2. 代表对象类型的 `Class` 对象. 通过查询 `Class` 对象可以获得有用的运行时信息。 -在 C++ 中,经典的类型转换 “`(Shape)`” 并不使用 RTTI。它只是简单地告诉编译器将这个对象作为新的类型对待. 而 Java 会进行类型检查,这种类型转换一般被称作“类型安全的向下转型”。之所以称作“向下转型”,是因为传统上类继承图是这么画的。将 `Circle` 转换为 `Shape` 是一次向上转型, 将 `Shape` 转换为 `Circle` 是一次向下转型。但是, 因为我们知道 `Circle` 肯定是一个 `Shape`,所以编译器允许我们自由地做向上转型的赋值操作,且不需要任何显式的转型操作。当你给编译器一个 `Shape` 的时候,编译器并不知道它到底是什么类型的 `Shape`——它可能是 `Shape`,也可能是 `Shape` 的子类型,例如 `Circle`、`Square`、`Triangle` 或某种其他的类型。在编译期,编译器只能知道它是 `Shape`。因此,你需要使用显式地进行类型转换,以告知编译器你想转换的特定类型,否则编译器就不允许你执行向下转型赋值。 (编译器将会检查向下转型是否合理,因此它不允许向下转型到实际不是待转型类型的子类类型上)。 +在 C++ 中,经典的类型转换 “`(Shape)`” 并不使用 RTTI。它只是简单地告诉编译器将这个对象作为新的类型对待. 而 Java 会进行类型检查,这种类型转换一般被称作“类型安全的向下转型”。之所以称作“向下转型”,是因为传统上类继承图是这么画的。将 `Circle` 转换为 `Shape` 是一次向上转型, 将 `Shape` 转换为 `Circle` 是一次向下转型。但是, 因为我们知道 `Circle` 肯定是一个 `Shape`,所以编译器允许我们自由地做向上转型的赋值操作,且不需要任何显式的转型操作。当你给编译器一个 `Shape` 的时候,编译器并不知道它到底是什么类型的 `Shape`——它可能是 `Shape`,也可能是 `Shape` 的子类型,例如 `Circle`、`Square`、`Triangle` 或某种其他的类型。在编译期,编译器只能知道它是 `Shape`。因此,你需要使用显式地进行类型转换,以告知编译器你想转换的特定类型,否则编译器就不允许你执行向下转型赋值。 (编译器将会检查向下转型是否合理,因此它不允许向下转型到实际不是子类的类型)。 RTTI 在 Java 中还有第三种形式,那就是关键字 `instanceof`。它返回一个布尔值,告诉我们对象是不是某个特定类型的实例,可以用提问的方式使用它,就像这个样子: @@ -712,7 +712,7 @@ public class Hamster extends Rodent { 我们必须显式地为每一个子类编写无参构造器。因为我们有一个带一个参数的构造器,所以编译器不会自动地为我们加上无参构造器。 -接下来,我们需要一个类,它可以随机地创建不同类型的宠物,同时,它还可以创建宠物数组和持有宠物的 `List`。为了使这个类更加普遍适用,我们将其定义为抽象类: +接下来,我们需要一种方法来随机创建不同类型的宠物,为了方便,它应该还可以创建宠物数组和`List`。为了使这个工具能通过几个不同实现类来“进化”,我们将其定义为抽象类: ```java // typeinfo/pets/PetCreator.java @@ -739,9 +739,9 @@ public abstract class PetCreator implements Supplier { } ``` -抽象的 `types()` 方法需要子类来实现,以此来获取 `Class` 对象构成的 `List`(这是模板方法设计模式的一种变体)。注意,其中类的类型被定义为“任何从 `Pet` 导出的类型”,因此 `newInstance()` 不需要转型就可以产生 `Pet`。`get()` 随机的选取出一个 `Class` 对象,然后可以通过 `Class.newInstance()` 来生成该类的新实例。 +抽象的 `types()` 方法需要子类来实现,以此来获取 `Class` 对象构成的 `List`(这是模板方法设计模式的一种变体)。注意,其中类的类型被定义为“任何从 `Pet` 导出的类型(`Class`)”,因此 `newInstance()` 不需要转型就可以产生 `Pet`。`get()` 随机的选取出一个 `Class` 对象,然后可以通过 `Class.newInstance()` 来生成该类的新实例。 -在调用 `newInstance()` 时,可能会出现两种异常。在紧跟 `try` 语句块后面的 `catch` 子句中可以看到对它们的处理。异常的名字再次成为了一种对错误类型相对比较有用的解释(`IllegalAccessException` 违反了 Java 安全机制,在本例中,表示默认构造器为 `private` 的情况)。 +在调用 `newInstance()` 时,可能会出现两种异常。在紧跟 `try` 语句块后面的 `catch` 子句中可以看到对它们的处理。异常的名字再次成为了一种对错误类型相对比较有用的解释( `InstantiationException`系统无法调用无参数的构造函数实例化类;`IllegalAccessException` 违反了 Java 安全机制,在本例中,当默认构造器为 `private` 的时候会出现)。 当你创建 `PetCreator` 的子类时,你需要为 `get()` 方法提供 `Pet` 类型的 `List`。`types()` 方法会简单地返回一个静态 `List` 的引用。下面是使用 `forName()` 的一个具体实现: @@ -914,11 +914,11 @@ typeinfo.pets.Hamster] ``` -在即将到来的 `PetCount3.java` 示例中,我们用所有 `Pet` 类型预先加载一个 `Map`(不仅仅是随机生成的),因此 `ALL_TYPES` 类型的列表是必要的。`types` 列表是 `ALL_TYPES` 类型(使用 `List.subList()` 创建)的一部分,它包含精确的宠物类型,因此用于随机生成 `Pet`。 +在接下来的 `PetCount3.java` 示例中,我们用所有 `Pet` 类型预先加载一个 `Map`,因此 `ALL_TYPES` 类型的列表是必要的(这是为下文准备,而不只为随机生成而准备)。`types` 列表是 `ALL_TYPES` 类型(使用 `List.subList()` 创建)的一部分(子集),它包含精确的宠物类型,因此用于随机生成 `Pet`。 这次,`types` 的创建没有被 `try` 块包围,因为它是在编译时计算的,因此不会引发任何异常,不像 `Class.forName()`。 -我们现在在 `typeinfo.pets` 库中有两个 `PetCreator` 的实现。为了提供第二个作为默认实现,我们可以创建一个使用 `LiteralPetCreator` 的 *外观模式*: +我们现在在 `typeinfo.pets` 库中有两个 `PetCreator` 的实现。为了提供第二个作为默认实现,我们可以创建一个使用 `LiteralPetCreator` 的 *外观模式* (Facade设计模式,又称为门面模式): ```java // typeinfo/pets/Pets.java @@ -1046,15 +1046,15 @@ Pug Mouse Cymric EgyptianMau=2, Rodent=5, Hamster=1, Manx=7, Pet=20} ``` -为了计算所有不同类型的 `Pet`,`Counter Map` 预先加载了来自 `LiteralPetCreator.ALL_TYPES` 的类型。如果不预先加载 `Map`,将只计数随机生成的类型,而不是像 `Pet` 和 `Cat` 这样的基本类型。 +为了计数所有不同类型的 `Pet`,`Counter Map` 预先加载了来自 `LiteralPetCreator.ALL_TYPES` 的类型。如果不预先加载 `Map`,最后只会计数随机生成的类型,而不会计数是像 `Pet`、`Cat`、`Dog` 和 `Rodent` 这样的基本的类型。(译者注:意思是,`ALL_TYPES`有两个作用:1.利用其子集来生成随机详细的宠物类型,2.利用其全集来分类计数,分类包括笼统类/基本类,比如Pet=20,是因为生成的所有详细类都归属于Pet,基本类和详细类的计数都会增1) -`isInstance()` 方法消除了对 `instanceof` 表达式的需要。此外,这意味着你可以通过更改 `LiteralPetCreator.types` 数组来添加新类型的 `Pet`;程序的其余部分不需要修改(就像使用 `instanceof` 表达式时那样)。 +`isInstance()` 方法消除了对 `instanceof` 表达式的需要。此外,这意味着你可以通过更改 `LiteralPetCreator.types` 数组来添加新类型的 `Pet`;程序的其余部分不需要修改(就像使用 `instanceof` 表达式时那样)(解耦了!)。 -`toString()` 方法被重载,以便更容易读取输出,该输出仍与打印 `Map` 时看到的典型输出匹配。 +`toString()` 方法被重写,以便更容易读取输出,该输出仍与打印 `Map` 时看到的典型输出匹配。 ### 递归计数 -`PetCount3.Counter` 中的 `Map` 预先加载了所有不同的 `Pet` 类。我们可以使用 `Class.isAssignableFrom()` 而不是预加载 `Map` ,并创建一个不限于计数 `Pet` 的通用工具: +`PetCount3.Counter` 中的 `Map` 预加载了所有不同的 `Pet` 类。我们可以使用 `Class.isAssignableFrom()` 来代替预加载 `Map` 这一操作,并创建一个不仅限于计数 `Pet` 的通用工具: ```java // onjava/TypeCounter.java @@ -1083,8 +1083,7 @@ public class TypeCounter extends HashMap, Integer> { Integer quantity = get(type); put(type, quantity == null ? 1 : quantity + 1); Class superClass = type.getSuperclass(); - if(superClass != null && - baseType.isAssignableFrom(superClass)) + if(superClass != null && baseType.isAssignableFrom(superClass)) countClass(superClass); } @@ -1100,7 +1099,7 @@ public class TypeCounter extends HashMap, Integer> { } ``` -`count()` 方法获取其参数的 `Class`,并使用 `isAssignableFrom()` 进行运行时检查,以验证传递的对象实际上属于感兴趣的层次结构。`countClass()` 首先计算类的确切类型。然后,如果 `baseType` 可以从超类赋值,则在超类上递归调用 `countClass()`。 +`count()` 方法获取其参数的 `Class`,并使用 `isAssignableFrom()` 进行运行时检查,以验证传递的对象是否真的属于继承相关的层次结构。`countClass()` 首先对该类的确切类型计数,然后,如果 `baseType` 是该类的超类的父类或同类,则在该类的超类上递归调用 `countClass()`。 ```java // typeinfo/PetCount4.java @@ -1139,11 +1138,11 @@ Mouse=2} 从 `Pet` 层次结构生成对象的问题是,每当向层次结构中添加一种新类型的 `Pet` 时,必须记住将其添加到 `LiteralPetCreator.java` 的条目中。在一个定期添加更多类的系统中,这可能会成为问题。 -你可能会考虑向每个子类添加静态初始值设定项,因此初始值设定项会将其类添加到某个列表中。不幸的是,静态初始值设定项仅在首次加载类时调用,因此存在鸡和蛋的问题:生成器的列表中没有类,因此它无法创建该类的对象,因此类不会被加载并放入列表中。 +你可能会考虑向每个子类添加静态初始化块,初始化块会将其类添加到某个列表中。不幸的是,静态初始化块仅在首次加载类时调用,由此产生了先有鸡还是先有蛋的悖论:生成器的列表中没有该类,所以它永远无法创建该类的对象,所以该类不会被加载并放入列表中。 -基本上,你必须自己手工创建列表(除非你编写了一个工具来搜索和分析源代码,然后创建和编译列表)。所以你能做的最好的事情就是把列表集中放在一个明显的地方。层次结构的基类可能是最好的地方。 +基本上,你必须亲自创建这个列表(除非你编写了一个工具来搜索和分析源代码,然后创建和编译这个列表)。所以你能做的最好的事情就是把列表集中放在一个中央的、明显的地方。继承层次结构的基类可能是最好的地方。 -我们在这里所做的另一个更改是使用*工厂方法*设计模式将对象的创建推迟到类本身。工厂方法可以以多态方式调用,并为你创建适当类型的对象。事实证明,`java.util.function.Supplier` 用 `T get()` 描述了原型工厂方法。协变返回类型允许 `get()` 为 `Supplier` 的每个子类实现返回不同的类型。 +我们在这里所做的另一个更改是使用 *工厂方法 Factory Method* 设计模式——将对象的创建推迟到类本身。工厂方法可以以多态方式调用,并为你创建适当类型的对象。事实证明,`java.util.function.Supplier` 用 `T get()` 描述了原型工厂方法。协变返回类型允许 `get()` 为 `Supplier` 的每个子类实现返回不同的类型。 在本例中,基类 `Part` 包含一个工厂对象的静态列表,列表成员类型为 `Supplier`。对于应该由 `get()` 方法生成的类型的工厂,通过将它们添加到 `prototypes` 列表向基类“注册”。奇怪的是,这些工厂本身就是对象的实例。此列表中的每个对象都是用于创建其他对象的*原型*: From 08be1963b9fd2b783f447b278071ceaff6fe698a Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 18 Dec 2020 09:24:11 +0800 Subject: [PATCH 42/68] chapter 19 02 --- docs/book/19-Type-Information.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/book/19-Type-Information.md b/docs/book/19-Type-Information.md index 90954aa6..625725db 100755 --- a/docs/book/19-Type-Information.md +++ b/docs/book/19-Type-Information.md @@ -1142,9 +1142,9 @@ Mouse=2} 基本上,你必须亲自创建这个列表(除非你编写了一个工具来搜索和分析源代码,然后创建和编译这个列表)。所以你能做的最好的事情就是把列表集中放在一个中央的、明显的地方。继承层次结构的基类可能是最好的地方。 -我们在这里所做的另一个更改是使用 *工厂方法 Factory Method* 设计模式——将对象的创建推迟到类本身。工厂方法可以以多态方式调用,并为你创建适当类型的对象。事实证明,`java.util.function.Supplier` 用 `T get()` 描述了原型工厂方法。协变返回类型允许 `get()` 为 `Supplier` 的每个子类实现返回不同的类型。 +我们在这里所做的另一个更改是使用 *工厂方法 Factory Method* 设计模式——将【对象的创建】推迟到【类本身】(即:相比于直接new一个类,这方法使得 类本身可以创建继承自本类的子类型对象)。工厂方法可以以多态方式调用,并为你创建适当类型的对象。事实证明,`java.util.function.Supplier` 用 `T get()` 描述了原型工厂方法。协变返回类型允许 `get()` 为 `Supplier` 的每个子类实现返回不同的类型。 -在本例中,基类 `Part` 包含一个工厂对象的静态列表,列表成员类型为 `Supplier`。对于应该由 `get()` 方法生成的类型的工厂,通过将它们添加到 `prototypes` 列表向基类“注册”。奇怪的是,这些工厂本身就是对象的实例。此列表中的每个对象都是用于创建其他对象的*原型*: +在本例中,基类`Part`包含一个元素为工厂对象的静态列表,元素的类型为 `Supplier`。对于应该由 `get()` 方法产生的各种工厂,通过将它们添加至 `prototypes` 列表,向基类`Part`注册。奇怪的是,这些工厂本身就是对象的实例。此列表中的每个对象都是用于创建其他对象的*原型*: ```java // typeinfo/RegisteredFactories.java @@ -1254,9 +1254,9 @@ PowerSteeringBelt FuelFilter ``` -并非层次结构中的所有类都应实例化;这里的 `Filter` 和 `Belt` 只是分类器,这样你就不会创建任何一个类的实例,而是只创建它们的子类(请注意,如果尝试这样做,你将获得 `Part` 基类的行为)。 +不是所有在继承层次结构中的类都应该被实例化;这里的 `Filter` 和 `Belt` 只是分类器——你不会创建这两个类的实例,而是只创建它们的子类(请注意,如果尝试这样做(创建这两个类的实例),你将获得 `Part` 基类的行为,即使用的是基类中的方法)。 -因为 `Part implements Supplier`,`Part` 通过其 `get()` 方法供应其他 `Part`。如果为基类 `Part` 调用 `get()`(或者如果 `generate()` 调用 `get()`),它将创建随机特定的 `Part` 子类型,每个子类型最终都从 `Part` 继承,并重写相应的 `get()` 以生成它们中的一个。 +因为 `Part implements Supplier`,`Part` 通过其 `get()` 方法供应其他 `Part` (原型工厂)。如果对基类 `Part` 调用 `get()`(或者如果 `generate()` 调用 `get()`),它将创建(new)随机的具体的 `Part` 的子类型,其每一个最终都继承自 `Part` ,并通过重写了的 `get()` 方法来创建(new)它们本身。 From 4c25e217dd4da7fbadbbe30cd54495c1c47b5b27 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 18 Dec 2020 18:21:13 +0800 Subject: [PATCH 43/68] chapter 19 04 --- docs/book/19-Type-Information.md | 104 ++++++++++++++----------------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/docs/book/19-Type-Information.md b/docs/book/19-Type-Information.md index 625725db..fddf455a 100755 --- a/docs/book/19-Type-Information.md +++ b/docs/book/19-Type-Information.md @@ -1330,7 +1330,7 @@ x.getClass().equals(Base.class)) false x.getClass().equals(Derived.class)) true ``` -`test()` 方法使用两种形式的 `instanceof` 对其参数执行类型检查。然后,它获取 `Class` 引用,并使用 `==` 和 `equals()` 测试 `Class` 对象的相等性。令人放心的是,`instanceof` 和 `isInstance()` 产生的结果相同, `equals()` 和 `==` 产生的结果也相同。但测试本身得出了不同的结论。与类型的概念一致,`instanceof` 说的是“你是这个类,还是从这个类派生的类?”。而如果使用 `==` 比较实际的`Class` 对象,则与继承无关 —— 它要么是确切的类型,要么不是。 +`test()` 方法使用两种形式的 `instanceof` 对其参数执行类型检查。然后,它获取 `Class` 引用,并使用 `==` 和 `equals()` 测试 `Class` 对象的相等性。令人放心的是,`instanceof` 和 `isInstance()` 产生的结果相同, `equals()` 和 `==` 产生的结果也相同。但测试本身得出了不同的结论。与类型的概念一致,`instanceof` 说的是“你是这个类,还是从这个类派生的类?”。另一方面,如果使用 `==` 比较实际的`Class` 对象,则与继承无关 —— 其 要么的确是该类型,要么不是。 ## 反射:运行时类信息 @@ -1339,19 +1339,19 @@ x.getClass().equals(Derived.class)) true 起初,这看起来并没有那么大的限制,但是假设你引用了一个不在程序空间中的对象。实际上,该对象的类在编译时甚至对程序都不可用。也许你从磁盘文件或网络连接中获得了大量的字节,并被告知这些字节代表一个类。由于这个类在编译器为你的程序生成代码后很长时间才会出现,你如何使用这样的类? -在传统编程环境中,这是一个牵强的场景。但是,当我们进入一个更大的编程世界时,会有一些重要的情况发生。第一个是基于组件的编程,你可以在应用程序构建器*集成开发环境*中使用*快速应用程序开发*(RAD)构建项目。这是一种通过将表示组件的图标移动到窗体上来创建程序的可视化方法。然后,通过在编程时设置这些组件的一些值来配置这些组件。这种设计时配置要求任何组件都是可实例化的,它公开自己的部分,并且允许读取和修改其属性。此外,处理*图形用户界面*(GUI)事件的组件必须公开有关适当方法的信息,以便 IDE 可以帮助程序员覆写这些事件处理方法。反射提供了检测可用方法并生成方法名称的机制。 +在传统编程环境中,这是一个牵强的场景。但是,当我们进入一个更大的编程世界时,有一些重要的情况发生在这种情况下。第一个是基于组件的编程,你可以在应用程序构建器 *集成开发环境 (Integrated Development Environment IDE)* 中使用 *快速应用程序开发 (Rapid Application Development RAD)* 构建项目。这是一种通过将表示组件的图标移动到窗体上来创建程序的可视化方法。然后,通过在编程时设置这些组件的一些值来配置这些组件。这种【设计时配置】要求任何组件都是可实例化的,它公开自己的部分,并且允许读取和修改其属性。此外,处理*图形用户界面*(*Graphical User Interface* GUI)事件的组件必须公开有关适当方法的信息,以便 IDE 可以帮助程序员重写这些事件处理方法。反射提供了检测可用方法并生成方法名称的机制。 -在运行时发现类信息的另一个令人信服的动机是提供跨网络在远程平台上创建和执行对象的能力。这称为*远程方法调用*(RMI),它使 Java 程序的对象分布在许多机器上。这种分布有多种原因。如果你想加速一个计算密集型的任务,你可以把它分解成小块放到空闲的机器上。或者你可以将处理特定类型任务的代码(例如,多层次客户机/服务器体系结构中的“业务规则”)放在特定的机器上,这样机器就成为描述这些操作的公共存储库,并且可以很容易地更改它以影响系统中的每个人。分布式计算还支持专门的硬件,这些硬件可能擅长于某个特定的任务——例如矩阵转换——但对于通用编程来说不合适或过于昂贵。 +在运行时发现类信息的另一个令人信服的动机是提供跨网络在远程平台上创建和执行对象的能力。这称为*远程方法调用*(*Remote Method Invocation* RMI),它使 Java 程序的对象分布在许多机器上。这种分布有多种原因。如果你想加速一个计算密集型的任务,你可以把它分解成小块放到空闲的机器上。或者你可以将处理特定类型任务的代码(例如,多层次客户机/服务器体系结构中的“业务规则”)放在特定的机器上,这样机器就成为描述这些操作的公共存储库,并且可以很容易地更改它以影响系统中的每个人。分布式计算还支持专门的硬件,这些硬件可能擅长于某个特定的任务——例如矩阵转换——但对于通用编程来说不合适或过于昂贵。 -类 `Class` 支持*反射*的概念, `java.lang.reflect` 库中包含类 `Field`、`Method` 和 `Constructor`(每一个都实现了 `Member` 接口)。这些类型的对象由 JVM 在运行时创建,以表示未知类中的对应成员。然后,可以使用 `Constructor` 创建新对象,`get()` 和 `set()` 方法读取和修改与 `Field` 对象关联的字段,`invoke()` 方法调用与 `Method` 对象关联的方法。此外,还可以调用便利方法 `getFields()`、`getMethods()`、`getConstructors()` 等,以返回表示字段、方法和构造函数的对象数组。(你可以通过在 JDK 文档中查找类 `Class` 来了解更多信息。)因此,匿名对象的类信息可以在运行时完全确定,编译时不需要知道任何信息。 +`Class`类支持 *反射 reflection* 的概念 和 `java.lang.reflect` 库——该库包含类 `Field`、`Method` 和 `Constructor`(每一个都实现了 `Member` 接口)。这些类型的对象由 JVM 在运行时创建,以表示未知类中的对应成员。然后,可以使用 `Constructor` 创建新对象,`get()` 和 `set()` 方法读取和修改与 `Field` 对象关联的字段,`invoke()` 方法调用与 `Method` 对象关联的方法。此外,还可以调用便利方法 `getFields()`、`getMethods()`、`getConstructors()` 等,以返回表示字段、方法和构造函数的对象数组。(你可以通过在 JDK 文档中查找类 `Class` 来了解更多信息。)因此,匿名对象的类信息可以在运行时完全确定,编译时不需要知道任何信息。 -重要的是要意识到反射没有什么魔力。当你使用反射与未知类型的对象交互时,JVM 将查看该对象,并看到它属于特定的类(就像普通的 RTTI)。在对其执行任何操作之前,必须加载 `Class` 对象。因此,该特定类型的 `.class` 文件必须在本地计算机上或通过网络对 JVM 仍然可用。因此,RTTI 和反射的真正区别在于,使用 RTTI 时,编译器在编译时会打开并检查 `.class` 文件。换句话说,你可以用“正常”的方式调用一个对象的所有方法。通过反射,`.class` 文件在编译时不可用;它由运行时环境打开并检查。 +重要的是要意识到反射并没有什么神奇的地方。当你使用反射与未知类型的对象交互时,JVM 将查看该对象,并看到它属于特定的类(就像普通的 RTTI)。在对其执行任何操作之前,必须加载 `Class` 对象。因此,该特定类型的 `.class` 文件仍然必须对 JVM 可用,无论是在本地机器上或在网络上。因此,RTTI 和反射的真正区别在于,使用 RTTI 时,编译器在编译时会打开并检查 `.class` 文件。换句话说,你可以用“正常”的方式调用一个对象的所有方法。通过反射,`.class` 文件在编译时不可用;它由运行时环境打开并检查。 ### 类方法提取器 通常,你不会直接使用反射工具,但它们可以帮助你创建更多的动态代码。反射是用来支持其他 Java 特性的,例如对象序列化(参见[附录:对象序列化](https://lingcoder.github.io/OnJava8/#/book/Appendix-Object-Serialization))。但是,有时动态提取有关类的信息很有用。 -考虑一个类方法提取器。查看类定义的源代码或 JDK 文档,只显示*在该类定义中*定义或重写的方法。但是,可能还有几十个来自基类的可用方法。找到它们既单调又费时[^1]。幸运的是,反射提供了一种方法,可以简单地编写一个工具类自动地向你展示所有的接口: +考虑一个类方法提取器。当我们在查看类定义的源代码或 JDK 文档的时候,它只显示*在该类定义中*定义或重写的方法。但是,可能还有几十个来自基类的可用方法。找到它们既繁琐又费时[^1]。幸运的是,反射提供了一种方法,可以简单地编写一个工具类自动地向你展示所有的接口: ```java // typeinfo/ShowMethods.java @@ -1381,24 +1381,19 @@ public class ShowMethods { Constructor[] ctors = c.getConstructors(); if (args.length == 1) { for (Method method : methods) - System.out.println( - p.matcher( - method.toString()).replaceAll("")); + System.out.println(p.matcher(method.toString()).replaceAll("")); for (Constructor ctor : ctors) - System.out.println( - p.matcher(ctor.toString()).replaceAll("")); + System.out.println(p.matcher(ctor.toString()).replaceAll("")); lines = methods.length + ctors.length; } else { for (Method method : methods) if (method.toString().contains(args[1])) { - System.out.println(p.matcher( - method.toString()).replaceAll("")); + System.out.println(p.matcher(method.toString()).replaceAll("")); lines++; } for (Constructor ctor : ctors) if (ctor.toString().contains(args[1])) { - System.out.println(p.matcher( - ctor.toString()).replaceAll("")); + System.out.println(p.matcher(ctor.toString()).replaceAll("")); lines++; } } @@ -1414,10 +1409,8 @@ public class ShowMethods { ``` public static void main(String[]) public final void wait() throws InterruptedException -public final void wait(long,int) throws -InterruptedException -public final native void wait(long) throws -InterruptedException +public final void wait(long,int) throws InterruptedException +public final native void wait(long) throws InterruptedException public boolean equals(Object) public String toString() public native int hashCode() @@ -1427,7 +1420,7 @@ public final native void notifyAll() public ShowMethods() ``` -`Class` 方法 `getmethods()` 和 `getconstructors()` 分别返回 `Method` 数组和 `Constructor` 数组。这些类中的每一个都有进一步的方法来解析它们所表示的方法的名称、参数和返回值。但你也可以像这里所做的那样,使用 `toString()`,生成带有整个方法签名的 `String`。代码的其余部分提取命令行信息,确定特定签名是否与目标 `String`(使用 `indexOf()`)匹配,并使用正则表达式(在 [Strings](#ch021.xhtml#strings) 一章中介绍)删除名称限定符。 +`Class` 方法 `getmethods()` 和 `getconstructors()` 分别返回 `Method` 数组和 `Constructor` 数组。这些类中的每一个都有进一步的方法来解析它们所表示的方法的名称、参数和返回值。但你也可以像这里所做的那样,使用 `toString()`,生成带有整个方法签名的 `String`。余下代码则提取命令行信息,使用`contains()`(其内在使用 `indexOf()`)确定特定方法签名是否与入参 `String`匹配,并使用正则表达式(在 [Strings](#ch021.xhtml#strings) 一章中介绍)删除名称限定符。 编译时无法知道 `Class.forName()` 生成的结果,因此所有方法签名信息都是在运行时提取的。如果你研究 JDK 反射文档,你将看到有足够的支持来实际设置和对编译时完全未知的对象进行方法调用(本书后面有这样的例子)。虽然最初你可能认为你永远都不需要这样做,但是反射的全部价值可能会令人惊讶。 @@ -1437,17 +1430,17 @@ public ShowMethods() java ShowMethods ShowMethods ``` -输出包含一个 `public` 无参数构造函数,即使未定义构造函数。你看到的构造函数是由编译器自动合成的。如果将 `ShowMethods` 设置为非 `public` 类(即只有包级访问权),则合成的无参数构造函数将不再显示在输出中。自动为合成的无参数构造函数授予与类相同的访问权。 +输出包含有一个 `public` 无参构造函数,即使未定义构造函数。你看到的构造函数是由编译器自动合成的。如果将 `ShowMethods` 设置为非 `public` 类(即变成包级访问权),那么输出中就没有合成的无参构造函数。这是因为合成的无参构造函数也变成了包级访问,是自动被赋予了和类相同的访问权限。 尝试运行 `java ShowMethods java.lang.String`,并附加一个 `char`、`int`、`String` 等参数。 -编程时,当你不记得某个类是否有特定的方法,并且不想在 JDK 文档中搜索索引或类层次结构时,或者如果你不知道该类是否可以对 `Color` 对象执行任何操作时,该工具能节省不少时间。 +编程时该工具能节省不少时间——当你不记得某个类是否有特定的方法,并且不想在 JDK 文档中搜索索引或类层次结构时;或者如果你不知道该类是否可以对某个对象,例如 `Color` 对象执行任何操作时。 ## 动态代理 -*代理*是基本的设计模式之一。一个对象封装真实对象,代替其提供其他或不同的操作---这些操作通常涉及到与“真实”对象的通信,因此代理通常充当中间对象。这是一个简单的示例,显示代理的结构: +*代理 Proxy* 是基本的设计模式之一。它是你插入一个对象来代替“真实”对象,以提供额外的或不同的操作——这些操作通常涉及到与“真实”对象的通信,所以代理通常作为一个中间人。这里有一个简单的示例展示代理的结构: ```java // typeinfo/SimpleProxyDemo.java @@ -1516,11 +1509,11 @@ somethingElse bonobo ``` 因为 `consumer()` 接受 `Interface`,所以它不知道获得的是 `RealObject` 还是 `SimpleProxy`,因为两者都实现了 `Interface`。 -但是,在客户端和 `RealObject` 之间插入的 `SimpleProxy` 执行操作,然后在 `RealObject` 上调用相同的方法。 +但是插入在客户端和 `RealObject` 之间的 `SimpleProxy` 会执行操作,然后在 `RealObject` 上调用相同的方法。 -当你希望将额外的操作与“真实对象”做分离时,代理可能会有所帮助,尤其是当你想要轻松地启用额外的操作时,反之亦然(设计模式就是封装变更---所以你必须改变一些东西以证明模式的合理性)。例如,如果你想跟踪对 `RealObject` 中方法的调用,或衡量此类调用的开销,该怎么办?你不想这部分代码耦合到你的程序中,而代理能使你可以很轻松地添加或删除它。 +当你希望将【额外的操作】与【“真实对象”】分离时,尤其是当你想要轻松地启用和停止【额外的操作】时,代理可能会有所帮助。(设计模式的要点是封装变更——所以你必须改变一些东西以证明模式的合理性)。例如,如果你想跟踪对 `RealObject` 中方法的调用,或测量这种调用的开销,该怎么办?你不想这部分代码耦合到你的程序中,而代理能使你可以很轻松地添加或删除它。 -Java 的*动态代理*更进一步,不仅动态创建代理对象而且动态处理对代理方法的调用。在动态代理上进行的所有调用都被重定向到单个*调用处理程序*,该处理程序负责发现调用的内容并决定如何处理。这是 `SimpleProxyDemo.java` 使用动态代理重写的例子: +Java 的*动态代理 dynamic proxy* 更进一步,不仅动态创建代理对象,而且动态处理对代理方法的调用。在动态代理上进行的所有调用都被重定向到单个*调用处理程序* *invocation handler*,该处理程序负责发现调用的内容并决定如何处理。这里是 `SimpleProxyDemo.java` 使用动态代理理念重写的例子: ```java // typeinfo/SimpleDynamicProxy.java @@ -1535,9 +1528,7 @@ class DynamicProxyHandler implements InvocationHandler { } @Override - public Object - invoke(Object proxy, Method method, Object[] args) - throws Throwable { + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "**** proxy: " + proxy.getClass() + ", method: " + method + ", args: " + args); @@ -1572,21 +1563,24 @@ class SimpleDynamicProxy { ``` doSomething somethingElse bonobo -**** proxy: class $Proxy0, method: public abstract void -Interface.doSomething(), args: null +**** proxy: class typeinfo.$Proxy0, method: public abstract void typeinfo.Interface.doSomething(), args: null doSomething -**** proxy: class $Proxy0, method: public abstract void -Interface.somethingElse(java.lang.String), args: -[Ljava.lang.Object;@6bc7c054 +**** proxy: class typeinfo.$Proxy0, method: public abstract void typeinfo.Interface.somethingElse(java.lang.String), args: [Ljava.lang.Object;@3b764bce bonobo somethingElse bonobo ``` -可以通过调用静态方法 `Proxy.newProxyInstance()` 来创建动态代理,该方法需要一个类加载器(通常可以从已加载的对象中获取),希望代理实现的接口列表(不是类或抽象类),以及接口 `InvocationHandler` 的一个实现。动态代理会将所有调用重定向到调用处理程序,因此通常为调用处理程序的构造函数提供对“真实”对象的引用,以便一旦执行中介任务便可以转发请求。 +可以通过调用静态方法 `Proxy.newProxyInstance()` 来创建动态代理,该方法的三个参数: + +- 1.一个类加载器(通常可以从已加载的对象中获取); +- 2.希望代理实现的接口列表(不是类或抽象类); +- 3.接口 `InvocationHandler` 的一个实现。 + +动态代理会将所有调用重定向到调用处理程序 `InvocationHandler`,因此,调用处理程序的构造函数通常被赋予对“真实”对象的引用,以便一旦执行中介任务就可以转发请求。 -`invoke()` 方法被传递给代理对象,以防万一你必须区分请求的来源---但是在很多情况下都无需关心。但是,在 `invoke()` 内的代理上调用方法时要小心,因为接口的调用是通过代理重定向的。 +`invoke()` 方法会被交给代理对象,以防你必须区分请求来自哪里——但是在很多情况下不会在意。然而,在调用 `invoke()` 中的代理方法时要小心,因为通过接口的调用会通过代理对象重定向。 -通常执行代理操作,然后使用 `Method.invoke()` 将请求转发给被代理对象,并携带必要的参数。这在一开始看起来是有限制的,好像你只能执行一般的操作。但是,可以过滤某些方法调用,同时传递其他方法调用: +一般来说,你执行代理操作,然后使用`Method.invoke()`将请求转发给代理对象,并传递必要的参数。这最初可能看起来很有局限性,好像你只能执行一般的操作。然而,你可以对某些方法调用进行过滤,而将其他方法传递过去: ```java // typeinfo/SelectingMethods.java @@ -1602,12 +1596,9 @@ class MethodSelector implements InvocationHandler { } @Override - public Object - invoke(Object proxy, Method method, Object[] args) - throws Throwable { + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("interesting")) - System.out.println( - "Proxy detected the interesting method"); + System.out.println("Proxy detected the interesting method"); return method.invoke(proxied, args); } } @@ -1681,7 +1672,7 @@ boring3 虽然 `Optional` 是 Java 8 为了支持流式编程才引入的,但其实它是一个通用的工具。为了证明这点,在本节中,我们会把它用在普通的类中。因为涉及一些运行时检测,所以把这一小节放在了本章。 -实际上,在所有地方都使用 `Optional` 是没有意义的,有时候检查一下是不是 `null` 也挺好的,或者有时我们可以合理地假设不会出现 `null`,甚至有时候检查 `NullPointException` 异常也是可以接受的。`Optional` 最有用武之地的是在那些“更接近数据”的地方,在问题空间中代表实体的对象上。举个简单的例子,很多系统中都有 `Person` 类型,代码中有些情况下你可能没有一个实际的 `Person` 对象(或者可能有,但是你还没用关于那个人的所有信息)。这时,在传统方法下,你会用到一个 `null` 引用,并且在使用的时候测试它是不是 `null`。而现在,我们可以使用 `Optional`: +在实践中,并非所有地方使用 `Optional` 都有意义的,有时检查一下 `null` 是可接受的,有时可以合理地假设不会出现 `null`,甚至有时通过 `NullPointException` 来检测异常也是可以接受的。`Optional` 最有用武之地的是在那些“更接近数据”的地方,用对象来代表问题空间中的实体。举个简单的例子,很多系统中都有 `Person` 类型,在代码中有些情况下,你可能没有一个实际的人(也许你有,但你还没有这个人的所有信息)。此时,在传统方法下,你会使用一个 `null` 引用,并且在使用的时候测试它是不是 `null`。而现在,我们可以使用 `Optional`: ```java // typeinfo/Person.java @@ -1747,11 +1738,11 @@ Bob Smith Bob Smith 11 Degree Lane, Frostbite Falls, MN ``` -`Person` 的设计有时候又叫“数据传输对象(DTO,data-transfer object)”。注意,所有字段都是 `public` 和 `final` 的,所以没有 `getter` 和 `setter` 方法。也就是说,`Person` 是不可变的,你只能通过构造器给它赋值,之后就只能读而不能修改它的值(字符串本身就是不可变的,因此你无法修改字符串的内容,也无法给它的字段重新赋值)。如果你想修改一个 `Person`,你只能用一个新的 `Person` 对象来替换它。`empty` 字段在对象创建的时候被赋值,用于快速判断这个 `Person` 对象是不是空对象。 +`Person` 的设计有时候又叫“数据传输对象(DTO,data-transfer object)”。注意,所有字段都是 `public` 和 `final` 的,所以没有 `getter` 和 `setter` 方法。也就是说,`Person` 是不可变的,你只能通过构造器给它赋值,之后就只能读而不能修改它的值(字符串本身就是不可变的,因此你无法修改字符串的内容,也无法给它的字段重新赋值)。如果你想修改一个 `Person`,你只能用一个新的 `Person` 对象来替换它。`empty` 字段在对象创建的时候被赋值,用于快速判断这个 `Person` 对象是否代表一个空对象。 -如果想使用 `Person`,就必须使用 `Optional` 接口才能访问它的 `String` 字段,这样就不会意外触发 `NullPointException` 了。 +无论是谁如果想使用 `Person`,就必须使用 `Optional` 接口才能访问它的 `String` 字段,这样就不会意外触发 `NullPointException` 了。 -现在假设你已经因你惊人的理念而获得了一大笔风险投资,现在你要招兵买马了,但是在虚位以待时,你可以将 `Person Optional` 对象放在每个 `Position` 上: +现在假设你已经为你的 "惊人创意 "获得了一大笔风险资金。您已经准备好增补职员,但是在您等待职位被填补的时候,你可以将 `Person Optional` 对象放在每个 `Position` 上: ```java // typeinfo/Position.java @@ -1829,9 +1820,9 @@ caught EmptyTitleException `Person` 字段的限制又不太一样:如果你把它的值设为 `null`,程序会自动把将它赋值成一个空的 `Person` 对象。先前我们也用过类似的方法把字段转换成 `Optional`,但这里我们是在返回结果的时候使用 `orElse(new Person())` 插入一个空的 `Person` 对象替代了 `null`。 -在 `Position` 里边,我们没有创建一个表示“空”的标志位或者方法,因为 `person` 字段的 `Person` 对象为空,就表示这个 `Position` 是个空缺位置。之后,你可能会发现你必须添加一个显式的表示“空位”的方法,但是正如 YAGNI[^2] (You Aren't Going to Need It,你永远不需要它)所言,在初稿时“实现尽最大可能的简单”,直到程序在某些方面要求你为其添加一些额外的特性,而不是假设这是必要的。 +在 `Position` 里边,我们没有创建一个表示“空”的标志位或者方法,因为 `person` 字段中的,空的 `Person` 对象就表示这个 `Position` 是个空缺位置。在以后,你可能会发现你必须添加一个显式的表示“空位”的方法,但是正如 YAGNI[^2] (You Aren't Going to Need It,你永远不需要它)所言,在初稿时“实现尽最大可能的简单”,直到程序在某些方面要求你为其添加一些额外的特性,而不是假设这是必要的。 -请注意,虽然你清楚你使用了 `Optional`,可以免受 `NullPointerExceptions` 的困扰,但是 `Staff` 类却对此毫不知情。 +请注意,`Staff` 类可以完全忽略 `Optional` 的存在(解耦),尽管你清楚你使用了 `Optional`,保护你免受 `NullPointerExceptions` 的困扰。 ```java // typeinfo/Staff.java @@ -1919,7 +1910,7 @@ package onjava; public interface Null {} ``` -如果你用接口取代具体类,那么就可以使用 `DynamicProxy` 来自动地创建 `Null` 对象。假设我们有一个 `Robot` 接口,它定义了一个名字、一个模型和一个描述 `Robot` 行为能力的 `List`: +如果你用接口取代具体类,那么就可以使用 `DynamicProxy` 来自动地创建 `Null` 对象。假设我们有一个 `Robot` 接口,它定义了一个名字、一个型号和一个描述 `Robot` 的行为能力列表 `List`: ```java // typeinfo/Robot.java @@ -2028,7 +2019,7 @@ Slusher can clear the roof Slusher clearing roof ``` -假设存在许多不同类型的 `Robot`,我们想让每种 `Robot` 都创建一个 `Null` 对象来执行一些特殊的操作——在本例中,即提供 `Null` 对象所代表 `Robot` 的确切类型信息。这些信息是通过动态代理捕获的: +假设存在许多不同类型的 `Robot`,我们希望每个 `Null` 为每个 `Robot` 类型做一些特别的事情——在本例中,即提供 `Null` 对象所代表 `Robot` 的确切类型信息。这些信息是通过动态代理捕获的: ```java // typeinfo/NullRobot.java @@ -2040,8 +2031,7 @@ import java.util.stream.*; import onjava.*; -class NullRobotProxyHandler - implements InvocationHandler { +class NullRobotProxyHandler implements InvocationHandler { private String nullName; private Robot proxied = new NRobot(); @@ -2075,8 +2065,7 @@ class NullRobotProxyHandler } public class NullRobot { - public static Robot - newNullRobot(Class type) { + public static Robot newNullRobot(Class type) { return (Robot) Proxy.newProxyInstance( NullRobot.class.getClassLoader(), new Class[] { Null.class, Robot.class }, @@ -2112,11 +2101,14 @@ Robot model: SnowRemovalRobot NullRobot ### Mock 对象和桩 -**Mock 对象**和 **桩(Stub)**在逻辑上都是 `Optional` 的变体。他们都是最终程序中所使用的“实际”对象的代理。不过,Mock 对象和桩都是假扮成那些可以传递实际信息的实际对象,而不是像 `Optional` 那样把包含潜在 `null` 值的对象隐藏。 +**Mock 对象**和 **桩(Stub)**在逻辑上都是 `Optional` 的变体。他们都是最终程序中所使用的“实际”对象的代理。不过,Mock 对象和桩都假装是真实的对象,提供真实的信息,而不是像 `Optional` 那样隐藏【包含潜在 `null` 值的对象】。 -Mock 对象和桩之间的的差别在于程度不同。Mock 对象往往是轻量级的,且用于自测试。通常,为了处理各种不同的测试场景,我们会创建出很多 Mock 对象。而桩只是返回桩数据,它通常是重量级的,并且经常在多个测试中被复用。桩可以根据它们被调用的方式,通过配置进行修改。因此,桩是一种复杂对象,它可以做很多事情。至于 Mock 对象,如果你要做很多事,通常会创建大量又小又简单的 Mock 对象。 +Mock 对象和桩之间的的区别是一个程度上的区别。Mock 对象往往是轻量级的,且用于自测试。通常很多 Mock 对象是为了处理各种测试情况而创建的。而桩只是返回桩数据,它通常是重量级的,并且经常在多个测试中被复用。桩可以根据它们被调用的方式,通过配置进行修改。因此,桩是一种复杂对象,它可以做很多事情。至于 Mock 对象,如果你必须做很多事,通常会创建很多小的、简单的 Mock 对象。 + +当你构建应用程序的测试驱动时,模拟对象能帮助你集中注意力。他们让你专注于你现在正在做的测试,同时推迟对你未创建对象的测试。他们让你专注于你正在测试的对象的部分,忽略你已经测试过或尚未测试的东西。他们还让你专注于你自己的代码,用简单的类代替复杂的框架类。https://zhuanlan.zhihu.com/p/27144800 + ## 接口和类型 `interface` 关键字的一个重要目标就是允许程序员隔离组件,进而降低耦合度。使用接口可以实现这一目标,但是通过类型信息,这种耦合性还是会传播出去——接口并不是对解耦的一种无懈可击的保障。比如我们先写一个接口: From c33bcd7c0dc39e3f5a295cd6c175626b98fdca7c Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Mon, 21 Dec 2020 16:26:55 +0800 Subject: [PATCH 44/68] chapter 19 end --- docs/book/19-Type-Information.md | 82 ++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 10 deletions(-) diff --git a/docs/book/19-Type-Information.md b/docs/book/19-Type-Information.md index fddf455a..5f0e6953 100755 --- a/docs/book/19-Type-Information.md +++ b/docs/book/19-Type-Information.md @@ -5,7 +5,7 @@ > RTTI(RunTime Type Information,运行时类型信息)能够在程序运行时发现和使用类型信息 -RTTI 把我们从只能在编译期进行面向类型操作的禁锢中解脱了出来,并且让我们可以使用某些非常强大的程序。对 RTTI 的需要,揭示了面向对象设计中许多有趣(并且复杂)的特性,同时也带来了关于如何组织程序的基本问题。 +RTTI (RunTime Type Information)把我们从只能在编译期进行面向类型操作的禁锢中解脱了出来,并且让我们可以使用某些非常强大的程序。对 RTTI 的需要,揭示了面向对象设计中许多有趣(并且复杂)的特性,同时也带来了关于如何组织程序的基本问题。 本章将讨论 Java 是如何在运行时识别对象和类信息的。主要有两种方式: @@ -324,7 +324,7 @@ Java 还提供了另一种方法来生成类对象的引用:**类字面常量* 3. **初始化**。如果该类具有超类,则先初始化超类,执行 `static` 初始化器和 `static` 初始化块。 -直到第一次引用一个 `static` 方法(构造器是隐式的 `static`)或者 **非常量** 的 `static` 字段,才会进行类初始化。 +直到第一次引用一个 `static` 方法(构造器是隐式的 `static`)或者 **非常量** 的 `static` 字段,才会进行类初始化。(当我们使用.class的方式时,初始化被延迟到了对静态方法或者是非常数静态域进行首次引用时才执行。) ```java // typeinfo/ClassInitialization.java @@ -1330,14 +1330,15 @@ x.getClass().equals(Base.class)) false x.getClass().equals(Derived.class)) true ``` -`test()` 方法使用两种形式的 `instanceof` 对其参数执行类型检查。然后,它获取 `Class` 引用,并使用 `==` 和 `equals()` 测试 `Class` 对象的相等性。令人放心的是,`instanceof` 和 `isInstance()` 产生的结果相同, `equals()` 和 `==` 产生的结果也相同。但测试本身得出了不同的结论。与类型的概念一致,`instanceof` 说的是“你是这个类,还是从这个类派生的类?”。另一方面,如果使用 `==` 比较实际的`Class` 对象,则与继承无关 —— 其 要么的确是该类型,要么不是。 +`test()` 方法使用两种形式的 `instanceof` 对其参数执行类型检查。然后,它获取 `Class` 引用,并使用 `==` 和 `equals()` 测试 `Class` 对象的相等性。令人放心的是,`instanceof` 和 `isInstance()` 产生的结果相同, `equals()` 和 `==` 产生的结果也相同。但测试本身得出了不同的结论。与类型的概念一致,`instanceof` 的意思是:“你是这个类,又或者是 从这个类派生的类?”。另一方面,如果使用 `==` 比较实际的`Class` 对象,则与继承无关 —— 其 要么的确是该类型,要么不是。 + ## 反射:运行时类信息 如果你不知道对象的确切类型,RTTI 会告诉你。但是,有一个限制:必须在编译时知道类型,才能使用 RTTI 检测它,并对信息做一些有用的事情。换句话说,编译器必须知道你使用的所有类。 -起初,这看起来并没有那么大的限制,但是假设你引用了一个不在程序空间中的对象。实际上,该对象的类在编译时甚至对程序都不可用。也许你从磁盘文件或网络连接中获得了大量的字节,并被告知这些字节代表一个类。由于这个类在编译器为你的程序生成代码后很长时间才会出现,你如何使用这样的类? +起初,这看起来并不是什么大的限制,但是假设你引用了一个不在程序空间中的对象。实际上,该对象的类在编译时甚至对程序都不可用。也许你从磁盘文件或网络连接中获得了大量的字节,并被告知这些字节代表一个类。由于这个类在编译器为你的程序生成代码后很长时间才会出现,你如何使用这样的类? 在传统编程环境中,这是一个牵强的场景。但是,当我们进入一个更大的编程世界时,有一些重要的情况发生在这种情况下。第一个是基于组件的编程,你可以在应用程序构建器 *集成开发环境 (Integrated Development Environment IDE)* 中使用 *快速应用程序开发 (Rapid Application Development RAD)* 构建项目。这是一种通过将表示组件的图标移动到窗体上来创建程序的可视化方法。然后,通过在编程时设置这些组件的一些值来配置这些组件。这种【设计时配置】要求任何组件都是可实例化的,它公开自己的部分,并且允许读取和修改其属性。此外,处理*图形用户界面*(*Graphical User Interface* GUI)事件的组件必须公开有关适当方法的信息,以便 IDE 可以帮助程序员重写这些事件处理方法。反射提供了检测可用方法并生成方法名称的机制。 @@ -2099,13 +2100,74 @@ Robot model: SnowRemovalRobot NullRobot 无论何时,如果你需要一个空 `Robot` 对象,只需要调用 `newNullRobot()`,并传递需要代理的 `Robot` 的类型。这个代理满足了 `Robot` 和 `Null` 接口的需要,并提供了它所代理的类型的确切名字。 -### Mock 对象和桩 +### 模拟对象和桩对象 + +**模拟对象 (Mock)** 和 **桩对象 (Stub)** 在逻辑上都是 `Optional` 的变体。他们都是最终程序中所使用的“实际”对象的代理。不过,模拟对象和桩都假装是真实的对象,提供真实的信息,而不是像 `Optional` 那样,去隐藏【包含潜在 `null` 值的对象】。 + +模拟对象和桩,它们都是为了同一个目标而出现的,代替依赖部分,让原先的“整合测试”简化为“单元测试”。而它们之间的区别在于程度不同: + +- 桩只是返回桩数据,它通常是重量级的,并且经常在多个测试中被复用。桩可以根据它们被调用的方式,通过配置进行修改。因此,桩是一种复杂对象,它可以做很多事。Stubs一般用来stub out那些难于创建或操纵的对象。一个经典的例子就是一个database connection。因此,一般的stub都被发现于系统边界,或者围绕着系统中复杂的对象群。为了建立一个stub,你建立了一个接口的另一种实现,利用简单的数据替换了真实的方法。总结为一句就是: **stub给被调用者( 方法/模块)制造假的返回值,以便不影响调用者的测试,用于提供测试的条件。** +- 模拟对象往往是轻量级的,且用于`自我测试(self-testing)`——每个测试用例都能够自行判断其后置条件(postcondition)是否得到满足,并依次来反馈测试的执行是否成功。通常很多模拟对象是为了处理各种测试情况而创建的。如果你需要做很多事,通常会创建很多小而简单的 模拟对象。总结为一句就是: **mock给被测试方法模拟一个预期的效果**。 + +Here we can begin to see the difference between mocks and stubs. If we were writing a test for this mailing behavior, we might write a simple stub like this. + +```java +public interface MailService { + public void send (Message msg); +} +public class MailServiceStub implements MailService { + private List messages = new ArrayList(); + public void send (Message msg) { + messages.add(msg); + } + public int numberSent() { + return messages.size(); + } +} +``` + +We can then use state verification on the stub like this. + +```java +class OrderStateTester... + public void testOrderSendsMailIfUnfilled() { + Order order = new Order(TALISKER, 51); + MailServiceStub mailer = new MailServiceStub(); + order.setMailer(mailer); + order.fill(warehouse); + assertEquals(1, mailer.numberSent()); + } +``` + +Of course this is a very simple test - only that a message has been sent. We've not tested it was sent to the right person, or with the right contents, but it will do to illustrate the point. + +Using mocks this test would look quite different. + +```java +class OrderInteractionTester... + public void testOrderSendsMailIfUnfilled() { + Order order = new Order(TALISKER, 51); + Mock warehouse = mock(Warehouse.class); + Mock mailer = mock(MailService.class); + order.setMailer((MailService) mailer.proxy()); + + mailer.expects(once()).method("send"); + warehouse.expects(once()).method("hasInventory") + .withAnyArguments() + .will(returnValue(false)); + + order.fill((Warehouse) warehouse.proxy()); + } +} +``` + +In both cases I'm using a test double instead of the real mail service. There is a difference in that the stub uses state verification while the mock uses behavior verification. + +In order to use state verification on the stub, I need to make some extra methods on the stub to help with verification. As a result the stub implements `MailService` but adds extra test methods. -**Mock 对象**和 **桩(Stub)**在逻辑上都是 `Optional` 的变体。他们都是最终程序中所使用的“实际”对象的代理。不过,Mock 对象和桩都假装是真实的对象,提供真实的信息,而不是像 `Optional` 那样隐藏【包含潜在 `null` 值的对象】。 +Mock objects always use behavior verification, a stub can go either way. Meszaros refers to stubs that use behavior verification as a Test Spy. The difference is in how exactly the double runs and verifies and I'll leave that for you to explore on your own.[Mocks Aren't Stubs] -Mock 对象和桩之间的的区别是一个程度上的区别。Mock 对象往往是轻量级的,且用于自测试。通常很多 Mock 对象是为了处理各种测试情况而创建的。而桩只是返回桩数据,它通常是重量级的,并且经常在多个测试中被复用。桩可以根据它们被调用的方式,通过配置进行修改。因此,桩是一种复杂对象,它可以做很多事情。至于 Mock 对象,如果你必须做很多事,通常会创建很多小的、简单的 Mock 对象。 -当你构建应用程序的测试驱动时,模拟对象能帮助你集中注意力。他们让你专注于你现在正在做的测试,同时推迟对你未创建对象的测试。他们让你专注于你正在测试的对象的部分,忽略你已经测试过或尚未测试的东西。他们还让你专注于你自己的代码,用简单的类代替复杂的框架类。https://zhuanlan.zhihu.com/p/27144800 @@ -2160,9 +2222,9 @@ B 通过使用 RTTI,我们发现 `a` 是用 `B` 实现的。通过将其转型为 `B`,我们可以调用不在 `A` 中的方法。 -这样的操作完全是合情合理的,但是你也许并不想让客户端开发者这么做,因为这给了他们一个机会,使得他们的代码与你的代码的耦合度超过了你的预期。也就是说,你可能认为 `interface` 关键字正在保护你,但其实并没有。另外,在本例中使用 `B` 来实现 `A` 这种情况是有公开案例可查的[^3]。 +这样的操作完全是合情合理的,但是你也许并不想让客户端开发者这么做,因为这给了他们一个机会,使得他们的代码与你的代码的耦合度超过了你的预期。也就是说,你可能认为 `interface` 关键字正保护着你,然而并没有。另外,在本例中使用 `B` 来实现 `A` 这种情况是有公开案例可查的[^3]。 -一种解决方案是直接声明,如果开发者决定使用实际的类而不是接口,他们需要自己对自己负责。这在很多情况下都是可行的,但“可能”还不够,你或许希望能有一些更严格的控制方式。 +一种解决方案是直接声明,如果开发者决定使用实际的类而不是接口,他们需要自己对自己负责。 在许多情况下,这可能是合理的,但如果这种“可能”还不足够的话,你会用更严格的控制方式。 最简单的方式是让实现类只具有包访问权限,这样在包外部的客户端就看不到它了: From b98c845619a8baa3f06ce5b4719b0cee18262092 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 22 Dec 2020 09:31:06 +0800 Subject: [PATCH 45/68] chapter 20 00 --- docs/book/20-Generics.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 72263fcc..268d5da2 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -6,9 +6,9 @@ > 普通的类和方法只能使用特定的类型:基本数据类型或类类型。如果编写的代码需要应用于多种类型,这种严苛的限制对代码的束缚就会很大。 -多态是一种面向对象思想的泛化机制。你可以将方法的参数类型设为基类,这样的方法就可以接受任何派生类作为参数,包括暂时还不存在的类。这样的方法更通用,应用范围更广。在类内部也是如此,在任何使用特定类型的地方,基类意味着更大的灵活性。除了 `final` 类(或只提供私有构造函数的类)任何类型都可被扩展,所以大部分时候这种灵活性是自带的。 +多态是一种面向对象思想的泛化工具。你可以将方法的参数类型设为基类,这样的方法就可以接受任何派生类作为参数,包括暂时还不存在的类。这样的方法更通用,应用范围更广。在类内部也是如此,在任何使用特定类型的地方,基类意味着更大的灵活性。除了 `final` 类(或只提供私有构造函数的类)之外的任何类型都可被扩展,所以大部分时候这种灵活性是自带的。 -拘泥于单一的继承体系太过局限,因为只有继承体系中的对象才能适用基类作为参数的方法中。如果方法以接口而不是类作为参数,限制就宽松多了,只要实现了接口就可以。这给予调用方一种选项,通过调整现有的类来实现接口,满足方法参数要求。接口可以突破继承体系的限制。 +单一的继承层次限制性太强,因为你必须从该层次结构中继承,才能产生一个适配你的方法参数的对象。如果一个方法参数是一个接口而不是一个类,那么限制就会放宽,包括任何实现了接口的东西。这就给了客户程序员一个选择,将接口与现有的类结合起来实现——也就是说,可以将现有的类改编成适配你的方法。接口可以跨越类的继承层次结构,只要你可以选择实现这些接口来适配。 即便是接口也还是有诸多限制。一旦指定了接口,它就要求你的代码必须使用特定的接口。而我们希望编写更通用的代码,能够适用“非特定的类型”,而不是一个具体的接口或类。 @@ -126,7 +126,7 @@ public class Diamond { 有时一个方法需要能返回多个对象。而 **return** 语句只能返回单个对象,解决方法就是创建一个对象,用它打包想要返回的多个对象。当然,可以在每次需要的时候,专门创建一个类来完成这样的工作。但是有了泛型,我们就可以一劳永逸。同时,还获得了编译时的类型安全。 -这个概念称为*元组*,它是将一组对象直接打包存储于单一对象中。可以从该对象读取其中的元素,但不允许向其中存储新对象(这个概念也称为 *数据传输对象* 或 *信使* )。 +这个概念称为 *元组* *tuple*,它是将一组对象包裹在一起,形成一个对象。 允许对象的接收者读取元素,但不允许将新元素放入其中。(这个概念也称为 *数据传输对象* *Data Transfer Object* 或 *信使* *Messenger*)。 通常,元组可以具有任意长度,元组中的对象可以是不同类型的。不过,我们希望能够为每个对象指明类型,并且从元组中读取出来时,能够得到正确的类型。要处理不同长度的问题,我们需要创建多个不同的元组。下面是一个可以存储两个对象的元组: @@ -149,7 +149,7 @@ public class Tuple2 { 构造函数传入要存储的对象。这个元组隐式地保持了其中元素的次序。 -初次阅读上面的代码时,你可能认为这违反了 Java 编程的封装原则。`a1` 和 `a2` 应该声明为 **private**,然后提供 `getFirst()` 和 `getSecond()` 取值方法才对呀?考虑下这样做能提供的“安全性”是什么:元组的使用程序可以读取 `a1` 和 `a2` 然后对它们执行任何操作,但无法对 `a1` 和 `a2` 重新赋值。例子中的 `final` 可以实现同样的效果,并且更为简洁明了。 +初次阅读上面的代码时,你可能认为这违反了 Java 编程封装的安全性原则。`a1` 和 `a2` 应该声明为 **private**,然后提供 `getFirst()` 和 `getSecond()` 取值方法才对呀?考虑下这样做提供的所谓“安全性”实际是什么:元组的使用程序可以读取 `a1` 和 `a2` 然后对它们执行任何操作,但无法对 `a1` 和 `a2` 重新赋值。而例子中的 `final` 就可以实现同样的效果,并且更为简洁明了。 另一种设计思路是允许元组的用户给 `a1` 和 `a2` 重新赋值。然而,采用上例中的形式无疑更加安全,如果用户想存储不同的元素,就会强制他们创建新的 `Tuple2` 对象。 @@ -292,7 +292,7 @@ public class LinkedStack { } } - private Node top = new Node<>(); // 栈顶 + private Node top = new Node<>(); // 末端标识 public void push(T item) { top = new Node<>(item, top); From ae6a6421424b21c6937a970b49de6650c31e4c61 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 22 Dec 2020 16:21:21 +0800 Subject: [PATCH 46/68] chapter 20 01 --- docs/book/20-Generics.md | 112 ++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 268d5da2..b7ea4f7d 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -529,15 +529,19 @@ public class Fibonacci implements Supplier { 如果还想更进一步,编写一个实现了 `Iterable` 的 `Fibnoacci` 生成器。我们的一个选择是重写这个类,令其实现 `Iterable` 接口。不过,你并不是总能拥有源代码的控制权,并且,除非必须这么做,否则,我们也不愿意重写一个类。而且我们还有另一种选择,就是创建一个 *适配器* (Adapter) 来实现所需的接口,我们在前面介绍过这个设计模式。 -有多种方法可以实现适配器。例如,可以通过继承来创建适配器类: +有多种方法可以实现适配器。例如,可以通过继承来创建适配器类 : + +``` +【类适配器模式】新定义一个适配器类,它实现了需求对应的接口,并继承现有的业务类, +通过在接口方法中显式地调用父类的方法的方式,达到适应新需求同时又复用现有方法代码的目的 +``` ```java // generics/IterableFibonacci.java // Adapt the Fibonacci class to make it Iterable import java.util.*; -public class IterableFibonacci -extends Fibonacci implements Iterable { +public class IterableFibonacci extends Fibonacci implements Iterable { private int n; public IterableFibonacci(int count) { n = count; } @@ -579,7 +583,7 @@ extends Fibonacci implements Iterable { 到目前为止,我们已经研究了参数化整个类。其实还可以参数化类中的方法。类本身可能是泛型的,也可能不是,不过这与它的方法是否是泛型的并没有什么关系。 -泛型方法独立于类而改变方法。作为准则,请“尽可能”使用泛型方法。通常将单个方法泛型化要比将整个类泛型化更清晰易懂。 +泛型方法独立于类而改变方法。它的使用准则是:只要条件允许,应该随时随地使用泛型方法。通常将单个方法泛型化要比将整个类泛型化更清晰易懂。 如果方法是 **static** 的,则无法访问该类的泛型类型参数,因此,如果使用了泛型类型参数,则它必须是泛型方法。 @@ -617,7 +621,7 @@ GenericMethods 对于泛型类,必须在实例化该类时指定类型参数。使用泛型方法时,通常不需要指定参数类型,因为编译器会找出这些类型。 这称为 *类型参数推断*。因此,对 `f()` 的调用看起来像普通的方法调用,并且 `f()` 看起来像被重载了无数次一样。它甚至会接受 **GenericMethods** 类型的参数。 -如果使用基本类型调用 `f()` ,自动装箱就开始起作用,自动将基本类型包装在它们对应的包装类型中。 +如果调用 `f()` 使用了基本类型 ,自动装箱就开始起作用,自动将基本类型包装在它们对应的包装类型中。 ### 变长参数和泛型方法 @@ -659,12 +663,35 @@ S, T, U, V, W, X, Y, Z] 此处显示的 `makeList()` 方法产生的功能与标准库的 `java.util.Arrays.asList()` 方法相同。 -`@SafeVarargs` 注解保证我们不会对变长参数列表进行任何修改,这是正确的,因为我们只从中读取。如果没有此注解,编译器将无法知道这些并会发出警告。 +`@SafeVarargs` 注解保证我们不会对变长参数列表进行任何修改,这是正确的,因为我们只从中读取。如果没有此注解,编译器就无法知道,并发出警告。 + +```java +// Mixing generics and varargs can violate type safety! +static void dangerous(List... stringLists) { + List intList = List.of(42); + Object[] objects = stringLists; + objects[0] = intList; // Heap pollution + String s = stringLists[0].get(0); // ClassCastException +} +//当参数化类型的变量引用不属于该类型的对象时,会发生堆污染(Heap pollution ) +``` + +本质上,SafeVarargs注释代表了该方法作者的一个承诺,它是类型安全的(the SafeVarargs annotation constitutes a promise by the author of a method that it is typesafe)。作为对此承诺的交换,编译器同意不会警告用户——调用该方法可能是不安全的。 + +除非方法实际上是安全的,否则不要使用`@SafeVarargs`注释方法,这点至关重要。所以确保这一点【方法是安全的】需要什么呢?回想一下,在调用方法时会创建一个泛型数组,用来保存可变参数。如果方法没有将任何内容存储到数组中(这会覆盖参数)并且不允许对数组的引用进行转义(这会使不受信任的代码访问数组),那么它就是安全的。换句话说,如果可变参数数组仅用于从调用者向方法传递可变数量的参数——毕竟这是可变参数的目的——那么该方法就是安全的。 + +决定何时使用SafeVarargs注释的规则很简单:**在每个方法上使用`@SafeVarargs`,使用泛型或参数化类型的可变参数,** 这样其用户就不用承担不必要和令人困惑的编译器警告的负担。这意味着你永远不应该编写像dangerous或toArray这样的不安全的可变参数方法。每次编译器在你控制的方法中警告你可能存在来自泛型可变参数的堆污染时,请检查该方法是否安全。提醒一下,如果符合以下条件,泛型可变参数方法是安全的: + +  1、它不会在可变参数数组中存储任何内容。 +  2、它不会使数组(或克隆出来的数组)对不受信任的代码可见。 + +  请注意,`@SafeVarargs`注释仅对无法覆盖的方法是合法的,因为无法保证每个可能的重写方法都是安全的。在Java 8中,注释仅对静态方法和final的实例方法合法; 在Java 9中,它在private实例方法上也是合法的。 + ### 一个泛型的 Supplier -这是一个为任意具有无参构造方法的类生成 **Supplier** 的类。为了减少键入,它还包括一个用于生成 **BasicSupplier** 的泛型方法: +这是一个类,为任何具有无参构造方法的类生成 **Supplier** 。为了减少键入,它还包括一个用于生成 **BasicSupplier** 的泛型方法: ```java // onjava/BasicSupplier.java @@ -767,18 +794,15 @@ public class Tuple { return new Tuple2<>(a, b); } - public static Tuple3 - tuple(A a, B b, C c) { + public static Tuple3 tuple(A a, B b, C c) { return new Tuple3<>(a, b, c); } - public static Tuple4 - tuple(A a, B b, C c, D d) { + public static Tuple4 tuple(A a, B b, C c, D d) { return new Tuple4<>(a, b, c, d); } - public static - Tuple5 tuple(A a, B b, C c, D d, E e) { + public static Tuple5 tuple(A a, B b, C c, D d, E e) { return new Tuple5<>(a, b, c, d, e); } } @@ -814,8 +838,7 @@ public class TupleTest2 { new Vehicle(), new Amphibian(), "hi", 47); } - static Tuple5 k() { + static Tuple5 k() { return tuple(new Vehicle(), new Amphibian(), "hi", 47, 11.1); } @@ -860,16 +883,14 @@ public class Sets { return result; } - public static - Set intersection(Set a, Set b) { + public static Set intersection(Set a, Set b) { Set result = new HashSet<>(a); result.retainAll(b); return result; } // Subtract subset from superset: - public static Set - difference(Set superset, Set subset) { + public static Set difference(Set superset, Set subset) { Set result = new HashSet<>(superset); result.removeAll(subset); return result; @@ -884,7 +905,7 @@ public class Sets { 前三个方法通过将第一个参数的引用复制到新的 **HashSet** 对象中来复制第一个参数,因此不会直接修改参数集合。因此,返回值是一个新的 **Set** 对象。 -这四种方法代表数学集合操作: `union()` 返回一个包含两个参数并集的 **Set** , `intersection()` 返回一个包含两个参数集合交集的 **Set** , `difference()` 从 **superset** 中减去 **subset** 的元素 ,而 `complement()` 返回所有不在交集中的元素的 **Set**。作为显示这些方法效果的简单示例的一部分,下面是一个包含不同水彩名称的 **enum** : +这四种方法代表数学集合操作: `union()` 返回一个包含两个参数并集的 **Set** , `intersection()` 返回一个包含两个参数集合交集的 **Set** , `difference()` 从 **superset** 中减去 **subset** 后剩余的元素 (差集),而 `complement()` 返回所有不在交集中的元素的 **Set** (交集的补集)。作为显示这些方法效果的简单示例的一部分,下面是一个包含不同水彩名称的 **enum** : ```java // generics/watercolors/Watercolors.java @@ -1106,8 +1127,7 @@ import onjava.Tuple4; import java.util.ArrayList; -public class TupleList - extends ArrayList> { +public class TupleList extends ArrayList> { public static void main(String[] args) { TupleList tl = new TupleList<>(); @@ -1237,7 +1257,7 @@ public class Store extends ArrayList { ## 泛型擦除 -当你开始更深入地钻研泛型时,会发现有大量的东西初看起来是没有意义的。例如,尽管可以说 `ArrayList.class`,但不能说成 `ArrayList.class`。考虑下面的情况: +当你开始更深入地钻研泛型时,会发现有大量的东西初看起来是没有意义的。例如,虽然可以说 `ArrayList.class`,但不能说成 `ArrayList.class`。考虑以下情况: ```java // generics/ErasedTypeEquivalence.java @@ -1299,9 +1319,9 @@ public class LostInformation { 残酷的现实是: -在泛型代码内部,无法获取任何有关泛型参数类型的信息。 +> 在泛型代码内部,无法获取任何有关泛型参数类型的信息。 -因此,你可以知道如类型参数标识符和泛型边界这些信息,但无法得知实际的类型参数从而用来创建特定的实例。如果你曾是 C++ 程序员,那么这个事实会让你很沮丧,在使用 Java 泛型工作时,它是必须处理的最基本的问题。 +因此,你可以知道如类型参数标识符和泛型边界这些信息,但无法得知实际的类型参数从而用来创建特定的实例。如果你曾是 C++ 程序员,那么这个事实会让你很沮丧,在使用 Java 泛型工作时,这一事实是必须处理的最基本的问题。 Java 泛型是使用擦除实现的。这意味着当你在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。因此,`List` 和 `List` 在运行时实际上是相同的类型。它们都被擦除成原生类型 `List`。 @@ -1399,9 +1419,9 @@ public class Manipulator2 { 边界 `` 声明 T 必须是 HasF 类型或其子类。如果情况确实如此,就可以安全地在 **obj** 上调用 `f()` 方法。 -我们说泛型类型参数会擦除到它的第一个边界(可能有多个边界,稍后你将看到)。我们还提到了类型参数的擦除。编译器实际上会把类型参数替换为它的擦除,就像上面的示例,**T** 擦除到了 **HasF**,就像在类的声明中用 **HasF** 替换了 **T** 一样。 +我们说泛型类型参数会擦除到它的第一个边界(可能有多个边界,稍后你将看到)【如果泛型参数是有界的, 那么编译之后会替换成边界, 否则的话会替换成`Object`】。我们还提到了类型参数的擦除。编译器实际上会把类型参数替换为它的擦除,因此在上述例子中,**T** 擦除到了 **HasF**,就像在类的声明中用 **HasF** 替换了 **T** 一样。 -你可能正确地观察到了泛型在 **Manipulator2.java** 中没有贡献任何事。你可以很轻松地自己去执行擦除,生成没有泛型的类: +你可能正确地观察到:泛型在 **Manipulator2.java** 中没有任何贡献。你可以很轻松地自己执行擦除,生成没有泛型的类: ```java // generics/Manipulator3.java @@ -1447,15 +1467,31 @@ public class ReturnGenericType { 如果 Java 1.0 就含有泛型的话,那么这个特性就不会使用擦除来实现——它会使用具体化,保持参数类型为第一类实体,因此你就能在类型参数上执行基于类型的语言操作和反射操作。本章稍后你会看到,擦除减少了泛型的泛化性。泛型在 Java 中仍然是有用的,只是不如它们本来设想的那么有用,而原因就是擦除。 -在基于擦除的实现中,泛型类型被当作第二类类型处理,即不能在某些重要的上下文使用泛型类型。泛型类型只有在静态类型检测期间才出现,在此之后,程序中的所有泛型类型都将被擦除,替换为它们的非泛型上界。例如, `List` 这样的类型注解会被擦除为 **List**,普通的类型变量在未指定边界的情况下会被擦除为 **Object**。 +第一类对象(First-class Object)在1960年由Christopher Strachey发明,原来称之为一等公民(First-class citizen),意思是指函数可以作为电脑中的一等公民。英文中也称之为First-class entity或First-class value。 + + +> +> 闲话:很多资料把 first-class object 翻译成 “第一类对象”,我觉得还是翻译成 “一等对象” 比较好,因为它明显借用了英语中 “一等公民” first-class citizen 的说法。 + + + +第一类对象不一定是指面向对象程序设计中所指的对象,而是指程序中的所有实体(比如:变量、函数、队列、字典等等)。一般第一类对象具有一下特征: + +- 可以被存入变量或其他结构 +- 可以被作为参数传递给其他方法/函数 +- 可以被作为方法/函数的返回值 +- 可以在执行期被创建,而无需在设计期全部写出 +- 有固定身份 + +在基于擦除的实现中,泛型类型被当作第二类对象类型处理,即不能在某些重要的上下文使用泛型类型。泛型类型只有在静态类型检测期间才出现,在此之后,程序中的所有泛型类型都将被擦除,替换为它们的非泛型上界。例如, `List` 这样的类型注解会被擦除为 **List**,普通的类型变量在未指定边界的情况下会被擦除为 **Object**。 擦除的核心动机是你可以在泛化的客户端上使用非泛型的类库,反之亦然。这经常被称为“迁移兼容性”。在理想情况下,所有事物将在指定的某天被泛化。在现实中,即使程序员只编写泛型代码,他们也必须处理 Java 5 之前编写的非泛型类库。这些类库的作者可能从没想过要泛化他们的代码,或许他们可能刚刚开始接触泛型。 因此 Java 泛型不仅必须支持向后兼容性——现有的代码和类文件仍然合法,继续保持之前的含义——而且还必须支持迁移兼容性,使得类库能按照它们自己的步调变为泛型,当某个类库变为泛型时,不会破坏依赖于它的代码和应用。在确定了这个目标后,Java 设计者们和从事此问题相关工作的各个团队决策认为擦除是唯一可行的解决方案。擦除使得这种向泛型的迁移成为可能,允许非泛型的代码和泛型代码共存。 -例如,假设一个应用使用了两个类库 **X** 和 **Y**,**Y** 使用了类库 **Z**。随着 Java 5 的出现,这个应用和这些类库的创建者最终可能希望迁移到泛型上。但是当进行迁移时,它们有着不同的动机和限制。为了实现迁移兼容性,每个类库与应用必须与其他所有的部分是否使用泛型无关。因此,它们不能探测其他类库是否使用了泛型。因此,某个特定的类库使用了泛型这样的证据必须被”擦除“。 +例如,假设一个应用使用了两个类库 **X** 和 **Y**,**Y** 使用了类库 **Z**。随着 Java 5 的出现,这个应用和这些类库的创建者最终可能希望迁移到泛型上。但是当进行迁移时,它们有着不同的动机和限制。为了实现迁移兼容性,每个类库与应用必须与其他所有的部分是否使用泛型无关。因此,它们不能探测其他类库是否使用了泛型。因此,某个特定的类库使用了泛型的证据必须被”擦除“。 -如果没有某种类型的迁移途径,所有已经构建了很长时间的类库就需要与希望迁移到 Java 泛型上的开发者们说再见了。类库毫无争议是编程语言的一部分,对生产效率有着极大的影响,所以这种代码无法接受。擦除是否是最佳的或唯一的迁移途径,还待时间来证明。 +如果没有某种类型的迁移途径,所有已经构建了很长时间的类库就需要与选择迁移到 Java 泛型上的开发者们说再见了。类库可以说是编程语言中对生产力影响最大的部分,所以这不是一个可以接受的代价。擦除是否是最好的或唯一的迁移路径,只有时间才能证明。 ### 擦除的问题 @@ -1509,7 +1545,7 @@ public class ErasureAndInteritance { public static void main(String[] args) { Derived2 d2 = new Derived2(); Object obj = d2.get(); - d2.set(obj); // Warning here! + d2.set(obj); // Warning here! -> Unchecked call to 'set(T)' as a member of raw type 'GenericBase' } } ``` @@ -1524,13 +1560,13 @@ public class ErasureAndInteritance { 这个注解放置在产生警告的方法上,而不是整个类上。当你要关闭警告时,最好尽可能地“聚焦”,这样就不会因为过于宽泛地关闭警告,而导致意外地遮蔽掉真正的问题。 -可以推断,**Derived3** 产生的错误意味着编译器期望得到一个原生基类。 +可以推断,**Derived3** 产生的错误意味着编译器期望得到一个原生基类( No wildcard expected )。 当你希望将类型参数不仅仅当作 Object 处理时,就需要付出额外努力来管理边界,并且与在 C++、Ada 和 Eiffel 这样的语言中获得参数化类型相比,你需要付出多得多的努力来获得少得多的回报。这并不是说,对于大多数的编程问题而言,这些语言通常都会比 Java 更得心应手,只是说它们的参数化类型机制相比 Java 更灵活、更强大。 ### 边界处的动作 -因为擦除,我发现了泛型最令人困惑的方面是可以表示没有任何意义的事物。例如: +因为擦除,我发现了泛型最令人困惑的方面是——可以表示没有任何意义的事物。例如: ```java // generics/ArrayMaker.java @@ -1561,7 +1597,7 @@ public class ArrayMaker { */ ``` -即使 **kind** 被存储为 `Class`,擦除也意味着它实际被存储为没有任何参数的 **Class**。因此,当你在使用它时,例如创建数组,`Array.newInstance()` 实际上并未拥有 **kind** 所蕴含的类型信息。所以它不会产生具体的结果,因而必须转型,这会产生一条令你无法满意的警告。 +即使 **kind** 被存储为 `Class`,擦除也意味着它实际被存储为没有任何参数的 **Class**。因此,当你在使用它时,例如创建数组,`Array.newInstance()` 实际上并未拥有 **kind** 所蕴含的类型信息。所以它不会产生特定类型的结果,因而必须转型,这会产生一条碍眼的警告。 注意,对于在泛型中创建数组,使用 `Array.newInstance()` 是推荐的方式。 @@ -1622,7 +1658,7 @@ public class FilledList extends ArrayList { 即使编译器无法得知 `add()` 中的 **T** 的任何信息,但它仍可以在编译期确保你放入 **FilledList** 中的对象是 **T** 类型。因此,即使擦除移除了方法或类中的实际类型的信息,编译器仍可以确保方法或类中使用的类型的内部一致性。 -因为擦除移除了方法体中的类型信息,所以在运行时的问题就是*边界*:即对象进入和离开方法的地点。这些正是编译器在编译期执行类型检查并插入转型代码的地点。 +因为擦除移除了方法体中的类型信息,所以在运行时重要的是*边界*:即对象进入和离开方法的地点。这些点正是编译器在编译期执行类型检查并插入转型代码的地方。 考虑如下这段非泛型示例: @@ -1677,7 +1713,7 @@ public static void main(java.lang.String[]); 22: return ``` -`set()` 和 `get()` 方法存储和产生值,转型在调用 `get()` 时接受检查。 +`set()` 和 `get()` 方法分别存储和产生值,转型在调用 `get()` 时接受检查。 现在将泛型融入上例代码中: @@ -1732,9 +1768,9 @@ public static void main(java.lang.String[]); 22: return ``` -所产生的字节码是相同的。对进入 `set()` 的类型进行检查是不需要的,因为这将由编译器执行。而对 `get()` 返回的值进行转型仍然是需要的,只不过不需要你来操作,它由编译器自动插入,这样你就不用编写(阅读)杂乱的代码。 +所产生的字节码是相同的。对进入 `set()` 的类型进行检查是不需要的,因为这将由编译器执行。而对 `get()` 返回的值进行转型仍然是需要的,只不过不需要你来操作,它由编译器自动插入,这样你就不用编写和阅读杂乱的代码。 -`get()` 和 `set()` 产生了相同的字节码,这就告诉我们泛型的所有动作都发生在边界处——对入参的编译器检查和对返回值的转型。这有助于澄清对擦除的困惑,记住:“边界就是动作发生的地方”。 +`get()` 和 `set()` 产生了相同的字节码,这就告诉我们泛型的所有动作都发生在边界——编译时对入参的额外检查,以及对返回值的插入转类型。记住:“边界就是动作发生的地方”,这有助于解除对擦除的疑惑。 From f2b151760635a327a30c3f9cdb28a07eebef6cf9 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 22 Dec 2020 18:04:23 +0800 Subject: [PATCH 47/68] chapter 20 02 --- docs/book/20-Generics.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index b7ea4f7d..14dc9485 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -1800,7 +1800,7 @@ public class Erased { } ``` -有时,我们可以对这些问题进行编程,但是有时必须通过引入类型标签来补偿擦除。这意味着为所需的类型显式传递一个 **Class** 对象,以在类型表达式中使用它。 +有时,我们可以对这些问题进行编程,但是有时必须通过引入**类型标签**来补偿擦除。这意味着为所需的类型显式传递一个 **Class** 对象,以在类型表达式中使用它。 例如,由于擦除了类型信息,因此在上一个程序中尝试使用 **instanceof** 将会失败。类型标签可以使用动态 `isInstance()` : @@ -1922,7 +1922,7 @@ java.lang.InstantiationException: java.lang.Integer */ ``` -这样可以编译,但对于 `ClassAsFactory` 会失败,这是因为 **Integer** 没有无参构造函数。由于错误不是在编译时捕获的,因此语言创建者不赞成这种方法。他们建议使用显式工厂(**Supplier**)并约束类型,以便只有实现该工厂的类可以这样创建对象。这是创建工厂的两种不同方法: +这样可以编译,但对于 `ClassAsFactory` 会失败,这是因为 **Integer** 没有无参构造函数。由于错误不是在编译时捕获的,因此语言创建者不赞成这种方法。他们建议使用明确的工厂(**Supplier**)并约束类型,以便只有实现该工厂的类可以这样创建对象。这是创建工厂的两种不同方法: ```java // generics/FactoryConstraint.java @@ -2005,7 +2005,7 @@ public class FactoryConstraint { */ ``` -**IntegerFactory** 本身就是通过实现 `Supplier` 的工厂。 **Widget** 包含一个内部类,它是一个工厂。还要注意,**Fudge** 并没有做任何类似于工厂的操作,并且传递 `Fudge::new` 仍然会产生工厂行为,因为编译器将对函数方法 `::new` 的调用转换为对 `get()` 的调用。 +**IntegerFactory** 本身就是通过实现 `Supplier` 的工厂。 **Widget** 包含一个内部类,它是一个工厂。还要注意,**Fudge** 并没有做任何类似于工厂的操作,而传递 `Fudge::new` 仍然会产生工厂行为,因为编译器将对函数方法 `::new` 的调用转换为对 `get()` 的调用。 另一种方法是模板方法设计模式。在以下示例中,`create()` 是模板方法,在子类中被重写以生成该类型的对象: @@ -2054,7 +2054,7 @@ X ### 泛型数组 -正如在 **Erased.java** 中所看到的,我们无法创建泛型数组。通用解决方案是在试图创建泛型数组的时候使用 **ArrayList** : +正如在 **Erased.java** 中所看到的,我们无法创建泛型数组( `new T[SIZE] `)。通用解决方案是在试图创建泛型数组的时候使用 **ArrayList** : ```java // generics/ListOfGenerics.java @@ -2107,7 +2107,7 @@ public class ArrayOfGeneric { System.out.println(e.getMessage()); } // Runtime type is the raw (erased) type: - gia = (Generic[]) new Generic[SIZE]; + gia = (Generic[]) new Generic[SIZE]; //唯一方法 System.out.println(gia.getClass().getSimpleName()); gia[0] = new Generic<>(); //- gia[1] = new Object(); // Compile-time error @@ -2121,7 +2121,7 @@ Generic[] */ ``` -问题在于数组会跟踪其实际类型,而该类型是在创建数组时建立的。因此,即使 `gia` 被强制转换为 `Generic[]` ,该信息也仅在编译时存在(并且没有 **@SuppressWarnings** 注解,将会收到有关该强制转换的警告)。在运行时,它仍然是一个 **Object** 数组,这会引起问题。成功创建泛型类型的数组的唯一方法是创建一个已擦除类型的新数组,并将其强制转换。 +问题在于数组会跟踪其实际类型,而该类型是在创建数组时建立的。因此,即使 `gia` 被强转为 `Generic[]` ,该信息也仅在编译时存在(并且没有 **@SuppressWarnings** 注解,将会收到有关该强制转换的警告)。在运行时,它仍然是一个 **Object** 数组,这会引起问题。成功创建泛型类型的数组的唯一方法:创建一个已擦除类型的新数组,并将其强制转换。 让我们看一个更复杂的示例。考虑一个包装数组的简单泛型包装器: @@ -2166,9 +2166,9 @@ public class GenericArray { */ ``` -和以前一样,我们不能说 `T[] array = new T[sz]` ,所以我们创建了一个 **Object** 数组并将其强制转换。 +和之前一样,我们不能说 `T[] array = new T[sz]` ,所以我们创建了一个 **Object** 数组并将其强制转换。 -`rep()` 方法返回一个 `T[]` ,在主方法中它应该是 `gai` 的 `Integer[]`,但是如果调用它并尝试将结果转换为 `Integer[]` 引用,则会得到 **ClassCastException** ,这再次是因为实际的运行时类型为 `Object[]` 。 +`rep()` 方法返回一个 `T[]` ,在主方法中它应该是 `gai` 的 `Integer[]`,但是如果调用它并尝试将结果转换为 `Integer[]` 引用,则会得到 **ClassCastException** ,再一次地,因为实际的运行时类型为 `Object[]` 。 如果再注释掉 **@SuppressWarnings** 注解后编译 **GenericArray.java** ,则编译器会产生警告: @@ -2182,7 +2182,14 @@ Recompile with -Xlint:unchecked for details. 但是要真正确定,请使用 `-Xlint:unchecked` 进行编译: ```java -GenericArray.java:7: warning: [unchecked] unchecked cast array = (T[])new Object[sz]; ^ required: T[] found: Object[] where T is a type-variable: T extends Object declared in class GenericArray 1 warning +GenericArray.java:7: warning: [unchecked] unchecked cast + array = (T[])new Object[sz]; + ^ +required: T[] +found: Object[] +where T is a type-variable: + T extends Object declared in class GenericArray +1 warning ``` 确实是在抱怨那个强制转换。由于警告会变成噪音,因此,一旦我们确认预期会出现特定警告,我们可以做的最好的办法就是使用 **@SuppressWarnings** 将其关闭。这样,当警告确实出现时,我们将进行实际调查。 From 1e22998991554a9c668d963c73e8830a7ae7afba Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Wed, 23 Dec 2020 17:31:33 +0800 Subject: [PATCH 48/68] chapter 20 03 --- docs/book/20-Generics.md | 107 +++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 14dc9485..794add44 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -834,13 +834,11 @@ public class TupleTest2 { } static Tuple4 h() { - return tuple( - new Vehicle(), new Amphibian(), "hi", 47); + return tuple(new Vehicle(), new Amphibian(), "hi", 47); } static Tuple5 k() { - return tuple(new Vehicle(), new Amphibian(), - "hi", 47, 11.1); + return tuple(new Vehicle(), new Amphibian(), "hi", 47, 11.1); } public static void main(String[] args) { @@ -1922,7 +1920,7 @@ java.lang.InstantiationException: java.lang.Integer */ ``` -这样可以编译,但对于 `ClassAsFactory` 会失败,这是因为 **Integer** 没有无参构造函数。由于错误不是在编译时捕获的,因此语言创建者不赞成这种方法。他们建议使用明确的工厂(**Supplier**)并约束类型,以便只有实现该工厂的类可以这样创建对象。这是创建工厂的两种不同方法: +这样可以编译,但对于 `ClassAsFactory` 会失败,这是因为 **Integer** 没有无参构造函数。由于错误不是在编译时捕获的,因此语言创建者不赞成这种方法。他们建议使用明确的工厂(**Supplier**)并约束类型,以便只有实现该工厂的类可以这样创建对象。下面是创建工厂的 2 种不同方法: ```java // generics/FactoryConstraint.java @@ -2119,10 +2117,33 @@ public class ArrayOfGeneric { [Ljava.lang.Object; cannot be cast to [LGeneric; Generic[] */ +//String型数组的类型是用“[Ljava.lang.String”,数组类型的表示: +// a. " [ "表示一维数组, "[[ "二维数组 +// b. "L"代表这个数组是引用数据类型的数组. "java.lang.String"是数组元素的类型,标识这个数组是什么类型的数组.基本数据类型的每种类型都有自已对应的标识符,如int[] 的类型是"[I"表示它是int型的数组 ``` 问题在于数组会跟踪其实际类型,而该类型是在创建数组时建立的。因此,即使 `gia` 被强转为 `Generic[]` ,该信息也仅在编译时存在(并且没有 **@SuppressWarnings** 注解,将会收到有关该强制转换的警告)。在运行时,它仍然是一个 **Object** 数组,这会引起问题。成功创建泛型类型的数组的唯一方法:创建一个已擦除类型的新数组,并将其强制转换。 +```java +try { + Object obj = new Object(); + String str = (String)obj; //如果一个[Ljava.lang.Object 类型的实例并不指向[Ljava.lang.String类型的对象,强转肯定报错 +} catch (Exception e) { + System.err.println("not OK! "+e); +} + +try { + String str = new String(); + Object obj = str; + String str2 = (String)obj; + System.err.println("OK!"); +} catch (Exception e) { + System.err.println(e); +} +//not OK! java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String +//OK! +``` + 让我们看一个更复杂的示例。考虑一个包装数组的简单泛型包装器: ```java @@ -2168,7 +2189,7 @@ public class GenericArray { 和之前一样,我们不能说 `T[] array = new T[sz]` ,所以我们创建了一个 **Object** 数组并将其强制转换。 -`rep()` 方法返回一个 `T[]` ,在主方法中它应该是 `gai` 的 `Integer[]`,但是如果调用它并尝试将结果转换为 `Integer[]` 引用,则会得到 **ClassCastException** ,再一次地,因为实际的运行时类型为 `Object[]` 。 +`rep()` 方法返回一个 `T[]` ,在主方法中它应该是 `gai` 的 `Integer[]`,但是如果调用它并尝试将结果转换为 `Integer[]` 引用,则会得到 **ClassCastException** ,这又是因为实际的运行时类型为 `Object[]` 。 如果再注释掉 **@SuppressWarnings** 注解后编译 **GenericArray.java** ,则编译器会产生警告: @@ -2192,7 +2213,7 @@ where T is a type-variable: 1 warning ``` -确实是在抱怨那个强制转换。由于警告会变成噪音,因此,一旦我们确认预期会出现特定警告,我们可以做的最好的办法就是使用 **@SuppressWarnings** 将其关闭。这样,当警告确实出现时,我们将进行实际调查。 +确实是在抱怨那个强制转换。由于警告会变成噪音,因此,一旦我们确认预期会出现特定警告,最好的办法就是使用 **@SuppressWarnings** 将其关闭。这样,当警告确实出现时,我们将进行实际调查。 由于擦除,数组的运行时类型只能是 `Object[]` 。 如果我们立即将其转换为 `T[]` ,则在编译时会丢失数组的实际类型,并且编译器可能会错过一些潜在的错误检查。因此,最好在集合中使用 `Object[]` ,并在使用数组元素时向 **T** 添加强制类型转换。让我们来看看在 **GenericArray.java** 示例中会是怎么样的: @@ -2236,13 +2257,12 @@ public class GenericArray2 { } } /* Output: -0 1 2 3 4 5 6 7 8 9 -java.lang.ClassCastException: [Ljava.lang.Object; -cannot be cast to [Ljava.lang.Integer; +0 1 2 3 4 5 6 7 8 9 +java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer; */ ``` -最初,看起来并没有太大不同,只是转换的位置移动了。没有 **@SuppressWarnings** 注解,仍然会收到“unchecked”警告。但是,内部表示现在是 `Object[]` 而不是 `T[]` 。 调用 `get()` 时,它将对象强制转换为 **T** ,实际上这是正确的类型,因此很安全。但是,如果调用 `rep()` ,它将再次尝试将 `Object[]` 强制转换为 `T[]` ,但仍然不正确,并在编译时生成警告,并在运行时生成异常。因此,无法破坏基础数组的类型,该基础数组只能是 `Object[]` 。在内部将数组视为 `Object[]` 而不是 `T[]` 的优点是,我们不太可能会忘记数组的运行时类型并意外地引入了bug,尽管大多数(也许是全部)此类错误会在运行时被迅速检测到。 +最初,看起来并没有太大不同,只是转换的位置移动了。没有 **@SuppressWarnings** 注解,仍然会收到“unchecked”警告。但是,内部表示现在是 `Object[]` 而不是 `T[]` 。 调用 `get()` 时,它将对象强制转换为 **T** ,实际上这是正确的类型,因此很安全。但是,如果调用 `rep()` ,它将再次尝试将 `Object[]` 强制转换为 `T[]` ,但仍然不正确,并在编译时生成警告,并在运行时生成异常。因此,无法破坏基础数组的类型,该基础数组只能是 `Object[]` 。在内部将数组视为 `Object[]` 而不是 `T[]` 的优点是,我们不太可能会遗忘数组的运行时类型并意外地引入bug,而且这些bug大多数(也许是全部)会在运行时被迅速检测到。 对于新代码,请传入类型标记。在这种情况下,**GenericArray** 如下所示: @@ -2305,15 +2325,15 @@ Note: Recompile with -Xlint:unchecked for details. Neal Gafter(Java 5 的主要开发人员之一)在他的博客中[^2]指出,他在重写 Java 库时是很随意、马虎的,我们不应该像他那样做。Neal 还指出,他在不破坏现有接口的情况下无法修复某些 Java 库代码。因此,即使在 Java 库源代码中出现了一些习惯用法,它们也不一定是正确的做法。当查看库代码时,我们不能认为这就是要在自己代码中必须遵循的示例。 -请注意,在 Java 文献中推荐使用类型标记技术,例如 Gilad Bracha 的论文《Generics in the Java Programming Language》[^3],他指出:“例如,这种用法已广泛用于新的 API 中以处理注解。” 我发现此技术在人们对于舒适度的看法方面存在一些不一致之处;有些人强烈喜欢本章前面介绍的工厂方法。 +请注意,在 Java 文献中推荐使用类型标记技术,例如 Gilad Bracha 的论文《Generics in the Java Programming Language》[^3],他指出:“这种用法已广泛用于新的 API 中,例如用来处理注解。” 我发现此技术在人们对于舒适度的看法方面存在一些不一致之处;有些人强烈喜欢本章前面介绍的工厂方法。 ## 边界 -*边界*(bounds)在本章的前面进行了简要介绍。边界允许我们对泛型使用的参数类型施加约束。尽管这可以强制执行有关应用了泛型类型的规则,但潜在的更重要的效果是我们可以在绑定的类型中调用方法。 +*边界*(bounds)在本章的前面进行了简要介绍。边界允许我们对泛型使用的参数类型施加约束。这可以强制执行适用于某泛型的规则,而更重要的潜在效果是我们可以在绑定的类型中调用方法。 -由于擦除会删除类型信息,因此唯一可用于无限制泛型参数的方法是那些 **Object** 可用的方法。但是,如果将该参数限制为某类型的子集,则可以调用该子集中的方法。为了应用约束,Java 泛型使用了 `extends` 关键字。 +由于擦除会删除类型信息,所以对于一个无约束的泛型参数,你只能调用那些 **Object** 可用的方法。但是,如果将该参数限制为某类型的子集,则可以调用该子集中的方法。为了施加约束,Java 泛型重用了 `extends` 关键字。 重要的是要理解,当用于限定泛型类型时,`extends` 的含义与通常的意义截然不同。此示例展示边界的基础应用: @@ -2348,7 +2368,7 @@ class Coord { // This fails. Class must be first, then interfaces: // class WithColorCoord { -// Multiple bounds: +// Multiple bounds: 多个边界,类放在前,接口放在后 class WithColorCoord { T item; @@ -2382,7 +2402,7 @@ interface Weight { } // As with inheritance, you can have only one -// concrete class but multiple interfaces: +// concrete class but multiple interfaces: 一个实体类 和两个接口 class Solid { T item; @@ -2415,8 +2435,7 @@ class Solid { } } -class Bounded - extends Coord implements HasColor, Weight { +class Bounded extends Coord implements HasColor, Weight { @Override public java.awt.Color getColor() { return null; @@ -2439,7 +2458,7 @@ public class BasicBounds { } ``` -你可能会观察到 **BasicBounds.java** 中似乎包含一些冗余,它们可以通过继承来消除。在这里,每个继承级别还添加了边界约束: +你可能会观察到 **BasicBounds.java** 中似乎包含一些冗余,它们可以通过继承来消除(如下)。在这里每个继承级别还添加了边界约束: ```java // generics/InheritBounds.java @@ -2456,8 +2475,7 @@ class HoldItem { } } -class WithColor2 - extends HoldItem { +class WithColor2 extends HoldItem { WithColor2(T item) { super(item); } @@ -2467,8 +2485,7 @@ class WithColor2 } } -class WithColorCoord2 - extends WithColor2 { +class WithColorCoord2 extends WithColor2 { WithColorCoord2(T item) { super(item); } @@ -2486,8 +2503,7 @@ class WithColorCoord2 } } -class Solid2 - extends WithColorCoord2 { +class Solid2 extends WithColorCoord2 { Solid2(T item) { super(item); } @@ -2545,8 +2561,7 @@ class SuperHero { } } -class SuperSleuth - extends SuperHero { +class SuperSleuth extends SuperHero { SuperSleuth(POWER power) { super(power); } @@ -2556,9 +2571,7 @@ class SuperSleuth } } -class -CanineHero - extends SuperHero { +class CanineHero extends SuperHero { CanineHero(POWER power) { super(power); } @@ -2572,8 +2585,7 @@ CanineHero } } -class SuperHearSmell - implements SuperHearing, SuperSmell { +class SuperHearSmell implements SuperHearing, SuperSmell { @Override public void hearSubtleNoises() { } @@ -2622,7 +2634,7 @@ public class EpicBattle { 你已经在 [集合](book/12-Collections.md) 章节中看到了一些简单示例使用了通配符——在泛型参数表达式中的问号,在 [类型信息](book/19-Type-Information.md) 一章中这种示例更多。本节将更深入地探讨这个特性。 -我们的起始示例要展示数组的一种特殊行为:你可以将派生类的数组赋值给基类的引用: +我们从一个示例开始,它展示了数组的一种特殊行为:你可以将派生类的数组赋值给基类的引用: ```java // generics/CovariantArrays.java @@ -2663,11 +2675,11 @@ java.lang.ArrayStoreException: Orange `main()` 中的第一行创建了 **Apple** 数组,并赋值给一个 **Fruit** 数组引用。这是有意义的,因为 **Apple** 也是一种 **Fruit**,因此 **Apple** 数组应该也是一个 **Fruit** 数组。 -但是,如果实际的数组类型是 **Apple[]**,你可以在其中放置 **Apple** 或 **Apple** 的子类型,这在编译期和运行时都可以工作。但是你也可以在数组中放置 **Fruit** 对象。这对编译器来说是有意义的,因为它有一个 **Fruit[]** 引用——它有什么理由不允许将 **Fruit** 对象或任何从 **Fruit** 继承出来的对象(比如 **Orange**),放置到这个数组中呢?因此在编译期,这是允许的。然而,运行时的数组机制知道它处理的是 **Apple[]**,因此会在向数组中放置异构类型时抛出异常。 +但是,如果实际的数组类型是 **Apple[]**,你可以在其中放置 **Apple** 或 **Apple** 的子类型,这在编译期和运行时都可以工作。但是你也可以在数组中放置 **Fruit** 对象。这对编译器来说是有意义的,因为它有一个 **Fruit[]** 引用——它有什么理由不允许将 **Fruit** 对象或任何从 **Fruit** 继承出来的对象(比如 **Orange**),放置到这个数组中呢?因此在编译期,这是允许的。然而,【运行时的数组机制】知道它处理的是 **Apple[]**,因此【运行时的数组机制】会在放置异构(foreign)类型到数组时抛出异常。 -向上转型用在这里不合适。你真正在做的是将一个数组赋值给另一个数组。数组的行为是持有其他对象,这里只是因为我们能够向上转型而已,所以很明显,数组对象可以保留有关它们包含的对象类型的规则。看起来就像数组对它们持有的对象是有意识的,因此在编译期检查和运行时检查之间,你不能滥用它们。 +“向上转型”在这里不是恰当的描述。你真正在做的是将一个数组赋值给另一个数组。数组的行为是持有其他对象,但因为我们能够向上转型,所以很明显,数组对象可以保留有关它们所包含的对象类型的规则。这就好像数组是有意识地知道它们所容纳的(对象),因此在编译期检查和运行时检查都不能滥用数组。 -数组的这种赋值并不是那么可怕,因为在运行时你可以发现插入了错误的类型。但是泛型的主要目标之一是将这种错误检测移到编译期。所以当我们试图使用泛型集合代替数组时,会发生什么呢? +数组的这种赋值并不是那么可怕,因为在运行时你可以发现插入了错误的类型。但是泛型的主要目标之一是将这种错误检测提前到编译期。所以当我们试图使用泛型集合代替数组时,会发生什么呢? ```java // generics/NonCovariantGenerics.java @@ -2681,9 +2693,9 @@ public class NonCovariantGenerics { } ``` -尽管你在首次阅读这段代码时会认为“不能将一个 **Apple** 集合赋值给一个 **Fruit** 集合”。记住,泛型不仅仅是关于集合,它真正要表达的是“不能把一个涉及 **Apple** 的泛型赋值给一个涉及 **Fruit** 的泛型”。如果像在数组中的情况一样,编译器对代码的了解足够多,可以确定所涉及到的集合,那么它可能会留下一些余地。但是它不知道任何有关这方面的信息,因此它拒绝向上转型。然而实际上这也不是向上转型—— **Apple** 的 **List** 不是 **Fruit** 的 **List**。**Apple** 的 **List** 将持有 **Apple** 和 **Apple** 的子类型,**Fruit** 的 **List** 将持有任何类型的 **Fruit**。是的,这包括 **Apple**,但是它不是一个 **Apple** 的 **List**,它仍然是 **Fruit** 的 **List**。**Apple** 的 **List** 在类型上不等价于 **Fruit** 的 **List**,即使 **Apple** 是一种 **Fruit** 类型。 +尽管你在首次阅读这段代码时会认为“不能将一个 **Apple** 集合赋值给一个 **Fruit** 集合”。记住,泛型不仅仅是关于集合,它真正要表达的是“不能把一个 **Apple** 的泛型赋值给一个 **Fruit** 的泛型”。如果和在数组中的情况一样,编译器对代码的了解足够多,可以确定所涉及到的集合,那么它可能会留下一些余地。但是它不知道任何有关这方面的信息,因此它不允许向上转型。然而实际上这也不是向上转型—— **Apple** 的 **List** 不是 **Fruit** 的 **List**。**Apple** 的 **List** 将持有 **Apple** 和 **Apple** 的子类型,**Fruit** 的 **List** 将持有任何类型的 **Fruit**。是的,这包括 **Apple**,但是它不是一个 **Apple** 的 **List**,它仍然是 **Fruit** 的 **List**。**Apple** 的 **List** 在类型上不等价于 **Fruit** 的 **List**,即使 **Apple** 是一种 **Fruit** 类型。 -真正的问题是我们在讨论的集合类型,而不是集合持有对象的类型。与数组不同,泛型没有内建的协变类型。这是因为数组是完全在语言中定义的,因此可以具有编译期和运行时的内建检查,但是在使用泛型时,编译器和运行时系统不知道你想用类型做什么,以及应该采用什么规则。 +真正的问题是我们在讨论的集合类型,而不是集合持有对象的类型。与数组不同,泛型没有内建的协变类型。这是因为数组是完全在java语言中定义的,因此可以具有编译期和运行时的内建检查,但是在使用泛型时,编译器和运行时系统不知道你想用类型做什么,以及应该采用什么规则。(Java中,数组是协变的,泛型是不变的,``实现了泛型的协变,``实现了泛型的逆变) 但是,有时你想在两个类型间建立某种向上转型关系。通配符可以产生这种关系。 @@ -2709,17 +2721,22 @@ public class GenericsAndCovariance { } ``` -**flist** 的类型现在是 `List`,你可以读作“一个具有任何从 **Fruit** 继承的类型的列表”。然而,这实际上并不意味着这个 **List** 将持有任何类型的 **Fruit**。通配符引用的是明确的类型,因此它意味着“某种 **flist** 引用没有指定的具体类型”。因此这个被赋值的 **List** 必须持有诸如 **Fruit** 或 **Apple** 这样的指定类型,但是为了向上转型为 **Fruit**,这个类型是什么没人在意。 +**flist** 的类型现在是 `List`,你可以读作“一个具有任何继承自 **Fruit** 类型的列表”。然而,这实际上并不意味着这个 **List** 将持有任何类型的 **Fruit**。通配符引用的是明确的类型,因此它意味着“一些 **flist** 引用没有指定特定类型”。因此这个被赋值的 **List** 必须持有诸如 **Fruit** 或 **Apple** 这样的指定类型,但是为了向上转型为 **Fruit**,并不关心这个具体的类型是什么。(编译器只知道 **flist** 是**Fruit**某个子类的List,但并不知道这个子类具体是什么类,只好阻止向其中加入任何子类。为了类型安全,不能往使用了`? extends`的数据结构里写入任何的值。) + +**List** 必须持有一种具体的 **Fruit** 或 **Fruit** 的子类型,但是如果你不关心具体的类型是什么,那么你能对这样的 **List** 做什么呢?如果不知道 **List** 中持有的对象是什么类型,你怎能保证安全地向其中添加对象呢?就和 **CovariantArrays.java** 中的 向上转型的数组一样,你不能这样做,只不过是现在是编译器阻止了这种情况的发生,而不是运行时系统——你会更早发现问题。 -**List** 必须持有一种具体的 **Fruit** 或 **Fruit** 的子类型,但是如果你不关心具体的类型是什么,那么你能对这样的 **List** 做什么呢?如果不知道 **List** 中持有的对象是什么类型,你怎能保证安全地向其中添加对象呢?就像在 **CovariantArrays.java** 中向上转型一样,你不能,除非编译器而不是运行时系统可以阻止这种操作的发生。你很快就会发现这个问题。 +你可能认为事情变得更糟了,因为现在你甚至不能向刚刚声明过将持有 **Apple** 对象的 **List** 中放入一个 **Apple** 对象。是的,但编译器并不知道这一点。`List` 可以合法地指向一个 `List`。一旦你做了这种“向上转型”,你就失去了传入任何对象的能力,甚至传递 **Object** 都不行。 -你可能认为事情开始变得有点走极端了,因为现在你甚至不能向刚刚声明过将持有 **Apple** 对象的 **List** 中放入一个 **Apple** 对象。是的,但编译器并不知道这一点。`List` 可能合法地指向一个 `List`。一旦执行这种类型的向上转型,你就丢失了向其中传递任何对象的能力,甚至传递 **Object** 也不行。 +另一方面,如果你调用一个返回 **Fruit** 类型的方法则是安全的,因为你知道这个 **List** 中的任何对象至少具有 **Fruit** 类型,因此编译器允许这么做。 -另一方面,如果你调用了一个返回 **Fruit** 的方法,则是安全的,因为你知道这个 **List** 中的任何对象至少具有 **Fruit** 类型,因此编译器允许这么做。 +- 总结PECS原则如下: + - 如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends) + - 如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super) + - 如果既要存又要取,那么就不要使用任何通配符。 ### 编译器有多聪明 -现在你可能会猜想自己不能去调用任何接受参数的方法,但是考虑下面的代码: +现在你可能会认为你不能去调用任何接受参数的方法,但是考虑下面的代码: ```java // generics/CompilerIntelligence.java @@ -2740,9 +2757,9 @@ public class CompilerIntelligence { 这里对 `contains()` 和 `indexOf()` 的调用接受 **Apple** 对象作为参数,执行没问题。这是否意味着编译器实际上会检查代码,以查看是否有某个特定的方法修改了它的对象? -通过查看 **ArrayList** 的文档,我们发现编译器没有那么聪明。尽管 `add()` 接受一个泛型参数类型的参数,但 `contains()` 和 `indexOf()` 接受的参数类型是 **Object**。因此当你指定一个 `ArrayList` 时,`add()` 的参数就变成了"**? extends Fruit**"。从这个描述中,编译器无法得知这里需要 **Fruit** 的哪个具体子类型,因此它不会接受任何类型的 **Fruit**。如果你先把 **Apple** 向上转型为 **Fruit**,也没有关系——编译器仅仅会拒绝调用像 `add()` 这样参数列表中涉及通配符的方法。 +通过查看 **ArrayList** 的文档,我们发现编译器没有那么聪明。 `add()` 接受一个泛型参数类型的参数,而 `contains()` 和 `indexOf()` 接受的参数类型是 **Object**。因此当你指定一个 `ArrayList` 时,`add()` 的参数就变成了"**? extends Fruit**"。从这个描述来看,编译器无法知道那里需要 **Fruit** 的哪个具体子类型,因此它不会接受任何类型的 **Fruit**。如果你先把 **Apple** 向上转型为 **Fruit**,也没有关系——编译器仅仅会拒绝调用诸如像 `add()` 这样参数列表中涉及通配符的方法。(当我们使用?号通配符的时候:**就只能调对象与类型无关的方法,不能调用对象与类型有关的方法。** 在上面的List集合,我是不能使用add()方法的。**因为add()方法是把对象丢进集合中,而现在我是不知道对象的类型是什么。**) -`contains()` 和 `indexOf()` 的参数类型是 **Object**,不涉及通配符,所以编译器允许调用它们。这意味着将由泛型类的设计者来决定哪些调用是“安全的”,并使用 **Object** 类作为它们的参数类型。为了禁止对类型中使用了通配符的方法调用,需要在参数列表中使用类型参数。 +`contains()` 和 `indexOf()` 的参数类型是 **Object**,不涉及通配符,所以编译器允许调用它们。这意味着将由泛型类的设计者来决定哪些调用是“安全的”,并使用 **Object** 类作为它们的参数类型。要在类型使用通配符时禁止调用,请使用参数列表中的类型参数。 下面展示一个简单的 **Holder** 类: From c5296272a1120017cfd78e43e9ae4248b628a250 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 24 Dec 2020 17:21:20 +0800 Subject: [PATCH 49/68] chapter 20 04 --- docs/book/19-Type-Information.md | 2 +- docs/book/20-Generics.md | 49 ++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/docs/book/19-Type-Information.md b/docs/book/19-Type-Information.md index 5f0e6953..0b5138cf 100755 --- a/docs/book/19-Type-Information.md +++ b/docs/book/19-Type-Information.md @@ -567,7 +567,7 @@ Java 类库中另一个没有任何用处的特性: `Class.asSubclass()`,该 在 C++ 中,经典的类型转换 “`(Shape)`” 并不使用 RTTI。它只是简单地告诉编译器将这个对象作为新的类型对待. 而 Java 会进行类型检查,这种类型转换一般被称作“类型安全的向下转型”。之所以称作“向下转型”,是因为传统上类继承图是这么画的。将 `Circle` 转换为 `Shape` 是一次向上转型, 将 `Shape` 转换为 `Circle` 是一次向下转型。但是, 因为我们知道 `Circle` 肯定是一个 `Shape`,所以编译器允许我们自由地做向上转型的赋值操作,且不需要任何显式的转型操作。当你给编译器一个 `Shape` 的时候,编译器并不知道它到底是什么类型的 `Shape`——它可能是 `Shape`,也可能是 `Shape` 的子类型,例如 `Circle`、`Square`、`Triangle` 或某种其他的类型。在编译期,编译器只能知道它是 `Shape`。因此,你需要使用显式地进行类型转换,以告知编译器你想转换的特定类型,否则编译器就不允许你执行向下转型赋值。 (编译器将会检查向下转型是否合理,因此它不允许向下转型到实际不是子类的类型)。 -RTTI 在 Java 中还有第三种形式,那就是关键字 `instanceof`。它返回一个布尔值,告诉我们对象是不是某个特定类型的实例,可以用提问的方式使用它,就像这个样子: +RTTI 在 Java 中还有**第三种形式**,那就是关键字 `instanceof`。它返回一个布尔值,告诉我们对象是不是某个特定类型的实例,可以用提问的方式使用它,就像这个样子: ```java if(x instanceof Dog) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 794add44..28d3e4ab 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -2725,7 +2725,7 @@ public class GenericsAndCovariance { **List** 必须持有一种具体的 **Fruit** 或 **Fruit** 的子类型,但是如果你不关心具体的类型是什么,那么你能对这样的 **List** 做什么呢?如果不知道 **List** 中持有的对象是什么类型,你怎能保证安全地向其中添加对象呢?就和 **CovariantArrays.java** 中的 向上转型的数组一样,你不能这样做,只不过是现在是编译器阻止了这种情况的发生,而不是运行时系统——你会更早发现问题。 -你可能认为事情变得更糟了,因为现在你甚至不能向刚刚声明过将持有 **Apple** 对象的 **List** 中放入一个 **Apple** 对象。是的,但编译器并不知道这一点。`List` 可以合法地指向一个 `List`。一旦你做了这种“向上转型”,你就失去了传入任何对象的能力,甚至传递 **Object** 都不行。 +你可能认为事情变得更糟了,因为现在你甚至不能向刚刚声明过将持有 **Apple** 对象的 **List** 中放入一个 **Apple** 对象。的确如此,但编译器并不知道这一点(编译能通过)。`List` 可以合法地指向一个 `List`。而一旦你做了这种“向上转型”,你就失去了传入任何对象的能力,甚至传递 **Object** 都不行。 另一方面,如果你调用一个返回 **Fruit** 类型的方法则是安全的,因为你知道这个 **List** 中的任何对象至少具有 **Fruit** 类型,因此编译器允许这么做。 @@ -2736,7 +2736,7 @@ public class GenericsAndCovariance { ### 编译器有多聪明 -现在你可能会认为你不能去调用任何接受参数的方法,但是考虑下面的代码: +现在你可能会认为你不能去调用任何有入参的方法,但是考虑下面的代码: ```java // generics/CompilerIntelligence.java @@ -2818,7 +2818,7 @@ false */ ``` -**Holder** 有一个接受 **T** 类型对象的 `set()` 方法,一个返回 T 对象的 `get()` 方法和一个接受 Object 对象的 `equals()` 方法。正如你所见,如果创建了一个 `Holder`,就不能将其向上转型为 `Holder`,但是可以向上转型为 `Holder`。如果调用 `get()`,只能返回一个 **Fruit**——这就是在给定“任何扩展自 **Fruit** 的对象”这一边界后,它所能知道的一切了。如果你知道更多的信息,就可以将其转型到某种具体的 **Fruit** 而不会导致任何警告,但是存在得到 **ClassCastException** 的风险。`set()` 方法不能工作在 **Apple** 和 **Fruit** 上,因为 `set()` 的参数也是"**? extends Fruit**",意味着它可以是任何事物,编译器无法验证“任何事物”的类型安全性。 +**Holder** 有一个接受 **T** 类型对象的 `set()` 方法,一个返回 T 对象的 `get()` 方法和一个接受 Object 对象的 `equals()` 方法。正如你所见,如果创建了一个 `Holder`,就不能将其向上转型为 `Holder`,但是可以向上转型为 `Holder`。如果调用 `get()`,只能返回一个 **Fruit**——这已是在给定“任何扩展自 **Fruit** 的对象”这一边界后,它所能知道的一切了。如果你知道更多的信息,就可以将其转型到某种具体的 **Fruit** 而不会导致任何警告,但是存在得到 **ClassCastException** 的风险。`set()` 方法不能工作在 **Apple** 和 **Fruit** 上,因为 `set()` 的参数也是"**? extends Fruit**",意味着它可以是任何事物,编译器无法验证“任何事物”的类型安全性。 但是,`equals()` 方法可以正常工作,因为它接受的参数是 **Object** 而不是 **T** 类型。因此,编译器只关注传递进来和要返回的对象类型。它不会分析代码,以查看是否执行了任何实际的写入和读取操作。 @@ -2826,7 +2826,7 @@ Java 7 引入了 **java.util.Objects** 库,使创建 `equals()` 和 `hashCode( ### 逆变 -还可以走另外一条路,即使用超类型通配符。这里,可以声明通配符是由某个特定类的任何基类来界定的,方法是指定 `<?super MyClass>` ,或者甚至使用类型参数: `<?super T>`(尽管你不能对泛型参数给出一个超类型边界;即不能声明 `` )。这使得你可以安全地传递一个类型对象到泛型类型中。因此,有了超类型通配符,就可以向 **Collection** 写入了: +还可以走另外一条路——使用超类型通配符 (*supertype wildcards*)。这里,可以声明通配符是由某个特定类的任何基类来限制的,通过指定 `<?super MyClass>` ,或者甚至使用类型参数: `<?super T>`(尽管你不能对泛型参数给出一个超类型边界;即不能声明 `` )。这使得你可以安全地传递一个类型对象到泛型类型中。因此,有了超类型通配符,就可以向 **Collection** 写入了: ```java // generics/SuperTypeWildcards.java @@ -2840,7 +2840,8 @@ public class SuperTypeWildcards { } ``` -参数 **apples** 是 **Apple** 的某种基类型的 **List**,这样你就知道向其中添加 **Apple** 或 **Apple** 的子类型是安全的。但是因为 **Apple** 是下界,所以你知道向这样的 **List** 中添加 **Fruit** 是不安全的,因为这将使这个 **List** 敞开口子,从而可以向其中添加非 **Apple** 类型的对象,而这是违反静态类型安全的。 +参数 **apples** 是 **Apple** 的某种基类型的 **List**;这样你就知道向其中添加 **Apple** 或 **Apple** 的子类型是安全的。但是因为 **Apple** 是下界,所以你知道将 **Fruit** 添加到这样的 **List** 中是不安全的——将使这个 **List** 敞开口子,导致可以向其中添加非 **Apple** 类型的对象(只是**Apple** 的某种基类型,不一定就是**Fruit**),而这是违反静态类型安全的。(下界规定元素的最小的粒度,实际上是容器的元素的类型控制。所以放比 Apple 粒度小的如 Jonathan、Apple 都行, 但往外取时, 只有所有类的基类Object对象才能装下——但是这样的话,元素的类型信息就全部消失了。) + 下面的示例复习了一下逆变和通配符的的使用: ```java @@ -2898,8 +2899,10 @@ public class GenericReading { } ``` -`readExact()` 方法使用了精确的类型。如果使用这个没有任何通配符的精确类型,就可以向 **List** 中写入和读取这个精确类型。另外,对于返回值,静态的泛型方法 `readExact()` 可以有效地“适应”每个方法调用,并能够从 `List` 中返回一个 **Apple** ,从 `List` 中返回一个 **Fruit** ,就像在 `f1()` 中看到的那样。因此,如果可以摆脱静态泛型方法,那么在读取时就不需要协变类型了。 -然而对于泛型类来说,当你创建这个类的实例时,就要为这个类确定参数。就像在 `f2()` 中看到的,**fruitReader** 实例可以从 `List` 中读取一个 **Fruit** ,因为这就是它的确切类型。但是 `List` 也应该产生 **Fruit** 对象,而 **fruitReader** 不允许这么做。 +`readExact()` 方法使用了精确的类型。如果使用这个没有任何通配符的精确类型,就可以向 **List** 中写入和读取这个精确类型。另外,对于返回值,静态的泛型方法 `readExact()` 可以有效地“适应”每个方法调用,并能够从 `List` 中返回一个 **Apple** ,从 `List` 中返回一个 **Fruit** ,就像在 `f1()` 中看到的那样。因此,在你可用静态泛型方法的时候,如果只用作读取,不需要协变类型(参与)。 + +然而对于泛型类来说,当你创建这个类的实例时,就要为这个类确定参数。就像在 `f2()` 中看到的,**fruitReader** 实例可以从 `List` 中读取一个 **Fruit** ,因为这就是它的确切类型。但在 `List` 也应该能产生 **Fruit** 对象时, **fruitReader** 却不允许(容器之间没有继承关系)。 + 为了修正这个问题,`CovariantReader.readCovariant()` 方法将接受 `List<?extends T>` ,因此,从这个列表中读取一个 **T** 是安全的(你知道在这个列表中的所有对象至少是一个 **T** ,并且可能是从 T 导出的某种对象)。在 `f3()` 中,你可以看到现在可以从 `List` 中读取 **Fruit** 了。 ### 无界通配符 @@ -2969,7 +2972,8 @@ public class UnboundedWildcards1 { ``` 有很多情况都和你在这里看到的情况类似,即编译器很少关心使用的是原生类型还是 `` 。在这些情况中,`` 可以被认为是一种装饰,但是它仍旧是很有价值的,因为,实际上它是在声明:“我是想用 Java 的泛型来编写这段代码,我在这里并不是要用原生类型,但是在当前这种情况下,泛型参数可以持有任何类型。” -第二个示例展示了无界通配符的一个重要应用。当你在处理多个泛型参数时,有时允许一个参数可以是任何类型,同时为其他参数确定某种特定类型的这种能力会显得很重要: + +第二个示例展示了无界通配符的一个重要应用。当你在处理多个泛型参数时,有时允许一个参数可以是任何类型,同时为其他参数确定特定类型: ```java // generics/UnboundedWildcards2.java @@ -3016,8 +3020,10 @@ public class UnboundedWildcards2 { } ``` -但是,当你拥有的全都是无界通配符时,就像在 `Map` 中看到的那样,编译器看起来就无法将其与原生 **Map** 区分开了。另外, **UnboundedWildcards1.java** 展示了编译器处理 `List` 和 `List` 是不同的。 -令人困惑的是,编译器并非总是关注像 `List` 和 `List` 之间的这种差异,因此它们看起来就像是相同的事物。事实上,因为泛型参数擦除到它的第一个边界,因此 `List` 看起来等价于 `List` ,而 **List** 实际上也是 `List` ——除非这些语句都不为真。**List** 实际上表示“持有任何 **Object** 类型的原生 **List** ”,而 `List` 表示“具有某种特定类型的非原生 **List** ,只是我们不知道类型是什么。” +但是,当你用的全是无界通配符时,就像在 `Map` 中看到的那样,编译器看起来就无法将其与原生 **Map** 【*raw* *type*(原生类型)】区分开了。而且, **UnboundedWildcards1.java** 也展示了编译器处理 `List` 和 `List` 是不同的。 + +令人困惑的是,编译器并不总是关注像 `List` 和 `List` 之间的这种差异,所以它们看起来就像是相同的。事实上,因为泛型参数擦除到它的第一个边界,因此 `List` 看起来等价于 `List` ,而 **List** 实际上也是 `List` ——只是这两种说法都不完全正确。**List** 实际上表示“持有任何 **Object** 类型的原生 **List** ”,而 `List` 表示“具有某种特定类型的非原生 **List** ,只是我们不知道类型是什么。” + 编译器何时才会关注原生类型和涉及无界通配符的类型之间的差异呢?下面的示例使用了前面定义的 `Holder` 类,它包含接受 **Holder** 作为参数的各种方法,但是它们具有不同的形式:作为原生类型,具有具体的类型参数以及具有无界通配符参数: ```java @@ -3308,21 +3314,28 @@ public class Wildcards { ``` 在 `rawArgs()` 中,编译器知道 `Holder` 是一个泛型类型,因此即使它在这里被表示成一个原生类型,编译器仍旧知道向 `set()` 传递一个 **Object** 是不安全的。由于它是原生类型,你可以将任何类型的对象传递给 `set()` ,而这个对象将被向上转型为 **Object** 。因此无论何时,只要使用了原生类型,都会放弃编译期检查。对 `get()` 的调用说明了相同的问题:没有任何 **T** 类型的对象,因此结果只能是一个 **Object**。 + 人们很自然地会开始考虑原生 `Holder` 与 `Holder` 是大致相同的事物。但是 `unboundedArg()` 强调它们是不同的——它揭示了相同的问题,但是它将这些问题作为错误而不是警告报告,因为原生 **Holder** 将持有任何类型的组合,而 `Holder` 将持有具有某种具体类型的同构集合,因此不能只是向其中传递 **Object** 。 + 在 `exact1()` 和 `exact2()` 中,你可以看到使用了确切的泛型参数——没有任何通配符。你将看到,`exact2()`与 `exact1()` 具有不同的限制,因为它有额外的参数。 -在 `wildSubtype()` 中,在 **Holder** 类型上的限制被放松为包括持有任何扩展自 **T** 的对象的 **Holder** 。这还是意味着如果 T 是 **Fruit** ,那么 `holder` 可以是 `Holder` ,这是合法的。为了防止将 **Orange** 放置到 `Holder` 中,对 `set()` 的调用(或者对任何接受这个类型参数为参数的方法的调用)都是不允许的。但是,你仍旧知道任何来自 `Holder<?extends Fruit>` 的对象至少是 **Fruit** ,因此 `get()` (或者任何将产生具有这个类型参数的返回值的方法)都是允许的。 -`wildSupertype()` 展示了超类型通配符,这个方法展示了与 `wildSubtype()` 相反的行为:`holder` 可以是持有任何 T 的基类型的容器。因此, `set()` 可以接受 **T** ,因为任何可以工作于基类的对象都可以多态地作用于导出类(这里就是 **T** )。但是,尝试着调用 `get()` 是没有用的,因为由 `holder` 持有的类型可以是任何超类型,因此唯一安全的类型就是 **Object** 。 + +在 `wildSubtype()` 中,在 **Holder** 类型上的限制被放松为包括持有任何扩展自 **T** 的对象的 **Holder** 。这还是意味着如果 T 是 **Fruit** ,那么 该方法的参数`holder`的类型 可以是 `Holder` ,这是合法的。为了防止将 **Orange** 放置到 `Holder` 中,对 `set()` 的调用(或者对任何接受这个类型参数为参数的方法的调用)都是不允许的。但是,你仍旧知道任何来自 `Holder<?extends Fruit>` 的对象至少是 **Fruit** ,因此 `get()` (或者任何将产生具有这个类型参数的返回值的方法)都是允许的。 + +`wildSupertype()` 中展示了超类型通配符,这个方法展示了与 `wildSubtype()` 相反的行为:`holder` 是一个集合,它持有的任何类型都是 T 的基类。因此, `set()` 可以接受 **T** ,因为任何与基类一起工作的东西都会多态地与派生类一起工作(这里就是 **T** )。但是,尝试着调用 `get()` 是没有用的,因为由 `holder` 持有的类型可以是任何基类,因此唯一安全的类型就是 **Object** 。 + 这个示例还展示了对于在 `unbounded()` 中使用无界通配符能够做什么不能做什么所做出的限制:因为你没有 **T**,所以你不能将 `set()` 或 `get()` 作用于 **T** 上。 在 `main()` 方法中你看到了某些方法在接受某些类型的参数时没有报错和警告。为了迁移兼容性,`rawArgs()` 将接受所有 **Holder** 的不同变体,而不会产生警告。`unboundedArg()` 方法也可以接受相同的所有类型,尽管如前所述,它在方法体内部处理这些类型的方式并不相同。 -如果向接受“确切”泛型类型(没有通配符)的方法传递一个原生 **Holder** 引用,就会得到一个警告,因为确切的参数期望得到在原生类型中并不存在的信息。如果向 `exact1()` 传递一个无界引用,就不会有任何可以确定返回类型的类型信息。 -可以看到,`exact2()` 具有最多的限制,因为它希望精确地得到一个 `Holder` ,以及一个具有类型 **T** 的参数,正由于此,它将产生错误或警告,除非提供确切的参数。有时,这样做很好,但是如果它过于受限,那么就可以使用通配符,这取决于是否想要从泛型参数中返回类型确定的返回值(就像在 `wildSubtype()` 中看到的那样),或者是否想要向泛型参数传递类型确定的参数(就像在 `wildSupertype()` 中看到的那样)。 -因此,使用确切类型来替代通配符类型的好处是,可以用泛型参数来做更多的事,但是使用通配符使得你必须接受范围更宽的参数化类型作为参数。因此,必须逐个情况地权衡利弊,找到更适合你的需求的方法。 +如果将一个原生 **Holder** 引用传递至一个接受“确切”泛型类型(没有通配符)的方法,就会得到警告,因为确切的参数期望得到在原生类型中并不存在的信息。如果向 `exact1()` 传递一个无界引用,就不会有任何可以确定返回类型的类型信息。 + +可以看到,`exact2()` 有最多的约束,因为它希望精确地得到一个 `Holder` ,以及一个具有类型 **T** 的参数,正由于此,它将产生错误或警告,除非提供确切的参数。有时,这样做很好,但如果觉得它过于受限,就可以使用通配符,这取决于是否想要从泛型参数中返回类型确切类型的返回值(就像在 `wildSubtype()` 中看到那样),或者是否想要将确切类型的参数传递到泛型参数(就像在 `wildSupertype()` 中看到那样)。 + +因此,使用确切类型来替代通配符类型的好处是,可以用泛型参数来做更多的事。但是通配符可以接受更广泛的参数化类型作为参数。您必须根据具体情况决定哪种取舍更适合您的需求。 ### 捕获转换 -有一种特殊情况需要使用 `` 而不是原生类型。如果向一个使用 `` 的方法传递原生类型,那么对编译器来说,可能会推断出实际的类型参数,使得这个方法可以回转并调用另一个使用这个确切类型的方法。下面的示例演示了这种技术,它被称为捕获转换,因为未指定的通配符类型被捕获,并被转换为确切类型。这里,有关警告的注释只有在 `@SuppressWarnings` 注解被移除之后才能起作用: +有一种情况,特别需要使用 `` 而不是原生类型。如果你把一个原生类型传递给一个使用 `` 的方法,编译器就有可能会推断出实际的类型参数,这样该方法就可以回转并调用另一个使用这个确切类型的方法。下面的示例演示了这种技术,它被称为捕获转换(*capture* *conversion*),因为未指定的通配符类型被捕获并转换为确切类型。这里,有关警告的注释只有在 `@SuppressWarnings` 注解被移除后才生效: ```java // generics/CaptureConversion.java @@ -3386,8 +3399,8 @@ Double */ ``` -`f1()` 中的类型参数都是确切的,没有通配符或边界。在 `f2()` 中,**Holder** 参数是一个无界通配符,因此它看起来是未知的。但是,在 `f2()` 中调用了 `f1()`,而 `f1()` 需要一个已知参数。这里所发生的是:在调用 `f2()` 的过程中捕获了参数类型,并在调用 `f1()` 时使用了这种类型。 -你可能想知道这项技术是否可以用于写入,但是这要求在传递 `Holder` 时同时传递一个具体类型。捕获转换只有在这样的情况下可以工作:即在方法内部,你需要使用确切的类型。注意,不能从 `f2()` 中返回 **T**,因为 **T** 对于 `f2()` 来说是未知的。捕获转换十分有趣,但是非常受限。 +`f1()` 中的类型参数都是确切的,没有通配符或边界。在 `f2()` 中,**Holder** 参数是一个无界通配符,因此它看起来是未知的。但是,在 `f2()` 中调用了 `f1()`,而 `f1()` 需要一个已知参数。这里所发生的是:参数类型在调用 `f2()` 的过程中被捕获,并在调用 `f1()` 中使用。 +你可能想知道这项技术是否可以用于写入,但这样会要求在传递 `Holder` 时同时传递一个具体类型。捕获转换只适用于这样的情况:即在方法内部,你需要使用确切的类型。注意,不能从 `f2()` 中返回 **T**,因为 **T** 对于 `f2()` 来说是未知的。捕获转换很有趣,但是非常受限。 From 63fcb4b80f1b9e7a4286799342f948d8d89b59c3 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 5 Jan 2021 12:02:51 +0800 Subject: [PATCH 50/68] chapter 20 05 --- docs/book/20-Generics.md | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 28d3e4ab..eb1e8bca 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -1768,7 +1768,7 @@ public static void main(java.lang.String[]); 所产生的字节码是相同的。对进入 `set()` 的类型进行检查是不需要的,因为这将由编译器执行。而对 `get()` 返回的值进行转型仍然是需要的,只不过不需要你来操作,它由编译器自动插入,这样你就不用编写和阅读杂乱的代码。 -`get()` 和 `set()` 产生了相同的字节码,这就告诉我们泛型的所有动作都发生在边界——编译时对入参的额外检查,以及对返回值的插入转类型。记住:“边界就是动作发生的地方”,这有助于解除对擦除的疑惑。 +`get()` 和 `set()` 产生了相同的字节码,这就告诉我们泛型的所有动作都发生在边界——对入参进行额外的编译期检查,以及对返回值插入的转型。记住:“边界就是动作发生的地方”,这有助于解除对擦除的疑惑。 @@ -1868,7 +1868,7 @@ int main() { } ``` -Java 中的解决方案是传入一个工厂对象,并使用该对象创建新实例。方便的工厂对象只是 **Class** 对象,因此,如果使用类型标记,则可以使用 `newInstance()` 创建该类型的新对象: +Java 中的解决方案是传入一个工厂对象,并使用该对象创建新实例。方便的工厂对象只是 **Class** 对象,因此,如果使用类型标记/**类型标签**,则可以使用 `newInstance()` 创建该类型的新对象: ```java // generics/InstantiateGenericType.java @@ -2840,9 +2840,9 @@ public class SuperTypeWildcards { } ``` -参数 **apples** 是 **Apple** 的某种基类型的 **List**;这样你就知道向其中添加 **Apple** 或 **Apple** 的子类型是安全的。但是因为 **Apple** 是下界,所以你知道将 **Fruit** 添加到这样的 **List** 中是不安全的——将使这个 **List** 敞开口子,导致可以向其中添加非 **Apple** 类型的对象(只是**Apple** 的某种基类型,不一定就是**Fruit**),而这是违反静态类型安全的。(下界规定元素的最小的粒度,实际上是容器的元素的类型控制。所以放比 Apple 粒度小的如 Jonathan、Apple 都行, 但往外取时, 只有所有类的基类Object对象才能装下——但是这样的话,元素的类型信息就全部消失了。) +参数 **apples** 是 **Apple** 的某种基类型的 **List**;这样你就知道向其中添加 **Apple** 或 **Apple** 的子类型是安全的。但是因为 **Apple** 是下界,所以你知道将 **Fruit** 添加到这样的 **List** 中是不安全的——将使这个 **List** 敞开口子,导致可以向其中添加非 **Apple** 类型的对象(只是**Apple** 的某种基类,这种基类不一定就是 **Fruit**),而这是违反静态类型安全的。(因为下界规定了元素的最小粒度的下限,实际上是放松了容器元素的类型控制。既然元素是 **Apple** 的基类,所以放比 **Apple** 粒度小的如 Jonathan、Apple 都行, 但往外取时, 只有所有类的基类 **Object** 对象才能装下——但是这样的话,元素的类型信息全部丢失。) -下面的示例复习了一下逆变和通配符的的使用: +下面的示例复习了一下协变和通配符的的使用: ```java // generics/GenericReading.java @@ -2905,6 +2905,31 @@ public class GenericReading { 为了修正这个问题,`CovariantReader.readCovariant()` 方法将接受 `List<?extends T>` ,因此,从这个列表中读取一个 **T** 是安全的(你知道在这个列表中的所有对象至少是一个 **T** ,并且可能是从 T 导出的某种对象)。在 `f3()` 中,你可以看到现在可以从 `List` 中读取 **Fruit** 了。 +```java +//第一段 +public void testAdd(List list){ + list.add(new Animal("animal")); + list.add(new Bird("bird")); + list.add(new Cat("cat")); +} +//第二段 +List list = new ArrayList<>(); +list.add(new Animal("animal")); +list.add(new Bird("bird")); +list.add(new Cat("cat")); +/* +我们知道List、List的子类型。先假设传入的参数为为List,则第一段代码的三个“add”操作都是可行的;可如果是List呢??则只有第二个“add”可以执行;再假设传入的是List(Tiger是想象出来的,可认为是Cat的子类),则三个“add”操作都不能执行。 + +现在反过来说,给testAdd传入不同的参数,三个“add”操作都可能引发类型不兼容问题,而传入的参数是未知的,所以java为了保护其类型一致,禁止向List添加任意对象,不过却可以添加null,即list.add(null)是可行的。 + +有了上面谈到的基础,再来理解第二段代码就不难了,因为List的类型“? extends Animal”无法确定,可以是Animal,Bird或者Cat等,所以为了保护其类型的一致性,也是不能往list添加任意对象的,不过却可以添加null。 + +总结如下:不能往List 添加任意对象,除了null。 +*/ +``` + + + ### 无界通配符 无界通配符 `` 看起来意味着“任何事物”,因此使用无界通配符好像等价于使用原生类型。事实上,编译器初看起来是支持这种判断的: From 68163f25ef2618a6f9460a2757821a996def1a5c Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 5 Jan 2021 14:21:55 +0800 Subject: [PATCH 51/68] chapter 20 06 --- docs/book/20-Generics.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index eb1e8bca..381788b6 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -2695,7 +2695,7 @@ public class NonCovariantGenerics { 尽管你在首次阅读这段代码时会认为“不能将一个 **Apple** 集合赋值给一个 **Fruit** 集合”。记住,泛型不仅仅是关于集合,它真正要表达的是“不能把一个 **Apple** 的泛型赋值给一个 **Fruit** 的泛型”。如果和在数组中的情况一样,编译器对代码的了解足够多,可以确定所涉及到的集合,那么它可能会留下一些余地。但是它不知道任何有关这方面的信息,因此它不允许向上转型。然而实际上这也不是向上转型—— **Apple** 的 **List** 不是 **Fruit** 的 **List**。**Apple** 的 **List** 将持有 **Apple** 和 **Apple** 的子类型,**Fruit** 的 **List** 将持有任何类型的 **Fruit**。是的,这包括 **Apple**,但是它不是一个 **Apple** 的 **List**,它仍然是 **Fruit** 的 **List**。**Apple** 的 **List** 在类型上不等价于 **Fruit** 的 **List**,即使 **Apple** 是一种 **Fruit** 类型。 -真正的问题是我们在讨论的集合类型,而不是集合持有对象的类型。与数组不同,泛型没有内建的协变类型。这是因为数组是完全在java语言中定义的,因此可以具有编译期和运行时的内建检查,但是在使用泛型时,编译器和运行时系统不知道你想用类型做什么,以及应该采用什么规则。(Java中,数组是协变的,泛型是不变的,``实现了泛型的协变,``实现了泛型的逆变) +真正的问题是我们在讨论的集合类型,而不是集合持有对象的类型。与数组不同,泛型没有内建的协变类型。这是因为数组是完全在java语言中定义的,因此可以具有编译期和运行时的内建检查,但是在使用泛型时,编译器和运行时系统不知道你想用类型做什么,以及应该采用什么规则。(Java中,数组是协变的,泛型是不变的,``实现了泛型的协变 **covariance**,``实现了泛型的逆变**contravariance**) 但是,有时你想在两个类型间建立某种向上转型关系。通配符可以产生这种关系。 @@ -3348,15 +3348,15 @@ public class Wildcards { `wildSupertype()` 中展示了超类型通配符,这个方法展示了与 `wildSubtype()` 相反的行为:`holder` 是一个集合,它持有的任何类型都是 T 的基类。因此, `set()` 可以接受 **T** ,因为任何与基类一起工作的东西都会多态地与派生类一起工作(这里就是 **T** )。但是,尝试着调用 `get()` 是没有用的,因为由 `holder` 持有的类型可以是任何基类,因此唯一安全的类型就是 **Object** 。 -这个示例还展示了对于在 `unbounded()` 中使用无界通配符能够做什么不能做什么所做出的限制:因为你没有 **T**,所以你不能将 `set()` 或 `get()` 作用于 **T** 上。 +这个例子也显示了在 `unboundedArg()` 中,对无界参数能做什么不能做什么的限制:因为你没有 **T**,所以你不能将 `set()` 或 `get()`一个 **T** 。 在 `main()` 方法中你看到了某些方法在接受某些类型的参数时没有报错和警告。为了迁移兼容性,`rawArgs()` 将接受所有 **Holder** 的不同变体,而不会产生警告。`unboundedArg()` 方法也可以接受相同的所有类型,尽管如前所述,它在方法体内部处理这些类型的方式并不相同。 -如果将一个原生 **Holder** 引用传递至一个接受“确切”泛型类型(没有通配符)的方法,就会得到警告,因为确切的参数期望得到在原生类型中并不存在的信息。如果向 `exact1()` 传递一个无界引用,就不会有任何可以确定返回类型的类型信息。 +如果将一个原生 **Holder** 引用传递至一个接受“精确”泛型类型(没有通配符)的方法,就会得到警告,因为确切的参数期望得到在原生类型中并不存在的信息。如果向 `exact1()` 传递一个无界引用,就不会有任何可以确定返回类型的类型信息。 -可以看到,`exact2()` 有最多的约束,因为它希望精确地得到一个 `Holder` ,以及一个具有类型 **T** 的参数,正由于此,它将产生错误或警告,除非提供确切的参数。有时,这样做很好,但如果觉得它过于受限,就可以使用通配符,这取决于是否想要从泛型参数中返回类型确切类型的返回值(就像在 `wildSubtype()` 中看到那样),或者是否想要将确切类型的参数传递到泛型参数(就像在 `wildSupertype()` 中看到那样)。 +可以看到,`exact2()` 有最多的约束,因为它希望精确地得到一个 `Holder` ,以及一个具有类型 **T** 的参数,正由于此,它将产生错误或警告,除非提供精确的参数。有时,这样做很好,但如果觉得它过于受限,就可以使用通配符,这取决于是否想要从泛型参数中返回类型精确类型的返回值(就像在 `wildSubtype()` 中看到那样),或者是否想要将精确类型的参数传递到泛型参数(就像在 `wildSupertype()` 中看到那样)。 -因此,使用确切类型来替代通配符类型的好处是,可以用泛型参数来做更多的事。但是通配符可以接受更广泛的参数化类型作为参数。您必须根据具体情况决定哪种取舍更适合您的需求。 +因此,使用精确泛型类型(T)来替代通配符类型的好处是,可以用泛型参数来做更多的事。但是通配符可以接受更广泛的参数化类型作为参数。您必须根据具体情况决定哪种取舍更适合您的需求。 ### 捕获转换 From d703389487ca795834093c1c5360115d0c2d4ef1 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Tue, 5 Jan 2021 17:36:40 +0800 Subject: [PATCH 52/68] chapter 20 07 --- docs/book/20-Generics.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 381788b6..35e964ce 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -3541,13 +3541,13 @@ class Employee implements Payable {} class Hourly extends Employee implements Payable {} ``` -**Hourly** 不能编译,因为擦除会将 `Payable` 和 `Payable` 简化为相同的类 **Payable**,这样,上面的代码就意味着在重复两次地实现相同的接口。十分有趣的是,如果从 **Payable** 的两种用法中都移除掉泛型参数(就像编译器在擦除阶段所做的那样)这段代码就可以编译。 +**Hourly** 不能编译,因为擦除会将 `Payable` 和 `Payable` 简化为相同的类 **Payable**,这样,上面的代码就意味着在重复两次地实现相同的接口。十分有趣的是,如果从 **Payable** 的两种用法中都移除掉泛型参数(就像编译器在擦除阶段所做的那样),这段代码就可以编译。 在使用某些更基本的 Java 接口,例如 `Comparable` 时,这个问题可能会变得十分令人恼火,就像你在本节稍后看到的那样。 ### 转型和警告 -使用带有泛型类型参数的转型或 **instanceof** 不会有任何效果。下面的集合在内部将各个值存储为 **Object**,并在获取这些值时,再将它们转型回 **T**: +对泛型类型参数使用转型或 **instanceof** 不会有任何效果。下面的集合在内部将各个值存储为 **Object**,并在获取这些值时,再将它们转型回 **T**: ```java // generics/GenericCast.java @@ -3716,7 +3716,7 @@ public class ComparablePet implements Comparable { } ``` -尝试缩小 **ComparablePet** 子类的比较类型是有意义的。例如,**Cat** 类可以与其他的 **Cat** 比较: +尝试缩小 **ComparablePet** 子类的比较类型是有意义的。例如,**Cat** 类应该限制为只能与其他的 **Cat** 比较: ```java // generics/HijackedInterface.java @@ -3766,13 +3766,13 @@ class Gecko extends ComparablePet { class SelfBounded> { // ... ``` -这就像两面镜子彼此照向对方所引起的目眩效果一样,是一种无限反射。**SelfBounded** 类接受泛型参数 **T**,而 **T** 由一个边界类限定,这个边界就是拥有 **T** 作为其参数的 **SelfBounded**。 +这就像两面镜子彼此照向对方所引起的目眩效果一样,是一种无限反射。**SelfBounded** 类接受泛型参数 **T**,而 **T** 被边界约束,这个边界就是 **SelfBounded** ,**SelfBounded** 又拥有 **T** 作为其参数。 当你首次看到它时,很难去解析它,它强调的是当 **extends** 关键字用于边界与用来创建子类明显是不同的。 ### 古怪的循环泛型 -为了理解自限定类型的含义,我们从这个惯用法的一个简单版本入手,它没有自限定的边界。 +为了理解自限定类型的含义,我们从这个惯用法的一个简化版本入手:它没有自限定的边界。 不能直接继承一个泛型参数,但是,可以继承在其自己的定义中使用这个泛型参数的类。也就是说,可以声明: @@ -3785,8 +3785,8 @@ public class CuriouslyRecurringGeneric extends GenericType {} ``` -这可以按照 Jim Coplien 在 C++ 中的*古怪的循环模版模式*的命名方式,称为古怪的循环泛型(CRG)。“古怪的循环”是指类相当古怪地出现在它自己的基类中这一事实。 -为了理解其含义,努力大声说:“我在创建一个新类,它继承自一个泛型类型,这个泛型类型接受我的类的名字作为其参数。”当给出导出类的名字时,这个泛型基类能够实现什么呢?好吧,Java 中的泛型关乎参数和返回类型,因此它能够产生使用导出类作为其参数和返回类型的基类。它还能将导出类型用作其域类型,尽管这些将被擦除为 **Object** 的类型。下面是表示了这种情况的一个泛型类: +这可以按照 Jim Coplien 在 C++ 中的*古怪的循环模版模式*的命名方式,称为古怪的循环泛型(CRG *curiously recurring generics*)。“古怪的循环”是指类相当古怪地出现在它自己的基类中这一事实。 +为了理解其含义,试着大声跟读:“我在创建一个新的类,它继承自一个泛型类型,这个泛型类型以我的这个新类名作为其参数。”当给予派生类名时,泛型基类能够实现什么呢?好吧,Java 中的泛型关于参数和返回类型的,所以它可以产生一个使用派生类型作为参数和返回类型的基类。它还能将派生类型用作其字段,尽管这些字段的类型被擦除了,变为 **Object** 的类型。下面的一个泛型类表示了这种情况: ```java // generics/BasicHolder.java @@ -3801,7 +3801,7 @@ public class BasicHolder { } ``` -这是一个普通的泛型类型,它的一些方法将接受和产生具有其参数类型的对象,还有一个方法在其存储的域上执行操作(尽管只是在这个域上执行 **Object** 操作)。 +这是一个普通的泛型类型,其方法都接受和生成参数类型的对象,还有一个方法`f()`会对存储的字段进行操作(尽管只是对该字段进行 **Object** 类操作)。 我们可以在一个古怪的循环泛型中使用 **BasicHolder**: ```java @@ -3822,7 +3822,7 @@ Subtype */ ``` -注意,这里有些东西很重要:新类 **Subtype** 接受的参数和返回的值具有 **Subtype** 类型而不仅仅是基类 **BasicHolder** 类型。这就是 CRG 的本质:基类用导出类替代其参数。这意味着泛型基类变成了一种其所有导出类的公共功能的模版,但是这些功能对于其所有参数和返回值,将使用导出类型。也就是说,在所产生的类中将使用确切类型而不是基类型。因此,在**Subtype** 中,传递给 `set()` 的参数和从 `get()` 返回的类型都是确切的 **Subtype**。 +注意,这里有些东西很重要:新类 **Subtype** 接受的参数和返回的值具有 **Subtype** 类型而不仅仅是基类 **BasicHolder** 类型。这就是 CRG 的本质:基类用派生类替代其参数。这意味着泛型基类变成了所有派生类的公共功能的一种模版,但这些功能对于其所有参数和返回值,将使用派生类型。也就是说,在由此产生的类中将使用精确类型而不是基类类型。因此,在**Subtype** 中,传递给 `set()` 的参数和从 `get()` 返回的类型都是确切的 **Subtype**。 ### 自限定 @@ -3851,7 +3851,7 @@ Other */ ``` -限定将采取额外的步骤,强制泛型当作其自身的边界参数来使用。观察所产生的类可以如何使用以及不可以如何使用: +自限定将采取额外的步骤,强制泛型当作其自身的边界参数来使用。观察由此产生的类可以如何使用以及不可以如何使用: ```java // generics/SelfBounding.java From 2bd39114e91d7015369c6819cf64ef26dbd2f7b8 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Thu, 7 Jan 2021 11:56:41 +0800 Subject: [PATCH 53/68] chapter 20 08 --- docs/book/20-Generics.md | 78 ++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 35e964ce..d750032c 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -903,7 +903,7 @@ public class Sets { 前三个方法通过将第一个参数的引用复制到新的 **HashSet** 对象中来复制第一个参数,因此不会直接修改参数集合。因此,返回值是一个新的 **Set** 对象。 -这四种方法代表数学集合操作: `union()` 返回一个包含两个参数并集的 **Set** , `intersection()` 返回一个包含两个参数集合交集的 **Set** , `difference()` 从 **superset** 中减去 **subset** 后剩余的元素 (差集),而 `complement()` 返回所有不在交集中的元素的 **Set** (交集的补集)。作为显示这些方法效果的简单示例的一部分,下面是一个包含不同水彩名称的 **enum** : +这四种方法代表数学集合操作: `union()` 返回一个包含两个参数并集的 **Set** , `intersection()` 返回一个包含两个参数集合交集的 **Set** , `difference()` 从 **superset** 中减去 **subset** 后剩余的元素 (差集),而 `complement()` 返回的 **Set** 包含所有不在交集中的元素(交集的补集)。作为显示这些方法效果的简单示例的一部分,下面是一个包含不同水彩名称的 **enum** : ```java // generics/watercolors/Watercolors.java @@ -3902,10 +3902,10 @@ public class SelfBounding { class A extends SelfBounded{} ``` -这会强制要求将正在定义的类当作参数传递给基类。 +这将迫使你把正在定义的类作为参数传递给基类。 -自限定的参数有何意义呢?它可以保证类型参数必须与正在被定义的类相同。正如你在 B 类的定义中所看到的,还可以从使用了另一个 **SelfBounded** 参数的 **SelfBounded** 中导出,尽管在 **A** 类看到的用法看起来是主要的用法。对定义 **E** 的尝试说明不能使用不是 **SelfBounded** 的类型参数。 -遗憾的是, **F** 可以编译,不会有任何警告,因此自限定惯用法不是可强制执行的。如果它确实很重要,可以要求一个外部工具来确保不会使用原生类型来替代参数化类型。 +自限定的参数有何附带意义呢?——它可以保证类型参数必须与正在定义的类相同。如同你在 B 类的定义中所看到的,还可以从使用另一个 **SelfBounded** 参数的 **SelfBounded** 中派生,尽管在 **A** 类看到的用法看起来是主要的用法。定义 **E** 的尝试表明了,不能使用非**SelfBounded** 的类型参数。 +遗憾的是, **F** 可以编译,不会有任何警告,因此自限定惯用法不是可强制执行的。如果这真的很重要,可以用一个外部工具来确保原始类型不被使用来代替参数化类型。 注意,可以移除自限定这个限制,这样所有的类仍旧是可以编译的,但是 **E** 也会因此而变得可编译: ```java @@ -3935,7 +3935,7 @@ class D2 {} class E2 extends NotSelfBounded {} ``` -因此很明显,自限定限制只能强制作用于继承关系。如果使用自限定,就应该了解这个类所用的类型参数将与使用这个参数的类具有相同的基类型。这会强制要求使用这个类的每个人都要遵循这种形式。 +显然,自限定约束的作用只是为了强制继承关系。如果使用了自限定,说明类使用的类型参数与使用该类型参数的类的类型是一样的。它迫使任何使用该类的人都要遵循这种形式。 还可以将自限定用于泛型方法: ```java @@ -3955,13 +3955,13 @@ public class SelfBoundingMethods { } ``` -这可以防止这个方法被应用于除上述形式的自限定参数之外的任何事物上。 +这样可以防止这个方法被应用于除上述形式的自限定参数之外的其它地方。 ### 参数协变 自限定类型的价值在于它们可以产生*协变参数类型*——方法参数类型会随子类而变化。 -尽管自限定类型还可以产生与子类类型相同的返回类型,但是这并不十分重要,因为*协变返回类型*是在 Java 5 引入: +尽管自限定类型还可以产生与子类类型相同的返回类型,但是这并不十分重要,因为*协变返回类型*在 Java 5 引入了(如下): ```java // generics/CovariantReturnTypes.java @@ -3986,9 +3986,9 @@ public class CovariantReturnTypes { } ``` -**DerivedGetter** 中的 `get()` 方法覆盖了 **OrdinaryGetter** 中的 `get()` ,并返回了一个从 `OrdinaryGetter.get()` 的返回类型中导出的类型。尽管这是完全合乎逻辑的事情(导出类方法应该能够返回比它覆盖的基类方法更具体的类型)但是这在早先的 Java 版本中是不合法的。 +**DerivedGetter** 中的 `get()` 方法覆盖了 **OrdinaryGetter** 中的 `get()` ,并返回了一个从 `OrdinaryGetter.get()` 的返回类型中派生的类型。尽管这是完全合乎逻辑的事情(派生类方法应该能够返回比它重写的基类方法更具体的类型)但是这在早先的 Java 版本中是不合法的。 -自限定泛型事实上将产生确切的导出类型作为其返回值,就像在 `get()` 中所看到的一样: +自限定泛型事实上将产生确切的派生类型作为其返回值,就像这里 所看到的`get()` 一样: ```java // generics/GenericsAndReturnTypes.java @@ -4007,7 +4007,7 @@ public class GenericsAndReturnTypes { } ``` -注意,这段代码不能编译,除非是使用囊括了协变返回类型的 Java 5。 +注意,这需要使用囊括了协变返回类型的 Java 5,否则这段代码不能编译。 然而,在非泛型代码中,参数类型不能随子类型发生变化: @@ -4042,8 +4042,8 @@ OrdinarySetter.set(Base) */ ``` -`set(derived)` 和 `set(base)` 都是合法的,因此 `DerivedSetter.set()` 没有覆盖 `OrdinarySetter.set()` ,而是重载了这个方法。从输出中可以看到,在 **DerivedSetter** 中有两个方法,因此基类版本仍旧是可用的,因此可以证明它被重载过。 -但是,在使用自限定类型时,在导出类中只有一个方法,并且这个方法接受导出类型而不是基类型为参数: +`set(derived)` 和 `set(base)` 都是合法的,因此 `DerivedSetter.set()` 没有重写 `OrdinarySetter.set()` ,而是重载了这个方法。从输出中可以看到,在 **DerivedSetter** 中有两个方法,因此基类版本仍旧是可用的,因此可以证明它被重载过。 +但是,在使用自限定类型时,派生类中只有一个方法,并且这个方法接受派生类型而不是基类型为参数: ```java // generics/SelfBoundingAndCovariantArguments.java @@ -4055,8 +4055,7 @@ interface SelfBoundSetter> { interface Setter extends SelfBoundSetter {} public class SelfBoundingAndCovariantArguments { - void - testA(Setter s1, Setter s2, SelfBoundSetter sbs) { + void testA(Setter s1, Setter s2, SelfBoundSetter sbs) { s1.set(s2); //- s1.set(sbs); // error: method set in interface SelfBoundSetter @@ -4075,7 +4074,7 @@ public class SelfBoundingAndCovariantArguments { } ``` -编译器不能识别将基类型当作参数传递给 `set()` 的尝试,因为没有任何方法具有这样的签名。实际上,这个参数已经被覆盖。 +编译器不能识别将基类型当作参数传递给 `set()` 的尝试,因为没有任何方法具有这样的签名。这个参数实际上已经被重写。 如果不使用自限定类型,普通的继承机制就会介入,而你将能够重载,就像在非泛型的情况下一样: ```java @@ -4114,9 +4113,9 @@ GenericSetter.set(Base) ## 动态类型安全 -因为可以向 Java 5 之前的代码传递泛型集合,所以旧式代码仍旧有可能会破坏你的集合。Java 5 的 **java.util.Collections** 中有一组便利工具,可以解决在这种情况下的类型检查问题,它们是:静态方法 `checkedCollection()` 、`checkedList()`、 `checkedMap()` 、 `checkedSet()` 、`checkedSortedMap()`和 `checkedSortedSet()`。这些方法每一个都会将你希望动态检查的集合当作第一个参数接受,并将你希望强制要求的类型作为第二个参数接受。 +因为可以向 Java 5 之前的代码传递泛型集合,所以旧式代码仍旧有可能会破坏你的集合。Java 5 的 **java.util.Collections** 中有一组便利工具,可以解决在这种情况下的类型检查问题,它们是:静态方法 `checkedCollection()` 、`checkedList()`、 `checkedMap()` 、 `checkedSet()` 、`checkedSortedMap()`和 `checkedSortedSet()`。所有这些方法都会将你希望动态检查的集合当作第一个参数,并将你希望强制要求的类型作为第二个参数。 -受检查的集合在你试图插入类型不正确的对象时抛出 **ClassCastException** ,这与泛型之前的(原生)集合形成了对比,对于后者来说,当你将对象从集合中取出时,才会通知你出现了问题。在后一种情况中,你知道存在问题,但是不知道罪魁祸首在哪里,如果使用受检查的集合,就可以发现谁在试图插入不良对象。 +受检查的集合在你试图插入类型不正确的对象时抛出 **ClassCastException** ,而不是之前泛型(原生)集合——当你将对象从集合中取出时,才会通知你出现了问题——在种情况中,你知道存在问题,但是不知道罪魁祸首在哪里。如果使用受检查的集合,就可以发现谁在试图插入不良对象。 让我们用受检查的集合来看看“将猫插入到狗列表中”这个问题。这里,`oldStyleMethod()` 表示遗留代码,因为它接受的是原生的 **List** ,而 **@SuppressWarnings(“unchecked”)** 注解对于压制所产生的警告是必需的: ```java @@ -4155,14 +4154,14 @@ with element type class typeinfo.pets.Dog */ ``` -运行这个程序时,你会发现插入一个 **Cat** 对于 **dogs1** 来说没有任何问题,而 **dogs2** 立即会在这个错误类型的插入操作上抛出一个异常。还可以看到,将导出类型的对象放置到将要检查基类型的受检查容器中是没有问题的。 +运行这个程序时,你会发现插入一个 **Cat** 对于 **dogs1** 来说没有任何问题,而 **dogs2** 立即会在这个错误类型的插入操作上抛出一个异常。还可以看到,将派生类型的对象放置到将要检查基类型的受检查容器中是没有问题的【` pets.add(new Cat());`】。 ## 泛型异常 -由于擦除的原因,**catch** 语句不能捕获泛型类型的异常,因为在编译期和运行时都必须知道异常的确切类型。泛型类也不能直接或间接继承自 **Throwable**(这将进一步阻止你去定义不能捕获的泛型异常)。 -但是,类型参数可能会在一个方法的 **throws** 子句中用到。这使得你可以编写随检查型异常类型变化的泛型代码: +由于擦除的原因,**catch** 语句不能捕获泛型类型的异常,因为在编译期和运行时都必须知道异常的确切类型。泛型类也不能直接或间接地继承 **Throwable**(这将进一步阻止你试图定义不能捕获的泛型异常)。 +但是,类型参数可以在方法声明的 **throws** 子句中使用。这意味着你可以编写随【被检查的异常】的类型而变化的泛型代码: ```java // generics/ThrowGenericException.java @@ -4173,8 +4172,7 @@ interface Processor { void process(List resultCollector) throws E; } -class ProcessRunner -extends ArrayList> { +class ProcessRunner extends ArrayList> { List processAll() throws E { List resultCollector = new ArrayList<>(); for(Processor processor : this) @@ -4185,12 +4183,10 @@ extends ArrayList> { class Failure1 extends Exception {} -class Processor1 -implements Processor { +class Processor1 implements Processor { static int count = 3; @Override - public void process(List resultCollector) - throws Failure1 { + public void process(List resultCollector) throws Failure1 { if(count-- > 1) resultCollector.add("Hep!"); else @@ -4202,12 +4198,10 @@ implements Processor { class Failure2 extends Exception {} -class Processor2 -implements Processor { +class Processor2 implements Processor { static int count = 2; @Override - public void process(List resultCollector) - throws Failure2 { + public void process(List resultCollector) throws Failure2 { if(count-- == 0) resultCollector.add(47); else { @@ -4247,15 +4241,15 @@ Failure2 */ ``` -**Processor** 执行 `process()` 方法,并且可能会抛出具有类型 **E** 的异常。`process()` 的结果存储在 `ListresultCollector` 中(这被称为*收集参数*)。**ProcessRunner** 有一个 `processAll()` 方法,它会在所持有的每个 **Process** 对象执行,并返回 **resultCollector** 。 -如果不能参数化所抛出的异常,那么由于检查型异常的缘故,将不能编写出这种泛化的代码。 +**Processor** 执行 `process()` 方法,并且可能会抛出具有类型 **E** 的异常。`process()` 的结果存储在 `ListresultCollector` 中(这被称为*收集参数* *collecting* *parameter*)。**ProcessRunner** 有一个 `processAll()` 方法,它执行它所持有的每个 **Process** 对象,并返回 **resultCollector** 。 +如果不能参数化所抛出的异常(`E extends Exception`),那么由于【被检查的异常】的缘故,将不能编写出这种通用的代码。 ## 混型 -术语*混型*随时间的推移好像拥有了无数的含义,但是其最基本的概念是混合多个类的能力,以产生一个可以表示混型中所有类型的类。这往往是你最后的手段,它将使组装多个类变得简单易行。 -混型的价值之一是它们可以将特性和行为一致地应用于多个类之上。如果想在混型类中修改某些东西,作为一种意外的好处,这些修改将会应用于混型所应用的所有类型之上。正由于此,混型有一点*面向切面编程* (AOP) 的味道,而切面经常被建议用来解决混型问题。 +*混型* **mixin** 这一术语已经被赋予了多种含义,但其最基本的概念是将多个类的功能混合起来,由此产生一个类,可以代表所有类型的混型 **mixins** 。这往往是你最后才做的事情——方便了你轻松组装类。 +混型的价值之一是它们可以将特性和行为一致地应用于多个类之上。另外,如果在混型类中修改了某些东西,这些修改将会应用在所有使用混型的类上面。正因为这样,混型有一点*面向切面编程* (AOP) 的味道,而切面经常被建议用来解决混型问题。 ### C++ 中的混型 @@ -4316,11 +4310,11 @@ test string 2 1452987605 2 TimeStamped> mixin1,mixin2; ``` -遗憾的是,Java 泛型不允许这样。擦除会忘记基类类型,因此 +遗憾的是,Java 泛型不允许这样。擦除会忘记基类类型,因此: > 泛型类不能直接继承自一个泛型参数 -这突显了许多我在 Java 语言设计决策(以及与这些功能一起发布)中遇到的一大问题:处理一件事很有希望,但是当您实际尝试做一些有趣的事情时,您会发现自己做不到。 +这突显了我在许多 Java 语言设计决策(以及与这些特性一起推广)中遇到的一大问题:有很多承诺,但是当您真正尝试做一些有趣的事情时,您会发现做不到。 ### 与接口混合 @@ -4364,11 +4358,9 @@ class BasicImp implements Basic { public String get() { return value; } } -class Mixin extends BasicImp -implements TimeStamped, SerialNumbered { +class Mixin extends BasicImp implements TimeStamped, SerialNumbered { private TimeStamped timeStamp = new TimeStampedImp(); - private SerialNumbered serialNumber = - new SerialNumberedImp(); + private SerialNumbered serialNumber = new SerialNumberedImp(); @Override public long getStamp() { return timeStamp.getStamp(); @@ -4396,13 +4388,13 @@ test string 2 1494331663027 2 */ ``` -**Mixin** 类基本上是在使用*委托*,因此每个混入类型都要求在 **Mixin** 中有一个相应的域,而你必须在 **Mixin** 中编写所有必需的方法,将方法调用转发给恰当的对象。这个示例使用了非常简单的类,但是当使用更复杂的混型时,代码数量会急速增加。[^4] +上面的 **Mixin** 类基本上是在使用*委托* *delegation*,因此每个混入类型都要求在 **Mixin** 中有一个相应的字段,而你必须在 **Mixin** 中编写所有必需的方法,将方法调用转发给恰当的对象。这个示例使用了一些简单的类,但是当使用更复杂的混型时,代码数量会急速增加。[^4] ### 使用装饰器模式 当你观察混型的使用方式时,就会发现混型概念好像与*装饰器*设计模式关系很近。装饰器经常用于满足各种可能的组合,而直接子类化会产生过多的类,因此是不实际的。 -装饰器模式使用分层对象来动态透明地向单个对象中添加责任。装饰器指定包装在最初的对象周围的所有对象都具有相同的基本接口。某些事物是可装饰的,可以通过将其他类包装在这个可装饰对象的四周,来将功能分层。这使得对装饰器的使用是透明的——无论对象是否被装饰,你都拥有一个可以向对象发送的公共消息集。装饰类也可以添加新方法,但是正如你所见,这将是受限的。 -装饰器是通过使用组合和形式化结构(可装饰物/装饰器层次结构)来实现的,而混型是基于继承的。因此可以将基于参数化类型的混型当作是一种泛型装饰器机制,这种机制不需要装饰器设计模式的继承结构。 +装饰器模式使用分层对象来动态透明地向单个对象中添加责任。该模式规定,包装在最初的对象周围的所有对象都具有相同的基本接口。某些事物是可装饰的,可以通过将其他类包装在这个可装饰对象的四周,来将功能分层。这使得对装饰器的使用是透明的——无论对象是否被装饰,你都拥有一个可以向对象发送的公共消息集。装饰类也可以添加新方法,但是正如你所见,这将是受限的。 +装饰器是通过使用组合和形式化结构(可装饰物/装饰器层次结构)来实现的,而混型是基于继承的。可以将基于参数化类型的混型当作是一种泛型装饰器机制,这种机制不需要装饰器设计模式的继承结构。 前面的示例可以被改写为使用装饰器: ```java From 7f9f861f0ed17f422aba14593071d4c92dfbe40c Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 8 Jan 2021 11:43:45 +0800 Subject: [PATCH 54/68] chapter 20 09 --- docs/book/20-Generics.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index d750032c..86e98e86 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -2721,7 +2721,7 @@ public class GenericsAndCovariance { } ``` -**flist** 的类型现在是 `List`,你可以读作“一个具有任何继承自 **Fruit** 类型的列表”。然而,这实际上并不意味着这个 **List** 将持有任何类型的 **Fruit**。通配符引用的是明确的类型,因此它意味着“一些 **flist** 引用没有指定特定类型”。因此这个被赋值的 **List** 必须持有诸如 **Fruit** 或 **Apple** 这样的指定类型,但是为了向上转型为 **Fruit**,并不关心这个具体的类型是什么。(编译器只知道 **flist** 是**Fruit**某个子类的List,但并不知道这个子类具体是什么类,只好阻止向其中加入任何子类。为了类型安全,不能往使用了`? extends`的数据结构里写入任何的值。) +**flist** 的类型现在是 `List`,你可以读作“一个具有任何继承自 **Fruit** 类型的列表”。然而,这实际上并不意味着这个 **List** 将持有任何类型的 **Fruit**。通配符引用的是明确的类型,因此它意味着“一些 **flist** 引用没有指定特定类型”。因此这个被赋值的 **List** 必须持有诸如 **Fruit** 或 **Apple** 这样的指定类型,但是为了向上转型为 **flist**,并不关心这个具体的类型是什么。(编译器只知道 **flist** 是**Fruit**某个子类的List,但并不知道这个子类具体是什么类,只好阻止向其中加入任何子类。为了类型安全,不能往使用了`? extends`的数据结构里写入任何的值。) **List** 必须持有一种具体的 **Fruit** 或 **Fruit** 的子类型,但是如果你不关心具体的类型是什么,那么你能对这样的 **List** 做什么呢?如果不知道 **List** 中持有的对象是什么类型,你怎能保证安全地向其中添加对象呢?就和 **CovariantArrays.java** 中的 向上转型的数组一样,你不能这样做,只不过是现在是编译器阻止了这种情况的发生,而不是运行时系统——你会更早发现问题。 @@ -4842,9 +4842,9 @@ Pretending to sit 反射提供了一些有用的可能性,但是它将所有的类型检查都转移到了运行时,因此在许多情况下并不是我们所希望的。如果能够实现编译期类型检查,这通常会更符合要求。但是有可能实现编译期类型检查和潜在类型机制吗? -让我们看一个说明这个问题的示例。假设想要创建一个 `apply()` 方法,它能够将任何方法应用于某个序列中的所有对象。这种情况下使用接口不适合,因为你想要将任何方法应用于一个对象集合,而接口不可能描述任何方法。如何用 Java 来实现这个需求呢? +让我们来看一个探讨这个问题的例子。假设想要创建一个 `apply()` 方法——它能够将任何方法应用于序列中的每个对象。这种情况下使用接口不适合,因为你想要将任何方法应用于一个对象集合,而接口不可能描述任何方法。如何用 Java 来实现这个需求呢? -最初,我们可以用反射来解决这个问题,由于有了 Java 的可变参数,这种方式被证明是相当优雅的: +最初,我们可以用反射来解决这个问题,由于用了 Java 5 的可变参数,发现这种方式是相当优雅的: ```java // generics/Apply.java @@ -4870,7 +4870,7 @@ public class Apply { 在 **Apply.java** 中,异常被转换为 **RuntimeException** ,因为没有多少办法可以从这种异常中恢复——在这种情况下,它们实际上代表着程序员的错误。 -为什么我们不只使用 Java 8 方法参考(稍后显示)而不是反射方法 **f** ? 注意,`invoke()` 和 `apply()` 的优点是它们可以接受任意数量的参数。 在某些情况下,灵活性可能至关重要。 +为什么我们不能单单使用 Java 8 方法引用(稍后展示)来代替反射方法 **f** ? 请注意`invoke()` 和 `apply()` 的优点是它们可以接受任意数量的参数。 在某些情况下,灵活性可能至关重要。 为了测试 **Apply** ,我们首先创建一个 **Shape** 类: From ec839a39d512379fd6ef529e06a064a0cff1efd3 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 8 Jan 2021 12:58:18 +0800 Subject: [PATCH 55/68] chapter 20 10 --- docs/book/20-Generics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 86e98e86..6c461179 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -5043,7 +5043,7 @@ Square 11 rotate 我们使用 `peek()` 当做对 `rotate()` 的调用,因为 `peek()` 执行一个操作(此处是出于副作用),并在未更改的情况下传递对象。 -注意,使用 **FilledList** 和 **shapeQ** 调用 `forEach()` 比 `Apply.apply()` 代码整洁得多。 在代码简单性和可读性方面,结果比以前的方法好得多。 并且,现在也不可能从 `main()` 引发异常。 +注意,使用 **FilledList** 和 **shapeQ** 调用 `forEach()` 比 `Apply.apply()` 代码整洁得多。 在代码简单性和可读性方面,结果比以前的方法好得多。 并且,现在不再从 `main()` 引发运行时异常。 From f7860e6a86325acc5e4de7fa0644643dc2fb8d41 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 8 Jan 2021 14:34:27 +0800 Subject: [PATCH 56/68] chapter 20 f --- docs/book/20-Generics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index 6c461179..e63e5a28 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -5156,7 +5156,7 @@ public class Suppliers { `create()` 为你创建一个新的 **Collection** 子类型,而 `fill()` 的第一个版本将元素放入 **Collection** 的现有子类型中。 请注意,还会返回传入的容器的确切类型,因此不会丢失类型信息。[^6] -前两种方法一般都受约束,只能与 **Collection** 子类型一起使用。`fill()` 的第二个版本适用于任何类型的 **holder** 。 它需要一个附加参数:未绑定方法引用 `adder. fill()` ,使用辅助潜在类型来使其与任何具有添加元素方法的 **holder** 类型一起使用。因为此未绑定方法 **adder** 必须带有一个参数(要添加到 **holder** 的元素),所以 **adder** 必须是 `BiConsumer ` ,其中 **H** 是要绑定到的 **holder** 对象的类型,而 **A** 是要被添加的绑定元素类型。 对 `accept()` 的调用将使用参数 a 调用对象 **holder** 上的未绑定方法 **holder**。 +前两种方法一般都受约束,只能与 **Collection** 子类型一起使用。第二个版本的`fill()` 适用于任何类型的 **holder** 。 它需要一个附加参数:未绑定方法引用 `adder. fill()` ,使用辅助潜在类型来使其与任何具有添加元素方法的 **holder** 类型一起使用。因为此未绑定方法 **adder** 必须带有一个参数(要添加到 **holder** 的元素),所以 **adder** 必须是 `BiConsumer ` ,其中 **H** 是要绑定到的 **holder** 对象的类型,而 **A** 是要被添加的绑定元素类型。 对 `accept()` 的调用将使用参数 a 调用对象 **holder** 上的未绑定方法 **holder**。 在一个稍作模拟的测试中对 **Suppliers** 工具程序进行了测试,该仿真还使用了本章前面定义的 **RandomList** : From 1d69923adefe4c53dc5409edbd2a06b7d040e050 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 8 Jan 2021 14:35:44 +0800 Subject: [PATCH 57/68] chapter 20 f1 --- docs/book/20-Generics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/20-Generics.md b/docs/book/20-Generics.md index e63e5a28..767ac344 100644 --- a/docs/book/20-Generics.md +++ b/docs/book/20-Generics.md @@ -5232,7 +5232,7 @@ Teller 4 serves Customer 12 */ ``` -可以看到 `create()` 生成一个新的 **Collection** 对象,而 `fill()` 添加到现有 **Collection** 中。第二个版本`fill()` 显示,它不仅与无关的新类型 **Bank** 一起使用,还能与 **List** 一起使用。因此,从技术上讲,`fill()` 的第一个版本在技术上不是必需的,但在使用 **Collection** 时提供了较短的语法。 +可以看到 `create()` 生成一个新的 **Collection** 对象,而 `fill()` 添加到现有 **Collection** 中。第二个版本`fill()` 显示,它不仅与无关的新类型 **Bank** 一起使用,还能与 **List** 一起使用。因此,从技术上讲,`fill()` 的第一个版本不是必需的,但使用 **Collection** 提供了较短的语法。 From 1720b3045c32f6671a47e59e4eda5854c15ffd40 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Mon, 22 Feb 2021 09:20:03 +0800 Subject: [PATCH 58/68] chapter 14 f1 --- docs/book/14-Streams.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md index fbb7b87b..69bf9346 100644 --- a/docs/book/14-Streams.md +++ b/docs/book/14-Streams.md @@ -1951,8 +1951,8 @@ Lambda 表达式中的第一个参数 `fr0` 是 `reduce()` 中上一次调用的 ### 匹配 -- `allMatch(Predicate)` :如果流的每个元素提供给 **Predicate** 都返回 true ,结果返回为 true。在第一个 false 时,则停止执行计算。 -- `anyMatch(Predicate)`:如果流的任意一个元素提供给 **Predicate** 返回 true ,结果返回为 true。在第一个 true 是停止执行计算。 +- `allMatch(Predicate)` :如果流的每个元素提供给 **Predicate** 都返回 true ,结果返回为 true。在第一个 false 时停止执行计算。 +- `anyMatch(Predicate)`:如果流的任意一个元素提供给 **Predicate** 返回 true ,结果返回为 true。在第一个 true 时停止执行计算。 - `noneMatch(Predicate)`:如果流的每个元素提供给 **Predicate** 都返回 false 时,结果返回为 true。在第一个 true 时停止执行计算。 我们已经在 `Prime.java` 中看到了 `noneMatch()` 的示例;`allMatch()` 和 `anyMatch()` 的用法基本上是等同的。下面我们来探究一下短路行为。为了消除冗余代码,我们创建了 `show()`。首先我们必须知道如何统一描述上述的这3个匹配器的操作,然后把这描述的概念创建为 **Matcher** 接口。代码示例: From 810db02eaa7dd55fe532cad763e98cc77460b146 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Mon, 22 Feb 2021 10:19:07 +0800 Subject: [PATCH 59/68] chapter 21 f0 --- docs/book/21-Arrays.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/21-Arrays.md b/docs/book/21-Arrays.md index 979170cf..50271bdc 100755 --- a/docs/book/21-Arrays.md +++ b/docs/book/21-Arrays.md @@ -19,7 +19,7 @@ 将数组和其他类型的集合区分开来的原因有三:效率,类型,保存基本数据类型的能力。在 Java 中,使用数组存储和随机访问对象引用序列是非常高效的。数组是简单的线性序列,这使得对元素的访问变得非常快。然而这种高速也是有代价的,代价就是数组对象的大小是固定的,且在该数组的生存期内不能更改。 -速度通常并不是问题,如果有问题,你保存和检索对象的方式也很少是罪魁祸首。你应该总是从 **ArrayList** (来自 [集合](book/12-Collections.md ))开始,它将数组封装起来。必要时,它会自动分配更多的数组空间,创建新数组,并将旧数组中的引用移动到新数组。这种灵活性需要开销,所以一个 **ArrayList** 的效率不如数组。在极少的情况下效率会成为问题,所以这种时候你可以直接使用数组。 +速度通常并不是问题,如果有问题,你保存和检索对象的方式也很少是罪魁祸首。你应该总是从 **ArrayList** (来自 [集合](book/12-Collections.md ))开始,它将数组封装起来,在内部使用和管理数组。必要时,它会自动分配更多的数组空间,创建新数组,并将旧数组中的引用移动到新数组。这种灵活性需要开销,所以一个 **ArrayList** 的效率不如数组。当效率成为了问题的罕见情况下,可以直接使用数组。 数组和集合(Collections)都不能滥用。不管你使用数组还是集合,如果你越界,你都会得到一个 **RuntimeException** 的异常提醒,这表明你的程序中存在错误。 From 54b046db7f99e3034521e9cfcded022aa410aba1 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 26 Feb 2021 10:11:05 +0800 Subject: [PATCH 60/68] chapter 21 f1 --- docs/book/21-Arrays.md | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/docs/book/21-Arrays.md b/docs/book/21-Arrays.md index 50271bdc..bb4b8c0c 100755 --- a/docs/book/21-Arrays.md +++ b/docs/book/21-Arrays.md @@ -745,7 +745,7 @@ a9: [Hello, Hello, Hello, World, World, Hello] * **void setAll(int[] a, IntUnaryOperator gen)** * **void setAll(long[] a, IntToLongFunction gen)** -* **void setAll(double[] a, IntToDoubleFunctiongen)** +* **void setAll(double[] a, IntToDoubleFunction gen)** * ** void setAll(T[] a, IntFunction gen)** 除了 **int** , **long** , **double** 有特殊的版本,其他的一切都由泛型版本处理。生成器不是 **Supplier** 因为它们不带参数,并且必须将 **int** 数组索引作为参数。 @@ -1477,7 +1477,7 @@ public interface Rand { ``` -对于除了 **int** 、 **long** 和 **double** 之外的所有基本类型元素生成器,只生成数组,而不是 Count 中看到的完整操作集。这只是一个设计选择,因为本书不需要额外的功能。 +对于除了 **int** 、 **long** 和 **double** 之外的所有基本类型元素生成器,只生成数组(没对数组内元素初始化,用临近的类型强制转换获得),而不是 Count 中看到的完整操作集。这只是一个设计选择,因为本书不需要额外的功能。 下面是对所有 **Rand** 工具的测试: @@ -2115,10 +2115,17 @@ public class ArrayCopying { } } } -/* Output: a1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] a1: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - a2:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]a2:[0, 1, 2, 3, 4, 5, 6]a2:[ - 0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0]a4:[4, 5, 6, 7, 8, 9, 10, 11][Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6][ - Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6]java.lang.ArrayStoreException */ +/* Output: +a1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] +a1: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +a2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] +a2: [0, 1, 2, 3, 4, 5, 6] +a2: [0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0] +a4: [4, 5, 6, 7, 8, 9, 10, 11] +[Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6] +[Sub0, Sub1, Sub2, Sub3, Sub4, Sub5, Sub6] +java.lang.ArrayStoreException +*/ ``` @@ -2144,7 +2151,7 @@ public class ArrayCopying { **数组** 提供了 **equals()** 来比较一维数组,以及 **deepEquals()** 来比较多维数组。对于所有原生类型和对象,这些方法都是重载的。 -数组相等的含义:数组必须有相同数量的元素,并且每个元素必须与另一个数组中的对应元素相等,对每个元素使用 **equals()**(对于原生类型,使用原生类型的包装类的 **equals()** 方法;例如,int的Integer.equals()。 +数组相等的含义:数组必须有相同数量的元素,并且每个元素必须与另一个数组中的对应元素相等,对每个元素使用 **equals()** ( 对于原生类型,使用原生类型的包装类的 **equals()** 方法;例如,int的Integer.equals()。) ```JAVA // arrays/ComparingArrays.java @@ -2551,11 +2558,11 @@ Location of 635 is 2, a[2] is 635 在while循环中,随机值作为搜索项生成,直到在数组中找到其中一个为止。 -如果找到了搜索项,**Arrays.binarySearch()** 将生成一个大于或等于零的值。否则,它将产生一个负值,表示如果手动维护已排序的数组,则应该插入元素的位置。产生的值是 -(插入点) - 1 。插入点是大于键的第一个元素的索引,如果数组中的所有元素都小于指定的键,则是 **a.size()** 。 +如果找到了搜索项(搜索键 r),**Arrays.binarySearch()** 将生成一个大于或等于零的值。否则,它会产生一个负值,代表如果你是手工维护排序数组的话,该元素应该被插入的位置。产生的值是 - (插入点) - 1 。插入点是大于搜索键 r 的第一个元素的索引,如果数组中的所有元素都小于搜索键 r,则是 **a.size()** 。 -如果数组包含重复的元素,则无法保证找到其中的那些重复项。搜索算法不是为了支持重复的元素,而是为了容忍它们。如果需要没有重复元素的排序列表,可以使用 **TreeSet** (用于维持排序顺序)或 **LinkedHashSet** (用于维持插入顺序)。这些类自动为您处理所有的细节。只有在出现性能瓶颈的情况下,才应该使用手工维护的数组替换这些类中的一个。 +如果数组包含重复的元素,则无法保证找到其中的那些重复项。搜索算法不是为了支持重复的元素,而是为了容忍它们。如果需要元素不重复的排序列表,可以使用 **TreeSet** (用于维持排序)或 **LinkedHashSet** (用于维持插入顺序)。这些类自动为您处理所有的细节。只有在出现性能瓶颈的情况下,才应该使用手工维护的数组替换这些类。 -如果使用比较器(原语数组不允许使用比较器进行排序)对对象数组进行排序,那么在执行 **binarySearch()** (使用重载版本的binarySearch())时必须包含相同的比较器。例如,可以修改 **StringSorting.java** 来执行搜索: +如果使用比较器(原语数组不允许使用比较器进行排序)对对象数组进行排序,那么在执行 **binarySearch()** ( 使用重载版本的binarySearch() ) 时必须包含相同的比较器。例如,可以修改 **StringSorting.java** 来执行搜索: ```JAVA // arrays/AlphabeticSearch.java @@ -2604,11 +2611,11 @@ import static onjava.ArrayShow.*; public class ParallelPrefix1 { public static void main(String[] args) { int[] nums = new Count.Pint().array(10); - show(nums); - System.out.println(Arrays.stream(nums).reduce(Integer::sum).getAsInt()); + show(nums);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + System.out.println(Arrays.stream(nums).reduce(Integer::sum).getAsInt());//45 Arrays.parallelPrefix(nums, Integer::sum); - show(nums); - System.out.println(Arrays.stream(new Count.Pint().array(6)).reduce(Integer::sum).getAsInt()); + show(nums);//[0, 1, 3, 6, 10, 15, 21, 28, 36, 45] + System.out.println(Arrays.stream(new Count.Pint().array(6)).reduce(Integer::sum).getAsInt());//15 } } /* Output: From 133e0f3f4ef7be3823edae2f5351c586baa1d2f0 Mon Sep 17 00:00:00 2001 From: "jim.deng" Date: Fri, 26 Feb 2021 14:29:44 +0800 Subject: [PATCH 61/68] chapter 22 f0 --- docs/book/22-Enumerations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/22-Enumerations.md b/docs/book/22-Enumerations.md index 818641a9..d9e8889d 100644 --- a/docs/book/22-Enumerations.md +++ b/docs/book/22-Enumerations.md @@ -342,7 +342,7 @@ final class Explore extends java.lang.Enum { 答案是,values() 是由编译器添加的 static 方法。可以看出,在创建 Explore 的过程中,编译器还为其添加了 valueOf() 方法。这可能有点令人迷惑,Enum 类不是已经有 valueOf() 方法了吗。 -不过 Enum 中的 valueOf() 方法需要两个参数,而这个新增的方法只需一个参数。由于这里使用的 Set 只存储方法的名字,而不考虑方法的签名,所以在调用 Explore.removeAll(Enum) 之后,就只剩下[values] 了。 +不过 Enum 中的 valueOf() 方法需要两个参数,而这个新增的方法只需一个参数。由于这里存储用的 Set 只存方法名,而不是方法签名,所以在调用 Explore.removeAll(Enum) 之后,就只剩下[values] 了。 从最后的输出中可以看到,编译器将 Explore 标记为 final 类,所以无法继承自 enum,其中还有一个 static 的初始化子句,稍后我们将学习如何重定义该句。 From 857c4bfece915aba217c4984b5a171cd331181b4 Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Mon, 21 Feb 2022 21:54:11 +0800 Subject: [PATCH 62/68] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E7=AB=A0=EF=BC=9A?= =?UTF-8?q?=E9=87=8C=E5=BC=8F=E6=9B=BF=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/01-What-is-an-Object.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/01-What-is-an-Object.md b/docs/book/01-What-is-an-Object.md index b434eaa5..e18a4fcf 100644 --- a/docs/book/01-What-is-an-Object.md +++ b/docs/book/01-What-is-an-Object.md @@ -130,7 +130,7 @@ Java 有三个显式关键字来设置类中的访问权限:`public`(公开 ### "是一个"与"像是一个"的关系 -对于继承可能会引发争论:继承应该只覆盖基类的方法(不应该添加基类中没有的方法)吗?如果这样的话,基类和派生类就是相同的类型了,因为它们具有相同的接口。这会造成,你可以用一个派生类对象完全替代基类对象,这叫作"纯粹替代",也经常被称作"替代原则"。在某种意义上,这是一种处理继承的理想方式。我们经常把这种基类和派生类的关系称为是一个(is-a)关系,因为可以说"圆是一个形状"。判断是否继承,就看在你的类之间有无这种 is-a 关系。 +对于继承可能会引发争论:继承应该只覆盖基类的方法(不应该添加基类中没有的方法)吗?如果这样的话,基类和派生类就是相同的类型了,因为它们具有相同的接口。这会造成,你可以用一个派生类对象完全替代基类对象,这叫作"纯粹替代",也经常被称作"替代原则(里式替换)"。在某种意义上,这是一种处理继承的理想方式。我们经常把这种基类和派生类的关系称为是一个(is-a)关系,因为可以说"圆是一个形状"。判断是否继承,就看在你的类之间有无这种 is-a 关系。 有时你在派生类添加了新的接口元素,从而扩展接口。虽然新类型仍然可以替代基类,但是这种替代不完美,原因在于基类无法访问新添加的方法。这种关系称为像是一个(is-like-a)关系。新类型不但拥有旧类型的接口,而且包含其他方法,所以不能说新旧类型完全相同。 From cc0308a97773476fa1fcc2e0920cc611c2b6391d Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Sat, 26 Feb 2022 10:48:33 +0800 Subject: [PATCH 63/68] 01 --- docs/book/01-What-is-an-Object.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/01-What-is-an-Object.md b/docs/book/01-What-is-an-Object.md index e18a4fcf..5c4c94ad 100644 --- a/docs/book/01-What-is-an-Object.md +++ b/docs/book/01-What-is-an-Object.md @@ -102,7 +102,7 @@ Java 有三个显式关键字来设置类中的访问权限:`public`(公开 使用“组合”关系给我们的程序带来极大的灵活性。通常新建的类中,成员对象会使用 `private` 访问权限,这样应用程序员则无法对其直接访问。我们就可以在不影响客户代码的前提下,从容地修改那些成员。我们也可以在“运行时"改变成员对象从而动态地改变程序的行为,这进一步增大了灵活性。下面一节要讲到的“继承”并不具备这种灵活性,因为编译器对通过继承创建的类进行了限制。 -在面向对象编程中经常重点强调“继承”。在新手程序员的印象里,或许先入为主地认为“继承应当随处可见”。沿着这种思路产生的程序设计通常拙劣又复杂。相反,在创建新类时首先要考虑“组合”,因为它更简单灵活,而且设计更加清晰。等我们有一些编程经验后,一旦需要用到继承,就会明显意识到这一点。 +在面向对象编程中经常重点强调“继承”。在新手程序员的印象里,或许先入为主地认为“继承应当随处可见”。沿着这种思路产生的程序设计通常拙劣又复杂。相反,在创建新类时首先要考虑“组合”,因为它更简单灵活,而且设计更加清晰。等我们有一些编程经验后,一旦需要用到继承,就会明显意识到这一点。(合成/聚合复用原则:尽量使用合成/聚合,而不是继承来达到复用的目的) ## 继承 From 642ffa947d6ba6388d9cab9c8713f03e6068c222 Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Mon, 14 Mar 2022 15:29:03 +0800 Subject: [PATCH 64/68] 10 --- docs/book/10-Interfaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/10-Interfaces.md b/docs/book/10-Interfaces.md index f2257f52..100eda86 100644 --- a/docs/book/10-Interfaces.md +++ b/docs/book/10-Interfaces.md @@ -648,7 +648,7 @@ Crack Twist ``` -这里展示了创建 **Operations** 的不同方式:一个外部类(Bing),一个匿名类,一个方法引用和 lambda 表达式——毫无疑问用在这里是最好的解决方法。 +这里展示了创建 **Operations** 的不同方式(self-note:其实并没有展示。。):一个外部类(Bing),一个匿名类,一个方法引用, 一个lambda 表达式——毫无疑问用在这里是最好的解决方法。 这个特性是一项改善,因为它允许把静态方法放在更合适的地方。 From f5a26c8a2310afea63091e0344dc48d2aee6fe3f Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Wed, 16 Mar 2022 00:44:53 +0800 Subject: [PATCH 65/68] 11 --- docs/book/11-Inner-Classes.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md index 66d3d5a1..03771f30 100755 --- a/docs/book/11-Inner-Classes.md +++ b/docs/book/11-Inner-Classes.md @@ -368,9 +368,11 @@ public class Parcel5 { } ``` -**PDestination** 类是 `destination()` 方法的一部分,而不是 **Parcel5** 的一部分。所以,在 `destination()` 之外不能访问 **PDestination**,注意出现在 **return** 语句中的向上转型-返回的是 **Destination** 的引用,它是 **PDestination** 的基类。当然,在 `destination()` 中定义了内部类 **PDestination**,并不意味着一旦 `destination()` 方法执行完毕,**PDestination** 就不可用了。 +**PDestination** 类是 `destination()` 方法的一部分,而不是 **Parcel5** 的一部分。所以,在 `destination()` 之外不能访问 **PDestination**,注意出现在 **return** 语句中的向上转型-返回的是 **Destination** 的引用,它是 **PDestination** 的基类。 -你可以在同一个子目录下的任意类中对某个内部类使用类标识符 **PDestination**,这并不会有命名冲突。 +当然,在 `destination()` 中定义了内部类 **PDestination**,并不是说一旦 `destination()` 方法执行完毕,**PDestination** 就不可用了。( 外部可持有该引用 ) + +由于作用域在方法内部,因此你可以在同一个子目录下的任意类中对某个内部类使用类标识符 **PDestination**,这并不会有命名冲突。 下面的例子展示了如何在任意的作用域内嵌入一个内部类: @@ -1150,7 +1152,7 @@ public class GreenhouseControls extends Controller { 一个由 **Event** 对象组成的数组被递交给 **Restart**,该数组要加到控制器上。由于 `Restart()` 也是一个 **Event** 对象,所以同样可以将 **Restart** 对象添加到 `Restart.action()` 中,以使系统能够有规律地重新启动自己。 -下面的类通过创建一个 **GreenhouseControls** 对象,并添加各种不同的 **Event** 对象来配置该系统,这是 *命令* 设计模式的一个例子—**eventList** 中的每个对象都被封装成对象的请求: +下面的类通过创建一个 GreenhouseControls 对象,并添加各种不同的 Event 对象来配置该系统,这是 *命令* 设计模式的一个例子—eventList 中的每个对象都是“请求对象”(包含与请求相关的所有信息的独立对象,这样封装的好处是让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作): ```java // innerclasses/GreenhouseController.java From 24b484dded7fdd88c1abc9c1ebfb7258e023861e Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Wed, 16 Mar 2022 01:02:47 +0800 Subject: [PATCH 66/68] 11 1 --- docs/book/11-Inner-Classes.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md index 03771f30..1ba39158 100755 --- a/docs/book/11-Inner-Classes.md +++ b/docs/book/11-Inner-Classes.md @@ -1413,9 +1413,15 @@ Anonymous inner 8 Anonymous inner 9 ``` -**Counter** 返回的是序列中的下一个值。我们分别使用局部内部类和匿名内部类实现了这个功能,它们具有相同的行为和能力,既然局部内部类的名字在方法外是不可见的,那为什么我们仍然使用局部内部类而不是匿名内部类呢?唯一的理由是,我们需要一个已命名的构造器,或者需要重载构造器,而匿名内部类只能使用实例初始化。 +**Counter** 返回的是序列中的下一个值。我们分别使用局部内部类和匿名内部类实现了这个功能,它们具有相同的行为和能力,既然局部内部类的名字在方法外是不可见的,那为什么我们仍然使用局部内部类而不是匿名内部类呢? -所以使用局部内部类而不使用匿名内部类的另一个理由就是,需要不止一个该内部类的对象。 +使用局部内部类而不使用匿名内部类的第一个理由是, + +我们需要一个已命名的构造器,或者需要重载构造器,而匿名内部类只能使用实例初始化。 + +使用局部内部类而不使用匿名内部类的第二个理由就是, + +需要不止一个内部类,因此要用两个局部内部类,每个都必须有名字。 From d81bdcd24d953cc7a4cdcc98128f606acfdd8cdf Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Wed, 16 Mar 2022 21:29:56 +0800 Subject: [PATCH 67/68] 13 0 --- docs/book/13-Functional-Programming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/13-Functional-Programming.md b/docs/book/13-Functional-Programming.md index 65f3ece4..80e4b61f 100644 --- a/docs/book/13-Functional-Programming.md +++ b/docs/book/13-Functional-Programming.md @@ -23,7 +23,7 @@ OO(object oriented,面向对象)是抽象数据,FP(functional programming,函数式编程)是抽象行为。 -纯粹的函数式语言在安全性方面更进一步。它强加了额外的约束,即所有数据必须是不可变的:设置一次,永不改变。将值传递给函数,该函数然后生成新值但从不修改自身外部的任何东西(包括其参数或该函数范围之外的元素)。当强制执行此操作时,你知道任何错误都不是由所谓的副作用引起的,因为该函数仅创建并返回结果,而不是其他任何错误。 +纯粹的函数式语言在安全性方面更进一步。它强加了额外的约束,即所有数据必须是不可变的:设置一次,永不改变。将值传递给函数,该函数然后生成新值但从不修改自身外部的任何东西(包括其参数或该函数范围之外的元素)。当强制执行此操作时,你知道任何错误都不是由所谓的副作用引起的,因为该函数仅创建并返回结果,不做其它操作。 更好的是,“不可变对象和无副作用”范式解决了并发编程中最基本和最棘手的问题之一(当程序的某些部分同时在多个处理器上运行时)。这是可变共享状态的问题,这意味着代码的不同部分(在不同的处理器上运行)可以尝试同时修改同一块内存(谁赢了?没人知道)。如果函数永远不会修改现有值但只生成新值,则不会对内存产生争用,这是纯函数式语言的定义。 因此,经常提出纯函数式语言作为并行编程的解决方案(还有其他可行的解决方案)。 From b45a3c1c1070648e5840a4180857a8d07f3e4c5c Mon Sep 17 00:00:00 2001 From: andyphone <792998301@qq.com> Date: Wed, 16 Mar 2022 23:58:30 +0800 Subject: [PATCH 68/68] 9 1 --- docs/book/09-Polymorphism.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/09-Polymorphism.md b/docs/book/09-Polymorphism.md index ddca482d..52af1bc4 100644 --- a/docs/book/09-Polymorphism.md +++ b/docs/book/09-Polymorphism.md @@ -591,7 +591,7 @@ sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0 当 **Sub** 对象向上转型为 **Super** 引用时,任何属性访问都被编译器解析,因此不是多态的。在这个例子中,**Super.field** 和 **Sub.field** 被分配了不同的存储空间,因此,**Sub** 实际上包含了两个称为 **field** 的属性:它自己的和来自 **Super** 的。然而,在引用 **Sub** 的 **field** 时,默认的 **field** 属性并不是 **Super** 版本的 **field** 属性。为了获取 **Super** 的 **field** 属性,需要显式地指明 **super.field**。 -尽管这看起来是个令人困惑的问题,实际上基本不会发生。首先,通常会将所有的属性都指明为 **private**,因此不能直接访问它们,只能通过方法来访问。此外,你可能也不会给基类属性和派生类属性起相同的名字,这样做会令人困惑。 +尽管这看起来是个令人困惑的问题,实际上基本不会发生。首先,通常会将所有的属性都指明为 **private**,因此不能直接访问它们,只能通过方法来访问(利用函数的副作用)。此外,你可能也不会给基类属性和派生类属性起相同的名字,这样做会令人困惑。 如果一个方法是静态(**static**)的,它的行为就不具有多态性: