JavaNotesForProfessionals PDF
JavaNotesForProfessionals PDF
Java
Notes for Professionals
®
900+ pages
of professional hints and tricks
Disclaimer
GoalKicker.com This is an unocial free book created for educational purposes and is
not aliated with ocial Java® group(s) or company(s).
Free Programming Books All trademarks and registered trademarks are
the property of their respective owners
Contents
About ................................................................................................................................................................................... 1
Chapter 1: Getting started with Java Language .......................................................................................... 2
Section 1.1: Creating Your First Java Program ........................................................................................................... 2
Chapter 2: Type Conversion .................................................................................................................................... 7
Section 2.1: Numeric primitive casting ......................................................................................................................... 7
Section 2.2: Basic Numeric Promotion ........................................................................................................................ 7
Section 2.3: Non-numeric primitive casting ................................................................................................................ 7
Section 2.4: Object casting ........................................................................................................................................... 8
Section 2.5: Testing if an object can be cast using instanceof ................................................................................. 8
Chapter 3: Getters and Setters ............................................................................................................................. 9
Section 3.1: Using a setter or getter to implement a constraint ............................................................................... 9
Section 3.2: Why Use Getters and Setters? ................................................................................................................ 9
Section 3.3: Adding Getters and Setters ................................................................................................................... 10
Chapter 4: Reference Data Types .................................................................................................................... 12
Section 4.1: Dereferencing .......................................................................................................................................... 12
Section 4.2: Instantiating a reference type ............................................................................................................... 12
Chapter 5: Java Compiler - 'javac' .................................................................................................................... 13
Section 5.1: The 'javac' command - getting started ................................................................................................ 13
Section 5.2: Compiling for a dierent version of Java ............................................................................................ 15
Chapter 6: Documenting Java Code ................................................................................................................. 17
Section 6.1: Building Javadocs From the Command Line ....................................................................................... 17
Section 6.2: Class Documentation ............................................................................................................................. 17
Section 6.3: Method Documentation ......................................................................................................................... 18
Section 6.4: Package Documentation ....................................................................................................................... 19
Section 6.5: Links ......................................................................................................................................................... 19
Section 6.6: Code snippets inside documentation ................................................................................................... 20
Section 6.7: Field Documentation .............................................................................................................................. 21
Section 6.8: Inline Code Documentation ................................................................................................................... 21
Chapter 7: Command line Argument Processing ....................................................................................... 23
Section 7.1: Argument processing using GWT ToolBase ......................................................................................... 23
Section 7.2: Processing arguments by hand ............................................................................................................ 23
Chapter 8: The Java Command - 'java' and 'javaw' ................................................................................. 26
Section 8.1: Entry point classes .................................................................................................................................. 26
Section 8.2: Troubleshooting the 'java' command .................................................................................................. 26
Section 8.3: Running a Java application with library dependencies ..................................................................... 28
Section 8.4: Java Options ........................................................................................................................................... 29
Section 8.5: Spaces and other special characters in arguments ........................................................................... 30
Section 8.6: Running an executable JAR file ............................................................................................................ 32
Section 8.7: Running a Java applications via a "main" class ................................................................................. 32
Chapter 9: Date Class ............................................................................................................................................... 34
Section 9.1: Convert java.util.Date to java.sql.Date .................................................................................................. 34
Section 9.2: A basic date output ................................................................................................................................ 34
Section 9.3: Java 8 LocalDate and LocalDateTime objects ................................................................................... 35
Section 9.4: Creating a Specific Date ........................................................................................................................ 36
Section 9.5: Converting Date to a certain String format ......................................................................................... 36
Section 9.6: LocalTime ................................................................................................................................................ 37
Section 9.7: Convert formatted string representation of date to Date object ..................................................... 37
Section 9.8: Creating Date objects ............................................................................................................................ 38
Section 9.9: Comparing Date objects ........................................................................................................................ 38
Section 9.10: Converting String into Date ................................................................................................................. 41
Section 9.11: Time Zones and java.util.Date .............................................................................................................. 41
Chapter 10: Dates and Time (java.time.*) ...................................................................................................... 43
Section 10.1: Calculate Dierence between 2 LocalDates ....................................................................................... 43
Section 10.2: Date and time ........................................................................................................................................ 43
Section 10.3: Operations on dates and times ........................................................................................................... 43
Section 10.4: Instant ..................................................................................................................................................... 43
Section 10.5: Usage of various classes of Date Time API ....................................................................................... 44
Section 10.6: Date Time Formatting .......................................................................................................................... 46
Section 10.7: Simple Date Manipulations ................................................................................................................... 46
Chapter 11: LocalTime ............................................................................................................................................... 48
Section 11.1: Amount of time between two LocalTime ............................................................................................. 48
Section 11.2: Intro ......................................................................................................................................................... 49
Section 11.3: Time Modification ................................................................................................................................... 49
Section 11.4: Time Zones and their time dierence ................................................................................................. 49
Chapter 12: Literals .................................................................................................................................................... 51
Section 12.1: Using underscore to improve readability ............................................................................................ 51
Section 12.2: Hexadecimal, Octal and Binary literals ............................................................................................... 51
Section 12.3: Boolean literals ...................................................................................................................................... 52
Section 12.4: String literals .......................................................................................................................................... 52
Section 12.5: The Null literal ........................................................................................................................................ 53
Section 12.6: Escape sequences in literals ................................................................................................................ 53
Section 12.7: Character literals ................................................................................................................................... 54
Section 12.8: Decimal Integer literals ......................................................................................................................... 54
Section 12.9: Floating-point literals ............................................................................................................................ 55
Chapter 13: Operators .............................................................................................................................................. 58
Section 13.1: The Increment/Decrement Operators (++/--) .................................................................................... 58
Section 13.2: The Conditional Operator (? :) ............................................................................................................. 59
Section 13.3: The Bitwise and Logical Operators (~, &, |, ^) ..................................................................................... 60
Section 13.4: The String Concatenation Operator (+) .............................................................................................. 61
Section 13.5: The Arithmetic Operators (+, -, *, /, %) ................................................................................................ 63
Section 13.6: The Shift Operators (<<, >> and >>>) ................................................................................................... 66
Section 13.7: The Instanceof Operator ...................................................................................................................... 67
Section 13.8: The Assignment Operators (=, +=, -=, *=, /=, %=, <<=, >>= , >>>=, &=, |= and ^=) ................................. 67
Section 13.9: The conditional-and and conditional-or Operators ( && and || ) ..................................................... 69
Section 13.10: The Relational Operators (<, <=, >, >=) ............................................................................................... 71
Section 13.11: The Equality Operators (==, !=) ............................................................................................................. 71
Section 13.12: The Lambda operator ( -> ) ................................................................................................................ 74
Chapter 14: Primitive Data Types ...................................................................................................................... 75
Section 14.1: The char primitive .................................................................................................................................. 75
Section 14.2: Primitive Types Cheatsheet .................................................................................................................. 75
Section 14.3: The float primitive ................................................................................................................................. 76
Section 14.4: The int primitive ..................................................................................................................................... 77
Section 14.5: Converting Primitives ............................................................................................................................ 78
Section 14.6: Memory consumption of primitives vs. boxed primitives .................................................................. 78
Section 14.7: The double primitive ............................................................................................................................. 79
Section 14.8: The long primitive .................................................................................................................................. 80
Section 14.9: The boolean primitive ........................................................................................................................... 81
Section 14.10: The byte primitive ................................................................................................................................ 81
Section 14.11: Negative value representation ............................................................................................................ 82
Section 14.12: The short primitive ............................................................................................................................... 83
Chapter 15: Constructors ........................................................................................................................................ 84
Section 15.1: Default Constructor ............................................................................................................................... 84
Section 15.2: Call parent constructor ......................................................................................................................... 85
Section 15.3: Constructor with Arguments ................................................................................................................ 86
Chapter 16: Object Class Methods and Constructor ................................................................................. 88
Section 16.1: hashCode() method ............................................................................................................................... 88
Section 16.2: toString() method .................................................................................................................................. 90
Section 16.3: equals() method .................................................................................................................................... 91
Section 16.4: wait() and notify() methods ................................................................................................................. 94
Section 16.5: getClass() method ................................................................................................................................. 95
Section 16.6: clone() method ...................................................................................................................................... 96
Section 16.7: Object constructor ................................................................................................................................. 97
Section 16.8: finalize() method ................................................................................................................................... 99
Chapter 17: Annotations ........................................................................................................................................ 100
Section 17.1: The idea behind Annotations .............................................................................................................. 100
Section 17.2: Defining annotation types .................................................................................................................. 100
Section 17.3: Runtime annotation checks via reflection ........................................................................................ 102
Section 17.4: Built-in annotations ............................................................................................................................. 102
Section 17.5: Compile time processing using annotation processor .................................................................... 105
Section 17.6: Repeating Annotations ....................................................................................................................... 109
Section 17.7: Inherited Annotations .......................................................................................................................... 110
Section 17.8: Getting Annotation values at run-time ............................................................................................. 111
Section 17.9: Annotations for 'this' and receiver parameters ............................................................................... 112
Section 17.10: Add multiple annotation values ....................................................................................................... 113
Chapter 18: Immutable Class .............................................................................................................................. 114
Section 18.1: Example without mutable refs ............................................................................................................ 114
Section 18.2: What is the advantage of immutability? .......................................................................................... 114
Section 18.3: Rules to define immutable classes .................................................................................................... 114
Section 18.4: Example with mutable refs ................................................................................................................. 115
Chapter 19: Immutable Objects ......................................................................................................................... 116
Section 19.1: Creating an immutable version of a type using defensive copying .............................................. 116
Section 19.2: The recipe for an immutable class .................................................................................................... 116
Section 19.3: Typical design flaws which prevent a class from being immutable .............................................. 117
Chapter 20: Visibility (controlling access to members of a class) .................................................. 121
Section 20.1: Private Visibility ................................................................................................................................... 121
Section 20.2: Public Visibility .................................................................................................................................... 121
Section 20.3: Package Visibility ............................................................................................................................... 122
Section 20.4: Protected Visibility .............................................................................................................................. 122
Section 20.5: Summary of Class Member Access Modifiers ................................................................................. 123
Section 20.6: Interface members ............................................................................................................................ 123
Chapter 21: Generics ................................................................................................................................................ 124
Section 21.1: Creating a Generic Class ..................................................................................................................... 124
Section 21.2: Deciding between `T`, `? super T`, and `? extends T` ........................................................................ 126
Section 21.3: The Diamond ....................................................................................................................................... 128
Section 21.4: Declaring a Generic Method .............................................................................................................. 128
Section 21.5: Requiring multiple upper bounds ("extends A & B") ....................................................................... 129
Section 21.6: Obtain class that satisfies generic parameter at runtime .............................................................. 129
Section 21.7: Benefits of Generic class and interface ............................................................................................ 130
Section 21.8: Instantiating a generic type ............................................................................................................... 131
Section 21.9: Creating a Bounded Generic Class ................................................................................................... 131
Section 21.10: Referring to the declared generic type within its own declaration .............................................. 133
Section 21.11: Binding generic parameter to more than 1 type ............................................................................. 134
Section 21.12: Using Generics to auto-cast ............................................................................................................. 135
Section 21.13: Use of instanceof with Generics ....................................................................................................... 135
Section 21.14: Dierent ways for implementing a Generic Interface (or extending a Generic Class) .............. 137
Chapter 22: Classes and Objects ...................................................................................................................... 139
Section 22.1: Overloading Methods ......................................................................................................................... 139
Section 22.2: Explaining what is method overloading and overriding ................................................................ 140
Section 22.3: Constructors ........................................................................................................................................ 142
Section 22.4: Initializing static final fields using a static initializer ........................................................................ 143
Section 22.5: Basic Object Construction and Use .................................................................................................. 144
Section 22.6: Simplest Possible Class ...................................................................................................................... 146
Section 22.7: Object Member vs Static Member .................................................................................................... 146
Chapter 23: Local Inner Class ............................................................................................................................. 148
Section 23.1: Local Inner Class ................................................................................................................................. 148
Chapter 24: Nested and Inner Classes .......................................................................................................... 149
Section 24.1: A Simple Stack Using a Nested Class ............................................................................................... 149
Section 24.2: Static vs Non Static Nested Classes ................................................................................................. 149
Section 24.3: Access Modifiers for Inner Classes ................................................................................................... 151
Section 24.4: Anonymous Inner Classes ................................................................................................................. 152
Section 24.5: Create instance of non-static inner class from outside ................................................................. 153
Section 24.6: Method Local Inner Classes .............................................................................................................. 154
Section 24.7: Accessing the outer class from a non-static inner class ................................................................ 154
Chapter 25: The java.util.Objects Class ......................................................................................................... 156
Section 25.1: Basic use for object null check .......................................................................................................... 156
Section 25.2: Objects.nonNull() method reference use in stream api ................................................................. 156
Chapter 26: Default Methods ............................................................................................................................. 157
Section 26.1: Basic usage of default methods ........................................................................................................ 157
Section 26.2: Accessing overridden default methods from implementing class ............................................... 157
Section 26.3: Why use Default Methods? ............................................................................................................... 158
Section 26.4: Accessing other interface methods within default method ........................................................... 158
Section 26.5: Default method multiple inheritance collision ................................................................................. 159
Section 26.6: Class, Abstract class and Interface method precedence .............................................................. 160
Chapter 27: Packages ............................................................................................................................................ 162
Section 27.1: Using Packages to create classes with the same name ................................................................. 162
Section 27.2: Using Package Protected Scope ...................................................................................................... 162
Chapter 28: Inheritance ......................................................................................................................................... 164
Section 28.1: Inheritance ........................................................................................................................................... 164
Section 28.2: Abstract Classes ................................................................................................................................. 165
Section 28.3: Using 'final' to restrict inheritance and overriding .......................................................................... 167
Section 28.4: The Liskov Substitution Principle ...................................................................................................... 168
Section 28.5: Abstract class and Interface usage: "Is-a" relation vs "Has-a" capability ................................... 168
Section 28.6: Static Inheritance ................................................................................................................................ 172
Section 28.7: Programming to an interface ........................................................................................................... 173
Section 28.8: Overriding in Inheritance ................................................................................................................... 175
Section 28.9: Variable shadowing ........................................................................................................................... 176
Section 28.10: Narrowing and Widening of object references ............................................................................. 176
Section 28.11: Inheritance and Static Methods ........................................................................................................ 177
Chapter 29: Reference Types ............................................................................................................................. 179
Section 29.1: Dierent Reference Types ................................................................................................................. 179
Chapter 30: Strings .................................................................................................................................................. 181
Section 30.1: Comparing Strings .............................................................................................................................. 181
Section 30.2: Changing the case of characters within a String ............................................................................ 183
Section 30.3: Finding a String Within Another String ............................................................................................. 185
Section 30.4: String pool and heap storage ........................................................................................................... 186
Section 30.5: Splitting Strings ................................................................................................................................... 187
Section 30.6: Joining Strings with a delimiter ......................................................................................................... 189
Section 30.7: String concatenation and StringBuilders ......................................................................................... 190
Section 30.8: Substrings ............................................................................................................................................ 191
Section 30.9: Platform independent new line separator ....................................................................................... 192
Section 30.10: Reversing Strings .............................................................................................................................. 192
Section 30.11: Adding toString() method for custom objects ................................................................................ 193
Section 30.12: Remove Whitespace from the Beginning and End of a String .................................................... 194
Section 30.13: Case insensitive switch ..................................................................................................................... 194
Section 30.14: Replacing parts of Strings ................................................................................................................ 195
Section 30.15: Getting the length of a String .......................................................................................................... 196
Section 30.16: Getting the nth character in a String .............................................................................................. 196
Section 30.17: Counting occurrences of a substring or character in a string ..................................................... 196
Chapter 31: StringBuer ....................................................................................................................................... 198
Section 31.1: String Buer class ................................................................................................................................ 198
Chapter 32: StringBuilder ..................................................................................................................................... 199
Section 32.1: Comparing StringBuer, StringBuilder, Formatter and StringJoiner ............................................ 199
Section 32.2: Repeat a String n times ..................................................................................................................... 200
Chapter 33: String Tokenizer .............................................................................................................................. 201
Section 33.1: StringTokenizer Split by space ........................................................................................................... 201
Section 33.2: StringTokenizer Split by comma ',' .................................................................................................... 201
Chapter 34: Splitting a string into fixed length parts ........................................................................... 202
Section 34.1: Break a string up into substrings all of a known length ................................................................. 202
Section 34.2: Break a string up into substrings all of variable length ................................................................. 202
Chapter 35: BigInteger ........................................................................................................................................... 203
Section 35.1: Initialization .......................................................................................................................................... 203
Section 35.2: BigInteger Mathematical Operations Examples ............................................................................. 204
Section 35.3: Comparing BigIntegers ...................................................................................................................... 206
Section 35.4: Binary Logic Operations on BigInteger ............................................................................................ 207
Section 35.5: Generating random BigIntegers ....................................................................................................... 208
Chapter 36: Console I/O ........................................................................................................................................ 210
Section 36.1: Reading user input from the console ................................................................................................ 210
Section 36.2: Aligning strings in console ................................................................................................................. 211
Section 36.3: Implementing Basic Command-Line Behavior ................................................................................ 212
Chapter 37: BigDecimal ......................................................................................................................................... 214
Section 37.1: Comparing BigDecimals ..................................................................................................................... 214
Section 37.2: Using BigDecimal instead of float .................................................................................................... 214
Section 37.3: BigDecimal.valueOf() ......................................................................................................................... 215
Section 37.4: Mathematical operations with BigDecimal ...................................................................................... 215
Section 37.5: Initialization of BigDecimals with value zero, one or ten ................................................................ 218
Section 37.6: BigDecimal objects are immutable .................................................................................................. 218
Chapter 38: NumberFormat ................................................................................................................................ 220
Section 38.1: NumberFormat .................................................................................................................................... 220
Chapter 39: Bit Manipulation .............................................................................................................................. 221
Section 39.1: Checking, setting, clearing, and toggling individual bits. Using long as bit mask ........................ 221
Section 39.2: java.util.BitSet class ............................................................................................................................ 221
Section 39.3: Checking if a number is a power of 2 .............................................................................................. 222
Section 39.4: Signed vs unsigned shift .................................................................................................................... 224
Section 39.5: Expressing the power of 2 ................................................................................................................. 224
Section 39.6: Packing / unpacking values as bit fragments ................................................................................ 225
Chapter 40: Arrays .................................................................................................................................................. 226
Section 40.1: Creating and Initializing Arrays ......................................................................................................... 226
Section 40.2: Creating a List from an Array ........................................................................................................... 232
Section 40.3: Creating an Array from a Collection ................................................................................................ 234
Section 40.4: Multidimensional and Jagged Arrays .............................................................................................. 234
Section 40.5: ArrayIndexOutOfBoundsException .................................................................................................. 236
Section 40.6: Array Covariance ............................................................................................................................... 237
Section 40.7: Arrays to Stream ................................................................................................................................ 238
Section 40.8: Iterating over arrays .......................................................................................................................... 238
Section 40.9: Arrays to a String ............................................................................................................................... 240
Section 40.10: Sorting arrays ................................................................................................................................... 241
Section 40.11: Getting the Length of an Array ........................................................................................................ 243
Section 40.12: Finding an element in an array ....................................................................................................... 243
Section 40.13: How do you change the size of an array? ..................................................................................... 244
Section 40.14: Converting arrays between primitives and boxed types ............................................................. 245
Section 40.15: Remove an element from an array ................................................................................................ 246
Section 40.16: Comparing arrays for equality ........................................................................................................ 247
Section 40.17: Copying arrays .................................................................................................................................. 247
Section 40.18: Casting Arrays ................................................................................................................................... 248
Chapter 41: Streams ............................................................................................................................................... 250
Section 41.1: Using Streams ...................................................................................................................................... 250
Section 41.2: Consuming Streams ............................................................................................................................ 252
Section 41.3: Creating a Frequency Map ................................................................................................................ 254
Section 41.4: Infinite Streams ................................................................................................................................... 254
Section 41.5: Collect Elements of a Stream into a Collection ................................................................................ 255
Section 41.6: Using Streams to Implement Mathematical Functions ................................................................... 257
Section 41.7: Flatten Streams with flatMap() .......................................................................................................... 258
Section 41.8: Parallel Stream .................................................................................................................................... 259
Section 41.9: Creating a Stream ............................................................................................................................... 259
Section 41.10: Finding Statistics about Numerical Streams ................................................................................... 261
Section 41.11: Converting an iterator to a stream ................................................................................................... 261
Section 41.12: Using IntStream to iterate over indexes .......................................................................................... 261
Section 41.13: Concatenate Streams ........................................................................................................................ 262
Section 41.14: Reduction with Streams .................................................................................................................... 262
Section 41.15: Using Streams of Map.Entry to Preserve Initial Values after Mapping ........................................ 265
Section 41.16: IntStream to String ............................................................................................................................. 265
Section 41.17: Finding the First Element that Matches a Predicate ...................................................................... 265
Section 41.18: Using Streams and Method References to Write Self-Documenting Processes ........................ 266
Section 41.19: Converting a Stream of Optional to a Stream of Values .............................................................. 267
Section 41.20: Get a Slice of a Stream ..................................................................................................................... 267
Section 41.21: Create a Map based on a Stream .................................................................................................... 267
Section 41.22: Joining a stream to a single String ................................................................................................. 268
Section 41.23: Sort Using Stream ............................................................................................................................. 269
Section 41.24: Streams of Primitives ........................................................................................................................ 270
Section 41.25: Stream operations categories ......................................................................................................... 270
Section 41.26: Collect Results of a Stream into an Array ...................................................................................... 271
Section 41.27: Generating random Strings using Streams .................................................................................... 271
Chapter 42: InputStreams and OutputStreams ....................................................................................... 272
Section 42.1: Closing Streams .................................................................................................................................. 272
Section 42.2: Reading InputStream into a String ................................................................................................... 272
Section 42.3: Wrapping Input/Output Streams ..................................................................................................... 273
Section 42.4: DataInputStream Example ................................................................................................................ 274
Section 42.5: Writing bytes to an OutputStream ................................................................................................... 274
Section 42.6: Copying Input Stream to Output Stream ......................................................................................... 274
Chapter 43: Readers and Writers .................................................................................................................... 276
Section 43.1: BueredReader ................................................................................................................................... 276
Section 43.2: StringWriter Example ......................................................................................................................... 277
Chapter 44: Preferences ...................................................................................................................................... 278
Section 44.1: Using preferences ............................................................................................................................... 278
Section 44.2: Adding event listeners ....................................................................................................................... 278
Section 44.3: Getting sub-nodes of Preferences .................................................................................................... 279
Section 44.4: Coordinating preferences access across multiple application instances .................................... 280
Section 44.5: Exporting preferences ....................................................................................................................... 280
Section 44.6: Importing preferences ....................................................................................................................... 281
Section 44.7: Removing event listeners .................................................................................................................. 282
Section 44.8: Getting preferences values ............................................................................................................... 283
Section 44.9: Setting preferences values ................................................................................................................ 283
Chapter 45: Collections ......................................................................................................................................... 284
Section 45.1: Removing items from a List within a loop ........................................................................................ 284
Section 45.2: Constructing collections from existing data .................................................................................... 286
Section 45.3: Declaring an ArrayList and adding objects ..................................................................................... 288
Section 45.4: Iterating over Collections ................................................................................................................... 288
Section 45.5: Immutable Empty Collections ........................................................................................................... 290
Section 45.6: Sub Collections ................................................................................................................................... 290
Section 45.7: Unmodifiable Collection ..................................................................................................................... 291
Section 45.8: Pitfall: concurrent modification exceptions ..................................................................................... 292
Section 45.9: Removing matching items from Lists using Iterator ...................................................................... 292
Section 45.10: Join lists ............................................................................................................................................. 293
Section 45.11: Creating your own Iterable structure for use with Iterator or for-each loop .............................. 293
Section 45.12: Collections and Primitive Values ..................................................................................................... 295
Chapter 46: Queues and Deques ...................................................................................................................... 296
Section 46.1: The usage of the PriorityQueue ......................................................................................................... 296
Section 46.2: Deque .................................................................................................................................................. 296
Section 46.3: Stacks .................................................................................................................................................. 297
Section 46.4: BlockingQueue .................................................................................................................................... 298
Section 46.5: LinkedList as a FIFO Queue ............................................................................................................... 299
Section 46.6: Queue Interface .................................................................................................................................. 300
Chapter 47: Collection Factory Methods ..................................................................................................... 301
Section 47.1: List<E> Factory Method Examples .................................................................................................... 301
Section 47.2: Set<E> Factory Method Examples .................................................................................................... 301
Section 47.3: Map<K, V> Factory Method Examples ............................................................................................. 301
Chapter 48: Alternative Collections ................................................................................................................ 302
Section 48.1: Multimap in Guava, Apache and Eclipse Collections ....................................................................... 302
Section 48.2: Apache HashBag, Guava HashMultiset and Eclipse HashBag ...................................................... 304
Section 48.3: Compare operation with collections - Create collections .............................................................. 306
Chapter 49: Concurrent Collections ............................................................................................................... 311
Section 49.1: Thread-safe Collections ..................................................................................................................... 311
Section 49.2: Insertion into ConcurrentHashMap .................................................................................................. 311
Section 49.3: Concurrent Collections ....................................................................................................................... 312
Chapter 50: Choosing Collections .................................................................................................................... 314
Section 50.1: Java Collections Flowchart ................................................................................................................ 314
Chapter 51: super keyword .................................................................................................................................. 315
Section 51.1: Super keyword use with examples ..................................................................................................... 315
Chapter 52: Serialization ...................................................................................................................................... 318
Section 52.1: Basic Serialization in Java .................................................................................................................. 318
Section 52.2: Custom Serialization .......................................................................................................................... 319
Section 52.3: Versioning and serialVersionUID ...................................................................................................... 322
Section 52.4: Serialization with Gson ....................................................................................................................... 323
Section 52.5: Custom JSON Deserialization with Jackson ................................................................................... 324
Chapter 53: Enums ................................................................................................................................................... 327
Section 53.1: Declaring and using a basic enum .................................................................................................... 327
Section 53.2: Enums with constructors ................................................................................................................... 330
Section 53.3: Enums with Abstract Methods ........................................................................................................... 331
Section 53.4: Implements Interface ......................................................................................................................... 332
Section 53.5: Implement Singleton pattern with a single-element enum ............................................................ 333
Section 53.6: Using methods and static blocks ...................................................................................................... 334
Section 53.7: Zero instance enum ........................................................................................................................... 335
Section 53.8: Enum as a bounded type parameter ............................................................................................... 335
Section 53.9: Documenting enums .......................................................................................................................... 335
Section 53.10: Enum constant specific body ........................................................................................................... 336
Section 53.11: Getting the values of an enum ......................................................................................................... 338
Section 53.12: Enum Polymorphism Pattern ........................................................................................................... 338
Section 53.13: Compare and Contains for Enum values ........................................................................................ 339
Section 53.14: Get enum constant by name ........................................................................................................... 340
Section 53.15: Enum with properties (fields) ........................................................................................................... 340
Section 53.16: Convert enum to String .................................................................................................................... 341
Section 53.17: Enums with static fields ..................................................................................................................... 341
Chapter 54: Enum Map .......................................................................................................................................... 343
Section 54.1: Enum Map Book Example .................................................................................................................. 343
Chapter 55: EnumSet class .................................................................................................................................. 344
Section 55.1: Enum Set Example .............................................................................................................................. 344
Chapter 56: Enum starting with number ...................................................................................................... 345
Section 56.1: Enum with name at begining ............................................................................................................. 345
Chapter 57: Lists ....................................................................................................................................................... 346
Section 57.1: Sorting a generic list ........................................................................................................................... 346
Section 57.2: Convert a list of integers to a list of strings ..................................................................................... 347
Section 57.3: Classes implementing List - Pros and Cons ..................................................................................... 347
Section 57.4: Finding common elements between 2 lists ..................................................................................... 349
Section 57.5: In-place replacement of a List element ........................................................................................... 350
Section 57.6: Making a list unmodifiable ................................................................................................................ 351
Section 57.7: Moving objects around in the list ...................................................................................................... 351
Section 57.8: Creating, Adding and Removing element from an ArrayList ........................................................ 351
Section 57.9: Creating a List ..................................................................................................................................... 352
Section 57.10: Positional Access Operations ........................................................................................................... 353
Section 57.11: Iterating over elements in a list ........................................................................................................ 355
Section 57.12: Removing elements from list B that are present in the list A ....................................................... 355
Chapter 58: Sets ........................................................................................................................................................ 357
Section 58.1: Initialization .......................................................................................................................................... 357
Section 58.2: Basics of Set ........................................................................................................................................ 357
Section 58.3: Types and Usage of Sets ................................................................................................................... 358
Section 58.4: Create a list from an existing Set ..................................................................................................... 359
Section 58.5: Eliminating duplicates using Set ....................................................................................................... 359
Section 58.6: Declaring a HashSet with values ...................................................................................................... 360
Chapter 59: List vs Set ........................................................................................................................................... 361
Section 59.1: List vs Set ............................................................................................................................................. 361
Chapter 60: Maps ..................................................................................................................................................... 362
Section 60.1: Iterating Map Entries Eciently ......................................................................................................... 362
Section 60.2: Usage of HashMap ............................................................................................................................ 364
Section 60.3: Using Default Methods of Map from Java 8 ................................................................................... 365
Section 60.4: Iterating through the contents of a Map ......................................................................................... 367
Section 60.5: Merging, combine and composing Maps ........................................................................................ 368
Section 60.6: Add multiple items .............................................................................................................................. 369
Section 60.7: Creating and Initializing Maps ........................................................................................................... 370
Section 60.8: Check if key exists .............................................................................................................................. 372
Section 60.9: Add an element .................................................................................................................................. 372
Section 60.10: Clear the map .................................................................................................................................... 373
Section 60.11: Use custom object as key ................................................................................................................. 373
Chapter 61: LinkedHashMap ................................................................................................................................ 374
Section 61.1: Java LinkedHashMap class ................................................................................................................ 374
Chapter 62: TreeMap and TreeSet .................................................................................................................. 375
Section 62.1: TreeMap of a simple Java type ........................................................................................................ 375
Section 62.2: TreeSet of a simple Java Type ......................................................................................................... 375
Section 62.3: TreeMap/TreeSet of a custom Java type ....................................................................................... 376
Section 62.4: TreeMap and TreeSet Thread Safety .............................................................................................. 377
Chapter 63: SortedMap ......................................................................................................................................... 379
Section 63.1: Introduction to sorted Map ................................................................................................................ 379
Chapter 64: WeakHashMap ................................................................................................................................ 380
Section 64.1: Concepts of WeakHashmap .............................................................................................................. 380
Chapter 65: Hashtable ........................................................................................................................................... 381
Section 65.1: Hashtable ............................................................................................................................................. 381
Chapter 66: Optional ............................................................................................................................................... 382
Section 66.1: Map ....................................................................................................................................................... 382
Section 66.2: Return default value if Optional is empty ........................................................................................ 383
Section 66.3: Throw an exception, if there is no value .......................................................................................... 383
Section 66.4: Lazily provide a default value using a Supplier .............................................................................. 383
Section 66.5: Filter ..................................................................................................................................................... 384
Section 66.6: Using Optional containers for primitive number types .................................................................. 384
Section 66.7: Run code only if there is a value present ......................................................................................... 385
Section 66.8: FlatMap ................................................................................................................................................ 385
Chapter 67: Object References ......................................................................................................................... 386
Section 67.1: Object References as method parameters ...................................................................................... 386
Chapter 68: Exceptions and exception handling ...................................................................................... 389
Section 68.1: Catching an exception with try-catch ............................................................................................... 389
Section 68.2: The try-with-resources statement .................................................................................................... 390
Section 68.3: Custom Exceptions ............................................................................................................................. 393
Section 68.4: Handling InterruptedException ......................................................................................................... 395
Section 68.5: Return statements in try catch block ............................................................................................... 396
Section 68.6: Introduction ......................................................................................................................................... 397
Section 68.7: The Java Exception Hierarchy - Unchecked and Checked Exceptions ........................................ 398
Section 68.8: Creating and reading stacktraces .................................................................................................... 401
Section 68.9: Throwing an exception ...................................................................................................................... 404
Section 68.10: Advanced features of Exceptions ................................................................................................... 406
Section 68.11: The try-finally and try-catch-finally statements ............................................................................ 407
Section 68.12: The 'throws' clause in a method declaration ................................................................................. 409
Chapter 69: Calendar and its Subclasses ..................................................................................................... 411
Section 69.1: Creating Calendar objects ................................................................................................................. 411
Section 69.2: Increasing / Decreasing calendar fields .......................................................................................... 411
Section 69.3: Subtracting calendars ........................................................................................................................ 411
Section 69.4: Finding AM/PM ................................................................................................................................... 411
Chapter 70: Using the static keyword ........................................................................................................... 413
Section 70.1: Reference to non-static member from static context .................................................................... 413
Section 70.2: Using static to declare constants ..................................................................................................... 413
Chapter 71: Properties Class ............................................................................................................................... 415
Section 71.1: Loading properties ............................................................................................................................... 415
Section 71.2: Saving Properties as XML ................................................................................................................... 415
Section 71.3: Property files caveat: trailing whitespace ......................................................................................... 416
Chapter 72: Lambda Expressions ..................................................................................................................... 419
Section 72.1: Introduction to Java lambdas ........................................................................................................... 419
Section 72.2: Using Lambda Expressions to Sort a Collection ............................................................................. 422
Section 72.3: Method References ............................................................................................................................ 423
Section 72.4: Implementing multiple interfaces ..................................................................................................... 425
Section 72.5: Lambda - Listener Example .............................................................................................................. 425
Section 72.6: Java Closures with lambda expressions .......................................................................................... 426
Section 72.7: Lambdas and memory utilization ..................................................................................................... 427
Section 72.8: Using lambda expression with your own functional interface ...................................................... 427
Section 72.9: Traditional style to Lambda style ..................................................................................................... 428
Section 72.10: `return` only returns from the lambda, not the outer method ..................................................... 429
Section 72.11: Lambdas and Execute-around Pattern ........................................................................................... 431
Section 72.12: Using lambda expressions & predicates to get a certain value(s) from a list ........................... 431
Chapter 73: Basic Control Structures ............................................................................................................. 433
Section 73.1: Switch statement ................................................................................................................................. 433
Section 73.2: do...while Loop ..................................................................................................................................... 434
Section 73.3: For Each ............................................................................................................................................... 435
Section 73.4: Continue Statement in Java .............................................................................................................. 436
Section 73.5: If / Else If / Else Control ..................................................................................................................... 436
Section 73.6: For Loops ............................................................................................................................................. 436
Section 73.7: Ternary Operator ............................................................................................................................... 437
Section 73.8: Try ... Catch ... Finally ........................................................................................................................... 438
Section 73.9: Break .................................................................................................................................................... 438
Section 73.10: While Loops ....................................................................................................................................... 439
Section 73.11: If / Else ................................................................................................................................................ 439
Section 73.12: Nested break / continue .................................................................................................................. 439
Chapter 74: BueredWriter ............................................................................................................................... 441
Section 74.1: Write a line of text to File .................................................................................................................... 441
Chapter 75: New File I/O ...................................................................................................................................... 442
Section 75.1: Creating paths ..................................................................................................................................... 442
Section 75.2: Manipulating paths ............................................................................................................................. 442
Section 75.3: Retrieving information about a path ................................................................................................ 442
Section 75.4: Retrieving information using the filesystem .................................................................................... 443
Section 75.5: Reading files ........................................................................................................................................ 444
Section 75.6: Writing files .......................................................................................................................................... 444
Chapter 76: File I/O ................................................................................................................................................. 445
Section 76.1: Migrating from java.io.File to Java 7 NIO (java.nio.file.Path) .......................................................... 445
Section 76.2: Reading an image from a file ........................................................................................................... 447
Section 76.3: File Read/Write Using FileInputStream/FileOutputStream ........................................................... 447
Section 76.4: Reading all bytes to a byte[] ............................................................................................................ 448
Section 76.5: Copying a file using Channel ............................................................................................................. 449
Section 76.6: Writing a byte[] to a file .................................................................................................................... 449
Section 76.7: Stream vs Writer/Reader API ............................................................................................................ 450
Section 76.8: Reading a file with a Scanner ........................................................................................................... 451
Section 76.9: Copying a file using InputStream and OutputStream .................................................................... 452
Section 76.10: Reading from a binary file ............................................................................................................... 452
Section 76.11: Reading a file using Channel and Buer ......................................................................................... 452
Section 76.12: Adding Directories ............................................................................................................................. 453
Section 76.13: Blocking or redirecting standard output / error ............................................................................ 454
Section 76.14: Reading a whole file at once ............................................................................................................ 455
Section 76.15: Locking ............................................................................................................................................... 455
Section 76.16: Reading a file using BueredInputStream ..................................................................................... 455
Section 76.17: Iterate over a directory printing subdirectories in it ...................................................................... 456
Section 76.18: Writing a file using Channel and Buer .......................................................................................... 456
Section 76.19: Writing a file using PrintStream ....................................................................................................... 457
Section 76.20: Iterating over a directory and filter by file extension ................................................................... 457
Section 76.21: Accessing the contents of a ZIP file ................................................................................................ 458
Chapter 77: Scanner ............................................................................................................................................... 459
Section 77.1: General Pattern that does most commonly asked about tasks .................................................... 459
Section 77.2: Using custom delimiters .................................................................................................................... 461
Section 77.3: Reading system input using Scanner ............................................................................................... 461
Section 77.4: Reading file input using Scanner ...................................................................................................... 461
Section 77.5: Read the entire input as a String using Scanner ............................................................................. 462
Section 77.6: Carefully Closing a Scanner .............................................................................................................. 462
Section 77.7: Read an int from the command line ................................................................................................ 463
Chapter 78: Interfaces ........................................................................................................................................... 464
Section 78.1: Implementing multiple interfaces ...................................................................................................... 464
Section 78.2: Declaring and Implementing an Interface ...................................................................................... 465
Section 78.3: Extending an interface ....................................................................................................................... 465
Section 78.4: Usefulness of interfaces .................................................................................................................... 466
Section 78.5: Default methods ................................................................................................................................. 468
Section 78.6: Modifiers in Interfaces ........................................................................................................................ 470
Section 78.7: Using Interfaces with Generics .......................................................................................................... 470
Section 78.8: Strengthen bounded type parameters ............................................................................................ 473
Section 78.9: Implementing interfaces in an abstract class ................................................................................. 473
Chapter 79: Regular Expressions ..................................................................................................................... 475
Section 79.1: Using capture groups ......................................................................................................................... 475
Section 79.2: Using regex with custom behaviour by compiling the Pattern with flags .................................... 476
Section 79.3: Escape Characters ............................................................................................................................. 476
Section 79.4: Not matching a given string .............................................................................................................. 477
Section 79.5: Matching with a regex literal ............................................................................................................. 477
Section 79.6: Matching a backslash ........................................................................................................................ 477
Chapter 80: Comparable and Comparator ................................................................................................ 479
Section 80.1: Sorting a List using Comparable<T> or a Comparator<T> ............................................................ 479
Section 80.2: The compareTo and compare Methods ......................................................................................... 482
Section 80.3: Natural (comparable) vs explicit (comparator) sorting ................................................................ 483
Section 80.4: Creating a Comparator using comparing method ........................................................................ 484
Section 80.5: Sorting Map entries ............................................................................................................................ 484
Chapter 81: Java Floating Point Operations .............................................................................................. 486
Section 81.1: Comparing floating point values ........................................................................................................ 486
Section 81.2: OverFlow and UnderFlow .................................................................................................................. 488
Section 81.3: Formatting the floating point values ................................................................................................ 489
Section 81.4: Strict Adherence to the IEEE Specification ....................................................................................... 489
Chapter 82: Currency and Money .................................................................................................................... 491
Section 82.1: Add custom currency ......................................................................................................................... 491
Chapter 83: Object Cloning .................................................................................................................................. 492
Section 83.1: Cloning performing a deep copy ...................................................................................................... 492
Section 83.2: Cloning using a copy factory ............................................................................................................ 493
Section 83.3: Cloning using a copy constructor ..................................................................................................... 493
Section 83.4: Cloning by implementing Clonable interface .................................................................................. 493
Section 83.5: Cloning performing a shallow copy ................................................................................................. 494
Chapter 84: Recursion ........................................................................................................................................... 496
Section 84.1: The basic idea of recursion ................................................................................................................ 496
Section 84.2: Deep recursion is problematic in Java ............................................................................................ 496
Section 84.3: Types of Recursion ............................................................................................................................ 498
Section 84.4: Computing the Nth Fibonacci Number ............................................................................................ 498
Section 84.5: StackOverflowError & recursion to loop .......................................................................................... 499
Section 84.6: Computing the Nth power of a number ........................................................................................... 501
Section 84.7: Traversing a Tree data structure with recursion ............................................................................ 501
Section 84.8: Reverse a string using Recursion ..................................................................................................... 502
Section 84.9: Computing the sum of integers from 1 to N .................................................................................... 502
Chapter 85: Converting to and from Strings ............................................................................................. 503
Section 85.1: Converting String to other datatypes ............................................................................................... 503
Section 85.2: Conversion to / from bytes ............................................................................................................... 504
Section 85.3: Base64 Encoding / Decoding ........................................................................................................... 504
Section 85.4: Converting other datatypes to String .............................................................................................. 505
Section 85.5: Getting a `String` from an `InputStream` .......................................................................................... 506
Chapter 86: Random Number Generation ................................................................................................... 507
Section 86.1: Pseudo Random Numbers ................................................................................................................. 507
Section 86.2: Pseudo Random Numbers in Specific Range ................................................................................. 507
Section 86.3: Generating cryptographically secure pseudorandom numbers ................................................... 508
Section 86.4: Generating Random Numbers with a Specified Seed .................................................................... 508
Section 86.5: Select random numbers without duplicates .................................................................................... 509
Section 86.6: Generating Random number using apache-common lang3 ........................................................ 510
Chapter 87: Singletons .......................................................................................................................................... 511
Section 87.1: Enum Singleton .................................................................................................................................... 511
Section 87.2: Singleton without use of Enum (eager initialization) ...................................................................... 511
Section 87.3: Thread-safe lazy initialization using holder class | Bill Pugh Singleton implementation ............ 512
Section 87.4: Thread safe Singleton with double checked locking ...................................................................... 512
Section 87.5: Extending singleton (singleton inheritance) .................................................................................... 513
Chapter 88: Autoboxing ........................................................................................................................................ 516
Section 88.1: Using int and Integer interchangeably ............................................................................................. 516
Section 88.2: Auto-unboxing may lead to NullPointerException .......................................................................... 517
Section 88.3: Using Boolean in if statement ........................................................................................................... 517
Section 88.4: Dierent Cases When Integer and int can be used interchangeably .......................................... 518
Section 88.5: Memory and Computational Overhead of Autoboxing ................................................................. 519
Chapter 89: 2D Graphics in Java ...................................................................................................................... 521
Section 89.1: Example 1: Draw and Fill a Rectangle Using Java ........................................................................... 521
Section 89.2: Example 2: Drawing and Filling Oval ................................................................................................ 523
Chapter 90: JAXB ...................................................................................................................................................... 524
Section 90.1: Reading an XML file (unmarshalling) ............................................................................................... 524
Section 90.2: Writing an XML file (marshalling an object) .................................................................................... 524
Section 90.3: Manual field/property XML mapping configuration ...................................................................... 525
Section 90.4: Binding an XML namespace to a serializable Java class .............................................................. 526
Section 90.5: Using XmlAdapter to generate desired xml format ....................................................................... 526
Section 90.6: Using XmlAdapter to trim string ....................................................................................................... 528
Section 90.7: Automatic field/property XML mapping configuration (@XmlAccessorType) ........................... 528
Section 90.8: Specifying a XmlAdapter instance to (re)use existing data .......................................................... 530
Chapter 91: Class - Java Reflection ................................................................................................................. 533
Section 91.1: getClass() method of Object class ..................................................................................................... 533
Chapter 92: Networking ........................................................................................................................................ 534
Section 92.1: Basic Client and Server Communication using a Socket ................................................................ 534
Section 92.2: Basic Client/Server Communication using UDP (Datagram) ....................................................... 536
Section 92.3: Loading TrustStore and KeyStore from InputStream .................................................................... 537
Section 92.4: Socket example - reading a web page using a simple socket ...................................................... 538
Section 92.5: Temporarily disable SSL verification (for testing purposes) ......................................................... 539
Section 92.6: Downloading a file using Channel .................................................................................................... 539
Section 92.7: Multicasting ......................................................................................................................................... 540
Chapter 93: NIO - Networking ............................................................................................................................ 543
Section 93.1: Using Selector to wait for events (example with OP_CONNECT) .................................................. 543
Chapter 94: HttpURLConnection ...................................................................................................................... 545
Section 94.1: Get response body from a URL as a String ..................................................................................... 545
Section 94.2: POST data ........................................................................................................................................... 546
Section 94.3: Delete resource .................................................................................................................................. 546
Section 94.4: Check if resource exists ..................................................................................................................... 547
Chapter 95: JAX-WS ................................................................................................................................................ 549
Section 95.1: Basic Authentication ........................................................................................................................... 549
Chapter 96: Nashorn JavaScript engine ....................................................................................................... 550
Section 96.1: Execute JavaScript file ....................................................................................................................... 550
Section 96.2: Intercept script output ....................................................................................................................... 550
Section 96.3: Hello Nashorn ..................................................................................................................................... 551
Section 96.4: Evaluate Arithmetic Strings ............................................................................................................... 551
Section 96.5: Set global variables ............................................................................................................................ 551
Section 96.6: Set and get global variables ............................................................................................................. 552
Section 96.7: Usage of Java objects in JavaScript in Nashorn ............................................................................ 552
Section 96.8: Implementing an interface from script ............................................................................................ 553
Chapter 97: Java Native Interface .................................................................................................................. 554
Section 97.1: Calling C++ methods from Java ........................................................................................................ 554
Section 97.2: Calling Java methods from C++ (callback) ..................................................................................... 555
Section 97.3: Loading native libraries ..................................................................................................................... 557
Chapter 98: Functional Interfaces ................................................................................................................... 559
Section 98.1: List of standard Java Runtime Library functional interfaces by signature .................................. 559
Chapter 99: Fluent Interface .............................................................................................................................. 560
Section 99.1: Fluent programming style ................................................................................................................. 560
Section 99.2: Truth - Fluent Testing Framework .................................................................................................... 561
Chapter 100: Dequeue Interface ....................................................................................................................... 562
Section 100.1: Adding Elements to Deque ............................................................................................................... 562
Section 100.2: Removing Elements from Deque .................................................................................................... 562
Section 100.3: Retrieving Element without Removing ........................................................................................... 562
Section 100.4: Iterating through Deque .................................................................................................................. 562
Chapter 101: Remote Method Invocation (RMI) ......................................................................................... 564
Section 101.1: Callback: invoking methods on a "client" ......................................................................................... 564
Section 101.2: Simple RMI example with Client and Server implementation ....................................................... 568
Section 101.3: Client-Server: invoking methods in one JVM from another .......................................................... 570
Chapter 102: Iterator and Iterable .................................................................................................................. 573
Section 102.1: Removing elements using an iterator ............................................................................................. 573
Section 102.2: Creating your own Iterable .............................................................................................................. 573
Section 102.3: Using Iterable in for loop .................................................................................................................. 574
Section 102.4: Using the raw iterator ...................................................................................................................... 575
Chapter 103: Reflection API ................................................................................................................................. 576
Section 103.1: Dynamic Proxies ................................................................................................................................ 576
Section 103.2: Introduction ....................................................................................................................................... 577
Section 103.3: Evil Java hacks with Reflection ....................................................................................................... 578
Section 103.4: Misuse of Reflection API to change private and final variables ................................................... 580
Section 103.5: Getting and Setting fields ................................................................................................................. 581
Section 103.6: Call constructor ................................................................................................................................. 582
Section 103.7: Call constructor of nested class ...................................................................................................... 583
Section 103.8: Invoking a method ............................................................................................................................ 583
Section 103.9: Get Class given its (fully qualified) name ....................................................................................... 584
Section 103.10: Getting the Constants of an Enumeration .................................................................................... 584
Section 103.11: Call overloaded constructors using reflection ............................................................................... 585
Chapter 104: ByteBuer ....................................................................................................................................... 587
Section 104.1: Basic Usage - Using DirectByteBuer ............................................................................................ 587
Section 104.2: Basic Usage - Creating a ByteBuer ............................................................................................. 587
Section 104.3: Basic Usage - Write Data to the Buer .......................................................................................... 588
Chapter 105: Applets ............................................................................................................................................... 589
Section 105.1: Minimal Applet ................................................................................................................................... 589
Section 105.2: Creating a GUI ................................................................................................................................... 590
Section 105.3: Open links from within the applet ................................................................................................... 590
Section 105.4: Loading images, audio and other resources ................................................................................. 591
Chapter 106: Expressions ...................................................................................................................................... 593
Section 106.1: Operator Precedence ........................................................................................................................ 593
Section 106.2: Expression Basics .............................................................................................................................. 594
Section 106.3: Expression evaluation order ............................................................................................................ 595
Section 106.4: Constant Expressions ....................................................................................................................... 596
Chapter 107: JSON in Java .................................................................................................................................. 599
Section 107.1: Using Jackson Object Mapper ......................................................................................................... 599
Section 107.2: JSON To Object (Gson Library) ....................................................................................................... 600
Section 107.3: JSONObject.NULL ............................................................................................................................. 600
Section 107.4: JSON Builder - chaining methods ................................................................................................... 601
Section 107.5: Object To JSON (Gson Library) ....................................................................................................... 601
Section 107.6: JSON Iteration ................................................................................................................................... 601
Section 107.7: optXXX vs getXXX methods ............................................................................................................. 602
Section 107.8: Extract single element from JSON .................................................................................................. 602
Section 107.9: JsonArray to Java List (Gson Library) ........................................................................................... 602
Section 107.10: Encoding data as JSON .................................................................................................................. 603
Section 107.11: Decoding JSON data ....................................................................................................................... 603
Chapter 108: XML Parsing using the JAXP APIs ......................................................................................... 605
Section 108.1: Parsing a document using the StAX API .......................................................................................... 605
Section 108.2: Parsing and navigating a document using the DOM API ............................................................. 606
Chapter 109: XML XPath Evaluation ................................................................................................................ 608
Section 109.1: Parsing multiple XPath Expressions in a single XML ...................................................................... 608
Section 109.2: Parsing single XPath Expression multiple times in an XML .......................................................... 608
Section 109.3: Evaluating a NodeList in an XML document .................................................................................. 609
Chapter 110: XOM - XML Object Model ........................................................................................................... 610
Section 110.1: Reading a XML file .............................................................................................................................. 610
Section 110.2: Writing to a XML File ......................................................................................................................... 612
Chapter 111: Polymorphism .................................................................................................................................. 615
Section 111.1: Method Overriding ............................................................................................................................... 615
Section 111.2: Method Overloading ........................................................................................................................... 616
Section 111.3: Polymorphism and dierent types of overriding ............................................................................ 617
Section 111.4: Virtual functions .................................................................................................................................. 620
Section 111.5: Adding behaviour by adding classes without touching existing code .......................................... 621
Chapter 112: Encapsulation .................................................................................................................................. 623
Section 112.1: Encapsulation to maintain invariants ............................................................................................... 623
Section 112.2: Encapsulation to reduce coupling .................................................................................................... 624
Chapter 113: Java Agents ...................................................................................................................................... 625
Section 113.1: Modifying classes with agents ........................................................................................................... 625
Section 113.2: Adding an agent at runtime ............................................................................................................. 625
Section 113.3: Setting up a basic agent .................................................................................................................... 626
Chapter 114: Varargs (Variable Argument) ................................................................................................ 627
Section 114.1: Working with Varargs parameters ................................................................................................... 627
Section 114.2: Specifying a varargs parameter ...................................................................................................... 627
Chapter 115: Logging (java.util.logging) ....................................................................................................... 628
Section 115.1: Logging complex messages (eciently) ......................................................................................... 628
Section 115.2: Using the default logger ................................................................................................................... 629
Section 115.3: Logging levels .................................................................................................................................... 630
Chapter 116: log4j / log4j2 .................................................................................................................................. 632
Section 116.1: Properties-File to log to DB ............................................................................................................... 632
Section 116.2: How to get Log4j ................................................................................................................................ 632
Section 116.3: Setting up property file ...................................................................................................................... 633
Section 116.4: Basic log4j2.xml configuration file ................................................................................................... 634
Section 116.5: How to use Log4j in Java code ........................................................................................................ 634
Section 116.6: Migrating from log4j 1.x to 2.x ........................................................................................................... 635
Section 116.7: Filter Logoutput by level (log4j 1.x) ................................................................................................... 636
Chapter 117: Oracle Ocial Code Standard ............................................................................................... 637
Section 117.1: Naming Conventions .......................................................................................................................... 637
Section 117.2: Class Structure ................................................................................................................................... 638
Section 117.3: Annotations ......................................................................................................................................... 639
Section 117.4: Import statements ............................................................................................................................. 639
Section 117.5: Braces ................................................................................................................................................. 640
Section 117.6: Redundant Parentheses .................................................................................................................... 641
Section 117.7: Modifiers .............................................................................................................................................. 641
Section 117.8: Indentation .......................................................................................................................................... 642
Section 117.9: Literals ................................................................................................................................................. 642
Section 117.10: Package declaration ........................................................................................................................ 642
Section 117.11: Lambda Expressions ......................................................................................................................... 642
Section 117.12: Java Source Files .............................................................................................................................. 643
Section 117.13: Wrapping statements ....................................................................................................................... 643
Section 117.14: Wrapping Method Declarations ...................................................................................................... 644
Section 117.15: Wrapping Expressions ...................................................................................................................... 644
Section 117.16: Whitespace ........................................................................................................................................ 645
Section 117.17: Special Characters ............................................................................................................................ 645
Section 117.18: Variable Declarations ....................................................................................................................... 646
Chapter 118: Character encoding ..................................................................................................................... 647
Section 118.1: Reading text from a file encoded in UTF-8 ..................................................................................... 647
Section 118.2: Writing text to a file in UTF-8 ............................................................................................................ 647
Section 118.3: Getting byte representation of a string in UTF-8 ........................................................................... 648
Chapter 119: Apache Commons Lang ............................................................................................................. 649
Section 119.1: Implement equals() method .............................................................................................................. 649
Section 119.2: Implement hashCode() method ....................................................................................................... 649
Section 119.3: Implement toString() method ........................................................................................................... 650
Chapter 120: Localization and Internationalization ................................................................................ 652
Section 120.1: Locale .................................................................................................................................................. 652
Section 120.2: Automatically formatted Dates using "locale" .............................................................................. 653
Section 120.3: String Comparison ............................................................................................................................ 653
Chapter 121: Parallel programming with Fork/Join framework ...................................................... 654
Section 121.1: Fork/Join Tasks in Java .................................................................................................................... 654
Chapter 122: Non-Access Modifiers ................................................................................................................. 656
Section 122.1: final ...................................................................................................................................................... 656
Section 122.2: static ................................................................................................................................................... 657
Section 122.3: abstract .............................................................................................................................................. 658
Section 122.4: strictfp ................................................................................................................................................ 659
Section 122.5: volatile ................................................................................................................................................ 659
Section 122.6: synchronized ..................................................................................................................................... 660
Section 122.7: transient ............................................................................................................................................. 661
Chapter 123: Process ............................................................................................................................................... 662
Section 123.1: Pitfall: Runtime.exec, Process and ProcessBuilder don't understand shell syntax ...................... 662
Section 123.2: Simple example (Java version < 1.5) ............................................................................................... 664
Chapter 124: Java Native Access ..................................................................................................................... 665
Section 124.1: Introduction to JNA ........................................................................................................................... 665
Chapter 125: Modules .............................................................................................................................................. 666
Section 125.1: Defining a basic module ................................................................................................................... 666
Chapter 126: Concurrent Programming (Threads) .................................................................................. 667
Section 126.1: Callable and Future ........................................................................................................................... 667
Section 126.2: CountDownLatch ............................................................................................................................... 668
Section 126.3: Basic Multithreading ......................................................................................................................... 670
Section 126.4: Locks as Synchronisation aids ......................................................................................................... 671
Section 126.5: Semaphore ........................................................................................................................................ 672
Section 126.6: Synchronization ................................................................................................................................. 673
Section 126.7: Runnable Object ................................................................................................................................ 674
Section 126.8: Creating basic deadlocked system ................................................................................................. 675
Section 126.9: Creating a java.lang.Thread instance ............................................................................................. 677
Section 126.10: Atomic operations ........................................................................................................................... 678
Section 126.11: Exclusive write / Concurrent read access ...................................................................................... 679
Section 126.12: Producer-Consumer ........................................................................................................................ 680
Section 126.13: Visualizing read/write barriers while using synchronized / volatile ........................................... 682
Section 126.14: Get status of all threads started by your program excluding system threads ........................ 683
Section 126.15: Using ThreadLocal ........................................................................................................................... 684
Section 126.16: Multiple producer/consumer example with shared global queue ............................................. 685
Section 126.17: Add two `int` arrays using a Threadpool ....................................................................................... 686
Section 126.18: Pausing Execution ............................................................................................................................ 687
Section 126.19: Thread Interruption / Stopping Threads ....................................................................................... 688
Chapter 127: Executor, ExecutorService and Thread pools ................................................................ 691
Section 127.1: ThreadPoolExecutor .......................................................................................................................... 691
Section 127.2: Retrieving value from computation - Callable ............................................................................... 692
Section 127.3: submit() vs execute() exception handling dierences .................................................................. 693
Section 127.4: Handle Rejected Execution .............................................................................................................. 695
Section 127.5: Fire and Forget - Runnable Tasks ................................................................................................... 695
Section 127.6: Use cases for dierent types of concurrency constructs ............................................................. 696
Section 127.7: Wait for completion of all tasks in ExecutorService ...................................................................... 697
Section 127.8: Use cases for dierent types of ExecutorService .......................................................................... 699
Section 127.9: Scheduling tasks to run at a fixed time, after a delay or repeatedly .......................................... 701
Section 127.10: Using Thread Pools ......................................................................................................................... 702
Chapter 128: ThreadLocal .................................................................................................................................... 703
Section 128.1: Basic ThreadLocal usage .................................................................................................................. 703
Section 128.2: ThreadLocal Java 8 functional initialization .................................................................................. 704
Section 128.3: Multiple threads with one shared object ........................................................................................ 705
Chapter 129: Using ThreadPoolExecutor in MultiThreaded applications. .................................... 707
Section 129.1: Performing Asynchronous Tasks Where No Return Value Is Needed Using a Runnable Class
Instance .............................................................................................................................................................. 707
Section 129.2: Performing Asynchronous Tasks Where a Return Value Is Needed Using a Callable Class
Instance .............................................................................................................................................................. 708
Section 129.3: Defining Asynchronous Tasks Inline using Lambdas .................................................................... 711
Chapter 130: Common Java Pitfalls ................................................................................................................ 713
Section 130.1: Pitfall: using == to compare primitive wrappers objects such as Integer ..................................... 713
Section 130.2: Pitfall: using == to compare strings ................................................................................................. 714
Section 130.3: Pitfall: forgetting to free resources ................................................................................................. 715
Section 130.4: Pitfall: testing a file before attempting to open it .......................................................................... 716
Section 130.5: Pitfall: thinking of variables as objects ........................................................................................... 718
Section 130.6: Pitfall: memory leaks ........................................................................................................................ 721
Section 130.7: Pitfall: Not understanding that String is an immutable class ....................................................... 722
Section 130.8: Pitfall: combining assignment and side-eects ............................................................................. 722
Chapter 131: Java Pitfalls - Exception usage .............................................................................................. 724
Section 131.1: Pitfall - Catching Throwable, Exception, Error or RuntimeException ............................................ 724
Section 131.2: Pitfall - Ignoring or squashing exceptions ....................................................................................... 725
Section 131.3: Pitfall - Throwing Throwable, Exception, Error or RuntimeException ........................................... 726
Section 131.4: Pitfall - Using exceptions for normal flowcontrol ........................................................................... 727
Section 131.5: Pitfall - Directly subclassing `Throwable` ......................................................................................... 728
Section 131.6: Pitfall - Catching InterruptedException ............................................................................................ 728
Section 131.7: Pitfall - Excessive or inappropriate stacktraces .............................................................................. 730
Chapter 132: Java Pitfalls - Language syntax ........................................................................................... 731
Section 132.1: Pitfall - Missing a ‘break’ in a 'switch' case ...................................................................................... 731
Section 132.2: Pitfall - Declaring classes with the same names as standard classes ........................................ 731
Section 132.3: Pitfall - Leaving out braces: the "dangling if" and "dangling else" problems ............................. 732
Section 132.4: Pitfall - Octal literals .......................................................................................................................... 734
Section 132.5: Pitfall - Using '==' to test a boolean ................................................................................................. 734
Section 132.6: Pitfall - Ignoring method visibility .................................................................................................... 735
Section 132.7: Pitfall: Using 'assert' for argument or user input validation ......................................................... 735
Section 132.8: Pitfall - Wildcard imports can make your code fragile ................................................................. 736
Section 132.9: Pitfall - Misplaced semicolons and missing braces ....................................................................... 737
Section 132.10: Pitfall - Overloading instead of overriding .................................................................................... 738
Section 132.11: Pitfall of Auto-Unboxing Null Objects into Primitives .................................................................... 739
Chapter 133: Java Pitfalls - Threads and Concurrency ......................................................................... 740
Section 133.1: Pitfall - Extending 'java.lang.Thread' ................................................................................................ 740
Section 133.2: Pitfall - Too many threads makes an application slower ............................................................. 741
Section 133.3: Pitfall: incorrect use of wait() / notify() ........................................................................................... 742
Section 133.4: Pitfall: Shared variables require proper synchronization .............................................................. 742
Section 133.5: Pitfall - Thread creation is relatively expensive ............................................................................. 745
Chapter 134: Java Pitfalls - Nulls and NullPointerException ............................................................. 748
Section 134.1: Pitfall - "Making good" unexpected nulls ......................................................................................... 748
Section 134.2: Pitfall - Using null to represent an empty array or collection ...................................................... 749
Section 134.3: Pitfall - Not checking if an I/O stream isn't even initialized when closing it ............................... 750
Section 134.4: Pitfall - Returning null instead of throwing an exception .............................................................. 750
Section 134.5: Pitfall - Unnecessary use of Primitive Wrappers can lead to NullPointerExceptions ................ 751
Section 134.6: Pitfall - Using "Yoda notation" to avoid NullPointerException ...................................................... 752
Chapter 135: Java Pitfalls - Performance Issues ...................................................................................... 753
Section 135.1: Pitfall - String concatenation in a loop does not scale .................................................................. 753
Section 135.2: Pitfall - Using size() to test if a collection is empty is inecient .................................................. 754
Section 135.3: Pitfall - Interning strings so that you can use == is a bad idea ..................................................... 754
Section 135.4: Pitfall - Using 'new' to create primitive wrapper instances is inecient ..................................... 756
Section 135.5: Pitfall - Eciency concerns with regular expressions ................................................................... 756
Section 135.6: Pitfall - Small reads / writes on unbuered streams are inecient ........................................... 759
Section 135.7: Pitfall - Over-use of primitive wrapper types is inecient ............................................................ 761
Section 135.8: Pitfall - The overheads of creating log messages ......................................................................... 762
Section 135.9: Pitfall - Iterating a Map's keys can be inecient ........................................................................... 763
Section 135.10: Pitfall - Calling System.gc() is inecient ....................................................................................... 763
Section 135.11: Pitfall - Calling 'new String(String)' is inecient ............................................................................ 764
Chapter 136: ServiceLoader ................................................................................................................................ 765
Section 136.1: Simple ServiceLoader Example ........................................................................................................ 765
Section 136.2: Logger Service ................................................................................................................................... 766
Chapter 137: Classloaders .................................................................................................................................... 768
Section 137.1: Implementing a custom classLoader ............................................................................................... 768
Section 137.2: Loading an external .class file .......................................................................................................... 768
Section 137.3: Instantiating and using a classloader ............................................................................................. 769
Chapter 138: Creating Images Programmatically ................................................................................... 771
Section 138.1: Creating a simple image programmatically and displaying it ..................................................... 771
Section 138.2: Save an Image to disk ...................................................................................................................... 772
Section 138.3: Setting individual pixel's color in BueredImage ........................................................................... 772
Section 138.4: Specifying image rendering quality ................................................................................................ 773
Section 138.5: Creating an image with BueredImage class ............................................................................... 775
Section 138.6: Editing and re-using image with BueredImage ........................................................................... 776
Section 138.7: How to scale a BueredImage ........................................................................................................ 777
Chapter 139: Atomic Types .................................................................................................................................. 778
Section 139.1: Creating Atomic Types ...................................................................................................................... 778
Section 139.2: Motivation for Atomic Types ............................................................................................................ 778
Chapter 140: RSA Encryption ............................................................................................................................. 782
Section 140.1: An example using a hybrid cryptosystem consisting of OAEP and GCM .................................... 782
Chapter 141: Secure objects ................................................................................................................................ 787
Section 141.1: SealedObject (javax.crypto.SealedObject) ...................................................................................... 787
Section 141.2: SignedObject (java.security.SignedObject) ..................................................................................... 787
Chapter 142: Security & Cryptography ......................................................................................................... 789
Section 142.1: Compute Cryptographic Hashes ...................................................................................................... 789
Section 142.2: Encrypt and Decrypt Data with Public / Private Keys .................................................................. 789
Section 142.3: Generate Cryptographically Random Data ................................................................................... 790
Section 142.4: Generate Public / Private Key Pairs ................................................................................................ 790
Section 142.5: Compute and Verify Digital Signatures .......................................................................................... 791
Chapter 143: Security & Cryptography ......................................................................................................... 792
Section 143.1: The JCE ............................................................................................................................................... 792
Section 143.2: Keys and Key Management ............................................................................................................ 792
Section 143.3: Common Java vulnerabilities .......................................................................................................... 792
Section 143.4: Networking Concerns ....................................................................................................................... 792
Section 143.5: Randomness and You ....................................................................................................................... 792
Section 143.6: Hashing and Validation .................................................................................................................... 792
Chapter 144: SecurityManager ......................................................................................................................... 794
Section 144.1: Sandboxing classes loaded by a ClassLoader ............................................................................... 794
Section 144.2: Enabling the SecurityManager ........................................................................................................ 795
Section 144.3: Implementing policy deny rules ...................................................................................................... 795
Chapter 145: JNDI .................................................................................................................................................... 803
Section 145.1: RMI through JNDI .............................................................................................................................. 803
Chapter 146: sun.misc.Unsafe ............................................................................................................................ 807
Section 146.1: Instantiating sun.misc.Unsafe via reflection .................................................................................... 807
Section 146.2: Instantiating sun.misc.Unsafe via bootclasspath ........................................................................... 807
Section 146.3: Getting Instance of Unsafe .............................................................................................................. 807
Section 146.4: Uses of Unsafe .................................................................................................................................. 808
Chapter 147: Java Memory Model ................................................................................................................... 809
Section 147.1: Motivation for the Memory Model .................................................................................................... 809
Section 147.2: Happens-before relationships ......................................................................................................... 811
Section 147.3: How to avoid needing to understand the Memory Model ............................................................ 812
Section 147.4: Happens-before reasoning applied to some examples ............................................................... 813
Chapter 148: Java deployment ......................................................................................................................... 816
Section 148.1: Making an executable JAR from the command line ..................................................................... 816
Section 148.2: Creating an UberJAR for an application and its dependencies .................................................. 817
Section 148.3: Creating JAR, WAR and EAR files ................................................................................................... 818
Section 148.4: Introduction to Java Web Start ....................................................................................................... 819
Chapter 149: Java plugin system implementations ............................................................................... 822
Section 149.1: Using URLClassLoader ...................................................................................................................... 822
Chapter 150: JavaBean ......................................................................................................................................... 826
Section 150.1: Basic Java Bean ................................................................................................................................ 826
Chapter 151: Java SE 7 Features ....................................................................................................................... 827
Section 151.1: New Java SE 7 programming language features .......................................................................... 827
Section 151.2: Binary Literals .................................................................................................................................... 827
Section 151.3: The try-with-resources statement ................................................................................................... 827
Section 151.4: Underscores in Numeric Literals ...................................................................................................... 828
Section 151.5: Type Inference for Generic Instance Creation ................................................................................ 828
Section 151.6: Strings in switch Statements ............................................................................................................. 828
Chapter 152: Java SE 8 Features ...................................................................................................................... 830
Section 152.1: New Java SE 8 programming language features ......................................................................... 830
Chapter 153: Dynamic Method Dispatch ....................................................................................................... 831
Section 153.1: Dynamic Method Dispatch - Example Code ................................................................................... 831
Chapter 154: Generating Java Code .............................................................................................................. 834
Section 154.1: Generate POJO From JSON ............................................................................................................. 834
Chapter 155: JShell .................................................................................................................................................. 835
Section 155.1: Editting Snippets ................................................................................................................................ 835
Section 155.2: Entering and Exiting JShell ............................................................................................................... 836
Section 155.3: Expressions ........................................................................................................................................ 836
Section 155.4: Methods and Classes ........................................................................................................................ 837
Section 155.5: Variables ............................................................................................................................................ 837
Chapter 156: Stack-Walking API ........................................................................................................................ 838
Section 156.1: Print all stack frames of the current thread .................................................................................... 838
Section 156.2: Print current caller class ................................................................................................................... 839
Section 156.3: Showing reflection and other hidden frames ................................................................................. 839
Chapter 157: Sockets .............................................................................................................................................. 841
Section 157.1: Read from socket .............................................................................................................................. 841
Chapter 158: Java Sockets .................................................................................................................................. 842
Section 158.1: A simple TCP echo back server ........................................................................................................ 842
Chapter 159: FTP (File Transfer Protocol) .................................................................................................... 845
Section 159.1: Connecting and Logging Into a FTP Server .................................................................................... 845
Chapter 160: Using Other Scripting Languages in Java ....................................................................... 850
Section 160.1: Evaluating A JavaScript file in -scripting mode of nashorn .......................................................... 850
Chapter 161: C++ Comparison ............................................................................................................................. 853
Section 161.1: Static Class Members ......................................................................................................................... 853
Section 161.2: Classes Defined within Other Constructs ........................................................................................ 853
Section 161.3: Pass-by-value & Pass-by-reference ................................................................................................ 854
Section 161.4: Inheritance vs Composition .............................................................................................................. 855
Section 161.5: Outcast Downcasting ........................................................................................................................ 856
Section 161.6: Abstract Methods & Classes ............................................................................................................. 856
Chapter 162: Audio .................................................................................................................................................... 858
Section 162.1: Play a MIDI file .................................................................................................................................... 858
Section 162.2: Play an Audio file Looped ................................................................................................................ 859
Section 162.3: Basic audio output ............................................................................................................................ 859
Section 162.4: Bare metal sound .............................................................................................................................. 860
Chapter 163: Java Print Service ........................................................................................................................ 862
Section 163.1: Building the Doc that will be printed ................................................................................................ 862
Section 163.2: Discovering the available print services ......................................................................................... 862
Section 163.3: Defining print request attributes ...................................................................................................... 863
Section 163.4: Listening print job request status change ...................................................................................... 863
Section 163.5: Discovering the default print service .............................................................................................. 865
Section 163.6: Creating a print job from a print service ........................................................................................ 865
Chapter 164: CompletableFuture ..................................................................................................................... 867
Section 164.1: Simple Example of CompletableFuture ........................................................................................... 867
Chapter 165: Runtime Commands .................................................................................................................... 868
Section 165.1: Adding shutdown hooks .................................................................................................................... 868
Chapter 166: Unit Testing ...................................................................................................................................... 869
Section 166.1: What is Unit Testing? ......................................................................................................................... 869
Chapter 167: Asserting ........................................................................................................................................... 872
Section 167.1: Checking arithmetic with assert ....................................................................................................... 872
Chapter 168: Multi-Release JAR Files ............................................................................................................. 873
Section 168.1: Example of a multi-release Jar file's contents ............................................................................... 873
Section 168.2: Creating a multi-release Jar using the jar tool .............................................................................. 873
Section 168.3: URL of a loaded class inside a multi-release Jar .......................................................................... 874
Chapter 169: Just in Time (JIT) compiler ...................................................................................................... 876
Section 169.1: Overview ............................................................................................................................................. 876
Chapter 170: Bytecode Modification ............................................................................................................... 878
Section 170.1: What is Bytecode? ............................................................................................................................. 878
Section 170.2: How to edit jar files with ASM .......................................................................................................... 879
Section 170.3: How to load a ClassNode as a Class .............................................................................................. 881
Section 170.4: How to rename classes in a jar file ................................................................................................. 882
Section 170.5: Javassist Basic .................................................................................................................................. 882
Chapter 171: Disassembling and Decompiling ............................................................................................ 884
Section 171.1: Viewing bytecode with javap ............................................................................................................. 884
Chapter 172: JMX ...................................................................................................................................................... 891
Section 172.1: Simple example with Platform MBean Server ................................................................................ 891
Chapter 173: Java Virtual Machine (JVM) .................................................................................................... 895
Section 173.1: These are the basics .......................................................................................................................... 895
Chapter 174: XJC ....................................................................................................................................................... 896
Section 174.1: Generating Java code from simple XSD file ................................................................................... 896
Chapter 175: JVM Flags ......................................................................................................................................... 899
Section 175.1: -XXaggressive .................................................................................................................................... 899
Section 175.2: -XXallocClearChunks ......................................................................................................................... 899
Section 175.3: -XXallocClearChunkSize .................................................................................................................... 899
Section 175.4: -XXcallProfiling .................................................................................................................................. 899
Section 175.5: -XXdisableFatSpin ............................................................................................................................. 900
Section 175.6: -XXdisableGCHeuristics .................................................................................................................... 900
Section 175.7: -XXdumpSize ...................................................................................................................................... 900
Section 175.8: -XXexitOnOutOfMemory ................................................................................................................... 901
Chapter 176: JVM Tool Interface ...................................................................................................................... 902
Section 176.1: Iterate over objects reachable from object (Heap 1.0) .................................................................. 902
Section 176.2: Get JVMTI environment .................................................................................................................... 904
Section 176.3: Example of initialization inside of Agent_OnLoad method .......................................................... 904
Chapter 177: Java Memory Management .................................................................................................... 906
Section 177.1: Setting the Heap, PermGen and Stack sizes ................................................................................... 906
Section 177.2: Garbage collection ............................................................................................................................ 907
Section 177.3: Memory leaks in Java ....................................................................................................................... 909
Section 177.4: Finalization ......................................................................................................................................... 910
Section 177.5: Manually triggering GC ..................................................................................................................... 911
Chapter 178: Java Performance Tuning ....................................................................................................... 912
Section 178.1: An evidence-based approach to Java performance tuning ........................................................ 912
Section 178.2: Reducing amount of Strings ............................................................................................................ 913
Section 178.3: General approach ............................................................................................................................. 913
Chapter 179: Benchmarks ..................................................................................................................................... 915
Section 179.1: Simple JMH example ......................................................................................................................... 915
Chapter 180: FileUpload to AWS ....................................................................................................................... 918
Section 180.1: Upload file to s3 bucket .................................................................................................................... 918
Chapter 181: AppDynamics and TIBCO BusinessWorks Instrumentation for Easy
Integration ................................................................................................................................................................... 920
Section 181.1: Example of Instrumentation of all BW Applications in a Single Step for Appdynamics ............. 920
Appendix A: Installing Java (Standard Edition) ........................................................................................ 921
Section A.1: Setting %PATH% and %JAVA_HOME% after installing on Windows .............................................. 921
Section A.2: Installing a Java JDK on Linux ........................................................................................................... 922
Section A.3: Installing a Java JDK on macOS ........................................................................................................ 924
Section A.4: Installing a Java JDK or JRE on Windows ........................................................................................ 925
Section A.5: Configuring and switching Java versions on Linux using alternatives .......................................... 926
Section A.6: What do I need for Java Development ............................................................................................. 927
Section A.7: Selecting an appropriate Java SE release ........................................................................................ 927
Section A.8: Java release and version naming ...................................................................................................... 928
Section A.9: Installing Oracle Java on Linux with latest tar file ............................................................................ 928
Section A.10: Post-installation checking and configuration on Linux ................................................................... 929
Appendix B: Java Editions, Versions, Releases and Distributions ................................................... 931
Section B.1: Dierences between Java SE JRE or Java SE JDK distributions .................................................... 931
Section B.2: Java SE Versions .................................................................................................................................. 932
Section B.3: Dierences between Java EE, Java SE, Java ME and JavaFX ....................................................... 933
Appendix C: The Classpath .................................................................................................................................. 935
Section C.1: Dierent ways to specify the classpath ............................................................................................. 935
Section C.2: Adding all JARs in a directory to the classpath ................................................................................ 935
Section C.3: Load a resource from the classpath .................................................................................................. 936
Section C.4: Classpath path syntax ......................................................................................................................... 936
Section C.5: Dynamic Classpath .............................................................................................................................. 937
Section C.6: Mapping classnames to pathnames .................................................................................................. 937
Section C.7: The bootstrap classpath ..................................................................................................................... 937
Section C.8: What the classpath means: how searches work .............................................................................. 938
Appendix D: Resources (on classpath) .......................................................................................................... 939
Section D.1: Loading default configuration ............................................................................................................ 939
Section D.2: Loading an image from a resource ................................................................................................... 939
Section D.3: Finding and reading resources using a classloader ........................................................................ 939
Section D.4: Loading same-name resource from multiple JARs ......................................................................... 941
Credits ............................................................................................................................................................................ 942
You may also like ...................................................................................................................................................... 956
About
Please feel free to share this PDF with anyone for free,
latest version of this book can be downloaded from:
http://GoalKicker.com/JavaBook
This Java® Notes for Professionals book is compiled from Stack Overflow
Documentation, the content is written by the beautiful people at Stack Overflow.
Text content is released under Creative Commons BY-SA, see credits at the end
of this book whom contributed to the various chapters. Images may be copyright
of their respective owners unless otherwise specified
This is an unofficial free book created for educational purposes and is not
affiliated with official Java® group(s) or company(s) nor Stack Overflow. All
trademarks and registered trademarks are the property of their respective
company owners
Note: For Java to recognize this as a public class (and not throw a compile time error), the filename must be the
same as the class name (HelloWorld in this example) with a .java extension. There should also be a public access
modifier before it.
Naming conventions recommend that Java classes begin with an uppercase character, and be in camel case format
(in which the first letter of each word is capitalized). The conventions recommend against underscores (_) and dollar
signs ($).
cd /path/to/containing/folder/
$ javac HelloWorld.java
It's fairly common to get the error 'javac' is not recognized as an internal or external command, operable
program or batch file. even when you have installed the JDK and are able to run the program from IDE ex.
eclipse etc. Since the path is not added to the environment by default.
In case you get this on windows, to resolve, first try browsing to your javac.exe path, it's most probably in your
C:\Program Files\Java\jdk(version number)\bin. Then try running it with below.
Previously when we were calling javac it was same as above command. Only in that case your OS knew where
javac resided. So let's tell it now, this way you don't have to type the whole path every-time. We would need to add
this to our PATH
You cannot undo this so be careful. First copy your existing path to notepad. Then to get the exact PATH to your
javac browse manually to the folder where javac resides and click on the address bar and then copy it. It should
look something like c:\Program Files\Java\jdk1.8.0_xx\bin
In "Variable value" field, paste this IN FRONT of all the existing directories, followed by a semi-colon (;). DO NOT
DELETE any existing entries.
The compiler will then generate a bytecode file called HelloWorld.class which can be executed in the Java Virtual
Machine (JVM). The Java programming language compiler, javac, reads source files written in the Java programming
language and compiles them into bytecode class files. Optionally, the compiler can also process annotations found
in source and class files using the Pluggable Annotation Processing API. The compiler is a command line tool but
can also be invoked using the Java Compiler API.
To run your program, enter java followed by the name of the class which contains the main method (HelloWorld in
our example). Note how the .class is omitted:
$ java HelloWorld
Hello, World!
You have successfully coded and built your very first Java program!
Note: In order for Java commands (java, javac, etc) to be recognized, you will need to make sure:
You will need to use a compiler (javac) and an executor (java) provided by your JVM. To find out which versions you
The "Hello World" program contains a single file, which consists of a HelloWorld class definition, a main method,
and a statement inside the main method.
The class keyword begins the class definition for a class named HelloWorld. Every Java application contains at least
one class definition (Further information about classes).
This is an entry point method (defined by its name and signature of public static void main(String[])) from
which the JVM can run your program. Every Java program should have one. It is:
public: meaning that the method can be called from anywhere mean from outside the program as well. See
Visibility for more information on this.
static: meaning it exists and can be run by itself (at the class level without creating an object).
void: meaning it returns no value. Note: This is unlike C and C++ where a return code such as int is expected
(Java's way is System.exit()).
An array (typically called args) of Strings passed as arguments to main function (e.g. from command line
arguments).
Non-required parts:
The name args is a variable name, so it can be called anything you want, although it is typically called args.
Whether its parameter type is an array (String[] args) or Varargs (String... args) does not matter
because arrays can be passed into varargs.
Note: A single application may have multiple classes containing an entry point (main) method. The entry point of the
application is determined by the class name passed as an argument to the java command.
System.out.println("Hello, World!");
Element Purpose
this denotes that the subsequent expression will call upon the System class, from the java.lang
System
package.
this is a "dot operator". Dot operators provide you access to a classes members1; i.e. its fields
. (variables) and its methods. In this case, this dot operator allows you to reference the out static field
within the System class.
this is the name of the static field of PrintStream type within the System class containing the standard
out
output functionality.
Here's another example demonstrating the OO paradigm. Let's model a football team with one (yes, one!) member.
There can be more, but we'll discuss that when we get to arrays.
class Member {
private String name;
private String type;
private int level; // note the data type here
private int rank; // note the data type here as well
Why do we use private here? Well, if someone wanted to know your name, they should ask you directly, instead of
reaching into your pocket and pulling out your Social Security card. This private does something like that: it
prevents outside entities from accessing your variables. You can only return private members through getter
functions (shown below).
After putting it all together, and adding the getters and main method as discussed before, we have:
class Member {
private String name;
private String type;
private int level;
private int rank;
Output:
Aurieel
light
10
1
Run on ideone
Once again, the main method inside the Test class is the entry point to our program. Without the main method, we
cannot tell the Java Virtual Machine (JVM) from where to begin execution of the program.
1 - Because the HelloWorld class has little relation to the System class, it can only access public data.
//Implicit casting
byte byteVar = 42;
short shortVar = byteVar;
int intVar = shortVar;
long longVar = intvar;
float floatVar = longVar;
double doubleVar = floatVar;
Explicit casting has to be done when the source type has larger range than the target type.
//Explicit casting
double doubleVar = 42.0d;
float floatVar = (float) doubleVar;
long longVar = (long) floatVar;
int intVar = (int) longVar;
short shortVar = (short) intVar;
byte byteVar = (byte) shortVar;
When casting floating point primitives (float, double) to whole number primitives, the number is rounded down.
A char can be cast to/from any numeric type by using the code-point mappings specified by Unicode. A char is
represented in memory as an unsigned 16-bit integer value (2 bytes), so casting to byte (1 byte) will drop 8 of those
bits (this is safe for ASCII characters). The utility methods of the Character class use int (4 bytes) to transfer
to/from code-point values, but a short (2 bytes) would also suffice for storing a Unicode code-point.
Implicit casting happens when the source type extends or implements the target type (casting to a superclass or
interface).
Explicit casting has to be done when the source type is extended or implemented by the target type (casting to a
subtype). This can produce a runtime exception (ClassCastException) when the object being cast is not of the
target type (or the target's subtype).
In this Person class, there is a single variable: name. This variable can be accessed using the getName() method and
changed using the setName(String) method, however, setting a name requires the new name to have a length
greater than 2 characters and to not be null. Using a setter method rather than making the variable name public
allows others to set the value of name with certain restrictions. The same can be applied to the getter method:
In the modified getName() method above, the name is returned only if its length is less than or equal to 16.
Otherwise, "Name is too large" is returned. This allows the programmer to create variables that are reachable
and modifiable however they wish, preventing client classes from editing the variables unwantedly.
We can't access the count variable because it's private. But we can access the getCount() and the setCount(int)
methods because they are public. To some, this might raise the question; why introduce the middleman? Why not
just simply make they count public?
For all intents and purposes, these two are exactly the same, functionality-wise. The difference between them is the
extensibility. Consider what each class says:
First: "I have a method that will give you an int value, and a method that will set that value to another int".
Second: "I have an int that you can set and get as you please."
These might sound similar, but the first is actually much more guarded in its nature; it only lets you interact with its
internal nature as it dictates. This leaves the ball in its court; it gets to choose how the internal interactions occur.
The second has exposed its internal implementation externally, and is now not only prone to external users, but, in
the case of an API, committed to maintaining that implementation (or otherwise releasing a non-backward-
compatible API).
Lets consider if we want to synchronize access to modifying and accessing the count. In the first, this is simple:
but in the second example, this is now nearly impossible without going through and modifying each place where
the count variable is referenced. Worse still, if this is an item that you're providing in a library to be consumed by
others, you do not have a way of performing that modification, and are forced to make the hard choice mentioned
above.
So it begs the question; are public variables ever a good thing (or, at least, not evil)?
I'm unsure. On one hand, you can see examples of public variables that have stood the test of time (IE: the out
variable referenced in System.out). On the other, providing a public variable gives no benefit outside of extremely
minimal overhead and potential reduction in wordiness. My guideline here would be that, if you're planning on
making a variable public, you should judge it against these criteria with extreme prejudice:
1. The variable should have no conceivable reason to ever change in its implementation. This is something
that's extremely easy to screw up (and, even if you do get it right, requirements can change), which is why
getters/setters are the common approach. If you're going to have a public variable, this really needs to be
thought through, especially if released in a library/framework/API.
2. The variable needs to be referenced frequently enough that the minimal gains from reducing verbosity
warrants it. I don't even think the overhead for using a method versus directly referencing should be
considered here. It's far too negligible for what I'd conservatively estimate to be 99.9% of applications.
There's probably more than I haven't considered off the top of my head. If you're ever in doubt, always use
getters/setters.
These private variables cannot be accessed directly from outside the class. Hence they are protected from
unauthorized access. But if you want to view or modify them, you can use Getters and Setters.
getXxx() method will return the current value of the variable xxx, while you can set the value of the variable xxx
using setXxx().
The naming convention of the methods are (in example variable is called variableName):
boolean variables
Public Getters and Setters are part of the Property definition of a Java Bean.
Dereferencing follows the memory address stored in a reference, to the place in memory where the actual object
resides. When an object has been found, the requested method is called (toString in this case).
null indicates the absence of a value, i.e. following the memory address leads nowhere. So there is no object on
which the requested method can be called.
Where:
What happens:
int i = 10;
(For an explanation of the above code, please refer to Getting started with Java Language .)
$ javac HelloWorld.java
This produces a file called "HelloWorld.class", which we can then run as follows:
$ java HelloWorld
Hello world!
1. The source filename "HelloWorld.java" must match the class name in the source file ... which is HelloWorld. If
they don't match, you will get a compilation error.
2. The bytecode filename "HelloWorld.class" corresponds to the classname. If you were to rename the
"HelloWorld.class", you would get an error when your tried to run it.
3. When running a Java application using java, you supply the classname NOT the bytecode filename.
Most practical Java code uses packages to organize the namespace for classes and reduce the risk of accidental
class name collision.
If we wanted to declare the HelloWorld class in a package call com.example, the "HelloWorld.java" would contain
the following Java source:
package com.example;
This source code file needs to stored in a directory tree whose structure corresponds to the package naming.
$ javac com/example/HelloWorld.java
This produces a file called "com/example/HelloWorld.class"; i.e. after compilation, the file structure should look like
this:
$ java com.example.HelloWorld
Hello world!
If your application consists of multiple source code files (and most do!) you can compile them one at a time.
Alternatively, you can compile multiple files at the same time by listing the pathnames:
$ javac *.java
$ javac com/example/*.java
$ javac */**/*.java #Only works on Zsh or with globstar enabled on your shell
This will compile all Java source files in the current directory, in the "com/example" directory, and recursively in
child directories respectively. A third alternative is to supply a list of source filenames (and compiler options) as a
file. For example:
$ javac @sourcefiles
Foo.java
Bar.java
Note: compiling code like this is appropriate for small one-person projects, and for once-off programs. Beyond that,
it is advisable to select and use a Java build tool. Alternatively, most programmers use a Java IDE (e.g. NetBeans,
eclipse, IntelliJ IDEA) which offers an embedded compiler and incremental building of "projects".
Here are a few options for the javac command that are likely to be useful to you
The -d option sets a destination directory for writing the ".class" files.
The -sourcepath option sets a source code search path.
The -cp or -classpath option sets the search path for finding external and previously compiled classes. For
more information on the classpath and how to specify it, refer to the The Classpath Topic.
The -version option prints the compiler's version information.
References
The definitive reference for the javac command is the Oracle manual page for javac.
With very few exceptions (for example the enum keyword, changes to some "internal" classes, etc), these changes
are backwards compatible.
A Java program that was compiled using an older version of the Java toolchain will run on a newer version
Java platform without recompilation.
A Java program that was written in an older version of Java will compile successfully with a new Java compiler.
If you need to (re-)compile older Java code on a newer Java platform to run on the newer platform, you generally
don't need to give any special compilation flags. In a few cases (e.g. if you had used enum as an identifier) you could
use the -source option to disable the new syntax. For example, given the following class:
the following is required to compile the class using a Java 5 compiler (or later):
If you need to compile Java to run on an older Java platforms, the simplest approach is to install a JDK for the oldest
version you need to support, and use that JDK's compiler in your builds.
The code you are compiling must not use Java language constructs that were not available in the version of
Java that you are targeting.
The code must not depend on standard Java classes, fields, methods and so on that were not available in the
older platforms.
Third party libraries that the code depends must also be built for the older platform and available at compile-
time and run-time.
Given the preconditions are met, you can recompile code for an older platform using the -target option. For
example,
will compile the above class to produce bytecodes that are compatible with Java 1.4 or later JVM. (In fact, the -
source option implies a compatible -target, so javac -source 1.4 ... would have the same effect. The
relationship between -source and -target is described in the Oracle documentation.)
Having said that, if you simply use -target or -source, you will still be compiling against the standard class libraries
provided by the compiler's JDK. If you are not careful, you can end up with classes with the correct bytecode
version, but with dependencies on APIs that are not available. The solution is to use the -bootclasspath option. For
example:
will compile against an alternative set of runtime libraries. If the class being compiled has (accidental) dependencies
on newer libraries, this will give you compilation errors.
However, these tools are not required to generate the Javadoc HTML; this can be done using the command line
javadoc tool.
javadoc JavaFile.java
A more practical use of the command line tool, which will recursively read all java files in [source-directory],
create documentation for [package.name] and all sub-packages, and place the generated HTML in the [docs-
directory] is:
/**
* Brief summary of this class, ending with a period.
*
* It is common to leave a blank line between the summary and further details.
* The summary (everything before the first period) is used in the class or package
* overview section.
*
* The following inline tags can be used (not an exhaustive list):
* {@link some.other.class.Documentation} for linking to other docs or symbols
* {@link some.other.class.Documentation Some Display Name} the link's appearance can be
* customized by adding a display name after the doc or symbol locator
* {@code code goes here} for formatting as code
* {@literal <>[]()foo} for interpreting literal text without converting to HTML markup
* or other tags.
*
* Optionally, the following tags may be used at the end of class documentation
* (not an exhaustive list):
*
* @author John Doe
* @version 1.0
* @since 5/10/15
* @see some.other.class.Documentation
* @deprecated This class has been replaced by some.other.package.BetterFileReader
*
The same tags and format used for Classes can be used for Enums and Interfaces as well.
/**
* Brief summary of method, ending with a period.
*
* Further description of method and what it does, including as much detail as is
* appropriate. Inline tags such as
* {@code code here}, {@link some.other.Docs}, and {@literal text here} can be used.
*
* If a method overrides a superclass method, {@inheritDoc} can be used to copy the
* documentation
* from the superclass method
*
* @param stream Describe this parameter. Include as much detail as is appropriate
* Parameter docs are commonly aligned as here, but this is optional.
* As with other docs, the documentation before the first period is
* used as a summary.
*
* @return Describe the return values. Include as much detail as is appropriate
* Return type docs are commonly aligned as here, but this is optional.
* As with other docs, the documentation before the first period is used as a
* summary.
*
* @throws IOException Describe when and why this exception can be thrown.
* Exception docs are commonly aligned as here, but this is
* optional.
* As with other docs, the documentation before the first period
* is used as a summary.
* Instead of @throws, @exception can also be used.
*
* @since 2.1.0
* @see some.other.class.Documentation
* @deprecated Describe why this method is outdated. A replacement can also be specified.
*/
public String[] read(InputStream stream) throws IOException {
return null;
}
It is possible to create package-level documentation in Javadocs using a file called package-info.java. This file
must be formatted as below. Leading whitespace and asterisks optional, typically present in each line for formatting
reason
/**
* Package documentation goes here; any documentation before the first period will
* be used as a summary.
*
* It is common practice to leave a blank line between the summary and the rest
* of the documentation; use this space to describe the package in as much detail
* as is appropriate.
*
* Inline tags such as {@code code here}, {@link reference.to.other.Documentation},
* and {@literal text here} can be used in this documentation.
*/
package com.example.foo;
In the above case, you must put this file package-info.java inside the folder of the Java package com.example.foo.
/**
* You can link to the javadoc of an already imported class using {@link ClassName}.
*
* You can also use the fully-qualified name, if the class is not already imported:
* {@link some.other.ClassName}
*
* You can link to members (fields or methods) of a class like so:
* {@link ClassName#someMethod()}
* {@link ClassName#someMethodWithParameters(int, String)}
* {@link ClassName#someField}
* {@link #someMethodInThisClass()} - used to link to members in the current class
*
* You can add a label to a linked javadoc like so:
* {@link ClassName#someMethod() link text}
*/
/**
* This method has a nice explanation but you might found further
* information at the bottom.
*
* @see ClassName#someMethod()
*/
If you want to add links to external resources you can just use the HTML <a> tag. You can use it inline anywhere
or inside both @link and @see tags.
/**
* Wondering how this works? You might want
* to check this <a href="http://stackoverflow.com/">great service</a>.
*
* @see <a href="http://stackoverflow.com/">Stack Overflow</a>
*/
/**
* The Class TestUtils.
* <p>
* This is an {@code inline("code example")}.
* <p>
* You should wrap it in pre tags when writing multiline code.
* <pre>{@code
* Example example1 = new FirstLineExample();
* example1.butYouCanHaveMoreThanOneLine();
* }</pre>
* <p>
* Thanks for reading.
*/
class TestUtils {
Sometimes you may need to put some complex code inside the javadoc comment. The @ sign is specially
problematic. The use of the old <code> tag alongside the {@literal } construct solves the problem.
/**
* Usage:
* <pre><code>
* class SomethingTest {
* {@literal @}Rule
/**
* Fields can be documented as well.
*
* As with other javadocs, the documentation before the first period is used as a
* summary, and is usually separated from the rest of the documentation by a blank
* line.
*
* Documentation for fields can use inline tags, such as:
* {@code code here}
* {@literal text here}
* {@link other.docs.Here}
*
* Field documentation can also make use of the following tags:
*
* @since 2.1.0
* @see some.other.class.Documentation
* @deprecated Describe why this field is outdated
*/
public static final String CONSTANT_STRING = "foo";
Single Line comments are started by // and may be positioned after a statement on the same line, but not before.
Multi-Line comments are defined between /* and */. They can span multiple lines and may even been positioned
between statements.
/*
As too many inline comments may decrease readability of code, they should be used sparsely in case the code isn't
self-explanatory enough or the design decision isn't obvious.
An additional use case for single-line comments is the use of TAGs, which are short, convention driven keywords.
Some development environments recognize certain conventions for such single-comments. Common examples are
//TODO
//FIXME
//PRJ-1234
https://gwt.googlesource.com/gwt/+/2.8.0-beta1/dev/core/src/com/google/gwt/util/tools/ToolBase.java
An example for handling the command-line myprogram -dir "~/Documents" -port 8888 is:
public MyProgramHandler() {
this.registerHandler(new ArgHandlerDir() {
@Override
public void setDir(File dir) {
this.dir = dir;
}
});
this.registerHandler(new ArgHandlerInt() {
@Override
public String[] getTagArgs() {
return new String[]{"port"};
}
@Override
public void setInt(int value) {
this.port = value;
}
});
}
public static void main(String[] args) {
MyProgramHandler myShell = new MyProgramHandler();
if (myShell.processArgs(args)) {
// main program operation
System.out.println(String.format("port: %d; dir: %s",
myShell.getPort(), myShell.getDir()));
}
System.exit(1);
}
}
ArgHandler also has a method isRequired() which can be overwritten to say that the command-line argument is
required (default return is false so that the argument is optional.
In this example, we will present a series of simple case studies. In each case, the code will produce error messages
if the arguments are unacceptable, and then call System.exit(1) to tell the shell that the command has failed. (We
will assume in each case that the Java code is invoked using a wrapper whose name is "myapp".)
In this case-study, the command requires no arguments. The code illustrates that args.length gives us the number
of command line arguments.
Note that if we neglected to check args.length, the command would crash if the user ran it with too few
command-line arguments.
In this case-study, the command has a couple of (optional) flag options, and requires at least one argument after
the options.
package tommy;
public class Main {
public static void main(String[] args) {
boolean feelMe = false;
boolean seeMe = false;
int index;
loop: for (index = 0; index < args.length; index++) {
String opt = args[index];
switch (opt) {
case "-c":
seeMe = true;
break;
case "-f":
feelMe = true;
As you can see, processing the arguments and options gets rather cumbersome if the command syntax is
complicated. It is advisable to use a "command line parsing" library; see the other examples.
When the java command starts the virtual machine, it loads the specified entry-point classes and tries to find main.
If successful, the arguments from command line are converted to Java String objects and assembled into an array.
If main is invoked like this, the array will not be null and won't contain any null entries.
It is conventional to declare the class as public but this not strictly necessary. From Java 5 onward, the main
method's argument type may be a String varargs instead of a string array. main can optionally throw exceptions,
and its parameter can be named anything, but conventionally it is args.
JavaFX entry-points
From Java 8 onwards the java command can also directly launch a JavaFX application. JavaFX is documented in the
JavaFX tag, but a JavaFX entry-point must do the following:
Extend javafx.application.Application
Be public and not abstract
Not be generic or nested
Have an explicit or implicit public no-args constructor
when trying to run the java command, this means that there is no java command on your shell's command search
path. The cause could be:
Refer to "Installing Java" for the steps that you need to take.
This error message is output by the java command if it has been unable to find / load the entry-point class that you
have specified. In general terms, there are three broad reasons that this can happen:
You have specified an entry point class that does not exist.
The class exists, but you have specified it incorrectly.
The class exists and you have specified it correctly, but Java cannot it find it because the classpath is
incorrect.
If you have source code for a class, then the full name consists of the package name and the simple
class name. The instance the "Main" class is declared in the package "com.example.myapp" then its full
name is "com.example.myapp.Main".
If you have a compiled class file, you can find the class name by running javap on it.
If the class file is in a directory, you can infer the full class name from the directory names.
If the class file is in a JAR or ZIP file, you can infer the full class name from the file path in the JAR or ZIP
file.
2. Look at the error message from the java command. The message should end with the full class name that
java is trying to use.
Check that it exactly matches the full classname for the entry-point class.
It should not end with ".java" or ".class".
It should not contain slashes or any other character that is not legal in a Java identifier1.
The casing of the name should exactly match the full class name.
3. If you are using the correct classname, make sure that the class is actually on the classpath:
Work out the pathname that the classname maps to; see Mapping classnames to pathnames
Work out what the classpath is; see this example: Different ways to specify the classpath
Look at each of the JAR and ZIP files on the classpath to see if they contain a class with the required
pathname.
Look at each directory to see if the pathname resolves to a file within the directory.
If checking the classpath by hand did not find the issue, you could add the -Xdiag and -XshowSettings options. The
former lists all classes that are loaded, and the latter prints out settings that include the effective classpath for the
JVM.
An executable JAR file with a Main-Class attribute that specifies a class that does not exist.
An executable JAR file with an incorrect Class-Path attribute.
If you mess up2 the options before the classname, the java command may attempt to interpret one of them
This problem happens when the java command is able to find and load the class that you nominated, but is then
unable to find an entry-point method.
If you are trying to run an executable JAR file, then the JAR's manifest has an incorrect "Main-Class" attribute
that specifies a class that is not a valid entry point class.
You have told the java command a class that is not an entry point class.
The entry point class is incorrect; see Entry point classes for more information.
Other Resources
1 - From Java 8 and later, the java command will helpfully map a filename separator ("/" or "") to a period (".").
However, this behavior is not documented in the manual pages.
2 - A really obscure case is if you copy-and-paste a command from a formatted document where the text editor has
used a "long hyphen" instead of a regular hyphen.
Typical Java applications consist of an application-specific code, and various reusable library code that you have
implemented or that has been implemented by third parties. The latter are commonly referred to as library
dependencies, and are typically packaged as JAR files.
Java is a dynamically bound language. When you run a Java application with library dependencies, the JVM needs to
know where the dependencies are so that it can load classes as required. Broadly speaking, there are two ways to
deal with this:
The application and its dependencies can be repackaged into a single JAR file that contains all of the required
classes and resources.
The JVM can be told where to find the dependent JAR files via the runtime classpath.
For an executable JAR file, the runtime classpath is specified by the "Class-Path" manifest attribute. (Editorial Note:
This should be described in a separate Topic on the jar command.) Otherwise, the runtime classpath needs to be
supplied using the -cp option or using the CLASSPATH environment variable.
For example, suppose that we have a Java application in the "myApp.jar" file whose entry point class is
com.example.MyApp. Suppose also that the application depends on library JAR files "lib/library1.jar" and
"lib/library2.jar". We could launch the application using the java command as follows in a command line:
$ # Alternative 1 (preferred)
$ # Alternative 2
$ export CLASSPATH=myApp.jar:lib/library1.jar:lib/library2.jar
$ java com.example.MyApp
(On Windows, you would use ; instead of : as the classpath separator, and you would set the (local) CLASSPATH
variable using set rather than export.)
While a Java developer would be comfortable with that, it is not "user friendly". So it is common practice to write a
simple shell script (or Windows batch file) to hide the details that the user doesn't need to know about. For
example, if you put the following shell script into a file called "myApp", made it executable, and put it into a
directory on the command search path:
#!/bin/bash
# The 'myApp' wrapper script
export DIR=/usr/libexec/myApp
export CLASSPATH=$DIR/myApp.jar:$DIR/lib/library1.jar:$DIR/lib/library2.jar
java com.example.MyApp
Any arguments on the command line will be passed to the Java application via the "$@" expansion. (You can do
something similar with a Windows batch file, though the syntax is different.)
--
Options must appear before the <classname> or the -jar <jarfile> argument to be recognized. Any
arguments after them will be treated as arguments to be passed to Java app that is being run.
Options that do not start with -X or -XX are standard options. You can rely on all Java implementations1 to
support any standard option.
Options that start with -X are non-standard options, and may be withdrawn from one Java version to the
next.
Options that start with -XX are advanced options, and may also be withdrawn.
The -D<property>=<value> option is used to set a property in the system Properties object. This parameter can be
repeated to set different properties.
The main options for controlling the heap and stack sizes are documented in Setting the Heap, PermGen and Stack
sizes. (Editorial note: Garbage Collector options should be described in the same topic.)
The -ea and -da options respectively enable and disable Java assert checking:
Note that enabling to assertion checking is liable to alter the behavior of a Java programming.
The -client and -server options allow you to select between two different forms of the HotSpot VM:
The "client" form is tuned for user applications and offers faster startup.
The "server" form is tuned for long running applications. It takes longer capturing statistic during JVM "warm
up" which allows the JIT compiler to do a better of job of optimizing the native code.
By default, the JVM will run in 64bit mode if possible, depending on the capabilities of the platform. The -d32 and -
d64 options allow you to select the mode explicitly.
1 - Check the official manual for the java command. Sometimes a standard option is described as "subject to
change".
import java.io.File;
Now suppose that we want print the size of a file whose pathname has spaces in it; e.g. /home/steve/Test
File.txt. If we run the command like this:
the shell won't know that /home/steve/Test File.txt is actually one pathname. Instead, it will pass 2 distinct
arguments to the Java application, which will attempt to find their respective file sizes, and fail because files with
those paths (probably) do not exist.
POSIX shells include sh as well derivatives such as bash and ksh. If you are using one of these shells, then you can
solve the problem by quoting the argument.
The double-quotes around the pathname tell the shell that it should be passed as a single argument. The quotes
will be removed when this happens. There are a couple of other ways to do this:
Single (straight) quotes are treated like double-quotes except that they also suppress various expansions within the
argument.
A backslash escapes the following space, and causes it not to be interpreted as an argument separator.
For more comprehensive documentation, including descriptions of how to deal with other special characters in
arguments, please refer to the quoting topic in the Bash documentation.
The fundamental problem for Windows is that at the OS level, the arguments are passed to a child process as a
single string (source). This means that the ultimate responsibility of parsing (or re-parsing) the command line falls
on either program or its runtime libraries. There is lots of inconsistency.
You can put double-quotes around an argument in a java command, and that will allow you to pass
arguments with spaces in them.
However, when you try to combine this with the use of SET and variable substitution in a batch file, it gets
really complicated as to whether double-quotes get removed.
The cmd.exe shell apparently has other escaping mechanisms; e.g. doubling double-quotes, and using ^
escapes.
Assuming that you have an executable JAR file with pathname <jar-path>, you should be able to run it as follows:
If the command requires command-line arguments, add them after the <jar-path>. For example:
If you need to provide additional JVM options on the java command line, they need to go before the -jar option.
Note that a -cp / -classpath option will be ignored if you use -jar. The application's classpath is determined by the
JAR file manifest.
The "HelloWorld" example is described in Creating a new Java program . It consists of a single class called
HelloWorld which satisfies the requirements for an entry-point.
Assuming that the (compiled) "HelloWorld.class" file is in the current directory, it can be launched as follows:
java HelloWorld
We must provide the name of the class: not the pathname for the ".class" file or the ".java" file.
If the class is declared in a package (as most Java classes are), then the class name we supply to the java
command must be the full classname. For instance if SomeClass is declared in the com.example package, then
the full classname will be com.example.SomeClass.
Specifying a classpath
Unless we are using in the java -jar command syntax, the java command looks for the class to be loaded by
searching the classpath; see The Classpath. The above command is relying on the default classpath being (or
including) the current directory. We can be more explicit about this by specifying the classpath to be used using the
-cp option.
This says to make the current directory (which is what "." refers to) the sole entry on the classpath.
The -cp is an option that is processed by the java command. All options that are intended for the java command
should be before the classname. Anything after the class will be treated as an command line argument for the Java
application, and will be passed to application in the String[] that is passed to the main method.
(If no -cp option is provided, the java will use the classpath that is given by the CLASSPATH environment variable. If
that variable is unset or empty, java uses "." as the default classpath.)
java.sql.Date is a wrapper around millisecond value and is used by JDBC to identify an SQL DATE type
In the below example, we use the java.util.Date() constructor, that creates a Date object and initializes it to
represent time to the nearest millisecond. This date is used in the convert(java.util.Date utilDate) method to
return a java.sql.Date object
Example
Output
java.util.Date has both date and time information, whereas java.sql.Date only has date information
2016/04/19 11:45.36
// print it
System.out.println(formattedDate);
Creates a LocalDate
Creates a LocalDateTime
// LocalDate to Date
Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
// Date to LocalDateTime
LocalDateTime localDateTime = date.toInstant().atZone(defaultZoneId).toLocalDateTime();
// LocalDateTime to Date
Date out = Date.from(localDateTime.atZone(defaultZoneId).toInstant());
To create a new date, you will need a Calendar instance. From there you can set the Calendar instance to the date
that you need.
Calendar c = Calendar.getInstance();
This returns a new Calendar instance set to the current time. Calendar has many methods for mutating it's date
and time or setting it outright. In this case, we'll set it to a specific date.
c.set(1974, 6, 2, 8, 0, 0);
Date d = c.getTime();
The getTime method returns the Date instance that we need. Keep in mind that the Calendar set methods only set
one or more fields, they do not set them all. That is, if you set the year, the other fields remain unchanged.
PITFALL
In many cases, this code snippet fulfills its purpose, but keep in mind that two important parts of the date/time are
not defined.
the (1974, 6, 2, 8, 0, 0) parameters are interpreted within the default timezone, defined somewhere
else,
the milliseconds are not set to zero, but filled from the system clock at the time the Calendar instance is
created.
dateFormat.applyPattern("dd-MM-yyyy");
System.out.println(dateFormat.format(today)); //25-02-2016
Note: Here mm (small letter m) denotes minutes and MM (capital M) denotes month. Pay careful attention when
formatting years: capital "Y" (Y) indicates the "week in the year" while lower-case "y" (y) indicates the year.
LocalTime also has a built in toString method that displays the format very nicely.
System.out.println(time);
you can also get, add and subtract hours, minutes, seconds, and nanoseconds from the LocalTime object i.e.
time.plusMinutes(1);
time.getMinutes();
time.minusMinutes(1);
You can turn it into a Date object with the following code:
this class works very nicely within a timer class to simulate an alarm clock.
/**
* Parses the date using the given format.
*
* @param formattedDate the formatted date string
* @param dateFormat the date format which was used to create the string.
* @return the date
*/
public static Date parseDate(String formattedDate, String dateFormat) {
Date date = null;
Here this Date object contains the current date and time when this object was created.
Date objects are best created through a Calendar instance since the use of the data constructors is deprecated and
discouraged. To do se we need to get an instance of the Calendar class from the factory method. Then we can set
year, month and day of month by using numbers or in case of months constants provided py the Calendar class to
improve readability and reduce errors.
Along with date, we can also pass time in the order of hour, minutes and seconds.
//Before example
System.out.printf("Is %1$tF before %2$tF? %3$b%n", today, birthdate,
Boolean.valueOf(today.before(birthdate)));
System.out.printf("Is %1$tF before %1$tF? %3$b%n", today, today,
Boolean.valueOf(today.before(today)));
System.out.printf("Is %2$tF before %1$tF? %3$b%n", today, birthdate,
Boolean.valueOf(birthdate.before(today)));
//After example
System.out.printf("Is %1$tF after %2$tF? %3$b%n", today, birthdate,
//Compare example
System.out.printf("Compare %1$tF to %2$tF: %3$d%n", today, birthdate,
Integer.valueOf(today.compareTo(birthdate)));
System.out.printf("Compare %1$tF to %1$tF: %3$d%n", today, birthdate,
Integer.valueOf(today.compareTo(today)));
System.out.printf("Compare %2$tF to %1$tF: %3$d%n", today, birthdate,
Integer.valueOf(birthdate.compareTo(today)));
//Equal example
System.out.printf("Is %1$tF equal to %2$tF? %3$b%n", today, birthdate,
Boolean.valueOf(today.equals(birthdate)));
System.out.printf("Is %1$tF equal to %2$tF? %3$b%n", birthdate, samebirthdate,
Boolean.valueOf(birthdate.equals(samebirthdate)));
System.out.printf(
"Because birthdate.getTime() -> %1$d is different from samebirthdate.getTime() -> %2$d,
there are millisecondes!%n",
Long.valueOf(birthdate.getTime()), Long.valueOf(samebirthdate.getTime()));
System.out.printf("Is %1$tF equal to %2$tF after clearing ms? %3$b%n", birthdate, samebirthdate,
Boolean.valueOf(birthdate.equals(samebirthdate)));
Version ≥ Java SE 8
isBefore, isAfter, compareTo and equals methods
//Use of LocalDate
final LocalDate now = LocalDate.now();
final LocalDate birthdate2 = LocalDate.of(2012, 6, 30);
final LocalDate birthdate3 = LocalDate.of(2012, 6, 30);
//Hours, minutes, second and nanoOfsecond can also be configured with an other class LocalDateTime
//LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
//isBefore example
System.out.printf("Is %1$tF before %2$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(now.isBefore(birthdate2)));
System.out.printf("Is %1$tF before %1$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(now.isBefore(now)));
System.out.printf("Is %2$tF before %1$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(birthdate2.isBefore(now)));
//isAfter example
System.out.printf("Is %1$tF after %2$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(now.isAfter(birthdate2)));
System.out.printf("Is %1$tF after %1$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(now.isAfter(now)));
System.out.printf("Is %2$tF after %1$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(birthdate2.isAfter(now)));
//compareTo example
System.out.printf("Compare %1$tF to %2$tF %3$d%n", now, birthdate2,
Integer.valueOf(now.compareTo(birthdate2)));
//equals example
System.out.printf("Is %1$tF equal to %2$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(now.equals(birthdate2)));
System.out.printf("Is %1$tF to %2$tF? %3$b%n", birthdate2, birthdate3,
Boolean.valueOf(birthdate2.equals(birthdate3)));
//isEqual example
System.out.printf("Is %1$tF equal to %2$tF? %3$b%n", now, birthdate2,
Boolean.valueOf(now.isEqual(birthdate2)));
System.out.printf("Is %1$tF to %2$tF? %3$b%n", birthdate2, birthdate3,
Boolean.valueOf(birthdate2.isEqual(birthdate3)));
Before Java 8, dates could be compared using java.util.Calendar and java.util.Date classes. Date class offers 4
methods to compare dates :
after(Date when)
before(Date when)
compareTo(Date anotherDate)
equals(Object obj)
after, before, compareTo and equals methods compare the values returned by getTime() method for each date.
Value greater than 0 : when the Date is after the Date argument
Value greater than 0 : when the Date is before the Date argument
Value equals to 0 : when the Date is equal to the Date argument
equals results can be surprising as shown in the example because values, like milliseconds, are not initialize with
the same value if not explicitly given.
Since Java 8
With Java 8 a new Object to work with Date is available java.time.LocalDate. LocalDate implements
ChronoLocalDate, the abstract representation of a date where the Chronology, or calendar system, is pluggable.
To have the date time precision the Object java.time.LocalDateTime has to be used. LocalDate and LocalDateTime
use the same methods name for comparing.
Comparing dates using a LocalDate is different from using ChronoLocalDate because the chronology, or calendar
system are not taken in account the first one.
Because most application should use LocalDate, ChronoLocalDate is not included in examples. Further reading
here.
Most applications should declare method signatures, fields and variables as LocalDate, not
this[ChronoLocalDate] interface.
In case of LocalDate parameter, isAfter, isBefore, isEqual, equals and compareTo now use this method:
equals method check if the parameter reference equals the date first whereas isEqual directly calls compareTo0.
In case of an other class instance of ChronoLocalDate the dates are compared using the Epoch Day. The Epoch Day
count is a simple incrementing count of days where day 0 is 1970-01-01 (ISO).
There are 4 different styles for the text format, SHORT, MEDIUM (this is the default), LONG and FULL, all of which
depend on the locale. If no locale is specified, the system default locale is used.
However, it is possible to display the date represented by the point in time described by the Date object in a
different time zone using e.g. java.text.SimpleDateFormat:
Output:
now, since the method between of the ChronoUnit enumerator takes 2 Temporals as parameters so you can pass
without a problem the LocalDate instances
Date and time with offset information (i.e. no DST changes taken into account)
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.TimeZone;
public class SomeMethodsExamples {
/**
* Has the methods of the class {@link LocalDateTime}
*/
public static void checkLocalDateTime() {
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("Local Date time using static now() method ::: >>> "
+ localDateTime);
System.out
.println("Following is a static map in ZoneId class which has mapping of short timezone
names to their Actual timezone names");
System.out.println(ZoneId.SHORT_IDS);
/**
* This has the methods of the class {@link LocalDate}
*/
public static void checkLocalDate() {
LocalDate localDate = LocalDate.now();
System.out.println("Gives date without Time using now() method. >> "
+ localDate);
LocalDate localDate2 = LocalDate.now(ZoneId.of(ZoneId.SHORT_IDS
.get("ECT")));
System.out
.println("now() is overridden to take ZoneID as parametere using this we can get the
same date under different timezones. >> "
+ localDate2);
}
/**
/**
* This has the {@link Instant} class methods.
*/
public static void checkInstant() {
Instant instant = Instant.now();
/**
* This class checks the methods of the {@link Duration} class.
*/
public static void checkDuration() {
// toString() converts the duration to PTnHnMnS format according to ISO
// 8601 standard. If a field is zero its ignored.
System.out.println(Duration.ofDays(2));
}
/**
* Shows Local time without date. It doesn't store or represenet a date and
* time. Instead its a representation of Time like clock on the wall.
*/
public static void checkLocalTime() {
LocalTime localTime = LocalTime.now();
System.out.println("LocalTime :: " + localTime);
}
/**
}
}
In formatting and parsing first you pass a String object to DateTimeFormatter, and in turn use it for formatting or
parsing.
import java.time.*;
import java.time.format.*;
class DateTimeFormat
{
public static void main(String[] args) {
//Parsing
String pattern = "d-MM-yyyy HH:mm";
DateTimeFormatter dtF1 = DateTimeFormatter.ofPattern(pattern);
//Formatting
DateTimeFormatter dtF2 = DateTimeFormatter.ofPattern("EEE d, MMMM, yyyy HH:mm");
System.out.println(ldtf1.format(dtF2) +"\n"+ldtf1.format(dtF3));
}
}
An important notice, instead of using Custom patterns, it is good practice to use predefined formatters. Your code
look more clear and usage of ISO8061 will definitely help you in the long run.
LocalDate.now()
LocalDate t = LocalDate.now().plusDays(1);
In addition to the plus and minus methods, there are a set of "with" methods that can be used to set a particular
field on a LocalDate instance.
LocalDate.now().withMonth(6);
The example above returns a new instance with the month set to June (this differs from java.util.Date where
setMonth was indexed a 0 making June 5).
Because LocalDate manipulations return immutable LocalDate instances, these methods may also be chained
together.
LocalDate ld = LocalDate.now().plusDays(1).plusYears(1);
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
This class does not store or represent a date or time-zone. Instead, it is a description of the local time as seen on a
wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-
zone. This is a value based class, equals method should be used for comparisons.
Fields
You can also add/subtract hours, minutes or seconds from any object of LocalTime.
now.plusHours(1L);
now1.minusMinutes(20L);
}
}
Version ≥ Java SE 7
int i1 = 123456;
int i2 = 123_456;
System.out.println(i1 == i2); // true
Version ≥ Java SE 7
byte color = 1_2_3;
short yearsAnnoDomini= 2_016;
int socialSecurtyNumber = 999_99_9999;
long creditCardNumber = 1234_5678_9012_3456L;
float piFourDecimals = 3.14_15F;
double piTenDecimals = 3.14_15_92_65_35;
This also works using prefixes for binary, octal and hexadecimal bases:
Version ≥ Java SE 7
short binary= 0b0_1_0_1;
int octal = 07_7_7_7_7_7_7_7_0;
long hexBytes = 0xFF_EC_DE_5E;
There are a few rules about underscores which forbid their placement in the following places:
At the beginning or end of a number (e.g. _123 or 123_ are not valid)
Adjacent to a decimal point in a floating point literal (e.g. 1._23 or 1_.23 are not valid)
Prior to an F or L suffix (e.g. 1.23_F or 9999999_L are not valid)
In positions where a string of digits is expected (e.g. 0_xFFFF is not valid)
The octal literal can easily be a trap for semantic errors. If you define a leading '0' to your decimal literals you will
get the wrong value:
For example:
Note that a single string literal may not span multiple source code lines. It is a compilation error for a line-break (or
the end of the source file) to occur before a literal's closing double-quote. For example:
Long strings
If you need a string that is too long to fit on a line, the conventional way to express it is to split it into multiple
literals and use the concatenation operator (+) to join the pieces. For example
An expression like the above consisting of string literals and + satisfies the requirements to be a Constant
Expression. That means that the expression will be evaluated by the compiler and represented at runtime by a
single String object.
For more information on interning and the string pool, refer to the String pool and heap storage example in the
Strings topic.
myMethod(null);
if (objects != null) {
// Do something
}
The null type is rather unusual. It has no name, so you cannot express it in Java source code. (And it has no runtime
representation either.)
The sole purpose of the null type is to be the type of null. It is assignment compatible with all reference types, and
can be type cast to any reference type. (In the latter case, the cast does not entail a runtime type check.)
Finally, null has the property that null instanceof <SomeReferenceType> will evaluate to false, no matter what
the type is.
The <octal> in the above consists of one, two or three octal digits ('0' through '7') which represent a number
between 0 and 255 (decimal).
Note that a backslash followed by any other character is an invalid escape sequence. Invalid escape sequences are
treated as compilation errors by the JLS.
Reference:
Unicode escapes
In addition to the string and character escape sequences described above, Java has a more general Unicode
escaping mechanism, as defined in JLS 3.3. Unicode Escapes. A Unicode escape has the following syntax:
where <hex-digit> is one of '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C',
'D', 'E', 'F'.
A Unicode escape is mapped by the Java compiler to a character (strictly speaking a 16-bit Unicode code unit), and
can be used anywhere in the source code where the mapped character is valid. It is commonly used in character
and string literals when you need to represent a non-ASCII character in a literal.
Escaping in regexes
TBD
For example:
char a = 'a';
char doubleQuote = '"';
char singleQuote = '\'';
The simplest and most common form of integer literal is a decimal integer literal. For example:
Integer literals are unsigned. If you see something like -10 or +10, these are actually expressions using the unary
The range of integer literals of this form have an intrinsic type of int, and must fall in the range zero to 231 or
2,147,483,648.
Note that 231 is 1 greater than Integer.MAX_VALUE. Literals from 0 through to 2147483647 can be used anywhere,
but it is a compilation error to use 2147483648 without a preceding unary
operator. (In other words, it is reserved for expressing the value of Integer.MIN_VALUE.)
int max = 2147483647; // OK
int min = -2147483648; // OK
int tooBig = 2147483648; // ERROR
Note that the distinction between int and long literals is significant in other places. For example
int i = 2147483647;
long l = i + 1; // Produces a negative value because the operation is
// performed using 32 bit arithmetic, and the
// addition overflows
long l2 = i + 1L; // Produces the (intuitively) correct value.
(The JLS syntax rules combine the two decimal forms into a single form. We treat them separately for ease of
explanation.)
The simplest form of floating point literal consists of one or more decimal digits and a decimal point (.) and an
optional suffix (f, F, d or D). The optional suffix allows you to specify that the literal is a float (f or F) or double (d or
D) value. The default (when no suffix is specified) is double.
For example
The meaning of a decimal literal is the IEEE floating point number that is closest to the infinite precision
mathematical Real number denoted by the decimal floating point form. This conceptual value is converted to IEEE
binary floating point representation using round to nearest. (The precise semantics of decimal conversion are
specified in the javadocs for Double.valueOf(String) and Float.valueOf(String), bearing in mind that there are
differences in the number syntaxes.)
Scaled decimal forms consist of simple decimal with an exponent part introduced by an E or e, and followed by a
signed integer. The exponent part is a short hand for multiplying the decimal form by a power of ten, as shown in
the examples below. There is also an optional suffix to distinguish float and double literals. Here are some
examples:
The size of a literal is limited by the representation (float or double). It is a compilation error if the scale factor
results in a value that is too large or too small.
Hexadecimal forms
Starting with Java 6, it is possible to express floating point literals in hexadecimal. The hexadecimal form have an
analogous syntax to the simple and scaled decimal forms with the following differences:
1. Every hexadecimal floating point literal starts with a zero (0) and then an x or X.
2. The digits of the number (but not the exponent part!) also include the hexadecimal digits a through f and
their uppercase equivalents.
3. The exponent is mandatory, and is introduced by the letter p (or P) instead of an e or E. The exponent
represents a scaling factor that is a power of 2 instead of a power of 10.
Advice: since hexadecimal floating-point forms are unfamiliar to most Java programmers, it is advisable to use them
sparingly.
Underscores
Starting with Java 7, underscores are permitted within the digit strings in all three forms of floating point literal. This
applies to the "exponent" parts as well. See Using underscores to improve readability.
Special cases
It is a compilation error if a floating point literal denotes a number that is too large or too small to represent in the
selected representation; i.e. if the number would overflow to +INF or -INF, or underflow to 0.0. However, it is legal
for a literal to represent a non-zero denormalized number.
The floating point literal syntax does not provide literal representations for IEEE 754 special values such as the INF
and NaN values. If you need to express them in source code, the recommended way is to use the constants defined
by the java.lang.Float and java.lang.Double; e.g. Float.NaN, Float.NEGATIVE_INFINITY and
Float.POSITIVE_INFINITY.
--
operators, respectively.
--
operators follow variables, they are called post-increment and post-decrement respectively.
int a = 10;
a++; // a now equals 11
a--; // a now equals 10 again
--
operators precede the variables the operations are called pre-increment and pre-decrement respectively.
int x = 10;
--x; // x now equals 9
++x; // x now equals 10
If the operator precedes the variable, the value of the expression is the value of the variable after being
incremented or decremented. If the operator follows the variable, the value of the expression is the value of the
variable prior to being incremented or decremented.
int x=10;
System.out.println("x=" + x + " x=" + x++ + " x=" + x); // outputs x=10 x=10 x=11
System.out.println("x=" + x + " x=" + ++x + " x=" + x); // outputs x=11 x=12 x=12
System.out.println("x=" + x + " x=" + x-- + " x=" + x); // outputs x=12 x=12 x=11
System.out.println("x=" + x + " x=" + --x + " x=" + x); // outputs x=11 x=10 x=10
Be careful not to overwrite post-increments or decrements. This happens if you use a post-in/decrement operator
at the end of an expression which is reassigned to the in/decremented variable itself. The in/decrement will not
have an effect. Even though the variable on the left hand side is incremented correctly, its value will be immediately
overwritten with the previously evaluated result from the right hand side of the expression:
int x = 0;
x = x++ + 1 + x++; // x = 0 + 1 + 1
// do not do this - the last increment has no effect (bug!)
System.out.println(x); // prints 2 (not 3!)
Correct:
int x = 0;
x = x++ + 1 + x; // evaluates to x = 0 + 1 + 1
As shown in the syntax, the Conditional Operator (also known as the Ternary Operator1) uses the ? (question mark)
and : (colon) characters to enable a conditional expression of two possible outcomes. It can be used to replace
longer if-else blocks to return one of two values based on condition.
Is equivalent to
if (testCondition) {
result = value1;
} else {
result = value2;
}
It can be read as “If testCondition is true, set result to value1; otherwise, set result to value2”.
For example:
Is equivalent to
Common Usage
You can use the conditional operator for conditional assignments (like null checking).
String x = "";
if (y != null) {
x = y.toString();
}
// parenthesis required
7 * (a > 0 ? 2 : 5)
Conditional operators nesting can also be done in the third part, where it works more like chaining or like a switch
statement.
a ? "a is true" :
b ? "a is false, b is true" :
c ? "a and b are false, c is true" :
"a, b, and c are false"
a ? x : (b ? y : (c ? z : w))
Footnote:
1 - Both the Java Language Specification and the Java Tutorial call the (? :) operator the Conditional Operator. The
Tutorial says that it is "also known as the Ternary Operator" as it is (currently) the only ternary operator defined by
Java. The "Conditional Operator" terminology is consistent with C and C++ and other languages with an equivalent
operator.
The complement (~) operator is a unary operator that performs a bitwise or logical inversion of the bits of
one operand; see JLS 15.15.5..
The AND (&) operator is a binary operator that performs a bitwise or logical "and" of two operands; see JLS
15.22.2..
The OR (|) operator is a binary operator that performs a bitwise or logical "inclusive or" of two operands; see
JLS 15.22.2..
The XOR (^) operator is a binary operator that performs a bitwise or logical "exclusive or" of two operands;
see JLS 15.22.2..
The logical operations performed by these operators when the operands are booleans can be summarized as
follows:
A B ~A A & B A | B A ^ B
001 0 0 0
011 0 1 1
100 0 1 1
110 1 1 0
Note that for integer operands, the above table describes what happens for individual bits. The operators actually
operate on all 32 or 64 bits of the operand or operands in parallel.
The ~ operator is used to reverse a boolean value, or change all the bits in an integer operand.
The & operator is used for "masking out" some of the bits in an integer operand. For example:
The | operator is used to combine the truth values of two operands. For example:
For more examples of the use of the bitwise operators, see Bit Manipulation
In the simple case, the Concatenation operator joins two strings to give a third string. For example:
When one of the two operands is not a string, it is converted to a String as follows:
An operand whose type is a primitive type is converted as if by calling toString() on the boxed value.
An operand whose type is a reference type is converted by calling the operand's toString() method. If the
operand is null, or if the toString() method returns null, then the string literal "null" is used instead.
For example:
int one = 1;
String s3 = "One is " + one; // s3 contains "One is 1"
String s4 = null + " is null"; // s4 contains "null is null"
String s5 = "{1} is " + new int[]{1}; // s5 contains something like
// "{} is [I@xxxxxxxx"
The explanation for the s5 example is that the toString() method on array types is inherited from
java.lang.Object, and the behavior is to produce a string that consists of the type name, and the object's identity
The Concatenation operator is specified to create a new String object, except in the case where the expression is a
Constant Expression. In the latter case, the expression is evaluated at compile type, and its runtime value is
equivalent to a string literal. This means that there is no runtime overhead in splitting a long string literal like this:
As noted above, with the exception of constant expressions, each string concatenation expression creates a new
String object. Consider this code:
In the method above, each iteration of the loop will create a new String that is one character longer than the
previous iteration. Each concatenation copies all of the characters in the operand strings to form the new String.
Thus, stars(N) will:
create N new String objects, and throw away all but the last one,
copy N * (N + 1) / 2 characters, and
generate O(N^2) bytes of garbage.
This is very expensive for large N. Indeed, any code that concatenates strings in a loop is liable to have this problem.
A better way to write this would be as follows:
Ideally, you should set the capacity of the StringBuilder, but if this is not practical, the class will automatically grow
the backing array that the builder uses to hold characters. (Note: the implementation expands the backing array
exponentially. This strategy keeps that amount of character copying to a O(N) rather than O(N^2).)
Some people apply this pattern to all string concatenations. However, this is unnecessary because the JLS allows a
Java compiler to optimize string concatenations within a single expression. For example:
String s1 = ...;
String s2 = ...;
String test = "Hello " + s1 + ". Welcome to " + s2 + "\n";
(The JIT compiler may optimize that further if it can deduce that s1 or s2 cannot be null.) But note that this
optimization is only permitted within a single expression.
operators:
The binary subtraction operator subtracts one number from another one.
The unary minus operator is equivalent to subtracting its operand from zero.
The binary multiply operator (*) multiplies one number by another.
The binary divide operator (/) divides one number by another.
The binary remainder1 operator (%) calculates the remainder when one number is divided by another.
1. This is often incorrectly referred to as the "modulus" operator. "Remainder" is the term that is used by the JLS.
"Modulus" and "remainder" are not the same thing.
The operators require numeric operands and produce numeric results. The operand types can be any primitive
numeric type (i.e. byte, short, char, int, long, float or double) or any numeric wrapper type define in java.lang;
i.e. (Byte, Character, Short, Integer, Long, Float or Double.
The result type is determined base on the types of the operand or operands, as follows:
If either of the operands is a double or Double, then the result type is double.
Otherwise, if either of the operands is a float or Float, then the result type is float.
Otherwise, if either of the operands is a long or Long, then the result type is long.
Otherwise, the result type is int. This covers byte, short and char operands as well as `int.
The result type of the operation determines how the arithmetic operation is performed, and how the operands are
handled
If the result type is double, the operands are promoted to double, and the operation is performed using 64-
bit (double precision binary) IEE 754 floating point arithmetic.
If the result type is float, the operands are promoted to float, and the operation is performed using 32-bit
If the operand type is a wrapper type, the operand value is unboxed to a value of the corresponding primitive
type.
If necessary, the primitive type is promoted to the required type:
Promotion of integers to int or long is loss-less.
Promotion of float to double is loss-less.
Promotion of an integer to a floating point value can lead to loss of precision. The conversion is
performed using IEE 768 "round-to-nearest" semantics.
The / operator divides the left-hand operand n (the dividend) and the right-hand operand d (the divisor) and
produces the result q (the quotient).
Java integer division rounds towards zero. The JLS Section 15.17.2 specifies the behavior of Java integer division as
follows:
The quotient produced for operands n and d is an integer value q whose magnitude is as large as possible
while satisfying |d ? q| ? |n|. Moreover, q is positive when |n| ? |d| and n and d have the same sign,
but q is negative when |n| ? |d| and n and d have opposite signs.
If the n is MIN_VALUE, and the divisor is -1, then integer overflow occurs and the result is MIN_VALUE. No
exception is thrown in this case.
If d is 0, then `ArithmeticException is thrown.
Java floating point division has more edge cases to consider. However the basic idea is that the result q is the value
that is closest to satisfying d . q = n.
Floating point division will never result in an exception. Instead, operations that divide by zero result in an INF and
NaN values; see below.
Unlike C and C++, the remainder operator in Java works with both integer and floating point operations.
For integer cases, the result of a % b is defined to be the number r such that (a / b) * b + r is equal to a, where
/, * and + are the appropriate Java integer operators. This applies in all cases except when b is zero. That case,
remainder results in an ArithmeticException.
It follows from the above definition that a % b can be negative only if a is negative, and it be positive only if a is
positive. Moreover, the magnitude of a % b is always less than the magnitude of b.
Floating point remainder operation is a generalization of the integer case. The result of a % b is the remainder r is
defined by the mathematical relation r = a - (b ? q) where:
Floating point remainder can produce INF and NaN values in edge-cases such as when b is zero; see below. It will not
throw an exception.
Important note:
The result of a floating-point remainder operation as computed by % is not the same as that produced by
the remainder operation defined by IEEE 754. The IEEE 754 remainder may be computed using the
Math.IEEEremainder library method.
Integer Overflow
Java 32 and 64 bit integer values are signed and use twos-complement binary representation. For example, the
range of numbers representable as (32 bit) int -231 through +231 - 1.
When you add, subtract or multiple two N bit integers (N == 32 or 64), the result of the operation may be too large
to represent as an N bit integer. In this case, the operation leads to integer overflow, and the result can be computed
as follows:
It should be noted that integer overflow does not result in exceptions under any circumstances.
Java uses IEE 754 floating point representations for float and double. These representations have some special
values for representing values that fall outside of the domain of Real numbers:
The "infinite" or INF values denote numbers that are too large. The +INF value denote numbers that are too
large and positive. The -INF value denote numbers that are too large and negative.
The "indefinite" / "not a number" or NaN denote values resulting from meaningless operations.
The INF values are produced by floating operations that cause overflow, or by division by zero.
The NaN values are produced by dividing zero by zero, or computing zero remainder zero.
Surprisingly, it is possible perform arithmetic using INF and NaN operands without triggering exceptions. For
example:
For full details, please refer to the relevant subsections of JLS 15. Note that this is largely "academic". For typical
calculations, an INF or NaN means that something has gone wrong; e.g. you have incomplete or incorrect input data,
The << or left shift operator shifts the value given by the first operand leftwards by the number of bit positions
given by the second operand. The empty positions at the right end are filled with zeros.
The '>>' or arithmetic shift operator shifts the value given by the first operand rightwards by the number of bit
positions given by the second operand. The empty positions at the left end are filled by copying the left-most
bit. This process is known as sign extension.
The '>>>' or logical right shift operator shifts the value given by the first operand rightwards by the number of
bit positions given by the second operand. The empty positions at the left end are filled with zeros.
Notes:
1. These operators require an int or long value as the first operand, and produce a value with the same type as
the first operand. (You will need to use an explicit type cast when assigning the result of a shift to a byte,
short or char variable.)
2. If you use a shift operator with a first operand that is a byte, char or short, it is promoted to an int and the
operation produces an int.)
3. The second operand is reduced modulo the number of bits of the operation to give the amount of the shift. For
more about the mod mathematical concept, see Modulus examples.
4. The bits that are shifted off the left or right end by the operation are discarded. (Java does not provide a
primitive "rotate" operator.)
5. The arithmetic shift operator is equivalent dividing a (two's complement) number by a power of 2.
6. The left shift operator is equivalent multiplying a (two's complement) number by a power of 2.
The following table will help you see the effects of the three shift operators. (The numbers have been expressed in
binary notation to aid vizualization.)
Example:
true
This operator will still return true if the object being compared is the assignment compatible with the type on the
right.
Example:
class Vehicle {}
true
Section 13.8: The Assignment Operators (=, +=, -=, *=, /=, %=,
<<=, >>= , >>>=, &=, |= and ^=)
The left hand operand for these operators must be a either a non-final variable or an element of an array. The right
hand operand must be assignment compatible with the left hand operand. This means that either the types must be
the same, or the right operand type must be convertible to the left operands type by a combination of boxing,
unboxing or widening. (For complete details refer to JLS 5.2.)
The precise meaning of the "operation and assign" operators is specified by JLS 15.26.2 as:
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)),
where T is the type of E1, except that E1 is evaluated only once.
1.
The simple assignment operator: assigns the value of the right hand operand to the left hand operand.
2. +=
The "add and assign" operator: adds the value of right hand operand to the value of the left hand operand and
assigns the result to left hand operand. If the left hand operand has type String, then this a "concatenate and
assign" operator.
3. -=
The "subtract and assign" operator: subtracts the value of the right operand from the value of the left hand
operand and assign the result to left hand operand.
4. *=
The "multiply and assign" operator: multiplies the value of the right hand operand by the value of the left hand
operand and assign the result to left hand operand. .
5. /=
The "divide and assign" operator: divides the value of the right hand operand by the value of the left hand operand
and assign the result to left hand operand.
6. %=
The "modulus and assign" operator: calculates the modulus of the value of the right hand operand by the value of
the left hand operand and assign the result to left hand operand.
8. >>=
9. >>>=
10. &=
11. |=
12. ^=
|| - the conditional-OR operators. The evaluation of <left-expr> && <right-expr> is equivalent to the
following pseudo-code:
{
boolean L = evaluate(<left-expr>);
if (!L) {
return evaluate(<right-expr>);
} else {
// short-circuit the evaluation of the 2nd operand expression
return true;
}
}
As the pseudo-code above illustrates, the behavior of the short-circuit operators are equivalent to using if / else
statements.
The following example shows the most common usage pattern for the && operator. Compare these two versions of
a method to test if a supplied Integer is zero.
The first version works in most cases, but if the value argument is null, then a NullPointerException will be
thrown.
In the second version we have added a "guard" test. The value != null && value == 0 expression is evaluated by
first performing the value != null test. If the null test succeeds (i.e. it evaluates to true) then the value == 0
expression is evaluated. If the null test fails, then the evaluation of value == 0 is skipped (short-circuited), and we
don't get a NullPointerException.
The following example shows how && can be used to avoid a relatively costly calculation:
- `a < b` tests if the value of `a` is less than the value of `b`.
- `a <= b` tests if the value of `a` is less than or equal to the value of `b`.
- `a > b` tests if the value of `a` is greater than the value of `b`.
- `a >= b` tests if the value of `a` is greater than or equal to the value of `b`.
Relational operators can be used to compare numbers with different types. For example:
int i = 1;
long l = 2;
if (i < l) {
System.out.println("i is smaller");
}
Relational operators can be used when either or both numbers are instances of boxed numeric types. For example:
You need to be careful with relational comparisons that involve floating point numbers:
Expressions that compute floating point numbers often incur rounding errors due to the fact that the
computer floating-point representations have limited precision.
When comparing an integer type and a floating point type, the conversion of the integer to floating point can
also lead to rounding errors.
Finally, Java does bit support the use of relational operators with any types other than the ones listed above. For
example, you cannot use these operators to compare strings, arrays of numbers, and so on.
==
==
operator gives true if the operands are equal and false otherwise. The != operator gives false if the operands are
equal and true otherwise.
These operators can be used operands with primitive and reference types, but the behavior is significantly
different. According to the JLS, there are actually three distinct sets of these operators:
The Boolean
==
and != operators.
The Numeric
==
and != operators.
The Reference
==
and != operators.
==
==
and != operators
==
or != operator is a primitive numeric type (byte, short, char, int, long, float or double), the operator is a numeric
comparison. The second operand must be either a primitive numeric type, or a boxed numeric type.
==
and != operators
If both operands are boolean, or one is boolean and the other is Boolean, these operators the Boolean
==
A B A == B A != B
false false true false
false true false true
true false false true
true true true false
==
If you use
==
or != to compare two Boolean objects, then the Reference operators are used. This may give an unexpected
result; see Pitfall: using == to compare primitive wrappers objects such as Integer
The
==
. For most operand types, this mistake leads to a compilation error. However, for boolean and Boolean
operands the mistake leads to incorrect runtime behavior; see Pitfall - Using '==' to test a boolean
The Reference
==
and != operators
==
and != operators test if the two operands refer to the same object. This often not what you want. To test if two
objects are equal by value, the .equals() method should be used instead.
String s1 = "We are equal";
String s2 = new String("We are equal");
Warning: using
==
==
is false but the result of != is true. Indeed, the test x != x is true if and only if the value of x is NaN.
This behavior is (to most programmers) unexpected. If you test if a NaN value is equal to itself, the answer is "No it
isn't!". In other words,
==
However, this is not a Java "oddity", this behavior is specified in the IEEE 754 floating-point standards, and you will
find that it is implemented by most modern programming languages. (For more information, see
http://stackoverflow.com/a/1573715/139985 ... noting that this is written by someone who was "in the room when
the decisions were made"!)
Version ≥ Java SE 8
a -> a + 1 // a lambda that adds one to its argument
a -> { return a + 1; } // an equivalent lambda using a block.
A lambda expression defines an anonymous function, or more correctly an instance of an anonymous class that
implements a functional interface.
(This example is included here for completeness. Refer to the Lambda Expressions topic for the full treatment.)
It has a minimum value of \u0000 (0 in the decimal representation, also called the null character) and a maximum
value of \uffff (65,535).
In order to define a char of ' value an escape sequence (character preceded by a backslash) has to be used:
It is also possible to add to a char. e.g. to iterate through every lower-case letter, you could do to the following:
default
data type numeric representation range of values
value
Notes:
1. The Java Language Specification mandates that signed integral types (byte through long) use binary twos-
complement representation, and the floating point types use standard IEE 754 binary floating point
representations.
2. Java 8 and later provide methods to perform unsigned arithmetic operations on int and long. While these
methods allow a program to treat values of the respective types as unsigned, the types remain signed types.
3. The smallest floating point shown above are subnormal; i.e. they have less precision than a normal value. The
smallest normal numbers are 1.175494351e?38 and 2.2250738585072014e?308
4. A char conventionally represents a Unicode / UTF-16 code unit.
5. Although a boolean contains just one bit of information, its size in memory varies depending on the Java
Virtual Machine implementation (see boolean type).
Floats handle the five common arithmetical operations: addition, subtraction, multiplication, division, and modulus.
Note: The following may vary slightly as a result of floating point errors. Some results have been rounded for clarity and
readability purposes (i.e. the printed result of the addition example was actually 34.600002).
// addition
float result = 37.2f + -2.6f; // result: 34.6
// subtraction
float result = 45.1f - 10.3f; // result: 34.8
// multiplication
float result = 26.3f * 1.7f; // result: 44.71
// modulus
float result = 37.1f % 4.8f; // result: 3.4999971
Because of the way floating point numbers are stored (i.e. in binary form), many numbers don't have an exact
representation.
While using float is fine for most applications, neither float nor double should be used to store exact
representations of decimal numbers (like monetary amounts), or numbers where higher precision is required.
Instead, the BigDecimal class should be used.
Note: Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NaN are float values. NaN stands for results of
operations that cannot be determined, such as dividing 2 infinite values. Furthermore 0f and -0f are different, but
==
yields true:
float f1 = 0f;
float f2 = -0f;
System.out.println(f1 == f2); // true
System.out.println(1f / f1); // Infinity
System.out.println(1f / f2); // -Infinity
System.out.println(Float.POSITIVE_INFINITY / Float.POSITIVE_INFINITY); // NaN
According to java API: "The Integer class wraps a value of the primitive type int in an object. An object of type
Integer contains a single field whose type is int."
By default, int is a 32-bit signed integer. It can store a minimum value of -231, and a maximum value of 231 - 1.
If you need to store a number outside of this range, long should be used instead. Exceeding the value range of int
leads to an integer overflow, causing the value exceeding the range to be added to the opposite site of the range
(positive becomes negative and vise versa). The value is ((value - MIN_VALUE) % RANGE) + MIN_VALUE, or ((value
+ 2147483648) % 4294967296) - 2147483648
There are two types of conversions: widening conversion and narrowing conversion.
A widening conversion is when a value of one datatype is converted to a value of another datatype that occupies
more bits than the former. There is no issue of data loss in this case.
Correspondingly, A narrowing conversion is when a value of one datatype is converted to a value of another
datatype that occupies fewer bits than the former. Data loss can occur in this case.
Java performs widening conversions automatically. But if you want to perform a narrowing conversion (if you are sure
that no data loss will occur), then you can force Java to perform the conversion using a language construct known
as a cast.
Widening Conversion:
int a = 1;
double d = a; // valid conversion to double, no cast needed (widening)
Narrowing Conversion:
double d = 18.96
int b = d; // invalid conversion to int, will throw a compile-time error
int b = (int) d; // valid conversion to int, but result is truncated (gets rounded down)
// This is type-casting
// Now, b = 18
Boxed objects always require 8 bytes for type and memory management, and because the size of objects is always
a multiple of 8, boxed types all require 16 bytes total. In addition, each usage of a boxed object entails storing a
reference which accounts for another 4 or 8 bytes, depending on the JVM and JVM options.
In data-intensive operations, memory consumption can have a major impact on performance. Memory
consumption grows even more when using arrays: a float[5] array will require only 32 bytes; whereas a Float[5]
storing 5 distinct non-null values will require 112 bytes total (on 64 bit without compressed pointers, this increases
to 152 bytes).
The space overheads of the boxed types can be mitigated to a degree by the boxed value caches. Some of the
boxed types implement a cache of instances. For example, by default, the Integer class will cache instances to
represent numbers in the range -128 to +127. This does not, however, reduce the additional cost arising from the
additional memory indirection.
If you create an instance of a boxed type either by autoboxing or by calling the static valueOf(primitive) method,
the runtime system will attempt to use a cached value. If your application uses a lot of values in the range that is
cached, then this can substantially reduce the memory penalty of using boxed types. Certainly, if you are creating
boxed value instances "by hand", it is better to use valueOf rather than new. (The new operation always creates a
new instance.) If, however, the majority of your values are not in the cached range, it can be faster to call new and
save the cache lookup.
Because of the way floating point numbers are stored, many numbers don't have an exact representation.
While using double is fine for most applications, neither float nor double should be used to store precise numbers
such as currency. Instead, the BigDecimal class should be used
Note: Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN are double values. NaN stands for
results of operations that cannot be determined, such as dividing 2 infinite values. Furthermore 0d and -0d are
different, but
yields true:
double d1 = 0d;
double d2 = -0d;
System.out.println(d1 == d2); // true
System.out.println(1d / d1); // Infinity
System.out.println(1d / d2); // -Infinity
System.out.println(Double.POSITIVE_INFINITY / Double.POSITIVE_INFINITY); // NaN
//an "L" must be appended to the end of the number, because by default,
//numbers are assumed to be the int type. Appending an "L" makes it a long
//as 549755813888 (2 ^ 39) is larger than the maximum value of an int (2^31 - 1),
//"L" must be appended
long bigNumber = 549755813888L;
Note: letter "L" appended at the end of long literal is case insensitive, however it is good practice to use capital as it
is easier to distinct from digit one:
2L == 2l; // true
Warning: Java caches Integer objects instances from the range -128 to 127. The reasoning is explained here:
https://blogs.oracle.com/darcy/entry/boxing_and_caches_integer_valueof
To properly compare 2 Object Long values, use the following code(From Java 1.7 onward):
Comparing a primitive long to an Object long will not result in a false negative like comparing 2 objects with ==
does.
For a unique binary representation of a data type using n bits, values are encoded like this:
The least significant n-1 bits store a positive integral number x in integral representation. Most significant value
stores a bit vith value s. The value repesented by those bits is
x - s * 2n-1
i.e. if the most significant bit is 1, then a value that is just by 1 larger than the number you could represent with the
other bits (2n-2 + 2n-3 + ... + 21 + 20 = 2n-1 - 1) is subtracted allowing a unique binary representation for
each value from - 2n-1 (s = 1; x = 0) to 2n-1 - 1 (s = 0; x = 2n-1 - 1).
This also has the nice side effect, that you can add the binary representations as if they were positive binary
numbers:
v1 = x1 - s1 * 2n-1 v2 = x2 - s2 * 2n-1
s1 s2 x1 + x2 overflow addition result
0 0 No x1 + x2 = v1 + v2
0 0 Yes too large to be represented with data type (overflow)
x1 + x2 - 2n-1 = x1 + x2 - s2 * 2n-1
0 1 No
= v1 + v2
(x1 + x2) mod 2n-1 = x1 + x2 - 2n-1
0 1 Yes
= v1 + v2
1 0 * see above (swap summands)
1 1 No too small to be represented with data type (x1 + x2 - 2n < -2n-1 ; underflow)
(x1 + x2) mod 2n-1 - 2n-1 = (x1 + x2 - 2n-1) - 2n-1
1 1 Yes = (x1 - s1 * 2n-1) + (x2 - s2 * 2n-1)
= v1 + v2
Note that this fact makes finding binary representation of the additive inverse (i.e. the negative value) easy:
Observe that adding the bitwise complement to the number results in all bits being 1. Now add 1 to make value
overflow and you get the neutral element 0 (all bits 0).
So the negative value of a number i can be calculated using (ignoring possible promotion to int here)
(~i) + 1
The result of negating 0, is 11111111. Adding 1 gives a value of 100000000 (9 bits). Because a byte can only store 8
bits, the leftmost value is truncated, and the result is 00000000
}
}
The visibility of the default constructor is the same as the visibility of the class. Thus a class defined package-
privately has a package-private default constructor
However, if you have non-default constructor, the compiler will not generate a default constructor for you. So these
are not equivalent:
Beware that the generated constructor performs no non-standard initialization. This means all fields of your class
will have their default value, unless they have an initializer.
public TestClass() {
testData = "Test"
}
}
class Parent {
private String name;
private int age;
// This does not even compile, because name and age are private,
// making them invisible even to the child class.
class Child extends Parent {
public Child() {
// compiler implicitly calls super() here
name = "John";
age = 42;
}
}
class Parent {
private String name;
private int age;
public Parent(String tName, int tAge) {
name = tName;
age = tAge;
}
}
Note: Calls to another constructor (chaining) or the super constructor MUST be the first statement inside the
constructor.
If you call the super(...) constructor explicitly, a matching parent constructor must exist (that's straightforward,
isn't it?).
class Parent{
public Parent(String tName, int tAge) {}
}
The class Parent has no default constructor, so, the compiler can't add super in the Child constructor. This code will
not compile. You must change the constructors to fit both sides, or write your own super call, like that:
A class can have multiple constructors with different signatures. To chain constructor calls (call a different
constructor of the same class when instantiating) use this().
public TestClass() {
this("Test"); // testData defaults to "Test"
}
}
Whenever it is invoked on the same object more than once during an execution of a Java
application, the hashCode method must consistently return the same integer, provided no
information used in equals comparisons on the object is modified. This integer need not remain
consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode
method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce distinct integer results.
However, the programmer should be aware that producing distinct integer results for unequal
objects may improve the performance of hash tables.
Hash codes are used in hash implementations such as HashMap, HashTable, and HashSet. The result of the hashCode
function determines the bucket in which an object will be put. These hash implementations are more efficient if the
provided hashCode implementation is good. An important property of good hashCode implementation is that the
distribution of the hashCode values is uniform. In other words, there is a small probability that numerous instances
will be stored in the same bucket.
An algorithm for computing a hash code value may be similar to the following:
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
In Java 1.2 and above, instead of developing an algorithm to compute a hash code, one can be generated using
java.util.Arrays#hashCode by supplying an Object or primitives array containing the field values:
@Override
public int hashCode() {
return Arrays.hashCode(new Object[] {field1, field2, field3});
}
Version ≥ Java SE 7
Java 1.7 introduced the java.util.Objects class which provides a convenience method, hash(Object...
objects), that computes a hash code based on the values of the objects supplied to it. This method works just like
java.util.Arrays#hashCode.
@Override
public int hashCode() {
return Objects.hash(field1, field2, field3);
}
Note: this approach is inefficient, and produces garbage objects each time your custom hashCode() method is
called:
A temporary Object[] is created. (In the Objects.hash() version, the array is created by the "varargs"
mechanism.)
If any of the fields are primitive types, they must be boxed and that may create more temporary objects.
The array must be populated.
The array must iterated by the Arrays.hashCode or Objects.hash method.
The calls to Object.hashCode() that Arrays.hashCode or Objects.hash has to make (probably) cannot be
inlined.
Since the calculation of an object's hash code can be expensive, it can be attractive to cache the hash code value
within the object the first time that it is calculated. For example
// Other methods
@Override
public boolean equals(Object obj) {
@Override
public int hashCode() {
int h = hash;
if (h == 0) {
h = Arrays.hashCode(array);
hash = h;
}
return h;
}
}
This approach trades off the cost of (repeatedly) calculating the hash code against the overhead of an extra field to
cache the hash code. Whether this pays off as a performance optimization will depend on how often a given object
is hashed (looked up) and other factors.
You will also notice that if the true hashcode of an ImmutableArray happens to be zero (one chance in 232), the
cache is ineffective.
Finally, this approach is much harder to implement correctly if the object we are hashing is mutable. However,
there are bigger concerns if hash codes change; see the contract above.
@Override
public String toString() {
return firstName + " " + lastName;
}
Here toString() from Object class is overridden in the User class to provide meaningful data regarding the object
when printing it.
When using println(), the object's toString() method is implicitly called. Therefore, these statements do the
same thing:
If the toString() is not overridden in the above mentioned User class, System.out.println(user) may return
User@659e0bfd or a similar String with almost no useful information except the class name. This will be because the
call will use the toString() implementation of the base Java Object class which does not know anything about the
User class's structure or business rules. If you want to change this functionality in your class, simply override the
method.
==
tests for reference equality (whether they are the same object)
.equals() tests for value equality (whether they are logically "equal")
equals() is a method used to compare two objects for equality. The default implementation of the equals()
method in the Object class returns true if and only if both references are pointing to the same instance. It
therefore behaves the same as comparison by
==
.
public class Foo {
int field1, field2;
String field3;
Even though foo1 and foo2 are created with the same fields, they are pointing to two different objects in memory.
The default equals() implementation therefore evaluates to false.
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
@Override
public int hashCode() {
int hash = 1;
hash = 31 * hash + this.field1;
hash = 31 * hash + this.field2;
hash = 31 * hash + (field3 == null ? 0 : field3.hashCode());
return hash;
}
Here the overridden equals() method decides that the objects are equal if their fields are the same.
Notice that the hashCode() method was also overwritten. The contract for that method states that when two
objects are equal, their hash values must also be the same. That's why one must almost always override
hashCode() and equals() together.
Pay special attention to the argument type of the equals method. It is Object obj, not Foo obj. If you put the latter
in your method, that is not an override of the equals method.
When writing your own class, you will have to write similar logic when overriding equals() and hashCode(). Most
IDEs can automatically generate this for you.
An example of an equals() implementation can be found in the String class, which is part of the core Java API.
Rather than comparing pointers, the String class compares the content of the String.
Version ≥ Java SE 7
Java 1.7 introduced the java.util.Objects class which provides a convenience method, equals, that compares two
potentially null references, so it can be used to simplify implementations of the equals method.
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
Class Comparison
Since the equals method can run against any object, one of the first things the method often does (after checking
for null) is to check if the class of the object being compared matches the current class.
@Override
public boolean equals(Object obj) {
//...check for null
if (getClass() != obj.getClass()) {
return false;
}
//...compare fields
}
This is typically done as above by comparing the class objects. However, that can fail in a few special cases which
may not be obvious. For example, some frameworks generate dynamic proxies of classes and these dynamic
proxies are actually a different class. Here is an example using JPA.
One mechanism to work around that limitation is to compare classes using instanceof
@Override
public final boolean equals(Object obj) {
if (!(obj instanceof Foo)) {
return false;
}
//...compare fields
}
However, there are a few pitfalls that must be avoided when using instanceof. Since Foo could potentially have
other subclasses and those subclasses might override equals() you could get into a case where a Foo is equal to a
FooSubclass but the FooSubclass is not equal to Foo.
This violates the properties of symmetry and transitivity and thus is an invalid implementation of the equals()
method. As a result, when using instanceof, a good practice is to make the equals() method final (as in the
above example). This will ensure that no subclass overrides equals() and violates key assumptions.
package com.example.examples.object;
import java.util.concurrent.atomic.AtomicBoolean;
while (!aHasFinishedWaiting.get()) {
synchronized (obj) {
// notify ONE thread which has called obj.wait()
obj.notify();
}
}
}
};
threadA.join();
threadB.join();
System.out.println("Finished!");
}
}
The getClass() method will return the most specific class type, which is why when getClass() is called on
anotherSpecificUser, the return value is class SpecificUser because that is lower down the inheritance tree
than User.
The actual static type returned by a call to getClass is Class<? extends T> where T is the static type of the object
on which getClass is called.
For the method to be used all classes calling the method must implement the Cloneable interface.
The Cloneable interface itself is just a tag interface used to change the behaviour of the native clone() method
which checks if the calling objects class implements Cloneable. If the caller does not implement this interface a
CloneNotSupportedException will be thrown.
The Object class itself does not implement this interface so a CloneNotSupportedException will be thrown if the
calling object is of class Object.
For a clone to be correct it should be independent of the object it is being cloned from, therefore it may be
necessary to modify the object before it gets returned. This means to essentially create a "deep copy" by also
copying any of the mutable objects that make up the internal structure of the object being cloned. If this is not
implemented correctly the cloned object will not be independent and have the same references to the mutable
objects as the object that it was cloned from. This would result in inconsistent behaviour as any changes to those in
one would affect the other.
} catch (CloneNotSupportedException e) {
// in case any of the cloned mutable fields do not implement Cloneable
throw new AssertionError(e);
}
}
}
If you do not specify the call to super() in a constructor the compiler will put it in for you.
public MyClass() {
super();
}
}
public MyClass() {
// empty
}
}
doSomethingWith(size);
this(initialValues.size());
addInitialValues(initialValues);
}
}
Calling new MyClass(Arrays.asList("a", "b", "c")) will call the second constructor with the List-argument,
which will in turn delegate to the first constructor (which will delegate implicitly to super()) and then call
addInitialValues(int size) with the second size of the list. This is used to reduce code duplication where
multiple constructors need to do the same work.
Given the example above, one can either call new MyClass("argument") or new MyClass("argument", 0). In other
words, much like method overloading, you just call the constructor with the parameters that are necessary for your
chosen constructor.
Nothing more than would happen in a sub-class that has a default empty constructor (minus the call to super()).
The default empty constructor can be explicitly defined but if not the compiler will put it in for you as long as no
other constructors are already defined.
The actual creation of objects is down to the JVM. Every constructor in Java appears as a special method named
<init> which is responsible for instance initializing. This <init> method is supplied by the compiler and because
<init> is not a valid identifier in Java, it cannot be used directly in the language.
The JVM will invoke the <init> method using the invokespecial instruction and can only be invoked on
uninitialized class instances.
For more information take a look at the JVM specification and the Java Language Specification:
According to the doc, this method gets called by the garbage collector on an object when garbage
collection determines that there are no more references to the object.
But there are no guarantees that finalize() method would gets called if the object is still reachable or no Garbage
Collectors run when the object become eligible. That's why it's better not rely on this method.
In Java core libraries some usage examples could be found, for instance in FileInputStream.java:
In this case it's the last chance to close the resource if that resource has not been closed before.
Generally it's considered bad practice to use finalize() method in applications of any kind and should be avoided.
Finalizers are not meant for freeing resources (e.g., closing files). The garbage collector gets called when (if!) the
system runs low on heap space. You can't rely on it to be called when the system is running low on file handles or,
for any other reason.
The intended use-case for finalizers is for an object that is about to be reclaimed to notify some other object about
its impending doom. A better mechanism now exists for that purpose---the java.lang.ref.WeakReference<T>
class. If you think you need write a finalize() method, then you should look into whether you can solve the same
problem using WeakReference instead. If that won't solve your problem, then you may need to re-think your design
on a deeper level.
For further reading here is an Item about finalize() method from "Effective Java" book by Joshua Bloch.
An annotation is a marker which associates information with a program construct, but has no effect at
run time.
Annotations may appear before types or declarations. It is possible for them to appear in a place where they could
apply to both a type or a declaration.
What exactly an annotation applies to is governed by the "meta-annotation" @Target. See "Defining annotation
types" for more information.
Annotations are used for a multitude of purposes. Frameworks like Spring and Spring-MVC make use of
annotations to define where Dependencies should be injected or where requests should be routed.
Other frameworks use annotations for code-generation. Lombok and JPA are prime examples, that use annotations
to generate Java (and SQL) code.
@interface MyAnnotation {
String param1();
boolean param2();
int[] param3(); // array parameter
}
Default values
@interface MyAnnotation {
String param1() default "someValue";
boolean param2() default true;
int[] param3() default {};
}
Meta-Annotations
Meta-annotations are annotations that can be applied to annotation types. Special predefined meta-annotation
define how annotation types can be used.
The @Target meta-annotation restricts the types the annotation can be applied to.
@Target(ElementType.METHOD)
@interface MyAnnotation {
// this annotation can only be applied to methods
}
Multiple values can be added using array notation, e.g. @Target({ElementType.FIELD, ElementType.TYPE})
Available Values
ElementType target example usage on target element
@Retention(RetentionPolicy.RUNTIME) terface
ANNOTATION_TYPE annotation types
MyAnnotation
CONSTRUCTOR constructors @MyAnnotationlic MyClass() {}
FIELD fields, enum constants @XmlAttributevate int count;
for (@LoopVariable int i = 0; i < 100; i++) { @Unused
variable declarations inside
LOCAL_VARIABLE String resultVariable;
methods
}
package (in package-
PACKAGE @Deprecatedkage very.old;
info.java)
METHOD methods @XmlElementlic int getCount() {...}
public Rectangle( @NamedArg("width") double width,
method/constructor @NamedArg("height") double height) {
PARAMETER
parameters ...
}
TYPE classes, interfaces, enums @XmlRootElementlic class Report {}
Version ≥ Java SE 8
ElementType target example usage on target element
TYPE_PARAMETER Type parameter declarations public <@MyAnnotation T> void f(T t) {}
TYPE_USE Use of a type Object o = "42";ing s = (@MyAnnotation String) o;
@Retention
The @Retention meta-annotation defines the annotation visibility during the applications compilation process or
execution. By default, annotations are included in .class files, but are not visible at runtime. To make an
annotation accessible at runtime, RetentionPolicy.RUNTIME has to be set on that annotation.
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
// this annotation can be accessed with reflections at runtime
}
Available values
RetentionPolicy Effect
CLASS The annotation is available in the .class file, but not at runtime
RUNTIME The annotation is available at runtime and can be accessed via reflection
The annotation is available at compile time, but not added to the .class files. The annotation can
SOURCE
be used e.g. by an annotation processor.
@Documented
The @Documented meta-annotation is used to mark annotations whose usage should be documented by API
documentation generators like javadoc. It has no values. With @Documented, all classes that use the annotation will
list it on their generated documentation page. Without @Documented, it's not possible to see which classes use the
annotation in the documentation.
@Inherited
For a non-inherited annotation, the query only examines the class being examined.
For an inherited annotation, the query will also check the super-class chain (recursively) until an instance of
the annotation is found.
Note that only the super-classes are queried: any annotations attached to interfaces in the classes hierarchy will be
ignored.
@Repeatable
The @Repeatable meta-annotation was added in Java 8. It indicates that multiple instances of the annotation can be
attached to the annotation's target. This meta-annotation has no values.
@interface MyDefaultAnnotation {
@Retention(RetentionPolicy.RUNTIME)
@interface MyRuntimeVisibleAnnotation {
@MyDefaultAnnotation
static class RuntimeCheck1 {
}
@MyRuntimeVisibleAnnotation
static class RuntimeCheck2 {
}
@Override
Concrete superclass
Abstract class
class Logger1 {
public void log(String logString) {
System.out.prinln(logString);
}
}
class Logger2 {
// This will throw compile-time error. Logger2 is not a subclass of Logger1.
// log method is not overriding anything
@Override
public void log(String logString) {
System.out.println("Log 2" + logString);
}
}
The main purpose is to catch mistyping, where you think you are overriding a method, but are actually defining a
new one.
class Vehicle {
public void drive() {
System.out.println("I am driving");
}
}
In Java 5, it meant that the annotated method had to override a non-abstract method declared in the
superclass chain.
From Java 6 onward, it is also satisfied if the annotated method implements an abstract method declared in
the classes superclass / interface hierarchy.
(This can occasionally cause problems when back-porting code to Java 5.)
@Deprecated
This marks the method as deprecated. There can be several reasons for this:
The specific reason for deprecation can usually be found in the documentation of the API.
The annotation will cause the compiler to emit an error if you use it. IDEs may also highlight this method somehow
as deprecated
class ComplexAlgorithm {
@Deprecated
public void oldSlowUnthreadSafeMethod() {
// stuff here
}
@SuppressWarnings
In almost all cases, when the compiler emits a warning, the most appropriate action is to fix the cause. In some
instances (Generics code using untype-safe pre-generics code, for example) this may not be possible and it's better
to suppress those warnings that you expect and cannot fix, so you can more clearly see unexpected warnings.
This annotation can be applied to a whole class, method or line. It takes the category of warning as a parameter.
@SuppressWarnings("deprecation")
@SuppressWarning("finally")
public boolean checkData() {
// method calling return from within finally block
}
It is better to limit the scope of the annotation as much as possible, to prevent unexpected warnings also being
suppressed. For example, confining the scope of the annotation to a single-line:
The warnings supported by this annotation may vary from compiler to compiler. Only the unchecked and
deprecation warnings are specifically mentioned in the JLS. Unrecognized warning types will be ignored.
@SafeVarargs
Because of type erasure, void method(T... t) will be converted to void method(Object[] t) meaning that the
compiler is not always able to verify that the use of varargs is type-safe. For instance:
There are instances where the use is safe, in which case you can annotate the method with the SafeVarargs
annotation to suppress the warning. This obviously hides the warning if your use is unsafe too.
@FunctionalInterface
This is an optional annotation used to mark a FunctionalInterface. It will cause the compiler to complain if it does
not conform to the FunctionalInterface spec (has a single abstract method)
@FunctionalInterface
public interface ITrade {
public boolean check(Trade t);
}
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
The annotation
The @Setter annotation is a marker can be applied to methods. The annotation will be discarded during
compilation not be available afterwards.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Setter {
}
The SetterProcessor class is used by the compiler to process the annotations. It checks, if the methods annotated
with the @Setter annotation are public, non-static methods with a name starting with set and having a
uppercase letter as 4th letter. If one of these conditions isn't met, a error is written to the Messager. The compiler
writes this to stderr, but other tools could use this information differently. E.g. the NetBeans IDE allows the user
specify annotation processors that are used to display error messages in the editor.
package annotation.processor;
import annotation.Setter;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes({"annotation.Setter"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SetterProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// get elements annotated with the @Setter annotation
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(Setter.class);
@Override
public void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
Packaging
To be applied by the compiler, the annotation processor needs to be made available to the SPI (see ServiceLoader).
annotation.processor.SetterProcessor
The following class is example class in the default package with the annotations being applied to the correct
elements according to the retention policy. However only the annotation processor only considers the second
method a valid annotation target.
import annotation.Setter;
@Setter
@Setter
public void setString(String value) {}
@Setter
public static void main(String[] args) {}
If the annotation processor is discovered using the SPI, it is automatically used to process annotated elements. E.g.
compiling the AnnotationProcessorTest class using
This could be prevented by specifying the -proc:none option for javac. You could also forgo the usual compilation
by specifying -proc:only instead.
IDE integration
Netbeans
Annotation processors can be used in the NetBeans editor. To do this the annotation processor needs to be
specified in the project settings:
2. add check marks for Enable Annotation Processing and Enable Annotation Processing in Editor
4. in the popup that appears enter the fully qualified class name of the annotation processor and click Ok.
Result
// Author.java
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
String value();
}
// Authors.java
@Retention(RetentionPolicy.RUNTIME)
public @interface Authors {
Author[] value();
}
// Test.java
@Authors({
@Author("Mary"),
@Author("Sam")
})
public class Test {
public static void main(String[] args) {
Author[] authors = Test.class.getAnnotation(Authors.class).value();
for (Author author : authors) {
System.out.println(author.value());
// Output:
// Mary
// Sam
}
}
}
Version ≥ Java SE 8
Java 8 provides a cleaner, more transparent way of using container annotations, using the @Repeatable annotation.
First we add this to the Author class:
@Repeatable(Authors.class)
This tells Java to treat multiple @Author annotations as though they were surrounded by the @Authors container.
We can also use Class.getAnnotationsByType() to access the @Author array by its own class, instead of through its
@Author("Mary")
@Author("Sam")
public class Test {
public static void main(String[] args) {
Author[] authors = Test.class.getAnnotationsByType(Author.class);
for (Author author : authors) {
System.out.println(author.value());
// Output:
// Mary
// Sam
}
}
}
Example
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedAnnotationType {
}
and
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UninheritedAnnotationType {
}
@UninheritedAnnotationType
class A {
}
@InheritedAnnotationType
class B extends A {
}
class C extends B {
}
System.out.println(new A().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println(new B().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println(new C().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println("_________________________________");
System.out.println(new A().getClass().getAnnotation(UninheritedAnnotationType.class));
will print a result similar to this (depending on the packages of the annotation):
null
@InheritedAnnotationType()
@InheritedAnnotationType()
_________________________________
@UninheritedAnnotationType()
null
null
Note that annotations can only be inherited from classes, not interfaces.
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String key() default "foo";
String value() default "bar";
}
class AnnotationExample {
// Put the Annotation on the method, but leave the defaults
@MyAnnotation
public void testDefaults() throws Exception {
// Using reflection, get the public method "testDefaults", which is this method with no args
Method method = AnnotationExample.class.getMethod("testDefaults", null);
foo = bar
baz = buzz
The receiver parameter is an optional syntactic device for an instance method or an inner class's
constructor. For an instance method, the receiver parameter represents the object for which the method
is invoked. For an inner class's constructor, the receiver parameter represents the immediately enclosing
instance of the newly constructed object. Either way, the receiver parameter exists solely to allow the type
of the represented object to be denoted in source code, so that the type may be annotated. The receiver
parameter is not a formal parameter; more precisely, it is not a declaration of any kind of variable
(§4.12.3), it is never bound to any value passed as an argument in a method invocation expression or
qualified class instance creation expression, and it has no effect whatsoever at run time.
The following example illustrates the syntax for both kinds of receiver parameter:
The sole purpose of receiver parameters is to allow you to add annotations. For example, you might have a custom
annotation @IsOpen whose purpose is to assert that a Closeable object has not been closed when a method is
called. For example:
At one level, the @IsOpen annotation on this could simply serve as documentation. However, we could potentially
do more. For example:
An annotation processor could insert a runtime check that this is not in closed state when update is called.
A code checker could perform a static code analysis to find cases where this could be closed when update is
called.
The value parameter is an array of Strings. You can set multiple values by using a notation similar to Array
initializers:
@SuppressWarnings({"unused"})
@SuppressWarnings({"unused", "javadoc"})
If you only need to set a single value, the brackets can be omitted:
@SuppressWarnings("unused")
By having an immutable object, one can ensure that all threads that are looking at the object will be seeing the
same state, as the state of an immutable object will not change.
1. Don't provide "setter" methods - methods that modify fields or objects referred to by fields.
2. Make all fields final and private.
3. Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A
more sophisticated approach is to make the constructor private and construct instances in factory methods.
4. If the instance fields include references to mutable objects, don't allow those objects to be changed:
5. Don't provide methods that modify the mutable objects.
6. Don't share references to the mutable objects. Never store references to external, mutable objects passed to
the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of
your internal mutable objects when necessary to avoid returning the originals in your methods.
class Point {
private int x, y;
//...
One way to deal with this is to create an immutable wrapper for the mutable type. Here is a simple wrapper for an
array of integers
This class works by using defensive copying to isolate the mutable state (the int[]) from any code that might mutate
it:
The constructor uses clone() to create a distinct copy of the parameter array. If the caller of the constructor
subsequent changed the parameter array, it would not affect the state of the ImmutableIntArray.
The getValue() method also uses clone() to create the array that is returned. If the caller were to change
the result array, it would not affect the state of the ImmutableIntArray.
We could also add methods to ImmutableIntArray to perform read-only operations on the wrapped array; e.g. get
its length, get the value at a particular index, and so on.
Note that an immutable wrapper type implemented this way is not type compatible with the original type. You
cannot simply substitute the former for the latter.
A variation on this is to declare the constructor as private and provide a public static factory method instead.
Immutability does not prevent object from being nullable; e.g. null can be assigned to a String variable.
If an immutable classes properties are declared as final, instances are inherently thread-safe. This makes
immutable classes a good building block for implementing multi-threaded applications.
The following snippet shows that the above class is not immutable:
import java.util.List;
import java.util.ArrayList;
public final class Names {
private final List<String> names;
public Names(List<String> names) {
this.names = new ArrayList<String>(names);
}
public List<String> getNames() {
return names;
}
public int size() {
return names.size();
}
}
Names class seems immutable at the first sight, but it is not as the following code shows:
This happened because a change to the reference List returned by getNames() can modify the actual list of Names.
To fix this, simply avoid returning references that reference class's mutable objects either by making defensive
copies, as follows:
or by designing getters in way that only other immutable objects and primitives are returned, as follows:
Injecting constructor with object(s) that can be modified outside the immutable class
This is a variation of the previous flaw. Take a look at the following class:
import java.util.List;
public final class NewNames {
private final List<String> names;
public Names(List<String> names) {
this.names = names;
}
public String getName(int index) {
return names.get(index);
}
public int size() {
return names.size();
}
}
As Names class before, also NewNames class seems immutable at the first sight, but it is not, in fact the following
snippet proves the contrary:
To fix this, as in the previous flaw, simply make defensive copies of the object without assigning it directly to the
immutable class, i.e. constructor can be changed as follows:
Person class seems immutable at the first sight, but suppose a new subclass of Person is defined:
now Person (im)mutability can be exploited through polymorphism by using the new subclass:
To fix this, either mark the class as final so it cannot be extended or declare all of its constructor(s) as private.
class SomeClass {
private int variable;
public Test(){
}
}
Now let's try to create an instance of the class. In this example, we can access number because it is public.
package javax.swing;
public abstract class JComponent extends Container … {
…
static boolean DEBUG_GRAPHICS_LOADED;
…
}
package javax.swing;
public class DebugGraphics extends Graphics {
…
static {
JComponent.DEBUG_GRAPHICS_LOADED = true;
}
…
}
As an example:
package com.stackexchange.docs;
public class MyClass{
protected int variable; //This is the variable that we are trying to access
public MyClass(){
variable = 2;
};
}
Now we'll extend this class and try to access one of its protected members.
package some.other.pack;
import com.stackexchange.docs.MyClass;
public class SubClass extends MyClass{
public SubClass(){
super();
System.out.println(super.variable);
}
}
You would be also able to access a protected member without extending it if you are accessing it from the same
package.
Note that this modifier only works on members of a class, not on the class itself.
There was once a private protected (both keywords at once) modifier that could be applied to methods or
variables to make them accessible from a subclass outside the package, but make them private to the classes in
that package. However, this was removed in Java 1.0's release.
public class X {
}
class Y {
}
}
Interface members always have public visibility, even if the public keyword is omitted. So both foo(), bar(), TEXT,
ANSWER, X, and Y have public visibility. However, access may still be limited by the containing interface - since
MyInterface has public visibility, its members may be accessed from anywhere, but if MyInterface had had
package visibility, its members would only have been accessible from within the same package.
This example uses generic class Param to take a single type parameter T, delimited by angle brackets (<>):
public T getValue() {
return value;
}
To instantiate this class, provide a type argument in place of T. For example, Integer:
The type argument can be any reference type, including arrays and other generic types:
Param<String[]> stringArrayParam;
Param<int[][]> int2dArrayParam;
Param<Param<Object>> objectNestedParam;
In Java SE 7 and later, the type argument can be replaced with an empty set of type arguments (<>) called the
diamond:
Version ≥ Java SE 7
Param<Integer> integerParam = new Param<>();
Unlike other identifiers, type parameters have no naming constraints. However their names are commonly the first
letter of their purpose in upper case. (This is true even throughout the official JavaDocs.)
Examples include T for "type", E for "element" and K/V for "key"/"value".
public T getValue() {
return value;
}
AbstractParam is an abstract class declared with a type parameter of T. When extending this class, that type
parameter can be replaced by a type argument written inside <>, or the type parameter can remain unchanged. In
the first and second examples below, String and Integer replace the type parameter. In the third example, the
type parameter remains unchanged. The fourth example doesn't use generics at all, so it's similar to if the class had
an Object parameter. The compiler will warn about AbstractParam being a raw type, but it will compile the
ObjectParam class. The fifth example has 2 type parameters (see "multiple type parameters" below), choosing the
second parameter as the type parameter passed to the superclass.
Notice that in the Email class, the T getValue() method acts as if it had a signature of String getValue(), and the
void setValue(T) method acts as if it was declared void setValue(String).
It is also possible to instantiate with anonymous inner class with an empty curly braces ({}):
Java provides the ability to use more than one type parameter in a generic class or interface. Multiple type
parameters can be used in a class or interface by placing a comma-separated list of types between the angle
brackets. Example:
public T getFirstParam() {
return firstParam;
}
public S getSecondParam() {
return secondParam;
}
? extends T represents an upper bounded wildcard. The unknown type represents a type that must be a
subtype of T, or type T itself.
? super T represents a lower bounded wildcard. The unknown type represents a type that must be a
supertype of T, or type T itself.
class Shoe {}
class IPhone {}
interface Fruit {}
class Apple implements Fruit {}
class Banana implements Fruit {}
class GrannySmith extends Apple {}
Choosing the right T, ? super T or ? extends T is necessary to allow the use with subtypes. The compiler can then
ensure type safety; you should not need to cast (which is not type safe, and may cause programming errors) if you
use them properly.
Java 7 introduced the Diamond1 to remove some boiler-plate around generic class instantiation. With Java 7+ you
can write:
One limitation is for Anonymous Classes, where you still must provide the type parameter in the instantiation:
Although using the diamond with Anonymous Inner Classes is not supported in Java 7 and 8, it will be included as
a new feature in Java 9.
Footnote:
1 - Some people call the <> usage the "diamond operator". This is incorrect. The diamond does not behave as an
operator, and is not described or listed anywhere in the JLS or the (official) Java Tutorials as an operator. Indeed, <>
is not even a distinct Java token. Rather it is a < token followed by a > token, and it is legal (though bad style) to have
whitespace or comments between the two. The JLS and the Tutorials consistently refer to <> as "the diamond", and
that is therefore the correct term for it.
Notice that we don't have to pass an actual type argument to a generic method. The compiler infers the type
argument for us, based on the target type (e.g. the variable we assign the result to), or on the types of the actual
arguments. It will generally infer the most specific type argument that will make the call type-correct.
Sometimes, albeit rarely, it can be necessary to override this type inference with explicit type arguments:
void usage() {
consumeObjects(this.<Object>makeList("Jeff", "Atwood").stream());
}
It's necessary in this example because the compiler can't "look ahead" to see that Object is desired for T after
calling stream() and it would otherwise infer String based on the makeList arguments. Note that the Java
language doesn't support omitting the class or object on which the method is called (this in the above example)
when type arguments are explicitly provided.
Example: we want to sort a list of numbers but Number doesn't implement Comparable.
In this example T must extend Number and implement Comparable<T> which should fit all "normal" built-in number
implementations like Integer or BigDecimal but doesn't fit the more exotic ones like Striped64.
Since multiple inheritance is not allowed, you can use at most one class as a bound and it must be the first listed.
For example, <T extends Comparable<T> & Number> is not allowed because Comparable is an interface, and not a
class.
Generic parameterization on a class can be inspected by creating an anonymous inner class. This class will capture
the type information. In general this mechanism is referred to as super type tokens, which are detailed in Neal
Gafter's blog post.
Implementations
Guava's TypeToken
Spring's ParameterizedTypeReference
Jackson's TypeReference
Example usage
A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing
compile-time errors is easier than fixing runtime errors, which can be difficult to find.
Elimination of casts
When re-written to use generics, the code does not require casting:
By using generics, programmers can implement generic algorithms that work on collections of different types, can
be customized, and are type safe and easier to read.
The type T is erased. Since, at runtime, the JVM does not know what T originally was, it does not know which
constructor to call.
Workarounds
genericMethod(String.class);
Which throws exceptions, since there is no way to know if the passed class has an accessible default
constructor.
Version ≥ Java SE 8
genericMethod(String::new);
Without bounded generics, we cannot make a container class that is both generic and knows that each element is
an animal:
public AnimalContainer() {
col = new ArrayList<T>();
}
public BoundedAnimalContainer() {
col = new ArrayList<T>();
}
// Legal
AnimalContainer<Cat> a = new AnimalContainer<Cat>();
// Legal
AnimalContainer<String> a = new AnimalContainer<String>();
Assume we have a DataSeries<T> type (interface here), which defines a generic data series containing values of
type T. It is cumbersome to work with this type directly when we want to perform a lot of operations with e.g.
double values, so we define DoubleSeries extends DataSeries<Double>. Now assume, the original DataSeries<T>
type has a method add(values) which adds another series of the same length and returns a new one. How do we
enforce the type of values and the type of the return to be DoubleSeries rather than DataSeries<Double> in our
derived class?
The problem can be solved by adding a generic type parameter referring back to and extending the type being
declared (applied to an interface here, but the same stands for classes):
Here T represents the data type the series holds, e.g. Double and DS the series itself. An inherited type (or types) can
now be easily implemented by substituting the above mentioned parameter by a corresponding derived type, thus,
yielding a concrete Double-based definition of the form:
At this moment even an IDE will implement the above interface with correct types in place, which, after a bit of
content filling may look like this:
DoubleSeriesImpl(Collection<Double> data) {
this.data = new ArrayList<>(data);
}
@Override
@Override
public List<Double> data() {
return Collections.unmodifiableList(data);
}
}
As you can see the add method is declared as DoubleSeries add(DoubleSeries values) and the compiler is
happy.
Let's say you want to create a class whose Generic type should implement both Flushable and Closeable, you can
write
Now, the ExampleClass only accepts as generic parameters, types which implement both Flushable and
Closeable.
ExampleClass<Console> arg4; // Does NOT work because Console only implements Flushable
ExampleClass<ZipFile> arg5; // Does NOT work because ZipFile only implements Closeable
ExampleClass<Flushable> arg2; // Does NOT work because Closeable bound is not satisfied.
ExampleClass<Closeable> arg3; // Does NOT work because Flushable bound is not satisfied.
The class methods can choose to infer generic type arguments as either Closeable or Flushable.
/* You can even invoke the methods of any valid type directly. */
public void test2 (T param) {
param.flush(); // Method of Flushable called on T and works fine.
param.close(); // Method of Closeable called on T and works fine too.
Note:
You cannot bind the generic parameter to either of the type using OR (|) clause. Only the AND (&) clause is
supported. Generic type can extends only one class and many interfaces. Class must be placed at the beginning of
the list.
The method will compile with a warning. The code is actually more safe than it looks because the Java runtime will
do a cast when you use it:
Here, the cast will work when the returned type is any kind of List (i.e. returning List<String> would not trigger a
ClassCastException; you'd eventually get it when taking elements out of the list).
To work around this problem, you can create an API which uses typed keys:
With this approach, you can't put the wrong type into the map, so the result will always be correct (unless you
accidentally create two keys with the same name but different types).
Related:
Type-safe Map
Consider the following generic class Example declared with the formal parameter <T>:
class Example<T> {
public boolean isTypeAString(String s) {
return s instanceof T; // Compilation error, cannot use T as class type here
}
This will always give a Compilation error because as soon as the compiler compiles the Java source into Java
bytecode it applies a process known as type erasure, which converts all generic code into non-generic code, making
impossible to distinguish among T types at runtime. The type used with instanceof has to be reifiable, which
means that all information about the type has to be available at runtime, and this is usually not the case for generic
types.
The following class represents what two different classes of Example, Example<String> and Example<Number>, look
like after generics has stripped off by type erasure:
Since types are gone, it's not possible for the JVM to know which type is T.
You can always use unbounded wildcard (?) for specifying a type in the instanceof as follows:
The other side of the coin is that using an instance t of T with instanceof is legal, as shown in the following
example:
class Example<T> {
public boolean isTypeAString(T t) {
return t instanceof String; // No compilation error this time
}
}
because after the type erasure the class will look like the following:
Since, even if the type erasure happen anyway, now the JVM can distinguish among different types in memory, even
if they use the same reference type (Object), as the following snippet shows:
Choose a specific type to replace the formal type parameter <T> of MyGenericClass and implement it, as the
following example does:
This class only deals with String, and this means that using MyGenericInterface with different parameters (e.g.
Integer, Object etc.) won't compile, as the following snippet shows:
Declare another generic interface with the formal type parameter <T> which implements MyGenericInterface, as
follows:
Note that a different formal type parameter may have been used, as follows:
Declare a non-generic class which implements MyGenericInteface as a raw type (not using generic at all), as follows:
This way is not recommended, since it is not 100% safe at runtime because it mixes up raw type (of the subclass)
with generics (of the interface) and it is also confusing. Modern Java compilers will raise a warning with this kind of
implementation, nevertheless the code - for compatibility reasons with older JVM (1.4 or earlier) - will compile.
All the ways listed above are also allowed when using a generic class as a supertype instead of a generic interface.
Class ? A class can be defined as a template/blueprint that describes the behavior/state that the object of its type
support.
The advantage is that the same functionality is called with two different numbers of inputs. While invoking the
method according to the input we are passing, (In this case either one string value or two string values) the
corresponding method is executed.
Note: Methods cannot be overloaded by changing just the return type (int method() is considered the same as String
method() and will throw a RuntimeException if attempted). If you change the return type you must also change the
parameters in order to overload.
Method Overloading
Method overloading (also known as static Polymorphism) is a way you can have two (or more) methods (functions)
with same name in a single class. Yes its as simple as that.
This way user can call the same method for area depending on the type of shape it has.
But the real question now is, how will java compiler will distinguish which method body is to be executed?
Well Java have made it clear that even though the method names (area() in our case) can be same but the
arguments method is taking should be different.
Overloaded methods must have different arguments list (quantity and types).
That being said we cannot add another method to calculate area of a square like this : public Double area(Long
side) because in this case, it will conflict with area method of circle and will cause ambiguity for java compiler.
Thank god, there are some relaxations while writing overloaded methods like
Well that's because which overloaded methods is to be invoked is decided at compile time, based on the actual
number of arguments and the compile-time types of the arguments.
Method Overriding
Well, method overriding (yes you guess it right, it is also known as dynamic polymorphism) is somewhat more
interesting and complex topic.
In method overriding we overwrite the method body provided by the parent class. Got it? No? Let's go through an
example.
So we have a class called Shape and it has method called area which will probably return the area of the shape.
Let's say now we have two classes called Circle and Rectangle.
// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return 3.14 * radius * radius;
}
}
// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return length * breadth;
}
So, now both of your children classes have updated method body provided by the parent (Shape) class. Now
question is how to see the result? Well lets do it the old psvm way.
// Drumbeats ......
//This should print 78.5
System.out.println("Shape of circle : "+circle.area());
}
}
Wow! isn't it great? Two objects of same type calling same methods and returning different values. My friend, that's
the power of dynamic polymorphism.
It is important to understand that constructors are different from methods in several ways:
1. Constructors can only take the modifiers public, private, and protected, and cannot be declared abstract,
final, static, or synchronized.
3. Constructors MUST be named the same as the class name. In the Hello example, the Hello object's
constructor name is the same as the class name.
4. The this keyword has an additional usage inside constructors. this.method(...) calls a method on the
current instance, while this(...) refers to another constructor in the current class with different signatures.
Constructors also can be called through inheritance using the keyword super.
public SuperManClass(){
// some implementation
}
// ... methods
}
static {
Set<String> set = new HashSet<>();
set.add("Hello");
set.add("World");
set.add("foo");
set.add("bar");
set.add("42");
WORDS = Collections.unmodifiableSet(set);
}
}
public Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}
Objects are instances of their class. So, the way you would create an object would be by calling the Car class in
one of two ways in your main class (main method in Java or onCreate in Android).
Option 1
Option 1 is where you essentially tell the program everything about the Car upon creation of the object. Changing
any property of the car would require calling one of the methods such as the repaintCar method. Example:
newCar.repaintCar("Blue");
Note: Make sure you pass the correct data type to the method. In the example above, you may also pass a variable
to the repaintCar method as long as the data type is correct`.
That was an example of changing properties of an object, receiving properties of an object would require using a
method from the Car class that has a return value (meaning a method that is not void). Example:
Option 1 is the best option when you have all the object's data at the time of creation.
Option 2
Option 2 gets the same effect but required more work to create an object correctly. I want to recall this Constructor
in the Car class:
Notice that you do not have to actually pass any parameters into the object to create it. This is very useful for when
you do not have all the aspects of the object but you need to use the parts that you do have. This sets generic data
into each of the instance variables of the object so that, if you call for a piece of data that does not exist, no errors
are thrown.
This is a common mistake amongst objects that are not initialized with all their data. Errors were avoided because
there is a Constructor that allows an empty Car object to be created with stand-in variables (public Car(){}), but
no part of the myCar was actually customized. Correct example of creating Car Object:
And, as a reminder, get an object's properties by calling a method in your main class. Example:
A class consists at a minimum of the class keyword, a name, and a body, which might be empty.
class ObjectMemberVsStaticMember {
void increment() {
staticCounter ++;
memberCounter++;
}
}
o1.increment();
o2.increment();
o2.increment();
System.out.println("ObjectMemberVsStaticMember.staticCounter = " +
ObjectMemberVsStaticMember.staticCounter);
o1 static counter 3
o1 member counter 1
o2 static counter 3
o2 member counter 2
ObjectMemberVsStaticMember.staticCounter = 3
Note: You should not call static members on objects, but on classes. While it does not make a difference for the
JVM, human readers will appreciate it.
static members are part of the class and exists only once per class. Non-static members exist on instances, there
is an independent copy for each instance. This also means that you need access to an object of that class to access
its members.
And the use thereof, which (notably) does not at all acknowledge the existence of the nested class.
//prints: 0, 1, 2, 3, 4,
for(int i = 0; i < 5; i++) {
System.out.print(s.pop() + ", ");
}
}
}
Or non-static:
At its core, static nested classes do not have a surrounding instance of the outer class, whereas non-static nested
classes do. This affects both where/when one is allowed to instantiate a nested class, and what instances of those
nested classes are allowed to access. Adding to the above example:
private StaticNestedClass() {
innerField = aField; //Illegal, can't access aField from static context
aMethod(); //Illegal, can't call aMethod from static context
}
private NestedClass() {
innerField = aField; //Legal
aMethod(); //Legal
Thus, your decision of static vs non-static mainly depends on whether or not you need to be able to directly access
fields and methods of the outer class, though it also has consequences for when and where you can construct the
nested class.
As a rule of thumb, make your nested classes static unless you need to access fields and methods of the outer
class. Similar to making your fields private unless you need them public, this decreases the visibility available to the
nested class (by not allowing access to an outer instance), reducing the likelihood of error.
public, as usual, gives unrestricted access to any scope able to access the type.
public int x = 5;
both protected and the default modifier (of nothing) behave as expected as well, the same as they do for non-
nested classes.
private, interestingly enough, does not restrict to the class it belongs to. Rather, it restricts to the compilation unit -
the .java file. This means that Outer classes have full access to Inner class fields and methods, even if they are
marked private.
private int x;
private void anInnerMethod() {}
}
The Inner Class itself can have a visibility other than public. By marking it private or another restricted access
modifier, other (external) classes will not be allowed to import and assign the type. They can still get references to
objects of that type, however.
Anonymous classes are typically used in situations where you need to be able to create a light-weight class to be
passed as a parameter. This is typically done with an interface. For example:
This anonymous class defines a Comparator<String> object (CASE_INSENSITIVE) that compares two strings ignoring
differences in case.
Other interfaces that are frequently implemented and instantiated using anonymous classes are Runnable and
Anonymous inner classes can also be based on classes. In this case, the anonymous class implicitly extends the
existing class. If the class being extended is abstract, then the anonymous class must implement all abstract
methods. It may also override non-abstract methods.
Constructors
An anonymous class cannot have an explicit constructor. Instead, an implicit constructor is defined that uses
super(...) to pass any parameters to a constructor in the class that is being extended. For example:
The implicit constructor for our anonymous subclass of SomeClass will call a constructor of SomeClass that matches
the call signature SomeClass(int, String). If no constructor is available, you will get a compilation error. Any
exceptions that are thrown by the matched constructor are also thrown by the implicit constructor.
Naturally, this does not work when extending an interface. When you create an anonymous class from an interface,
the classes superclass is java.lang.Object which only has a no-args constructor.
The inner class depends on the outside class and requires a reference to an instance of it. To create an instance of
the inner class, the new operator only needs to be called on an instance of the outer class.
class OuterClass {
class InnerClass {
}
}
class OutsideClass {
OuterClass.InnerClass createInner() {
return outer.new InnerClass();
}
}
A method-local inner class can be instantiated only within the method where the inner class is defined.
You can access fields and methods of the outer class directly.
But in case of name collision you can use the outer class reference.
// updating my counter
counter = OuterClass.this.counter;
}
}
}
With the Objects.nonNull method and Java8 Stream API, we can do the above in this way:
/**
* Class which falls back to default implementation of {@link #printString()}
*/
public class WithDefault
implements Printable
{
}
/**
* Custom implementation of {@link #printString()}
*/
public class OverrideDefault
implements Printable {
@Override
public void printString() {
System.out.println( "overridden implementation" );
}
}
new WithDefault().printString();
new OverrideDefault().printString();
default implementation
overridden implementation
For example, you have Swim interface that you published 20 years ago.
We did a great job, our interface is very popular, there are many implementation on that around the world and you
don't have control over their source code.
After 20 years, you've decided to add new functionality to the interface, but it looks like our interface is frozen
because it will break existing implementations.
Now all existing implementations of our interface can still work. But most importantly they can implement the
newly added method in their own time.
One of the biggest reasons for this change, and one of its biggest uses, is in the Java Collections framework. Oracle
could not add a foreach method to the existing Iterable interface without breaking all existing code which
implemented Iterable. By adding default methods, existing Iterable implementation will inherit the default
implementation.
int getB();
@Override
public int getB() {
return 2;
}
}
System.out.println(new Sum().calculateSum());
Default methods could be used along with interface static methods as well:
System.out.println(new Sum().calculateSum());
public interface A {
default void foo() { System.out.println("A.foo"); }
}
public interface B {
default void foo() { System.out.println("B.foo"); }
Here are two interfaces declaring default method foo with the same signature.
If you will try to extend these both interfaces in the new interface you have to make choice of two, because Java
forces you to resolve this collision explicitly.
First, you can declare method foo with the same signature as abstract, which will override A and B behaviour.
And when you will implement ABExtendsAbstract in the class you will have to provide foo implementation:
Or second, you can provide a completely new default implementation. You also may reuse code of A and B foo
methods by Accessing overridden default methods from implementing class.
And when you will implement ABExtends in the class you will not have to provide foo implementation:
Will produce
AbstractSwimmer.backStroke
new FooSwimmer().backStroke();
Will produce
FooSwimmer.backStroke
package foo.bar
package foo.bar.baz
The above is fine because the two classes exist in different packages.
package foo.bar
public ExampleClass() {
exampleNumber = 3;
exampleString = "Test String";
}
//No getters or setters
}
package foo.bar
package baz.foo
Additional content can be added to a subclass. Doing so allows for additional functionality in the subclass without
any change to the base class or any other subclasses from that same base class:
public int x;
public SubClassWithField(int x) {
this.x = x; //Can access fields
}
}
private fields and methods still exist within the subclass, but are not accessible:
private int x = 5;
This is known as multiple inheritance, and while it is legal in some languages, Java does not permit it with classes.
As a result of this, every class has an unbranching ancestral chain of classes leading to Object, from which all
classes descend.
An abstract class cannot be instantiated. It can be sub-classed (extended) as long as the sub-class is either also
abstract, or implements all methods marked as abstract by super classes.
The class must be marked abstract, when it has at least one abstract method. An abstract method is a method that
has no implementation. Other methods can be declared within an abstract class that have implementation in order
to provide common code for any sub-classes.
However a class that extends Component, and provides an implementation for all of its abstract methods and can be
instantiated.
@Override
public void render() {
//render a button
}
}
@Override
public void render() {
//render a textbox
}
}
Instances of inheriting classes also can be cast as the parent class (normal inheritance) and they provide a
polymorphic effect when the abstract method is called.
Abstract classes and interfaces both provide a way to define method signatures while requiring the
extending/implementing class to provide the implementation.
There are two key differences between abstract classes and interfaces:
A class may only extend a single class, but may implement many interfaces.
An abstract class can contain instance (non-static) fields, but interfaces may only contain static fields.
Methods declared in interfaces could not contain implementations, so abstract classes were used when it was
useful to provide additional methods which implementations called the abstract methods.
Version ≥ Java SE 8
Java 8 allows interfaces to contain default methods, usually implemented using the other methods of the interface,
making interfaces and abstract classes equally powerful in this regard.
As a convenience java allows for instantiation of anonymous instances of subclasses of abstract classes, which
provide implementations for the abstract methods upon creating the new object. Using the above example this
could look like this:
When used in a class declaration, the final modifier prevents other classes from being declared that extend the
class. A final class is a "leaf" class in the inheritance class hierarchy.
Final classes can be combined with a private constructor to control or prevent the instantiation of a class. This can
be used to create a so-called "utility class" that only defines static members; i.e. constants and static methods.
Immutable classes should also be declared as final. (An immutable class is one whose instances cannot be
changed after they have been created; see the Immutable Objects topic. ) By doing this, you make it impossible to
create a mutable subclass of an immutable class. That would violate the Liskov Substitution Principle which
requires that a subtype should obey the "behavioral contract" of its supertypes.
From a practical perspective, declaring an immutable class to be final makes it easier to reason about program
behavior. It also addresses security concerns in the scenario where untrusted code is executed in a security
sandbox. (For instance, since String is declared as final, a trusted class does not need to worry that it might be
tricked into accepting mutable subclass, which the untrusted caller could then surreptitiously change.)
One disadvantage of final classes is that they do not work with some mocking frameworks such as Mockito.
Update: Mockito version 2 now support mocking of final classes.
Final methods
The final modifier can also be applied to methods to prevent them being overridden in sub-classes:
@Override
public void someMethod() { // Compiler error (overridden method is final)
}
}
Final methods are typically used when you want to restrict what a subclass can change in a class without forbidding
subclasses entirely.
The final modifier can also be applied to variables, but the meaning of final for variables is unrelated to
inheritance.
class A {...}
class B extends A {...}
This also applies when the type is an interface, where there doesn't need to any hierarchical relationship between
the objects:
interface Foo {
void bar();
}
Now the list contains objects that are not from the same class hierarchy.
Abstract classes create "is a" relations while interfaces provide "has a" capability.
System.out.println("Dog:"+dog);
System.out.println("Cat:"+cat);
dog.remember();
dog.protectOwner();
Learn dl = dog;
dl.learn();
cat.remember();
cat.protectOwner();
Climb c = cat;
c.climb();
Climb cm = man;
cm.climb();
Think t = man;
t.think();
Learn l = man;
l.learn();
Apply a = man;
a.apply();
}
}
interface Learn {
void learn();
}
interface Apply{
void apply();
}
output:
Key notes:
1. Animal is an abstract class with shared attributes: name and lifeExpectancy and abstract methods:
remember() and protectOwner(). Dog and Cat are Animals that have implemented the remember() and
protectOwner() methods.
2. Cat can climb() but Dog cannot. Dog can think() but Cat cannot. These specific capabilities are added to Cat
and Dog by implementation.
3. Man is not an Animal but he can Think , Learn, Apply, and Climb.
6. Man is neither a Cat nor a Dog but can have some of the capabilities of the latter two without extending
Animal, Cat, or Dog. This is done with Interfaces.
TL;DR:
Unrelated classes can have capabilities through interfaces, but related classes change the behaviour through extension of
base classes.
Refer to the Java documentation page to understand which one to use in a specific use case.
1. You expect that unrelated classes would implement your interface. For example, many unrelated objects can
implement the Serializable interface.
2. You want to specify the behaviour of a particular data type but are not concerned about who implements its
behaviour.
3. You want to take advantage of multiple inheritance of type.
SubClass.sayHello();
//This will be different than the above statement's output, since it runs
//A different method
SubClass.sayHello(true);
StaticOverride.sayHello();
System.out.println("StaticOverride's num: " + StaticOverride.num);
}
}
Hello
BaseClass's num: 5
Hello
Hey
Static says Hi
StaticOverride's num: test
Not only the former can be applied to a wider choice of arguments, its results will be more compatible with code
provided by other developers that generally adhere to the concept of programming to an interface. However, the
most important reasons to use the former are:
most of the time the context, in which the result is used, does not and should not need that many details as
the concrete implementation provides;
adhering to an interface forces cleaner code and less hacks such as yet another public method gets added to
a class serving some specific scenario;
the code is more testable as interfaces are easily mockable;
finally, the concept helps even if only one implementation is expected (at least for testability).
So how can one easily apply the concept of programming to an interface when writing new code having in mind
one particular implementation? One option that we commonly use is a combination of the following patterns:
programming to an interface
factory
builder
The following example based on these principles is a simplified and truncated version of an RPC implementation
written for a number of different protocols:
The above interface is not supposed to be instantiated directly via a factory, instead we derive further more
concrete interfaces, one for HTTP invocation and one for AMQP, each then having a factory and a builder to
construct instances, which in turn are also instances of the above interface:
Instances of RemoteInvoker for the use with AMQP can now be constructed as easy as (or more involved depending
on the builder):
Due to Java 8 permitting placing of static methods directly into interfaces, the intermediate factory has become
implicit in the above code replaced with AmqpInvoker.with(). In Java prior to version 8, the same effect can be
achieved with an inner Factory class:
The builder used above could look like this (although this is a simplification as the actual one permits defining of up
to 15 parameters deviating from defaults). Note that the construct is not public, so it is specifically usable only from
the above AmqpInvoker interface:
@Override
public <RQ, RS> CompletableFuture<RS> invoke(final RQ request, final Class<RS> respClass) {
...
}
}
Meanwhile, this pattern proved to be very efficient in developing all our new code not matter how simple or
complex the functionality is.
The following example demonstrates how ClassB overrides the functionality of ClassA by changing what gets sent
out through the printing method:
Example:
class ClassA {
public void printing() {
System.out.println("A");
}
}
Output:
class Car {
public int gearRatio = 8;
Casting an instance of a subclass to a base class as in: A a = b; is called widening and does not need a type-cast.
class Vehicle {
}
class Test {
The statement Vehicle vehicle = new Car(); is a valid Java statement. Every instance of Car is also a Vehicle.
Therefore, the assignment is legal without the need for an explicit type-cast.
On the other hand, Car c = vehicle; is not valid. The static type of the vehicle variable is Vehicle which means
that it could refer to an instance of Car, Truck,MotorCycle, or any other current or future subclass
ofVehicle. (Or indeed, an instance ofVehicleitself, since we did not declare it as anabstractclass.)
The assignment cannot be allowed, since that might lead tocarreferring to aTruck` instance.
The type-cast tells the compiler that we expect the value of vehicle to be a Car or a subclass of Car. If necessary,
compiler will insert code to perform a run-time type check. If the check fails, then a ClassCastException will be
thrown when the code is executed.
The Java compiler knows that an instance that is type compatible with Vehicle cannot ever be type compatible with
String. The type-cast could never succeed, and the JLS mandates that this gives in a compilation error.
class StaticMethodTest {
Static methods are bind to a class not to an instance and this method binding happens at compile time. Since in the
first call to staticMethod(), parent class reference p was used, Parent's version of staticMethod() is invoked. In
second case, we did cast p into Child class, Child's staticMethod() executed.
Strong Reference
Weak Reference
Soft Reference
Phantom Reference
1. Strong Reference
The variable holder is holding a strong reference to the object created. As long as this variable is live and holds this
value, the MyObject instance will not be collected by the garbage collector.
2. Weak Reference
When you do not want to keep an object longer, and you need to clear/free the memory allocated for an object as
soon as possible, this is the way to do so.
Simply, a weak reference is a reference that isn't strong enough to force an object to remain in memory. Weak
references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have
to do it yourself.
When you need the object you created, just use .get() method:
myObjectRef.get();
3. Soft Reference
Soft references are slightly stronger than weak references. You can create a soft referenced object as following:
They can hold onto the memory more strongly than the weak reference. If you have enough memory
supply/resources, garbage collector will not clean the soft references as enthusiastically as weak references.
4. Phantom Reference
This is the weakest referencing type. If you created an object reference using Phantom Reference, the get()
method will always return null!
The use of this referencing is that "Phantom reference objects, which are enqueued after the collector determines
that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-
mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism." - From
Phantom Reference Javadoc from Oracle.
In Java, Strings are immutable, meaning that they cannot be changed. (Click here for a more thorough explanation
of immutability.)
For example, the following snippet will determine if the two instances of String are equal on all characters:
if (firstString.equals(secondString)) {
// Both Strings have the same content.
}
Live demo
if (firstString.equalsIgnoreCase(secondString)) {
// Both Strings are equal, ignoring the case of the individual characters.
}
Live demo
Note that equalsIgnoreCase does not let you specify a Locale. For instance, if you compare the two words "Taki"
and "TAKI" in English they are equal; however, in Turkish they are different (in Turkish, the lowercase I is ?). For
cases like this, converting both strings to lowercase (or uppercase) with Locale and then comparing with equals is
the solution.
System.out.println(firstString.toLowerCase(locale).equals(
secondString.toLowerCase(locale))); //prints false
Live demo
Unless you can guarantee that all strings have been interned (see below), you should not use the
==
Instead, use the String.equals(Object) method, which will compare the String objects based on their values. For a
detailed explanation, please refer to Pitfall: using == to compare strings.
As of Java 1.7, it is possible to compare a String variable to literals in a switch statement. Make sure that the String
is not null, otherwise it will always throw a NullPointerException. Values are compared using String.equals, i.e.
case sensitive.
switch (stringToSwitch) {
case "a":
System.out.println("a");
break;
case "A":
System.out.println("A"); //the code goes here
break;
case "B":
System.out.println("B");
break;
default:
break;
}
Live demo
When comparing a String to a constant value, you can put the constant value on the left side of equals to ensure
that you won't get a NullPointerException if the other String is null.
"baz".equals(foo)
While foo.equals("baz") will throw a NullPointerException if foo is null, "baz".equals(foo) will evaluate to
false.
Version ≥ Java SE 7
A more readable alternative is to use Objects.equals(), which does a null check on both parameters:
Objects.equals(foo, "baz").
(Note: It is debatable as to whether it is better to avoid NullPointerExceptions in general, or let them happen and
then fix the root cause; see here and here. Certainly, calling the avoidance strategy "best practice" is not justifiable.)
String orderings
The String class implements Comparable<String> with the String.compareTo method (as described at the start of
this example). This makes the natural ordering of String objects case-sensitive order. The String class provide a
Comparator<String> constant called CASE_INSENSITIVE_ORDER suitable for case-insensitive sorting.
"Moreover, a string literal always refers to the same instance of class String. This is because string literals
- or, more generally, strings that are the values of constant expressions - are interned so as to share
unique instances, using the method String.intern."
==
. Moreover, the same is true for references to String objects that have been produced using the String.intern()
method.
For example:
// The two string references point two strings that are equal
if (strObj.equals(str)) {
System.out.println("The strings are equal");
}
if (internedStr == str) {
System.out.println("The interned string and the literal are the same object");
}
Behind the scenes, the interning mechanism maintains a hash table that contains all interned strings that are still
reachable. When you call intern() on a String, the method looks up the object in the hash table:
If the string is found, then that value is returned as the interned string.
Otherwise, a copy of the string is added to the hash table and that string is returned as the interned string.
==
. However, there are significant problems with doing this; see Pitfall - Interning strings so that you can use == is a
bad idea for details. It is not recommended in most cases.
Non-alphabetic characters, such as digits and punctuation marks, are unaffected by these methods. Note that these
methods may also incorrectly deal with certain Unicode characters under certain conditions.
Note: These methods are locale-sensitive, and may produce unexpected results if used on strings that are intended
to be interpreted independent of the locale. Examples are programming language identifiers, protocol keys, and
HTML tags.
For instance, "TITLE".toLowerCase() in a Turkish locale returns "t?tle", where ? (\u0131) is the LATIN SMALL
LETTER DOTLESS I character. To obtain correct results for locale insensitive strings, pass Locale.ROOT as a
parameter to the corresponding case converting method (e.g. toLowerCase(Locale.ROOT) or
toUpperCase(Locale.ROOT)).
Although using Locale.ENGLISH is also correct for most cases, the language invariant way is Locale.ROOT.
A detailed list of Unicode characters that require special casing can be found on the Unicode Consortium website.
To change the case of a specific character of an ASCII string following algorithm can be used:
Steps:
1. Declare a string.
2. Input the string.
3. Convert the string into a character array.
4. Input the character that is to be searched.
5. Search for the character into the character array.
6. If found,check if the character is lowercase or uppercase.
If Uppercase, add 32 to the ASCII code of the character.
If Lowercase, subtract 32 from the ASCII code of the character.
7. Change the original character from the Character array.
8. Convert the character array back into the string.
The String.contains() method can be used to verify if a CharSequence can be found in the String. The method
looks for the String a in the String b in a case-sensitive way.
To find the exact position where a String starts within another String, use String.indexOf():
The String.indexOf() method returns the first index of a char or String in another String. The method returns
-1 if it is not found.
class Strings
{
public static void main (String[] args)
{
String a = "alpha";
String b = "alpha";
String c = new String("alpha");
true
true
true
true
However using new operator, we force String class to create a new String object in heap space. We can use intern()
method to put it into the pool or refer to other String object from string pool having same value.
Before Java 7, String literals were stored in the runtime constant pool in the method area of PermGen, that had a
fixed size.
Version ≥ Java SE 7
RFC: 6962931
In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are
instead allocated in the main part of the Java heap (known as the young and old generations), along with
the other objects created by the application. This change will result in more data residing in the main Java
heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most
applications will see only relatively small differences in heap usage due to this change, but larger
applications that load many classes or make heavy use of the String.intern() method will see more
significant differences.
Note that delimiting character or regular expression gets removed from the resulting String Array.
In the previous example . is treated as the regular expression wildcard that matches any character, and since every
character is a delimiter, the result is an empty array.
< > - = ! ( ) [ ] { } \ ^ $ | ? * + .
To split a string based on one of the above delimiters, you need to either escape them using \\ or use
Pattern.quote():
Using Pattern.quote():
String s = "a|b|c";
String regex = Pattern.quote("|");
String[] arr = s.split(regex);
String s = "a|b|c";
String[] arr = s.split("\\|");
split(delimiter) by default removes trailing empty strings from result array. To turn this mechanism off we need
to use overloaded version of split(delimiter, limit) with limit set to negative value like
The limit parameter controls the number of times the pattern is applied and therefore affects the length of the
resulting array.
If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no
greater than n, and the array's last entry will contain all input beyond the last matched delimiter.
If n is negative, then the pattern will be applied as many times as possible and the array can have any length.
If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing
empty strings will be discarded.
Besides the split() method Strings can also be split using a StringTokenizer.
StringTokenizer is even more restrictive than String.split(), and also a bit harder to use. It is essentially
designed for pulling out tokens delimited by a fixed set of characters (given as a String). Each character will act as a
separator. Because of this restriction, it's about twice as fast as String.split().
Default set of characters are empty spaces (\t\n\r\f). The following example will print out each word separately.
the
lazy
fox
jumped
over
the
brown
fence
j
mp
d ov
r
To have a fine-grained control over joining, you may use StringJoiner class:
sj.add("foo");
sj.add("bar");
sj.add("foobar");
String s1 = "a";
String s2 = "b";
String s3 = "c";
String s = s1 + s2 + s3; // abc
Normally a compiler implementation will perform the above concatenation using methods involving a
StringBuilder under the hood. When compiled, the code would look similar to the below:
StringBuilder has several overloaded methods for appending different types, for example, to append an int
instead of a String. For example, an implementation can convert:
String s1 = "a";
String s2 = "b";
String s = s1 + s2 + 2; // ab2
to the following:
The above examples illustrate a simple concatenation operation that is effectively done in a single place in the code.
The concatenation involves a single instance of the StringBuilder. In some cases, a concatenation is carried out in
a cumulative way such as in a loop:
In such cases, the compiler optimization is usually not applied, and each iteration will create a new StringBuilder
object. This can be optimized by explicitly transforming the code to use a single StringBuilder:
A StringBuilder will be initialized with an empty space of only 16 characters. If you know in advance that you will
be building larger strings, it can be beneficial to initialize it with sufficient size in advance, so that the internal buffer
does not need to be resized:
If (and only if) multiple threads are writing to the same buffer, use StringBuffer, which is a synchronized version of
StringBuilder. But because usually only a single thread writes to a buffer, it is usually faster to use StringBuilder
without synchronization.
This returns a new string that is string1 with string2 added to it at the end. You can also use the concat() method
with string literals, as in:
Substrings may also be applied to slice and add/replace character into its original String. For instance, you faced a
Chinese date containing Chinese characters but you want to store it as a well format Date String.
The substring method extracts a piece of a String. When provided one parameter, the parameter is the start and
the piece extends until the end of the String. When given two parameters, the first parameter is the starting
In JDK <7u6 versions the substring method instantiates a String that shares the same backing char[] as the
original String and has the internal offset and count fields set to the result start and length. Such sharing may
cause memory leaks, that can be prevented by calling new String(s.substring(...)) to force creation of a copy,
after which the char[] can be garbage collected.
Version ≥ Java SE 7
From JDK 7u6 the substring method always copies the entire underlying char[] array, making the complexity
linear compared to the previous constant one but guaranteeing the absence of memory leaks at the same time.
System.getProperty("line.separator")
Version ≥ Java SE 7
Because the new line separator is so commonly needed, from Java 7 on a shortcut method returning exactly the
same result as the code above is available:
System.lineSeparator()
Note: Since it is very unlikely that the new line separator changes during the program's execution, it is a good idea
to store it in in a static final variable instead of retrieving it from the system property every time it is needed.
When using String.format, use %n rather than \n or '\r\n' to output a platform independent new line separator.
1. StringBuilder/StringBuffer:
System.out.println(code);
2. Char array:
// print reversed
System.out.println(new String(array));
String name;
int age;
and later in your code you use the following statement in order to print the object:
System.out.println(person.toString());
Person@7ab89d
This is the result of the implementation of the toString() method defined in the Object class, a superclass of
Person. The documentation of Object.toString() states:
The toString method for class Object returns a string consisting of the name of the class of which the
object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal to the value of:
So, for meaningful output, you'll have to override the toString() method:
@Override
public String toString() {
System.out.println(person);
If you trim a String that doesn't have any whitespace to remove, you will be returned the same String instance.
Note that the trim() method has its own notion of whitespace, which differs from the notion used by the
Character.isWhitespace() method:
All ASCII control characters with codes U+0000 to U+0020 are considered whitespace and are removed by
trim(). This includes U+0020 'SPACE', U+0009 'CHARACTER TABULATION', U+000A 'LINE FEED' and U+000D
'CARRIAGE RETURN' characters, but also the characters like U+0007 'BELL'.
Unicode whitespace like U+00A0 'NO-BREAK SPACE' or U+2003 'EM SPACE' are not recognized by trim().
switch itself can not be parameterised to be case insensitive, but if absolutely required, can behave insensitive to
the input string by using toLowerCase() or toUpperCase:
switch (myString.toLowerCase()) {
case "case1" :
...
break;
case "case2" :
...
break;
}
Beware
Note: the original String object will be unchanged, the return value holds the changed String.
Exact match
Replace single character with another single character:
String replace(char oldChar, char newChar)
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
String s = "popcorn";
System.out.println(s.replace('p','W'));
Result:
WoWcorn
Replaces each substring of this string that matches the literal target sequence with the specified literal
replacement sequence.
Result:
Regex
Note: the grouping uses the $ character to reference the groups, like $1.
Replaces each substring of this string that matches the given regular expression with the given
replacement.
Result:
Result:
A char in a String is UTF-16 value. Unicode codepoints whose values are ? 0x1000 (for example, most emojis) use
two char positions. To count the number of Unicode codepoints in a String, regardless of whether each codepoint
fits in a UTF-16 char value, you can use the codePointCount method:
System.out.println(str.charAt(0)); // "M"
System.out.println(str.charAt(1)); // "y"
System.out.println(str.charAt(2)); // " "
System.out.println(str.charAt(str.length-1)); // Last character "g"
To get the nth character in a string, simply call charAt(n) on a String, where n is the index of the character you
would like to retrieve
import org.apache.commons.lang3.StringUtils;
String text = "One fish, two fish, red fish, blue fish";
Otherwise for does the same with standard Java API's you could use Regular Expressions:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String text = "One fish, two fish, red fish, blue fish";
System.out.println(countStringInString("fish", text)); // prints 4
System.out.println(countStringInString(",", text)); // prints 3
int stringOccurrences = 0;
while (matcher.find()) {
stringOccurrences++;
}
return stringOccurrences;
}
Methods:
class Test {
public static void main(String args[])
{
String str = "study";
str.concat("tonight");
System.out.println(str); // Output: study
The StringBuffer class has been present since Java 1.0, and provides a variety of methods for building and
modifying a "buffer" containing a sequence of characters.
The StringBuilder class was added in Java 5 to address performance issues with the original StringBuffer
class. The APIs for the two clases are essentially the same. The main difference between StringBuffer and
StringBuilder is that the former is thread-safe and synchronized and the latter is not.
int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.
(The StringBuffer class is used the same way: just change StringBuilder to StringBuffer in the above)
The StringBuffer and StringBuilder classes are suitable for both assembling and modifying strings; i.e they
provide methods for replacing and removing characters as well as adding them in various. The remining two
classes are specific to the task of assembling strings.
The Formatter class was added in Java 5, and is loosely modeled on the sprintf function in the C standard
library. It takes a format string with embedded format specifiers and a sequences of other arguments, and
generates a string by converting the arguments into text and substituting them in place of the format
specifiers. The details of the format specifiers say how the arguments are converted into text.
The StringJoiner class was added in Java 8. It is a special purpose formatter that succinctly formats a
sequence of strings with separators between them. It is designed with a fluent API, and can be used with Java
8 streams.
This creates n new string instances containing 1 to n repetitions of s resulting in a runtime of O(s.length() * n²) =
O(s.length() * (1+2+...+(n-1)+n)).
To avoid this StringBuilder should be used, which allows creating the String in O(s.length() * n) instead:
The set of delimiters (the characters that separate tokens) may be specified either at creation time or on a per-
token basis.
Output:
apple
ball
cat
dog
Output:
apple
ball cat
dog
The regex matches 8 characters after the end of the last match. Since in this case the match is zero-width, we could
more simply say "8 characters after the last match".
Conveniently, \G is initialized to start of input, so it works for the first part of the input too.
int length = 5;
String[] parts = str.split("(?<=\\G.{" + length + "})");
which will widen the intValue integer to long, using sign bit extension for negative values, so that negative values
will stay negative.
Following constructor is used to translate the String representation of a BigInteger in the specified radix into a
BigInteger.
Java also supports direct conversion of bytes to an instance of BigInteger. Currently only signed and unsigned big
endian encoding may be used:
This will generate a BigInteger instance with value -128 as the first bit is interpreted as the sign bit.
This will generate a BigInteger instance with value 128 as the bytes are interpreted as unsigned number, and the
sign is explicitly set to 1, a positive number.
There's also BigInteger.TWO (value of "2"), but you can't use it in your code because it's private.
Addition: 10 + 10 = 20
output: 20
Substraction: 10 - 9 = 1
output: 1
Division: 10 / 5 = 2
output: 2
Division: 17/4 = 4
output: 4
output: 50
Power: 10 ^ 3 = 1000
output: 1000
Remainder: 10 % 6 = 4
output: 4
System.out.println(value1.gcd(value2));
Output: 6
System.out.println(value1.max(value2));
Output: 11
System.out.println(value1.min(value2));
Output: 10
For example:
if(one.equals(two)){
System.out.println("Equal");
}
else{
System.out.println("Not Equal");
}
Output:
Not Equal
Note:
==
==
operator: compares references; i.e. whether two values refer to the same object
equals() method: compares the content of two BigIntegers.
if (firstBigInteger == secondBigInteger) {
// Only checks for reference equality, not content equality!
}
==
operator only checks for reference equality. If both BigIntegers contain the same content, but do not refer to the
same object, this will fail. Instead, compare BigIntegers using the equals methods, as explained above.
You can also compare your BigInteger to constant values like 0,1,10.
for example:
You can also compare two BigIntegers by using compareTo() method, as following: compareTo() returns 3 values.
if(reallyBig.compareTo(reallyBig1) == 0){
//code when both are equal.
}
else if(reallyBig.compareTo(reallyBig1) == 1){
//code when reallyBig is greater than reallyBig1.
}
else if(reallyBig.compareTo(reallyBig1) == -1){
//code when reallyBig is less than reallyBig1.
}
Binary Or:
val1.or(val2);
Binary And:
val1.and(val2);
Binary Xor:
val1.xor(val2);
RightShift:
LeftShift:
val1.not();
Output: 5
NAND (And-Not):*
val1.andNot(val2);
Output: 7
then you'll end up with a BigInteger whose value is between 0 (inclusive) and 2bitCount (exclusive).
This also means that new BigInteger(2147483647, sourceOfRandomness) may return all positive BigIntegers
given enough time.
If you're willing to give up speed for higher-quality random numbers, you can use a new
="https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html" rel="nofollow
noreferrer">SecureRandom() instead:
import java.security.SecureRandom;
You can even implement an algorithm on-the-fly with an anonymous class! Note that rolling out your own RNG
algorithm will end you up with low quality randomness, so always be sure to use an algorithm that is proven to
be decent unless you want the resulting BigInteger(s) to be predictable.
@Override
protected int next(int bits) {
seed = ((22695477 * seed) + 1) & 2147483647; // Values shamelessly stolen from
="https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use" rel="nofollow
noreferrer">Wikipedia return seed; } });
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
Using Scanner:
Version ≥ Java SE 5
System.out.println("Please type your name and press Enter");
import java.util.Scanner;
System.out.println("Please enter your first and your last name, on separate lines.");
There are two methods for obtaining Strings, next() and nextLine(). next() returns text up until the first space
(also known as a "token"), and nextLine() returns all text that the user inputted until pressing enter.
Scanner also provides utility methods for reading data types other than String. These include:
scanner.nextByte();
scanner.nextShort();
scanner.nextInt();
scanner.nextLong();
scanner.nextFloat();
scanner.nextDouble();
scanner.nextBigInteger();
scanner.nextBigDecimal();
Using System.console:
Version ≥ Java SE 6
String name = System.console().readLine("Please type your name and press Enter%n");
Advantages:
Note: This will only work if the program is run from a real command line without redirecting the standard input and
output streams. It does not work when the program is run from within certain IDEs, such as Eclipse. For code that
works within IDEs and with stream redirection, see the other examples.
Output:
1 1 1
1234 1234 1234
Using format strings with fixed size permits to print the strings in a table-like appearance with fixed size columns:
Output:
1 1 1
123 1234 1234
123 1234567 123456
123 12345678 123456
private static final String CMD_QUIT = "quit"; //string for exiting the program
private static final String CMD_HELLO = "hello"; //string for printing "Hello World!" on
the screen
private static final String CMD_ANSWER = "answer"; //string for printing 42 on the screen
try {
cmd = reader.readLine(); //takes input from user. user input should be started with
"hello", "answer" or "quit"
String[] cmdArr = cmd.split(" ");
// prints "Hello World!" on the screen if user input starts with "hello"
private void hello(String[] cmdArr) {
System.out.println("Hello World!");
}
Commonly you should not use the equals method since it considers two BigDecimals equal only if they are equal
in value and also scale:
import java.math.BigDecimal;
For a starting balance of 10000.00, after 1000 operations for 1.99, we expect the balance to be 8010.00. Using the
float type gives us an answer around 8009.77, which is unacceptably imprecise in the case of monetary calculations.
Using BigDecimal gives us the proper result.
1.Addition
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = a + b
BigDecimal result = a.add(b);
System.out.println(result);
Result : 12
2.Subtraction
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = a - b
BigDecimal result = a.subtract(b);
System.out.println(result);
Result : -2
When multiplying two BigDecimals the result is going to have scale equal to the sum of the scales of operands.
//Equivalent to result = a * b
BigDecimal result = a.multiply(b);
System.out.println(result);
Result : 36.89931
To change the scale of the result use the overloaded multiply method which allows passing MathContext - an object
describing the rules for operators, in particular the precision and rounding mode of the result. For more
information about available rounding modes please refer to the Oracle Documentation.
//Equivalent to result = a * b
BigDecimal result = a.multiply(b, returnRules);
System.out.println(result);
Result : 36.90
4.Division
Division is a bit more complicated than the other arithmetic operations, for instance consider the below example:
We would expect this to give something similar to : 0.7142857142857143, but we would get:
This would work perfectly well when the result would be a terminating decimal say if I wanted to divide 5 by 2, but
for those numbers which upon dividing would give a non terminating result we would get an ArithmeticException.
In the real world scenario, one cannot predict the values that would be encountered during the division, so we need
to specify the Scale and the Rounding Mode for BigDecimal division. For more information on the Scale and
Rounding Mode, refer the Oracle Documentation.
Result : 0.7142857143
5.Remainder or Modulus
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = a % b
BigDecimal result = a.remainder(b);
System.out.println(result);
Result : 5
6.Power
BigDecimal a = new BigDecimal("5");
Result : 9765625
7.Max
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
Result : 7
8.Min
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
Result : 5
Result : 52.3449843776
Result : 5234498.43776
There are many more options and combination of parameters for the above mentioned examples (For instance,
there are 6 variations of the divide method), this set is a non-exhaustive list and covers a few basic examples.
BigDecimal.ZERO
BigDecimal.ONE
BigDecimal.TEN
By using the static properties, you avoid an unnecessary instantiation, also you've got a literal in your code instead
of a 'magic number'.
//Bad example:
BigDecimal bad0 = new BigDecimal(0);
BigDecimal bad1 = new BigDecimal(1);
BigDecimal bad10 = new BigDecimal(10);
//Good Example:
BigDecimal good0 = BigDecimal.ZERO;
BigDecimal good1 = BigDecimal.ONE;
BigDecimal good10 = BigDecimal.TEN;
1. Format Number
numberFormat.format(10000000.99);
2. Format Currency
3. Format Percentage
numberFormat.setMinimumIntegerDigits(int digits)
numberFormat.setMaximumIntegerDigits(int digits)
numberFormat.setMinimumFractionDigits(int digits)
numberFormat.setMaximumFractionDigits(int digits)
Prints
FIRST_BIT: true
SECOND_BIT: false
THIRD_BIT: true
FOURTh_BIT: false
FIFTH_BIT: true
BIT_55: true
which matches that mask we passed as checkBitMask parameter: FIRST_BIT | THIRD_BIT | FIFTH_BIT | BIT_55.
final BitSet bitSet = new BitSet(8); // by default all bits are unset
bitSet.set(3); // {0, 2, 3, 4, 6}
bitSet.flip(6); // {0, 2, 4}
BitSet implements Clonable and Serializable, and under the hood all bit values are stored in long[] words field,
that expands automatically.
bitSet.and(new BitSet(8));
bitSet.or(new BitSet(8));
bitSet.xor(new BitSet(8));
bitSet.andNot(new BitSet(8));
boolean isPowerOfTwo(int x)
{
return (x != 0) && ((x & (x - 1)) == 0);
}
Let’s suppose, we have three kind of permissions, READ, WRITE and EXECUTE. Each permission can range from 0 to
7. (Let’s assume 4 bit number system)
How can we get the (12 bit number) permissions, set on above (12 bit number)?
So, this is how we can get the EXECUTE permissions of the RESOURCE. Now, what if we want to get READ
permissions of the RESOURCE?
Right? You are probably assuming this? But, permissions are resulted in 1024. We want to get only READ
permissions for the resource. Don’t worry, that’s why we had the shift operators. If we see, READ permissions are 8
bits behind the actual result, so if apply some shift operator, which will bring READ permissions to the very right of
the result? What if we do:
0100 0000 0000 >> 8 => 0000 0000 0100 (Because it’s a positive number so replaced with 0’s, if you don’t
care about sign, just use unsigned right shift operator)
Now, for example, we are given READ, WRITE, EXECUTE permissions for a RESOURCE, what can we do to make
permissions for this RESOURCE?
Let’s first take the example of binary permissions. (Still assuming 4 bit number system)
READ = 0001
WRITE = 0100
EXECUTE = 0110
READ | WRITE | EXECUTE, you are somewhat right but not exactly. See, what will happen if we will perform READ |
WRITE | EXECUTE
But permissions are actually being represented (in our example) as 0001 0100 0110
So, in order to do this, we know that READ is placed 8 bits behind, WRITE is placed 4 bits behind and PERMISSIONS
is placed at the last. The number system being used for RESOURCE permissions is actually 12 bit (in our example). It
can(will) be different in different systems.
Basic shift operators >> and << are signed operators. They will conserve the sign of the value.
But it is common for programmers to use numbers to store unsigned values. For an int, it means shifting the range
to [0, 2^32 - 1], to have twice as much value as with a signed int.
For those power users, the bit for sign as no meaning. That's why Java added >>>, a left-shift operator, disregarding
that sign bit.
This comes from the intended definition of right-shift. As it fills the emptied places on the left, there are no decision
to take regarding the bit of sign. As a consequence, there is no need for 2 different operators.
Examples:
This is especially useful when defining constant values that should make it apparent, that a power of 2 is used,
For example, one can pack 3 bytes - such as color code in RGB - into an single int.
Arrays allow for the storage and retrieval of an arbitrary quantity of values. They are analogous to vectors in
mathematics. Arrays of arrays are analogous to matrices, and act as multidimensional arrays. Arrays can store any
data of any type: primitives such as int or reference types such as Object.
float[] boats = new float[5]; // Array of five 32-bit floating point numbers.
double[] header = new double[] { 4.56, 332.267, 7.0, 0.3367, 10.0 };
// Array of five 64-bit floating point numbers.
String[] theory = new String[] { "a", "b", "c" };
// Array of three strings (reference type).
Object[] dArt = new Object[] { new Object(), "We love Stack Overflow.", new Integer(3) };
// Array of three Objects (reference type).
For the last example, note that subtypes of the declared array type are allowed in the array.
Arrays for user defined types can also be built similar to primitive types
Intro
Each item in an array is called an element, and each element is accessed by its numerical index. The length of an
array is established when the array is created:
The size of an array is fixed at runtime when initialized. It cannot be changed after initialization. If the size must
be mutable at runtime, a Collection class such as ArrayList should be used instead. ArrayList stores elements in
an array and supports resizing by allocating a new array and copying elements from the old array.
the values are stored in the array itself. In the absence of an initializer (as in array2 above), the default value
assigned to each element is 0 (zero).
then the array contains references to objects of type SomeClassOrInterface. Those references can refer to an
instance of SomeClassOrInterface or any subclass (for classes) or implementing class (for interfaces) of
SomeClassOrInterface. If the array declaration has no initializer then the default value of null is assigned to each
element.
Because all arrays are int-indexed, the size of an array must be specified by an int. The size of the array cannot be
specified as a long:
Arrays use a zero-based index system, which means indexing starts at 0 and ends at length - 1.
For example, the following image represents an array with size 10. Here, the first element is at index 0 and the last
element is at index 9, instead of the first element being at index 1 and the last element at index 10 (see figure
below).
Accesses to elements of arrays are done in constant time. That means accessing to the first element of the array
has the same cost (in time) of accessing the second element, the third element and so on.
Java offers several ways of defining and initializing arrays, including literal and constructor notations. When
0 for primitive numerical types: byte, short, int, long, float, and double.
'\u0000' (null character) for the char type.
false for the boolean type.
null for reference types.
When declaring an array, [] will appear as part of the type at the beginning of the declaration (after the type name),
or as part of the declarator for a particular variable (after variable name), or both:
int array5[]; /*
equivalent to */ int[] array5;
int a, b[], c[][]; /*
equivalent to */ int a; int[] b; int[][] c;
int[] a, b[]; /*
equivalent to */ int[] a; int[][] b;
int a, []b, c[][]; /*
Compilation Error, because [] is not part of the type at beginning
of the declaration, rather it is before 'b'. */
// The same rules apply when declaring a method that returns an array:
int foo()[] { ... } /* equivalent to */ int[] foo() { ... }
In the following example, both declarations are correct and can compile and run without any problems. However,
both the Java Coding Convention and the Google Java Style Guide discourage the form with brackets after the
variable name—the brackets identify the array type and should appear with the type designation. The same should
be used for method return signatures.
The discouraged type is meant to accommodate transitioning C users, who are familiar with the syntax for C which
has the brackets after the variable name.
However, since it's an empty array, no elements can be read from it or assigned to it:
Such empty arrays are typically useful as return values, so that the calling code only has to worry about dealing with
an array, rather than a potential null value that may lead to a NullPointerException.
Note: array.length returns the actual size of the array and not the number of array elements which were assigned
a value, unlike ArrayList.size() which returns the number of array elements which were assigned a value.
It will create two three-length int arrays—a[0] and a[1]. This is very similar to the classical, C-style initialization of
rectangular multi-dimensional arrays.
Unlike C, where only rectangular multi-dimensional arrays are supported, inner arrays do not need to be of the
same length, or even defined:
Here, a[0] is a one-length int array, whereas a[1] is a two-length int array and a[2] is null. Arrays like this are
called jagged arrays or ragged arrays, that is, they are arrays of arrays. Multi-dimensional arrays in Java are
implemented as arrays of arrays, i.e. array[i][j][k] is equivalent to ((array[i])[j])[k]. Unlike C#, the syntax
array[i,j] is not supported in Java.
Live on Ideone
In addition to the String literals and primitives shown above, the shortcut syntax for array initialization also works
with canonical Object types:
Because arrays are covariant, a reference type array can be initialized as an array of a subclass, although an
ArrayStoreException will be thrown if you try to set an element to something other than a String:
The shortcut syntax cannot be used for this because the shortcut syntax would have an implicit type of Object[].
An array can be initialized with zero elements by using String[] emptyArray = new String[0]. For example, an
array with zero length like this is used for Creating an Array from a Collection when the method needs the
runtime type of an object.
In both primitive and reference types, an empty array initialization (for example String[] array8 = new
String[3]) will initialize the array with the default value for each data type.
In generic classes, arrays of generic types cannot be initialized like this due to type erasure:
public MyGenericClass() {
a = new T[5]; // Compile time error: generic array creation
}
}
Instead, they can be created using one of the following methods: (note that these will generate unchecked
warnings)
This is the simplest method, but since the underlying array is still of type Object[], this method does not
provide type safety. Therefore, this method of creating an array is best used only within the generic class -
not exposed publicly.
Here the class of T has to be explicitly passed to the constructor. The return type of Array.newInstance is
always Object. However, this method is safer because the newly created array is always of type T[], and
therefore can be safely externalized.
Arrays.fill() can be used to fill an array with the same value after initialization:
Live on Ideone
fill() can also assign a value to each element of the specified range of the array:
Live on Ideone
Version ≥ Java SE 8
Since Java version 8, the method setAll, and its Concurrent equivalent parallelSetAll, can be used to set every
element of an array to generated values. These methods are passed a generator function which accepts an index
and returns the desired value for that position.
The following example creates an integer array and sets all of its elements to their respective index value:
Live on Ideone
The value of an index for an array element must be a whole number (0, 1, 2, 3, 4, ...) and less than the length of the
array (indexes are zero-based). Otherwise, an ArrayIndexOutOfBoundsException will be thrown:
It is not possible to re-initialize an array via a shortcut syntax with an array initializer since an array initializer can
only be specified in a field declaration or local variable declaration, or as a part of an array creation expression.
However, it is possible to create a new array and assign it to the variable being used to reference the old array.
While this results in the array referenced by that variable being re-initialized, the variable contents are a completely
new array. To do this, the new operator can be used with an array initializer and assigned to the array variable:
Live on Ideone
Note: This list is backed by (a view of) the original array, meaning that any changes to the list will change the array
and vice versa. However, changes to the list that would change its size (and hence the array length) will throw an
exception.
To create a copy of the list, use the constructor of java.util.ArrayList taking a Collection as an argument:
Version ≥ Java SE 5
String[] stringArray = {"foo", "bar", "baz"};
List<String> stringList = new ArrayList<String>(Arrays.asList(stringArray));
Version ≥ Java SE 7
In Java SE 7 and later, a pair of angle brackets <> (empty set of type arguments) can be used, which is called the
Diamond. The compiler can determine the type arguments from the context. This means the type information can
be left out when calling the constructor of ArrayList and it will be inferred automatically during compilation. This is
called Type Inference which is a part of Java Generics.
// Using Arrays.asList()
// Using ArrayList.addAll()
// Using Collections.addAll()
Version ≥ Java SE 8
// Using Streams
This method returns List, which is an instance of Arrays$ArrayList(static inner class of Arrays) and not
java.util.ArrayList. The resulting List is of fixed-size. That means, adding or removing elements is not
supported and will throw an UnsupportedOperationException:
A new List can be created by passing an array-backed List to the constructor of a new List. This creates a
new copy of the data, which has changeable size and that is not backed by the original array:
Calling <T> List<T> asList(T... a) on a primitive array, such as an int[], will produce a List<int[]>
whose only element is the source primitive array instead of the actual elements of the source array.
The reason for this behavior is that primitive types cannot be used in place of generic type parameters, so
the entire primitive array replaces the generic type parameter in this case. In order to convert a primitive
array to a List, first of all, convert the primitive array to an array of the corresponding wrapper type (i.e. call
Arrays.asList on an Integer[] instead of an int[]).
View Demo
Integer[] arr = {1, 2, 3}; // object array of Integer (wrapper for int)
System.out.println(Arrays.asList(arr).contains(1));
View Demo
This will also print true, because the array will be interpreted as an Integer[]):
System.out.println(Arrays.asList(1,2,3).contains(1));
View Demo
Object[] toArray()
Version ≥ Java SE 5
Set<String> set = new HashSet<String>();
set.add("red");
set.add("blue");
Version ≥ Java SE 5
Set<String> set = new HashSet<String>();
set.add("red");
set.add("blue");
// The array does not need to be created up front with the correct size.
// Only the array type matters. (If the size is wrong, a new array will
// be created with the same type.)
String[] stringArray = set.toArray(new String[0]);
The difference between them is more than just having untyped vs typed results. Their performance can differ as
well (for details please read this performance analysis section):
Object[] toArray() uses vectorized arraycopy, which is much faster than the type-checked arraycopy used
in T[] toArray(T[] a).
T[] toArray(new T[non-zero-size]) needs to zero-out the array at runtime, while T[] toArray(new T[0])
does not. Such avoidance makes the latter call faster than the former. Detailed analysis here : Arrays of
Wisdom of the Ancients.
Version ≥ Java SE 8
Starting from Java SE 8+, where the concept of Stream has been introduced, it is possible to use the Stream
produced by the collection in order to create a new Array using the Stream.toArray method.
Examples taken from two answers (1, 2) to Converting 'ArrayList to 'String[]' in Java on Stack Overflow.
int rows = 3;
int columns = 3;
int[][] table = new int[rows][columns];
The array can be indexed and assign values to it with this construct. Note that the unassigned values are the default
values for the type of an array, in this case 0 for int.
table[0][0] = 0;
table[0][1] = 1;
table[0][2] = 2;
It is also possible to instantiate a dimension at a time, and even make non-rectangular arrays. These are more
commonly referred to as jagged arrays.
It is important to note that although it is possible to define any dimension of jagged array, it's preceding level must
be defined.
// valid
String[][] employeeGraph = new String[30][];
// invalid
int[][] unshapenMatrix = new int[][10];
// also invalid
int[][][] misshapenGrid = new int[100][][10];
Multidimensional arrays and jagged arrays can also be initialized with a literal expression. The following declares
and populates a 2x3 int array:
int[][] table = {
{1, 2, 3},
{4, 5, 6}
};
Note: Jagged subarrays may also be null. For instance, the following code declares and populates a two
dimensional int array whose first subarray is null, second subarray is of zero length, third subarray is of one
length and the last subarray is a two length array:
int[][] table = {
null,
{},
{1},
{1,2}
};
For multidimensional array it is possible to extract arrays of lower-level dimension by their indices:
Arrays are zero-based indexed, so the index of the first element is 0 and the index of the last element is the array
capacity minus 1 (i.e. array.length - 1).
Therefore, any request for an array element by the index i has to satisfy the condition 0 <= i < array.length,
otherwise the ArrayIndexOutOfBoundsException will be thrown.
Output:
Note that the illegal index that is being accessed is also included in the exception (2 in the example); this information could
To avoid this, simply check that the index is within the limits of the array:
int index = 2;
if (index >= 0 && index < people.length) {
System.out.println(people[index]);
}
Although Integer[] is a subclass of Number[], it can only hold Integers, and trying to assign a Long element throws
a runtime exception.
Note that this behavior is unique to arrays, and can be avoided by using a generic List instead:
It's not necessary for all of the array elements to share the same type, as long as they are a subclass of the array's
type:
interface I {}
class A implements I {}
class B implements I {}
class C implements I {}
I[] array10 = new I[] { new A(), new B(), new C() }; // Create an array with new
// operator and array initializer.
I[] array11 = { new A(), new B(), new C() }; // Shortcut syntax with array
// initializer.
I[] array13 = new A[] { new A(), new A() }; // Works because A implements I.
Object[] array14 = new Object[] { "Hello, World!", 3.14159, 42 }; // Create an array with
// new operator and array initializer.
Converting an array of primitives to Stream using Arrays.stream() will transform the array to a primitive
specialization of Stream:
You can also limit the Stream to a range of elements in the array. The start index is inclusive and the end index is
exclusive:
A method similar to Arrays.stream() appears in the Stream class: Stream.of(). The difference is that Stream.of()
uses a varargs parameter, so you can write something like:
It is worth noting here that there is no direct way to use an Iterator on an Array, but through the Arrays library it can
be easily converted to a list to obtain an Iterable object.
For primitive arrays (using java 8) use streams (specifically in this example - Arrays.stream -> IntStream):
If you can't use streams (no java 8), you can choose to use google's guava library:
In two-dimensional arrays or more, both techniques can be used in a slightly more complex fashion.
Example:
It is impossible to set an Array to any non-uniform value without using an index based loop.
Of course you can also use while or do-while loops when iterating using indices.
One note of caution: when using array indices, make sure the index is between 0 and array.length - 1 (both
inclusive). Don't make hard coded assumptions on the array length otherwise you might break your code if the
array length changes but your hard coded values don't.
Example:
// DON'T DO THIS :
for (int i = 0; i < 4; i++) {
numbers[i] += 1;
}
}
It's also best if you don't use fancy calculations to get the index but use the index to iterate and if you need
different values calculate those.
Example:
// DON'T DO THIS :
int doubleLength = array.length * 2;
for (int i = 0; i < doubleLength; i += 2) {
array[i / 2] = i;
}
}
Iterating over a temporary array instead of repeating code can make your code cleaner. It can be used where the
same operation is performed on multiple variables.
// copy-paste approach:
System.out.println(name);
System.out.println(eyeCount);
System.out.println(height);
System.out.println(legs);
System.out.println(arms);
Keep in mind that this code should not be used in performance-critical sections, as an array is created every time
the loop is entered, and that primitive variables will be copied into the array and thus cannot be modified.
Since Java 1.5 you can get a String representation of the contents of the specified array without iterating over its
every element. Just use Arrays.toString(Object[]) or Arrays.deepToString(Object[]) for multidimentional
arrays:
Arrays.toString() method uses Object.toString() method to produce String values of every item in the array,
beside primitive type array, it can be used for all type of arrays. For instance:
If no overridden toString() exists for the class, then the inherited toString() from Object will be used. Usually
the output is then not very useful, for example:
import java.util.Arrays;
String is not a numeric data, it defines it's own order which is called lexicographic order, also known as alphabetic
order. When you sort an array of String using sort() method, it sorts array into natural order defined by
Comparable interface, as shown below :
Increasing Order
Output:
Decreasing Order
Output:
String array after sorting in descending order : [Steve, Shane, John, Ben, Adam]
In order to sort an object array, all elements must implement either Comparable or Comparator interface to define
the order of the sorting.
We can use either sort(Object[]) method to sort an object array on its natural order, but you must ensure that all
elements in the array must implement Comparable.
Furthermore, they must be mutually comparable as well, for example e1.compareTo(e2) must not throw a
ClassCastException for any elements e1 and e2 in the array. Alternatively you can sort an Object array on custom
order using sort(T[], Comparator) method as shown in following example.
Arrays.sort(courses);
System.out.println("Object array after sorting in natural order : " + Arrays.toString(courses));
Output:
Object array before sorting : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401 Scala@500 ]
Object array after sorting in natural order : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 ,
#401 Scala@500 ]
Object array after sorting by price : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401
Scala@500 ]
Object array after sorting by name : [#101 Java@200 , #301 Python@400 , #201 Ruby@300 , #401
Scala@500 ]
The length field in an array stores the size of an array. It is a final field and cannot be modified.
This code shows the difference between the length of an array and amount of objects an array stores.
Result:
In addition, each one sets index or index2 to either the index of required element, or -1 if the element is not
present.
Using a Stream
Version ≥ Java SE 8
int index = IntStream.range(0, strings.length)
.filter(i -> "A".equals(strings[i]))
.findFirst()
.orElse(-1); // If not present, gives us -1.
// Similar for an array of primitives
Note: Using a direct linear search is more efficient than wrapping in a list.
The examples above can be adapted to test if the array contains an element by simply testing to see if the index
computed is greater or equal to zero.
There are various ways to do the above. Prior to Java 6, the most concise way was:
From Java 6 onwards, the Arrays.copyOf and Arrays.copyOfRange methods can do this more simply:
For other ways to copy an array, refer to the following example. Bear in mind that you need an array copy with a
different length to the original when resizing.
Copying arrays
It is inefficient. Making an array bigger (or smaller) involves copying many or all of the existing array
elements, and allocating a new array object. The larger the array, the more expensive it gets.
You need to be able to update any "live" variables that contain references to the old array.
One alternative is to create the array with a large enough size to start with. This is only viable if you can determine
that size accurately before allocating the array. If you cannot do that, then the problem of resizing the array arises
again.
The other alternative is to use a data structure class provided by the Java SE class library or a third-party library. For
example, the Java SE "collections" framework provides a number of implementations of the List, Set and Map APIs
with different runtime properties. The ArrayList class is closest to performance characteristics of a plain array (e.g.
O(N) lookup, O(1) get and set, O(N) random insertion and deletion) while providing more efficient resizing without
the reference update problem.
(The resize efficiency for ArrayList comes from its strategy of doubling the size of the backing array on each resize.
For a typical use-case, this means that you only resize occasionally. When you amortize over the lifetime of the list,
the resize cost per insert is O(1). It may be possible to use the same strategy when resizing a plain array.)
To convert the array, it's possible to use streams (in Java 8 and above):
Version ≥ Java SE 8
int[] primitiveArray = {1, 2, 3, 4};
Integer[] boxedArray =
With lower versions it can be by iterating the primitive array and explicitly copying it to the boxed array:
Version ≥ Java SE 8
Integer[] boxedArray = {1, 2, 3, 4};
int[] primitiveArray =
Arrays.stream(boxedArray).mapToInt(Integer::intValue).toArray();
Version < Java SE 8
Integer[] boxedArray = {1, 2, 3, 4};
int[] primitiveArray = new int[boxedArray.length];
for (int i = 0; i < boxedArray.length; ++i) {
primitiveArray[i] = boxedArray[i]; // Each element is outboxed here
}
Using ArrayList
You can convert the array to a java.util.List, remove the element and convert the list back to an array as follows:
// Creates a new array with the same size as the list and copies the list
// elements to it.
array = list.toArray(new String[list.size()]);
Using System.arraycopy
System.arraycopy() can be used to make a copy of the original array and remove the element you want. Below an
example:
To easily remove an element, you can use the Apache Commons Lang library and especially the static method
removeElement() of the class ArrayUtils. Below an example:
When the element type is a reference type, Arrays.equals() calls equals() on the array elements to determine
equality. In particular, if the element type is itself an array type, identity comparison will be used. To compare
multidimensional arrays for equality, use Arrays.deepEquals() instead as below:
int a[] = { 1, 2, 3 };
int b[] = { 1, 2, 3 };
Because sets and maps use equals() and hashCode(), arrays are generally not useful as set elements or map keys.
Either wrap them in a helper class that implements equals() and hashCode() in terms of the array elements, or
convert them to List instances and store the lists.
for loop
int[] a = { 4, 1, 3, 2 };
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
Note that using this option with an Object array instead of primitive array will fill the copy with reference to the
original content instead of copy of it.
Object.clone()
int[] a = { 4, 1, 3, 2 };
int[] b = a.clone(); // [4, 1, 3, 2]
Note that the Object.clone method for an array performs a shallow copy, i.e. it returns a reference to a new array
which references the same elements as the source array.
Arrays.copyOf()
java.util.Arrays provides an easy way to perform the copy of an array to another. Here is the basic usage:
Note that Arrays.copyOf also provides an overload which allows you to change the type of the array:
System.arraycopy()
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
Copies an array from the specified source array, beginning at the specified position, to the specified
position of the destination array.
int[] a = { 4, 1, 3, 2 };
int[] b = new int[a.length];
System.arraycopy(a, 0, b, 0, a.length); // [4, 1, 3, 2]
Arrays.copyOfRange()
Mainly used to copy a part of an Array, you can also use it to copy whole array to another as below:
int[] a = { 4, 1, 3, 2 };
int[] b = Arrays.copyOfRange(a, 0, a.length); // [4, 1, 3, 2]
Output:
APPLE
BANANA
ORANGE
PEAR
1. Create a Stream<String> containing a sequenced ordered Stream of fruit String elements using the static
factory method Stream.of(values).
2. The filter() operation retains only elements that match a given predicate (the elements that when tested
by the predicate return true). In this case, it retains the elements containing an "a". The predicate is given as
a lambda expression.
3. The map() operation transforms each element using a given function, called a mapper. In this case, each fruit
String is mapped to its uppercase String version using the method-reference String::toUppercase.
Note that the map() operation will return a stream with a different generic type if the mapping
function returns a type different to its input parameter. For example on a Stream<String> calling
.map(String::isEmpty) returns a Stream<Boolean>
4. The sorted() operation sorts the elements of the Stream according to their natural ordering
5. Finally, the forEach(action) operation performs an action which acts on each element of the Stream,
passing it to a Consumer. In the example, each element is simply being printed to the console. This operation
is a terminal operation, thus making it impossible to operate on it again.
Note that operations defined on the Stream are performed because of the terminal operation.
Without a terminal operation, the stream is not processed. Streams can not be reused. Once a
terminal operation is called, the Stream object becomes unusable.
Operations (as seen above) are chained together to form what can be seen as a query on the data.
Closing Streams
Note that a Stream generally does not have to be closed. It is only required to close streams that
operate on IO channels. Most Stream types don't operate on resources and therefore don't require
closing.
The Stream interface extends AutoCloseable. Streams can be closed by calling the close method or by using try-
with-resource statements.
An example use case where a Stream should be closed is when you create a Stream of lines from a file:
The Stream interface also declares the Stream.onClose() method which allows you to register Runnable handlers
which will be called when the stream is closed. An example use case is where code which produces a stream needs
to know when it is consumed to perform some cleanup.
The run handler will only execute if the close() method gets called, either explicitly or implicitly by a try-with-
resources statement.
Processing Order
Example:
// sequential
long howManyOddNumbers = integerList.stream()
.filter(e -> (e % 2) == 1)
.count();
System.out.println(howManyOddNumbers); // Output: 2
Live on Ideone
Parallel mode allows the use of multiple threads on multiple cores but there is no guarantee of the order in which
elements are processed.
If multiple methods are called on a sequential Stream, not every method has to be invoked. For example, if a Stream
is filtered and the number of elements is reduced to one, a subsequent call to a method such as sort will not occur.
This can increase the performance of a sequential Stream — an optimization that is not possible with a parallel
Stream.
Example:
// parallel
long howManyOddNumbersParallel = integerList.parallelStream()
.filter(e -> (e % 2) == 1)
.count();
System.out.println(howManyOddNumbersParallel); // Output: 2
Live on Ideone
While some actions can be performed on both Containers and Streams, they ultimately serve different purposes
and support different operations. Containers are more focused on how the elements are stored and how those
elements can be accessed efficiently. A Stream, on the other hand, doesn't provide direct access and manipulation
to its elements; it is more dedicated to the group of objects as a collective entity and performing operations on that
entity as a whole. Stream and Collection are separate high-level abstractions for these differing purposes.
In the following example, no terminal operation is added to the Stream, so the filter() operation will not be
invoked and no output will be produced because peek() is NOT a terminal operation.
This is a Stream sequence with a valid terminal operation, thus an output is produced.
Live on Ideone
Output:
2
4
6
8
After the terminal operation is performed, the Stream is consumed and cannot be reused.
Although a given stream object cannot be reused, it's easy to create a reusable Iterable that delegates to a stream
pipeline. This can be useful for returning a modified view of a live data set without having to collect results into a
temporary structure.
Output:
foo
bar
foo
bar
This works because Iterable declares a single abstract method Iterator<T> iterator(). That makes it effectively
a functional interface, implemented by a lambda that creates a new stream on each call.
NOTE: Argument checks are always performed, even without a terminal operation:
Live on Ideone
Output:
A classic example of this principle is to use a Map to count the occurrences of elements in a Stream. In this example,
the classifier is simply the identity function, which returns the element as-is. The downstream operation counts the
number of equal elements, using counting().
The downstream operation is itself a collector (Collectors.counting()) that operates on elements of type String
and produces a result of type Long. The result of the collect method call is a Map<String, Long>.
banana=1
orange=1
apple=2
This example generates a Stream of all natural numbers, starting with the number 1. Each successive term of the
Stream is one higher than the previous. By calling the limit method of this Stream, only the first five terms of the
Stream are considered and printed.
1
2
3
4
5
Another way of generating an infinite stream is using the Stream.generate method. This method takes a lambda of
type Supplier.
Elements from a Stream can be easily collected into a container by using the Stream.collect operation:
System.out.println(Arrays
.asList("apple", "banana", "pear", "kiwi", "orange")
.stream()
.filter(s -> s.contains("a"))
.collect(Collectors.toList())
);
// prints: [apple, banana, pear, orange]
Other collection instances, such as a Set, can be made by using other Collectors built-in methods. For example,
Collectors.toSet() collects the elements of a Stream into a Set.
For explicit control over the implementation to be returned, Collectors#toCollection(Supplier) can be used
instead, where the given supplier returns a new and empty collection.
Collector accumulates elements into a Map, Where key is the Student Id and Value is Student Value.
Output :
The mergeFunction often looks like: (s1, s2) -> s1 to retain value corresponding to the repeated key, or (s1,
s2) -> s2 to put new value for the repeated key.
Often it requires to make a map of list out of a primary list. Example: From a student of list, we need to make a map
of list of subjects for each student.
Output:
{ Robert=[LITERATURE],
Sascha=[ENGLISH, MATH, SCIENCE, LITERATURE],
Davis=[MATH, SCIENCE, GEOGRAPHY] }
list.stream().forEach(student -> {
map.computeIfAbsent(student.getName(), s -> new HashMap<>())
.computeIfAbsent(student.getSubject(), s -> new ArrayList<>())
.add(student.getMarks());
});
System.out.println(map);
Output:
{ Robert={ENGLISH=[12.0]},
Sascha={MATH=[80.0, 50.0], ENGLISH=[85.0, 12.0]},
Davis={MATH=[35.0, 37.0], SCIENCE=[12.9, 37.0]} }
Cheat-Sheet
Goal Code
Collect to a List Collectors.toList()
Collect to an ArrayList with pre-
Collectors.toCollection(() -> new ArrayList<>(size))
allocated size
Collect to a Set Collectors.toSet()
Collect to a Set with better iteration
Collectors.toCollection(() -> new LinkedHashSet<>())
performance
Collect to a case-insensitive Collectors.toCollection(() -> new
Set<String> TreeSet<>(String.CASE_INSENSITIVE_ORDER))
Collect to an EnumSet<AnEnum> (best
Collectors.toCollection(() -> EnumSet.noneOf(AnEnum.class))
performance for enums)
Collect to a Map<K,V> with unique keys Collectors.toMap(keyFunc,valFunc)
Map MyObject.getter() to unique
Collectors.toMap(MyObject::getter, Function.identity())
MyObject
Map MyObject.getter() to multiple
Collectors.groupingBy(MyObject::getter)
MyObjects
double pi = Math.sqrt(12) *
IntStream.rangeClosed(0, 100)
.mapToDouble(k -> Math.pow(-3, -1 * k) / (2 * k + 1))
.sum();
Note: With double's precision, selecting an upper bound of 29 is sufficient to get a result that's indistinguishable
from Math.Pi.
System.out.println(allValues);
// [1, 2, 3, 4, 5, 6]
When you want to perform Stream operations concurrently, you could use either of these ways.
Or:
To execute the operations defined for the parallel stream, call a terminal operator:
aParallelStream.forEach(System.out::println);
Three
Four
One
Two
Five
The order might change as all the elements are processed in parallel (Which may make it faster). Use
parallelStream when ordering does not matter.
Performance impact
In case networking is involved, parallel Streams may degrade the overall performance of an application because all
parallel Streams use a common fork-join thread pool for the network.
On the other hand, parallel Streams may significantly improve performance in many other cases, depending of the
number of available cores in the running CPU at the moment.
The difference between Arrays.stream() and Stream.of() is that Stream.of() has a varargs parameter, so it can
be used like:
There are also primitive Streams that you can use. For example:
These primitive streams can also be constructed using the Arrays.stream() method:
Note that any primitive stream can be converted to boxed type stream using the boxed method :
This can be useful in some case if you want to collect the data since primitive stream does not have any collect
method that takes a Collector as argument.
Stream is closed when ever terminal operation is called. Reusing the stream of intermediate operations, when only
terminal operation is only varying. we could create a stream supplier to construct a new stream with all
intermediate operations already set up.
// APPLE
// BANANA
// BLACKBERRY
// BLUEBERRY
Version ≥ Java SE 8
List<Integer> naturalNumbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
IntSummaryStatistics stats = naturalNumbers.stream()
.mapToInt((x) -> x)
.summaryStatistics();
System.out.println(stats);
Version ≥ Java SE 8
IntSummaryStatistics{count=10, sum=55, min=1, max=10, average=5.500000}
IntStream.range(0, names.length)
.mapToObj(i -> String.format("#%d %s", i + 1, names[i]))
.forEach(System.out::println);
The range(start, endExclusive) method returns another ÌntStream and the mapToObj(mapper) returns a stream
of String.
Output:
#1 Jon
#2 Darin
#3 Bauke
#4 Hans
#5 Marc
This is very similar to using a normal for loop with a counter, but with the benefit of pipelining and parallelization:
concat1.forEach(System.out::print);
// prints: abc123
System.out.println(concat2.collect(Collectors.joining(", ")));
// prints: a, b, c, 1, 2, 3, alpha, beta, gamma
Alternatively to simplify the nested concat() syntax the Streams can also be concatenated with flatMap():
System.out.println(concat3.collect(Collectors.joining(", ")));
// prints: a, b, c, 1, 2, 3, alpha, beta, gamma
Be careful when constructing Streams from repeated concatenation, because accessing an element of a deeply
concatenated Stream can result in deep call chains or even a StackOverflowException.
The sum() method of an IntStream is an example of a reduction; it applies addition to every term of the Stream,
resulting in one final value:
The reduce method of a Stream allows one to create a custom reduction. It is possible to use the reduce method to
implement the sum() method:
IntStream istr;
//Initialize istr
OptionalInt istr.reduce((a,b)->a+b);
The Optional version is returned so that empty Streams can be handled appropriately.
Stream<LinkedList<T>> listStream;
//Create a Stream<LinkedList<T>>
You can also provide an identity element. For example, the identity element for addition is 0, as x+0==x. For
multiplication, the identity element is 1, as x*1==x. In the case above, the identity element is an empty
LinkedList<T>, because if you add an empty list to another list, the list that you are "adding" to doesn't change:
Stream<LinkedList<T>> listStream;
//Create a Stream<LinkedList<T>>
Note that when an identity element is provided, the return value is not wrapped in an Optional—if called on an
empty stream, reduce() will return the identity element.
The binary operator must also be associative, meaning that (a+b)+c==a+(b+c). This is because the elements may be
reduced in any order. For example, the above addition reduction could be performed like this:
public static <K, V> Function<K, Map.Entry<K, V>> entryMapper(Function<K, V> mapper){
return (k)->new AbstractMap.SimpleEntry<>(k, mapper.apply(k));
}
Then you can use your converter to process Streams having access to both the original and mapped values:
Set<K> mySet;
Function<K, V> transformer = SomeClass::transformerMethod;
Stream<Map.Entry<K, V>> entryStream = mySet.stream()
.map(entryMapper(transformer));
You can then continue to process that Stream as normal. This avoids the overhead of creating an intermediate
collection.
It is a bit more involved to do the conversion other way around i.e. IntStreamToString. That can be done as follows:
For this example, we will find the first Integer whose square is over 50000.
This last method rewritten using Streams and method references is much more legible and each step of the process
is quickly and easily understood - it's not just shorter, it also shows at a glance which interfaces and classes are
responsible for the code in each step:
Notes:
To make things more declarative, we can use static method in Function interface - Function.identity(). We can
replace this lambda element -> element with Function.identity().
The BinaryOperator passed to Collectors.toMap(...) generates the value to be stored in the case of a collision. It
can:
return the old value, so that the first value in the stream takes precedence,
return the new value, so that the last value in the stream takes precedence, or
combine the old and new values
Grouping by value
You can use Collectors.groupingBy when you need to perform the equivalent of a database cascaded "group by"
operation. To illustrate, the following creates a map in which people's names are mapped to surnames:
Live on Ideone
System.out.println(result);
Output:
The Collectors.joining() method can also cater for pre- and postfixes:
System.out.println(result);
Output:
Live on Ideone
System.out.println(data);
System.out.println(sortedData);
Output:
It's also possible to use different comparison mechanism as there is a overloaded sorted version which takes a
comparator as its argument.
You can use Comparator.reverseOrder() to have a comparator that imposes the reverse of the natural ordering.
List<String> reverseSortedData =
Intermediate Operations:
An intermediate operation is always lazy, such as a simple Stream.map. It is not invoked until the stream is actually
consumed. This can be verified easily:
Intermediate operations are the common building blocks of a stream, chained after the source and are usually
followed by a terminal operation triggering the stream chain.
Terminal Operations
Terminal operations are what triggers the consumption of a stream. Some of the more common are
Stream.forEach or Stream.collect. They are usually placed after a chain of intermediate operations and are
almost always eager.
Stateless Operations
Statelessness means that each item is processed without the context of other items. Stateless operations allow for
memory-efficient processing of streams. Operations like Stream.map and Stream.filter that do not require
information on other items of the stream are considered to be stateless.
Stateful operations
Statefulness means the operation on each item depends on (some) other items of the stream. This requires a state
to be preserved. Statefulness operations may break with long, or infinite, streams. Operations like Stream.sorted
require the entirety of the stream to be processed before any item is emitted which will break in a long enough
stream of items. This can be demonstrated by a long stream (run at your own risk):
First we need to initialize a random number generator. To enhance security for the generated Strings, it is a good
idea to use SecureRandom.
Note: Creating a SecureRandom is quite expensive, so it is best practice to only do this once and call one of its
setSeed() methods from time to time to reseed it.
When creating random Strings, we usually want them to use only certain characters (e.g. only letters and digits).
Therefore we can create a method returning a boolean which can later be used to filter the Stream.
Next we can utilize the RNG to generate a random String of specific length containing the charset which pass our
useThisCharacter check.
//now we can use this Stream to build a String utilizing the collect method.
String randomString = randomCharStream.collect(StringBuilder::new, StringBuilder::append,
StringBuilder::append).toString();
return randomString;
}
Version ≥ Java SE 7
try(FileWriter fw = new FileWriter("outfilename");
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter out = new PrintWriter(bw))
{
out.println("the text");
//more code
out.println("more text");
//more code
} catch (IOException e) {
//handle this however you
}
Remember: try-with-resources guarantees, that the resources have been closed when the block is exited, whether
that happens with the usual control flow or because of an exception.
Version ≤ Java SE 6
Sometimes, try-with-resources is not an option, or maybe you're supporting older version of Java 6 or earlier. In this
case, proper handling is to use a finally block:
FileWriter fw = null;
BufferedWriter bw = null;
PrintWriter out = null;
try {
fw = new FileWriter("myfile.txt");
bw = new BufferedWriter(fw);
out = new PrintWriter(bw);
out.println("the text");
out.close();
} catch (IOException e) {
//handle this however you want
}
finally {
try {
if(out != null)
out.close();
} catch (IOException e) {
//typically not much you can do here...
}
}
Note that closing a wrapper stream will also close its underlying stream. This means you cannot wrap a stream,
close the wrapper and then continue using the original stream.
To speed the process up a bit, it's "usual" to allocate a buffer, so that we don't have too much overhead when
reading from Input.
Version ≥ Java SE 7
public String inputStreamToString(InputStream inputStream) throws Exception {
StringWriter writer = new StringWriter();
Transforming this example to Java SE 6 (and lower)-compatible code is left out as an exercise for the reader.
You can wrap a stream any number of times, just take note of the ordering.
Useful combinations
Compressing and encrypting data before writing to a file while using a buffer
byte b = 0x00;
stream.write( b );
stream.write( bytes );
int offset = 1;
int length = 2;
byte[] bytes = new byte[] { 0xFF, 0x00, 0x00, 0xFF };
Example -
The BufferedReader class is a wrapper for other Reader classes that serves two main purposes:
1. A BufferedReader provides buffering for the wrapped Reader. This allows an application to read characters
one at a time without undue I/O overheads.
The normal pattern for using a BufferedReader is as follows. First, you obtain the Reader that you want to read
characters from. Next you instantiate a BufferedReader that wraps the Reader. Then you read character data.
Finally you close the BufferedReader which close the wrapped `Reader. For example:
Notes:
1. We have used Java 7 (or later) try-with-resources to ensure that the underlying reader is always closed. This
avoids a potential resource leak. In earlier versions of Java, you would explicitly close the BufferedReader in a
finally block.
2. The code inside the try block is virtually identical to what we would use if we read directly from the
FileReader. In fact, a BufferedReader functions exactly like the Reader that it wraps would behave. The
difference is that this version is a lot more efficient.
This is done by getting each line in a file, and adding it into a List<String>. The list is then returned:
Java 8 provides a more concise way to do this using the lines() method:
In StringWriter class, system resources like network sockets and files are not used, therefore closing the
StringWriter is not necessary.
import java.io.*;
public class StringWriterDemo {
public static void main(String[] args) throws IOException {
char[] ary = new char[1024];
StringWriter writer = new StringWriter();
FileInputStream input = null;
BufferedReader buffer = null;
input = new FileInputStream("c://stringwriter.txt");
buffer = new BufferedReader(new InputStreamReader(input, "UTF-8"));
int x;
while ((x = buffer.read(ary)) != -1) {
writer.write(ary, 0, x);
}
System.out.println(writer.toString());
writer.close();
buffer.close();
}
}
The above example helps us to know simple example of StringWriter using BufferedReader to read file data from
the stream.
if (!doShowDialog) {
return true;
}
//
// Show a dialog here...
//
boolean exitWasConfirmed = ...; // whether the user clicked OK or Cancel
boolean doNotShowAgain = ...; // get value from "Do not show again" checkbox
return exitWasConfirmed;
}
PreferenceChangeEvent
A PreferenceChangeEvent gets emitted by a Properties object every time one of the node's key-value-pairs
changes. PreferenceChangeEvents can be listened for with a PreferenceChangeListener:
Version ≥ Java SE 8
preferences.addPreferenceChangeListener(evt -> {
String newValue = evt.getNewValue();
String changedPreferenceKey = evt.getKey();
Preferences changedNode = evt.getNode();
});
Version < Java SE 8
This listener will not listen to changed key-value pairs of child nodes.
NodeChangeEvent
This event will be fired whenever a child node of a Properties node is added or removed.
preferences.addNodeChangeListener(new NodeChangeListener() {
@Override
public void childAdded(NodeChangeEvent evt) {
Preferences addedChild = evt.getChild();
Preferences parentOfAddedChild = evt.getParent();
}
@Override
public void childRemoved(NodeChangeEvent evt) {
Preferences removedChild = evt.getChild();
Preferences parentOfRemovedChild = evt.getParent();
}
});
rRoot ├── com │ └── mycompany │ └── myapp │ ├── darkApplicationMode=true │ ├──
showExitConfirmation=false │ └── windowMaximized=true └── org └── myorganization └── anotherapp
├── defaultFont=Helvetica ├── defaultSavePath=/home/matt/Documents └── exporting ├── defaultFormat=pdf
└── openInBrowserAfterExport=false
package com.mycompany.myapp;
// ...
2. By relative path:
Using a relative path (a path not starting with a /) will cause the path to be resolved relative to the parent
node it is resolved on. For example, the following example will return the node of the path
3. By absolute path:
Using an absolute path on the root node will not be different from using a relative path. The difference is
that, if called on a sub-node, the path will be resolved relative to the root node.
If you have an application which is supposed to run in a single instance only, then no external synchronization is
required.
If you have an application which runs in multiple instances on a single system and therefore Preferences access
needs to be coordinated between the JVMs on the system, then the sync() method of any Preferences node may
be used to ensure changes to the Preferences node are visible to other JVMs on the system:
Version ≥ Java SE 7
try (OutputStream os = ...) {
preferences.exportNode(os);
} catch (IOException ioe) {
Version ≥ Java SE 7
try (OutputStream os = ...) {
preferences.exportNode(os);
} catch (IOException ioe) {
// Exception whilst writing data to the OutputStream
ioe.printStackTrace();
} catch (BackingStoreException bse) {
// Exception whilst reading from the backing preferences store
bse.printStackTrace();
}
Version < Java SE 7
OutputStream os = null;
try {
os = ...;
preferences.exportSubtree(os);
} catch (IOException ioe) {
// Exception whilst writing data to the OutputStream
ioe.printStackTrace();
} catch (BackingStoreException bse) {
// Exception whilst reading from the backing preferences store
bse.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException ignored) {}
}
}
The XML documents will remember whether they were exported from the user or system Preferences. Therefore,
they can be imported into their respective Preferences trees again, without you having to figure out or know where
they came from. The static function will automatically find out whether the XML document was exported from the
user or system Preferences and will automatically import them into the tree they were exported from.
Version ≥ Java SE 7
try (InputStream is = ...) {
// This is a static call on the Preferences class
Preferences.importPreferences(is);
} catch (IOException ioe) {
// Exception whilst reading data from the InputStream
ioe.printStackTrace();
} catch (InvalidPreferencesFormatException ipfe) {
// Exception whilst parsing the XML document tree
ipfe.printStackTrace();
}
Version < Java SE 7
InputStream is = null;
try {
is = ...;
// This is a static call on the Preferences class
Preferences.importPreferences(is);
} catch (IOException ioe) {
// Exception whilst reading data from the InputStream
ioe.printStackTrace();
} catch (InvalidPreferencesFormatException ipfe) {
// Exception whilst parsing the XML document tree
ipfe.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {}
}
}
Version ≥ Java SE 8
Preferences preferences = Preferences.userNodeForPackage(getClass());
//
// later...
//
preferences.removePreferenceChangeListener(listener);
Version < Java SE 8
Preferences preferences = Preferences.userNodeForPackage(getClass());
//
// later...
//
preferences.removePreferenceChangeListener(listener);
Collections framework contains interfaces for Collection<O>, with main sub-interfaces List<O> and Set<O>, and
mapping collection Map<K,V>. Collections are the root interface and are being implemented by many other
collection frameworks.
Given the following list, here are some examples that will give an unexpected result and some that will give the
correct result.
INCORRECT
Removing in iteration of for statement Skips "Banana":
The code sample will only print Apple and Strawberry. Banana is skipped because it moves to index 0 once Apple is
deleted, but at the same time i gets incremented to 1.
Throws: java.util.ConcurrentModificationException
CORRECT
Removing in while loop using an Iterator
Iterator<String> fruitIterator = fruits.iterator();
while(fruitIterator.hasNext()) {
String fruit = fruitIterator.next();
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruitIterator.remove();
The Iterator interface has a remove() method built in just for this case. However, this method is marked as
"optional" in the documentation, and it might throw an UnsupportedOperationException.
Therefore, it is advisable to check the documentation to make sure this operation is supported (in practice, unless
the collection is an immutable one obtained through a 3rd party library or the use of one of the
Collections.unmodifiable...() method, the operation is almost always supported).
While using an Iterator a ConcurrentModificationException is thrown when the modCount of the List is changed
from when the Iterator was created. This could have happened in the same thread or in a multi-threaded
application sharing the same list.
A modCount is an int variable which counts the number of times this list has been structurally modified. A structural
change essentially means an add() or remove() operation being invoked on Collection object (changes made by
Iterator are not counted). When the Iterator is created, it stores this modCount and on every iteration of the List
checks if the current modCount is same as and when the Iterator was created. If there is a change in the modCount
value it throws a ConcurrentModificationException.
Hence for the above-declared list, an operation like below will not throw any exception:
But adding a new element to the List after initializing an Iterator will throw a
ConcurrentModificationException:
Iterating backwards
for (int i = (fruits.size() - 1); i >=0; i--) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
This does not skip anything. The downside of this approach is that the output is reverse. However, in most cases
where you remove items that will not matter. You should never do this with LinkedList.
This does not skip anything. When the ith element is removed from the List, the element originally positioned at
index i+1 becomes the new ith element. Therefore, the loop can decrement i in order for the next iteration to
process the next element, without skipping.
This solution enables the developer to check if the correct elements are removed in a cleaner way.
Version ≥ Java SE 8
In Java 8 the following alternatives are possible. These are cleaner and more straight forward if the removing does not
have to happen in a loop.
Filtering a Stream
A List can be streamed and filtered. A proper filter can be used to remove all undesired elements.
List<String> filteredList =
fruits.stream().filter(p -> !"Apple".equals(p)).collect(Collectors.toList());
Note that unlike all the other examples here, this example produces a new List instance and keeps the original
List unchanged.
Using removeIf
Saves the overhead of constructing a stream if all that is needed is to remove a set of items.
A simple way to construct a List from individual data values is to use java.utils.Arrays method Arrays.asList:
All standard collection implementations provide constructors that take another collection as an argument adding all
elements to the new collection at the time of construction:
Another great framework is Google Guava that is amazing utility class (providing convenience static methods) for
construction of different types of standard collections Lists and Sets:
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
...
List<String> list1 = Lists.newArrayList("ab", "bc", "cd");
List<String> list2 = Lists.newArrayList(data);
Set<String> set4 = Sets.newHashSet(data);
SortedSet<String> set5 = Sets.newTreeSet("bc", "cd", "ab", "bc", "cd");
Mapping Collections
Java Collections framework
Similarly for maps, given a Map<String, Object> map a new map can be constructed with all elements as follows:
Using Apache Commons you can create Map using array in ArrayUtils.toMap as well as MapUtils.toMap:
import org.apache.commons.lang3.ArrayUtils;
...
// Taken from org.apache.commons.lang.ArrayUtils#toMap JavaDoc
Each element of the array must be either a Map.Entry or an Array, containing at least two elements, where the first
element is used as key and the second as value.
import com.google.common.collect.Maps;
...
void howToCreateMapsMethod(Function<? super K,V> valueFunction,
Iterable<K> keys1,
Set<K> keys2,
SortedSet<K> keys3) {
ImmutableMap<K, V> map1 = toMap(keys1, valueFunction); // Immutable copy
Map<K, V> map2 = asMap(keys2, valueFunction); // Live Map view
SortedMap<K, V> map3 = toMap(keys3, valueFunction); // Live Map view
}
Version ≥ Java SE 8
Using Stream,
Stream.of("xyz", "abc").collect(Collectors.toList());
Arrays.stream("xyz", "abc").collect(Collectors.toList());
aListOfFruits.add("Melon");
aListOfFruits.add("Strawberry");
In the above example, the ArrayList will contain the String "Melon" at index 0 and the String "Strawberry" at
index 1.
Also we can add multiple elements with addAll(Collection<? extends E> c) method
Now "Onion" is placed at 0 index in aListOfFruitsAndVeggies, "Melon" is at index 1 and "Strawberry" is at index 2.
names.parallelStream().forEach(System.out::println);
Version ≥ Java SE 5
for (String name : names) {
System.out.println(name);
}
Version < Java SE 5
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
Version ≥ Java SE 1.2
//Creates ListIterator which supports both forward as well as backward traversel
ListIterator<String> listIterator = names.listIterator();
//Iterates list in backward direction once reaches the last element from above iterator in forward
direction
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}
These methods are generic and will automatically convert the returned collection to the type it is assigned to. That
is, an invocation of e.g. emptyList() can be assigned to any type of List and likewise for emptySet() and
emptyMap().
The collections returned by these methods are immutable in that they will throw UnsupportedOperationException
if you attempt to call methods which would change their contents (add, put, etc.). These collections are primarily
useful as substitutes for empty method results or other default values, instead of using null or creating objects
with new.
Example:
Output:
Before Sublist [Hello1, Hello2]
After sublist changes [Hello1, Hello3, Hello2]
Set subSet(fromIndex,toIndex)
The returned set will throw an IllegalArgumentException on an attempt to insert an element outside its range.
If fromKey is greater than toKey or if this map itself has a restricted range, and fromKey or toKey lies outside the
bounds of the range then it throws IllegalArgumentException.
All the collections support backed collections means changes made on the sub collection will have same change on
the main collection.
An unmodifiable collection is often a copy of a modifiable collection which guarantees that the collection itself
cannot be altered. Attempts to modify it will result in an UnsupportedOperationException exception.
It is important to notice that objects which are present inside the collection can still be altered.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.List;
output:
If we run this code, ConcurrentModificationException will be raised since the code modifies the collection while
iterating it. The same exception may occur if one of the multiple threads working with the same list is trying to
modify the collection while others iterate over it. Concurrent modification of collections in multiple threads is a
natural thing, but should be treated with usual tools from the concurrent programming toolbox such as
synchronization locks, special collections adopted for concurrent modification, modifying the cloned collection from
initial etc.
Note: This is only adding on to the Removing items from a List within a loop example:
The following method takes in two Collection objects and performs the magic of removing the elements in our
removeNameList that match with elements in nameList.
Calling the method and passing in the nameList and the removeNameListas follows
removeNames(nameList,removeNameList);
Will produce the following output:
Array List before removing names: James Smith Sonny Huckle Berry Finn Allan
Array List after removing names: James Smith Finn Allan
A simple neat use for Collections that may come in handy to remove repeating elements within lists.
ListUtils.union(listOne,listTwo);
Version ≥ Java SE 8
1. The stuff we want to iterate upon has to be Iterable and expose iterator().
2. Design a java.util.Iterator by overriding hasNext(), next() and remove().
I have added a simple generic linked list implementation below that uses above entities to make the linked list
iterable.
import java.util.Iterator;
import java.util.NoSuchElementException;
Node(T data) {
this.data = data;
}
}
@Override
public boolean hasNext() {
return node != null;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
Node<T> prevNode = node;
node = node.next;
return prevNode.data;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removal logic not implemented.");
}
}
class App {
public static void main(String[] args) {
//Test #1
System.out.println("using Iterator:");
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()) {
Integer i = itr.next();
System.out.print(i + " ");
}
//Test #2
System.out.println("\n\nusing for-each:");
for (Integer data : list) {
System.out.print(data + " ");
}
}
}
Output
using Iterator:
1 2 4 3
using for-each:
1 2 4 3
This will run in Java 7+. You can make it run on Java 5 and Java 6 also by substituting:
with
Unfortunately, the overhead of this is substantial. A HashMap<Integer, Integer> will require about 72 bytes per
entry (e.g. on 64-bit JVM with compressed pointers, and assuming integers larger than 256, and assuming 50% load
of the map). Because the actual data is only 8 bytes, this yields a massive overhead. Furthermore, it requires two
level of indirection (Map -> Entry -> Value) it is unnecessarily slow.
There exist several libraries with optimized collections for primitive data types (that require only ~16 bytes per entry
at 50% load, i.e. 4x less memory, and one level of indirection less), that can yield substantial performance benefits
when using large collections of primitive values in Java.
//The PriorityQueue sorts the elements by using compareTo method of the Integer Class
//The head of this queue is the least element with respect to the specified ordering
System.out.println( queue ); //The Output: [1, 2, 3, 9, 3, 8]
queue.remove();
System.out.println( queue ); //The Output: [2, 3, 3, 9, 8]
queue.remove();
System.out.println( queue ); //The Output: [3, 8, 3, 9]
queue.remove();
System.out.println( queue ); //The Output: [3, 8, 9]
queue.remove();
System.out.println( queue ); //The Output: [8, 9]
queue.remove();
System.out.println( queue ); //The Output: [9]
queue.remove();
System.out.println( queue ); //The Output: []
The Deque inherits the Queue interface which means the regular methods remain, however the Deque interface
offers additional methods to be more flexible with a queue. The additional methods really speak for them self if you
know how a queue works, since those methods are intended to add more flexibility:
Of course the same options for offer, poll and peek are available, however they do not work with exceptions but
rather with special values. There is no point in showing what they do here.
To add elements to the tail of a Deque you call its add() method. You can also use the addFirst() and addLast()
methods, which add elements to the head and tail of the deque.
You can peek at the element at the head of the queue without taking the element out of the queue. This is done via
the element() method. You can also use the getFirst() and getLast() methods, which return the first and last
element in the Deque. Here is how that looks:
Removing Elements
To remove elements from a deque, you call the remove(), removeFirst() and removeLast() methods. Here are a
few examples:
In Java, Stacks are a LIFO (Last In, First Out) Data structure for objects.
Stack API
Example
import java.util.*;
st.push(10);
System.out.println("10 was pushed to the stack");
System.out.println("stack: " + st);
st.push(15);
System.out.println("15 was pushed to the stack");
System.out.println("stack: " + st);
st.push(80);
System.out.println("80 was pushed to the stack");
System.out.println("stack: " + st);
st.pop();
st.pop();
System.out.println("15 was popped from the stack");
System.out.println("stack: " + st);
st.pop();
System.out.println("10 was popped from the stack");
System.out.println("stack: " + st);
if(st.isEmpty())
{
System.out.println("empty stack");
}
}
}
This Returns:
stack: []
10 was pushed to the stack
stack: [10]
15 was pushed to the stack
stack: [10, 15]
80 was pushed to the stack
stack: [10, 15, 80]
80 was popped from the stack
stack: [10, 15]
15 was popped from the stack
stack: [10]
10 was popped from the stack
stack: []
empty stack
BlockingQueue methods come in four forms, with different ways of handling operations that cannot be satisfied
immediately, but may be satisfied at some point in the future: one throws an exception, the second returns a
special value (either null or false, depending on the operation), the third blocks the current thread indefinitely until
the operation can succeed, and the fourth blocks for only a given maximum time limit before giving up.
A BlockingQueue can be bounded or unbounded. A bounded BlockingQueue is one which is initialized with initial
capacity.
An unbounded Queue is one which is initialized without capacity, actually by default it initialized
with Integer.MAX_VALUE.
1. ArrayBlockingQueue
2. LinkedBlockingQueue
3. PriorityBlockingQueue
In the example below, with offer() method, the elements are inserted into the LinkedList. This insertion
operation is called enqueue. In the while loop below, the elements are removed from the Queue based on FIFO. This
operation is called dequeue.
while ( !queue.isEmpty() ) {
System.out.println( queue.poll() );
}
first element
second element
third element
fourth element
fifth element
A Queue is a collection for holding elements prior to processing. Queues typically, but not necessarily, order
elements in a FIFO (first-in-first-out) manner.
Head of the queue is the element that would be removed by a call to remove or poll. In a FIFO queue, all new
elements are inserted at the tail of the queue.
E remove();
E poll();
E element();
E peek();
}
The arrival of Java 9 brings many new features to Java's Collections API, one of which being collection factory
methods. These methods allow for easy initialization of immutable collections, whether they be empty or
nonempty.
Note that these factory methods are only available for the following interfaces: List<E>, Set<E>, and Map<K, V>
Eclipse (GS)
Key's order Value's order Duplicate Analog key Analog value Guava Apache JDK
Collections
HashMap<K,
not defined Insertion-order yes HashMap ArrayList ArrayListMultimap MultiValueMap FastListMultimap
ArrayList<V>>
MultiValueMap.
multiValueMap( new HashMap<K,
not defined not defined no HashMap HashSet HashMultimap HashMap<K, Set>(),
UnifiedSetMultimap
HashSet<V>>
HashSet.class);
Multimaps.
MultiValueMap.multiValueMap(
newMultimap( TreeSortedSet- HashMap<K,
not defined sorted no HashMap TreeSet HashMap, Supplier
new HashMap<K, Set>(),
Multimap TreeSet<V>>
TreeSet.class)
<TreeSet>)
MultiValueMap.
multiValueMap(new LinkedHashMap<
Insertion-order Insertion-order yes LinkedHashMap ArrayList LinkedListMultimap
LinkedHashMap<K, List>(), K, ArrayList>
ArrayList.class);
MultiValueMap.
multiValueMap(new LinkedHashMap<K,
Insertion-order Insertion-order no LinkedHashMap LinkedHashSet LinkedHashMultimap LinkedHashMap<K, Set>(), LinkedHashSet<V>>
LinkedHashSet.class)
MultiValueMap.
multiValueMap( new TreeMap<K,
sorted sorted no TreeMap TreeSet TreeMultimap TreeMap<K, TreeSet<V>>
Set>(),TreeSet.class)
Task: Parse "Hello World! Hello All! Hi World!" string to separate words and print all indexes of every word using
MultiMap (for example, Hello=[0, 2], World!=[1, 5] and so on)
// Fill Multimap
int i = 0;
for(String word: words) {
multiMap.put(word, i);
i++;
}
// Create Multiset
MutableBiMap<String, String> biMap = new HashBiMap(englishWords.length);
// Create English-Polish dictionary
int i = 0;
for(String englishWord: englishWords) {
biMap.put(englishWord, russianWords[i]);
i++;
}
// Fill Multimap
int i = 0;
for(String word: words) {
multiMap.put(word, i);
i++;
}
Nore examples:
I. Apache Collection:
1. MultiValueMap
2. MultiValueMapLinked
3. MultiValueMapTree
1. FastListMultimap
2. HashBagMultimap
3. TreeSortedSetMultimap
4. UnifiedSetMultimap
III. Guava
1. HashMultiMap
2. LinkedHashMultimap
3. LinkedListMultimap
4. TreeMultimap
5. ArrayListMultimap
Apache Commons
Type Guava GS Collections JDK
Collections
Order not
HashMultiset HashBag HashBag HashMap
defined
Sorted TreeMultiset TreeBag TreeBag TreeMap
Insertion-order LinkedHashMultiset - - LinkedHashMap
Concurrent
ConcurrentHashMultiset SynchronizedBag SynchronizedBag Collections.synchronizedMap(HashMap<String, Integer>)
variant
Concurrent
- SynchronizedSortedBag SynchronizedSortedBag Collections.synchronizedSortedMap(TreeMap<String,Integer>)
and sorted
Immutable
ImmutableMultiset UnmodifiableBag UnmodifiableBag Collections.unmodifiableMap(HashMap<String, Integer)]
collection
Immutable Collections.unmodifiableSortedMap(TreeMap<String,
ImmutableSortedMultiset UnmodifiableSortedBag UnmodifiableSortedBag
and sorted Integer>)
Examples:
More examples:
I. Apache Collection:
III. Guava
Examples:
System.out.println(withElements);
System.out.println(withElementsJDK);
System.out.println(withElementsGS);
System.out.println(fromIterable);
System.out.println(fromIterableJDK);
System.out.println(fromIterableGS);
/* Attention: JDK create list only from Collection, but guava and gs can create list from
Iterable and Collection */
2 Create Set
Description JDK guava gs-collections
Create
new HashSet<>() Sets.newHashSet() UnifiedSet.newSet()
empty set
new
Creatre set HashSet<>(Arrays.asList("alpha", Sets.newHashSet("alpha", UnifiedSet.newSetWith("alpha",
from values "beta", "gamma")) "beta", "gamma") "beta", "gamma")
Create set
from any new HashSet<>(collection) Sets.newHashSet(collection) UnifiedSet.newSet(collection)
collections
Create set
from any - Sets.newHashSet(iterable) UnifiedSet.newSet(iterable)
Iterable
Create set
from any - Sets.newHashSet(iterator) -
Iterator
Create set new
Sets.newHashSet(array) UnifiedSet.newSetWith(array)
from Array HashSet<>(Arrays.asList(array))
Examples:
System.out.println("createHashSet start");
// Create empty set
Set<String> emptyGuava = Sets.newHashSet(); // using guava
Set<String> emptyJDK = new HashSet<>(); // using JDK
Set<String> emptyGS = UnifiedSet.newSet(); // using gs
System.out.println(withElements);
System.out.println(withElementsJDK);
System.out.println(withElementsGS);
System.out.println(fromIterable);
System.out.println(fromIterableJDK);
System.out.println(fromIterableGS);
/* Attention: JDK create set only from Collection, but guava and gs can create set from Iterable
and Collection */
System.out.println("createHashSet end");
3 Create Map
Description JDK guava gs-collections
Create empty new
Maps.newHashMap() UnifiedMap.newMap()
map HashMap<>()
Create map
new
with capacity HashMap<>(130)
Maps.newHashMapWithExpectedSize(100) UnifiedMap.newMap(130)
= 130
Create map
new
from other HashMap<>(map)
Maps.newHashMap(map) UnifiedMap.newMap(map)
map
Create map UnifiedMap.newWithKeysValues("1",
- -
from keys "a", "2", "b")
Examples:
System.out.println("createHashMap start");
// Create empty map
Map<String, String> emptyGuava = Maps.newHashMap(); // using guava
Map<String, String> emptyJDK = new HashMap<>(); // using JDK
Map<String, String> emptyGS = UnifiedMap.newMap(); // using gs
System.out.println(withMap);
System.out.println(withMapJDK);
System.out.println(withMapGS);
System.out.println("createHashMap end");
1. CollectionCompare
When you make a thread-safe collection, you should never access it through the original collection, only through
the thread-safe wrapper.
Version ≥ Java SE 5
Starting in Java 5, java.util.collections has several new thread-safe collections that don't need the various
Collections.synchronized methods.
else
{
//'value' reference is mapped to key = 1.
}
}
While thread-safe collections have safe element addition or removal from multiple threads, they do not necessarily
have safe iteration in the same context (one may not be able to safely iterate through the collection in one thread,
while another one modifies it by adding/removing elements).
As iteration is often the base implementation of several bulk methods in collections, like addAll, removeAll, or also
collection copying (through a constructor, or other means), sorting, ... the use case for concurrent collections is
actually pretty large.
For example, the Java SE 5 java.util.concurrent.CopyOnWriteArrayList is a thread safe and concurrent List
implementation, its javadoc states :
The "snapshot" style iterator method uses a reference to the state of the array at the point that the
iterator was created. This array never changes during the lifetime of the iterator, so interference is
impossible and the iterator is guaranteed not to throw ConcurrentModificationException.
Iterators are weakly consistent, returning elements reflecting the state of the queue at some point at or
since the creation of the iterator. They do not throw java.util.ConcurrentModificationException, and may
proceed concurrently with other operations. Elements contained in the queue since the creation of the
iterator will be returned exactly once.
One should check the javadocs to see if a collection is concurrent, or not. The attributes of the iterator returned by
the iterator() method ("fail fast", "weakly consistent", ...) is the most important attribute to look for.
Could (and statistically will on most modern, multi CPU/core architectures) lead to exceptions.
Synchronized collections from the Collections utility methods are thread safe for addition/removal of elements,
but not iteration (unless the underlying collection being passed to it already is).
1. Constructor Level
2. Method Level
3. Variable Level
Constructor Level
super keyword is used to call parent class constructor. This constructor can be default constructor or
parameterized constructor.
class Parentclass
{
Parentclass(){
System.out.println("Constructor of Superclass");
}
}
class Subclass extends Parentclass
{
Subclass(){
/* Compile adds super() here at the first line
* of this constructor implicitly
*/
System.out.println("Constructor of Subclass");
}
Subclass(int n1){
/* Compile adds super() here at the first line
* of this constructor implicitly
*/
System.out.println("Constructor with arg");
}
void display(){
System.out.println("Hello");
}
public static void main(String args[]){
// Creating object using default constructor
Subclass obj= new Subclass();
//Calling sub class method
obj.display();
//Creating object 2 using arg constructor
Subclass obj2= new Subclass(10);
obj2.display();
}
}
Note: super() must be the first statement in constructor otherwise we will get the compilation error message.
Method Level
class Parentclass
{
//Overridden method
void display(){
System.out.println("Parent class method");
}
}
class Subclass extends Parentclass
{
//Overriding method
void display(){
System.out.println("Child class method");
}
void printMsg(){
//This would call Overriding method
display();
//This would call Overridden method
super.display();
}
public static void main(String args[]){
Subclass obj= new Subclass();
obj.printMsg();
}
}
Note:If there is not method overriding then we do not need to use super keyword to call parent class method.
Variable Level
super is used to refer immediate parent class instance variable. In case of inheritance, there may be possibility of
base class and derived class may have similar data members.In order to differentiate between the data member of
base/parent class and derived/child class, in the context of derived class the base class data members must be
preceded by super keyword.
After a serialized object has been written into a file, it can be read from the file and deserialized that is, the type
information and bytes that represent the object and its data can be used to recreate the object in memory.
Serialization is the process of converting an object's state (including its references) to a sequence of bytes, as well
as the process of rebuilding those bytes into a live object at some future time. Serialization is used when you want
to persist the object. It is also used by Java RMI to pass objects between JVMs, either as arguments in a method
invocation from a client to a server or as return values from a method invocation, or as exceptions thrown by
remote methods. In general, serialization is used when we want the object to exist beyond the lifetime of the JVM.
java.io.Serializable is a marker interface (has no body). It is just used to "mark" Java classes as serializable.
The serialization runtime associates with each serializable class a version number, called a serialVersionUID,
which is used during de-serialization to verify that the sender and receiver of a serialized object have loaded classes
for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that
has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in
an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field
named serialVersionUID that must be static, final, and of type long:
To persist an object the respective class must implement the java.io.Serializable interface.
import java.io.Serializable;
public SerialClass() {
currentTime = Calendar.getInstance().getTime();
}
Now we need to write this object to a file system. We use java.io.ObjectOutputStream for this purpose.
import java.io.FileOutputStream;
The stored object can be read from file system at later time using java.io.ObjectInputStream as shown below:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.java.lang.ClassNotFoundException;
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
time = (SerialClass)in.readObject();
in.close();
} catch(IOException ex){
ex.printStackTrace();
} catch(ClassNotFoundException cnfe){
cnfe.printStackTrace();
}
// print out restored time
System.out.println("Restored time: " + time.getTime());
}
}
The serialized class is in binary form. The deserialization can be problematic if the class definition changes: see the
Versioning of Serialized Objects chapter of the Java Serialization Specification for details.
Serializing an object serializes the entire object graph of which it is the root, and operates correctly in the presence
of cyclic graphs. A reset() method is provided to force the ObjectOutputStream to forget about objects that have
already been serialized.
Transient-fields - Serialization
@Override
private void WriteObject(ObjectOutputStreamout) throws IO Exception;
private void ReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
public void run() {
while(true) {
Random rand = new Random();
System.out.println("Thread: " + thread.getId() + " Random:" + rand.nextInt(max - min));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Now if we want to make this class Serializable there will be some problems. The Thread is one of the certain
system-level classes that are not Serializable. So we need to declare the thread as transient. By doing this we will
be able to serialize the objects of this class but we will still have an issue. As you can see in the constructor we set
the min and the max values of our randomizer and after this we start the thread which is responsible for
generating and printing the random value. Thus when restoring the persisted object by calling the readObject() the
constructor will not run again as there is no creation of a new object. In that case we need to develop a Custom
Serialization by providing two methods inside the class. Those methods are:
Thus by adding our implementation in the readObject() we can initiate and start our thread:
}
}
If you run the main you will see that there are two threads running for each RangeRandom instance and that is
because the Thread.start() method is now in both the constructor and the readObject().
This value is used for checking the compatibility of the classes with respect to serialization and this is done while de-
serializing a saved object. The Serialization Runtime verifies that serialVersionUID read from the de-serialized data
and the serialVersionUID declared in the class are exactly the same. If that is not the case, it throws an
InvalidClassException.
It's highly recommended that you explicitly declare and initialize the static, final field of type long and named
'serialVersionUID' in all your classes you want to make Serializable instead of relying on the default computation of
the value for this field even if you are not gonna use versioning. 'serialVersionUID' computation is extremely
sensitive and may vary from one compiler implementation to another and hence you may turn up getting
the InvalidClassException even for the same class just because you used different compiler
implementations on the sender and the receiver ends of the serialization process.
As long as serialVersionUID is the same, Java Serialization can handle different versions of a class. Compatible and
incompatible changes are;
Compatible Changes
Adding fields : When the class being reconstituted has a field that does not occur in the stream, that field in
the object will be initialized to the default value for its type. If class-specific initialization is needed, the class
may provide a readObject method that can initialize the field to nondefault values.
Adding classes : The stream will contain the type hierarchy of each object in the stream. Comparing this
hierarchy in the stream with the current class can detect additional classes. Since there is no information in
the stream from which to initialize the object, the class's fields will be initialized to the default values.
Removing classes : Comparing the class hierarchy in the stream with that of the current class can detect
that a class has been deleted. In this case, the fields and objects corresponding to that class are read from
the stream. Primitive fields are discarded, but the objects referenced by the deleted class are created, since
they may be referred to later in the stream. They will be garbage-collected when the stream is garbage-
collected or reset.
Adding writeObject/readObject methods : If the version reading the stream has these methods then
readObject is expected, as usual, to read the required data written to the stream by the default serialization.
Incompatible Changes
Deleting fields : If a field is deleted in a class, the stream written will not contain its value. When the stream
is read by an earlier class, the value of the field will be set to the default value because no value is available in
the stream. However, this default value may adversely impair the ability of the earlier version to fulfill its
contract.
Moving classes up or down the hierarchy : This cannot be allowed since the data in the stream appears in
the wrong sequence.
Changing a nonstatic field to static or a nontransient field to transient : When relying on default
serialization, this change is equivalent to deleting a field from the class. This version of the class will not write
that data to the stream, so it will not be available to be read by earlier versions of the class. As when deleting
a field, the field of the earlier version will be initialized to the default value, which can cause the class to fail in
unexpected ways.
Changing the declared type of a primitive field : Each version of the class writes the data with its declared
type. Earlier versions of the class attempting to read the field will fail because the type of the data in the
stream does not match the type of the field.
Changing the writeObject or readObject method so that it no longer writes or reads the default field data or
changing it so that it attempts to write it or read it when the previous version did not. The default field data
must consistently either appear or not appear in the stream.
Changing a class from Serializable to Externalizable or vice versa is an incompatible change since the stream
will contain data that is incompatible with the implementation of the available class.
Changing a class from a non-enum type to an enum type or vice versa since the stream will contain data that
is incompatible with the implementation of the available class.
Removing either Serializable or Externalizable is an incompatible change since when written it will no longer
supply the fields needed by older versions of the class.
Adding the writeReplace or readResolve method to a class is incompatible if the behavior would produce an
object that is incompatible with any older version of the class.
(Serialization)
//Skills
List<String> skills = new LinkedList<String>();
skills.add("leadership");
skills.add("Java Experience");
//Employe
Employe obj = new Employe();
obj.setFirstName("Christian");
obj.setLastName("Lusardi");
obj.setAge(25);
obj.setSalary(new BigDecimal("10000"));
obj.setSkills(skills);
//Serialization process
Gson gson = new Gson();
String json = gson.toJson(obj);
//{"firstName":"Christian","lastName":"Lusardi","age":25,"salary":10000,"skills":["leadership","Java
Experience"]}
Note that you can not serialize objects with circular references since that will result in infinite recursion.
(Deserialization)
And
{
"id": 1,
"name": "Program @# 1",
"createdBy": {
"id": 1,
"name": "Bazlur Rahman",
"email": "[email protected]"
},
"contents": "Some contents"
}
Now can do the opposite very easily. If we have this JSON, we can unmarshal to a program object using
ObjectMapper as following –
Now let’s say, this is not the real case, we are going to have a different JSON from an API which doesn’t match with
our Program class.
{
"id": 1,
"name": "Program @# 1",
"ownerId": 1
"contents": "Some contents"
}
Look at the JSON string, you can see, it has a different field that is owenerId.
Now if you want to serialize this JSON as we did earlier, you will have exceptions.
There are two ways to avoid exceptions and have this serialized –
Ignore the onwerId. Add the following annotation in the Program class
@JsonIgnoreProperties(ignoreUnknown = true)
public class Program {}
But there are cases when you actually need this owerId field. Let's say you want to relate it as an id of the User
class.
As you can see, first you have to access the JsonNode from the JonsParser. And then you can easily extract
information from a JsonNode using the get() method. and you have to make sure about the field name. It should
be the exact name, spelling mistake will cause exceptions.
mapper.registerModule(module);
@JsonDeserialize(using = ProgramDeserializer.class)
public class Program {
}
While the enum constants don't necessarily need to be in all-caps, it is Java convention that names of constants are
entirely uppercase, with words separated by underscores.
/**
* This enum is declared in the Season.java file.
*/
public enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
/**
* This enum is declared inside the Day.java file and
* cannot be accessed outside because it's declared as private.
*/
private enum Season {
WINTER,
SPRING,
SUMMER,
FALL
/**
* Constructor
*/
public Day() {
// Illegal. Compilation error
enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
}
Every constant of enum is public, static and final by default. As every constant is static, they can be accessed
directly using the enum name.
Note: this method allocates a new array of values each time it is called.
==
:
Season.FALL == Season.WINTER // false
Season.SPRING == Season.SPRING // true
Another way to compare enum constants is by using equals() as below, which is considered bad practice as you
can easily fall into pitfalls as follows:
Season.FALL.equals(Season.FALL); // true
Season.FALL.equals(Season.WINTER); // false
Season.FALL.equals("FALL"); // false and no compiler error
Furthermore, although the set of instances in the enum cannot be changed at run-time, the instances themselves
are not inherently immutable because like any other class, an enum can contain mutable fields as is demonstrated
below.
// Usage:
MutableExample.A.print(); // Outputs 0
MutableExample.A.increment();
MutableExample.A.print(); // Outputs 1 -- we've changed a field
MutableExample.B.print(); // Outputs 0 -- another instance remains unchanged
However, a good practice is to make enum instances immutable, i.e. when they either don't have any additional
fields or all such fields are marked as final and are immutable themselves. This will ensure that for a lifetime of
the application an enum won't leak any memory and that it is safe to use its instances across all threads.
Enums implicitly implement Serializable and Comparable because the Enum class does:
Coin(int value) {
this.value = value;
}
It is recommended that you keep all fields private and provide getter methods, as there are a finite number of
instances for an enum.
If you were to implement an Enum as a class instead, it would look like this:
Enum constants are technically mutable, so a setter could be added to change the internal structure of an enum
constant. However, this is considered very bad practice and should be avoided.
Coin(int value){
this.value = value;
}
...
You may define multiple constructors in the same enum. When you do, the arguments you pass in your enum
declaration decide which constructor is called:
Coin(int value){
this(value, false);
}
...
Note: All non-primitive enum fields should implement Serializable because the Enum class does.
This allows for each enum member to define its own behaviour for a given operation, without having to switch on
types in a method in the top-level definition.
Note that this pattern is a short form of what is typically achieved using polymorphism and/or implementing
interfaces.
import java.util.function.Predicate;
import java.util.regex.Pattern;
@Override
public boolean test(final String input) {
return this.pattern.matcher(input).matches();
}
}
INSTANCE;
private Attendant() {
// perform some initialization routine
}
According to "Effective Java" book by Joshua Bloch, a single-element enum is the best way to implement a singleton.
This approach has following advantages:
thread safety
guarantee of single instantiation
out-of-the-box serialization
Let's have a method that returns the enum in the opposite direction:
This can be improved further through the use of fields and static initializer blocks:
static {
NORTH.opposite = SOUTH;
SOUTH.opposite = NORTH;
WEST.opposite = EAST;
EAST.opposite = WEST;
}
}
In this example, the opposite direction is stored in a private instance field opposite, which is statically initialized the
first time a Direction is used. In this particular case (because NORTH references SOUTH and conversely), we cannot
use Enums with constructors here (Constructors NORTH(SOUTH), SOUTH(NORTH), EAST(WEST), WEST(EAST) would
be more elegant and would allow opposite to be declared final, but would be self-referential and therefore are
not allowed).
Just as enum can be used for singletons (1 instance classes), it can be used for utility classes (0 instance classes). Just
make sure to terminate the (empty) list of enum constants with a ;.
See the question Zero instance enum vs private constructors for preventing instantiation for a discussion on pro's
and con's compared to private constructors.
/**
* United States coins
*/
public enum Coins {
/**
* One-cent coin, commonly known as a penny,
* is a unit of currency equaling one-hundredth
* of a United States dollar
*/
PENNY(1),
/**
* A nickel is a five-cent coin equaling
* five-hundredth of a United States dollar
*/
NICKEL(5),
/**
* The dime is a ten-cent coin refers to
* one tenth of a United States dollar
/**
* The quarter is a US coin worth 25 cents,
* one-fourth of a United States dollar
*/
QUARTER(25);
Coins(int value){
this.value = value;
}
Suppose three piano students - John, Ben and Luke - are defined in an enum named PianoClass, as follows:
enum PianoClass {
JOHN, BEN, LUKE;
public String getSex() {
return "Male";
}
public String getLevel() {
return "Beginner";
}
}
And one day two other students arrive - Rita and Tom - with a sex (Female) and level (Intermediate) that do not
match the previous ones:
enum PianoClass2 {
JOHN, BEN, LUKE, RITA, TOM;
public String getSex() {
return "Male"; // issue, Rita is a female
}
public String getLevel() {
return "Beginner"; // issue, Tom is an intermediate student
}
}
so that simply adding the new students to the constant declaration, as follows, is not correct:
It's possible to define a specific behavior for each of the constant, Rita and Tom, which overrides the PianoClass2
enum PianoClass3 {
JOHN, BEN, LUKE,
RITA {
@Override
public String getSex() {
return "Female";
}
},
TOM {
@Override
public String getLevel() {
return "Intermediate";
}
};
public String getSex() {
return "Male";
}
public String getLevel() {
return "Beginner";
}
}
and now Tom's level and Rita's sex are as they should be:
Another way to define content specific body is by using constructor, for instance:
enum Friend {
MAT("Male"),
JOHN("Male"),
JANE("Female");
Friend(String gender) {
this.gender = gender;
}
and usage:
/**
* Print out all the values in this enum.
*/
public static void printAllDays() {
for(Day day : Day.values()) {
System.out.println(day.name());
}
}
}
This way, any enum tagged by (implementing) the interface can be used as a parameter, allowing the programmer to
create a variable amount of enums that will be accepted by the method. This can be useful, for example, in APIs
where there is a default (unmodifiable) enum and the user of these APIs want to "extend" the enum with more values.
Sample which shows how to use the enums - note how printEnum() accepts values from both enum types:
printEnum(DefaultValues.VALUE_ONE); // VALUE_ONE
printEnum(DefaultValues.VALUE_TWO); // VALUE_TWO
printEnum(ExtendedValues.VALUE_THREE); // VALUE_THREE
printEnum(ExtendedValues.VALUE_FOUR); // VALUE_FOUR
==
. So, only reference check is needed, no need to use .equals method. Moreover, if .equals used incorrectly, may
raise the NullPointerException while that's not the case with
==
check.
enum Day {
GOOD, AVERAGE, WORST;
}
if (day.equals(Day.GOOD)) {//NullPointerException!
System.out.println("Good Day!");
}
}
}
To group, complement, range the enum values we have EnumSet class which contains different methods.
EnumSet#of : Set of specific enums without any range. Multiple overloaded of methods are there.
EnumSet#complementOf : Set of enum which is complement of enum values provided in method parameter
enum Page {
A1, A2, A3, A4, A5, A6, A7, A8, A9, A10
}
if (range.contains(Page.A4)) {
System.out.println("Range contains A4");
}
if (of.contains(Page.A1)) {
enum DayOfWeek {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}
An enum is compiled with a built-in static valueOf() method which can be used to lookup a constant by its name:
Both of these valueOf() methods will throw an IllegalArgumentException if the specified enum does not have a
constant with a matching name.
The Guava library provides a helper method Enums.getIfPresent() that returns a Guava Optional to eliminate
explicit exception handling:
Coin(int value){
this.value = value;
}
Here we defined an Enum called Coin which represent its value. With the method isGreaterThan we can compare
two enums:
Assume we have:
name() is an internal method in enum that returns the String representation of the enum, the return String
represents exactly how the enum value was defined.
For example:
System.out.println(Fruit.BANANA.name()); // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.name()); // "GRAPE_FRUIT"
However, toString() is likely overridden by developers to make it print a more user friendly String
Don't use toString() if you want to do checking in your code, name() is much more stable for that. Only
use toString() when you are going to output the value to logs or stdout or something
By default:
System.out.println(Fruit.BANANA.toString()); // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.toString()); // "GRAPE_FRUIT"
enum Example {
ONE(1), TWO(2);
enum Example {
ONE(1), TWO(2);
enum Example {
ONE(1), TWO(2);
initialisisation:
K: It is the type of keys maintained by this map. V: It is the type of mapped values.
sort(List<T> list) applicable to lists where T extends Comparable<? super T>, and
sort(List<T> list, Comparator<? super T> c) applicable to lists of any type.
Applying the former requires amending the class of list elements being sorted, which is not always possible. It
might also be undesirable as although it provides the default sorting, other sorting orders may be required in
different circumstances, or sorting is just a one off task.
Consider we have a task of sorting objects that are instances of the following class:
@Override
public String toString() {
return String.format("%s:%d", username, id);
}
}
In order to use Collections.sort(List<User> list) we need to modify the User class to implement the
Comparable interface. For example
@Override
public String toString() {
return String.format("%s:%d", username, id);
}
@Override
/** The natural ordering for 'User' objects is by the 'id' field. */
public int compareTo(User o) {
return id.compareTo(o.id);
}
}
With the modification above, the we can easily sort a list of User objects based on the classes natural ordering. (In
this case, we have defined that to be ordering based on id values). For example:
System.out.print(users);
// [B:25, C:28, A:33]
However, suppose that we wanted to sort User objects by name rather than by id. Alternatively, suppose that we
had not been able to change the class to make it implement Comparable.
This is where the sort method with the Comparator argument is useful:
In Java 8 you can use a lambda instead of an anonymous class. The latter reduces to a one-liner:
Further, there Java 8 adds a default sort method on the List interface, which simplifies sorting even more.
That is:
These are all of the public classes in Java SE 8 that implement the java.util.List interface:
1. Abstract Classes:
AbstractList
AbstractSequentialList
2. Concrete Classes:
ArrayList
AttributeList
CopyOnWriteArrayList
LinkedList
RoleList
RoleUnresolvedList
Stack
Vector
ArrayList is a resizable-array implementation of the List interface. Storing the list into an array, ArrayList provides
methods (in addition to the methods implementing the List interface) for manipulating the size of the array.
List<Integer> myList = new ArrayList<Integer>(100); // Constructs an empty list with the specified
initial capacity.
- PROS:
The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. So getting and setting each
element of the List has the same time cost:
int e1 = myList.get(0); // \
int e2 = myList.get(10); // | => All the same constant cost => O(1)
myList.set(2,10); // /
- CONS:
Being implemented with an array (static structure) adding elements over the size of the array has a big cost due to
the fact that a new allocation need to be done for all the array. However, from documentation:
The add operation runs in amortized constant time, that is, adding n elements requires O(n) time
AttributeList
On coming
On coming
LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
LinkedList is implemented by a doubly-linked list a linked data structure that consists of a set of sequentially linked
records called nodes.
- PROS:
Adding or removing an element to the front of the list or to the end has constant time.
myList.add(10); // \
myList.add(0,2); // | => constant time => O(1)
myList.remove(); // /
Operations that index into the list will traverse the list from the beginning or the end, whichever is closer
to the specified index.
myList.get(10); // \
myList.add(11,25); // | => worst case done in O(n/2)
myList.set(15,35); // /
RoleList
On coming
RoleUnresolvedList
On coming
Stack
On coming
Vector
On coming
Example:
Consider an ArrayList containing the elements "Program starting!", "Hello world!" and "Goodbye world!"
If we know the index of the element we want to replace, we can simply use set as follows:
If we don't know the index, we can search for it first. For example:
Notes:
If you want an unmodifiable list with one item you can use:
Reversing a list:
Collections.reverse(ls);
The rotate method requires an integer argument. This is how many spots to move it along the line by. An example
of this is below:
Using the same list above, we can shuffle the elements in a list:
Collections.shuffle(ls);
We can also give it a java.util.Random object that it uses to randomly place objects in spots:
It extends AbstractList class and implements List interface. An ArrayList can contain duplicate elements where
it maintains insertion order. It should be noted that the class ArrayList is non-synchronized, so care should be
The type of the ArrayList can be any Object. The type can't be a primitive type (use their wrapper classes instead).
myArrayList.add(element);
myArrayList.remove(element);
To create a list you need a type (any class, e.g. String). This is the type of your List. The List will only store objects
of the specified type. For example:
List<String> strings;
Can store "string1", "hello world!", "goodbye", etc, but it can't store 9.2, however:
List<Double> doubles;
If you try to add something to the lists above you will get a NullPointerException, because strings and doubles
both equal null!
List is an interface, which means that does not have a constructor, rather methods that a class must override.
ArrayList is the most commonly used List, though LinkedList is also common. So we initialise our list like this:
or
or
The Collections class provides two useful methods for creating Lists without a List variable:
addAll(L, T...): adds all the specified elements to the list passed as the first parameter.
Examples:
add(T type)
add(int index, T type)
remove(Object o)
remove(int index)
get(int index)
set(int index, E element)
int indexOf(Object o)
int lastIndexOf(Object o)
And we wanted to add the strings "Hello world!" and "Goodbye world!" to it, we would do it as such:
strings.add("Hello world!");
strings.add("Goodbye world!");
And our list would contain the two elements. Now lets say we wanted to add "Program starting!" at the front of the
Now, if we wanted to remove the "Goodbye world!" line, we could do it like this:
strings.remove("Goodbye world!");
And if we wanted to remove the first line (which in this case would be "Program starting!", we could do it like this:
strings.remove(0);
Note:
1. Adding and removing list elements modify the list, and this can lead to a ConcurrentModificationException
if the list is being iterated concurrently.
2. Adding and removing elements can be O(1) or O(N) depending on the list class, the method used, and
whether you are adding / removing an element at the start, the end, or in the middle of the list.
In order to retrieve an element of the list at a specified position you can use the E get(int index); method of the
List API. For example:
strings.get(0);
You can replace any element at a specified position by using the set(int index, E element);. For example:
strings.set(0,"This is a replacement");
This will set the String "This is a replacement" as the first element of the list.
Note: The set method will overwrite the element at the position 0. It will not add the new String at the position 0
and push the old one to the position 1.
The int indexOf(Object o); returns the position of the first occurrence of the object passed as argument. If there
are no occurrences of the object in the list then the -1 value is returned. In continuation of the previous example if
you call:
strings.indexOf("This is a replacement")
the 0 is expected to be returned as we set the String "This is a replacement" in the position 0 of our list. In case
where there are more than one occurrence in the list when int indexOf(Object o); is called then as mentioned
the index of the first occurrence will be returned. By calling the int lastIndexOf(Object o) you can retrieve the
index of the last occurrence in the list. So if we add another "This is a replacement":
strings.add("This is a replacement");
strings.lastIndexOf("This is a replacement");
The best way to iterate over each element is by using a for-each loop:
hello,
how
are
you?
To print them all in the same line, you can use a StringBuilder:
Will print:
Alternatively, you can use element indexing ( as described in Accessing element at ith Index from ArrayList ) to
iterate a list. Warning: this approach is inefficient for linked lists.
List.removeAll(Collection c);
#Example:
numbersB.removeAll(numbersA);
A: [1, 3, 4, 7, 5, 2]
Set have its implementation in various classes like HashSet, TreeSet, LinkedHashSet.
For example:
HashSet:
Here T can be String, Integer or any other object. HashSet allows for quick lookup of O(1) but does not sort the
data added to it and loses the insertion order of items.
TreeSet:
It stores data in a sorted manner sacrificing some speed for basic operations which take O(lg(n)). It does not
maintain the insertion order of items.
LinkedHashSet:
It is a linked list implementation of HashSet Once can iterate over the items in the order they were added. Sorting is
not provided for its contents. O(1) basic operations are provided, however there is higher cost than HashSet in
maintaining the backing linked list.
A set is a data structure which contains a set of elements with an important property that no two elements in the
set are equal.
Types of Set:
Creating a set
set = [12,13]
set = []
Existence of an element in the set can be checked using the contains() method
Output: False
Output: True
Output: 0
Example:
Output:
Using guava:
Using Streams:
Since Map is an interface, then you need to instantiate a concrete implementation of that interface in order to use it;
there are several Map implementations, and mostly used are the java.util.HashMap and java.util.TreeMap
Iterator<Integer> it = map.keySet().iterator();
while (it.hasNext()) {
Integer key = it.next();
sum += key + map.get(key);
}
map.entrySet()
.stream()
.parallel()
.forEach(e -> sum += e.getKey() + e.getValue());
x: Size of Map
f(x): Benchmark Score (μs/op)
1. Declaring HashMap
KeyType and ValueType must be valid types in Java, such as - String, Integer, Float or any custom class like
Employee, Student etc..
To put a value in the HashMap, we have to call put method on the HashMap object by passing the Key and the
Value as parameters.
myMap.put("key1", 1);
myMap.put("key2", 2);
If you call the put method with the Key that already exists in the Map, the method will override its value and return
the old value.
For getting the value from a HashMap you have to call the get method, by passing the Key as a parameter.
If you pass a key that does not exists in the HashMap, this method will return null
myMap.containsKey(varKey);
myMap.containsValue(varValue);
The above methods will return a boolean value true or false if key, value exists in the Map or not.
1. Using getOrDefault
Returns the value mapped to the key, or if the key is not present, returns the default value
2. Using forEach
Allows to perform the operation specified in the 'action' on each Map Entry
3. Using replaceAll
4. Using putIfAbsent
Key-Value pair is added to the map, if the key is not present or mapped to null
5. Using remove
Removes the key only if its associated with the given value
6. Using replace
If the key is present then the value is replaced by new-value. If the key is not present, does nothing.
7. Using computeIfAbsent
This method adds an entry in the Map. the key is specified in the function and the value is the result of the
application of the mapping function
This method adds an entry or modifies an existing entry in the Map. Does nothing if an entry with that key is not
present
9. Using compute
This method replaces the value of a key by the newly computed value
Adds the key-value pair to the map, if key is not present or value for the key is null Replaces the value with the
newly computed value, if the key is present Key is removed from the map , if new value computed is null
//Adds the key-value pair to the map, if key is not present or value for the key is null
map.merge("kelly", 50 , (k,v)->map.get("john")+10); // {john=20, paul=30, peter=40, kelly=50}
//Replaces the value with the newly computed value, if the key is present
map.merge("peter", 50 , (k,v)->map.get("john")+10); //{john=20, paul=30, peter=30, kelly=50}
Darin Dimitrov
Jon Skeet
BalusC
keySet() provides the keys of the map as a Set. Set is used as the keys cannot contain duplicate values. Iterating
through the set yields each key in turn. HashMaps are not ordered, so in this example the keys may be returned in
any order.
Prints:
715567
927654
708826
values() returns the values of the map as a Collection. Iterating through the collection yields each value in turn.
Again, the values may be returned in any order.
Prints:
entrySet() returns a collection of Map.Entry objects. Map.Entry gives access to the key and value for each entry.
"One" -> 1
"Two" -> 2
"Three" -> 4 //old value 3 was overwritten by new value 4
If you want to combine values instead of overwriting them, you can use Map.merge, added in Java 8, which uses a
user-provided BiFunction to merge values for duplicate keys. merge operates on individual keys and values, so
you'll need to use a loop or Map.forEach. Here we concatenate strings for duplicate keys:
If you want to enforce the constraint there are no duplicate keys, you can use a merge function that throws an
AssertionError:
mapA.forEach((k, v) ->
mapB.merge(k, v, (v1, v2) ->
{throw new AssertionError("duplicate values for key: "+k);}));
Associates the specified value with the specified key in this map (optional operation). If the map
previously contained a mapping for the key, the old value is replaced by the specified value.
String currentVal;
Map<Integer, String> map = new TreeMap<>();
map.putAll(map2);
System.out.println(map.size());
Output:
To add many items you can use an inner classes like this:
Keep in mind that creating an anonymous inner class is not always efficient and can lead to memory leaks so when
possible, use an initializer block instead:
static {
// Now no inner classes are created so we can avoid memory leaks
put(5, "high");
put(4, "low");
put(1, "too slow");
}
The example above makes the map static. It can also be used in a non-static context by removing all occurences of
static.
In addition to that most implementations support putAll, which can add all entries in one map to another like this:
another.putAll(one);
Maps stores key/value pairs, where each key has an associated value. Given a particular key, the map can look up
the associated value very quickly.
Way 1:
Way 2:
Way 3:
Way 4:
Way 5:
//Java 8
final Map<String, String> map =
Arrays.stream(new String[][] {
{ "name", "A" },
{ "address", "Malviya-Nagar" },
{ "city", "jaipur" },
}).collect(Collectors.toMap(m -> m[0], m -> m[1]));
System.out.println(map);
Way 6:
Any attemts to modify the map will result in throwing the UnsupportedOperationException.
if (num.containsKey("one")) {
System.out.println(num.get("one")); // => first
}
For maps, one has to be carrefull not to confuse "containing a key" with "having a value". For example, HashMaps
can contain null which means the following is perfectly normal behavior :
2. Override
HashMap is used as an example. Other implementations that implement the Map interface may be used as well.
map.clear();
System.out.println(map.size()); // => 0
class MyKey {
private String name;
MyKey(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof MyKey) {
return this.name.equals(((MyKey)obj).name);
}
return false;
}
@Override
public int hashCode() {
return this.name.hashCode();
}
}
hashCode will decide which hash bucket the key belongs to and equals will decide which object inside that hash
bucket.
Without these method, the reference of your object will be used for above comparison which will not work unless
you use the same object reference every time.
The important points about Java LinkedHashMap class are: A LinkedHashMap contains values based on the key. It
contains only unique elements. It may have one null key and multiple null values. It is same as HashMap instead
maintains insertion order.
Is Hash table and Linked list implementation of the Map interface, with predictable iteration order.
Methods:
void clear().
boolean containsKey(Object key).
Object get(Object key).
protected boolean removeEldestEntry(Map.Entry eldest)
Example:
TreeMap is implemented as a Red-Black tree, which provides O(log n) access times. TreeSet is implemented using
a TreeMap with dummy values.
Version ≥ Java SE 7
TreeMap<Integer, String> treeMap = new TreeMap<>();
Version < Java SE 7
TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
treeMap.put(10, "ten");
treeMap.put(4, "four");
treeMap.put(1, "one");
treeSet.put(12, "twelve");
Once we have a few elements in the map, we can perform some operations:
We can also iterate over the map elements using either an Iterator, or a foreach loop. Note that the entries are
printed according to their natural ordering, not the insertion order:
Version ≥ Java SE 7
for (Entry<Integer, String> entry : treeMap.entrySet()) {
System.out.print(entry + " "); //prints 1=one 4=four 10=ten 12=twelve
}
Version ≥ Java SE 7
TreeSet<Integer> treeSet = new TreeSet<>();
Version < Java SE 7
TreeSet<Integer> treeSet = new TreeSet<Integer>();
treeSet.add(10);
treeSet.add(4);
treeSet.add(1);
Once we have a few elements in the set, we can perform some operations:
System.out.println(treeSet.first()); // Prints 1
System.out.println(treeSet.last()); // Prints 12
System.out.println(treeSet.size()); // Prints 4, since there are 4 elemens in the set
System.out.println(treeSet.contains(12)); // Prints true
System.out.println(treeSet.contains(15)); // Prints false
We can also iterate over the map elements using either an Iterator, or a foreach loop. Note that the entries are
printed according to their natural ordering, not the insertion order:
Version ≥ Java SE 7
for (Integer i : treeSet) {
System.out.print(i + " "); //prints 1 4 10 12
}
To fix that, let's assume that we want to order Person instances based on the order of their ids (private int id).
We could do it in one of two ways:
@Override
public int compareTo(Person o) {
return Integer.compare(this.id, o.id); //Compare by id
}
}
Version ≥ Java SE 8
TreeSet<Person> treeSet = new TreeSet<>((personA, personB) -> Integer.compare(personA.getId(),
personB.getId()));
1. It's very important not to modify any fields used for ordering once an instance has been inserted into a
TreeSet/TreeMap. In the above example, if we change the id of a person that's already inserted into the
collection, we might run into unexpected behavior.
2. It's important to implement the comparison properly and consistently. As per the Javadoc:
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This
implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)
The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 &&
y.compareTo(z)>0) implies x.compareTo(z)>0.
Finally, the implementor must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) ==
sgn(y.compareTo(z)), for all z.
Both TreeMap and TreeSet are safe when read, even concurrently, by multiple threads. So if they have been created
and populated by a single thread (say, at the start of the program), and only then read, but not modified by multiple
threads, there's no reason for synchronization or locking.
However, if read and modified concurrently, or modified concurrently by more than one thread, the collection
might throw a ConcurrentModificationException or behave unexpectedly. In these cases, it's imperative to
synchronize/lock access to the collection using one of the following approaches:
This will provide a SortedSet/SortedMap implementation backed by the actual collection, and synchronized
on some mutex object. Note that this will synchronize all read and write access to the collection on a single
lock, so even concurrent reads would not be possible.
...
//Thread 1
synchronized (set) {
set.add(4);
}
...
//Thread 2
synchronized (set) {
set.remove(5);
}
...
//Thread 1
lock.writeLock().lock();
set.add(4);
lock.writeLock().unlock();
...
//Thread 2
lock.readLock().lock();
set.contains(5);
lock.readLock().unlock();
As opposed to the previous synchronization methods, using a ReadWriteLock allows multiple threads to read from
the map concurrently.
Comparator comparator( ).
Object firstKey( ).
SortedMap headMap(Object end).
Object lastKey( ).
SortedMap subMap(Object start, Object end).
SortedMap tailMap(Object start).
Example
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println();
Implementation of Map.
stores only weak references to its keys.
Weak References : The objects that are referenced only by weak references are garbage collected eagerly; the GC
won’t wait until it needs memory in that case.
If the Java memory manager no longer has a strong reference to the object specified as a key, then the entry in the
map will be removed in WeakHashMap.
Example:
hashMap.put(keyHashMap, "Ankita");
weakHashMap.put(keyWeakHashMap, "Atul");
System.gc();
System.out.println("Before: hash map value:"+hashMap.get("keyHashMap")+" and weak hash map
value:"+weakHashMap.get("keyWeakHashMap"));
keyHashMap = null;
keyWeakHashMap = null;
System.gc();
Calling size() method on HashMap object will return the same number of key-value pairs. size will decrease only if
remove() method is called explicitly on the HashMap object.
Because the garbage collector may discard keys at anytime, a WeakHashMap may behave as though an unknown
thread is silently removing entries. So it is possible for the size method to return smaller values over time.So, in
WeakHashMap size decrease happens automatically.
Additional methods that depend on the presence of the contained value are provided, such as orElse(), which
returns a default value if value not present, and ifPresent() which executes a block of code if the value is present.
(Note that the map() and filter() operations are evaluated immediately, unlike their Stream counterparts which
are only evaluated upon a terminal operation.)
Syntax:
Code examples:
return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "NONE"
return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "SOMETHING"
Because Optional.map() returns an empty optional when its mapping function returns null, you can chain several
map() operations as a form of null-safe dereferencing. This is also known as Null-safe chaining.
Here is an alternative way to get the value from toString() using Optional:
This will return an empty string if any of the mapping functions returned null.
Below is an another example, but slightly different. It will print the value only if none of the mapping functions
returned null.
Optional.ofNullable(foo)
.map(Foo::getBar)
.map(Bar::getBaz)
return Optional.ofNullable(value).orElse("defaultValue");
// returns "something"
return Optional.ofNullable(value).orElse("defaultValue");
// returns "defaultValue"
The crucial difference between the orElse and orElseGet is that the latter is only evaluated when the Optional is
empty while the argument supplied to the former one is evaluated even if the Optional is not empty. The orElse
should therefore only be used for constants and never for supplying value based on any sort of computation.
In the first example, the method simply returns the contained value:
return optional.orElseThrow(IllegalArgumentException::new);
// returns "something" string
In the second example, the method throws an exception because a value hasn't been set:
return optional.orElseThrow(IllegalArgumentException::new);
// throws IllegalArgumentException
You can also use the lambda syntax if throwing an exception with message is needed:
Consider:
It would still call getValueThatIsHardToCalculate() even though it's result is not used as the optional is not empty.
Code examples:
Because numeric types do have a value, there is no special handling for null. Empty containers can be checked with:
presentInt.isPresent(); // Is true.
absentInt.isPresent(); // Is false.
This method is similar to map(Function), but the provided mapper is one whose result is already an
Optional, and if invoked, flatMap does not wrap it with an additional Optional.
In other words, when you chain a method call that returns an Optional, using Optional.flatMap avoids creating
nested Optionals.
If you use Optional.map, you will get a nested Optional; i.e. Optional<Optional<Bar>>.
Optional<Optional<Bar>> nestedOptionalBar =
Optional.of(new Foo())
.map(Foo::getBar);
However, if you use Optional.flatMap, you will get a simple Optional; i.e. Optional<Bar>.
Optional<Bar> optionalBar =
Optional.of(new Foo())
.flatMap(Foo::getBar);
int i = 5;
setPersonName(person, i);
To be fully competent in Java programming, you should be able to explain this example to someone else off the top
of your head. Its concepts are fundamental to understanding how Java works.
As you can see, we have a main that instantiates an object to the variable person, and calls a method to set the name
field in that object to "Bob". Then it calls another method, and passes person as one of two parameters; the other
parameter is an integer variable, set to 5.
The method called sets the name value on the passed object to "Linda', and sets the integer variable passed to 99,
then returns.
Linda 5
So why does the change made to person take effect in main, but the change made to the integer does not?
When the call is made, the main method passes an object reference for person to the setPersonName method; any
change that setAnotherName makes to that object is part of that object, and so those changes are still part of that
object when the method returns.
Another way of saying the same thing: person points to an object (stored on the heap, if you're interested). Any
change the method makes to that object are made "on that object", and are not affected by whether the method
making the change is still active or has returned. When the method returns, any changes made to the object are still
stored on that object.
In Java, all primitives are passed by value. Objects are passed by reference, which means that a pointer to the object
is passed as the parameter to any methods that take them.
One less-obvious thing this means: it is not possible for a called method to create a new object and return it as one
of the parameters. The only way for a method to return an object that is created, directly or indirectly, by the
method call, is as a return value from the method. Let's first see how that would not work, and then how it would
work.
And, back in the main, below the call to setAnotherName, let's put a call to this method and another println call:
getAnotherObjectNot(person);
System.out.println(person.getName());
Linda 5
Linda
What happened to the object that had George? Well, the parameter that was passed in was a pointer to Linda;
when the getAnotherObjectNot method created a new object, it replaced the reference to the Linda object with a
reference to the George object. The Linda object still exists (on the heap), the main method can still access it, but the
getAnotherObjectNot method wouldn't be able to do anything with it after that, because it has no reference to it. It
would appear that the writer of the code intended for the method to create a new object and pass it back, but if so,
it didn't work.
If that is what the writer wanted to do, he would need to return the newly created object from the method,
something like this:
Person mary;
mary = getAnotherObject();
System.out.println(mary.getName());
Linda 5
int i = 5;
setPersonName(person, i);
System.out.println(person.getName() + " " + i);
getAnotherObjectNot(person);
System.out.println(person.getName());
Person person;
person = getAnotherObject();
System.out.println(person.getName());
}
try {
doSomething();
} catch (SomeException e) {
handle(e);
}
// next statement
try {
doSomething();
} catch (SomeException e) {
handleOneWay(e)
} catch (SomeOtherException e) {
handleAnotherWay(e);
}
// next statement
If there are multiple catch blocks, they are tried one at a time starting with the first one, until a match is found for
the exception. The corresponding handler is executed (as above), and then control is passed to the next statement
after the try...catch statement. The catch blocks after the one that matches are always skipped, even if the
handler code throws an exception.
try {
throw new RuntimeException("test");
} catch (Exception e) {
System.out.println("Exception");
} catch (RuntimeException e) {
System.out.println("RuntimeException");
}
This code snippet will output "Exception" rather than "RuntimeException". Since RuntimeException is a subtype of
Exception, the first (more general) catch will be matched. The second (more specific) catch will never be executed.
The lesson to learn from this is that the most specific catch blocks (in terms of the exception types) should appear
first, and the most general ones should be last. (Some Java compilers will warn you if a catch can never be
executed, but this is not a compilation error.)
Starting with Java SE 7, a single catch block can handle a list of unrelated exceptions. The exception type are listed,
separated with a vertical bar (|) symbol. For example:
try {
doSomething();
} catch (SomeException | SomeOtherException e) {
handleSomeException(e);
}
The behavior of a multi-exception catch is a simple extension for the single-exception case. The catch matches if
the thrown exception matches (at least) one of the listed exceptions.
There is some additional subtlety in the specification. The type of e is a synthetic union of the exception types in the
list. When the value of e is used, its static type is the least common supertype of the type union. However, if e is
rethrown within the catch block, the exception types that are thrown are the types in the union. For example:
In the above, IOException and SQLException are checked exceptions whose least common supertype is Exception.
This means that the report method must match report(Exception). However, the compiler knows that the throw
can throw only an IOException or an SQLException. Thus, method can be declared as throws IOException,
SQLException rather than throws Exception. (Which is a good thing: see Pitfall - Throwing Throwable, Exception,
Error or RuntimeException.)
What is a resource?
Java 7 introduced the java.lang.AutoCloseable interface to allow classes to be managed using the try-with-
resources statement. Instances of classes that implement AutoCloseable are referred to as resources. These
typically need to be disposed of in a timely fashion rather than relying on the garbage collector to dispose of them.
A close() method should dispose of the resource in an appropriate fashion. The specification states that it should
be safe to call the method on a resource that has already been disposed of. In addition, classes that implement
Autocloseable are strongly encouraged to declare the close() method to throw a more specific exception than
Exception, or no exception at all.
A wide range of standard Java classes and interfaces implement AutoCloseable. These include:
The syntax of a try-with-resources is based on classical try-catch, try-finally and try-catch-finally forms. Here is an
example of a "basic" form; i.e. the form without a catch or finally.
The resources to be manage are declared as variables in the (...) section after the try clause. In the example
above, we declare a resource variable stream and initialize it to a newly created PrintStream.
Once the resource variables have been initialized, the try block is executed. When that completes, stream.close()
will be called automatically to ensure that the resource does not leak. Note that the close() call happens no matter
how the block completes.
The try-with-resources statement can be enhanced with catch and finally blocks, as with the pre-Java 7 try-catch-
finally syntax. The following code snippet adds a catch block to our previous one to deal with the
FileNotFoundException that the PrintStream constructor can throw:
If either the resource initialization or the try block throws the exception, then the catch block will be executed. The
finally block will always be executed, as with a conventional try-catch-finally statement.
The resource variable is out of scope in the catch and finally blocks.
The resource cleanup will happen before the statement tries to match the catch block.
If the automatic resource cleanup threw an exception, then that could be caught in one of the catch blocks.
The code snippets above show a single resource being managed. In fact, try-with-resources can manage multiple
resources in one statement. For example:
This behaves as you would expect. Both is and os are closed automatically at the end of the try block. There are a
couple of points to note:
The initializations occur in the code order, and later resource variable initializers can use of the values of the
earlier ones.
All resource variables that were successfully initialized will be cleaned up.
Resource variables are cleaned up in reverse order of their declarations.
Thus, in the above example, is is initialized before os and cleaned up after it, and is will be cleaned up if there is an
exception while initializing os.
The Java Language Specification specifies the behavior of try-with-resource forms in terms of the classical try-catch-
finally statement. (Please refer to the JLS for the full details.)
(The JLS specifies that the actual t and primaryException variables will be invisible to normal Java code.)
The enhanced form of try-with-resources is specified as an equivalence with the basic form. For example:
is equivalent to:
try {
try (PrintStream stream = new PrintStream(fileName)) {
stream.println("Hello world!");
}
} catch (NullPointerException ex) {
System.err.println("Null filename");
} finally {
System.err.println("All done");
}
You are writing an API or library for use by others, and you want to allow users of your API to be able to
specifically catch and handle exceptions from your API, and be able to differentiate those exceptions from other,
more generic exceptions.
You are throwing exceptions for a specific kind of error in one part of your program, which you want to
catch and handle in another part of your program, and you want to be able to differentiate these errors from
other, more generic errors.
You can create your own custom exceptions by extending RuntimeException for an unchecked exception, or
checked exception by extending any Exception which is not also subclass of RuntimeException, because:
Subclasses of Exception that are not also subclasses of RuntimeException are checked exceptions
And the fields can be used where the exception is caught and handled:
[...] If a client can reasonably be expected to recover from an exception, make it a checked exception. If a
client cannot do anything to recover from the exception, make it an unchecked exception.
More:
At its most basic, if an InterruptedException is caught it means someone, somewhere, called Thread.interrupt()
on the thread your code is currently running in. You might be inclined to say "It's my code! I'll never interrupt it!"
and therefore do something like this:
But this is exactly the wrong way to handle an "impossible" event occurring. If you know your application will never
encounter an InterruptedException you should treat such an event as a serious violation of your program's
assumptions and exit as quickly as possible.
This does two things; it first restores the interrupt status of the thread (as if the InterruptedException had not
been thrown in the first place), and then it throws an AssertionError indicating the basic invariants of your
application have been violated. If you know for certain that you'll never interrupt the thread this code runs in this is
safe since the catch block should never be reached.
More often, however, you cannot guarantee that your thread will never be interrupted. In particular if you're writing
code that will be executed by an Executor or some other thread-management it's critical that your code responds
promptly to interrupts, otherwise your application will stall or even deadlock.
In such cases the best thing to do is generally to allow the InterruptedException to propagate up the call stack,
adding a throws InterruptedException to each method in turn. This may seem kludgy but it's actually a desirable
property - your method's signatures now indicates to callers that it will respond promptly to interrupts.
// Let the caller determine how to handle the interrupt if you're unsure
public void myLongRunningMethod() throws InterruptedException {
...
}
// Suppresses the exception but resets the interrupted state letting later code
// detect the interrupt and handle it properly.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return ...; // your expectations are still broken at this point - try not to do more work.
}
This method will always return 7 since the finally block associated with the try/catch block is executed before
anything is returned. Now, as finally has return 7;, this value supersedes the try/catch return values.
If the catch block returns a primitive value and that primitive value is subsequently changed in the finally block, the
value returned in the catch block will be returned and the changes from the finally block will be ignored.
System.out.println(n);
}
int returnNumber = 0;
try {
if (number % 2 == 0)
throw new Exception("Exception thrown");
else
return returnNumber;
} catch (Exception e) {
return returnNumber;
} finally {
returnNumber = 1;
class Division {
public static void main(String[] args) {
int a, b, result;
a = input.nextInt();
b = input.nextInt();
result = a / b;
Now we compile and execute the above code, and see the output for an attempted division by zero:
Division by zero is an invalid operation that would produce a value that cannot be represented as an integer. Java
deals with this by throwing an exception. In this case, the exception is an instance of the ArithmeticException class.
Note: The example on creating and reading stack traces explains what the output after the two numbers means.
The utility of an exception is the flow control that it allows. Without using exceptions, a typical solution to this
problem may be to first check if b == 0:
class Division {
public static void main(String[] args) {
int a, b, result;
a = input.nextInt();
b = input.nextInt();
if (b == 0) {
System.out.println("You cannot divide by zero.");
return;
}
This prints the message You cannot divide by zero. to the console and quits the program in a graceful way when
the user tries to divide by zero. An equivalent way of dealing with this problem via exception handling would be to
replace the if flow control with a try-catch block:
...
a = input.nextInt();
b = input.nextInt();
try {
result = a / b;
}
catch (ArithmeticException e) {
System.out.println("An ArithmeticException occurred. Perhaps you tried to divide by zero.");
return;
}
...
It is generally considered good practice to use exception handling as part of the normal flow control of an application
where behavior would otherwise be undefined or unexpected. For instance, instead of returning null when a
method fails, it is usually better practice to throw an exception so that the application making use of the method can
define its own flow control for the situation via exception handling of the kind illustrated above. In some sense, this
gets around the problem of having to return a particular type, as any one of multiple kinds of exceptions may be
thrown to indicate the specific problem that occurred.
For more advice on how and how not to use exceptions, refer to Java Pitfalls - Exception usage
java.lang.Throwable - This is the base class for all exception classes. Its methods and constructors
implement a range of functionality common to all exceptions.
java.lang.Exception - This is the superclass of all normal exceptions.
various standard and custom exception classes.
java.lang.RuntimeException - This the superclass of all normal exceptions that are unchecked
exceptions.
various standard and custom runtime exception classes.
Notes:
One of the criticisms of exception support in some programming languages is that is difficult to know which
exceptions a given method or procedure might throw. Given that an unhandled exception is liable to cause a
program to crash, this can make exceptions a source of fragility.
The Java language addresses this concern with the checked exception mechanism. First, Java classifies exceptions
into two categories:
Checked exceptions typically represent anticipated events that an application should be able to deal with. For
instance, IOException and its subtypes represent error conditions that can occur in I/O operations. Examples
include, file opens failing because a file or directory does not exist, network reads and writes failing because
a network connection has been broken and so on.
Unchecked exceptions typically represent unanticipated events that an application cannot deal with. These
are typically the result of a bug in the application.
(In the following, "thrown" refers to any exception thrown explicitly (by a throw statement), or implicitly (in a failed
dereference, type cast and so on). Similarly, "propagated" refers to an exception that was thrown in a nested call,
and not caught within that call. The sample code below will illustrate this.)
The second part of the checked exception mechanism is that there are restrictions on methods where a checked
exception may occur:
When a checked exception is thrown or propagated in a method, it must either be caught by the method, or
listed in the method's throws clause. (The significance of the throws clause is described in this example.)
When a checked exception is thrown or propagated in an initializer block, it must be caught the the block.
A checked exception cannot be propagated by a method call in a field initialization expression. (There is no
way to catch such an exception.)
These restrictions do not apply to unchecked exceptions. This includes all cases where an exception is thrown
implicitly, since all such cases throw unchecked exceptions.
These code snippets are intended to illustrate the checked exception restrictions. In each case, we show a version
of the code with a compilation error, and a second version with the error corrected.
The first example shows how explicitly thrown checked exceptions can be declared as "thrown" if they should not
be handled in the method.
// INCORRECT
public void methodThrowingCheckedException(boolean flag) {
int i = 1 / 0; // Compiles OK, throws ArithmeticException
if (flag) {
throw new MyException(); // Compilation error
} else {
throw new MyException2(); // Compiles OK
}
}
// CORRECTED
public void methodThrowingCheckedException(boolean flag) throws MyException {
int i = 1 / 0; // Compiles OK, throws ArithmeticException
if (flag) {
throw new MyException(); // Compilation error
} else {
throw new MyException2(); // Compiles OK
}
}
The second example shows how a propagated checked exception can be dealt with.
// INCORRECT
public void methodWithPropagatedCheckedException() {
InputStream is = new FileInputStream("someFile.txt"); // Compilation error
// FileInputStream throws IOException or a subclass if the file cannot
// be opened. IOException is a checked exception.
...
}
// CORRECTED (Version A)
public void methodWithPropagatedCheckedException() throws IOException {
InputStream is = new FileInputStream("someFile.txt");
...
}
// CORRECTED (Version B)
public void methodWithPropagatedCheckedException() {
try {
InputStream is = new FileInputStream("someFile.txt");
...
} catch (IOException ex) {
System.out.println("Cannot open file: " + ex.getMessage());
}
}
The final example shows how to deal with a checked exception in a static field initializer.
// INCORRECT
public class Test {
// CORRECTED
public class Test {
private static final InputStream is;
static {
InputStream tmp = null;
try {
tmp = new FileInputStream("someFile.txt");
} catch (IOException ex) {
System.out.println("Cannot open file: " + ex.getMessage());
}
is = tmp;
}
}
Note that in this last case, we also have to deal with the problems that is cannot be assigned to more than once,
and yet also has to be assigned to, even in the case of an exception.
Printing a stacktrace
Printing a stacktrace is simply a matter of calling the printStackTrace() method. For example:
try {
int a = 0;
int b = 0;
int c = a / b;
} catch (ArithmeticException ex) {
// This prints the stacktrace to standard output
ex.printStackTrace();
}
The printStackTrace() method without arguments will print to the application's standard output; i.e. the current
System.out. There are also printStackTrace(PrintStream) and printStackTrace(PrintWriter) overloads that
print to a specified Stream or Writer.
Notes:
1. The stacktrace does not include the details of the exception itself. You can use the toString() method to get
those details; e.g.
2. Stacktrace printing should be used sparingly; see Pitfall - Excessive or inappropriate stacktraces . It is often
better to use a logging framework, and pass the exception object to be logged.
Understanding a stacktrace
File: "Main.java"
1 public class Main {
2 public static void main(String[] args) {
3 new Test().foo();
4 }
5 }
File: "Test.java"
1 class Test {
2 public void foo() {
3 bar();
4 }
5
6 public int bar() {
7 int a = 1;
8 int b = 0;
9 return a / b;
10 }
When these files are compiled and run, we will get the following output.
Let us read this one line at a time to figure out what it is telling us.
Line #1 tells us that the thread called "main" has terminated due to an uncaught exception. The full name of the
exception is java.lang.ArithmeticException, and the exception message is "/ by zero".
Thrown when an exceptional arithmetic condition has occurred. For example, an integer "divide by zero"
throws an instance of this class.
Indeed, the message "/ by zero" is a strong hint that the cause of the exception is that some code has attempted to
divide something by zero. But what?
The remaining 3 lines are the stack trace. Each line represents a method (or constructor) call on the call stack, and
each one tells us three things:
the name of the class and method that was being executed,
the source code filename,
the source code line number of the statement that was being executed
These lines of a stacktrace are listed with the frame for the current call at the top. The top frame in our example
above is in the Test.bar method, and at line 9 of the Test.java file. That is the following line:
return a / b;
If we needed to go further, we can see from the stacktrace that bar() was called from foo() at line 3 of Test.java,
and that foo() was in turn called from Main.main().
Note: The class and method names in the stack frames are the internal names for the classes and methods. You will
need to recognize the following unusual cases:
(In some versions of Java, the stacktrace formatting code will detect and elide repeated stackframe sequences, as
can occur when an application fails due to excessive recursion.)
Exception chaining happens when a piece of code catches an exception, and then creates and throws a new one,
passing the first exception as the cause. Here is an example:
File: Test,java
1 public class Test {
2 int foo() {
3 return 0 / 0;
4 }
5
6 public Test() {
7 try {
8 foo();
9 } catch (ArithmeticException ex) {
10 throw new RuntimeException("A bad thing happened", ex);
11 }
12 }
13
14 public static void main(String[] args) {
15 new Test();
16 }
17 }
When the above class is compiled and run, we get the following stacktrace:
The stacktrace starts with the class name, method and call stack for the exception that (in this case) caused the
application to crash. This is followed by a "Caused by:" line that reports the cause exception. The class name and
message are reported, followed by the cause exception's stack frames. The trace ends with an "... N more" which
indicates that the last N frames are the same as for the previous exception.
Note: the cause mechanism was only exposed in the Throwable API in Java 1.4.0. Prior to that, exception chaining
needed to be implemented by the application using a custom exception field to represent the cause, and a custom
printStackTrace method.
Sometimes, an application needs to be able to capture a stacktrace as a Java String, so that it can be used for other
purposes. The general approach for doing this is to create a temporary OutputStream or Writer that writes to an in-
memory buffer and pass that to the printStackTrace(...).
The Apache Commons and Guava libraries provide utility methods for capturing a stacktrace as a String:
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)
com.google.common.base.Throwables.getStackTraceAsString(Throwable)
If you cannot use third party libraries in your code base, then the following method with do the task:
/**
* Returns the string representation of the stack trace.
*
* @param throwable the throwable
* @return the string.
*/
public static String stackTraceToString(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
throwable.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
Note that if your intention is to analyze the stacktrace, it is simpler to use getStackTrace() and getCause() than to
attempt to parse a stacktrace.
The exception is thrown on the 3rd line. This statement can be broken down into two parts:
When the exception is thrown, it causes the enclosing statements to terminate abnormally until the exception is
handled. This is described in other examples.
We have declared the checkNumber as throws IllegalArgumentException. This was not strictly necessary,
since IllegalArgumentException is a checked exception; see The Java Exception Hierarchy - Unchecked and
Checked Exceptions. However, it is good practice to do this, and also to include the exceptions thrown a
method's javadoc comments.
the compiler would report a compilation error for the return statement.
Exception chaining
Many standard exceptions have a constructor with a second cause argument in addition to the conventional
message argument. The cause allows you to chain exceptions. Here is an example.
First we define an unchecked exception that our application is going throw when it encounters a non-recoverable
error. Note that we have included a constructor that accepts a cause argument.
The primary use of exception stacktraces is to provide information about an application error and its context so
that the programmer can diagnose and fix the problem. Sometimes it can be used for other things. For example, a
SecurityManager class may need to examine the call stack to decide whether the code that is making a call should
be trusted.
You can use exceptions to examine the call stack programatically as follows:
1. The information available in a StackTraceElement is limited. There is no more information available than is
displayed by printStackTrace. (The values of the local variables in the frame are not available.)
2. The javadocs for getStackTrace() state that a JVM is permitted to leave out frames:
Some virtual machines may, under some circumstances, omit one or more stack frames from the
stack trace. In the extreme case, a virtual machine that has no stack trace information concerning
this throwable is permitted to return a zero-length array from this method.
As mentioned elsewhere, constructing an exception is rather expensive because it entails capturing and recording
information about all stack frames on the current thread. Sometimes, we know that that information is never going
to be used for a given exception; e.g. the stacktrace will never be printed. In that case, there is an implementation
trick that we can use in a custom exception to cause the information to not be captured.
The stack frame information needed for stacktraces, is captured when the Throwable constructors call the
Throwable.fillInStackTrace() method. This method is public, which means that a subclass can override it. The
trick is to override the method inherited from Throwable with one that does nothing; e.g.
@Override
public void fillInStackTrace() {
// do nothing
}
The problem with this approach is that an exception that overrides fillInStackTrace() can never capture the
stacktrace, and is useless in scenarios where you need one.
In some situations, the stacktrace for an exception created in the normal way contains either incorrect information,
or information that the developer does not want to reveal to the user. For these scenarios, the
Throwable.setStackTrace can be used to replace the array of StackTraceElement objects that holds the
information.
For example, the following can be used to discard an exception's stack information:
exception.setStackTrace(new StackTraceElement[0]);
Suppressed exceptions
Version ≥ Java SE 7
Java 7 introduced the try-with-resources construct, and the associated concept of exception suppression. Consider
the following snippet:
When the exception is thrown, the try will call close() on the w which will flush any buffered output and then close
the FileWriter. But what happens if an IOException is thrown while flushing the output?
What happens is that any exception that is thrown while cleaning up a resource is suppressed. The exception is
caught, and added to the primary exception's suppressed exception list. Next the try-with-resources will continue
with the cleanup of the other resources. Finally, primary exception will be rethrown.
A similar pattern occurs if an exception it thrown during the resource initialization, or if the try block completes
normally. The first exception thrown becomes the primary exception, and subsequent ones arising from cleanup
are suppressed.
The suppressed exceptions can be retrieved from the primary exception object by calling
getSuppressedExceptions.
Try-finally
try {
doSomething();
} finally {
cleanUp();
The code within finally block will always be executed. (The only exceptions are if System.exit(int) is called, or if
the JVM panics.) Thus a finally block is the correct place code that always needs to be executed; e.g. closing files
and other resources or releasing locks.
try-catch-finally
Our second example shows how catch and finally can be used together. It also illustrates that cleaning up
resources is not straightforward.
The complete set of (hypothetical) behaviors of try...catch...finally in this example are too complicated to
describe here. The simple version is that the code in the finally block will always be executed.
We declare the "resource" (i.e. reader variable) before the try block so that it will be in scope for the finally
block.
By putting the new FileReader(...), the catch is able to handle any IOError exception from thrown when
opening the file.
We need a reader.close() in the finally block because there are some exception paths that we cannot
intercept either in the try block or in catch block.
However, since an exception might have been thrown before reader was initialized, we also need an explicit
null test.
Finally, the reader.close() call might (hypothetically) throw an exception. We don't care about that, but if we
don't catch the exception at source, we would need to deal with it further up the call stack.
Java 7 and later provide an alternative try-with-resources syntax which significantly simplifies resource clean-up.
The throws OddNumberException declares that a call to checkEven could throw an exception that is of type
OddNumberException.
A throws clause can declare a list of types, and can include unchecked exceptions as well as checked exceptions.
1. It tells the compiler which exceptions are thrown so that the compiler can report uncaught (checked)
exceptions as errors.
2. It tells a programmer who is writing code that calls the method what exceptions to expect. For this purpose,
it often makes to senses to include unchecked exceptions in a throws list.
Note: that the throws list is also used by the javadoc tool when generating API documentation, and by a typical IDE's
"hover text" method tips.
The throws clause forms part of a method's signature for the purpose of method overriding. An override method
can be declared with the same set of checked exceptions as thrown by the overridden method, or with a subset.
However the override method cannot add extra checked exceptions. For example:
@Override
public void checkEven(int number) throws NullPointerException // OK—NullPointerException is an
unchecked exception
...
@Override
@Override
public void checkEven(int number) throws PrimeNumberException, NonEvenNumberException // OK—these
are both subclasses
@Override
public void checkEven(Double number) throws IOExcepion // ERROR
The reason for this rule is that if an overriden method can throw a checked exception that the overridden method
could not throw, that would break type substitutability.
It's important to notice that months in Calendar are zero based, which means that JANUARY is represented by an
int value 0. In order to provide a better code, always use Calendar constants, such as Calendar.JANUARY to avoid
misunderstandings.
Note: Always use the month constants: The numeric representation is misleading, e.g. Calendar.JANUARY has the
value 0
The add() method affects all fields, and behaves effectively if one were to add or subtract actual dates from the
calendar
calendar.add(Calendar.MONTH, -6);
The above operation removes six months from the calendar, taking us back to 30 September 2015.
To change a particular field without affecting the other fields, use roll().
calendar.roll(Calendar.MONTH, -6);
The above operation removes six months from the current month, so the month is identified as September. No
other fields have been adjusted; the year has not changed with this operation.
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c2.set(Calendar.DATE, c2.get(Calendar.DATE) + 1);
For example you might want to have an immutable list of constants, it would be a good idea to keep it static and
initialize it just once inside a static method. This would give you a significant performance gain if you are creating
several instances of a particular class on a regular basis.
Furthermore you can also have a static block in a class as well. You can use it to assign a default value to a static
variable. They are executed only once when the class is loaded into memory.
Instance variable as the name suggest are dependent on an instance of a particular object, they live to serve the
whims of it. You can play around with them during a particular life cycle of an object.
All the fields and methods of a class used inside a static method of that class must be static or local. If you try to use
instance (non-static) variables or methods, your code will not compile.
static E STATIC_VARIABLE_NAME
As constants cannot change, static can also be used with the final modifier:
It can be used to get property value based on the property key. The Properties class provides methods to get data
from properties file and store data into properties file. Moreover, it can be used to get properties of system.
Recompilation is not required, if information is changed from properties file: If any information is changed from
The way you store properties files as XML files is very similar to the way you would store them as .properties files.
Just instead of using the store() you would use storeToXML().
Now to load this file as a properties you need to call the loadFromXML() instead of the load() that you would use
with regular .propeties files.
When you run this code you will get the following in the console:
age=23
color=green
name=Steve
Since trailing whitespace is preserved the value of lastName would be "Smith" in the first case and "Smith " in the
second case.
Very rarely this is what users expect and one and can only speculate why this is the default behavior of Properties
class. It is however easy to create an enhanced version of Properties that fixes this problem. The following class,
TrimmedProperties, does just that. It is a drop-in replacement for standard Properties class.
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Map.Entry;
import java.util.Properties;
/**
* Properties class where values are trimmed for trailing whitespace if the
* properties are loaded from a file.
*
* <p>
* In the standard {@link java.util.Properties Properties} class trailing
* whitespace is always preserved. When loading properties from a file such
* trailing whitespace is almost always <i>unintentional</i>. This class fixes
* this problem. The trimming of trailing whitespace only takes place if the
* source of input is a file and only where the input is line oriented (meaning
* that for example loading from XML file is <i>not</i> changed by this class).
* For this reason this class is almost in all cases a safe drop-in replacement
* for the standard <tt>Properties</tt>
* class.
*
* <p>
* Whitespace is defined here as any of space (U+0020) or tab (U+0009).
* *
*/
public class TrimmedProperties extends Properties {
/**
* Reads a property list (key and element pairs) from the input byte stream.
*
* <p>Behaves exactly as {@link java.util.Properties#load(java.io.InputStream) }
* with the exception that trailing whitespace is trimmed from property values
* if <tt>inStream</tt> is an instance of <tt>FileInputStream</tt>.
*
* @see java.util.Properties#load(java.io.InputStream)
* @param inStream the input stream.
* @throws IOException if an error occurred when reading from the input stream.
*/
@Override
public void load(InputStream inStream) throws IOException {
if (inStream instanceof FileInputStream) {
// First read into temporary props using the standard way
Properties tempProps = new Properties();
tempProps.load(inStream);
/**
* Reads a property list (key and element pairs) from the input character stream in a simple
line-oriented format.
*
* <p>Behaves exactly as {@link java.util.Properties#load(java.io.Reader)}
* with the exception that trailing whitespace is trimmed on property values
* if <tt>reader</tt> is an instance of <tt>FileReader</tt>.
*
* @see java.util.Properties#load(java.io.Reader) }
* @param reader the input character stream.
* @throws IOException if an error occurred when reading from the input stream.
*/
@Override
public void load(Reader reader) throws IOException {
if (reader instanceof FileReader) {
// First read into temporary props using the standard way
Properties tempProps = new Properties();
tempProps.load(reader);
// Now trim and put into target
trimAndLoad(tempProps);
} else {
super.load(reader);
}
}
/**
* Trims trailing space or tabs from a string.
*
* @param str
* @return
*/
public static String trimTrailing(String str) {
if (str != null) {
// read str from tail until char is no longer whitespace
for (int i = str.length() - 1; i >= 0; i--) {
if ((str.charAt(i) != ' ') && (str.charAt(i) != '\t')) {
return str.substring(0, i + 1);
}
}
}
return str;
}
}
Method references implement functional interfaces using existing methods rather than expressions. They belong to
the lambda family as well.
Lambdas can only operate on a functional interface, which is an interface with just one abstract method. Functional
interfaces can have any number of default or static methods. (For this reason, they are sometimes referred to as
Single Abstract Method Interfaces, or SAM Interfaces).
interface Foo1 {
void bar();
}
interface Foo2 {
int bar(boolean baz);
}
interface Foo3 {
String bar(Object baz, int mink);
}
interface Foo4 {
default String bar() { // default so not counted
return "baz";
}
void quux();
}
When declaring a functional interface the @FunctionalInterface annotation can be added. This has no special
effect, but a compiler error will be generated if this annotation is applied to an interface which is not functional,
thus acting as a reminder that the interface should not be changed.
@FunctionalInterface
interface Foo5 {
void bar();
}
@FunctionalInterface
interface BlankFoo1 extends Foo3 { // inherits abstract method from Foo3
}
@FunctionalInterface
interface Foo6 {
void bar();
boolean equals(Object obj); // overrides one of Object's method so not counted
}
Conversely, this is not a functional interface, as it has more than one abstract method:
This is also not a functional interface, as it does not have any methods:
interface BlankFoo2 { }
and
Then Child cannot be a functional interface since it has two specified methods.
Java 8 also provides a number of generic templated functional interfaces in the package java.util.function. For
example, the built-in interface Predicate<T> wraps a single method which inputs a value of type T and returns a
boolean.
Lambda Expressions
fi will then hold a singleton instance of a class, similar to an anonymous class, which implements
FunctionalInterface and where the one method's definition is { System.out.println("Hello"); }. In other
words, the above is mostly equivalent to:
The lambda is only "mostly equivalent" to the anonymous class because in a lambda, the meaning of expressions
like this, super or toString() reference the class within which the assignment takes place, not the newly created
object.
You cannot specify the name of the method when using a lambda—but you shouldn't need to, because a functional
interface must have only one abstract method, so Java overrides that one.
In cases where the type of the lambda is not certain, (e.g. overloaded methods) you can add a cast to the lambda to
If the functional interface's single method takes parameters, the local formal names of these should appear
between the brackets of the lambda. There is no need to declare the type of the parameter or return as these are
taken from the interface (although it is not an error to declare the parameter types if you want to). Thus, these two
examples are equivalent:
The parentheses around the argument can be omitted if the function only has one argument:
Implicit Returns
If the code placed inside a lambda is a Java expression rather than a statement, it is treated as a method which
returns the value of the expression. Thus, the following two are equivalent:
Since lambdas are syntactic shorthand for anonymous classes, they follow the same rules for accessing local
variables in the enclosing scope; the variables must be treated as final and not modified inside the lambda.
If it is necessary to wrap a changing variable in this way, a regular object that keeps a copy of the variable should be
used. Read more in Java Closures with lambda expressions.
Accepting Lambdas
Because a lambda is an implementation of an interface, nothing special needs to be done to make a method accept
a lambda: any function which takes a functional interface can also accept a lambda.
Until any such assignment to a functional type is made, the lambda does not have a definite type. To illustrate,
consider the lambda expression o -> o.isEmpty(). The same lambda expression can be assigned to many
different functional types:
Now that they are assigned, the examples shown are of completely different types even though the lambda
expressions looked the same, and they cannot be assigned to each other.
Prior to Java 8, it was necessary to implement the java.util.Comparator interface with an anonymous (or named)
class when sorting a list1:
Starting with Java 8, the anonymous class can be replaced with a lambda expression. Note that the types for the
parameters p1 and p2 can be left out, as the compiler will infer them automatically:
Collections.sort(
people,
(p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName())
);
The example can be simplified by using Comparator.comparing and method references expressed using the ::
(double colon) symbol.
Collections.sort(
people,
Comparator.comparing(Person::getFirstName)
A static import allows us to express this more concisely, but it is debatable whether this improves overall
readability:
Comparators built this way can also be chained together. For example, after comparing people by their first name,
if there are people with the same first name, the thenComparing method with also compare by last name:
sort(people, comparing(Person::getFirstName).thenComparing(Person::getLastName));
1 - Note that Collections.sort(...) only works on collections that are subtypes of List. The Set and Collection APIs
do not imply any ordering of the elements.
Sorting maps
You can sort the entries of a HashMap by value in a similar fashion. (Note that a LinkedHashMap must be used as the
target. The keys in an ordinary HashMap are unordered.)
Map<String, Integer> map = new HashMap(); // ... or any other Map class
// populate the map
map = map.entrySet()
.stream()
.sorted(Map.Entry.<String, Integer>comparingByValue())
.collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue(),
(k, v) -> k, LinkedHashMap::new));
class Person {
private final String name;
private final String surname;
In this example, a method reference to the instance method getName() of type Person, is being passed. Since it's
known to be of the collection type, the method on the instance (known later) will be invoked.
Since System.out is an instance of PrintStream, a method reference to this specific instance is being passed as an
argument.
This example passes a reference to the static valueOf() method on the String type. Therefore, the instance object
in the collection is passed as an argument to valueOf().
Reference to a constructor
List<String> strings = Arrays.asList("1", "2", "3");
strings.stream().map(Integer::new)
Read Collect Elements of a Stream into a Collection to see how to collect elements to collection.
The single String argument constructor of the Integer type is being used here, to construct an integer given the
string provided as the argument. In this case, as long as the string represents a number, the stream will be mapped
to Integers. The equivalent lambda:
Cheat-Sheet
Method Reference Format Code Equivalent Lambda
Static method TypeName::method (args) -> TypeName.method(args)
Non-static method (on instance*) instance::method (args) -> instance.method(args)
Non-static method (no instance) TypeName::method (instance, args) -> instance.method(args)
Constructor** TypeName::new (args) -> new TypeName(args)
Array constructor TypeName[]::new (int size) -> new TypeName[size]
* instance can be any expression that evaluates to a reference to an instance, e.g. getInstance()::method,
this::method
** If TypeName is a non-static inner class, constructor reference is only valid within the scope of an outer class
instance
For example, you want to create a TreeSet with a custom Comparator and then serialize it and send it over the
network. The trivial approach:
doesn't work since the lambda for the comparator does not implement Serializable. You can fix this by using
intersection types and explicitly specifying that this lambda needs to be serializable:
If you're frequently using intersection types (for example, if you're using a framework such as Apache Spark where
almost everything has to be serializable), you can create empty interfaces and use them in your code instead:
This way you're guaranteed that the passed comparator will be serializable.
Before Java 8, it’s very common that an anonymous class is used to handle click event of a JButton, as shown in the
following code. This example shows how to implement an anonymous listener within the scope of
btn.addActionListener.
Lambda listener
Because the ActionListener interface defines only one method actionPerformed(), it is a functional interface
which means there’s a place to use Lambda expressions to replace the boilerplate code. The above example can be
re-written using Lambda expressions as follows:
Local variables from an enclosing scope that are used within a lambda have to be final. With Java 8 (the earliest
version that supports lambdas), they don't need to be declared final in the outside context, but must be treated
that way. For example:
This is legal as long as the value of the n variable is not changed. If you try to change the variable, inside or outside
the lambda, you will get the following compilation error:
"local variables referenced from a lambda expression must be final or effectively final".
For example:
int n = 0;
Runnable r = () -> { // Using lambda
int i = n;
// do something
};
n++; // Will generate an error.
If it is necessary to use a changing variable within a lambda, the normal approach is to declare a final copy of the
variable and use the copy. For example
int n = 0;
final int k = n; // With Java 8 there is no need to explicit final
Runnable r = () -> { // Using lambda
int i = k;
// do something
};
n++; // Now will not generate an error
r.run(); // Will run with i = 0 because k was 0 when the lambda was created
Naturally, the body of the lambda does not see the changes to the original variable.
Note that Java does not support true closures. A Java lambda cannot be created in a way that allows it to see
changes in the environment in which it was instantiated. If you want to implement a closure that observes or makes
changes to its environment, you should simulate it using a regular class. For example:
The above example will not compile for reasons discussed previously. We can work around the compilation error as
The problem is that this breaks the design contract for the IntUnaryOperator interface which states that instances
should be functional and stateless. If such a closure is passed to built-in functions that accept functional objects, it
is liable to cause crashes or erroneous behavior. Closures that encapsulate mutable state should be implemented
as regular classes. For example.
// Correct ...
public class Accumulator {
private int value = 0;
Although it might not be immediately obvious since the new keyword doesn't appear anywhere in the snippet, this
code is liable to create 1,000,000,000 separate objects to represent the instances of the () -> j lambda
expression. However, it should also be noted that future versions of Java1 may be able to optimize this so that at
runtime the lambda instances were reused, or were represented in some other way.
1 - For instance, Java 9 introduces an optional "link" phase to the Java build sequence which will provide the
opportunity for doing global optimizations like this.
For example, writing a Runnable in anonymous class and starting a Thread looks like:
Now, in line with above, lets say you have some custom interface:
interface TwoArgInterface {
int operate(int a, int b);
}
How do you use lambda to give implementation of this interface in your code? Same as Runnable example shown
above. See the driver program below:
}
}
interface MathOperation{
boolean unaryOperation(int num);
}
System.out.println(isEven.unaryOperation(25));
System.out.println(isEven.unaryOperation(20));
}
Lambda style
System.out.println(isEven.unaryOperation(25));
System.out.println(isEven.unaryOperation(20));
}
}
Section 72.10: `return` only returns from the lambda, not the
outer method
The return method only returns from the lambda, not the outer method.
void threeTimes(IntConsumer r) {
for (int i = 0; i < 3; i++) {
r.accept(i);
}
}
void demo() {
threeTimes(i -> {
System.out.println(i);
return; // Return from lambda to threeTimes only!
});
}
This can lead to unexpected behavior when attempting to write own language constructs, as in builtin constructs
such as for loops return behaves differently:
void demo2() {
In Scala and Kotlin, demo and demo2 would both only print 0. But this is not more consistent. The Java approach is
consistent with refactoring and the use of classes - the return in the code at the top, and the code below behaves
the same:
void demo3() {
threeTimes(new MyIntConsumer());
}
Therefore, the Java return is more consistent with class methods and refactoring, but less with the for and while
builtins, these remain special.
IntStream.range(1, 4)
.map(x -> x * x)
.forEach(System.out::println);
IntStream.range(1, 4)
.map(x -> { return x * x; })
.forEach(System.out::println);
void executeAround(Consumer<Resource> f) {
try (Resource r = new Resource()) {
System.out.print("before ");
f.accept(r);
System.out.print("after ");
}
}
void demo4() {
executeAround(r -> {
System.out.print("accept() ");
return; // Does not return from demo4, but frees the resource.
});
}
will print before accept() after close(). In the Scala and Kotlin semantics, the try-with-resources would not be
closed, but it would print before accept() only.
interface DataProcessor {
void process( Connection connection ) throws SQLException;;
}
This is not limited to I/O operations. It can apply to any scenario where similar setup/tear down tasks are applicable
with minor variations. The main benefit of this Pattern is code re-use and enforcing DRY (Don't Repeat Yourself).
Example: Use a lambda expressions & a predicate to get a certain value from a list. In this example every person
will be printed out with the fact if they are 18 and older or not.
Person Class:
The built-in interface Predicate from the java.util.function.Predicate packages is a functional interface with a
boolean test(T t) method.
Example Usage:
import java.util.ArrayList;
import java.util.List;
The print(personList, p -> p.getAge() >= 18); method takes a lambda expression (because the Predicate is
used a parameter) where you can define the expression that is needed. The checker's test method checks if this
expression is correct or not: checker.test(person).
You can easily change this to something else, for example to print(personList, p ->
p.getName().startsWith("J"));. This will check if the person's name starts with a "J".
case: This is the value that is evaluated for equivalence with the argument to the switch statement.
default: This is an optional, catch-all expression, should none of the case statements evaluate to true.
Abrupt completion of the case statement; usually break: This is required to prevent the undesired evaluation
of further case statements.
With the exception of continue, it is possible to use any statement which would cause the abrupt completion of a
statement. This includes:
break
return
throw
In the example below, a typical switch statement is written with four possible cases, including default.
By omitting break or any statement which would an abrupt completion, we can leverage what are known as "fall-
through" cases, which evaluate against several values. This can be used to create ranges for a value to be successful
against, but is still not as flexible as inequalities.
Version ≥ Java SE 5
enum Option {
BLUE_PILL,
RED_PILL
}
}
}
Version ≥ Java SE 7
int i = 0;
do {
i++;
System.out.println(i);
} while (i < 100); // Condition gets checked AFTER the content of the loop executes.
With the guarantee of at least one execution, it is possible to declare variables outside of the loop and initialize
them inside.
String theWord;
Scanner scan = new Scanner(System.in);
do {
theWord = scan.nextLine();
} while (!theWord.equals("Bird"));
System.out.println(theWord);
In this context, theWord is defined outside of the loop, but since it's guaranteed to have a value based on its natural
flow, theWord will be initialized.
With Java 5 and up, one can use for-each loops, also known as enhanced for-loops:
strings.add("This");
strings.add("is");
strings.add("a for-each loop");
For each loops can be used to iterate over Arrays and implementations of the Iterable interface, the later includes
Collections classes, such as List or Set.
The loop variable can be of any type that is assignable from the source type.
The loop variable for a enhanced for loop for Iterable<T> or T[] can be of type S, if
T extends S
both T and S are primitive types and assignable without a cast
S is a primitive type and T can be converted to a type assignable to S after unboxing conversion.
T is a primitive type and can be converted to S by autoboxing conversion.
Examples:
T elements = ...
for (S s : elements) {
}
T S
Compiles
int[] long yes
long[] int no
Iterable<Byte> long yes
Iterable<String> CharSequence yes
Iterable<CharSequence> String no
int[] Long no
int[] Integer yes
The continue statement can also make the control of the program shift to the step value (if any) of a named loop:
The else if condition is checked only if all the conditions before it (in previous else if constructs, and the parent
if constructs) have been tested to false. In this example, the else if condition will only be checked if i is greater
than or equal to 2.
If its result is true, its block is run, and any else if and else constructs after it will be skipped.
If none of the if and else if conditions have been tested to true, the else block at the end will be run.
The three components of the for loop (separated by ;) are variable declaration/initialization (here int i = 0), the
condition (here i < 100), and the increment statement (here i++). The variable declaration is done once as if placed
just inside the { on the first run. Then the condition is checked, if it is true the body of the loop will execute, if it is
false the loop will stop. Assuming the loop continues, the body will execute and finally when the } is reached the
increment statement will execute just before the condition is checked again.
The for loop components are optional. If your business logic contains one of these parts, you can omit the
corresponding component from your for loop.
Any looping statement having another loop statement inside called nested loop. The same way for looping having
more inner loop is called 'nested for loop'.
for(;;){
//Outer Loop Statements
for(;;){
//Inner Loop Statements
}
//Outer Loop Statements
}
For ex.
String name;
if (A > B) {
name = "Billy";
} else {
name = "Jimmy";
}
A finally clause can be added after the catch. The finally clause would always be executed, regardless of
whether an exception was thrown.
Loop:
while(true) {
The loop in the example would run forever. But when someCondition equals 5 at some point of execution, then the
loop ends.
If multiple loops are cascaded, only the most inner loop ends using break.
A while loop runs as long as the condition inside the parentheses is true. This is also called the "pre-test loop"
structure because the conditional statement must be met before the main loop body is performed every time.
The curly braces are optional if the loop contains just one statement, but some coding style conventions prefers
having the braces regardless.
An if statement executes code conditionally depending on the result of the condition in parentheses. When
condition in parentheses is true it will enter to the block of if statement which is defined by curly braces like { and }.
opening bracket till the closing bracket is the scope of the if statement.
The else block is optional and can be omitted. It runs if the if statement is false and does not run if the if
statement is true Because in that case if statement executes.
outerloop:
for(...) {
innerloop:
for(...) {
if(condition1)
break outerloop;
if(condition2)
continue innerloop; // equivalent to: continue;
}
Also note that write(String s) does not place newline character after string has been written. To put it use
newLine() method.
Version ≥ Java SE 7
Path p1 = Paths.get("/var/www");
Path p2 = Paths.get(URI.create("file:///home/testuser/File.txt"));
Path p3 = Paths.get("C:\\Users\\DentAr\\Documents\\HHGTDG.odt");
Path p4 = Paths.get("/home", "arthur", "files", "diary.tex");
Paths can be joined using the resolve() method. The path passed has to be a partial path, which is a path that
doesn't include the root element.
Path p5 = Paths.get("/home/");
Path p6 = Paths.get("arthur/files");
Path joined = p5.resolve(p6);
Path otherJoined = p5.resolve("ford/files");
joined.toString() == "/home/arthur/files"
otherJoined.toString() == "/home/ford/files"
Normalizing a path
Paths may contain the elements . (which points to the directory you're currently in) and ..(which points to the
parent directory).
When used in a path, . can be removed at any time without changing the path's destination, and .. can be
removed together with the preceding element.
With the Paths API, this is done using the .normalize() method:
Path p7 = Paths.get("/home/./arthur/../ford/files");
Path p8 = Paths.get("C:\\Users\\.\\..\\Program Files");
p7.normalize().toString() == "/home/ford/files"
p8.normalize().toString() == "C:\\Program Files"
getFileName() returns the file name (or, more specifically, the last element of the path
Checking existence
To check the existence of the file or directory a path points to, you use the following methods:
Files.exists(Path path)
and
Files.notExists(Path path)
!Files.exists(path) does not neccesarily have to be equal to Files.notExists(path), because there are three
possible scenarios:
A file's or directory's existence is verified (exists returns true and notExists returns false in this case)
A file's or directory's nonexistence is verfied (exists returns false and notExists returns true)
Neither the existence nor the nonexistence of a file or a directory can be verified (for example due to access
restrictions): Both exists and nonExists return false.
Path p1 = Paths.get("/var/www");
Path p2 = Paths.get("/home/testuser/File.txt");
Files.isDirectory(p1) == true
Files.isRegularFile(p1) == false
Files.isDirectory(p2) == false
Getting properties
Files.isReadable(Path path)
Files.isWritable(Path path)
Files.isExecutable(Path path)
Files.isHidden(Path path)
Files.isSymbolicLink(Path path)
This tries to get the MIME type of a file. It returns a MIME type String, like this:
Path p2 = Paths.get(URI.create("file:///home/testuser/File.txt"));
byte[] content = Files.readAllBytes(p2);
List<String> linesOfContent = Files.readAllLines(p2);
Path p2 = Paths.get("/home/testuser/File.txt");
List<String> lines = Arrays.asList(
new String[]{"First line", "Second line", "Third line"});
Files.write(p2, lines);
There is much more to Java 7's NIO such as memory-mapped files or opening a ZIP or JAR file using FileSystem.
These examples will only cover a limited number of basic use cases.
As a basic rule, if you are used to perform a file system read/write operation using a java.io.File instance
method, you will find it as a static method within java.nio.file.Files.
Point to a path
// -> IO
File file = new File("io.txt");
// -> NIO
Path path = Paths.get("nio.txt");
// -> NIO
Path directory = Paths.get("C:/");
Path pathInDirectory = directory.resolve("nio.txt");
// -> NIO to IO
File fileFromPath = Paths.get("nio.txt").toFile();
// -> NIO
Files.deleteIfExists(path);
There are several ways to write and read from a file using NIO for different performance and memory constraints,
readability and use cases, such as FileChannel, Files.write(Path path, byte\[\] bytes, OpenOption...
// -> IO
if (file.exists()) {
// Note: Not atomic
throw new IOException("File already exists");
}
try (FileOutputStream outputStream = new FileOutputStream(file)) {
for (String line : lines) {
outputStream.write((line + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
}
}
// -> NIO
try (OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE_NEW)) {
for (String line : lines) {
outputStream.write((line + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
}
}
// -> NIO
Files.walkFileTree(directory, EnumSet.noneOf(FileVisitOption.class), 1, new
SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path selectedPath, BasicFileAttributes attrs) throws
IOException {
System.out.println("d " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws
IOException {
System.out.println("f " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
});
// -> NIO
// Note: Symbolic links are NOT followed unless explicitly passed as an argument to
Files.walkFileTree
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws
IOException {
System.out.println("f " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
});
...
try {
Image img = ImageIO.read(new File("~/Desktop/cat.png"));
} catch (IOException e) {
e.printStackTrace();
}
Note, that since Java 1.7 the try-with-resources statement was introduced what made implementation of
reading\writing operation much simpler:
Version ≥ Java SE 7
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
try {
byte[] data = Files.readAllBytes(path);
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
Most java.io file APIs accept both Strings and Files as arguments, so you could as well use
// Read a chunk
byte[] data = new byte[1024];
int nBytesRead = inputStream.read(data);
if (nBytesRead >= 0) { // A negative value represents end of stream
// Write the chunk to another stream
outputStream.write(data, 0, nBytesRead);
}
There are some exceptions, probably most notably the PrintStream which adds the "ability to print representations
of various data values conveniently". This allows to use System.out both as a binary InputStream and as a textual
output using methods such as System.out.println().
Also, some stream implementations work as an interface to higher-level contents such as Java objects (see
Serialization) or native types, e.g. DataOutputStream / DataInputStream.
With the Writer and Reader classes, Java also provides an API for explicit character streams. Although most
applications will base these implementations on streams, the character stream API does not expose any methods
for binary content.
Whenever it is necessary to encode characters into binary data (e.g. when using the InputStreamWriter /
OutputStreamWriter classes), you should specify a charset if you do not want to depend on the platform's default
One of the most commonly used Readers is BufferedReader which provides a method to read whole lines of text
from another reader and is presumably the simplest way to read a character stream line by line:
word by word
and you can also change the delimeter by using scanner.useDelimeter() method
If you are using Java 7 or later, there is a simpler way using the nio API:
Version ≥ Java SE 7
Path path = Paths.get("path_to_the_file");
byte [] data = Files.readAllBytes(path);
To read data from a file using Channel we need to have the following steps-
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
if (!inputFile.exists()) {
System.out.println("The input file doesn't exit.");
return;
}
try {
FileInputStream fis = new FileInputStream(inputFile);
FileChannel fileChannel = fis.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// assume that neither "A New Folder" or "A New Folder 2" exist
If the above solutions are not feasible, then you should consider redirecting the streams.
On a UNIX, Linux or MacOSX system can be done from the shell using > redirection. For example:
The first one redirects standard output and standard error to "/dev/null", which throws away anything written to
those streams. The second of redirects standard output to "out.log" and standard error to "error.log".
(For more information on redirection, refer to the documentation of the command shell you are using. Similar
advice applies to Windows.)
Alternatively, you could implement the redirection in a wrapper script or batch file that launches the Java
application.
It is also possible to redired the streams within a Java application using System.setOut() and System.setErr(). For
example, the following snippet redirects standard output and standard error to 2 log files:
If you want to throw away the output entirely, you can create an output stream that "writes" to an invalid file
descriptor. This is functionally equivalent to writing to "/dev/null" on UNIX.
\Z is the EOF (End of File) Symbol. When set as delimiter the Scanner will read the fill until the EOF Flag is reached.
/*
* try to lock the file. true means whether the lock is shared or not i.e. multiple processes can
acquire a
* shared lock (for reading only) Using false with readable channel only will generate an
exception. You should
* use a writable channel (taken from FileOutputStream) when using false. tryLock will always
return immediately
*/
FileLock lock = channel.tryLock(0, Long.MAX_VALUE, true);
if (lock == null) {
System.out.println("Unable to acquire lock");
} else {
System.out.println("Lock acquired successfully");
}
// you can also use blocking call which will block until a lock is acquired.
channel.lock();
// Once you have completed desired operations of file. release the lock
if (lock != null) {
lock.release();
}
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
}
}
import java.io.*;
import java.nio.*;
public class FileChannelWrite {
try {
FileOutputStream fos = new FileOutputStream(outputFile);
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.time.LocalDate;
ps.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
The FileSystem is a resource that should be properly closed after use, therefore the try-with-resources block should
be used.
package com.stackoverflow.scanner;
import javax.annotation.Nonnull;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.regex.Pattern;
static
{
final SortedSet<String> ecmds = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
ecmds.addAll(Arrays.asList("exit", "done", "quit", "end", "fino"));
EXIT_COMMANDS = Collections.unmodifiableSortedSet(ecmds);
final SortedSet<String> hcmds = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
hcmds.addAll(Arrays.asList("help", "helpi", "?"));
HELP_COMMANDS = Collections.unmodifiableSet(hcmds);
DATE_PATTERN = Pattern.compile("\\d{4}([-\\/])\\d{2}\\1\\d{2}"); //
http://regex101.com/r/xB8dR3/1
HELP_MESSAGE = format("Please enter some data or enter one of the following commands to
exit %s", EXIT_COMMANDS);
}
/**
* Using exceptions to control execution flow is always bad.
* That is why this is encapsulated in a method, this is done this
* way specifically so as not to introduce any external libraries
* so that this is a completely self contained example.
* @param s possible url
* @return true if s represents a valid url, false otherwise
*/
private static boolean isValidURL(@Nonnull final String s)
{
try { new URL(s); return true; }
catch (final MalformedURLException e) { return false; }
}
private static void output(@Nonnull final String format, @Nonnull final Object... args)
This will allow you to read every element in the input individually. Note that you should not use this to parse CSV
data, instead, use a proper CSV parser library, see CSV parser for Java for other possibilities.
The scanner object is initialized to read input from keyboard. So for the below input from keyboar, it'll produce the
output as Reading from keyboard
Reading
from
keyboard
//space
Here a Scanner object is created by passing a File object containing the name of a text file as input. This text file
will be opened by the File object and read in by the scanner object in the following lines. scanner.hasNext() will
check to see if there is a next line of data in the text file. Combining that with a while loop will allow you to iterate
through every line of data in the Names.txt file. To retrieve the data itself, we can use methods such as
nextLine(),nextInt(),nextBoolean(), etc. In the example above, scanner.nextLine()is used. nextLine() refers
to the following line in a text file, and combining it with a scanner object allows you to print the contents of the line.
To close a scanner object, you would use .close().
Using try with resources (from Java 7 onwards), the above mentioned code can be written elegantly as below.
Remember that you'll have to close the Scanner, as well as catch the IoException this may throw, as described in
the example Reading file input using Scanner.
example:
If you want to read an int from the command line, just use this snippet. First of all, you have to create a Scanner
object, that listens to System.in, which is by default the Command Line, when you start the program from the
command line. After that, with the help of the Scanner object, you read the first int that the user passes into the
command line and store it in the variable number. Now you can do whatever you want with that stored int.
@Override
public void eat(Food food) {
System.out.println("meows appreciatively");
}
}
Notice how the Cat class must implement the inherited abstract methods in both the interfaces. Furthermore,
notice how a class can practically implement as many interfaces as needed (there is a limit of 65,535 due to JVM
Limitation).
Note:
Override Annotation
@Override
public String getSound() {
// Code goes here...
}
This forces the compiler to check that we are overriding and prevents the program from defining a new method or
messing up the method signature.
@Override
public String getSound() {
return "meow";
}
}
@Override
public String getSound() {
return "woof";
}
}
In the example, classes Cat and Dog must define the getSound() method as methods of an interface are inherently
abstract (with the exception of default methods).
Now a class implementing ExtendedResourceService will need to implement both getResource() and
updateResource().
Unlike classes, the extends keyword can be used to extend multiple interfaces (Separated by commas) allowing for
combinations of interfaces into a new interface
One way to do this would be to use interfaces. This would allow for the same method to be called on all of the
classes
Any class that implements Animal also must have a getSound() method in them, yet they can all have different
implementations
We now have three different classes, each of which has a getSound() method. Because all of these classes
implement the Animal interface, which declares the getSound() method, any instance of an Animal can have
getSound() called on it
dog.getSound(); // "Woof"
cat.getSound(); // "Meow"
bird.getSound(); // "Chirp"
Because each of these is an Animal, we could even put the animals in a list, loop through them, and print out their
sounds
Because the order of the array is Dog, Cat, and then Bird, "Woof Meow Chirp" will be printed to the console.
Interfaces can also be used as the return value for functions. For example, returning a Dog if the input is "dog", Cat if
the input is "cat", and Bird if it is "bird", and then printing the sound of that animal could be done using
Interfaces are also useful for extensibility, because if you want to add a new type of Animal, you wouldn't need to
change anything with the operations you perform on them.
For example, it's possible to implement the Observer-Listener pattern directly into the interface, providing more
flexibility to the implementing classes.
interface Observer {
void onAction(String a);
}
interface Observable{
public abstract List<Observer> getObservers();
Now, any class can be made "Observable" just by implementing the Observable interface, while being free to be
part of a different class hierarchy.
@Override
public List<Observer> getObservers() {
return myObservers;
}
@Override
public void work(){
notify("Started work");
notify("Completed work");
}
w.addListener(new Observer() {
@Override
w.work();
}
}
Diamond problem
The compiler in Java 8 is aware of the diamond problem which is caused when a class is implementing interfaces
containing a method with the same signature.
In order to solve it, an implementing class must override the shared method and provide its own implementation.
interface InterfaceA {
public default String getName(){
return "a";
}
}
interface InterfaceB {
public default String getName(){
return "b";
}
}
@Override
public String getName() {
//Must provide its own implementation
return InterfaceA.super.getName() + InterfaceB.super.getName();
}
There's still the issue of having methods with the same name and parameters with different return types, which will
not compile.
The default method implementations come in very handy if a method is added to an interface in an existing system
where the interfaces is used by several classes.
To avoid breaking up the entire system, you can provide a default method implementation when you add a method
to an interface. This way, the system will still compile and the actual implementations can be done step by step.
(See Modifiers in Oracle Official Code Standard for the context and a link to the actual Oracle document.)
This style guidance applies particularly to interfaces. Let's consider the following code snippet:
interface I {
public static final int VARIABLE = 0;
Variables
All interface variables are implicitly constants with implicit public (accessible for all), static (are accessible by
interface name) and final (must be initialized during declaration) modifiers:
Methods
1. All methods which don't provide implementation are implicitly public and abstract.
2. All methods with static or default modifier must provide implementation and are implicitly public.
After all of the above changes have been applied, we will get the following:
interface I {
int VARIABLE = 0;
void method();
Let's define a basic IO interface that can be re-used across multiple implementations:
Now I can instantiate that interface, but since we don't have default implementations for those methods, it'll need
an implementation when we instantiate it:
@Override
public void publish(String data) {
System.out.println("Publishing " + data + " to " + channel);
}
@Override
public String consume() {
System.out.println("Consuming from " + channel);
return "some useful data";
}
@Override
public String RPCSubmit(String data) {
return "received " + data + " just now ";
}
};
We can also do something more useful with that interface, let's say we want to use it to wrap some basic RabbitMQ
functions:
@Override
public void publish(String data) {
rabbit.basicPublish(exchange, queue, data.getBytes());
}
@Override
public String consume() {
return rabbit.basicConsume(exchange, queue);
}
@Override
public String RPCSubmit(String data) {
Let's say I want to use this IO interface now as a way to count visits to my website since my last system restart and
then be able to display the total number of visits - you can do something like this:
import java.util.concurrent.atomic.AtomicLong;
@Override
public void publish(Integer count) {
websiteCounter.addAndGet(count);
}
@Override
public Long consume() {
return websiteCounter.get();
}
@Override
public Long RPCSubmit(Integer count) {
return websiteCounter.addAndGet(count);
}
// show data for stats counter page, but include that as a page view
System.out.println(counter.RPCSubmit(1)); // prints 6
When implementing multiple interfaces, you can't implement the same interface twice. That also applies to generic
interfaces. Thus, the following code is invalid, and will result in a compile error:
interface Printer<T> {
void print(T value);
}
// Invalid!
class SystemPrinter implements Printer<Double>, Printer<Integer> {
@Override public void print(Double d){ System.out.println("Decimal: " + d); }
@Override public void print(Integer i){ System.out.println("Discrete: " + i); }
}
class SomeClass {
An interface type can be bound to a type that already had a binding. This is achieved using the & symbol:
interface SomeInterface {
This strengthens the bind, potentially requiring type arguments to derive from multiple types.
But should be used with caution. Multiple interface bindings is usually a sign of a code smell, suggesting that a new
type should be created which acts as an adapter for the other types:
@Override
public void eat() {
System.out.println("Dog eats some kibble.");
}
}
From Java 8 onward it is possible for an interface to declare default implementations of methods which means
the method won't be abstract, therefore any concrete sub-classes will not be forced to implement the method but
will inherit the default implementation unless overridden.
For this example, we'll start with a simple phone number regex:
\d{3}-\d{3}-\d{4}
If parentheses are added to the regex, each set of parentheses is considered a capturing group. In this case, we are
using what are called numbered capture groups:
(\d{3})-(\d{3})-(\d{4})
^-----^ ^-----^ ^-----^
Group 1 Group 2 Group 3
Before we can use it in Java, we must not forget to follow the rules of Strings, escaping the backslashes, resulting in
the following pattern:
"(\\d{3})-(\\d{3})-(\\d{4})"
We first need to compile the regex pattern to make a Pattern and then we need a Matcher to match our input
string with the pattern:
Next, the Matcher needs to find the first subsequence that matches the regex:
phoneMatcher.find();
Now, using the group method, we can extract the data from the string:
Version ≥ Java SE 7
Java 7 introduced named capture groups. Named capture groups function the same as numbered capture groups
(but with a name instead of a number), although there are slight syntax changes. Using named capture groups
improves readability.
/* Had the regex not been compiled case insensitively and singlelined,
* it would fail because FOO does not match /foo/ and \n (newline)
* does not match /./.
*/
To use regular expression specific characters (?+| etc.) in their literal meaning they need to be escaped. In common
regular expression this is done by a backslash \. However, as it has a special meaning in Java Strings, you have to
use a double backslash \\.
Escaping backslash \
"\\".matches("\\"); // PatternSyntaxException
"\\".matches("\\\"); // Syntax Error
This works:
"\\".matches("\\\\"); // true
Example:
Output:
[popcorn] nope!
[unicorn] matched!
\Q marks the beginning of the regex literal. \E marks the end of the regex literal.
// wrapping the bracket in \Q and \E allows the pattern to match as you would expect.
"[123".matches("\\Q[\\E123"); // returns true
An easier way of doing it without having to remember the \Q and \E escape sequences is to use Pattern.quote()
Backslash is an escape character in regular expressions. You can use '\\' to refer to a single backslash in a regular
expression.
However, backslash is also an escape character in Java literal strings. To make a regular expression from a string
literal, you have to escape each of its backslashes. In a string literal '\\\\' can be used to create a regular expression
For example, consider matching strings like "C:\dir\myfile.txt". A regular expression ([A-Za-z]):\\(.*) will match,
and provide the drive letter as a capturing group. Note the doubled backslash.
To express that pattern in a Java string literal, each of the backslashes in the regular expression needs to be
escaped.
If you want to match two backslashes, you'll find yourself using eight in a literal string, to represent four in the
regular expression, to match two.
if ( matcher.matches()) {
System.out.println( "This path is on host '" + matcher.group( 1 ) + "'.");
// This path is on host 'myhost'.
}
@Override
public boolean equals(Object o) {
if (! (o instanceof Person)) return false;
Person p = (Person)o;
return firstName.equals(p.firstName) && lastName.equals(p.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
}
Now we would like to sort a list of Person objects by their name, such as in the following scenario:
Unfortunately, as marked, the above currently won't compile. Collections.sort(..) only knows how to sort a list
if the elements in that list are comparable, or a custom method of comparison is given.
If you were asked to sort the following list : 1,3,5,4,2, you'd have no problem saying the answer is 1,2,3,4,5. This
@Override
public boolean equals(Object o) {
if (! (o instanceof Person)) return false;
Person p = (Person)o;
return firstName.equals(p.firstName) && lastName.equals(p.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
@Override
public int compareTo(Person other) {
// If this' lastName and other's lastName are not comparably equivalent,
// Compare this to other by comparing their last names.
// Otherwise, compare this to other by comparing their first names
int lastNameCompare = lastName.compareTo(other.lastName);
if (lastNameCompare != 0) {
return lastNameCompare;
} else {
return firstName.compareTo(other.firstName);
}
}
}
If, however, you either do not want or are unable to modify class Person, you can provide a custom Comparator<T>
that handles the comparison of any two Person objects. If you were asked to sort the following list: circle,
square, rectangle, triangle, hexagon you could not, but if you were asked to sort that list based on the number
of corners, you could. Just so, providing a comparator instructs Java how to compare two normally not comparable
objects.
//Assume the first version of Person (that does not implement Comparable) is used here
public static void main(String[] args) {
List<Person> people = Arrays.asList(new Person("John", "Doe"),
new Person("Bob", "Dole"),
new Person("Ronald", "McDonald"),
new Person("Alice", "McDonald"),
new Person("Jill", "Doe"));
Collections.sort(people); //Illegal, Person doesn't implement Comparable.
Collections.sort(people, new PersonComparator()); //Legal
//Assume the first version of Person (that does not implement Comparable) is used here
public static void main(String[] args) {
List<Person> people = Arrays.asList(new Person("John", "Doe"),
new Person("Bob", "Dole"),
new Person("Ronald", "McDonald"),
new Person("Alice", "McDonald"),
new Person("Jill", "Doe"));
Collections.sort(people); //Illegal, Person doesn't implement Comparable.
//Anonymous Class
Collections.sort(people, new Comparator<Person>() { //Legal
public int compare(Person p1, Person p2) {
//Method code...
}
});
//Lambda
Collections.sort(people, (p1, p2) -> { //Legal
//Method code....
});
Furthermore, there are interesting default methods on the Comparator interface for building comparators : the
following builds a comparator comparing by lastName and then firstName.
Collections.sort(people, Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName));
Any comparator can also easily be reversed using the reversedMethod which will change ascending order to
descending.
These two methods do essentially the same thing, with one minor difference: compareTo compares this to other,
whereas compare compares t1 to t2, not caring at all about this.
Aside from that difference, the two methods have similar requirements. Specifically (for compareTo), Compares this
object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object. Thus, for the comparison of a and b:
If a < b, a.compareTo(b) and compare(a,b) should return a negative integer, and b.compareTo(a) and
compare(b,a) should return a positive integer
If a > b, a.compareTo(b) and compare(a,b) should return a positive integer, and b.compareTo(a) and
compare(b,a) should return a negative integer
If a equals b for comparison, all comparisons should return 0.
One that takes a List<T> as a parameter where T must implement Comparable and override the
compareTo() method that determines sort order.
One that takes a List and a Comparator as the arguments, where the Comparator determines the sort order.
@Override
public int compareTo(Person o) {
return this.getAge() - o.getAge();
}
@Override
public String toString() {
return this.getAge()+"-"+this.getName();
}
Here is how you would use the above class to sort a List in the natural ordering of its elements, defined by the
compareTo() method override:
//-- usage
List<Person> pList = new ArrayList<Person>();
Person p = new Person();
p.setName("A");
p.setAge(10);
pList.add(p);
p = new Person();
p.setName("Z");
p.setAge(20);
pList.add(p);
p = new Person();
p.setName("D");
p.setAge(30);
pList.add(p);
Here is how you would use an anonymous inline Comparator to sort a List that does not implement Comparable, or
in this case, to sort a List in an order other than the natural ordering:
//-- explicit sorting, define sort on another property here goes with name
Collections.sort(pList, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getName().compareTo(o2.getName());
}
});
System.out.println(pList);
This creates a comparator for the class Person that uses this person name as the comparison source. Also it is
possible to use method version to compare long, int and double. For example:
Comparator.comparingInt(Person::getAge)
Reversed order
To create a comparator that imposes the reverse ordering use reversed() method:
Comparator.comparing(Person::getName).reversed()
Chain of comparators
Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName)
This will create a comparator that firs compares with last name then compares with first name. You can chain as
many comparators as you want.
Version ≥ Java SE 8
Map<String, Integer> numberOfEmployees = new HashMap<>();
numberOfEmployees.put("executives", 10);
numberOfEmployees.put("human ressources", 32);
numberOfEmployees.put("accounting", 12);
numberOfEmployees.put("IT", 100);
==
, !=, < and so on. These operators give results according to the binary representations of the floating point values.
For example:
public class CompareTest {
public static void main(String[] args) {
double oneThird = 1.0 / 3.0;
double one = oneThird * 3;
System.out.println(one == 1.0); // prints "false"
}
}
The calculation oneThird has introduced a tiny rounding error, and when we multiply oneThird by 3 we get a result
that is slightly different to 1.0.
This problem of inexact representations is more stark when we attempt to mix double and float in calculations.
For example:
System.out.println(floatVal); // 0.1
System.out.println(doubleVal); // 0.1
System.out.println(doubleValCopy); // 0.10000000149011612
The floating point representations used in Java for the float and double types have limited number of digits of
precision. For the float type, the precision is 23 binary digits or about 8 decimal digits. For the double type, it is 52
bits or about 15 decimal digits. On top of that, some arithmetical operations will introduce rounding errors.
Therefore, when a program compares floating point values, it standard practice to define an acceptable delta for
the comparison. If the difference between the two numbers is less than the delta, they are deemed to be equal. For
example
System.out.println();
}
}
}
Result:
delta: 0.01
1.0 == 1.0001 ? true
1.0001 == 1.0000001 ? true
1.0000001 == 1.000000001 ? true
1.000000001 == 1.0000000000001 ? true
delta: 1.0E-5
1.0 == 1.0001 ? false
1.0001 == 1.0000001 ? false
1.0000001 == 1.000000001 ? true
1.000000001 == 1.0000000000001 ? true
delta: 1.0E-7
1.0 == 1.0001 ? false
1.0001 == 1.0000001 ? false
1.0000001 == 1.000000001 ? true
1.000000001 == 1.0000000000001 ? true
delta: 1.0E-10
1.0 == 1.0001 ? false
1.0001 == 1.0000001 ? false
1.0000001 == 1.000000001 ? false
1.000000001 == 1.0000000000001 ? false
delta: 0.0
1.0 == 1.0001 ? false
1.0001 == 1.0000001 ? false
1.0000001 == 1.000000001 ? false
1.000000001 == 1.0000000000001 ? false
double a = 1.0;
double b = 1.0001;
System.out.println(Double.compare(a, b));//-1
System.out.println(Double.compare(b, a));//1
Finally, determining what deltas are most appropriate for a comparison can be tricky. A commonly used approach
is to pick delta values that are our intuition says are about right. However, if you know scale and (true) accuracy of
the input values, and the calculations performed, it may be possible to come up with mathematically sound bounds
on the accuracy of the results, and hence for the deltas. (There is a formal branch of Mathematics known as
Numerical Analysis that used to be taught to computational scientists that covered this kind of analysis.)
The float data type is a single-precision 32-bit IEEE 754 floating point.
Float overflow
Maximum possible value is 3.4028235e+38 , When it exceeds this value it produces Infinity
float f = 3.4e38f;
float result = f*2;
System.out.println(result); //Infinity
Float UnderFlow
Minimum value is 1.4e-45f, when is goes below this value it produces 0.0
float f = 1e-45f;
float result = f/1000;
System.out.println(result);
The double data type is a double-precision 64-bit IEEE 754 floating point.
Double OverFlow
Maximum possible value is 1.7976931348623157e+308 , When it exceeds this value it produces Infinity
double d = 1e308;
double result=d*2;
System.out.println(result); //Infinity
Double UnderFlow
Minimum value is 4.9e-324, when is goes below this value it produces 0.0
double d = 4.8e-323;
double result = d/1000;
strictfp disables this behavior. It is applied to a class, interface, or method, and applies to everything contained in
it, such as classes, interfaces, methods, constructors, variable initializers, etc. With strictfp, the intermediate
values of a floating-point expression must be within the float value set or the double value set. This causes the
results of such expressions to be exactly those that the IEEE 754 specification predicts.
All constant expressions are implicitly strict, even if they aren't inside a strictfp scope.
Therefore, strictfp has the net effect of sometimes making certain corner case computations less accurate, and
can also make floating point operations slower (as the CPU is now doing more work to ensure any native extra
precision does not affect the result). However, it also causes the results to be exactly the same on all platforms. It is
therefore useful in things like scientific programs, where reproducibility is more important than speed.
public static final strictfp class Ops { // strictfp affects all enclosed entities
private StrictOps() {}
import java.util.ArrayList;
import java.util.List;
@Override
public Object clone() throws CloneNotSupportedException {
Sheep clone = (Sheep) super.clone();
if (children != null) {
// make a deep copy of the children
List<Sheep> cloneChildren = new ArrayList<>(children.size());
for (Sheep child : children) {
cloneChildren.add((Sheep) child.clone());
}
clone.setChildren(cloneChildren);
}
return clone;
}
import java.util.Arrays;
import java.util.List;
// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);
sheep.setChildren(Arrays.asList(child1, child2));
// copy constructor
// copies the fields of other into the new object
public Sheep(Sheep other) {
this.name = other.name;
this.weight = other.weight;
}
// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly = new Sheep(sheep); // dolly.name is "Dolly" and dolly.weight is 20
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly = (Sheep) sheep.clone(); // dolly.name is "Dolly" and dolly.weight is 20
import java.util.List;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);
sheep.setChildren(Arrays.asList(child1, child2));
In general, recursion is when a function invokes itself, either directly or indirectly. For example:
There are two preconditions for using recursive functions to solving a specific problem:
1. There must be a base condition for the problem, which will be the endpoint for the recursion. When a
recursive function reaches the base condition, it makes no further (deeper) recursive calls.
2. Each level of recursion should be attempting a smaller problem. The recursive function thus divides the
problem into smaller and smaller parts. Assuming that the problem is finite, this will ensure that the
recursion terminates.
In Java there is a third precondition: it should not be necessary to recurse too deeply to solve the problem; see
Deep recursion is problematic in Java
Example
The following function calculates factorials using recursion. Notice how the method factorial calls itself within the
function. Each time it calls itself, it reduces the parameter n by 1. When n reaches 1 (the base condition) the
function will recurse no deeper.
This is not a practical way of computing factorials in Java, since it does not take account of integer overflow, or call
stack overflow (i.e. StackOverflowError exceptions) for large values of n.
This is algorithmically correct, but it has a major problem. If you call add with a large a, it will crash with a
StackOverflowError, on any version of Java up to (at least) Java 9.
In a typical functional programming language (and many other languages) the compiler optimizes tail recursion.
The compiler would notice that the call to add (at the tagged line) is a tail call, and would effectively rewrite the
recursion as a loop. This transformation is called tail-call elimination.
However, current generation Java compilers do not perform tail call elimination. (This is not a simple oversight.
There are substantial technical reasons for this; see below.) Instead, each recursive call of add causes a new frame
to be allocated on the thread's stack. For example, if you call add(1000, 1), it will take 1000 recursive calls to arrive
at the answer 1001.
The problem is that the size of Java thread stack is fixed when the thread is created. (This includes the "main"
thread in a single-threaded program.) If too many stack frames are allocated the stack will overflow. The JVM will
detect this and throw a StackOverflowError.
One approach to dealing with this is to simply use a bigger stack. There are JVM options that control the default size
of a stack, and you can also specify the stack size as a Thread constructor parameter. Unfortunately, this only "puts
off" the stack overflow. If you need to do a computation that requires an even larger stack, then the
StackOverflowError comes back.
The real solution is to identify recursive algorithms where deep recursion is likely, and manually perform the tail-call
optimization at the source code level. For example, our add method can be rewritten as follows:
(Obviously, there are better ways to add two integers. The above is simply to illustrate the effect of manual tail-call
elimination.)
There are a number of reasons why adding tail call elimination to Java is not easy. For example:
Some code could rely on StackOverflowError to (for example) place a bound on the size of a computational
problem.
Sandbox security managers often rely on analyzing the call stack when deciding whether to allow non-
privileged code to perform a privileged action.
"The effects of removing the caller’s stack frame are visible to some APIs, notably access control checks and
In other words, tail-call elimination could cause an access control method to mistakenly think that a security
sensitive API was was being called by trusted code.
In head recursion, the recursive call, when it happens, comes before other processing in the function (think of it
happening at the top, or head, of the function).
In tail recursion, it’s the opposite—the processing occurs before the recursive call. Choosing between the two
recursive styles may seem arbitrary, but the choice can make all the difference.
A function with a path with a single recursive call at the beginning of the path uses what is called head recursion.
The factorial function of a previous exhibit uses head recursion. The first thing it does once it determines that
recursion is needed is to call itself with the decremented parameter. A function with a single recursive call at the
end of a path is using tail recursion.
tail(n-1); System.out.println(n);
} }
If the recursive call occurs at the end of a method, it is called a tail recursion. The tail recursion is similar to a
loop. The method executes all the statements before jumping into the next recursive call.
If the recursive call occurs at the beginning of a method, it is called a head recursion. The method saves
the state before jumping into the next recursive call.
The method implements a base case (n <= 2) and a recursive case (n>2). This illustrates the use of recursion to
compute a recursive relation.
Example
public static void recursion(int depth) {
if (depth > 0) {
recursion(depth-1);
}
}
Calling this method with large parameters (e.g. recursion(50000) probably will result in a stack overflow. The exact
value depends on the thread stack size, which in turn depends on the thread construction, command-line
parameters such as -Xss, or the default size for the JVM.
Workaround
A recursion can be converted to a loop by storing the data for each recursive call in a data structure. This data
structure can be stored on the heap rather than on the thread stack.
In general the data required to restore the state of a method invocation can be stored in a stack and a while loop
can be used to "simulate" the recursive calls. Data that may be required include:
the object the method was called for (instance methods only)
the method parameters
local variables
the current position in the execution or the method
Example
The following class allows recursive of a tree structure printing up to a specified depth.
e.g.
Node n = new Node(10, new Node(20, new Node(50), new Node(1)), new Node(30, new Node(42), null));
n.print(2);
System.out.println();
Prints
(((...)20(...))10((...)30))
while (!stack.isEmpty()) {
// get topmost stack element
int index = stack.size() - 1;
Frame frame = stack.get(index); // get topmost frame
if (frame.maxDepth <= 0) {
// termial case (too deep)
System.out.print("(...)");
stack.remove(index); // drop frame
} else {
switch (frame.state) {
case 0:
frame.state++;
Note: This is just an example of the general approach. Often you can come up with a much better way to represent
a frame and/or store the frame data.
This illustrates the principles mentioned above: the recursive method implements a base case (two cases, n = 0 and
n = 1) that terminates the recursion, and a recursive case that calls the method again. This method is O(N) and can
be reduced to a simple loop using tail-call optimization.
We can traverse the tree constructed by connecting multiple Node class's object like below, the traversal is called
in-order traversal of tree.
As demonstrated above, using recursion we can traverse the tree data structure without using any other data
structure which is not possible with the iterative approach.
/**
* Just a snippet to explain the idea of recursion
*
**/
This method is O(N) and can be reduced to a simple loop using tail-call optimization. In fact there is a closed form
expression that computes the sum in O(1) operations.
String to int:
String to float:
String to double:
String to boolean:
String to long:
String to BigInteger:
String to BigDecimal:
Conversion Exceptions:
The numeric conversions above will all throw an (unchecked) NumberFormatException if you attempt to parse a
string that is not a suitably formatted number, or is out of range for the target type. The Exceptions topic discusses
how to deal with such exceptions.
If you wanted to test that you can parse a string, you could implement a tryParse... method like this:
However, calling this tryParse... method immediately before parsing is (arguably) poor practice. It would be
better to just call the parse... method and deal with the exception.
and to decode:
For less common character sets you can indicate the character set with a string:
this does however mean that you have to handle the checked UnsupportedCharsetException.
The following call will use the default character set. The default character set is platform specific and generally
differs between Windows, Mac and Linux platforms.
Note that invalid characters and bytes may be replaced or skipped by these methods. For more control - for
instance for validating input - you're encouraged to use the CharsetEncoder and CharsetDecoder classes.
import javax.xml.bind.DatatypeConverter;
import java.util.Arrays;
// assert that the original data and the decoded data are equal
assert Arrays.equals(binaryData, decodedData);
Apache commons-codec
import org.apache.commons.codec.binary.Base64;
If you inspect this program wile running, you will see that someBinaryData encodes to c29tZUJpbmFyeURhdGE=, a
very managable UTF-8 String object.
Version ≥ Java SE 8
// decode a String
byte [] barr = Base64.getDecoder().decode(encoded);
Reference
int i = 42;
String string = String.valueOf(i);
//string now equals "42”.
This method is also overloaded for other datatypes, such as float, double, boolean, and even Object.
You can also get any other Object (any instance of any class) as a String by calling .toString on it. For this to
give useful output, the class must override toString(). Most of the standard Java library classes do, such as
Date and others.
For example:
You can also convert any number type to String with short notation like below.
int i = 10;
String str = i + "";
import java.io.*;
This uses the system default charset, although an alternate charset may be specified:
import java.util.Random;
...
double randDouble = random.nextDouble(); //This returns a value between 0.0 and 1.0
float randFloat = random.nextFloat(); //Same as nextDouble
NOTE: This class only produces fairly low-quality pseudo-random numbers, and should never be used to generate
random numbers for cryptographic operations or other situations where higher-quality randomness is critical (For
that, you would want to use the SecureRandom class, as noted below). An explanation for the distinction between
"secure" and "insecure" randomness is beyond the scope of this example.
Starting in Java 1.7, you may also use ThreadLocalRandom (source). This class provides a thread-safe PRNG (pseudo-
random number generator). Note that the nextInt method of this class accepts both an upper and lower bound.
import java.util.concurrent.ThreadLocalRandom;
Note that the official documentation states that nextInt(int bound) can do weird things when bound is near 230+1
(emphasis added):
The algorithm is slightly tricky. It rejects values that would result in an uneven distribution (due to
the fact that 2^31 is not divisible by n). The probability of a value being rejected depends on n. The worst
In other words, specifying a bound will (slightly) decrease the performance of the nextInt method, and this
performance decrease will become more pronounced as the bound approaches half the max int value.
One can use java.security.SecureRandom in situations where a PRNG with an output that is very hard to predict is
required. Predicting the random numbers created by instances of this class is hard enough to label the class as
cryptographically secure.
import java.security.SecureRandom;
import java.util.Arrays;
Besides being cryptographically secure, SecureRandom has a gigantic period of 2160, compared to Randoms period of
248. It has one drawback of being considerably slower than Random and other linear PRNGs such as Mersenne
Twister and Xorshift, however.
Note that SecureRandom implementation is both platform and provider dependent. The default SecureRandom
(given by SUN provider in sun.security.provider.SecureRandom):
Using the same seed to generate random numbers will return the same numbers every time, so setting a different
seed for every Random instance is a good idea if you don't want to end up with duplicate numbers.
newRandSpot++;
// if we have gone though all the spots then set the value
if (newRandSpot==0){
randomNumbers[q] = t;
}
}
}
}
return randomNumbers;
} else {
// invalid can't have a length larger then the range of possible numbers
}
return null;
}
The method works by looping though an array that has the size of the requested length and finds the remaining
For example if the range is 5 and the length is 3 and we have already chosen the number 2. Then we have 4
remaining numbers so we get a random number between 1 and 4 and we loop through the range(5) skipping over
any numbers that we have already used(2).
Now let's say the next number chosen between 1 & 4 is 3. On the first loop we get 1 which has not yet been taken
so we can remove 1 from 3 making it 2. Now on the second loop we get 2 which has been taken so we do nothing.
We follow this pattern until we get to 4 where once we remove 1 it becomes 0 so we set the new randomNumber to
4.
Apart from int, we can generate random long, double, float and bytes using this class.
Enums have private constructors, are final and provide proper serialization machinery. They are also very concise
and lazily initialized in a thread safe manner.
The JVM provides a guarantee that enum values will not be instantiated more than once each, which gives the enum
singleton pattern a very strong defense against reflection attacks.
What the enum pattern doesn't protect against is other developers physically adding more elements to the source
code. Consequently, if you choose this implementation style for your singletons it is imperative that you very clearly
document that no new values should be added to those enums.
This is the recommended way of implementing the singleton pattern, as explained by Joshua Bloch in Effective Java.
private Singleton() {}
It can be argued that this example is effectively lazy initialization. Section 12.4.1 of the Java Language Specification
states:
A class or interface type T will be initialized immediately before the first occurrence of any one of the
following:
private Singleton() {}
}
This initializes the INSTANCE variable on the first call to Singleton.getInstance(), taking advantage of the
language's thread safety guarantees for static initialization without requiring additional synchronization.
Version ≥ Java SE 5
public class MySingleton {
// instance of class
private static volatile MySingleton instance = null;
// Private constructor
private MySingleton() {
// Some code for constructing object
}
It must be emphasized -- in versions prior to Java SE 5, the implementation above is incorrect and should be
/*
Enumeration that represents possible classes of singleton instance.
If unknown, we'll go with base class - Singleton.
*/
enum SingletonKind {
UNKNOWN,
LOWERCASE,
UPPERCASE
}
//Base class
class Singleton{
/*
Extended classes has to be private inner classes, to prevent extending them in
uncontrolled manner.
*/
private class UppercaseSingleton extends Singleton {
private UppercaseSingleton(){
super();
}
@Override
public String getMessage() {
return super.getMessage().toUpperCase();
}
}
@Override
public String getMessage() {
return super.getMessage().toLowerCase();
}
}
/*
By using this method prior to getInstance() method, you effectively change the
/*
If needed, getInstance() creates instance appropriate class, based on value of
singletonKind field.
*/
public static Singleton getInstance()
throws NoSuchMethodException,
IllegalAccessException,
InvocationTargetException,
InstantiationException {
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
Singleton singleton = new Singleton();
switch (kind){
case UNKNOWN:
instance = singleton;
break;
case LOWERCASE:
/*
I can't use simple
LowercaseSingleton.class.getDeclaredConstructor(Singleton.class);
break;
case UPPERCASE:
UppercaseSingleton.class.getDeclaredConstructor(Singleton.class);
//Singleton.setKind(SingletonKind.UPPERCASE);
//Singleton.setKind(SingletonKind.LOWERCASE);
Fortunately, expressions that evaluate to int can be used in place of an Integer when it is needed.
ints.add(Integer.valueOf(i));
And retains properties from Integer#valueOf such as having the same Integer objects cached by the JVM when it
is within the number caching range.
Care must be taken, however, in ambiguous situations. Consider the following code:
The java.util.List interface contains both a remove(int index) (List interface method) and a remove(Object
o) (method inherited from java.util.Collection). In this case no boxing takes place and remove(int index) is
called.
One more example of strange Java code behavior caused by autoboxing Integers with values in range from -128 to
127:
This happens because >= operator implicitly calls intValue() which returns int while
==
==
works because the Integers in this range reference to the same objects if their values are same. Maximal value of
the cacheable range can be defined with -XX:AutoBoxCacheMax JVM option. So, if you run the program with -
XX:AutoBoxCacheMax=1000, the following code will print true:
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // true
This is a minimalistic example, but in practice it often manifests in more sophisticated forms. The
NullPointerException is not very intuitive and is often little help in locating such bugs.
Rely on autoboxing and auto-unboxing with care, make sure that unboxed values will not have null values at
runtime.
Boolean a = Boolean.TRUE;
if (a) { // a gets converted to boolean
System.out.println("It works!");
}
That works for while, do while and the condition in the for statements as well.
Note that, if the Boolean is null, a NullPointerException will be thrown in the conversion.
If a method requires an object of wrapper class as argument.Then interchangeably the argument can be passed a
variable of the respective primitive type and vice versa.
Example:
int i;
Integer j;
void ex_method(Integer i)//Is a valid statement
void ex_method1(int j)//Is a valid statement
When a method returns a primitive type variable then an object of corresponding wrapper class can be passed as
the return value interchangeably and vice versa.
Example:
int i;
Integer j;
int ex_method()
{...
return j;}//Is a valid statement
Integer ex_method1()
{...
return i;//Is a valid statement
}
Whenever performing operations on numbers the primitive type variable and object of respective wrapper class
can be used interchangeably.
int i=5;
Integer j=new Integer(7);
int k=i+j;//Is a valid statement
Integer m=i+j;//Is also a valid statement
While using wrapper class object and primitive variable interchangeably never forget or miss to initialize or assign a
value to the wrapper class object else it may lead to null pointer exception at runtime.
Example:
In the above example, the value of the object is unassigned and uninitialized and thus at runtime the program will
run into null pointer exception.So as clear from the above example the value of object should never be left
uninitialized and unassigned.
will typically consume substantial amount of memory (about 60kb for 6k of actual data).
Furthermore, boxed integers usually require additional round-trips in the memory, and thus make CPU caches less
effective. In above example, the memory accessed is spread out to five different locations that may be in entirely
different regions of the memory: 1. the HashMap object, 2. the map's Entry[] table object, 3. the Entry object, 4.
the entrys key object (boxing the primitive key), 5. the entrys value object (boxing the primitive value).
class Example {
int primitive; // Stored directly in the class `Example`
Integer boxed; // Reference to another memory location
}
Reading boxed requires two memory accesses, accessing primitive only one.
When getting data from this map, the seemingly innocent code
int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
sumOfSquares += square.get(i);
}
is equivalent to:
int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
sumOfSquares += square.get(Integer.valueOf(i)).intValue();
}
Typically, the above code causes the creation and garbage collection of an Integer object for every
Map#get(Integer) operation. (See Note below for more details.)
To reduce this overhead, several libraries offer optimized collections for primitive types that do not require boxing.
In addition to avoiding the boxing overhead, these collection will require about 4x less memory per entry. While
Java Hotspot may be able to optimize the autoboxing by working with objects on the stack instead of the heap, it is
not possible to optimize the memory overhead and resulting memory indirection.
Java 8 streams also have optimized interfaces for primitive data types, such as IntStream that do not require
Note: a typical Java runtime maintains a simple cache of Integer and other primitive wrapper object that is used by
the valueOf factory methods, and by autoboxing. For Integer, the default range of this cache is -128 to +127. Some
JVMs provide a JVM command-line option for changing the cache size / range.
The Java 2D API is powerful and complex. There are multiple ways to do 2D graphics in Java.
Most methods of the Graphics class can be divided into two basic groups:
1. Draw and fill methods, enabling you to render basic shapes, text, and images
2. Attributes setting methods, which affect how that drawing and filling appears
Code Example: Let us start this with a little example of drawing a rectangle and filling color in it. There we declare
two classes, one class is MyPanel and other Class is Test. In class MyPanel we use drawRect( ) & fillRect( ) mathods
to draw rectangle and fill Color in it. We set the color by setColor(Color.blue) method. In Second Class we Test our
graphic which is Test Class we make a Frame and put MyPanel with p=new MyPanel() object in it.By running Test
Class we see a Rectangle and a Blue Color Filled Rectangle.
import javax.swing.*;
import java.awt.*;
// MyPanel extends JPanel, which will eventually be placed in a JFrame
public class MyPanel extends JPanel {
// custom painting is performed by the paintComponent method
@Override
public void paintComponent(Graphics g){
import javax.swing.;
import java.awt.;
public class Test { //the Class by which we display our rectangle
JFrame f;
MyPanel p;
public Test(){
f = new JFrame();
// get the content area of Panel.
Container c = f.getContentPane();
// set the LayoutManager
c.setLayout(new BorderLayout());
p = new MyPanel();
// add MyPanel object into container
c.add(p);
// set the size of the JFrame
f.setSize(400,400);
// make the JFrame visible
f.setVisible(true);
// sets close behavior; EXIT_ON_CLOSE invokes System.exit(0) on closing the JFrame
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
paintComponent( )
Note: The Java 2D API enables you to easily perform the following tasks:
g2.fillOval(int x,int y,int height, int width); This method will fill an oval at specified x and y position with given
height and width.
JAXB or Java Architecture for XML Binding (JAXB) is a software framework that allows Java developers to map Java
classes to XML representations. This Page will introduce readers to JAXB using detailed examples about its functions
provided mainly for marshaling and un-marshaling Java Objects into xml format and vice-versa.
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class User {
Here we have created the variables and class name according to the XML nodes. To map them, we use the
annotation XmlRootElement on the class.
Here unmarshal() method is used to parse the XML file. It takes the XML file name and the class type as two
arguments. Then we can use the getter methods of the object to print the data.
@XmlRootElement
By using the annotation XMLRootElement, we can mark a class as a root element of an XML file.
import java.io.File;
import javax.xml.bind.JAXB;
try {
JAXB.marshal(user, new File("UserDetails.xml"));
} catch (Exception e) {
System.err.println("Exception occurred while writing in XML!");
} finally {
System.out.println("XML created");
}
}
}
marshal() is used to write the object's content into an XML file. Here userobject and a new File object are passed
as arguments to the marshal().
On successful execution, this creates an XML file named UserDetails.xml in the class-path with the below content.
@XmlElement
private String field="field value";
@XmlAttribute
private String attribute="attr value";
@XmlAttribute(name="differentAttribute")
private String oneAttribute="other attr value";
@XmlElement(name="different name")
@XmlTransient
private String transientField = "will not get serialized ever";
@XmlElement
public String getModifiedTransientValue() {
return transientField.replace(" ever", ", unless in a getter");
}
/**
* A package containing serializable classes.
*/
@XmlSchema
(
xmlns =
{
@XmlNs(prefix = MySerializableClass.NAMESPACE_PREFIX, namespaceURI =
MySerializableClass.NAMESPACE)
},
namespace = MySerializableClass.NAMESPACE,
elementFormDefault = XmlNsForm.QUALIFIED
)
package com.test.jaxb;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlAttribute(name="attrValue")
String value;
public NodeValueElement() {
}
@Override
public NodeValueElement marshal(String v) throws Exception {
return new NodeValueElement(v);
}
@Override
public String unmarshal(NodeValueElement v) throws Exception {
if (v==null) return "";
return v.getValue();
}
}
@XmlRootElement(name="DataObject")
@XmlAccessorType(XmlAccessType.FIELD)
public static class DataObject {
String elementWithValue;
@XmlJavaTypeAdapter(value=ValueAsAttrXmlAdapter.class)
String elementWithAttribute;
}
System.out.println(xmlString);
}
}
import javax.xml.bind.annotation.adapters.XmlAdapter;
@Override
public String marshal(String v) throws Exception {
if (v == null)
return null;
return v.trim();
}
}
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType(XmlAccessType.FIELD)
static class AccessorExampleField {
public String field="value1";
@XmlAccessorType(XmlAccessType.NONE)
static class AccessorExampleNone {
public String field="value1";
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
static class AccessorExamplePublic {
public String field="value1";
Output
Field:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
value1
None:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Property:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
getter
Public:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
value1
It is possible to specify a XmlAdapter instance the Unmarshaller should use, which allows the user to use
XmlAdapters with no zero-arg constructor and/or pass data to the adapter.
Example
User class
import java.awt.image.BufferedImage;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
public class User {
@XmlAttribute
public String getName() {
return name;
}
@XmlJavaTypeAdapter(value=ImageCacheAdapter.class)
@XmlAttribute
public BufferedImage getImage() {
return image;
}
public User() {
this("", null);
}
Adapter
Version ≤ Java SE 7
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.xml.bind.annotation.adapters.XmlAdapter;
@Override
public BufferedImage unmarshal(String v) throws Exception {
return getImage(new URL(v));
}
@Override
public String marshal(BufferedImage v) throws Exception {
return reverseIndex.get(v).toExternalForm();
}
Example XMLs
The following 2 xmls are for Jon Skeet and his earth 2 counterpart, which both look exactly the same and therefore
use the same avatar.
System.out.println(result1.getName());
System.out.println(result2.getName());
The java.lang and java.lang.reflect packages provide classes for java reflection.
Where it is used
IDE (Integrated Development Environment) e.g. Eclipse, MyEclipse, NetBeans etc. Debugger Test Tools etc.
class Test {
void printName(Object obj){
Class c = obj.getClass();
System.out.println(c.getName());
}
public static void main(String args[]){
Simple s = new Simple();
while (true) {
// Wait for a client connection.
// Once a client connected, we get a "Socket" object
// that can be used to send and receive messages to/from the newly
// connected client
Socket clientSocket = serverSocket.accept();
We'll handle each client in a separate thread so multiple clients could interact with the server at the same time. This
technique works fine as long as the number of clients is low (<< 1000 clients, depending on the OS architecture and
the expected load of each thread).
The above examples left out some things to make them easier to read.
1. Just like files and other external resources, it's important we tell the OS when we're done with them. When
we're done with a socket, call socket.close() to properly close it.
2. Sockets handle I/O (Input/Output) operations that depend on a variety of external factors. For example what
A more complete code for the client would therefore be something like this:
Server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
}
}
Client:
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.io.*;
import java.net.*;
In this case, we pass in the address of the server, via an argument (args[0]). The port we are using is 4160.
Server.java
import java.io.*;
import java.net.*;
On the server-side, declare a DatagramSocket on the same port which we sent our message to (4160) and wait for a
response.
}
}
Intiating a KeyStore works the same, except replace any word Trust in a object name with Key. Additionally, the
KeyManager[] array must be passed to the the first argument of SSLContext.init. That is
SSLContext.init(keyMangers, trustMangers, null)
public static void main(String[] args) throws IOException {//We don't handle Exceptions in this
example
//Open a socket to stackoverflow.com, port 80
Socket socket = new Socket("stackoverflow.com",80);
You should get a response that starts with HTTP/1.1 200 OK, which indicates a normal HTTP response, followed by
the rest of the HTTP header, followed by the raw web page in HTML form.
Note the readFully() method is important to prevent a premature EOF exception. The last line of the web page
may be missing a return, to signal the end of line, then readLine() will complain, so one must read it by hand or
use utility methods from Apache commons-io IOUtils
This example is meant as a simple demonstration of connecting to an existing resource using a socket, it's not a
To continue developing and testing, you can turn off SSL verification programmatically by installing an "all-trusting"
trust manager:
try {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
Notes
// join by ip
socket.joinGroup(InetAddress.getByName(ip));
}
Run the Client First: The Client must subscribe to the IP before it can start receiving any packets. If you start the
server and call the send() method, and then make a client (& call printMessage()). Nothing will happen because
the client connected after the message was sent.
It allows for separation between detecting socket I/O (something can be read/written/...) and performing the I/O
(read/write/...). Especially, all I/O detection can be done in a single thread for multiple sockets (clients), while
performing I/O can be handled in a thread pool or anywhere else. That allows for an application to scale easily to
the number of connected clients.
1. Create a Selector
2. Create a SocketChannel
3. Register the SocketChannelto the Selector
4. Loop with the Selector to detect events
// Register the Channel TO the Selector FOR wake-up ON CONNECT event AND USE SOME description AS an
attachement
sc.register(sel, SelectionKey.OP_CONNECT, "Connection to google.com"); // RETURNS a SelectionKey:
the association BETWEEN the SocketChannel AND the Selector
System.out.println("Initiating connection");
IF (sc.connect(NEW InetSocketAddress("www.google.com", 80)))
System.out.println("Connected"); // Connected right-away: nothing ELSE TO do
ELSE {
BOOLEAN exit = FALSE;
while (!exit) {
IF (sel.select(100) == 0) // Did something happen ON SOME registered Channels during the
LAST 100ms?
continue; // No, wait SOME more
// Something happened...
Set<SelectionKey> KEYS = sel.selectedKeys(); // List OF SelectionKeys ON which SOME
registered operation was triggered
FOR (SelectionKey k : KEYS) {
System.out.println("Checking "+k.attachment());
IF (k.isConnectable()) { // CONNECT event
System.out.print("Connected through select() on "+k.channel()+" -> ");
IF (sc.finishConnect()) { // Finish connection process
System.out.println("done!");
k.interestOps(k.interestOps() & ~SelectionKey.OP_CONNECT); // We are already
connected: remove interest IN CONNECT event
Initiating connection
Checking Connection to google.com
Connected through 'select()' on java.nio.channels.SocketChannel[connection-pending
remote=www.google.com/216.58.208.228:80] -> done!
Disconnecting ... done
in.close();
return response.toString();
}
This will download text data from the specified URL, and return it as a String.
First, we create a HttpUrlConnection from our URL, with new URL(url).openConnection(). We cast the
UrlConnection this returns to a HttpUrlConnection, so we have access to things like adding headers (such as
User Agent), or checking the response code. (This example does not do that, but it's easy to add.)
Then, create InputStream basing on the response code (for error handling)
Then, create a BufferedReader which allows us to read text from InputStream we get from the connection.
Notes:
This method will throw an IoException in case of failure (such as a network error, or no internet connection),
and it will also throw an unchecked MalformedUrlException if the given URL is not valid.
It can be used for reading from any URL which returns text, such as webpages (HTML), REST APIs which
return JSON or XML, etc.
Is very simple:
try {
connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("Content-Type", contentType);
connection.setDoOutput(true);
out = connection.getOutputStream();
out.write(data);
out.close();
in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
in.close();
} finally {
if (connection != null) connection.disconnect();
if (out != null) out.close();
if (in != null) in.close();
}
}
This will POST data to the specified URL, then read the response line-by-line.
How it works
try {
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) connection.disconnect();
}
}
This will DELETE the resource in the specified URL, then print the response header.
How it works
Explanation:
If you are just checking if a resource exists, it better to use a HEAD request than a GET. This avoids the overhead of
transferring the resource.
Note that the method only returns true if the response code is 200. If you anticipate redirect (i.e. 3XX) responses,
then the method may need to be enhanced to honor them.
Here is an example where Service is the service class representation and Port is the service port you want to
access.
port.call();
// Outcome:
// 'Script from file!' printed on standard output
demo.js:
// Outcome:
// Nothing printed on standard output, but
// Outcome:
// 'Hello Nashorn!' printed on standard output
//String to be evaluated
String str = "3+2*4+5";
//Value after doing Arithmetic operation with operator precedence will be 16
//Outcome:
//Value of the string after arithmetic evaluation is printed on standard output.
//In this case '16.0' will be printed on standard output.
// Outcome:
// 'Data defined in Java.' printed on standard output
try {
// Set value in the global name space of the engine
engine.put("name","Nashorn");
// Execute an hardcoded script
engine.eval("var value='Hello '+name+'!';");
// Get value
String value=(String)engine.get("value");
System.out.println(value);
} catch (ScriptException ex) {
// This is the generic Exception subclass for the Scripting API
ex.printStackTrace();
}
// Outcome:
// 'Hello Nashorn!' printed on standard output
Below there is a table which describes behaviour of native Java objects inside JavaScript constructions.
Tested constructions:
1. Expression in if clause. In JS expression in if clause doesn't have to be boolean unlike Java. It's evaluated as
false for so called falsy values (null, undefined, 0, empty strings etc)
2. for each statement Nashorn has a special kind of loop - for each - which can iterate over different JS and Java
object.
3. Getting object size. In JS objects have a property length, which returns size of an array or a string.
Results:
Recommendatons:
It's advisable to use if (some_string) to check if a string is not null and not empty
for each can be safely used to iterate over any collection, and it doesn't raise exceptions if the collection is
not iterable, null or undefined
Before getting length of an object it must be checked for null or undefined (the same is true for any attempt
of calling a method or getting a property of Java object)
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
try {
//evaluate a script
/* pet.js */
/*
var Pet = Java.type("InterfaceImplementationExample.Pet");
new Pet() {
eat: function() { print("eat"); }
}
*/
pet.eat();
} catch (ScriptException ex) {
ex.printStackTrace();
}
// Outcome:
// 'eat' printed on standard output
}
}
Java code
/*** com/example/jni/JNIJava.java **/
package com.example.jni;
C++ code
Header files containing native function declarations should be generated using the javah tool on target classes.
Running the following command at the build directory :
... produces the following header file (comments stripped for brevity) :
// com_example_jni_JNIJava.hpp
#ifndef _Included_com_example_jni_JNIJava
#define _Included_com_example_jni_JNIJava
#ifdef __cplusplus
extern "C" { // This is absolutely required if using a C++ compiler
#endif
#ifdef __cplusplus
}
#endif
#endif
// com_example_jni_JNIJava.cpp
#include <iostream>
#include "com_example_jni_JNIJava.hpp"
Output
1. obtain a method pointer with the GetMethodID JNI function, using the method name and descriptor ;
2. call one of the Call*Method functions listed here.
Java code
/*** com.example.jni.JNIJavaCallback.java ***/
C++ code
// com_example_jni_JNICppCallback.cpp
#include <iostream>
#include "com_example_jni_JNIJavaCallback.h"
Output
Descriptors (or internal type signatures) are obtained using the javap program on the compiled .class file. Here is
the output of javap -p -s com.example.jni.JNIJavaCallback :
public com.example.jni.JNIJavaCallback();
Calls to System.loadLibrary are almost always static so as to occur during class loading, ensuring that no native
method can execute before the shared library has been loaded. However the following is possible :
...
This allows to defer shared library loading until necessary, but requires extra care to avoid
java.lang.UnsatisfiedLinkErrors.
Shared library files are searched for in the paths defined by the java.library.path system property, which can be
overriden using the -Djava.library.path= JVM argument at runtime :
Watch out for system path separators : for example, Windows uses ; instead of :.
Note that System.loadLibrary resolves library filenames in a platform-dependent manner : the code snippet above
expects a file named libExample.so on Linux, and Example.dll on Windows.
An alternative to System.loadLibrary is System.load(String), which takes the full path to a shared library file,
circumventing the java.library.path lookup :
...
This allows you to chain the different method calls which makes your code shorter and easier to handle for the
developers.
As the setter methods don't return anything, we need 4 instructions in the mainmethod to instantiate a Person with
some data and print it. With a fluent style this code can be changed to:
The idea is to always return some object to enable building of a method call chain and to use method names which
reflect natural speaking. This fluent style makes the code more readable.
The name deque is short for "double ended queue" and is usually pronounced "deck".
Most Deque implementations place no fixed limits on the number of elements they may contain, but this interface
supports capacity-restricted deques as well as those with no fixed size limit.
The Deque interface is a richer abstract data type than both Stack and Queue because it implements both stacks
and queues at same time
//Retrieves, but does not remove, the first element of this deque.
Object firstItem = deque.getFirst();
//Retrieves, but does not remove, the last element of this deque.
Object lastItem = deque.getLast();
In this example 2 clients send information to each other through a server. One client sends the server a number
which is relayed to the second client. The second client halves the number and sends it back to the first client
through the server. The first client does the same. The server stops the communication when the number returned
to it by any of the clients is less than 10. The return value from the server to the clients (the number it got converted
to string representation) then backtracks the process.
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
The server:
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
The client:
package callbackRemote;
import java.rmi.Remote;
The implementations
package callbackServer;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;
@Override
public RemoteConnection login(String name, RemoteClient client) {
try {
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
LoginServer server = new LoginServer();
UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
reg.rebind("LoginServerName", server);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
The server:
package callbackServer;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
RemoteClient client;
String name;
this.client = client;
this.name = name;
try {
UnicastRemoteObject.exportObject(this, Registry.REGISTRY_PORT);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void unreferenced() {
try {
UnicastRemoteObject.unexportObject(this, true);
} catch (NoSuchObjectException e) {
e.printStackTrace();
}
}
@Override
public void logout() {
try {
UnicastRemoteObject.unexportObject(this, true);
} catch (NoSuchObjectException e) {
e.printStackTrace();
}
}
@Override
public String passInt(String recipient, int i) {
The client:
package callbackClient;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
RemoteConnection connection;
String name, target;
this.name = name;
this.target = target;
}
if ("Client1".equals(client.name)) {
try {
client.connection.passInt(client.target, 120);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void half(int i) throws RemoteException {
The outputs will appear in 3 consoles since there are 3 JVMs. here they are lumped together:
Client2 logged in
Client1 logged in
Server received from Client1:120
Server received from Client2:60
Server received from Client1:30
Server received from Client2:15
Server received from Client1:7
Server Package
PersonListInterface.java
PersonListImplementation.java
/**
* Implementation of "PersonListInterface"
* @throws RemoteException
*/
@Override
public ArrayList<String> getPersonList() throws RemoteException
{
ArrayList<String> personList = new ArrayList<String>();
personList.add("Peter Pan");
personList.add("Pippi Langstrumpf");
// add your name here :)
return personList;
}
}
Server.java
Client package
PersonListLocal.java
/**
* Create a singleton instance
*/
private PersonListLocal() {
try {
// Lookup to the local running server with port 1099
final Registry registry = LocateRegistry.getRegistry("localhost",
Registry.REGISTRY_PORT);
return instance;
}
/**
* Returns the servers PersonList
*/
public ArrayList<String> getPersonList() {
if (instance != null) {
PersonTest.java
Peter Pan
Pippi Langstrumpf
package remote;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import remote.RemoteServer;
@Override
public int stringToInt(String string) throws RemoteException {
try {
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
Server server = new Server();
UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
reg.rebind("ServerName", server);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
package client;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import remote.RemoteServer;
try {
Registry reg = LocateRegistry.getRegistry();
server = (RemoteServer) reg.lookup("ServerName");
} catch (RemoteException | NotBoundException e) {
e.printStackTrace();
}
void callServer() {
Output:
Output :
Old Size : 5
New Size : 3
Note that is the code above is the safe way to remove elements while iterating a typical collection. If instead, you
attempt to do remove elements from a collection like this:
a typical collection (such as ArrayList) which provides iterators with fail fast iterator semantics will throw a
ConcurrentModificationException.
The remove() method can only called (once) following a next() call. If it is called before calling next() or if it is
called twice following a next() call, then the remove() call will throw an IllegalStateException.
The remove operation is described as an optional operation; i.e. not all iterators will allow it. Examples where it is not
supported include iterators for immutable collections, read-only views of collections, or fixed sized collections. If
remove() is called when the iterator does not support removal, it will throw an UnsupportedOperationException.
@Override
public Iterator<Character> iterator() {
return new Iterator<Character>() {
char letter = 'a';
@Override
public boolean hasNext() {
return letter <= 'z';
}
@Override
public Character next() {
return letter++;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Doesn't make sense to remove a letter");
}
};
}
}
To use:
The new Iterator should come with a state pointing to the first item, each call to next updates its state to point to
the next one. The hasNext() checks to see if the iterator is at the end. If the iterator were connected to a modifiable
collection then the iterator's optional remove() method might be implemented to remove the item currently
pointed to from the underlying collection.
// foreach-like loop
for (Integer i: iterable) {
This is much easier and clearer than having a isLastEntry variable or doing calculations with the loop index.
if(methodName.equals("someMethod1")){
System.out.println("someMethod1 was invoked!");
return null;
}
if(methodName.equals("someMethod2")){
System.out.println("someMethod2 was invoked!");
System.out.println("Parameter: " + args[0]);
return 42;
}
if(methodName.equals("anotherMethod")){
System.out.println("anotherMethod was invoked!");
return null;
}
System.out.println("Unkown method!");
return null;
The Reflection API allows one to check the class structure of the code at runtime and invoke code dynamically. This
is very powerful, but it is also dangerous since the compiler is not able to statically determine whether dynamic
invocations are valid.
A simple example would be to get the public constructors and methods of a given class:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
With this information it is possible to instance the object and call different methods dynamically.
The following example shows how to extract the generic type information in all three cases:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
System.out.println("Method parameter:");
final Type parameterType = method.getGenericParameterTypes()[0];
displayGenericType(parameterType, "\t");
System.out.println("Field type:");
final Type fieldType = field.getGenericType();
displayGenericType(fieldType, "\t");
Method parameter:
java.util.Map
java.lang.String
java.lang.Double
Method return type:
java.util.List
java.lang.Number
Field type:
java.util.Map
java.lang.String
java.util.Map
java.lang.Integer
java.util.List
java.lang.String
Lets start first with the only limitation means the only field we can't change with Reflection. That is the Java
SecurityManager. It is declared in java.lang.System as
for(Field f : System.class.getDeclaredFields())
System.out.println(f);
Thats because of the fieldFilterMap in sun.reflect.Reflection that holds the map itself and the security field in
the System.class and protects them against any access with Reflection. So we could not deactivate the
SecurityManager.
Crazy Strings
Each Java String is represented by the JVM as an instance of the String class. However, in some situations the JVM
saves heap space by using the same instance for Strings that are. This happens for string literals, and also for
strings that have been "interned" by calling String.intern(). So if you have "hello" in your code multiple times it
is always the same object instance.
Strings are supposed to be immutable, but it is possible to use "evil" reflection to change them. The example below
show how we can change the characters in a String by replacing its value field.
1 = 42
Everything is true
And according to this stackoverflow post we can use reflection to do something really evil.
Note that what we are doing here is going to cause the JVM to behave in inexplicable ways. This is very dangerous.
import java.lang.reflect.*;
class A {
private String name;
public int age;
public final String rep;
public static int count=0;
public A(){
name = "Unset";
age = 0;
rep = "Reputation";
count++;
}
}
Output:
A.name=StackOverFlow
A.age=20
A.rep=New Reputation
A.count=25
Explanation:
In normal scenario, private variables can't be accessed outside of declared class ( without getter and setter
methods). final variables can't be re-assigned after initialization.
Reflection breaks both barriers can be abused to change both private and final variables as explained above.
To do so, you will need to use the method Class#getField() in a way such as the one shown below:
// Get the field in class Field "modifiers". Note that it does not
// need to be static
Field modifiersField = Field.class.getDeclaredField("modifiers");
// Set the value of the modifiers field under an object for non-static fields
modifiersField.setInt(nameField, newModifiersOnNameField);
// Here I can directly access it. If needed, use reflection to get it. (Below)
System.out.println(SomeClass.NAME);
Getting fields is much easier. We can use Field#get() and its variants to get its value:
Do note this:
class Hacked {
public String someState;
}
Here, HackMe#iAmDeclared is declared field. However, HackMe#someState is not a declared field as it is inherited
from its superclass, Hacked.
You can obtain Constructor class from the Class object like this:
Where the constructors variable will have one Constructor instance for each public constructor declared in the
If you know the precise parameter types of the constructor you want to access, you can filter the specific
constructor. The next example returns the public constructor of the given class which takes a Integer as
parameter:
If the nested class is static you will not need this enclosing instance.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
It can be specified, if the class should be initialized (second parameter of forName) and which ClassLoader should
be used (third parameter):
enum Compass {
NORTH(0),
EAST(90),
SOUTH(180),
WEST(270);
private int degree;
Compass(int deg){
degree = deg;
}
public int getDegree(){
return degree;
}
}
In Java an enum class is like any other class but has some definied constants for the enum values. Additionally it has
a field that is an array that holds all the values and two static methods with name values() and valueOf(String).
We can see this if we use Reflection to print all fields in this class
for(Field f : Compass.class.getDeclaredFields())
System.out.println(f.getName());
NORTH
So we could examine enum classes with Reflection like any other class. But the Reflection API offers three enum-
specific methods.
enum check
Compass.class.isEnum();
retrieving values
Returns an array of all enum values like Compass.values() but without the need of an instance.
for(Field f : Compass.class.getDeclaredFields()){
if(f.isEnumConstant())
System.out.println(f.getName());
}
import java.lang.reflect.*;
class NewInstanceWithReflection{
public NewInstanceWithReflection(){
System.out.println("Default constructor");
}
public NewInstanceWithReflection( String a){
System.out.println("Constructor :String => "+a);
}
public static void main(String args[]) throws Exception {
NewInstanceWithReflection object =
(NewInstanceWithReflection)Class.forName("NewInstanceWithReflection").newInstance();
Constructor constructor = NewInstanceWithReflection.class.getDeclaredConstructor( new
Class[] {String.class});
NewInstanceWithReflection object1 = (NewInstanceWithReflection)constructor.newInstance(new
Object[]{"StackOverFlow"});
}
}
output:
Explanation:
This operation will allocate 16 bytes of memory. The contents of direct buffers may reside outside of the normal
garbage-collected heap.
directBuffer.isDirect(); // true
The main characteristics of DirectByteBuffer is that JVM will try to natively work on allocated memory without any
additional buffering so operations performed on it may be faster then those performed on ByteBuffers with arrays
lying underneath.
It is recomended to use DirectByteBuffer with heavy IO operations that rely on speed of execution, like real time
communication.
We have to be aware that if we try using array() method we will get UnsupportedOperationException. So it is a
good practice to chech whether our ByteBuffer has it (byte array) before we try to access it:
byte[] arrayOfBytes;
if(buffer.hasArray()) {
arrayOfBytes = buffer.array();
}
Another use of direct byte buffer is interop through JNI. Since a direct byte buffer does not use a byte[], but an
actual block of memory, it is possible to access that memory directly through a pointer in native code. This can save
a bit of trouble and overhead on marshalling between the Java and native representation of data.
The JNI interface defines several functions to handle direct byte buffers: NIO Support.
If you have an already existing byte[], you can "wrap" it into a ByteBuffer to simplify processing:
This would be a possibility for code that handles low-level networking interactions
If the code-path is extremely performance critical and you need direct system memory access, the ByteBuffer
can even allocate direct buffers using #allocateDirect()
Both methods allow "chaining" calls. Given a sufficiently sized buffer one can accordingly do the following:
buffer.putInt(0xCAFEBABE).putChar('c').putFloat(0.25).putLong(0xDEADBEEFCAFEBABE);
buffer.putInt(0xCAFEBABE);
buffer.putChar('c');
buffer.putFloat(0.25);
buffer.putLong(0xDEADBEEFCAFEBABE);
Do note that the method operating on bytes is not named specially. Additionally note that it's also valid to pass
both a ByteBuffer and a byte[] to put. Other than that, all primitive types have specialized put-methods.
An additional note: The index given when using absolute put* is always counted in bytes.
Recent years have seen an active push to move away from Applets and other browser plugins, with some browsers
blocking them or actively not supporting them.
In 2016, Oracle announced their plans to deprecate the plugin, Moving to a Plugin-Free Web
@Override
public void init() {
setBackground(Color.gray);
}
@Override
public void destroy() {}
@Override
public void start() {}
@Override
public void stop() {}
@Override
public void paint(Graphics g) {
g.setColor(Color.yellow);
g.fillRect(1,1,300,150);
g.setColor(Color.red);
g.setFont(new Font("TimesRoman", Font.PLAIN, 48));
g.drawString(str, 10, 80);
}
}
Before Java 1.2 and the introduction of the swing API applets had extended from java.applet.Applet.
Applets don't require a main method. The entry point is controlled by the life cycle. To use them, they need to be
embedded in a HTML document. This is also the point where their size is defined.
<html>
<head></head>
<body>
<applet code="MyApplet.class" width="400" height="200"></applet>
</body>
</html>
@Override
public void init(){
panel = new JPanel();
button = new JButton("ClickMe!");
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent ae) {
if(((String)cmbBox.getSelectedItem()).equals("greet")) {
JOptionPane.showMessageDialog(null,"Hello " + textField.getText());
} else {
JOptionPane.showMessageDialog(null,textField.getText() + " stinks!");
}
}
});
cmbBox = new JComboBox<>(new String[]{"greet", "offend"});
textField = new JTextField("John Doe");
panel.add(cmbBox);
panel.add(textField);
panel.add(button);
add(panel);
}
}
If you want to load resources from the same URL the Applet is stored you can use the method getCodeBase() to
retrieve the base URL. To load resources, applets offer the methods getImage() and getAudioClip() to load
images or audio files.
@Override
public void init(){
try {
img = getImage(new URL("http://cdn.sstatic.net/stackexchange/img/logos/so/so-
logo.png"));
} catch (MalformedURLException e) { /* omitted for brevity */ }
}
@Override
public void paint(Graphics g) {
g.drawImage(img, 0, 0, this);
}
}
@Override
public void init(){
try {
audioClip = getAudioClip(new URL("URL/TO/AN/AUDIO/FILE.WAV"));
} catch (MalformedURLException e) { /* omitted for brevity */ }
}
@Override
public void start() {
audioClip.play();
}
@Override
public void stop(){
audioClip.stop();
}
}
1. Add 1 and 2 and multiply the result by 3. This gives the answer 9. If we added parentheses, this would look
like ( 1 + 2 ) x 3.
2. Add 1 to the result of multiplying 2 and 3. This gives the answer 7. If we added parentheses, this would look
like 1 + ( 2 x 3 ).
In mathematics, the convention is to read the expression the second way. The general rule is that multiplication and
division are done before addition and subtraction. When more advanced mathematical notation is used, either the
meaning is either "self-evident" (to a trained mathematician!), or parentheses are added to disambiguate. In either
case, the effectiveness of the notation to convey meaning depends on the intelligence and shared knowledge of the
mathematicians.
Java has the same clear rules on how to read an expression, based on the precedence of the operators that are
used.
In general, each operator is ascribed a precedence value; see the table below.
For example:
1 + 2 * 3
The precedence of + is lower than the precedence of *, so the result of the expression is 7, not 9.
1 Lambda expression precedence is complex, as it can also occur after a cast, or as the third part of the conditional
ternary operator.
The details of the different forms of expressions may be found in other Topics.
The Operators topic covers unary, binary and ternary operator expressions.
The Lambda expressions topic covers lambda expressions and method reference expressions.
The Classes and Objects topic covers class instance creation expressions.
The Arrays topic covers array access expressions and array instance creation expressions.
The Literals topic covers the different kinds of literals expressions.
In most cases, an expression has a static type that can be determined at compile time by examining and its
subexpressions. These are referred to as stand-alone expressions.
Parenthesized expressions
Class instance creation expressions
Method invocation expressions
Method reference expressions
Conditional expressions
Lambda expressions
When an expression is a poly expression, its type may be influenced by the expression's target type; i.e. what it is
being used for.
The value of an expression is assignment compatible with its type. The exception to this is when heap pollution has
occurred; e.g. because "unsafe conversion" warnings have been (inappropriately) suppressed or ignored.
Expression Statements
Unlike many other languages, Java does not generally allow expressions to be used as statements. For example:
Since the result of evaluating an expression like cannot be use, and since it cannot affect the execution of the
program in any other way, the Java designers took the position that such usage is either a mistake, or misguided.
However, this does not apply to all expressions. A subset of expressions are (in fact) legal as statements. The set
comprises:
Simple Example
Note that if the effects of the calls are observable, you will be able to observe that the call to method1 occurs before
the call to method2.
int i = 1;
intArray[i] = ++i + 1;
Reference:
, ~ and !.
==
Simple names that refer to constant variables. (A constant variable is a variable declared as final where the
initializer expression is itself a constant expression.)
Qualified names of the form <TypeName> . <Identifier> that refer to constant variables.
--
, the assignment operators, class and instanceof, method calls and references to general variables or fields.
Constant expressions of type String result in an "interned" String, and floating point operations in constant
expressions are evaluated with FP-strict semantics.
Constant expressions can be used (just about) anywhere that a normal expression can be used. However, they have
a special significance in the following contexts.
Constant expressions are required for case labels in switch statements. For example:
switch (someValue) {
case 1 + 1: // OK
case Math.min(2, 3): // Error - not a constant expression
doSomething();
}
When the expression on the right hand side of an assignment is a constant expression, then the assignment can
perform a primitive narrowing conversion. This is allowed provided that the value of the constant expression is
within the range of the type on the left hand side. (See JLS 5.1.3 and 5.2) For example:
When a constant expression is used as the condition in a do, while or for, then it affects the readability analysis.
For example:
while (false) {
doSomething(); // Error - statenent not reachable
}
(Note that this does not apply if statements. The Java compiler allows the then or else block of an if statement to
be unreachable. This is the Java analog of conditional compilation in C and C++.)
Finally, static final fields in an class or interface with constant expression initializers are initialized eagerly. Thus,
it is guaranteed that these constants will be observed in the initialized state, even when there is a cycle in the class
initialization dependency graph.
Details
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper instance
//creating one
ObjectMapper objectMapper = new ObjectMapper();
ObjectMapper is threadsafe
recommended: have a shared, static instance
Deserialization:
<T> T readValue(String content, Class<T> valueType)
Throws
JsonProcessingException in case of an error
Note: prior to version 2.1, throws clause included IOException; 2.1 removed it.
Code:
JSONObject.NULL is a sentinel value used to explicitly define a property with an empty value.
Note
JSONObject example
JSONArray
Code:
// However, if a value cannot be coerced to the required type, the behavior differs
obj.getInt("foo"); // throws JSONException
obj.optInt("foo"); // returns 0
obj.optInt("foo", 123); // returns 123
System.out.println(jsonObject.get("name").getAsString()); //John
System.out.println(jsonObject.get("age").getAsInt()); //21
{
"list": [
"Test_String_1",
"Test_String_2"
]
}
Now pass the JsonArray 'list' to the following method which returns a corresponding Java ArrayList:
You should add the following maven dependency to your POM.xml file:
first.put("foo", "bar");
first.put("temperature", 21.5);
first.put("year", 2016);
// Encode
String json = object.toString();
String json =
"{\"foo\":\"bar\",\"temperature\":21.5,\"year\":2016,\"message\":{\"Hello\":\"world\"},\"months\":[
\"January\",\"February\",\"March\",null,\"May\"]}";
// Retrieve an array
JSONArray someMonths = object.getJSONArray("months");
// Get some values from the array
int nMonths = someMonths.length();
String february = someMonths.getString(1);
One can use the following code to parse it and build a map of book titles by book id.
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
System.out.println(bookTitlesById);
}
This outputs :
1. The use of xmlStreamReader.getAttributeValue works because we have checked first that the parser is in
the START_ELEMENT state. In evey other states (except ATTRIBUTES), the parser is mandated to throw
IllegalStateException, because attributes can only appear at the beginning of elements.
For more complex documents parsing (deeper, nested elements, ...), it is a good practice to "delegate" the parser to
sub-methods or other objets, e.g. have a BookParser class or method, and have it deal with every element from the
START_ELEMENT to the END_ELEMENT of the book XML tag.
One can also use a Stack object to keep around important datas up and down the tree.
One can use the following code to build a DOM tree out of a String :
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
<documentation>
<tags>
<tag name="Java">
<topic name="Regular expressions">
<example>Matching groups</example>
<example>Escaping metacharacters</example>
</topic>
<topic name="Arrays">
<example>Looping over arrays</example>
<example>Converting an array to a list</example>
</topic>
</tag>
<tag name="Android">
<topic name="Building Android projects">
<example>Building an Android application using Gradle</example>
<example>Building an Android application using Maven</example>
</topic>
<topic name="Layout resources">
<example>Including layout resources</example>
<example>Supporting multiple device screens</example>
</topic>
</tag>
</tags>
</documentation>
This is how you would use XPath to evaluate multiple expressions in one document:
...
Overall, two calls to XPathExpression.evaluate() will be much more efficient than two calls to XPath.evaluate().
<documentation>
<tags>
<tag name="Java">
<topic name="Regular expressions">
<example>Matching groups</example>
<example>Escaping metacharacters</example>
</topic>
<topic name="Arrays">
<example>Looping over arrays</example>
<example>Converting an array to a list</example>
</topic>
</tag>
<tag name="Android">
<topic name="Building Android projects">
<example>Building an Android application using Gradle</example>
<example>Building an Android application using Maven</example>
</topic>
<topic name="Layout resources">
<example>Including layout resources</example>
<example>Supporting multiple device screens</example>
</topic>
</tag>
</tags>
</documentation>
The following retrieves all example nodes for the Java tag (Use this method if only evaluating XPath in the XML once.
See other example for when multiple XPath calls are evaluated in the same XML file.):
To get the root element, the highest parent in the xml file, you need to use the getRootElement() on the Document
instance.
Now the Element class has a lot of handy methods that make reading xml really easy. Some of the most useful are
listed below:
When you call the getChildElements() you get a Elements instance. From this you can loop through and call the
get(int index) method on it to retrieve all the elements inside.
XML File:
// get the name element and its children: first and last
Element nameElement = person.getFirstChildElement("name");
Element firstNameElement = nameElement.getFirstChildElement("first");
Element lastNameElement = nameElement.getFirstChildElement("last");
try {
fName = firstNameElement.getValue();
lName = lastNameElement.getValue();
age = Integer.parseInt(ageElement.getValue());
ageUnit = ageElement.getAttributeValue("unit");
favColor = favColorElement.getValue();
To make a new Element use the constructor Element(String name). You will want to make a root element so that
you can easily add it to a Document.
The Element class has some handy methods for editing elements. They are listed below:
appendChild(String name) - this will basically set the value of the element to name.
appendChild(Node node) - this will make node the elements parent. (Elements are nodes so you can parse
elements).
addAttribute(Attribute attribute) - will add an attribute to the element.
The Attribute class has a couple of different constructors. The simplest one is Attribute(String name, String
value).
Once you have all of your elements add to your root element you can turn it into a Document. Document will take a
Element as an argument in it's constructor.
You can use a Serializer to write your XML to a file. You will need to make a new output stream to parse in the
constructor of Serializer.
Example
Code:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import nu.xom.Attribute;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Elements;
import nu.xom.ParsingException;
import nu.xom.Serializer;
// make the name element and it's children: first and last
Element nameElement = new Element("name");
Element firstNameElement = new Element("first");
Element lastNameElement = new Element("last");
public Person(String lName, String fName, String ageUnit, String favColor, int age){
this.lName = lName;
this.fName = fName;
this.age = age;
this.ageUnit = ageUnit;
this.favColor = favColor;
}
There are two ways to perform polymorphism. Method Overloading and Method Overriding.
In Java, this translates to subclasses overriding the methods defined in the super class. In Java, all non-primitive
variables are actually references, which are akin to pointers to the location of the actual object in memory. The
references only have one type, which is the type they were declared with. However, they can point to an object of
either their declared type or any of its subtypes.
When a method is called on a reference, the corresponding method of the actual object being pointed to is
invoked.
class SuperType {
public void sayHello(){
System.out.println("Hello from SuperType");
}
class Test {
public static void main(String... args){
SuperType superType = new SuperType();
superType.sayHello(); // -> Hello from SuperType
To override a method in the subclass, the overriding method (i.e. the one in the subclass) MUST HAVE:
same name
same return type in case of primitives (a subclass is allowed for classes, this is also known as covariant return
1. Method name
2. Number of parameters
3. Types of parameters
If these three are same for any two methods in a class, then compiler throws duplicate method error.
This type of polymorphism is called static or compile time polymorphism because the appropriate method to be
called is decided by the compiler during the compile time based on the argument list.
class Polymorph {
System.out.println(poly.add(a, b));
System.out.println(poly.add(a, b, c));
System.out.println(poly.add(d, e));
}
2
6
4.000000
Also if you change the return type of method, we are unable to get it as method overloading.
void methodOverloaded(){
//No argument and No return type
}
int methodOverloaded(){
//No argument and int return type
return 0;
}
The dictionary definition of polymorphism refers to a principle in biology in which an organism or species
can have many different forms or stages. This principle can also be applied to object-oriented
programming and languages like the Java language. Subclasses of a class can define their own unique
behaviors and yet share some of the same functionality of the parent class.
1. Base class provides no implementation and sub-class has to override complete method - (abstract)
2. Base class provides default implementation and sub-class can change the behaviour
3. Sub-class adds extension to base class implementation by calling super.methodName() as first statement
4. Base class defines structure of the algorithm (Template method) and sub-class will override a part of
algorithm
import java.util.HashMap;
public Game(){
player1 = new Player("Player 1");
player2 = new Player("Player 2");
currentPlayer = player1;
initializeGame();
}
/* Type 1: Let subclass define own implementation. Base class defines abstract method to force
sub-classes to define implementation
*/
/* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
protected void logTimeBetweenMoves(Player player){
System.out.println("Base class: Move Duration: player.PlayerActTime -
player.MoveShownTime");
}
/* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by
calling
super.methodName() in first line of the child class method and specific implementation later
*/
protected void logGameStatistics(){
System.out.println("Base class: logGameStatistics:");
}
/* Type 4: Template method: Structure of base class can't be changed but sub-class can some part
of behaviour */
protected void runGame() throws Exception{
System.out.println("Base class: Defining the flow for Game:");
while (runGame) {
/*
1. Set current player
2. Get Player Move
*/
validatePlayerMove(currentPlayer);
logTimeBetweenMoves(currentPlayer);
Thread.sleep(500);
setNextPlayer();
}
logGameStatistics();
}
/* sub-part of the template method, which define child class behaviour */
protected abstract void validatePlayerMove(Player p);
class Player{
String name;
Player(String name){
this.name = name;
}
public String getName(){
return name;
}
}
}catch(Exception err){
err.printStackTrace();
}
}
}
Output:
There are, however, some methods that are not virtual. For example, if the method is declared private or with the
keyword final, then the method is not Virtual.
Consider the following modified example of inheritance with Virtual Methods from this StackOverflow post How do
virtual functions work in C# and Java? :
public class A{
public void hello(){
System.out.println("Hello");
}
}
}
}
}
If we invoke class B and call hello() and boo(), we would get "No" and "Say haha" as the resulting output because B
overrides the same methods from A. Even though the example above is almost exactly the same as method
overriding, it is important to understand that the methods in class A are all, by default, Virtual.
Additionally, we can implement Virtual methods using the abstract keyword. Methods declared with the keyword
"abstract" does not have a method definition, meaning the method's body is not yet implemented. Consider the
example from above again, except the boo() method is declared abstract:
public class A{
public void hello(){
System.out.println("Hello");
}
}
}
If we invoke boo() from B, the output will still be "Say haha" since B inherits the abstract method boo() and makes
boo () output "Say haha".
Check out this great answer that gives a much more complete information about Virtual functions:
new MakeThingsFly().letTheMachinesFly(machines);
}
}
class MakeThingsFly {
public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
for (FlyingMachine flyingMachine : flyingMachines) {
flyingMachine.fly();
}
}
}
class FlyingMachine {
public void fly() {
out.println("No implementation");
}
}
Explanation
a) The MakeThingsFly class can work with everything that is of type FlyingMachine.
b) The method letTheMachinesFly also works without any change (!) when you add a new class, for example
PropellerPlane:
That's the power of polymorphism. You can implement the open-closed-principle with it.
The interface is the exposed functionality of the class. Its public methods and variables are part of the interface.
The implementation is the internal workings of a class. Other classes shouldn't need to know about the
implementation of a class.
Encapsulation refers to the practice of hiding the implementation of a class from any users of that class. This allows
the class to make assumptions about its internal state.
This class relies on a basic assumption (or invariant): angleInDegrees and angleInRadians are always in sync. If
the class members were public, there would be no guarantees that the two representations of angles are
correlated.
For example, let's change the implementation of the Angle class from the previous example:
private Angle(){}
}
The implementation of this class has changed so that it only stores one representation of the angle and calculates
the other angle when needed.
However, the implementation changed, but the interface didn't. If a calling class relied on accessing the
angleInRadians method, it would need to be changed to use the new version of Angle. Calling classes shouldn't care
about the internal representation of a class.
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Starting a java agent will let the agent access the class Instrumentation. With Instrumentation you can call
addTransformer(ClassFileTransformer transformer). ClassFileTransformers will let you rewrite the bytes of classes. The
class has only a single method which supplies the ClassLoader that loads the class, the class's name, a
java.lang.Class instance of it, it's ProtectionDomain, and lastly the bytes of the class itself.
Modifying a class purely from bytes can take ages. To remedy this there are libraries that can be used to convert
the class bytes into something more usable.
In this example I'll be using ASM, but other alternatives like Javassist and BCEL have similar features.
From here changes can be made to the ClassNode object. This makes changing field/method access incredibly easy.
Plus with ASM's Tree API modifying the bytecode of methods is a breeze.
Once the edits are finished you can convert the ClassNode back into bytes with the following method and return
them in the transform method:
This will not call premain((String agentArgs, Instrumentation inst) in the loaded agent, but instead will call
agentmain(String agentArgs, Instrumentation inst). This requires Agent-Class to be set in the agent Manifest.mf.
Here is an example:
import java.lang.instrument.Instrumentation;
When compiled into a jar file open the Manifest and ensure that it has the Premain-Class attribute.
Here is an example:
Premain-Class: PremainExample
To use the agent with another java program "myProgram" you must define the agent in the JVM arguments:
This example shows both an array and a sequence of arguments being passed into the printVarArgArray()
method, and how they are treated identically in the code inside the method:
// this method will print the entire contents of the parameter passed in
void printVarArgArray(int... x) {
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + ",");
}
}
//Using an array:
int[] testArray = new int[]{10, 20};
obj.printVarArgArray(testArray);
System.out.println(" ");
Output:
10,20,
5,6,5,8,6,31
If you define the method like this, it will give compile-time errors.
void method(String... a, int... b , int c){} //Compile time error (multiple varargs )
void method(int... a, String b){} //Compile time error (varargs must be the last argument
The three periods after the final parameter's type indicate that the final argument may be passed as an array or as
a sequence of arguments. Varargs can be used only in the final argument position.
The above example looks perfectly fine, but many programmers forgets that Java VM is stack machine. This means
that all method's parameters are calculated before executing the method.
This fact is crucial for logging in Java, especially for logging something in low levels like FINE, FINER, FINEST which
are disabled by default. Let's look at Java bytecode for the takeOrder() method.
Line 39 runs the actual logging. All of the previous work (loading variables, creating new objects, concatenating
Strings in format method) can be for nothing if logging level is set higher then FINE (and by default it is). Such
logging can be very inefficient, consuming unnecessary memory and processor resources.
That's why you should ask if the level you want to use is enabled.
Since Java 8:
The Logger class has additional methods that take a Supplier<String> as parameter, which can simply be provided
by a lambda:
The Suppliers get()method - in this case the lambda - is only called when the corresponding level is enabled and so
the ifconstruction is not needed anymore.
import java.util.logging.Level;
import java.util.logging.Logger;
// logging an exception
try {
// code might throw an exception
} catch (SomeException ex) {
// log a warning printing "Something went wrong"
// logging an object
LOG.log(Level.FINER, "String s: {0}", s);
The default level is INFO (but this depends on the system and used a virtual machine).
Note: There are also levels OFF (can be used to turn logging off) and ALL (the oposite of OFF).
import java.util.logging.Logger;
By default running this class will output only messages with level higher then CONFIG:
Even though this example is DB2 specific, it works for almost every other system if you exchange the driver and
adapt the JDBC URL.
Using Maven:
Add the following dependency to your POM.xml file:
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
<dependencies>
<dependency org="org.apache.logging.log4j" name="log4j-api" rev="2.6.2" />
<dependency org="org.apache.logging.log4j" name="log4j-core" rev="2.6.2" />
</dependencies>
Using Gradle:
dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.2'
}
Using Maven:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Using Ivy:
Usign Gradle:
Using Buildr:
'log4j:log4j:jar:1.2.17'
/ProjectFolder/src/java/resources
This is a basic log4j2.xml configuration which has a console appender and a root logger. The pattern layout
specifies which pattern should be used for logging the statements.
In order to debug the loading of log4j2.xml you can add the attribute status = <WARN | DEBUG | ERROR | FATAL |
TRACE | INFO> in the configuration tag of your log4j2.xml.
You can also add a monitor interval so that it loads the configuration again after the specified interval period. The
monitor interval can be added to the configuration tag as follows: monitorInterval = 30. It means that the config
will be loaded every 30 seconds.
//logs an exception
logger.error("Information about some error: ", exception);
Maven Build
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
Ivy Build
<dependencies>
<dependency org="org.apache.logging.log4j" name="log4j-1.2-api" rev="2.6.2" />
</dependencies>
Gradle Build
dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-1.2-api', version: '2.6.2'
}
Apache Commons Logging Bridge If your project is using Apache Commons Logging which use log4j 1.x and you
want to migrate it to log4j 2.x then add the following dependencies:
Maven Build
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
Ivy Build
<dependencies>
<dependency org="org.apache.logging.log4j" name="log4j-jcl" rev="2.6.2" />
</dependencies>
Gradle Build
Reference: https://logging.apache.org/log4j/2.x/maven-artifacts.html
Or "Level range"
Package names should be all lower case without underscores or other special characters.
Package names begin with the reversed authority part of the web address of the company of the developer.
This part can be followed a by project/program structure dependent package substructure.
Don’t use plural form. Follow the convention of the standard API which uses for instance
java.lang.annotation and not java.lang.annotations.
Examples: com.yourcompany.widget.button, com.yourcompany.core.api
Method Names
Variables
Variable names should be in mixed case with the first letter in lower case
Type Variables
For simple cases where there are few type variables involved use a single upper case letter.
Constants
Constants (static final fields whose content is immutable, by language rules or by convention) should be named
with all capital letters and underscore (_) to separate words.
Ordering fields and methods primarily by their access modifiers or identifier is not required.
class Example {
private int i;
Example(int i) {
this.i = i;
}
@Override
public String toString() {
return "An example [" + i + "]";
}
@SuppressWarnings("unchecked")
public T[] toArray(T[] typeHolder) {
...
}
However, few or short annotations annotating a single-line method may be put on the same line as the method if it
improves readability. For example, one may write:
For a matter of consistency and readability, either all annotations should be put on the same line or each
annotation should be put on a separate line.
// Bad.
@Deprecated @SafeVarargs
@CustomAnnotation
public final Tuple<T> extend(T... elements) {
...
}
// Even worse.
@Deprecated @SafeVarargs
@CustomAnnotation public final Tuple<T> extend(T... elements) {
...
}
// Good.
@Deprecated
@SafeVarargs
@CustomAnnotation
public final Tuple<T> extend(T... elements) {
...
}
// Good.
@Deprecated @SafeVarargs @CustomAnnotation
public final Tuple<T> extend(T... elements) {
...
}
Import statements should not be line wrapped, regardless of whether it exceeds the recommended
maximum length of a line.
Wildcard imports
Opening braces should be put on the end of the current line rather than on a line by its own.
There should be a new line in front of a closing brace unless the block is empty (see Short Forms below)
Braces are recommended even where the language makes them optional, such as single-line if and loop
bodies.
If a block spans more than one line (including comments) it must have braces.
If one of the blocks in a if / else statement has braces, the other block must too.
If the block comes last in an enclosing block, it must have braces.
The else, catch and the while keyword in do…while loops go on the same line as the closing brace of the
Short forms
enum Response { YES, NO, MAYBE }
public boolean isReference() { return true; }
The above recommendations are intended to improve uniformity (and thus increase familiarity / readability). In
some cases “short forms” that deviate from the above guidelines are just as readable and may be used instead.
These cases include for instance simple enum declarations and trivial methods and lambda expressions.
// Don't do this
return (flag ? "yes" : "no");
Redundant grouping parentheses (i.e. parentheses that does not affect evaluation) may be used if they
improve readability.
Redundant grouping parentheses should typically be left out in shorter expressions involving common
operators but included in longer expressions or expressions involving operators whose precedence and
associativity is unclear without parentheses. Ternary expressions with non-trivial conditions belong to the
latter.
The entire expression following a return keyword must not be surrounded by parentheses.
interface ExampleInterface {
// Avoid 'public' and 'abstract' since they are implicit
void sayHello();
}
Method parameters and local variables should not be declared final unless it improves readability or
documents an actual design decision.
Fields should be declared final unless there is a compelling reason to make them mutable.
switch (var) {
case TWO:
setChoice("two");
break;
case THREE:
setChoice("three");
break;
default:
throw new IllegalArgumentException();
}
The package declaration should not be line wrapped, regardless of whether it exceeds the recommended
maximum length of a line.
The name of a source file must equal the name of the class it contains followed by the .java extension, even
for files that only contain a package private class. This does not apply to files that do not contain any class
declarations, such as package-info.java.
The character limit must be judged on a case by case basis. What really matters is the semantical “density”
and readability of the line. Making lines gratuitously long makes them hard to read; similarly, making “heroic
attempts” to fit them into 80 columns can also make them hard to read. The flexibility outlined here aims to
enable developers to avoid these extremes, not to maximize use of monitor real-estate.
// Wrapping preferable
String pretty = Stream.of(args)
.map(Argument::prettyPrint)
.collectors(joining(", "));
Wrapping at a higher syntactical level is preferred over wrapping at a lower syntactical level.
Variant 1: With 8 extra spaces relative to the indentation of the previous line.
Variant 2: With 8 extra spaces relative to the starting column of the wrapped expression.
Variant 3: Aligned with previous sibling expression (as long as it is clear that it’s a continuation line)
Variant 4: Aligned with previous method call in a chained expression.
Method declarations can be formatted by listing the arguments vertically, or by a new line and +8 extra
spaces
If a throws clause needs to be wrapped, put the line break in front of the throws clause and make sure it
stands out from the argument list, either by indenting +8 relative to the function declaration, or +8 relative to
the previous line.
Package declaration
Class declarations
Constructors
Methods
Static initializers
Instance initializers
import statements
fields
statements
Multiple consecutive blank lines should only be used to separate groups of related members and not as the
standard inter-member spacing.
Horizontal Whitespace
\', \", \\, \t, \b, \r, \f, and \n should be preferred over corresponding octal (e.g. \047) or Unicode (e.g.
\u0027) escaped characters.
Should there be a need to go against the above rules for the sake of testing, the test should generate the
required input programatically.
String line;
while ((line = reader.readLine()) != null) {
System.out.print(line);
}
}
System.out.println(Arrays.toString(textInUtf8));
}
}
@Override
public boolean equals(Object obj) {
return builder.isEquals();
}
Using reflection:
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj, false);
}
the boolean parameter is to indicates if the equals should check transient fields.
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj, "field1", "field2");
}
@Override
public int hashCode() {
return builder.hashCode();
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, false);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, "field1", "field2");
}
@Override
public String toString() {
return builder.toString();
}
Example result:
ar.com.jonat.lang.MyClass@dd7123[<null>,0,false]
@Override
public String toString() {
return builder.toString();
}
Example result:
ar.com.jonat.lang.MyClass@dd7404[field1=<null>,field2=0,field3=false]
@Override
return builder.toString();
}
Example result:
ar.com.bna.lang.MyClass@ebbf5c[
field1=<null>
field2=0
field3=false
]
There are some styles, for example JSON, no Classname, short, etc ...
Via reflection:
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
The Locale instance is handed to components that need to localize their actions, whether it is converting the input,
output, or just need it for internal operations. The Locale class cannot do any internationalization or localization by
itself
Language
The language must be an ISO 639 2 or 3 character language code, or a registered language subtag of up to 8
characters. In case a language has both a 2 and 3 character language code, use the 2 character code. A full list of
language codes can be found in the IANA Language Subtag Registry.
Language codes are case insensitive, but the Locale class always use lowercase versions of the language codes
Creating a Locale
Locale constants
Locale constructors
Locale.Builder class
Locale.forLanguageTag factory method
Java ResourceBundle
message=This is locale
Output:
This is locale
Setting Locale
If you want to reproduce the state using other languages, you can use setDefault() method. Its usage:
If you hard-code "MM/dd/yyyy" all over your application your international users won't be happy.
Use the static methods in DateFormat to retrieve the right formatting for your user. For a desktop application
(where you'll rely on the default locale), simply call:
Where style is one of the formatting constants (FULL, LONG, MEDIUM, SHORT, etc.) specified in DateFormat.
For a server-side application where the user specifies their locale as part of the request, you should pass it explicitly
to getDateInstance() instead:
String localizedDate =
DateFormat.getDateInstance(style, request.getLocale()).format(date);
"School".equalsIgnoreCase("school"); // true
Don't use
text1.toLowerCase().equals(text2.toLowerCase());
Languages have different rules for converting upper and lower case. A 'I' would be converted to 'i' in English. But in
Turkish a 'I' becomes a '?'. If you have to use toLowerCase() use the overload which expects a Locale:
String.toLowerCase(Locale).
Sort Strings respecting natural language order, ignoring case (use collation key to:
A ForkJoinTask is the interface that defines such a problem. It is generally expected that you will subclass one of its
abstract implementations (usually the RecursiveTask) rather than implement the interface directly.
In this example, we are going to sum a collection of integers, dividing until we get to batch sizes of no more than
ten.
import java.util.List;
import java.util.concurrent.RecursiveTask;
@Override
public Integer compute() {
if (maxExclusive - minInclusive > MAX_BATCH_SIZE) {
// This is too big for a single batch, so we shall divide into two tasks
int mid = (minInclusive + maxExclusive) / 2;
SummingTask leftTask = new SummingTask(numbers, minInclusive, mid);
SummingTask rightTask = new SummingTask(numbers, mid, maxExclusive);
// Submit the left hand task as a new task to the same ForkJoinPool
leftTask.fork();
// Run the right hand task on the same thread and get the result
int rightResult = rightTask.compute();
// Wait for the left hand task to complete and get its result
int leftResult = leftTask.join();
// Submit the task to the pool, and get what is effectively the Future
ForkJoinTask<Integer> task = pool.submit(new SummingTask(numbers));
Usages
Some developer consider it good practice to mark a variable final when you can. If you have a variable that should
not be changed, you should mark it final.
An important use of final keyword if for method parameters. If you want to emphasize that a method doesn't
change its input parameters, mark the properties as final.
This emphasizes that the sumup method is not going to change the ints.
If your anonymous inner class wants to access a variable, the variable should be marked final
Version ≥ Java SE 8
Effectively final variables are an exception. These are local variables that are written to only once and could
therefore be made final. Effectively final variables can be accessed from anonymus classes too.
Even though the code below is completely legal when final variable foo is not static, in case of static it will not
compile:
class TestFinal {
private final static List foo;
The reason is, let's repeat again, final variable cannot be reassigned. Since foo is static, it is shared among all
instances of class TestFinal. When a new instance of a class TestFinal is created, its constructor is invoked and
therefore foo gets reassigned which compiler does not allow. A correct way to initialize variable foo in this case is
either:
class TestFinal {
private static final List foo = new ArrayList();
//..
}
class TestFinal {
private static final List foo;
static {
foo = new ArrayList();
}
//..
}
final methods are useful when base class implements some important functionality that derived class is not
supposed to change it. They are also faster than non-final methods, because there is no concept of virtual table
involved.
All wrapper classes in Java are final, such as Integer, Long etc. Creators of these classes didn't want that anyone
can e.g. extend Integer into his own class and change the basic behavior of Integer class. One of the requirements
to make a class immutable is that subclasses may not override methods. The simplest way to do this is to declare
the class as final.
Static fields are common to all instances of a class. They do not need an instance to access them.
Static methods can be run without an instance of the class they are in. However, they can only access static
fields of that class.
Static classes can be declared inside of other classes. They do not need an instance of the class they are in to
be instantiated.
static {
// This block of code is run when the class first loads
staticVariable = 11;
}
int nonStaticVariable = 5;
void add() {
// We can access both static and non-static variables from non-static methods
nonStaticVariable += staticVariable;
}
void doSomething() {
// We can access number and staticVariable, but not nonStaticVariable
number += staticVariable;
}
int getNumber() {
return number;
}
}
}
System.out.println(object1.staticVariable); // 11
System.out.println(TestStatic.staticVariable); // 11
TestStatic.doSomething();
System.out.println(object1.staticVariable); // 10
System.out.println(object2.staticVariable); // 10
System.out.println(TestStatic.staticVariable); // 10
object1.add();
System.out.println(object1.nonStaticVariable); // 15
System.out.println(object2.nonStaticVariable); // 10
System.out.println(object3.getNumber()); // 100
System.out.println(object4.getNumber()); // 200
object3.doSomething();
System.out.println(object3.getNumber()); // 110
System.out.println(object4.getNumber()); // 200
strictfp modifier is used for floating-point calculations. This modifier makes floating point variable more consistent
across multiple platforms and ensure all the floating point calculations are done according to IEEE 754 standards to
avoid errors of calculation (round-off errors), overflows and underflows on both 32bit and 64bit architecture. This
cannot be applied on abstract methods, variables or constructors.
class A{
strictfp void m(){}
}
class Shared
{
int i;
void SharedMethod2()
{
synchronized (this)
{
System.out.println("Thais access to currect object is synchronize "+this);
}
}
}
t1.start();
t2.start();
}
}
Spaces in pathnames
Suppose that we generalize the example above so that we can create an arbitrary directory:
This will typically work, but it will fail if dirPath is (for example) "/home/user/My Documents". The problem is that
exec(String) splits the string into a command and arguments by simply looking for whitespace. The command
string:
and this will cause the "mkdir" command to fail because it expects one argument, not two.
Faced with this, some programmers try to add quotes around the pathname. This doesn't work either:
The extra double-quote characters that were added in attempt to "quote" the spaces are treated like any other non-
whitespace characters. Indeed, anything we do quote or escape the spaces is going to fail.
The way to deal with this particular problems is to use the exec(String ...) overload.
This will work if dirpath includes whitespace characters because this overload of exec does not attempt to split the
Suppose that we want to redirect an external command's input or output, or run a pipeline. For example:
or
(The first example lists the names of all Java files in the file system, and the second one prints the package
statements2 in the Java files in the "source" tree.)
These are not going to work as expected. In the first case, the "find" command will be run with "2>/dev/null" as a
command argument. It will not be interpreted as a redirection. In the second example, the pipe character ("|") and
the works following it will be given to the "find" command.
The problem here is that the exec methods and ProcessBuilder do not understand any shell syntax. This includes
redirections, pipelines, variable expansion, globbing, and so on.
In a few cases (for example, simple redirection) you can easily achieve the desired effect using ProcessBuilder.
However, this is not true in general. An alternative approach is to run the command line in a shell; for example:
or
But note that in the second example, we needed to escape the wildcard character ("*") because we want the
wildcard to be interpreted by "find" rather than the shell.
Suppose the following examples won't work on a system with a UNIX-like shell:
or
1. On "cd" and "export" commands are shell builtin commands. They don't exist as distinct executables.
2. For shell builtins to do what they are supposed to do (e.g. change the working directory, update the
environment), they need to change the place where that state resides. For a normal application (including a
Java application) the state is associated with the application process. So for example, the child process that
would run the "cd" command could not change the working directory of its parent "java" process. Similarly,
1 - You can use ProcessBuilder as well, but that is not relevant to the point of this example.
2 - This is a bit rough and ready ... but once again, the failings of this approach are not relevant to the example.
package process.example;
import java.io.IOException;
System.out.println(exitCode);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Java Native Access (JNA) is a community-developed library providing Java programs an easy access to native shared
libraries (.dll files on windows, .so files on Unix ...)
Firstly, download the latest release of JNA and reference its jna.jar in your project's CLASSPATH.
For the purpose of this introduction, we suppose the native platform in use is Windows. If you're running on
another platform simply replace the string "msvcrt" with the string "c" in the code below.
The small Java program below will print a message on the console by calling the C printf function.
CRuntimeLibrary.java
package jna.introduction;
import com.sun.jna.Library;
import com.sun.jna.Native;
// We declare the printf function we need and the library containing it (msvcrt)...
public interface CRuntimeLibrary extends Library {
CRuntimeLibrary INSTANCE =
(CRuntimeLibrary) Native.loadLibrary("msvcrt", CRuntimeLibrary.class);
MyFirstJNAProgram.java
package jna.introduction;
Where to go now?
|-- module-info.java
|-- com
|-- example
|-- foo
|-- Foo.java
|-- bar
|-- Bar.java
module com.example {
requires java.httpclient;
exports com.example.foo;
}
The module name should be unique and it is recommended that you use the same Reverse-DNS naming notation
as used by packages to help ensure this.
The module java.base, which contains Java's basic classes, is implicitly visible to any module and does not need to
be included.
The requires declaration allows us to use other modules, in the example the module java.httpclient is imported.
A module can also specify which packages it exports and therefore makes it visible to other modules.
The package com.example.foo declared in the exports clause will be visible to other modules. Any sub-packages of
com.example.foo will not be exported, they need their own export declarations.
Conversely, com.example.bar which is not listed in exports clauses will not be visible to other modules.
Callable was introduced in Java 5 as a peer to Runnable. Callable is essentially the same except it has a call
method instead of run. The call method has the additional capability to return a result and is also allowed to throw
checked exceptions.
The result from a Callable task submission is available to be tapped via a Future
Future can be considered a container of sorts that houses the result of the Callable computation. Computation of
the callable can carry on in another thread, and any attempt to tap the result of a Future will block and will only
return the result once it is available.
Callable Interface
Future
interface Future<V> {
V get();
V get(long timeout, TimeUnit unit);
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
}
@Override
public String call() throws Exception {
// just sleep for 10 secs to simulate a lengthy computation
Thread.sleep(10000);
System.out.println("Result after a lengthy 10sec calculation");
return "Complex Result"; // the result
}
}
Output
While get() is the method to extract the actual result Future has provision
get(long timeout, TimeUnit unit) defines maximum time period during current thread will wait for a
result;
To cancel the task call cancel(mayInterruptIfRunning). The flag mayInterrupt indicates that task should be
interrupted if it was started and is running right now;
To check if task is completed/finished by calling isDone();
To check if the lengthy task were cancelled isCancelled().
A synchronization aid that allows one or more threads to wait until a set of operations being performed
in other threads completes.
Key Methods:
Causes the current thread to wait until the latch has counted down to zero, unless the thread is
interrupted.
Example:
import java.util.concurrent.*;
}
CountDownLatch latch = new CountDownLatch(numberOfThreads);
for (int n = 0; n < numberOfThreads; n++) {
Thread t = new Thread(new DoSomethingInAThread(latch));
t.start();
}
latch.await();
System.out.println("In Main thread after completion of " + numberOfThreads + "
threads");
} catch(Exception err) {
err.printStackTrace();
}
}
}
output:
java CountDownLatchDemo 5
Do some thing
Do some thing
Do some thing
Do some thing
Do some thing
In Main thread after completion of 5 threads
Explanation:
CountAndPrint(String name) {
this.name = name;
}
The code of the run method of the various CountAndPrint instances will execute in non predictable order. A snippet
of a sample execution might look like this:
Instance 4: 1
Instance 2: 1
Instance 4: 2
Instance 1: 1
Instance 1: 2
Main: 1
Instance 4: 3
Main: 2
Instance 3: 1
Instance 4: 4
...
Locks are thread synchronisation mechanisms that essentially serve the same purpose as synchronized blocks or
key words.
Intrinsic Locking
Locks also have functionality available that intrinsic locking does not offer, such as locking but remaining responsive
to interruption, or trying to lock, and not block when unable to.
class Locky {
int count = 0; // shared among multiple threads
There are several variants of lock available.For more details refer the api docs here
Semaphore semaphore = new Semaphore(1); // The int value being the number of permits
The Semaphore constructor accepts an additional boolean parameter for fairness. When set false, this class makes
no guarantees about the order in which threads acquire permits. When fairness is set true, the semaphore
guarantees that threads invoking any of the acquire methods are selected to obtain permits in the order in which
their invocation of those methods was processed. It is declared in the following manner:
Now let's look at an example from javadocs, where Semaphore is used to control access to a pool of items. A
Semaphore is used in this example to provide blocking functionality in order to ensure that there are always items
to be obtained when getItem() is called.
class Pool {
/*
* Note that this DOES NOT bound the amount that may be released!
* This is only a starting value for the Semaphore and has no other
* significant meaning UNLESS you enforce this inside of the
* getNextAvailableItem() and markAsUnused() methods
*/
private static final int MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
/**
* Obtains the next available item and reduces the permit count by 1.
* If there are no items available, block.
*/
public Object getItem() throws InterruptedException {
/**
* Puts the item into the pool and add 1 permit.
*/
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
Intrinsic locks provide atomicity to groups of statements. To understand what that means for us, let's have a look at
an example where synchronized is useful:
In this case, if it weren't for the synchronized block, there would have been multiple concurrency issues involved.
The first one would be with the post increment operator (it isn't atomic in itself), and the second would be that we
would be observing the value of t after an arbitrary amount of other threads has had the chance to modify it.
However, since we acquired an intrinsic lock, there will be no race conditions here and the output will contain
numbers from 1 to 100 in their normal order.
Intrinsic locks in Java are mutexes (i.e. mutual execution locks). Mutual execution means that if one thread has
acquired the lock, the second will be forced to wait for the first one to release it before it can acquire the lock for
itself. Note: An operation that may put the thread into the wait (sleep) state is called a blocking operation. Thus,
acquiring a lock is a blocking operation.
Intrinsic locks in Java are reentrant. This means that if a thread attempts to acquire a lock it already owns, it will not
The following blocks of code are practically equivalent (even though the bytecode seems to be different):
2. synchronized method:
class MyClass {
...
public static void bar() {
synchronized(MyClass.class) {
doSomeOtherStuff();
}
}
}
class MyClass {
...
public static synchronized void bar() {
doSomeOtherStuff();
}
}
The Runnable object is passed to the Thread constructor. And Thread's start() method is called.
@Override
public void run() {
System.out.println("Hello from a thread");
}
Example in Java8:
A Runnable object employment is more general, because the Runnable object can subclass a class other than
Thread.
Thread subclassing is easier to use in simple applications, but is limited by the fact that your task class must be a
descendant of Thread.
Consider there are 2 threads working on 1 instance, Lets call threads as First and Second, and lets say we have 2
resources R1 and R2. First acquires R1 and also needs R2 for its completion while Second acquires R2 and needs R1
for completion.
First has R1 and Second has R2. now First is waiting for R2 while Second is waiting for R1. this wait is indefinite and
this leads to deadlock.
@Override
public void run() {
// TODO Auto-generated method stub
dl.methodA();
@Override
public void run() {
// TODO Auto-generated method stub
try {
dl.method2();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.setName("First");
t2.setName("Second");
t1.start();
t2.start();
}
}
class DeadLock {
In Java, a thread is represented by an object - an instance of java.lang.Thread or its subclass. So the first approach is
to create that subclass and override the run() method.
Note: I'll use Thread to refer to the java.lang.Thread class and thread to refer to the logical concept of threads.
Now since we've already defined the code to be executed, the thread can be created simply as:
The Thread class also contains a constructor accepting a string, which will be used as the thread's name. This can
be particulary useful when debugging a multi thread program.
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Thread running! ");
}
}
}
The second approach is to define the code using java.lang.Runnable and its only method run(). The Thread class
then allows you to execute that method in a separated thread. To achieve this, create the thread using a
constructor accepting an instance of the Runnable interface.
This can be very powerful when combined with lambdas or methods references (Java 8 only):
Practicaly speaking, you can use both approaches without worries. However the general wisdom says to use the
latter.
For every of the four mentioned constructors, there is also an alternative accepting an instance of
java.lang.ThreadGroup as the first parameter.
The ThreadGroup represents a set of threads. You can only add a Thread to a ThreadGroup using a Thread's
constructor. The ThreadGroup can then be used to manage all its Threads together, as well as the Thread can gain
information from its ThreadGroup.
So to sumarize, the Thread can be created with one of these public constructors:
Thread()
Thread(String name)
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
The last one allows us to define desired stack size for the new thread.
Often the code readability suffers when creating and configuring many Threads with same properties or from the
same pattern. That's when java.util.concurrent.ThreadFactory can be used. This interface allows you to encapsulate
the procedure of creating the thread through the factory pattern and its only method newThread(Runnable).
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "Worker " + id++);
}
}
In this case, there are two issues. The first issue is that the post increment operator is not atomic. It is comprised of
multiple operations: get the value, add 1 to the value, set the value. That's why if we run the example, it is likely that
we won't see t: 100 in the output - two threads may concurrently get the value, increment it, and set it: let's say the
value of t is 10, and two threads are incrementing t. Both threads will set the value of t to 11, since the second
thread observes the value of t before the first thread had finished incrementing it.
The second issue is with how we are observing t. When we are printing the value of t, the value may have already
been changed by a different thread after this thread's increment operation.
To fix those issues, we'll use the java.util.concurrent.atomic.AtomicInteger, which has many atomic
operations for us to use.
The incrementAndGet method of AtomicInteger atomically increments and returns the new value, thus eliminating
the previous race condition. Please note that in this example the lines will still be out of order because we make no
effort to sequence the println calls and that this falls outside the scope of this example, since it would require
synchronization and the goal of this example is to show how to use AtomicInteger to eliminate race conditions
concerning state.
The ReadWriteLock interface, and its ReentrantReadWriteLock implementation allows for an access pattern that
can be described as follow :
1. There can be any number of concurrent readers of the data. If there is at least one reader access granted,
then no writer access is possible.
2. There can be at most one single writer to the data. If there is a writer access granted, then no reader can
access the data.
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
// Our lock. The constructor allows a "fairness" setting, which guarantees the chronology of lock
attributions.
protected static final ReadWriteLock RW_LOCK = new ReentrantReadWriteLock();
NOTE 1 : This precise use case has a cleaner solution using AtomicInteger, but what is described here is an access
pattern, that works regardless of the fact that data here is an integer that as an Atomic variant.
NOTE 2 : The lock on the reading part is really needed, although it might not look so to the casual reader. Indeed, if
you do not lock on the reader side, any number of things can go wrong, amongst which :
1. The writes of primitive values are not guaranteed to be atomic on all JVMs, so the reader could see e.g. only
32bits of a 64bits write if data were a 64bits long type
2. The visibility of the write from a thread that did not perform it is guaranteed by the JVM only if we establish
Happen Before relationship between the writes and the reads. This relationship is established when both
readers and writers use their respective locks, but not otherwise
Version ≥ Java SE 8
In case higher performance is required, an under certain types of usage, there is a faster lock type available, called
the StampedLock, that amongst other things implements an optimistic lock mode. This lock works very differently
from the ReadWriteLock, and this sample is not transposable.
producer.start();
consumer.start();
Thread.sleep(1000);
producer.interrupt();
Thread.sleep(10);
consumer.interrupt();
}
}
class Counter {
Let's suppose a thread A calls incrementCount() first then another thread B calls getCount(). In this scenario there
is no guarantee that B will see updated value of count. It may still see count as 10, even it is also possible that it
never sees updated value of count ever.
To understand this behavior we need to understand how Java memory model integrates with hardware
architecture. In Java, each thread has it's own thread stack. This stack contains: method call stack and local variable
created in that thread. In a multi core system, it is quite possible that two threads are running concurrently in
separate cores. In such scenario it is possible that part of a thread's stack lies inside register / cache of a core. If
inside a thread, an object is accessed using synchronized (or volatile) keyword, after synchronized block that
thread syncs it's local copy of that variable with the main memory. This creates a read / write barrier and makes
sure that the thread is seeing the latest value of that object.
But in our case, since thread B has not used synchronized access to count, it might be refering value of count
stored in register and may never see updates from thread A. To make sure that B sees latest value of count we
need to make getCount() synchronized as well.
Now when thread A is done with updating count it unlocks Counter instance, at the same time creates write barrier
and flushes all changes done inside that block to the main memory. Similarly when thread B acquires lock on the
same instance of Counter, it enters into read barrier and reads value of count from main memory and sees all
Same visibility effect goes for volatile read / writes as well. All variables updated prior to write to volatile will be
flushed to main memory and all reads after volatile variable read will be from main memory.
import java.util.Set;
Output:
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:3,5,main]:state:TIMED_WAITING
Thread :Thread[main,5,main]:state:RUNNABLE
Thread :Thread[MyThread:4,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread count started by Main thread:6
Explanation:
Thread.getAllStackTraces().keySet() returns all Threads including application threads and system threads. If
you are interested only in status of Threads, started by your application, iterate the Thread set by checking Thread
Group of a particular thread against your main program thread.
In absence of above ThreadGroup condition, the program returns status of below System Threads:
Reference Handler
Signal Dispatcher
Attach Listener
Finalizer
For example, this is frequently used to establish the context (such as authorization information) of handling a
request in a servlet. You might do something like this:
Now, instead of passing MyUserContext into every single method, you can instead use MyServlet.getContext()
where you need it. Now of course, this does introduce a variable that needs to be documented, but it’s thread-safe,
The key advantage here is that every thread has its own thread local variable in that contexts container. As long as
you use it from a defined entry point (like demanding that each servlet maintains its context, or perhaps by adding
a servlet filter) you can rely on this context being there when you need it.
import java.util.concurrent.*;
import java.util.Random;
pes.shutdown();
ces.shutdown();
}
}
output:
Produced:69:by thread:2
Produced:553:by thread:1
Consumed: 69:by thread:1
Consumed: 553:by thread:2
Produced:41:by thread:2
Produced:796:by thread:1
Consumed: 41:by thread:1
Consumed: 796:by thread:2
Produced:728:by thread:2
Consumed: 728:by thread:1
and so on ................
Explanation:
1. sharedQueue, which is a LinkedBlockingQueue is shared among all Producer and Consumer threads.
2. Producer threads produces one integer for every 200 milli seconds continuously and append it to
sharedQueue
3. Consumer thread consumes integer from sharedQueue continuously.
4. This program is implemented with-out explicit synchronized or Lock constructs. BlockingQueue is the key to
achieve it.
BlockingQueue implementations are thread-safe. All queuing methods achieve their effects atomically
using internal locks or other forms of concurrency control.
Version ≥ Java SE 8
int[] firstArray = { 2, 4, 6, 8 };
int[] secondArray = { 1, 3, 5, 7 };
int[] result = { 0, 0, 0, 0 };
System.out.println(Arrays.toString(result));
Notes:
1. This example is purely illustrative. In practice, there won't be any speedup by using threads for a task this
small. A slowdown is likely, since the overheads of task creation and scheduling will swamp the time taken to
run a task.
2. If you were using Java 7 and earlier, you would use anonymous classes instead of lambdas to implement the
tasks.
Thread.sleep(1000);
It is important to note that this is a hint to the operating system's kernel's scheduler. This may not necessarily be
Other than these mechanics, Java does not assign any special semantic meaning to interruption. Code is free to
interpret an interrupt any way it likes. But most often interruption is used to signal to a thread it should stop
running at its earliest convenience. But, as should be clear from the above, it is up to the code on that thread to
react to that interruption appropriately in order to stop running. Stopping a thread is a collaboration. When a
thread is interrupted its running code can be several levels deep into the stacktrace. Most code doesn't call a
blocking method, and finishes timely enough to not delay the stopping of the thread unduly. The code that should
mostly be concerned with being responsive to interruption, is code that is in a loop handling tasks until there are
none left, or until a flag is set signalling it to stop that loop. Loops that handle possibly infinite tasks (i.e. they keep
running in principle) should check the interrupt flag in order to exit the loop. For finite loops the semantics may
dictate that all tasks must be finished before ending, or it may be appropriate to leave some tasks unhandled. Code
that calls blocking methods will be forced to deal with the InterruptedException. If at all semantically possible, it can
simply propagate the InterruptedException and declare to throw it. As such it becomes a blocking method itself in
regard to its callers. If it cannot propagate the exception, it should at the very least set the interrupted flag, so
callers higher up the stack also know the thread was interrupted. In some cases the method needs to continue
waiting regardless of the InterruptedException, in which case it must delay setting the interrupted flag until after it
is done waiting, this may involve setting a local variable, which is to be checked prior to exiting the method to then
interrupt its thread.
Examples :
TaskHandler(BlockingQueue<Task> queue) {
this.queue = queue;
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) { // check for interrupt flag, exit loop
Example of code that delays setting the interrupt flag until completely done :
MustFinishHandler(BlockingQueue<Task> queue) {
this.queue = queue;
}
@Override
public void run() {
boolean shouldInterrupt = false;
while (true) {
try {
Task task = queue.take();
if (task.isEndOfTasks()) {
if (shouldInterrupt) {
Thread.currentThread().interrupt();
}
return;
}
handle(task);
} catch (InterruptedException e) {
shouldInterrupt = true; // must finish, remember to set interrupt flag when we're
done
}
}
}
Example of code that has a fixed list of tasks but may quit early when interrupted
@Override
public void run() {
for (Task task : tasks) {
pool.execute(new Runnable() {
@Override public void run() {
//code to run
}
});
Note If you configure the ThreadPoolExecutor with an unbounded queue, then the thread count will not exceed
corePoolSize since new threads are only created if the queue is full:
from JavaDoc
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will
be created only if the queue is full.
Advantages:
1. BlockingQueue size can be controlled and out-of-memory scenarios can be avoided. Application
performance won't be degraded with limited bounded queue size.
2. In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This
provides a simple feedback control mechanism that will slow down the rate that new tasks are
submitted.
4. In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down, the task at the head
of the work queue is dropped, and then execution is retried (which can fail again, causing this to be
repeated.)
The Service will return a Future which you can use to retrieve the result of the task execution.
When you need to get the result of the future, call future.get()
try {
// Blocks current thread until future is completed
Integer result = future.get();
catch (InterruptedException || ExecutionException e) {
// handle appropriately
}
try {
// Blocks current thread for a maximum of 500 milliseconds.
// If the future finishes before that, result is returned,
// otherwise TimeoutException is thrown.
Integer result = future.get(500, TimeUnit.MILLISECONDS);
catch (InterruptedException || ExecutionException || TimeoutException e) {
If the result of a scheduled or running task is no longer required, you can call Future.cancel(boolean) to cancel it.
Calling cancel(false) will just remove the task from the queue of tasks to be run.
Calling cancel(true) will also interrupt the task if it is currently running.
We should be aware of key difference of Exception Handling mechanisms between these two commands.
Exceptions from submit() are swallowed by framework if you did not catch them.
Case 1: submit the Runnable with execute() command, which reports the Exception.
import java.util.concurrent.*;
import java.util.*;
public ExtendedExecutor() {
super(1, 1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100));
}
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
output:
creating service
a and b=4:0
a and b=4:0
Exception in thread "pool-1-thread-1" Exception in thread "pool-1-thread-2"
java.lang.ArithmeticException: / by zero
at ExecuteSubmitDemo$1.run(ExecuteSubmitDemo.java:15)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
java.lang.ArithmeticException: / by zero
at ExecuteSubmitDemo$1.run(ExecuteSubmitDemo.java:15)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Case 2: Replace execute() with submit() : service.submit(new Runnable(){ In this case, Exceptions are
swallowed by framework since run() method did not catch them explicitly.
output:
creating service
a and b=4:0
a and b=4:0
output:
creating service
a and b=4:0
java.lang.ArithmeticException: / by zero
a and b=4:0
java.lang.ArithmeticException: / by zero
I have demonstrated this example to cover two topics : Use your custom ThreadPoolExecutor and handle Exectpion
with custom ThreadPoolExecutor.
The default behavior is that you'll get a RejectedExecutionException thrown at the caller. But there are more
predefined behaviors available:
You can as well implement your own behavior by extending RejectedExecutionHandler interface:
Note that with this executor, you have no means to get any computed value back.
With Java 8, one can utilize lambdas to shorten the code example.
Version ≥ Java SE 8
Executor exec = anExecutor;
exec.execute(() -> {
//offloaded work, no need to get result back
});
I prefer this one when number of Callable/Runnable tasks are small in number and piling of tasks in
unbounded queue does not increase memory & degrade the performance of the system. If you have
CPU/Memory constraints, I prefer to use ThreadPoolExecutor with capacity constraints &
RejectedExecutionHandler to handle rejection of tasks.
2. CountDownLatch
CountDownLatch will be initialized with a given count. This count is decremented by calls to the countDown()
method. Threads waiting for this count to reach zero can call one of the await() methods. Calling await()
blocks the thread until the count reaches zero. This class enables a java thread to wait until other set of threads
completes their tasks.
Use cases:
1. Achieving Maximum Parallelism: Sometimes we want to start a number of threads at the same time to
achieve maximum parallelism
3. Deadlock detection.
2. ThreadPoolExecutor.CallerRunsPolicy`, the thread that invokes execute itself runs the task. This
provides a simple feedback control mechanism that will slow down the rate that new tasks are
submitted.
4. ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down, the task at the head of
the work queue is dropped, and then execution is retried (which can fail again, causing this to be
repeated.)
If you want to simulate CountDownLatch behaviour, you can use invokeAll() method.
The ForkJoinPool was added to Java in Java 7. The ForkJoinPool is similar to the Java ExecutorService but
with one difference. The ForkJoinPool makes it easy for tasks to split their work up into smaller tasks which
are then submitted to the ForkJoinPool too. Task stealing happens in ForkJoinPool when free worker
threads steal tasks from busy worker thread queue.
Java 8 has introduced one more API in ExecutorService to create work stealing pool. You don't have to create
RecursiveTask and RecursiveAction but still can use ForkJoinPool.
Creates a work-stealing thread pool using all available processors as its target parallelism level.
All these four mechanism are complimentary to each other. Depending on level of granularity you want to control,
you have to chose right ones.
1. ExecutorService invokeAll()
Executes the given tasks, returning a list of Futures holding their status and results when
everything is completed.
Example:
import java.util.concurrent.*;
import java.util.*;
2. CountDownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being
performed in other threads completes.
A CountDownLatch is initialized with a given count. The await methods block until the current
count reaches zero due to invocations of the countDown() method, after which all waiting threads
are released and any subsequent invocations of await return immediately. This is a one-shot
phenomenon -- the count cannot be reset. If you need a version that resets the count, consider
using a CyclicBarrier.
shutdown(): Initiates an orderly shutdown in which previously submitted tasks are executed, but no new
tasks will be accepted.
shutdownNow():Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and
returns a list of the tasks that were awaiting execution.
In above example, if your tasks are taking more time to complete, you can change if condition to while
condition
Replace
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
with
while(!pool.awaitTermination(60, TimeUnit.SECONDS)) {
Thread.sleep(60000);
Creates an Executor that uses a single worker thread operating off an unbounded queue
There is a difference between newFixedThreadPool(1) and newSingleThreadExecutor() as the java doc says
for the latter:
Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to
be reconfigurable to use additional threads.
Which means that a newFixedThreadPool can be reconfigured later in the program by:
((ThreadPoolExecutor) fixedThreadPool).setMaximumPoolSize(10) This is not possible for
newSingleThreadExecutor
Use cases:
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded
queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks
are submitted when all threads are active, they will wait in the queue until a thread is available
Use cases:
Cons:
Creates a thread pool that creates new threads as needed, but will reuse previously constructed
threads when they are available
Use cases:
Cons:
Creates a thread pool that can schedule commands to run after a given delay, or to execute
periodically.
Use cases:
1. Handling recurring events with delays, which will happen in future at certain interval of times
Cons:
Use cases:
Cons:
You can see one common drawbacks in all these ExecutorService : unbounded queue. This will be addressed with
ThreadPoolExecutor
In addition to the normal ExecutorService methods, the ScheduledExecutorService API adds 4 methods that
schedule tasks and return ScheduledFuture objects. The latter can be used to retrieve results (in some cases) and
cancel tasks.
The following example schedules a task to start after ten minutes, and then repeatedly at a rate of once every one
minute.
Task execution will continue according to the schedule until the pool is shut down, the future is canceled, or one of
the tasks encounters an exception.
It is guaranteed that the tasks scheduled by a given scheduledAtFixedRate call will not overlap in time. If a task
takes longer than the prescribed period, then the next and subsequent task executions may start late.
The following example schedules a task to start after ten minutes, and then repeatedly with a delay of one minute
between one task ending and the next one starting.
Task execution will continue according to the schedule until the pool is shut down, the future is canceled, or one of
the tasks encounters an exception.
Method Description
submit Executes a the submitted work and return a future which can be used to get the result
execute Execute the task sometime in the future without getting any return value
invokeAll Execute a list of tasks and return a list of Futures
invokeAny Executes all the but return only the result of one that has been successful (without exceptions)
Once you are done with the Thread Pool you can call shutdown() to terminate the Thread Pool. This executes all
pending tasks. To wait for all tasks to execute you can can loop around awaitTermination or isShutdown().
This can be usedwe can use ThreadLocal variables. in situations where you have a thread pool like for example in a
web service. For example, Creating a SimpleDateFormat object every time for every request is time consuming and
a Static one cannot be created as SimpleDateFormat is not thread safe, so we can create a ThreadLocal so that we
can perform thread safe operations without the overhead of creating SimpleDateFormat every time.
Every thread has it’s own ThreadLocal variable and they can use it’s get() and set() methods to get the default
value or change it’s value local to Thread.
ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread.
Here is a small example showing use of ThreadLocal in java program and proving that every thread has it’s own
copy of ThreadLocal variable.
package com.examples.threads;
import java.text.SimpleDateFormat;
import java.util.Random;
@Override
public void run() {
System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter =
"+formatter.get().toPattern());
try {
formatter.set(new SimpleDateFormat());
Output:
As we can see from the output that Thread-0 has changed the value of formatter but still thread-2 default formatter
is same as the initialized value.
In Foo we count starting from zero. Instead of saving the state to a field we store our current number in the
ThreadLocal object which is statically accessible. Note that the synchronization in this example is not related to the
usage of ThreadLocal but rather ensures a better console output.
@Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
synchronized (threadLocal) {
//Although accessing a static field, we get our own (previously saved) value.
int value = threadLocal.get();
System.out.println(Thread.currentThread().getName() + ": " + value);
try {
threadLocal.notifyAll();
if (i < ITERATIONS - 1) {
threadLocal.wait();
}
} catch (InterruptedException ex) {
}
}
}
}
}
From the output we can see that each thread counts for itself and does not use the value of the other one:
In this example, we will create two classes: One which implements the Runnable interface, and one which contains
a main() method.
AsyncMaintenanceTaskCompleter.java
import lombok.extern.java.Log;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@Log
public class AsyncMaintenanceTaskCompleter implements Runnable {
private int taskNumber;
} catch (InterruptedException e) {
log.warning(e.getMessage());
}
}
}
AsyncExample1
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
Observations of Note: There are several things to note in the output above,
AsyncValueTypeTaskCompleter.java
import lombok.extern.java.Log;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@Log
public class AsyncValueTypeTaskCompleter implements Callable<Integer> {
private int taskNumber;
@Override
public Integer call() throws Exception {
int timeout = ThreadLocalRandom.current().nextInt(1, 20);
try {
log.info(String.format("Task %d is sleeping", taskNumber));
TimeUnit.SECONDS.sleep(timeout);
log.info(String.format("Task %d is done sleeping", taskNumber));
} catch (InterruptedException e) {
log.warning(e.getMessage());
}
return timeout;
}
}
AsyncExample2.java
import lombok.extern.java.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Log
public class AsyncExample2 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<Integer>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++){
Future<Integer> submittedFuture = executorService.submit(new
AsyncValueTypeTaskCompleter(i));
futures.add(submittedFuture);
}
executorService.shutdown();
while(!futures.isEmpty()){
for(int j = 0; j < futures.size(); j++){
Future<Integer> f = futures.get(j);
if(f.isDone()){
try {
Observations of Note:
1. Each call to ExecutorService.submit() returned an instance of Future, which was stored in a list for later use
2. Future contains a method called isDone() which can be used to check whether our task has been completed
before attempting to check it's return value. Calling the Future.get() method on a Future that is not yet done
will block the current thread until the task is complete, potentially negating many benefits gained from
performing the task Asynchronously.
3. The executorService.shutdown() method was called prior to checking the return values of the Future objects.
This is not required, but was done in this way to show that it is possible. The executorService.shutdown()
method does not prevent the completion of tasks which have already been submitted to the ExecutorService,
but rather prevents new tasks from being added to the Queue.
In this example, we will create a single class which contains a main() method. Inside this method, we will use
Lambda expressions to create and execute instances of Callable and Runnable<T>.
AsyncExample3.java
import lombok.extern.java.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
@Log
public class AsyncExample3 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<Integer>> futures = new ArrayList<>();
for(int i = 0; i < 5; i++){
final int index = i;
executorService.execute(() -> {
int timeout = getTimeout();
log.info(String.format("Runnable %d has been submitted and will sleep for %d
seconds", index, timeout));
try {
Observations of Note:
1. Lambda expressions have access to variables and methods which are available to the scope in which they are
defined, but all variables must be final (or effectively final) for use inside a lambda expression.
2. We do not have to specify whether our Lambda expression is a Callable or a Runnable<T> explicitly, the
return type is inferred automatically by the return type.
This includes any common mistakes in use of the Java language or understanding of the run-time environment.
Mistakes associated with specific APIs can be described in topics specific to those APIs. Strings are a special case;
they're covered in the Java Language Specification. Details other than common mistakes can be described in this
topic on Strings.
==
to compare values, because that is what you would do with int values. And in some cases this will seem to work:
Integer int1_1 = Integer.valueOf("1");
Integer int1_2 = Integer.valueOf(1);
Here we created two Integer objects with the value 1 and compare them (In this case we created one from a
String and one from an int literal. There are other alternatives). Also, we observe that the two comparison
methods (
==
In this case, only the equals comparison yields the correct result.
The reason for this difference in behavior is, that the JVM maintains a cache of Integer objects for the range -128 to
127. (The upper value can be overridden with the system property "java.lang.Integer.IntegerCache.high" or the JVM
argument "-XX:AutoBoxCacheMax=size"). For values in this range, the Integer.valueOf() will return the cached
value rather than creating a new one.
Thus, in the first example the Integer.valueOf(1) and Integer.valueOf("1") calls returned the same cached
Integer instance. By contrast, in the second example the Integer.valueOf(1000) and Integer.valueOf("1000")
both created and returned new Integer objects.
The
operator for reference types tests for reference equality (i.e. the same object). Therefore, in the first example
int1_1 == int1_2 is true because the references are the same. In the second example int2_1 == int2_2 is false
because the references are different.
==
The above program is supposed to test the first command line argument and print different messages when it and
isn't the word "hello". But the problem is that it won't work. That program will output "Are you feeling grumpy
today?" no matter what the first command line argument is.
In this particular case the String "hello" is put in the string pool while the String args[0] resides on the heap. This
means there are two objects representing the same literal, each with its reference. Since
==
tests for references, not actual equality, the comparison will yield a false most of the times. This doesn't mean that
it will always do so.
==
to test strings, what you are actually testing is if two String objects are the same Java object. Unfortunately, that is
not what string equality means in Java. In fact, the correct way to test strings is to use the equals(Object) method.
For a pair of strings, we usually want to test if they consist of the same characters in the same order.
public class Hello2 {
public static void main(String[] args) {
if (args.length > 0) {
if (args[0].equals("hello")) {
System.out.println("Hello back to you");
} else {
System.out.println("Are you feeling grumpy today?");
}
}
}
}
Interestingly, this will print "same", even though we are testing the strings the wrong way. Why is that? Because the
Java Language Specification (Section 3.10.5: String Literals) stipulates that any two string >>literals<< consisting of
the same characters will actually be represented by the same Java object. Hence, the
==
test will give true for equal literals. (The string literals are "interned" and added to a shared "string pool" when your
code is loaded, but that is actually an implementation detail.)
To add to the confusion, the Java Language Specification also stipulates that when you have a compile-time
constant expression that concatenates two string literals, that is equivalent to a single literal. Thus:
This will output "1. same" and "2. different". In the first case, the + expression is evaluated at compile time and we
compare one String object with itself. In the second case, it is evaluated at run time and we compare two different
String objects
In summary, using
==
to test strings in Java is almost always incorrect, but it is not guaranteed to give the wrong answer.
Since Java 7 there is a really useful and neat statement introduced in Java 7 particularly for this case, called try-with-
resources:
Version ≥ Java SE 7
private static void printFileJava7() throws IOException {
try (FileInputStream input = new FileInputStream("file.txt")) {
int data = input.read();
while (data != -1){
System.out.print((char) data);
data = input.read();
}
}
}
The try-with-resources statement can be used with any object that implements the Closeable or AutoCloseable
interface. It ensures that each resource is closed by the end of the statement. The difference between the two
interfaces is, that the close() method of Closeable throws an IOException which has to be handled in some way.
In cases where the resource has already been opened but should be safely closed after use, one can assign it to a
local variable inside the try-with-resources
Version ≥ Java SE 7
private static void printFileJava7(InputStream extResource) throws IOException {
try (InputStream input = extResource) {
... //access resource
}
}
The local resource variable created in the try-with-resources constructor is effectively final.
File f = null;
try {
f = getValidatedFile("somefile");
} catch (IOException ex) {
System.err.println(ex.getMessage());
return;
}
try (InputStream is = new FileInputStream(file)) {
// Read data etc.
}
The first problem is in the signature for FileInputStream(File) because the compiler will still insist we catch
IOException here, or further up the stack.
The second problem is that checks performed by getValidatedFile do not guarantee that the FileInputStream
will succeed.
Race conditions: another thread or a separate process could rename the file, delete the file, or remove read
access after the getValidatedFile returns. That would lead to a "plain" IOException without the custom
message.
There are edge cases not covered by those tests. For example, on a system with SELinux in "enforcing" mode,
an attempt to read a file can fail despite canRead() returning true.
The third problem is that the tests are inefficient. For example, the exists, isFile and canRead calls will each make
a syscall to perform the required check. Another syscall is then made to open the file, which repeats the same
checks behind the scenes.
In short, methods like getValidatedFile are misguided. It is better to simply attempt to open the file and handle
the exception:
If you wanted to distinguish IO errors thrown while opening and reading, you could use a nested try / catch. If you
wanted to produce better diagnostics for open failures, you could perform the exists, isFile and canRead checks
in the handler.
If you mistakenly think of variables as objects, the actual behavior of the Java language will surprise you.
For Java variables which have a primitive type (such as int or float) the variable holds a copy of the value. All
copies of a primitive value are indistinguishable; i.e. there is only one int value for the number one. Primitive
values are not objects and they do not behave like objects.
For Java variables which have a reference type (either a class or an array type) the variable holds a reference.
All copies of a reference are indistinguishable. References may point to objects, or they may be null which
means that they point to no object. However, they are not objects and they don't behave like objects.
Variables are not objects in either case, and they don't contain objects in either case. They may contain references to
objects, but that is saying something different.
Example class
The examples that follow use this class, which represents a point in 2D space.
An instance of this class is an object that has two fields x and y which have the type int.
We can have many instances of the MutableLocation class. Some will represent the same locations in 2D space; i.e.
the respective values of x and y will match. Others will represent different locations.
In the above, we have declared three variables here, there and elsewhere that can hold references to
If you (incorrectly) think of these variables as being objects, then you are likely to misread the statements as saying:
From that, you are likely to infer we have three independent objects in the three variables. In fact there are only two
objects created by the above. The variables here and there actually refer to the same object.
We assigned a new value to here.x and it changed the value that we see via there.x. They are referring to the
same object. But the value that we see via elsewhere.x has not changed, so elsewhere must refer to a different
object.
If a variable was an object, then the assignment here.x = 42 would not change there.x.
The equality operator does NOT test that two objects are equal
==
) operator to reference values tests if the values refer to the same object. It does not test whether two (different)
objects are "equal" in the intuitive sense.
MutableLocation here = new MutableLocation(1, 2);
MutableLocation there = here;
MutableLocation elsewhere = new MutableLocation(1, 2);
if (here == there) {
System.out.println("here is there");
}
if (here == elsewhere) {
System.out.println("here is elsewhere");
}
This will print "here is there", but it won't print "here is elsewhere". (The references in here and elsewhere are for
two distinct objects.)
By contrast, if we call the equals(Object) method that we implemented above, we are going to test if two
MutableLocation instances have an equal location.
This will print both messages. In particular, here.equals(elsewhere) returns true because the semantic criteria we
chose for equality of two MutableLocation objects has been satisfied.
Java method calls use pass by value1 to pass arguments and return a result.
When you pass a reference value to a method, you're actually passing a reference to an object by value, which
means that it is creating a copy of the object reference.
As long as both object references are still pointing to the same object, you can modify that object from either
reference, and this is what causes confusion for some.
However, you are not passing an object by reference2. The distinction is that if the object reference copy is modified
to point to another object, the original object reference will still point to the original object.
void g() {
MutableLocation foo = MutableLocation(1, 2);
f(foo);
System.out.println("foo.x is " + foo.x); // Prints "foo.x is 1".
}
void g() {
MutableLocation foo = new MutableLocation(0, 0);
f(foo);
System.out.println("foo.x is " + foo.x); // Prints "foo.x is 42"
}
1 - In languages like Python and Ruby, the term "pass by sharing" is preferred for "pass by value" of an object /
reference.
2 - The term "pass by reference" or "call by reference" has a very specific meaning in programming language
terminology. In effect, it means that you pass the address of a variable or an array element, so that when the called
method assigns a new value to the formal argument, it changes the value in the original variable. Java does not
support this. For a more fulsome description of different mechanisms for passing parameters, please refer to
https://en.wikipedia.org/wiki/Evaluation_strategy.
However, you can prevent memory from being freed, by allowing objects to be reachable that are no longer
needed. Whether you call this a memory leak or memory packratting, the result is the same -- an unnecessary
increase in allocated memory.
Memory leaks in Java can happen in various ways, but the most common reason is everlasting object references,
because the garbage collector can’t remove objects from the heap while there are still references to them.
Static fields
One can create such a reference by defining class with a static field containing some collection of objects, and
forgetting to set that static field to null after the collection is no longer needed. static fields are considered GC
roots and are never collected. Another issue is leaks in non-heap memory when JNI is used.
Classloader leak
By far, though, the most insidious type of memory leak is the classloader leak. A classloader holds a reference to
every class it has loaded, and every class holds a reference to its classloader. Every object holds a reference to its
class as well. Therefore, if even a single object of a class loaded by a classloader is not garbage, not a single class
that that classloader has loaded can be collected. Since each class also refers to its static fields, they cannot be
collected either.
Accumulation leak The accumulation leak example could look like the following:
scheduledExecutorService.scheduleAtFixedRate(() -> {
BigDecimal number = numbers.peekLast();
if (number != null && number.remainder(divisor).byteValue() == 0) {
System.out.println("Number: " + number);
System.out.println("Deque size: " + numbers.size());
}
}, 10, 10, TimeUnit.MILLISECONDS);
scheduledExecutorService.scheduleAtFixedRate(() -> {
numbers.add(new BigDecimal(System.currentTimeMillis()));
}, 10, 10, TimeUnit.MILLISECONDS);
try {
scheduledExecutorService.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
This example creates two scheduled tasks. The first task takes the last number from a deque called numbers, and, if
the number is divisible by 51, it prints the number and the deque's size. The second task puts numbers into the
deque. Both tasks are scheduled at a fixed rate, and they run every 10 ms.
If the code is executed, you’ll see that the size of the deque is permanently increasing. This will eventually cause the
deque to be filled with objects that consume all available heap memory.
The above code is supposed to print command line arguments in upper case. Unfortunately, it does not work, the
case of the arguments is not changed. The problem is this statement:
s.toUpperCase();
You might think that calling toUpperCase() is going to change s to an uppercase string. It doesn't. It can't! String
objects are immutable. They cannot be changed.
In reality, the toUpperCase() method returns a String object which is an uppercase version of the String that you
call it on. This will probably be a new String object, but if s was already all uppercase, the result could be the
existing string.
So in order to use this method effectively, you need to use the object returned by the method call; for example:
s = s.toUpperCase();
In fact, the "strings never change" rule applies to all String methods. If you remember that, then you can avoid a
whole category of beginner's mistakes.
i += a[i++] + b[i--];
Generally speaking:
for Java the answer is always specified1, but non-obvious, and often difficult to figure out
for C and C++ the answer is often unspecified.
Such examples are often used in exams or job interviews as an attempt to see if the student or interviewee
understands how expression evaluation really works in the Java programming language. This is arguably legitimate
To illustrate, the following seemingly simple example has appeared a few times in StackOverflow questions (like this
one). In some cases, it appears as a genuine mistake in someone's code.
int a = 1;
a = a++;
System.out.println(a); // What does this print.
Most programmers (including Java experts) reading those statements quickly would say that it outputs 2. In fact, it
outputs 1. For a detailed explanation of why, please read this Answer.
However the real takeaway from this and similar examples is that any Java statement that both assigns to and side-
effects the same variable is going to be at best hard to understand, and at worst downright misleading. You should
avoid writing code like this.
1 - modulo potential issues with the Java Memory Model if the variables or objects are visible to other threads.
....
try {
InputStream is = new FileInputStream(fileName);
// process the input
} catch (Exception ex) {
System.out.println("Could not open file " + fileName);
}
The above code has a significant flaw. The catch is actually going to catch more exceptions than the programmer is
expecting. Suppose that the value of the fileName is null, due to a bug elsewhere in the application. This will cause
the FileInputStream constructor to throw a NullPointerException. The handler will catch this, and report to the
user:
which is unhelpful and confusing. Worse still, suppose that the it was the "process the input" code that threw the
unexpected exception (checked or unchecked!). Now the user will get the misleading message for a problem that
didn't occur while opening the file, and may not be related to I/O at all.
The root of the problem is that the programmer has coded a handler for Exception. This is almost always a
mistake:
Catching Exception will catch all checked exceptions, and most unchecked exceptions as well.
Catching RuntimeException will catch most unchecked exceptions.
Catching Error will catch unchecked exceptions that signal JVM internal errors. These errors are generally not
recoverable, and should not be caught.
Catching Throwable will catch all possible exceptions.
The problem with catching too broad a set of exceptions is that the handler typically cannot handle all of them
appropriately. In the case of the Exception and so on, it is difficult for the programmer to predict what could be
caught; i.e. what to expect.
In general, the correct solution is to deal with the exceptions that are thrown. For example, you can catch them and
handle them in situ:
try {
InputStream is = new FileInputStream(fileName);
// process the input
} catch (FileNotFoundException ex) {
System.out.println("Could not open file " + fileName);
}
There are very few situations where catching Exception is appropriate. The only one that arises commonly is
something like this:
Here we genuinely want to deal with all exceptions, so catching Exception (or even Throwable) is correct.
Exceptions are usually thrown (by something) to notify other parts of the program that some significant (i.e.
"exceptional") event has occurred. Generally (though not always) an exception means that something has gone
wrong. If you code your program to squash the exception, there is a fair chance that the problem will reappear in
another form. To make things worse, when you squash the exception, you are throwing away the information in the
exception object and its associated stack trace. That is likely to make it harder to figure out what the original source
of the problem was.
In practice, exception squashing frequently happens when you use an IDE's auto-correction feature to "fix" a
compilation error caused by an unhandled exception. For example, you might see code like this:
try {
inputStream = new FileInputStream("someFile");
} catch (IOException e) {
/* add exception handling code here */
}
Clearly, the programmer has accepted the IDE's suggestion to make the compilation error go away, but the
suggestion was inappropriate. (If the file open has failed, the program should most likely do something about it.
With the above "correction", the program is liable to fail later; e.g. with a NullPointerException because
inputStream is now null.)
Having said that, here is an example of deliberately squashing an exception. (For the purposes of argument,
assume that we have determined that an interrupt while showing the selfie is harmless.) The comment tells the
reader that we squashed the exception deliberately, and why we did that.
try {
selfie.show();
} catch (InterruptedException e) {
// It doesn't matter if showing the selfie is interrupted.
Another conventional way to highlight that we are deliberately squashing an exception without saying why is to
indicate this with the exception variable's name, like this:
try {
selfie.show();
} catch (InterruptedException ignored) { }
Some IDEs (like IntelliJ IDEA) won't display a warning about the empty catch block if the variable name is set to
ignored.
The basic problem is that when your application needs to handle exceptions, the presence of the top level
exceptions make it hard to discriminate between different error conditions. For example
try {
InputStream is = new FileInputStream(someFile); // could throw IOException
...
if (somethingBad) {
throw new Exception(); // WRONG
}
} catch (IOException ex) {
System.err.println("cannot open ...");
} catch (Exception ex) {
System.err.println("something bad happened"); // WRONG
}
The problem is that because we threw an Exception instance, we are forced to catch it. However as described in
another example, catching Exception is bad. In this situation, it becomes difficult to discriminate between the
"expected" case of an Exception that gets thrown if somethingBad is true, and the unexpected case where we
actually catch an unchecked exception such as NullPointerException.
We now have to remember all of the different reasons that we threw the top-level, and discriminate / handle
them.
In the case of Exception and Throwable we also need to add these exceptions to the throws clause of
methods if we want the exception to propagate. This is problematic, as described below.
In short, don't throw these exceptions. Throw a more specific exception that more closely describes the
"exceptional event" that has happened. If you need to, define and use a custom exception class.
It is tempting to replace a long list of thrown exceptions in a method's throws clause with Exception or even
`Throwable. This is a bad idea:
This advice means that certain other patterns should be avoided. For example:
try {
doSomething();
} catch (Exception ex) {
report(ex);
throw ex;
}
The above attempts to log all exceptions as they pass, without definitively handling them. Unfortunately, prior to
Java 7, the throw ex; statement caused the compiler to think that any Exception could be thrown. That could force
you to declare the enclosing method as throws Exception. From Java 7 onwards, the compiler knows that the set
of exceptions that could be (re-thrown) there is smaller.
The essence of this is that is it is a bad idea (in Java) to use exceptions and exception handling to implement normal
flow control. For example, compare these two ways of dealing with a parameter that could be null.
In this example, we are (by design) treating the case where word is null as if it is an empty word. The two versions
deal with null either using conventional if ... else and or try ... catch. How should we decide which version is better?
The first criterion is readability. While readability is hard to quantify objectively, most programmers would agree
that the essential meaning of the first version is easier to discern. Indeed, in order to truly understand the second
form, you need to understand that a NullPointerException cannot be thrown by the Math.min or
String.substring methods.
The second criterion is efficiency. In releases of Java prior to Java 8, the second version is significantly (orders of
On the other hand, there are many situations where using exceptions is more readable, more efficient and
(sometimes) more correct than using conditional code to deal with "exceptional" events. Indeed, there are rare
situations where it is necessary to use them for "non-exceptional" events; i.e. events that occur relatively frequently.
For the latter, it is worth looking at ways to reduce the overheads of creating exception objects.
More to the point there is no practical benefit to directly subclassing Throwable, as the resulting class is, in effect,
simply a checked exception. Subclassing Exception instead will result in the same behavior, but will more clearly
convey your intent.
try {
// Some code
} catch (Exception) {
// Some error handling
}
Comes with a lot of different problems. But one perticular problem is that it can lead to deadlocks as it breaks the
interrupt system when writing multi-threaded applications.
If you start a thread you usually also need to be able to stop it abruptly for various reasons.
t.start();
The t.interrupt() will raise an InterruptedException in that thread, than is intended to shut down the thread. But
what if the Thread needs to clean up some resources before its completely stopped? For this it can catch the
But if you have a catch-all expression in your code, the InterruptedException will be caught by it as well and the
interruption will not continue. Which in this case could lead to a deadlock as the parent thread waits indefinitely for
this thead to stop with t.join().
So it is better to catch Exceptions individually, but if you insist on using a catch-all, at least catch the
InterruptedException individually beforehand.
The problem is that the printStackTrace() is going to write the stacktrace to standard output.
For an application that is intended for end-users who are not Java programmers, a stacktrace is
uninformative at best, and alarming at worst.
For a server-side application, the chances are that nobody will look at the standard output.
A better idea is to not call printStackTrace directly, or if you do call it, do it in a way that the stack trace is written
to a log file or error file rather than to the end-user's console.
One way to do this is to use a logging framework, and pass the exception object as a parameter of the log event.
However, even logging the exception can be harmful if done injudiciously. Consider the following:
If the exception is thrown in method2, you are likely to see two copies of the same stacktrace in the logfile,
corresponding to the same failure.
In short, either log the exception or re-throw it further (possibly wrapped with another exception). Don't do both.
In most cases, the cleaner solution would be to use interfaces and move code with specific behaviour into separate
implementations (composition over inheritance)
If a switch-statement is unavoidable it is recommended to document "expected" fallthroughs if they occur. That way
you show fellow developers that you are aware of the missing break, and that this is expected behaviour.
switch(caseIndex) {
[...]
case 2:
System.out.println("Two");
// fallthrough
default:
System.out.println("Default");
package com.example;
/**
Then they wonder why they get unexpected errors. For example:
package com.example;
If you compile and then attempt to run the above classes you will get an error:
$ javac com/example/*.java
$ java com.example.Test
Error: Main method not found in class test.Test, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
Someone looking at the code for the Test class would see the declaration of main and look at its signature and
wonder what the java command is complaining about. But in fact, the java command is telling the truth.
When we declare a version of String in the same package as Test, this version takes precedence over the
automatic import of java.lang.String. Thus, the signature of the Test.main method is actually
instead of
and the java command will not recognize that as an entrypoint method.
Lesson: Do not define classes that have the same name as existing classes in java.lang, or other commonly used
classes in the Java SE library. If you do that, you are setting yourself open for all sorts of obscure errors.
This is not actually required by Java language syntax. Indeed, if the "then" part of an if statement is a single
statement, it is legal to leave out the braces
or even
if (a) doSomething();
However there are dangers in ignoring Java style rules and leaving out the braces. Specifically, you significantly
increase the risk that code with faulty indentation will be misread.
if (a)
doSomething();
doSomeMore();
This code seems to say that the calls to doSomething and doSomeMore will both occur if and only if a is true. In fact,
the code is incorrectly indented. The Java Language Specification that the doSomeMore() call is a separate statement
following the if statement. The correct indentation is as follows:
if (a)
doSomething();
doSomeMore();
A second problem appears when we add else to the mix. Consider the following example with missing braces.
if (a)
if (b)
doX();
else if (c)
doY();
else
doZ();
The code above seems to say that doZ will be called when a is false. In fact, the indentation is incorrect once again.
The correct indentation for the code is:
if (a)
if (b)
doX();
else if (c)
doY();
else
doZ();
If the code was written according to the Java style rules, it would actually look like this:
if (a) {
if (b) {
doX();
} else if (c) {
doY();
} else {
To illustrate why that is better, suppose that you had accidentally mis-indented the code. You might end up with
something like this:
if (a) { if (a) {
if (b) { if (b) {
doX(); doX();
} else if (c) { } else if (c) {
doY(); doY();
} else { } else {
doZ(); doZ();
} }
} }
But in both cases, the mis-indented code "looks wrong" to the eye of an experienced Java programmer.
A Java beginner might be surprised to know that the above program prints the wrong answer. It actually prints the
sum of the numbers 1 to 8.
The reason is that an integer literal that starts with the digit zero ('0') is interpreted by the Java compiler as an octal
literal, not a decimal literal as you might expect. Thus, 010 is the octal number 10, which is 8 in decimal.
An experienced programmer would spot that as being clumsy and want to rewrite it as:
However, there is more wrong with ok == true than simple clumsiness. Consider this variation:
==
as
... and now the code has a subtle bug. The expression x = true unconditionally assigns true to x and then
evaluates to true. In other words, the check method will now print "It is OK" no matter what the parameter was.
The lesson here is to get out of the habit of using == false and == true. In addition to being verbose, they make
your coding more error prone.
Note: A possible alternative to ok == true that avoids the pitfall is to use Yoda conditions; i.e. put the literal on the
left side of the relational operator, as in true == ok. This works, but most programmers would probably agree that
Yoda conditions look odd. Certainly ok (or !ok) is more concise and more natural.
You should pay attention to what methods you make public. The public methods in an application are the
application’s visible API. This should be as small and compact as possible, especially if you are writing a reusable
library (see also the SOLID principle). It is important to similarly consider the visibility of all methods, and to only
use protected or package private access where appropriate.
When you declare methods that should be private as public, you expose the internal implementation details of the
class.
A corollary to this is that you only unit test the public methods of your class - in fact you can only test public
methods. It is bad practice to increase the visibility of private methods just to be able to run unit tests against those
methods. Testing public methods that call the methods with more restrictive visibility should be sufficient to test an
entire API. You should never expand your API with more public methods only to allow unit testing.
This is what the Java Language Specification (JLS 14.10, for Java 8) advises on this matter:
Because assertions may be disabled, programs must not assume that the expressions contained in
assertions will be evaluated. Thus, these boolean expressions should generally be free of side effects.
Evaluating such a boolean expression should not affect any state that is visible after the evaluation is
complete. It is not illegal for a boolean expression contained in an assertion to have a side effect, but it is
generally inappropriate, as it could cause program behavior to vary depending on whether assertions
were enabled or disabled.
In light of this, assertions should not be used for argument checking in public methods. Argument
checking is typically part of the contract of a method, and this contract must be upheld whether
assertions are enabled or disabled.
A secondary problem with using assertions for argument checking is that erroneous arguments should
result in an appropriate run-time exception (such as IllegalArgumentException,
ArrayIndexOutOfBoundsException, or NullPointerException). An assertion failure will not throw an
appropriate exception. Again, it is not illegal to use assertions for argument checking on public methods,
but it is generally inappropriate. It is intended that AssertionError never be caught, but it is possible to
do so, thus the rules for try statements should treat assertions appearing in a try block similarly to the
current treatment of throw statements.
import com.example.somelib.*;
import com.acme.otherlib.*;
Suppose that when when you first developed the code against version 1.0 of somelib and version 1.0 of otherlib.
Then at some later point, you need to upgrade your dependencies to a later versions, and you decide to use
otherlib version 2.0. Also suppose that one of the changes that they made to otherlib between 1.0 and 2.0 was to
add a Context class.
Now when you recompile Test, you will get a compilation error telling you that Context is an ambiguous import.
If you are familiar with the codebase, this probably is just a minor inconvenience. If not, then you have some work
to do to address this problem, here and potentially elsewhere.
The problem here is the wildcard imports. On the one hand, using wildcards can make your classes a few lines
shorter. On the other hand:
Upwards compatible changes to other parts of your codebase, to Java standard libraries or to 3rd party
libraries can lead to compilation errors.
Readability suffers. Unless you are using an IDE, figuring out which of the wildcard imports is pulling in a
named class can be difficult.
if (feeling == HAPPY)
System.out.println("Smile");
else
System.out.println("Frown");
if (feeling == HAPPY);
System.out.println("Smile");
else
System.out.println("Frown");
and are puzzled when the Java compiler tells them that the else is misplaced. The Java compiler with interpret the
above as follows:
if (feeling == HAPPY)
/*empty statement*/ ;
System.out.println("Smile"); // This is unconditional
else // This is misplaced. A statement cannot
// start with 'else'
System.out.println("Frown");
In other cases, there will be no be compilation errors, but the code won't do what the programmer intends. For
example:
only prints "Hello" once. Once again, the spurious semicolon means that the body of the for loop is an empty
statement. That means that the println call that follows is unconditional.
Another variation:
This will give a "Cannot find symbol" error for i. The presence of the spurious semicolon means that the println
call is attempting to use i outside of its scope.
In those examples, there is a straight-forward solution: simply delete the spurious semicolon. However, there are
some deeper lessons to be drawn from these examples:
1. The semicolon in Java is not "syntactic noise". The presence or absence of a semicolon can change the
meaning of your program. Don't just add them at the end of every line.
2. Don't trust your code's indentation. In the Java language, extra whitespace at the beginning of a line is
3. Use an automatic indenter. All IDEs and many simple text editors understand how to correctly indent Java
code.
4. This is the most important lesson. Follow the latest Java style guidelines, and put braces around the "then"
and "else" statements and the body statement of a loop. The open brace ({) should not be on a new line.
If the programmer followed the style rules then the if example with a misplaced semicolons would look like this:
if (feeling == HAPPY); {
System.out.println("Smile");
} else {
System.out.println("Frown");
}
That looks odd to an experienced eye. If you auto-indented that code, it would probably look like this:
if (feeling == HAPPY); {
System.out.println("Smile");
} else {
System.out.println("Frown");
}
This code is not going to behave as expected. The problem is that the equals and hashcode methods for Person do
not override the standard methods defined by Object.
The equals method has the wrong signature. It should be declared as equals(Object) not equals(String).
The hashcode method has the wrong name. It should be hashCode() (note the capital C).
However, there is a simple way to deal with this (from Java 5 onwards). Use the @Override annotation whenever
you intend your method to be an override:
Version ≥ Java SE 5
public final class Person {
...
@Override
public boolean equals(String other) {
....
}
@Override
public hashcode() {
....
}
}
When we add an @Override annotation to a method declaration, the compiler will check that the method does
override (or implement) a method declared in a superclass or interface. So in the example above, the compiler will
give us two compilation errors, which should be enough to alert us to the mistake.
// example:
Boolean ignore = null;
if (ignore == false) {
System.out.println("Do not ignore!");
}
}
}
The pitfall here is that null is compared to false. Since we're comparing a primitive boolean against a Boolean,
Java attempts to unbox the the Boolean Object into a primitive equivalent, ready for comparison. However, since
that value is null, a NullPointerException is thrown.
Java is incapable of comparing primitive types against null values, which causes a NullPointerException at
runtime. Consider the primitive case of the condition false == null; this would generate a compile time error
incomparable types: int and <null>.
Using a Runnable:
The custom thread class approach works, but it has a few problems:
1. It is awkward to use PrimeThread in a context that uses a classic thread pool, an executor, or the ForkJoin
framework. (It is not impossible, because PrimeThread indirectly implements Runnable, but using a custom
Thread class as a Runnable is certainly clumsy, and may not be viable ... depending on other aspects of the
class.)
2. There is more opportunity for mistakes in other methods. For example, if you declared a
PrimeThread.start() without delegating to Thread.start(), you would end up with a "thread" that ran on
the current thread.
The approach of putting the thread logic into a Runnable avoids these problems. Indeed, if you use an anonymous
class (Java 1.1 onwards) to implement the Runnable the result is more succinct, and more readable than the
With a lambda expression (Java 8 onwards), the above example would become even more elegant:
This tells us that simply creating more and more Java threads cannot make the application go faster and faster. But
there are other considerations as well:
Each thread requires an off-heap memory region for its thread stack. The typical (default) thread stack size is
512Kbytes or 1Mbytes. If you have a significant number of threads, the memory usage can be significant.
Each active thread will refer to a number of objects in the heap. That increases the working set of reachable
objects, which impacts on garbage collection and on physical memory usage.
The overheads of switching between threads is non-trivial. It typically entails a switch into the OS kernel
space to make a thread scheduling decision.
The overheads of thread synchronization and inter-thread signaling (e.g. wait(), notify() / notifyAll) can be
significant.
Depending on the details of your application, these factors generally mean that there is a "sweet spot" for the
number of threads. Beyond that, adding more threads gives minimal performance improvement, and can make
performance worse.
If your application create for each new task, then an unexpected increase in the workload (e.g. a high request rate)
can lead to catastrophic behavior.
A better way to deal with this is to use bounded thread pool whose size you can control (statically or dynamically).
When there is too much work to do, the application needs to queue the requests. If you use an ExecutorService, it
will take care of the thread pool management and task queuing.
The reason this is wrong is that it depends on some other thread to call lock.notify() or lock.notifyAll(), but
nothing guarantees that the other thread did not make that call before the consumer thread called lock.wait().
lock.notify() and lock.notifyAll() do not do anything at all if some other thread is not already waiting for the
notification. The thread that calls myConsumer() in this example will hang forever if it is too late to catch the
notification.
If you call wait() or notify() on an object without holding the lock, then the JVM will throw
IllegalMonitorStateException.
(The design for wait() / notify() requires that the lock is held because this is necessary to avoid systemic race
conditions. If it was possible to call wait() or notify() without locking, then it would be impossible to implement
the primary use-case for these primitives: waiting for a condition to occur.)
The best way to avoid problems with wait() and notify() is to not use them. Most synchronization problems can
be solved by using the higher-level synchronization objects (queues, barriers, semaphores, etc.) that are available in
the java.utils.concurrent package.
The intent of this program is intended to start a thread, let it run for 1000 milliseconds, and then cause it to stop by
setting the stop flag.
An application does not necessarily stop when the main method returns. If another thread has been created, and
that thread has not been marked as a daemon thread, then the application will continue to run after the main
thread has ended. In this example, that means that the application will keep running until child thread ends. That
should happens when tt.stop is set to true.
But that is actually not strictly true. In fact, the child thread will stop after it has observed stop with the value true.
Will that happen? Maybe yes, maybe no.
The Java Language Specification guarantees that memory reads and writes made in a thread are visible to that
thread, as per the order of the statements in the source code. However, in general, this is NOT guaranteed when
one thread writes and another thread (subsequently) reads. To get guaranteed visibility, there needs to be a chain
of happens-before relations between a write and a subsequent read. In the example above, there is no such chain
for the update to the stop flag, and therefore it is not guaranteed that the child thread will see stop change to true.
(Note to authors: There should be a separate Topic on the Java Memory Model to go into the deep technical details.)
In this case, there are two simple ways to ensure that the stop update is visible:
For a volatile variable, the JLS specifies that there is a happens-before relation between a write by one
thread and a later read by a second thread.
In addition to ensuring that there is mutual exclusion, the JLS specifies that there is a happens-before relation
between the releasing a mutex in one thread and gaining the same mutex in a second thread.
Yes it is!
However, that fact does not mean that the effects of update will be visible simultaneously to all threads. Only a
proper chain of happens-before relations will guarantee that.
Programmers doing multi-threaded programming in Java for the first time find the Memory Model is challenging.
Programs behave in an unintuitive way because the natural expectation is that writes are visible uniformly. So why
the Java designers design the Memory Model this way.
It actually comes down to a compromise between performance and ease of use (for the programmer).
A modern computer architecture consists of multiple processors (cores) with individual register sets. Main memory
is accessible either to all processors or to groups of processors. Another property of modern computer hardware is
that access to registers is typically orders of magnitude faster to access than access to main memory. As the
number of cores scales up, it is easy to see that reading and writing to main memory can become a system's main
performance bottleneck.
This mismatch is addressed by implementing one or more levels of memory caching between the processor cores
and main memory. Each core access memory cells via its cache. Normally, a main memory read only happens when
there is a cache miss, and a main memory write only happens when a cache line needs to be flushed. For an
application where each core's working set of memory locations will fit into its cache, the core speed is no longer
limited by main memory speed / bandwidth.
But that gives us a new problem when multiple cores are reading and writing shared variables. The latest version of
a variable may sit in one core's cache. Unless the that core flushes the cache line to main memory, AND other cores
The standard solution used at the hardware instruction set level is to provide instructions for cache invalidation and
a cache write-through, and leave it to the compiler to decide when to use them.
Returning to Java. the Memory Model is designed so that the Java compilers are not required to issue cache
invalidation and write-through instructions where they are not really needed. The assumption is that the
programmer will use an appropriate synchronization mechanism (e.g. primitive mutexes, volatile, higher-level
concurrency classes and so on) to indicate that it needs memory visibility. In the absence of a happens-before
relation, the Java compilers are free to assume that no cache operations (or similar) are required.
This has significant performance advantages for multi-threaded applications, but the downside is that writing
correct multi-threaded applications is not a simple matter. The programmer does have to understand what he or
she is doing.
There are a number of reasons why problems like this are difficult to reproduce:
1. As explained above, the consequence of not dealing with memory visibility issues problems properly is
typically that your compiled application does not handle the memory caches correctly. However, as we
alluded to above, memory caches often get flushed anyway.
2. When you change the hardware platform, the characteristics of the memory caches may change. This can
lead to different behavior if your application does not synchronize correctly.
3. You may be observing the effects of serendipitous synchronization. For example, if you add traceprints, their
is typically some synchronization happening behind the scenes in the I/O streams that causes cache flushes.
So adding traceprints often causes the application to behave differently.
4. Running an application under a debugger causes it to be compiled differently by the JIT compiler.
Breakpoints and single stepping exacerbate this. These effects will often change the way an application
behaves.
These things make bugs that are due to inadequate synchronization particularly difficult to solve.
The first benchmark simply creates, starts and joins threads. The thread's Runnable does no work.
$ java ThreadTest
34627.91355
33596.66021
33661.19084
33699.44895
33603.097
33759.3928
33671.5719
33619.46809
33679.92508
33500.32862
33409.70188
33475.70541
33925.87848
33672.89529
^C
On a typical modern PC running Linux with 64bit Java 8 u101, this benchmark shows an average time taken to
create, start and join thread of between 33.6 and 33.9 microseconds.
The second benchmark does the equivalent to the first but using an ExecutorService to submit tasks and a Future
to rendezvous with the end of the task.
import java.util.concurrent.*;
$ java ExecutorTest
6714.66053
5418.24901
5571.65213
5307.83651
5294.44132
5370.69978
5291.83493
5386.23932
5384.06842
5293.14126
5445.17405
5389.70685
As you can see, the averages are between 5.3 and 5.6 microseconds.
While the actual times will depend on a variety of factors, the difference between these two results is significant. It
is clearly faster to use a thread pool to recycle threads than it is to create new threads.
Often, this is accompanied with an assertion that is "best practice" to test for null like this to avoid
NullPointerException.
There are some underlying assumptions that need to be questioned before we can say if it is a good idea to do this
in our joinStrings:
A String value can be zero or more characters, so we already have a way of representing an empty string. Does
null mean something different to ""? If no, then it is problematic to have two ways to represent an empty string.
A null can come from an uninitialized field, or an uninitialized array element. The value could be uninitialized by
design, or by accident. If it was by accident then this is a bug.
Sometimes a null can have a genuine meaning; e.g. that the real value of a variable is unknown or unavailable or
"optional". In Java 8, the Optional class provides a better way of expressing that.
One interpretation of the code is that we are "making good" an unexpected null by using an empty string in its
place. Is the correct strategy? Would it be better to let the NullPointerException happen, and then catch the
exception further up the stack and log it as a bug?
The problem with "making good" is that it is liable to either hide the problem, or make it harder to diagnose.
If the "make good" approach is used consistently, your code is going to contain a lot of "defensive" null tests. This is
going to make it longer and harder to read. Furthermore, all of this testing and "making good" is liable to impact on
the performance of your application.
In summary
Otherwise, it is a better idea to treat an unexpected null as a programming error, and let the
NullPointerException happen so that the developer gets to know there is a problem in the code.
The first version is how you would normally code the method:
/**
* Sum the values in an array of integers.
* @arg values the array to be summed
* @return the sum
**/
public int sum(int[] values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return sum;
}
The second version is how you need to code the method if you are in the habit of using null to represent an empty
array.
/**
* Sum the values in an array of integers.
* @arg values the array to be summed, or null.
* @return the sum, or zero if the array is null.
**/
public int sum(int[] values) {
int sum = 0;
if (values != null) {
for (int value : values) {
sum += value;
}
}
return sum;
}
As you can see, the code is a bit more complicated. This is directly attributable to the decision to use null in this
way.
Now consider if this array that might be a null is used in lots of places. At each place where you use it, you need to
consider whether you need to test for null. If you miss a null test that needs to be there, you risk a
NullPointerException. Hence, the strategy of using null in this way leads to your application being more fragile;
i.e. more vulnerable to the consequences of programmer errors.
The lesson here is to use empty arrays and empty lists when that is what you mean.
The space overhead is small, and there are other ways to minimize it if this this is a worthwhile thing to do.
While the above code might look innocent, it has a flaw that can make debugging impossible. If the line where out is
initialized (out = new FileOutputStream(filename)) throws an exception, then out will be null when out.close()
is executed, resulting in a nasty NullPointerException!
To prevent this, simply make sure the stream isn't null before trying to close it.
An even better approach is to try-with-resources, since it'll automatically close the stream with a probability of 0 to
throw an NPE without the need of a finally block.
The problem is that the getReader is returning a null as a special value to indicate that the Reader could not be
opened. Now the returned value needs to be tested to see if it is null before it is used. If the test is left out, the
result will be a NullPointerException.
In fact, assuming that the exception did need to be caught early like this, there were a couple of alternatives to
returning null:
1. It would be possible to implement a NullReader class; e.g. one where API's operations behaves as if the
reader was already at the "end of file" position.
2. With Java 8, it would be possible to declare getReader as returning an Optional<Reader>.
...
MyRecord record = new MyRecord();
record.a = 1; // OK
record.b = record.b + 1; // OK
record.c = 1; // OK
record.d = record.d + 1; // throws a NullPointerException
Our MyRecord class1 relies on default initialization to initialize the values on its fields. Thus, when we new a record,
the a and b fields will be set to zero, and the c and d fields will be set to null.
When we try to use the default initialized fields, we see that the int fields works all of the time, but the Integer
fields work in some cases and not others. Specifically, in the case that fails (with d), what happens is that the
expression on the right-hand side attempts to unbox a null reference, and that is what causes the
NullPointerException to be thrown.
If the fields don't need to be primitive wrappers, then it is a mistake to make them primitive wrappers. In
addition to this problem, the primitive wrappers have extra overheads relative to primitive types.
The lesson here is to not use primitive wrapper types unless you really need to.
1 - This class is not an example of good coding practice. For instance, a well-designed class would not have public
fields. However, that is not the point of this example.
if ("A".equals(someString)) {
// do something
}
This does "prevent" or "avoid" a possible NullPointerException in the case that someString is null. Furthermore,
it is arguable that
"A".equals(someString)
is better than:
(It is more concise, and in some circumstances it might be more efficient. However, as we argue below, conciseness
could be a negative.)
However, the real pitfall is using the Yoda test to avoid NullPointerExceptions as a matter of habit.
When you write "A".equals(someString) you are actually "making good" the case where someString happens to
be null. But as another example (Pitfall - "Making good" unexpected nulls ) explains, "making good" null values
can be harmful for a variety of reasons.
This means that Yoda conditions are not "best practice"1. Unless the null is expected, it is better to let the
NullPointerException happen so that you can get a unit test failure (or a bug report). That allows you to find and
fix the bug that caused the unexpected / unwanted null to appear.
Yoda conditions should only be used in cases where the null is expected because the object you are testing has
come from an API that is documented as returning a null. And arguably, it could be better to use one of the less
pretty ways expressing the test because that helps to highlight the null test to someone who is reviewing your
code.
1 - According to Wikipedia: "Best coding practices are a set of informal rules that the software development community
has learned over time which can help improve the quality of software.". Using Yoda notation does not achieve this. In a
lot of situations, it makes the code worse.
Unfortunate this code is inefficient if the words list is long. The root of the problem is this statement:
For each loop iteration, this statement creates a new message string containing a copy of all characters in the
original message string with extra characters appended to it. This generates a lot of temporary strings, and does a
lot of copying.
When we analyse joinWords, assuming that there are N words with an average length of M, we find that O(N)
temporary strings are created and O(M.N2) characters will be copied in the process. The N2 component is
particularly troubling.
The recommended approach for this kind of problem1 is to use a StringBuilder instead of string concatenation as
follows:
The analysis of joinWords2 needs to take account of the overheads of "growing" the StringBuilder backing array
that holds the builder's characters. However, it turns out that the number of new objects created is O(logN) and
that the number of characters copied is O(M.N) characters. The latter includes characters copied in the final
toString() call.
(It may be possible to tune this further, by creating the StringBuilder with the correct capacity to start with.
However, the overall complexity remains the same.)
Returning to the original joinWords method, it turns out that the critical statement will be optimized by a typical
Java compiler to something like this:
However, the Java compiler will not "hoist" the StringBuilder out of the loop, as we did by hand in the code for
joinWords2.
Reference:
1 - In Java 8 and later, the Joiner class can be used to solve this particular problem. However, that is not what this
example is really supposed to be about.
Both methods can be used to test for collection emptiness. For example:
While these approaches look the same, some collection implementations do not store the size. For such a
collection, the implementation of size() needs to calculate the size each time it is called. For instance:
A simple linked list class (but not the java.util.LinkedList) might need to traverse the list to count the
elements.
The ConcurrentHashMap class needs to sum the entries in all of the map's "segments".
A lazy implementation of a collection might need to realize the entire collection in memory in order to count
the elements.
By contrast, an isEmpty() method only needs to test if there is at least one element in the collection. This does not
entail counting the elements.
While size() == 0 is not always less efficient that isEmpty(), it is inconceivable for a properly implemented
isEmpty() to be less efficient than size() == 0. Hence isEmpty() is preferred.
==
. (After all
==
Fragility
==
if you know that all of the String objects you are testing have been interned. The JLS guarantees that String literals
in your source code will have been interned. However, none of the standard Java SE APIs guarantee to return
interned strings, apart from String.intern(String) itself. If you miss just one source of String objects that
haven't been interned, your application will be unreliable. That unreliability will manifest itself as false negatives
rather than exceptions which is liable to make it harder to detect.
Costs of using 'intern()'
Under the hood, interning works by maintaining a hash table that contains previously interned String objects.
Some kind of weak reference mechanism is used so that the interning hash table does not become a storage leak.
While the hash table is implemented in native code (unlike HashMap, HashTable and so on), the intern calls are still
relatively costly in terms of CPU and memory used.
This cost has to be compared with the saving of we are going to get by using
==
instead of equals. In fact, we are not going to break even unless each interned string is compared with other strings
"a few" times.
(Aside: the few situations where interning is worthwhile tend to be about reducing the memory foot print of an
application where the same strings recur many times, and those strings have a long lifetime.)
In addition to the direct CPU and memory costs described above, interned Strings impact on the garbage collector
performance.
For versions of Java prior to Java 7, interned strings are held in the "PermGen" space which is collected infrequently.
If PermGen needs to be collected, this (typically) triggers a full garbage collection. If the PermGen space fills
completely, the JVM crashes, even if there was free space in the regular heap spaces.
In Java 7, the string pool was moved out of "PermGen" into the normal heap. However, the hash table is still going
to be a long-lived data structure, which is going to cause any interned strings to be long-lived. (Even if the interned
string objects were allocated in Eden space they would most likely be promoted before they were collected.)
Thus in all cases, interning a string is going to prolong its lifetime relative to an ordinary string. That will increase the
garbage collection overheads over the lifetime of the JVM.
The second issue is that the hash table needs to use a weak reference mechanism of some kind to prevent string
interning leaking memory. But such a mechanism is more work for the garbage collector.
According to this source, from Java 6 onwards, the string pool is implemented as fixed sized hash table with chains
to deal with strings that hash to the same bucket. In early releases of Java 6, the hash table had a (hard-wired)
constant size. A tuning parameter (-XX:StringTableSize) was added as a mid-life update to Java 6. Then in a mid-
life update to Java 7, the default size of the pool was changed from 1009 to 60013.
The bottom line is that if you do intend to use intern intensively in your code, it is advisable to pick a version of Java
where the hashtable size is tunable and make sure that you tune the size it appropriately. Otherwise, the
performance of intern is liable to degrade as the pool gets larger.
The hashcode algorithm for strings is well-known. If you intern strings supplied by malicious users or applications,
this could be used as part of a denial of service (DoS) attack. If the malicious agent arranges that all of the strings it
provides have the same hash code, this could lead to an unbalanced hash table and O(N) performance for intern ...
where N is the number of collided strings.
(There are simpler / more effective ways to launch a DoS attack against a service. However, this vector could be
used if the goal of the DoS attack is to break security, or to evade first-line DoS defences.)
The reason that using new Integer(int) explicitly is a bad idea is that it creates a new object (unless optimized out
by JIT compiler). By contrast, when autoboxing or an explicit valueOf call are used, the Java runtime will try to reuse
an Integer object from a cache of pre-existing objects. Each time the runtime has a cache "hit", it avoids creating an
object. This also saves heap memory and reduces GC overheads caused by object churn.
Notes:
1. In recent Java implementations, autoboxing is implemented by calling valueOf, and there are caches for
Boolean, Byte, Short, Integer, Long and Character.
2. The caching behavior for the integral types is mandated by the Java Language Specification.
This code is correct, but it is inefficient. The problem is in the matches(...) call. Under the hood, s.matches("[A-
Za-z0-9]*") is equivalent to this:
Pattern.matches(s, "[A-Za-z0-9]*")
Pattern.compile("[A-Za-z0-9]*").matcher(s).matches()
The Pattern.compile("[A-Za-z0-9]*") call parses the regular expression, analyze it, and construct a Pattern
object that holds the data structure that will be used by the regex engine. This is a non-trivial computation. Then a
Matcher object is created to wrap the s argument. Finally we call match() to do the actual pattern matching.
The problem is that this work is all repeated for each loop iteration. The solution is to restructure the code as
follows:
Instances of this class are immutable and are safe for use by multiple concurrent threads. Instances of
the Matcher class are not safe for such use.
Suppose you want to test if a string s contains three or more digits in a row. You cn express this in various ways
including:
if (s.matches(".*[0-9]{3}.*")) {
System.out.println("matches");
or
if (Pattern.compile("[0-9]{3}").matcher(s).find()) {
System.out.println("matches");
}
The first one is more concise, but it is also likely to be less efficient. On the face of it, the first version is going to try
to match the entire string against the pattern. Furthermore, since ".*" is a "greedy" pattern, the pattern matcher is
likely to advance "eagerly" try to the end of the string, and backtrack until it finds a match.
By contrast, the second version will search from left to right and will stop searching as soon as it finds the 3 digits in
a row.
Regular expressions are a powerful tool, but they should not be your only tool. A lot of tasks can be done more
efficiently in other ways. For example:
Pattern.compile("ABC").matcher(s).find()
s.contains("ABC")
except that the latter is a lot more efficient. (Even if you can amortize the cost of compiling the regular expression.)
Often, the non-regex form is more complicated. For example, the test performed by the matches() call the earlier
allAlplanumeric method can be rewritten as:
Now that is more code than using a Matcher, but it is also going to be significantly faster.
Catastrophic Backtracking
(This is potentially a problem with all implementations of regular expressions, but we will mention it here because it
is a pitfall for Pattern usage.)
The first println call will quickly print true. The second one will print false. Eventually. Indeed, if you experiment
This is behavior is an example of catastrophic backtracking. The pattern matching engine that implements the regex
matching is fruitlessly trying all of the possible ways that the pattern might match.
Let us look at what (A+)+B actually means. Superficially, it seems to say "one or more A characters followed by a B
value", but in reality it says one or more groups, each of which consists of one or more A characters. So, for
example:
In other words, the number of possible matches is 2N where N is the number of A characters.
The above example is clearly contrived, but patterns that exhibit this kind of performance characteristics (i.e.
O(2^N) or O(N^K) for a large K) arise frequently when ill-considered regular expressions are used. There are some
standard remedies:
Finally, beware of situations where a user or an API client can supply a regex string with pathological characteristics.
That can lead to accidental or deliberate "denial of service".
References:
import java.io.*;
(We have deliberated omitted normal argument checking, error reporting and so on because they are not relevant
to point of this example.)
If you compile the above code and use it to copy a huge file, you will notice that it is very slow. In fact, it will be at
least a couple of orders of magnitude slower than the standard OS file copy utilities.
The primary reason that the example above is slow (in the large file case) is that it is performing one-byte reads and
one-byte writes on unbuffered byte streams. The simple way to improve performance is to wrap the streams with
buffered streams. For example:
import java.io.*;
These small changes will improve data copy rate by at least a couple of orders of magnitude, depending on various
platform-related factors. The buffered stream wrappers cause the data to be read and written in larger chunks. The
instances both have buffers implemented as byte arrays.
With is, data is read from the file into the buffer a few kilobytes at a time. When read() is called, the
implementation will typically return a byte from the buffer. It will only read from the underlying input stream
if the buffer has been emptied.
The behavior for os is analogous. Calls to os.write(int) write single bytes into the buffer. Data is only
written to the output stream when the buffer is full, or when os is flushed or closed.
As you should be aware, Java I/O provides different APIs for reading and writing binary and text data.
InputStream and OutputStream are the base APIs for stream-based binary I/O
Reader and Writer are the base APIs for stream-based text I/O.
For text I/O, BufferedReader and BufferedWriter are the equivalents for BufferedInputStream and
BufferedOutputStream.
The real reason that buffered streams help performance is to do with the way that an application talks to the
operating system:
By contrast, JVM runtime calls to the operating system are not fast. They involve something known as a
"syscall". The typical pattern for a syscall is as follows:
As you can imagine, performing a single syscall can thousands of machine instructions. Conservatively, at least two
orders of magnitude longer than a regular method call. (Probably three or more.)
Given this, the reason that buffered streams make a big difference is that they drastically reduce the number of
syscalls. Instead of doing a syscall for each read() call, the buffered input stream reads a large amount of data into
a buffer as required. Most read() calls on the buffered stream do some simple bounds checking and return a byte
that was read previously. Similar reasoning applies in the output stream case, and also the character stream cases.
(Some people think that buffered I/O performance comes from the mismatch between the read request size and
the size of a disk block, disk rotational latency and things like that. In fact, a modern OS uses a number of strategies
to ensure that the application typically doesn't need to wait for the disk. This is not the real explanation.)
Not always. Buffered streams are definitely a win if your application is going to do lots of "small" reads or writes.
However, if your application only needs to perform large reads or writes to / from a large byte[] or char[], then
buffered streams will give you no real benefits. Indeed there might even be a (tiny) performance penalty.
No it isn't. When you use Java's stream-based APIs to copy a file, you incur the cost of at least one extra memory-to-
memory copy of the data. It is possible to avoid this if your use the NIO ByteBuffer and Channel APIs. (Add a link to
a separate example here.)
int a = 1000;
int b = a + 1;
and
Answer: The two versions look almost the identical, but the first version is a lot more efficient than the second one.
The second version is using a representation for the numbers that uses more space, and is relying on auto-boxing
and auto-unboxing behind the scenes. In fact the second version is directly equivalent to the following code:
Comparing this to the other version that uses int, there are clearly three extra method calls when Integer is used.
In the case of valueOf, the calls are each going to create and initialize a new Integer object. All of this extra boxing
and unboxing work is likely to make the second version an order of magnitude slower than the first one.
In addition to that, the second version is allocating objects on the heap in each valueOf call. While the space
utilization is platform specific, it is likely to be in the region of 16 bytes for each Integer object. By contrast, the int
version needs zero extra heap space, assuming that a and b are local variables.
Another big reason why primitives are faster then their boxed equivalent is how their respective array types are laid
out in memory.
If you take int[] and Integer[] as an example, in the case of an int[] the int values are contiguously laid out in
memory. But in the case of an Integer[] it's not the values that are laid out, but references (pointers) to Integer
objects, which in turn contain the actual int values.
Besides being an extra level of indirection, this can be a big tank when it comes to cache locality when iterating over
the values. In the case of an int[] the CPU could fetch all the values in the array, into it's cache at once, because
they are contiguous in memory. But in the case of an Integer[] the CPU potentially has to do an additional
memory fetch for each element, since the array only contains references to the actual values.
In short, using primitive wrapper types is relatively expensive in both CPU and memory resources. Using them
unnecessarily is in efficient.
Even when the log level is set to INFO, arguments passed to debug() will be evaluated on each execution of the line.
This makes it unnecessarily consuming on several counts:
Solution
Most logging framework provide means to create log messages using fix strings and object references. The log
message will be evaluated only if the message is actually logged. Example:
This works very well as long as all parameters can be converted to strings using String.valueOf(Object). If the log
message compuation is more complex, the log level can be checked before logging:
if (LOG.isDebugEnabled()) {
// Argument expression evaluated only when DEBUG is enabled
LOG.debug("Request coming from {}, parameters: {}", myInetAddress,
Arrays.toString(veryLongParamArray);
}
Here, LOG.debug() with the costly Arrays.toString(Obect[]) computation is processed only when DEBUG is
actually enabled.
That is because it requires a map lookup (the get() method) for each key in the map. This lookup may not be
efficient (in a HashMap, it entails calling hashCode on the key, then looking up the correct bucket in internal data
structures, and sometimes even calling equals). On a large map, this may not be a trivial overhead.
The correct way of avoiding this is to iterate on the map's entries, which is detailed in the Collections topic
"Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused
objects in order to make the memory they currently occupy available for quick reuse. When control
returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all
discarded objects."
There are a couple of important points that can be drawn from this:
1. The use of the word "suggests" rather than (say) "tells" means that the JVM is free to ignore the suggestion.
The default JVM behavior (recent releases) is to follow the suggestion, but this can be overridden by setting -
2. The phrase "a best effort to reclaim space from all discarded objects" implies that calling gc will trigger a
"full" garbage collection.
First, running a full garbage collection is expensive. A full GC involves visiting and "marking" every object that is still
reachable; i.e. every object that is not garbage. If you trigger this when there isn't much garbage to be collected,
then the GC does a lot of work for relatively little benefit.
Second, a full garbage collection is liable to disturb the "locality" properties of the objects that are not collected.
Objects that are allocated by the same thread at roughly the same time tend to be allocated close together in
memory. This is good. Objects that are allocated at the same time are likely to be related; i.e. reference each other.
If your application uses those references, then the chances are that memory access will be faster because of
various memory and page caching effects. Unfortunately, a full garbage collection tend to move objects around so
that objects that were once close are now further apart.
Third, running a full garbage collection is liable to make your application pause until the collection is complete.
While this is happening, your application will be non-responsive.
In fact, the best strategy is to let the JVM decide when to run the GC, and what kind of collection to run. If you don't
interfere, the JVM will choose a time and collection type that optimizes throughput or minimizes GC pause times.
At the beginning we said "... (almost always) a bad idea ...". In fact there are a couple of scenarios where it might be
a good idea:
1. If you are implementing a unit test for some code that is garbage collection sensitive (e.g. something
involving finalizers or weak / soft / phantom references) then calling System.gc() may be necessary.
2. In some interactive applications, there can be particular points in time where the user won't care if there is a
garbage collection pause. One example is a game where there are natural pauses in the "play"; e.g. when
loading a new level.
String objects are immutable, so there is no need to copy them to protect against changes.
In some older versions of Java, String objects can share backing arrays with other String objects. In those
versions, it is possible to leak memory by creating a (small) substring of a (large) string and retaining it.
However, from Java 7 onwards, String backing arrays are not shared.
In the absence of any tangible benefit, calling new String(String) is simply wasteful:
Lets start with the interface and put it in a jar, named for example accounting-api.jar
package example;
long getBalance();
}
package example.impl;
import example.AccountingService;
further, the accounting-impl.jar contains a file declaring that this jar provides an implementation of
AccountingService. The file has to have a path starting with META-INF/services/ and must have the same name
as the fully-qualified name of the interface:
META-INF/services/example.AccountingService
example.impl.DefaultAccountingService
Given both jars are in the classpath of the program, that consumes the AccountingService, an instance of the
Service can be obtained by using the ServiceLauncher
As the ServiceLoader is an Iterable, it supports multiple implementation providers, where the program may
choose from:
Note that when invoking next() a new instance will allways be created. If you want to re-use an instance, you have
to use the iterator() method of the ServiceLoader or the for-each loop as shown above.
Service
package servicetest;
import java.io.IOException;
package servicetest.logger;
import servicetest.Logger;
@Override
public void log(String message) {
System.err.println(message);
}
@Override
public void close() {
}
package servicetest.logger;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import servicetest.Logger;
@Override
public void log(String message) throws IOException {
writer.append(message);
writer.newLine();
}
@Override
public void close() throws IOException {
writer.close();
}
META-INF/services/servicetest.Logger
servicetest.logger.ConsoleLogger
servicetest.logger.FileLogger
Usage
The following main method writes a message to all available loggers. The loggers are instantiated using
ServiceLoader.
// iterate through instances of available loggers, writing the message to each one
Iterator<Logger> iterator = loader.iterator();
while (iterator.hasNext()) {
try (Logger logger = iterator.next()) {
logger.log(message);
}
}
}
findClass(String) - overload this method if your classloader follows the standard delegation model for
class loading.
loadClass(String, boolean) - overload this method to implement an alternative delegation model.
findResource and findResources - overload these methods to customize resource loading.
The defineClass methods which are responsible for actually loading the class from a byte array are final to
prevent overloading. Any custom behavior needs to be performed prior to calling defineClass.
@Override
protected Class findClass(String classname) throws ClassNotFoundException {
if (classname.equals(this.classname)) {
return defineClass(classname, classfile, 0, classfile.length);
} else {
throw new ClassNotFoundException(classname);
}
}
}
Since we have only overridden the findClass method, this custom class loader is going to behave as follows when
loadClass is called.
1. The classloader's loadClass method calls findLoadedClass to see if a class with this name has already been
loaded by this classloader. If that succeeds, the resulting Class object is returned to the requestor.
2. The loadClass method then delegates to the parent classloader by calling its loadClass call. If the parent can
deal with the request, it will return a Class object which is then returned to the requestor.
3. If the parent classloader cannot load the class, findClass then calls our override findClass method, passing
the name of the class to be loaded.
4. If the requested name matches this.classname, we call defineClass to load the actual class from the
this.classfile byte array. The resulting Class object is then returned.
5. If the name did not match, we throw ClassNotFoundException.
Now, we have a public defineClass() method. It can be called by passing the name of the class and the class bytes
as arguments.
To call the method we need the class bytes so we create a Path object representing our class' path by using the
Paths.get() method and passing the path of the binary class as an argument. Now, we can get the class bytes with
Files.readAllBytes(path). So we create a ByteClassLoader instance and use the method we created,
defineClass(). We already have the class bytes but to call our method we also need the class name which is given
by the package name (dot) the class canonical name, in this case stackoverflow.MyClass.
Note: The defineClass() method returns a Class<?> object. You can save it if you want.
To load the class, we just call loadClass() and pass the class name. This method can throw an
ClassNotFoundException so we need to use a try cath block
try{
loader.loadClass("stackoverflow.MyClass");
} catch(ClassNotFoundException e){
e.printStackTrace();
}
The classloader created in this example will have the default classloader as its parent, and will first try to find any
class in the parent classloader before looking in "extra.jar". If the requested class has already been loaded, the
findClass call will return the reference to the previously loaded class.
The findClass call can fail in a variety of ways. The most common are:
return img;
}
//you don't have to use the Graphics object, you can read and set pixel color individually
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
int alpha = 255; //don't forget this, or use BufferedImage.TYPE_INT_RGB instead
int red = i; //or any formula you like
int green = j; //or any formula you like
int blue = 50; //or any formula you like
int color = (alpha << 24) | (red << 16) | (green << 8) | blue;
image.setRGB(i, j, color);
}
}
Graphics g = image.createGraphics();
//draw whatever you like, like you would in a drawComponent(Graphics g) method in an UI application
g.setColor(Color.RED);
g.fillRect(20, 30, 50, 50);
g.setColor(Color.BLUE);
g.drawOval(120, 120, 80, 40);
//now image has programmatically generated content, you can use it in graphics.drawImage() to draw it
somewhere else
//or just simply save it to a file
ImageIO.write(image, "png", new File("myimage.png"));
Output:
//modify it
Graphics g = cat.createGraphics();
g.setColor(Color.RED);
g.drawString("Cat", 10, 10);
g.dispose();
g.setColor(Color.BLUE);
g.drawRect(0, 0, 255, 255); //add some nice border
g.dispose(); //and done
Produced file:
//Create a new image with good size that contains or might contain arbitrary alpha values between
and including 0.0 and 1.0.
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
//Finally draw the source image in the Graphics2D with the desired size.
g2.drawImage(srcImg, 0, 0, w, h, null);
//Disposes of this graphics context and releases any system resources that it is using
g2.dispose();
Java Atomic Types are simple mutable types that provide basic operations that are thread-safe and atomic without
resorting to locking. They are intended for use in cases where locking would be a concurrency bottleneck, or where
there is risk of deadlock or livelock.
In cases of more complex concurrency, using Atomic Variables is often a better alternative, as it allows an individual
variable to be accessed in a thread-safe manner without the overhead of using synchronized methods or code
blocks.
There is a notable exception that there is no float and double types. These can be simulated through the use of
Float.floatToIntBits(float) and Float.intBitsToFloat(int) for float as well as
Double.doubleToLongBits(double) and Double.longBitsToDouble(long) for doubles.
If you are willing to use sun.misc.Unsafe you can use any primitive variable as atomic by using the atomic
operation in sun.misc.Unsafe. All primitive types should be converted or encoded in int or longs to so use it in this
way. For more on this see: sun.misc.Unsafe.
/**
* Increments the integer at the given index
*/
public synchronized void count(int number) {
if (number >= 0 && number < counters.length) {
counters[number]++;
}
}
/**
* Obtains the current count of the number at the given index,
* or if there is no number at that index, returns 0.
*/
public synchronized int getCount(int number) {
return (number >= 0 && number < counters.length) ? counters[number] : 0;
}
}
This implementation will work correctly. However, if you have a large number of threads making lots of
simultaneous calls on the same Counters object, the synchronization is liable to be a bottleneck. Specifically:
1. Each synchronized method call will start with the current thread acquiring the lock for the Counters
instance.
2. The thread will hold the lock while it checks number value and updates the counter.
3. Finally, the it will release the lock, allowing other threads access.
If one thread attempts to acquire the lock while another one holds it, the attempting thread will be blocked
(stopped) at step 1 until the lock is released. If multiple threads are waiting, one of them will get it, and the others
will continue to be blocked.
If there is a lot of contention for the lock (i.e. lots of thread try to acquire it), then some threads can be
blocked for a long time.
When a thread is blocked waiting for the lock, the operating system will typically try switch execution to a
different thread. This context switching incurs a relatively large performance impact on the processor.
When there are multiple threads blocked on the same lock, there are no guarantees that any one of them
will be treated "fairly" (i.e. each thread is guaranteed to be scheduled to run). This can lead to thread
starvation.
/**
* Increments the integer at the given index
*/
public void count(int number) {
if (number >= 0 && number < counters.length) {
counters[number].incrementAndGet();
}
}
/**
* Obtains the current count of the object at the given index,
* or if there is no number at that index, returns 0.
*/
public int getCount(int number) {
return (number >= 0 && number < counters.length) ?
counters[number].get() : 0;
}
}
We have replaced the int[] with an AtomicInteger[], and initialized it with an instance in each element. We have
also added calls to incrementAndGet() and get() in place of operations on int values.
But the most important thing is that we can remove the synchronized keyword because locking is no longer
required. This works because the incrementAndGet() and get() operations are atomic and thread-safe. In this
context, it means that:
Each counter in the array will only be observable in the either the "before" state for an operation (like an
"increment") or in the "after" state.
Assuming that the operation occurs at time T, no thread will be able to see the "before" state after time T.
Furthermore, while two threads might actually attempt to update the same AtomicInteger instance at the same
time, the implementations of the operations ensure that only one increment happens at a time on the given
instance. This is done without locking, often resulting in better performance.
Atomic types typically rely on specialized hardware instructions in the instruction set of the target machine. For
example, Intel-based instruction sets provide a CAS (Compare and Swap) instruction that will perform a specific
sequence of memory operations atomically.
These low-level instructions are are used to implement higher-level operations in the APIs of the respective
AtomicXxx classes. For example, (again, in C-like pseudocode):
int increment() {
while (TRUE) {
int old = num;
int new = old + 1;
if (old == compare_and_swap(&num, old, new)) {
return new;
}
}
}
Incidentally, CAS instructions are typically used by the JVM to implement uncontended locking. If the JVM can see that
a lock is not currently locked, it will attempt to use a CAS to acquire the lock. If the CAS succeeds, then there is no
need to do the expensive thread scheduling, context switching and so on. For more information on the techniques
used, see Biased Locking in HotSpot.
OAEP is less vulnerable to padding oracle attacks than PKCS#1 v1.5 padding. GCM is also protected against padding
oracle attacks.
Decryption can be performed by first retrieving the length of the encapsulated key and then by retrieving the
encapsulated key. The encapsulated key can then be decrypted using the RSA private key that forms a key pair with
the public key. After that the AES/GCM encrypted ciphertext can be decrypted to the original plaintext.
1. a length field for the wrapped key (RSAPrivateKey misses a getKeySize() method);
2. the wrapped/encapsulated key, of the same size as the RSA key size in bytes;
3. the GCM ciphertext and 128 bit authentication tag (automatically added by Java).
Notes:
To correctly use this code you should supply an RSA key of at least 2048 bits, bigger is better (but slower,
especially during decryption);
To use AES-256 you should install the unlimited cryptography policy files first;
Instead creating your own protocol you might want to use a container format such as the Cryptographic
Message Syntax (CMS / PKCS#7) or PGP instead.
/**
* Encrypts the data using a hybrid crypto-system which uses GCM to encrypt the data and OAEP to
encrypt the AES key.
* The key size of the AES encryption will be 128 bit.
* All the default parameter choices are used for OAEP and GCM.
*
* @param publicKey the RSA public key used to wrap the AES key
* @param plaintext the plaintext to be encrypted, not altered
* @return the ciphertext
* @throws InvalidKeyException if the key is not an RSA public key
* @throws NullPointerException if the plaintext is null
*/
public static byte[] encryptData(PublicKey publicKey, byte[] plaintext)
throws InvalidKeyException, NullPointerException {
Cipher oaep;
try {
// SHA-1 is the default and not vulnerable in this setting
// use OAEPParameterSpec to configure more than just the hash
oaep = Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for RSA cipher (mandatory algorithm for runtimes)",
e);
KeyGenerator aesKeyGenerator;
try {
aesKeyGenerator = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for AES key generator (mandatory algorithm for
runtimes)", e);
}
// for AES-192 and 256 make sure you've got the rights (install the
// Unlimited Crypto Policy files)
aesKeyGenerator.init(128);
SecretKey aesKey = aesKeyGenerator.generateKey();
byte[] wrappedKey;
try {
wrappedKey = oaep.wrap(aesKey);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(
"AES key should always fit OAEP with normal sized RSA key", e);
}
Cipher aesGCM;
try {
aesGCM = Cipher.getInstance("AES/GCM/Nopadding");
// we can get away with a zero nonce since the key is randomly generated
// 128 bits is the recommended (maximum) value for the tag size
// 12 bytes (96 bits) is the default nonce size for GCM mode encryption
GCMParameterSpec staticParameterSpec = new GCMParameterSpec(128, new byte[12]);
aesGCM.init(Cipher.ENCRYPT_MODE, aesKey, staticParameterSpec);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for AES cipher (mandatory algorithm for runtimes)",
e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(
"Runtime doesn't have support for GCM (present in the standard Java runtime sinze
XX)", e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(
"IvParameterSpec not accepted by this implementation of GCM", e);
}
// --- create a buffer of the right size for our own protocol ---
// - element 1: make sure that we know the size of the wrapped key
ciphertextBuffer.putShort((short) wrappedKey.length);
return ciphertextBuffer.array();
}
Of course, encryption is not very useful without decryption. Note that this will return minimal information if
decryption fails.
/**
* Decrypts the data using a hybrid crypto-system which uses GCM to encrypt
* the data and OAEP to encrypt the AES key. All the default parameter
* choices are used for OAEP and GCM.
*
* @param privateKey
* the RSA private key used to unwrap the AES key
* @param ciphertext
* the ciphertext to be encrypted, not altered
* @return the plaintext
* @throws InvalidKeyException
* if the key is not an RSA private key
* @throws NullPointerException
* if the ciphertext is null
* @throws IllegalArgumentException
* with the message "Invalid ciphertext" if the ciphertext is invalid (minimize
information leakage)
*/
public static byte[] decryptData(PrivateKey privateKey, byte[] ciphertext)
throws InvalidKeyException, NullPointerException {
Cipher oaep;
try {
// SHA-1 is the default and not vulnerable in this setting
// use OAEPParameterSpec to configure more than just the hash
oaep = Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for RSA cipher (mandatory algorithm for runtimes)",
e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(
"Runtime doesn't have support for OAEP padding (present in the standard Java
runtime sinze XX)",
// sanity check #1
if (ciphertextBuffer.remaining() < 2) {
throw new IllegalArgumentException("Invalid ciphertext");
}
// - element 1: the length of the encapsulated key
int wrappedKeySize = ciphertextBuffer.getShort() & 0xFFFF;
// sanity check #2
if (ciphertextBuffer.remaining() < wrappedKeySize + 128 / Byte.SIZE) {
throw new IllegalArgumentException("Invalid ciphertext");
}
Cipher aesGCM;
try {
aesGCM = Cipher.getInstance("AES/GCM/Nopadding");
// we can get away with a zero nonce since the key is randomly
// generated
// 128 bits is the recommended (maximum) value for the tag size
// 12 bytes (96 bits) is the default nonce size for GCM mode
// encryption
GCMParameterSpec staticParameterSpec = new GCMParameterSpec(128,
new byte[12]);
aesGCM.init(Cipher.DECRYPT_MODE, aesKey, staticParameterSpec);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for AES cipher (mandatory algorithm for runtimes)",
e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(
"Runtime doesn't have support for GCM (present in the standard Java runtime sinze
XX)",
e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(
// --- create a buffer of the right size for our own protocol ---
return plaintextBuffer.array();
}
Given any Serializable object, one can create a SealedObject that encapsulates the original object, in serialized
format (i.e., a "deep copy"), and seals (encrypts) its serialized contents, using a cryptographic algorithm such as AES,
DES, to protect its confidentiality. The encrypted content can later be decrypted (with the corresponding algorithm
using the correct decryption key) and de-serialized, yielding the original object.
More specifically, a SignedObject contains another Serializable object, the (to-be-)signed object and its signature.
System.out.println("signedObject-" + signedObject);
System.out.println("signedObject Data-" + signedObject.getObject());
Additional algorithms may be available depending on your implementation of the Java platform.
rsa.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
rsa.update(message.getBytes());
final byte[] result = rsa.doFinal();
Message: Hello
Encrypted: 5641FBB9558ECFA9ED...
Note that when creating the Cipher object, you have to specify a transformation that is compatible with the type of
key being used. (See JCA Standard Algorithm Names for a list of supported transformations.). For RSA encryption
data message.getBytes() length must be smaller than the key size. See this SO Answer for detail.
rsa.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
rsa.update(cipherText);
final String result = new String(rsa.doFinal());
Decrypted: Hello
new SecureRandom().nextBytes(sample);
Sample: E4F14CEA2384F70B706B53A6DF8C5EFE
Note that the call to nextBytes() may block while entropy is gathered depending on the algorithm being used.
randomness.nextBytes(sample);
dhGenerator.initialize(1024);
dsaGenerator.initialize(1024);
rsaGenerator.initialize(2048);
signer.initSign(privateKey);
signer.update(data);
Note that the signature algorithm must be compatible with the algorithm used to generate the key pair.
To verify a signature:
verifier.initVerify(publicKey);
verifier.update(data);
Signature: true
Java platform security practices deal with managing the security and integrity of the JVM. It includes such topics as
managing JCE providers and security policies.
Secure Java programming practices concern the best ways to write secure Java programs. It includes such topics as
using random numbers and cryptography, and preventing vulnerabilities.
One commonly-accepted best practice for handling keys at runtime is to store them only as byte arrays, and never
as strings. This is because Java strings are immutable, and cannot be manually "cleared" or "zeroed out" in memory;
while a reference to a string can be removed, the exact string will remain in memory until its segment of memory is
garbage-collected and reused. An attacker would have a large window in which they could dump the program's
memory and easily find the key. Contrarily, byte arrays are mutable, and can have their contents overwritten in
place; it is a good idea to 'zero-out' your keys as soon as you no longer need them.
However, many cryptographic systems rely on randomness for their security, and the randomness provided by
Random simply isn't of high enough quality. For any cryptographic operation that requires a random input, you
should use SecureRandom instead.
Consistency: Given the same data, a hash function will always return the same value. That is, if X = Y, f(x) will always
equal f(y) for hash function f.
Uniqueness: No two inputs to a hash function will ever result in the same output. That is, if X != Y, f(x) != f(y), for any
Irreversibility: It is impractically difficult, if not impossible, to "reverse" a hash function. That is, given only f(X),
there should be no way of finding the original X short of putting every possible value of X through the function f
(brute-force). There should be no function f1 such that f1(f(X)) = X.
Many functions lack at least one of these attributes. For example, MD5 and SHA1 are known to have collisions, i.e.
two inputs that have the same output, so they lack uniqueness. Some functions that are currently believed to be
secure are SHA-256 and SHA-512.
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classDef = provider.getClass(name);
Class<?> clazz = defineClass(name, classDef, 0, classDef.length, pd);
return clazz;
}
}
By overriding findClass rather than loadClass the delegational model is preserved, and the PluginClassLoader will
first query the system and parent classloader for class definitions.
Create a Policy:
public PluginSecurityPolicy() {
// amend this as appropriate
appPermissions.add(new AllPermission());
// add any permissions plugins should have to pluginPermissions
}
@Override
public Provider getProvider() {
return super.getProvider();
}
@Override
public String getType() {
return super.getType();
}
@Override
public Parameters getParameters() {
return super.getParameters();
}
@Override
@Override
public PermissionCollection getPermissions(ProtectionDomain domain) {
return isPlugin(domain)?pluginPermissions:appPermissions;
}
Policy.setPolicy(new PluginSecurityPolicy());
System.setSecurityManager(new SecurityManager());
The SecurityManager can be installed by setting the java.security.manager system property on the command line
when starting the JVM:
System.setSecurityManager(new SecurityManager())
The standard Java SecurityManager grants permissions on the basis of a Policy, which is defined in a policy file. If no
policy file is specified, the default policy file under $JAVA_HOME/lib/security/java.policy will be used.
Notes:
The standard policy file syntax and mechanism for permission assignment in general remain unaffected. This
means that deny rules within policy files are still expressed as grants.
The policy wrapper is meant to specifically encapsulate the default file-backed Policy (assumed to be
com.sun.security.provider.PolicyFile).
Denied permissions are only processed as such at the policy level. If statically assigned to a domain, they will
by default be treated by that domain as ordinary "positive" permissions.
/**
* A representation of a "negative" privilege.
* <p>
* A <code>DeniedPermission</code>, when "granted" (to some <code>ProtectionDomain</code> and/or
* <code>Principal</code>), represents a privilege which <em>cannot</em> be exercised, regardless of
* any positive permissions (<code>AllPermission</code> included) possessed. In other words, if a
* set of granted permissions, <em>P</em>, contains a permission of this class, <em>D</em>, then the
* set of effectively granted permissions is<br/>
* <br/>
* <em>{ P<sub>implied</sub> - D<sub>implied</sub> }</em>.
* </p>
* <p>
* Each instance of this class encapsulates a <em>target permission</em>, representing the
* "positive" permission being denied.
* </p>
* Denied permissions employ the following naming scheme:<br/>
* <br/>
*
<em><target_class_name>:<target_name>(:<target_actions>)</e
m><br/>
* <br/>
* where:
* <ul>
* <li><em>target_class_name</em> is the name of the target permission's class,</li>
* <li><em>target_name</em> is the name of the target permission, and</li>
* <li><em>target_actions</em> is, optionally, the actions string of the target permission.</li>
* </ul>
* A denied permission, having a target permission <em>t</em>, is said to <em>imply</em> another
* permission <em>p</em>, if:
* <ul>
* <li>p <em>is not</em> itself a denied permission, and <code>(t.implies(p) == true)</code>,
* or</li>
* <li>p <em>is</em> a denied permission, with a target <em>t1</em>, and
* <code>(t.implies(t1) == true)</code>.
* </ul>
* <p>
* It is the responsibility of the policy decision point (e.g., the <code>Policy</code> provider) to
* take denied permission semantics into account when issuing authorization statements.
* </p>
*/
public final class DeniedPermission extends BasicPermission {
/**
* Instantiates a <code>DeniedPermission</code> that encapsulates a target permission of the
* indicated class, specified name and, optionally, actions.
*
* @throws IllegalArgumentException
* if:
* <ul>
* <li><code>targetClassName</code> is <code>null</code>, the empty string, does not
* refer to a concrete <code>Permission</code> descendant, or refers to
/**
* Instantiates a <code>DeniedPermission</code> that encapsulates a target permission of the
class,
* name and, optionally, actions, collectively provided as the <code>name</code> argument.
*
* @throws IllegalArgumentException
* if:
* <ul>
* <li><code>name</code>'s target permission class name component is empty, does not
* refer to a concrete <code>Permission</code> descendant, or refers to
* <code>DeniedPermission.class</code> or
<code>UnresolvedPermission.class</code>.</li>
* <li><code>name</code>'s target name component is <code>empty</code></li>
* <li>the target permission class cannot be instantiated, and it's the caller's
fault;
* e.g., because <code>name</code>'s target name and/or target actions component(s)
do
* not adhere to the naming constraints of the target class; or due to the target
class
* not exposing a <code>(String name)</code>, or
* <code>(String name, String actions)</code> constructor, depending on whether the
* target actions component is empty or not.</li>
* </ul>
*/
public DeniedPermission(String name) {
super(name);
String[] comps = name.split(":");
if (comps.length < 2) {
throw new IllegalArgumentException(MessageFormat.format("Malformed name [{0}]
argument.", name));
}
this.target = initTarget(comps[0], comps[1], ((comps.length < 3) ? null : comps[2]));
}
/**
* Checks whether the given permission is implied by this one, as per the {@link DeniedPermission
* overview}.
*/
@Override
public boolean implies(Permission p) {
if (p instanceof DeniedPermission) {
return target.implies(((DeniedPermission) p).target);
}
return target.implies(p);
}
/**
* Returns this denied permission's target permission (the actual positive permission which is
not
* to be granted).
*/
public Permission getTargetPermission() {
return target;
}
import java.security.CodeSource;
import java.security.NoSuchAlgorithmException;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.security.UnresolvedPermission;
import java.util.Enumeration;
/**
* Wrapper that adds rudimentary {@link DeniedPermission} processing capabilities to the standard
* file-backed <code>Policy</code>.
*/
public final class DenyingPolicy extends Policy {
{
try {
defaultPolicy = Policy.getInstance("javaPolicy", null);
}
catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException("Could not acquire default Policy.", nsae);
}
}
@Override
public PermissionCollection getPermissions(CodeSource codesource) {
return defaultPolicy.getPermissions(codesource);
}
@Override
public PermissionCollection getPermissions(ProtectionDomain domain) {
return defaultPolicy.getPermissions(domain);
}
/**
* @return
* <ul>
* <li><code>true</code> if:</li>
* <ul>
* <li><code>permission</code> <em>is not</em> an instance of
* <code>DeniedPermission</code>,</li>
* <li>an <code>implies(domain, permission)</code> invocation on the system-default
* <code>Policy</code> yields <code>true</code>, and</li>
* <li><code>permission</code> <em>is not</em> implied by any
<code>DeniedPermission</code>s
* having potentially been assigned to <code>domain</code>.</li>
* </ul>
* <li><code>false</code>, otherwise.
* </ul>
*/
@Override
public boolean implies(ProtectionDomain domain, Permission permission) {
if (permission instanceof DeniedPermission) {
/*
* At the policy decision level, DeniedPermissions can only themselves imply, not be
implied (as
* they take away, rather than grant, privileges). Furthermore, clients aren't supposed
to use this
if (!defaultPolicy.implies(domain, permission)) {
// permission not granted, so no need to check whether denied
return false;
}
/*
* Permission granted--now check whether there's an overriding DeniedPermission. The
following
* assumes that previousPolicy is a sun.security.provider.PolicyFile (different
implementations
* might not support #getPermissions(ProtectionDomain) and/or handle UnresolvedPermissions
* differently).
*/
@Override
public void refresh() {
defaultPolicy.refresh();
}
Demo
package com.example;
import java.security.Policy;
Lastly, run the Main and watch it fail, due to the "deny" rule (the DeniedPermission) overriding the grant (its
PropertyPermission). Note that a setProperty("foo.baz", "xyz") invocation would instead have succeeded,
since the denied permission only covers the "read" action, and solely for the "foo.bar" property.
To make this simple, we will use java.rmi.registry.CreateRegistry() to create the RMI Registry.
package com.neohope.jndi.test;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.Hashtable;
/**
* JNDI Server
* 1.create a registry on port 1234
* 2.bind JNDI
* 3.wait for connection
* 4.clean up and end
*/
public class Server {
private static Registry registry;
private static InitialContext ctx;
package com.neohope.jndi.test;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
/**
* 1.init context
* 2.lookup registry for the service
* 3.use the service
* 4.end
*/
public class Client {
public static void main(String[] args) throws NamingException {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");
jndiProperties.put(Context.PROVIDER_URL, "rmi://localhost:1234");
package com.neohope.jndi.test;
import java.io.Serializable;
import java.rmi.Remote;
/**
* NMessage
* RMI server class
* must implements Remote and Serializable
*/
public class NMessage implements Remote, Serializable {
public String message = "";
Introduce
The Java Naming and Directory Interface (JNDI) is a Java API for a directory service that allows Java software
clients to discover and look up data and objects via a name. It is designed to be independent of any specific naming
or directory service implementation.
The JNDI architecture consists of an API (Application Programming Interface) and an SPI (Service Provider
Interface). Java applications use this API to access a variety of naming and directory services. The SPI enables a
variety of naming and directory services to be plugged in transparently, allowing the Java application using the API
of the JNDI technology to access their services.
As you can see form the picture above, JNDI supports LDAP, DNS, NIS, NDS, RMI and CORBA. Of course, you can
extend it.
How it works
In this example, the Java RMI use the JNDI API to look up objects in a network. If you want to look up a object, you
need at least two pieces of information:
The RMI Registry manages the name bindings, it tells you where to find the object.
What is a object's name? It is usually a string, it can also be a object that implements the Name interface.
1. First you need a registry, which manage the name binding. In this example, we use
java.rmi.registry.LocateRegistry.
2. Both client and server need a Context. Server use the Context to bind the name and object. Client use the
Context to lookup the name and get the object.
ctx.unbind("/neohope/jndi/test01");
ctx.close();
sun.misc.Unsafe has a Private constructor, and the static getUnsafe() method is guarded with a check of the
classloader to ensure that the code was loaded with the primary classloader. Therefore, one method of loading the
instance is to use reflection to get the static field.
While this example will compile, it is likely to fail at runtime unless the Unsafe class was loaded with the primary
classloader. To ensure that happens the JVM should be loaded with the appropriate arguments, like:
static {
Unsafe unsafe = null;
try {
final PrivilegedExceptionAction<Unsafe> action = () -> {
final Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = AccessController.doPrivileged(action);
} catch (final Throwable t) {
throw new RuntimeException("Exception accessing Unsafe", t);
}
UNSAFE = unsafe;
}
Use API
Off heap / direct memory allocation, allocateMemory(bytes), reallocateMemory(address, bytes) and
reallocation and deallocation freeMemory(address)
Memory fences loadFence(), storeFence(), fullFence()
Parking current thread park(isAbsolute, time), unpark(thread)
Direct field and or memory access get* and put* family of methods
Throwing unchecked exceptions throwException(e)
CAS and Atomic Operations compareAndSwap* family of methods
Setting out memory setMemory
Volatile or concurrent operations get*Volatile, put*Volatile, putOrdered*
The get and put family of methods are relative to a given object. If the object is null then it is treated as an absolute
address.
Some methods are only defined for int and longs. You can use these methods on floats and doubles using
floatToRawIntBits, intBitsToFloat,doubleToRawLongBits,longBitsToDouble`
If this class is used is a single-threaded application, then the observable behavior will be exactly as you would
expect. For instance:
will output:
0, 0
1, 1
As far as the "main" thread can tell, the statements in the main() method and the doIt() method will be executed in
the order that they are written in the source code. This is a clear requirement of the Java Language Specification
(JLS).
1 - In practice the presence of the println statements is liable to cause some serendipitous synchronization and
memory cache flushing. That is likely to hide some of the effects that would cause the above behavior.
Reordering of assignments
One possible explanation for unexpected results is that the JIT compiler has changed the order of the assignments
in the doIt() method. The JLS requires that statements appear to execute in order from the perspective of the current
thread. In this case, nothing in the code of the doIt() method can observe the effect of a (hypothetical) reordering
of those two statement. This means that the JIT compiler would be permitted to do that.
On typical modern hardware, machine instructions are executed using a instruction pipeline which allows a
sequence of instructions to be in different stages. Some phases of instruction execution take longer than others,
and memory operations tend to take a longer time. A smart compiler can optimize the instruction throughput of
the pipeline by ordering the instructions to maximize the amount of overlap. This may lead to executing parts of
statements out of order. The JLS permits this provided that not affect the result of the computation from the
perspective of the current thread.
A second possible explanation is effect of memory caching. In a classical computer architecture, each processor has
a small set of registers, and a larger amount of memory. Access to registers is much faster than access to main
memory. In modern architectures, there are memory caches that are slower than registers, but faster than main
memory.
A compiler will exploit this by trying to keep copies of variables in registers, or in the memory caches. If a variable
does not need to be flushed to main memory, or does not need to be read from memory, there are significant
performance benefits in not doing this. In cases where the JLS does not require memory operations to be visible to
another thread, the Java JIT compiler is likely to not add the "read barrier" and "write barrier" instructions that will
force main memory reads and writes. Once again, the performance benefits of doing this are significant.
Proper synchronization
So far, we have seen that the JLS allows the JIT compiler to generate code that makes single-threaded code faster by
reordering or avoiding memory operations. But what happens when other threads can observe the state of the
(shared) variables in main memory?
The answer is, that the other threads are liable to observe variable states which would appear to be impossible ...
based on the code order of the Java statements. The solution to this is to use appropriate synchronization. The
three main approaches are:
The Java Memory Model is the section of the JLS that specifies the conditions under which one thread is guaranteed
to see the effects of memory writes made by another thread. The Memory Model is specified with a fair degree of
formal rigor, and (as a result) requires detailed and careful reading to understand. But the basic principle is that
certain constructs create a "happens-before" relation between write of a variable by one thread, and a subsequent
read of the same variable by another thread. If the "happens before" relation exists, the JIT compiler is obliged to
generate code that will ensure that the read operation sees the value written by the write.
Armed with this, it is possible to reason about memory coherency in a Java program, and decide whether this will
be predictable and consistent for all execution platforms.
Happens-before relationships are the part of the Memory Model that allow us to understand and reason about
memory visibility. As the JLS says (JLS 17.4.5):
"Two actions can be ordered by a happens-before relationship. If one action happens-before another, then
the first is visible to and ordered before the second."
Actions
The actions that the above quote refers to are specified in JLS 17.4.2. There are 5 kinds of action listed defined by
the spec:
Synchronization actions:
External Actions. An action that has a result that depends on the environment in which the program.
Thread divergence actions. These model the behavior of certain kinds of infinite loop.
These two orderings ( JLS 17.4.3 and JLS 17.4.4 ) govern the execution of statements in a Java
Program order describes the order of statement execution within a single thread.
Synchronization order describes the order of statement execution for two statements connected by a
synchronization:
An unlock action on monitor synchronizes-with all subsequent lock actions on that monitor.
A write to a volatile variable synchronizes-with all subsequent reads of the same variable by any thread.
An action that starts a thread (i.e. the call to Thread.start()) synchronizes-with the first action in the thread it
starts (i.e. the call to the thread's run() method).
The default initialization of fields synchronizes-with the first action in every thread. (See the JLS for an
explanation of this.)
The final action in a thread synchronizes-with any action in another thread that detects the termination; e.g.
the return of a join() call or isTerminated() call that returns true.
If one thread interrupts another thread, the interrupt call in the first thread synchronizes-with the point where
another thread detects that the thread was interrupted.
Happens-before Order
This ordering ( JLS 17.4.5 ) is what determines whether a memory write is guaranteed to be visible to a subsequent
memory read.
More specifically, a read of a variable v is guaranteed to observe a write to v if and only if write(v) happens-before
read(v) AND there is no intervening write to v. If there are intervening writes, then the read(v) may see the results
of them rather than the earlier one.
Happens-Before Rule #1 - If x and y are actions of the same thread and x comes before y in program order,
then x happens-before y.
Happens-Before Rule #2 - There is a happens-before edge from the end of a constructor of an object to the
start of a finalizer for that object.
In addition, various classes in the Java standard libraries are specified as defining happens-before relationships. You
can interpret this as meaning that it happens somehow, without needing to know exactly how the guarantee is
going to be met.
Use immutable data structures where possible. A properly implemented immutable class will be thread-safe,
and will not introduce thread-safety issues when you use it with other classes.
Use primitive mutexes or Lock objects to synchronize access to state in mutable objects that need to be
thread-safe1.
Use Executor / ExecutorService or the fork join framework rather than attempting to create manage
threads directly.
Use the `java.util.concurrent classes that provide advanced locks, semaphores, latches and barriers, instead
of using wait/notify/notifyAll directly.
Use the java.util.concurrent versions of maps, sets, lists, queues and deques rather than external
synchonization of non-concurrent collections.
The general principle is to try to use Java's built-in concurrency libraries rather than "rolling your own" concurrency.
You can rely on them working, if you use them properly.
1 - Not all objects need to be thread safe. For example, if an object or objects is thread-confined (i.e. it is only
accessible to one thread), then its thread-safety is not relevant.
Single-threaded code
As you would expect, writes are always visible to subsequent reads in a single-threaded program.
4. write(a) happens-before write(b) AND write(b) happens-before read(a) IMPLIES write(a) happens-before
read(a).
Summing up:
6. The write(a) happens-before read(a) relation means that the a + b statement is guaranteed to see the
correct value of a.
7. The write(b) happens-before read(b) relation means that the a + b statement is guaranteed to see the
correct value of b.
We will use the following example code to explore some implications of the Memory Model for `volatile.
3. The volatile-write(a) action in the first thread happens-before the volatile-read(a) action in the second
thread.
4. The write(b) action in the first thread happens-before the read(b) action in the second thread.
In other words, for this particular sequence, we are guaranteed that the 2nd thread will see the update to the non-
volatile variable b made by the first thread. However, it is should also be clear that if the assignments in the update
method were the other way around, or the observe() method read the variable b before a, then the happens-before
chain would be broken. The chain would also be broken if volatile-read(a) in the second thread was not
subsequent to the volatile-write(a) in the first thread.
When the chain is broken, there is no guarantee that observe() will see the correct value of b.
To analyse this completely, we need to consider all of the possible interleavings of the statements in thread one
and thread two. Instead, we will consider just two of them.
In this case, it is easy to see that there is an unbroken happens-before chain from write(b, 3) to read(b).
Furthermore there is no intervening write to b. So, for this scenario, the third thread is guaranteed to see b as
having value 3.
Scenario #2 - suppose that update(1, 2) and update(3,4) overlap and the ations are interleaved as follows:
Now, while there is a happens-before chain from write(b, 3) to read(b), there is an intervening write(b, 1)
action performed by the other thread. This means we cannot be certain which value read(b) will see.
(Aside: This demonstrates that we cannot rely on volatile for ensuring visibility of non-volatile variables, except in
very limited situations.)
import javax.swing.*;
import java.awt.Container;
You may use any program you want to do this. To run from the command line, see the documentation on compiling
and running your first java program.
Once you have HelloWorld.class, make a new folder and call it whatever you want.
Main-Class: HelloWorld
Class-Path: HelloWorld.jar
Use Terminal and change directory to the directory (cd /Users/user/Documents/Java/jarfolder on Mac) your
folder
When that is done, type in jar -cvfm HelloWorld.jar manifest.txt HelloWorld.class and press enter. This
makes a jar file (in the folder with your manifest and HelloWorld.class) using the .class files specified and named
HelloWorld.jar. See the Syntax section for information about the options (like -m and -v).
After these steps, go to your directory with the manifest file and you should find HelloWorld.jar
Clicking on it should display Hello, World in a text box.
Things are not so straightforward if the application depends on third-party libraries. If you simply put dependency
JAR files inside an application JAR, the standard Java class loader will not be able to find the library classes, and your
application will not start. Instead, you need to create a single JAR file that contains the application classes and
associated resources together with the dependency classes and resources. These need to be organized as a single
namespace for the classloader to search.
The procedure for creating an UberJAR is straight-forward. (I will use Linux commands for simplicity. The commands
should be identical for Mac OS, and similar for Windows.)
$ mkdir tempDir
$ cd tempDir
2. For each dependent JAR file, in the reverse order that they need to appear on the application's classpath, used
the jar command to unpack the JAR into the temporary directory.
Doing this for multiple JAR files will overlay contents of the JARs.
3. Copy the application classes from the build tree into the temporary directory
$ cp -r path/to/classes .
If you are creating an executable JAR file, include an appropriate MANIFEST.MF as described here.
If your project is built using Maven, you can get it to create an UberJAR using either the "maven-assembly" or
"maven-shade" plugins. See the Maven Assembly topic (in the Maven documentation) for details.
In addition, if you use an appropriate tooling to create the UberJAR, you will have the option of excluding library
classes that are not used from the JAR file. However, that this is typically done by static analysis of the classes. If
your application uses reflection, annotation processing and similar techniques, you need to be careful that classes
are not excluded incorrectly.
If you have lots of UberJARs with the same dependencies, then each one will contain a copy of the
dependencies.
Some open source libraries have licenses which may preclude 1 their use in an UberJAR.
1 - Some open source library licenses allow you to use the library only of the end-user is able to replace one version
of the library with another. UberJARs can make replacement of version dependencies difficult.
The recommended way to create these files is to use a Java-specific build tool which "understands" the
requirements for the respective file types. If you don't use a build tool, then IDE "export" is the next option to try.
(Editorial note: the descriptions of how to create these files are best placed in the documentation for the respective tools.
Put them there. Please show some self-restraint and DON'T shoe-horn them into this example!)
Creating a JAR or WAR using Maven is simply a matter of putting the correct <packaging> element into the POM file;
e,g,
<packaging>jar</packaging>
or
<packaging>war</packaging>
For more details. Maven can be configured to create "executable" JAR files by adding the requisite information
about the entry-point class and external dependencies as plugin properties for the maven jar plugin. There is even
a plugin for creating "uberJAR" files that combine an application and its dependencies into a single JAR file.
The Ant build tool has separate "tasks" for building JAR, WAR and EAR. Please refer to the Ant documentation (
http://stackoverflow.com/documentation/ant/topics ) for more information.
The three most popular Java IDEs all have built-in support for creating deployment files. The functionality is often
described as "exporting".
Creating JAR, WAR and EAR files using the jar command.
It is also possible to create these files "by hand" using the jar command. It is simply a matter of assembling a file
tree with the correct component files in the correct place, creating a manifest file, and running jar to create the JAR
file.
Please refer to the jar command Topic ( Creating and modifying JAR files ) for more information
Java Web Start software provides the power to launch full-featured applications with a single click. Users
can download and launch applications, such as a complete spreadsheet program or an Internet chat
client, without going through lengthy installation procedures.
Other advantages of Java Web Start are support for signed code and explicit declaration of platform dependencies,
and support for code caching and deployment of application updates.
Java Web Start is also referred to as JavaWS and JAWS. The primary sources of information are:
Prerequisites
At a high level, Web Start works by distributing Java applications packed as JAR files from a remote webserver. The
prerequisites are:
A pre-existing Java installation (JRE or JDK) on the target machine where the application is to run. Java 1.2.2 or
higher is required:
From Java 5.0 onwards, Web Start support is included in the JRE / JDK.
For earlier releases, Web Start support is installed separately.
The Web Start infrastructure includes some Javascript that can be included in a web page to assist the
user to install the necessary software.
The webserver that hosts the software must be accessible to the target machine.
If the user is going to launch a Web Start application using a link in a web page, then:
As you can see, a JNLP file XML-based, and the information is all contained in the <jnlp> element.
The spec attribute gives the version of the JNPL spec that this file conforms to.
The codebase attribute gives the base URL for resolving relative href URLs in the rest of the file.
The href attribute gives the definitive URL for this JNLP file.
The <information> element contains metadata the application including its title, authors, description and
help website.
The <resources> element describes the dependencies for the application including the required Java version,
OS platform and JAR files.
The <application-desc> (or <applet-desc>) element provides information needed to launch the
application.
The webserver must be configured to use application/x-java-jnlp-file as the MIMEtype for .jnlp files.
The JNLP file and the application's JAR files must be installed on the webserver so that they are available using the
URLs indicated by the JNLP file.
If the application is to be launched via a web link, the page that contains the link must be created on the webserver.
If you can assume that Java Web Start is already installed on the user's machine, then the web page simply
needs to contain a link for launching the application. For example.
Otherwise, the page should also include some scripting to detect the kind of browser the user is using and
request to download and install the required version of Java.
The instructions for launching an Web Start application from the command line are simple. Assuming that the user
has a Java 5.0 JRE or JDK installed, the simply need to run this:
$ javaws <url>
where <url> is the URL for the JNLP file on the remote server.
Suppose we have a module of a main application. This module is supposed to load plugins in form of Jars from
'plugins' folder. Initial code:
package main;
package main;
We want to load classes which implement this interface, so first we need to filter files which have a '.jar' extension:
If there are any files, we need to create collections of URLs and class names:
Let's add a static HashSet to MainApplication which will hold loaded plugins:
Next, we instantiate a URLClassLoader, and iterate over class names, instantiating classes which implement Plugin
interface:
package main;
public class MainApplication extends Application
{
static HashSet<Plugin> plugins=new HashSet<>();
@Override
public void start(Stage primaryStage) throws Exception
{
File pluginDirectory=new File("plugins");
if(!pluginDirectory.exists())pluginDirectory.mkdir();
Let's create two plugins. Obviously, the plugin's source should be in a separate module.
package plugins;
import main.Plugin;
Second plugin:
package plugins;
import main.Plugin;
These plugins have to be packaged into standard Jars - this process depends on your IDE or other tools.
When Jars will be put into 'plugins' directly, MainApplication will detect them and instantiate appropriate classes.
public BasicJavaBean(){}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration
statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7
and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in
a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or
abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
You can place underscores only between digits; you cannot place underscores in the following places:
instead of
list.addAll(new ArrayList<>());
because it can't compile. Note that the diamond often works in method calls; however, it is suggested that you use
the diamond primarily for variable declarations.
Dynamic Method Dispatch is a process in which the call to an overridden method is resolved at runtime rather than
at compile-time. When an overridden method is called by a reference, Java determines which version of that
method to execute based on the type of object it refer to. This is also know as runtime polymorphism.
Abstract Class :
package base;
/*
Abstract classes cannot be instantiated, but they can be subclassed
*/
public abstract class ClsVirusScanner {
import base.ClsVirusScanner;
//Child Class 3
class ClsFreeVersion extends ClsVirusScanner{
@Override
public void fnStartScan() {
super.fnVirusMalwareScan();
}
}; //ClsTrialVersion IS-A ClsVirusScanner
//Calling Class
public class ClsRunTheApplication {
Result :
Upcasting :
Now, I want to fill in the body of my method. Rather than rewrite the entire class, I can edit it:
By default, a swing editor will pop up with the most basic features possible. However you can change the editor that
JShell uses:
Note that if the new version of the snippet contains any syntax errors, it may not be saved. Likewise, a
snippet is only created if the original declaration/definition is syntactically correct; the following does not work:
However, snippets may be compiled and hence editable despite certain compile-time errors, such as mismatched
types—the following works:
jshell> int i = 13
jshell> /drop i
jshell> System.out.println(i)
| Error:
| cannot find symbol
| symbol: variable i
| System.out.println(i)
|
jshell> int i = 2
jshell> /reset
| Resetting state.
jshell> i
| Error:
| cannot find symbol
| symbol: variable i
| i
| ^
jshell> s
| Error:
| cannot find symbol
| symbol: variable s
| s
| ^
Before trying to start JShell, make sure your JAVA_HOME environment variable points to a JDK 9 installation. To start
JShell, run the following command:
$ jshell
Exiting JShell
To exit JShell, run the following command from the JShell prompt:
jshell> /exit
jshell> 4+2
jshell> System.out.printf("I am %d years old.\n", 421)
No access modifiers are necessary. As with other blocks, semicolons are required inside of method bodies. Keep in
mind that, as with variables, it is possible to redefine methods and classes. To see a list of methods or classes, enter
/methods or /types at the JShell prompt, respectively.
Keep in mind that variables can be redeclared with different types; this is perfectly valid in JShell:
An alternative standard API is now provided in JDK 9 via the java.lang.StackWalker? class, and is designed to be
efficient by allowing lazy access to the stack frames. Some applications may use this API to traverse the execution
stack and filter on classes.
1 package test;
2
3 import java.lang.StackWalker.StackFrame;
4 import java.lang.reflect.InvocationTargetException;
5 import java.lang.reflect.Method;
6 import java.util.List;
7 import java.util.stream.Collectors;
8
9 public class StackWalkerExample {
10
11 public static void main(String[] args) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
12 Method fooMethod = FooHelper.class.getDeclaredMethod("foo", (Class<?>[])null);
13 fooMethod.invoke(null, (Object[]) null);
14 }
15 }
16
17 class FooHelper {
18 protected static void foo() {
19 BarHelper.bar();
20 }
21 }
22
23 class BarHelper {
24 protected static void bar() {
25 List<StackFrame> stack = StackWalker.getInstance()
26 .walk((s) -> s.collect(Collectors.toList()));
27 for(StackFrame frame : stack) {
28 System.out.println(frame.getClassName() + " " + frame.getLineNumber() + " " +
frame.getMethodName());
29 }
30 }
31 }
Output:
test.BarHelper 26 bar
test.FooHelper 19 foo
test.StackWalkerExample 13 main
class FooHelper {
protected static void foo() {
BarHelper.bar();
}
}
class BarHelper {
protected static void bar() {
System.out.println(StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).getCallerClass());
}
}
Output:
class test.FooHelper
package test;
import java.lang.StackWalker.Option;
import java.lang.StackWalker.StackFrame;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;
class FooHelper {
protected static void foo() {
class BarHelper {
protected static void bar() {
// show reflection methods
List<StackFrame> stack = StackWalker.getInstance(Option.SHOW_REFLECT_FRAMES)
.walk((s) -> s.collect(Collectors.toList()));
for(StackFrame frame : stack) {
System.out.println(frame.getClassName() + " " + frame.getLineNumber() + " " +
frame.getMethodName());
}
}
}
Output:
test.BarHelper 27 bar
test.FooHelper 20 foo
jdk.internal.reflect.NativeMethodAccessorImpl -2 invoke0
jdk.internal.reflect.NativeMethodAccessorImpl 62 invoke
jdk.internal.reflect.DelegatingMethodAccessorImpl 43 invoke
java.lang.reflect.Method 563 invoke
test.StackWalkerExample 14 main
Note that line numbers for some reflection methods may not be available so StackFrame.getLineNumber() may
return negative values.
try (
Socket echoSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in))
) {
//Use the socket
}
// This class implements server sockets. A server socket waits for requests to come
// in over the network only when it is allowed through the local firewall
ServerSocket serverSocket;
@Override
public void run(){
try {
// We want the server to continuously accept connections
while(!Thread.interrupted()){
}
// Close the server once done.
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(CAPECHOServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void run(){
while(!Thread.interrupted()){
try {
// Log with the port number and machine ip
Logger.getLogger((this.getClass().getName())).log(Level.INFO, "Listening for Clients at
{0} on {1}", new Object[]{serverSocket.getLocalPort(),
InetAddress.getLocalHost().getHostAddress()});
Socket client = serverSocket.accept(); // Accept client conncetion
// Now get DataInputStream and DataOutputStreams
try {
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(CAPECHOServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
Now if you can open telnet and try connecting You'll see a Welcome message.
You must connect with the port you specified and IP Adress.
Welcome!
Well, the connection was lost because we terminated it. Sometimes we would have to program our own TCP client.
In this case, we need a client to request input from the user and send it across the network, receive the capitalised
input.
If the server sends data first, then the client must read the data first.
Socket server;
Scanner key; // Scanner for input
@Override
ostream.writeUTF("Welcome!");
And now run the server and client, You should have an output similar to this
Welcome!
>
import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
//Import all the required resource for this project.
Now we have the basics done. But what if we have an error connecting to the server? We'll want to know when
something goes wrong and get the error message. Let's add some code to catch errors while connecting.
try {
ftp.connect(server, port);
showServerReply(ftp);
int replyCode = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(replyCode)) {
System.out.printIn("Operation failed. Server reply code: " + replyCode)
return;
}
ftp.login(user, pass);
} catch {
showServerReply(ftp);
if (!FTPReply.isPositiveCompletion(replyCode)) {
System.out.printIn("Operation failed. Server reply code: " + replyCode)
return;
}
This checks the reply code to see if there was an error. If there was an error, it will simply print "Operation failed.
Server reply code: " followed by the error code. We also added a try/catch block which we will add to in the next
step. Next, let's also create a function that checks ftp.login() for errors.
This will not just attempt to login to the FTP server, it will also store the result as a boolean.
showServerReply(ftp);
This will check if the server sent us any messages, but we will first need to create the function in the next step.
if (!success) {
System.out.println("Failed to log into the server");
return;
} else {
System.out.println("LOGGED IN SERVER");
}
This statement will check if we logged in successfully; if so, it will print "LOGGED IN SERVER", otherwise it will print
"Failed to log into the server". This is our script so far:
import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
}
}
}
Now next let's create complete the Catch block in case we run into any errors with the whole process.
The completed catch block will now print "Oops! Something went wrong." and the stacktrace if there is an error.
Now our final step is to create the showServerReply() we have been using for a while now.
This function takes an FTPClient as a variable, and calls it "ftp". After that it stores any server replies from the
server in a string array. Next it checks if any messages were stored. If there is any, it prints each of them as
"SERVER: [reply]". Now that we have that function done, this is the completed script:
import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
We first need to create a new FTPClient and try connecting to the server it and logging into it using
.connect(String server, int port) and .login(String username, String password). It is important to
connect and login using a try/catch block in case our code fails to connect with the server. We will also need to
create a function that checks and displays any messages we may receive from the server as we try connecting and
logging in. We will call this function "showServerReply(FTPClient ftp)".
import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
After this, you should now have your FTP server connected to you Java script.
/*
* Note Nashorn is only available for Java-8 onwards
* You can use rhino from ScriptEngineManager.getEngineByName("js");
*/
ScriptEngine engine;
ScriptContext context;
public Bindings scope;
hello world
As you can see the exposed variable x has been printed. Now testing with a file.
print(x);
function test(){
print("hello test.js:test");
}
test();
hello world
hello test.js:test
C++ Example
// define in header
class Singleton {
public:
static Singleton *getInstance();
private:
Singleton() {}
static Singleton *instance;
};
// initialize in .cpp
Singleton* Singleton::instance = 0;
Java Example
public class Singleton {
private static Singleton instance;
private Singleton() {}
class Outer {
class Inner {
public:
Inner(Outer* o) :outer(o) {}
private:
Outer* outer;
};
};
Java
class OuterClass {
class Outer {
class Inner {
...
};
};
Java
class OuterClass {
...
static class StaticNestedClass {
...
}
}
C++
Local Class[ref]
void fun() {
class Test {
/* members of Test class */
};
}
Java
Local Class[ref]
class Test {
void f() {
new Thread(new Runnable() {
public void run() {
doSomethingBackgroundish();
}
}).start();
}
}
// passes a pointer
static void passByPointer(PassIt* ptr) {
ptr->i = 33;
ptr = 0; // better to use nullptr instead if '0'
}
C++ Example
// explicit type case required
Child *pChild = (Child *) &parent;
Java Example
if(mySubClass instanceof SubClass) {
SubClass mySubClass = (SubClass)someBaseClass;
mySubClass.nonInheritedMethod();
}
C++
Java
abstract method
Abstract Class
cannot be instantiated
Java
Interface
no instance fields
C++
Java
very similar to abstract class, but 1) supports multiple inheritance; 2) no instance fields
interface TestInterface {}
import java.io.File;
import java.io.IOException;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
A sequencer can be set to mute one or more of the sequence's tracks during playback so none of the instruments
in those specified play. The following example sets the first track in the sequence to be muted:
import javax.sound.midi.Track;
// ...
A sequencer can play a sequence repeatedly if the loop count is given. The following sets the sequencer to play a
sequence four times and indefinitely:
sequencer.setLoopCount(3);
sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
The sequencer does not always have to play the sequence from the beginning, nor does it have to play the
sequencer.setLoopStartPoint(512);
sequencer.setLoopEndPoint(32768);
sequencer.setTickPosition(8192);
Sequencers can also play a MIDI file at a certain tempo, which can be controlled by specifying the tempo in beats
per minute (BPM) or microseconds per quarter note (MPQ). The factor at which the sequence is played can be
adjusted as well.
sequencer.setTempoInBPM(1250f);
sequencer.setTempoInMPQ(4750f);
sequencer.setTempoFactor(1.5f);
sequencer.close();
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
This code will create a clip and play it continuously once started:
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
// Constructor
public SoundClipTest() {
try {
// Open an audio input stream.
File soundFile = new File("/usr/share/sounds/alsa/Front_Center.wav"); //you could also
get the sound file with an URL
AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
AudioFormat format = audioIn.getFormat();
As such this method is unusable for more complicated sound-sampling. For such purposes using specialized tools is
the better approach.
The following method generates and directly outputs a rectangle-wave of a given frequency in a given volume for a
given duration.
For a more differentiated way to generate different soundwaves sinus calculations and possibly larger sample sizes
are necessary. This results in significantly more complex code and is accordingly omitted here.
It includes extensible print attributes based on the standard attributes specified in the Internet Printing Protocol
(IPP) 1.1 from the IETF Specification, RFC 2911.
the print data content itself (an E-mail, an image, a document etc)
the print data format, called DocFlavor (MIME type + Representation class).
Before creating the Doc object, we need to load our document from somewhere. In the example, we will load an
specific file from the disk:
So now, we have to choose a DocFlavor that matches our content. The DocFlavor class has a bunch of constants to
represent the most usual types of data. Let's pick the INPUT_STREAM.PDF one:
The doc object now can be sent to the print job request (see Creating a print job from a print service).
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
Before choosing one of them and which value each one will have, first we need to build a set of attributes:
pras.add(new Copies(5));
pras.add(MediaSize.ISO_A4);
pras.add(OrientationRequested.PORTRAIT);
pras.add(PrintQuality.NORMAL);
The pras object now can be sent to the print job request (see Creating a print job from a print service).
The Java Print Service API provide some functionalities to get informed about these scenarios. All we have to do is:
When the print job state changes, we will be notified. We can do anything is needed, for example:
In the example bellow, we will log every print job status change:
import javax.print.event.PrintJobEvent;
import javax.print.event.PrintJobListener;
Finally, we can add our print job listener implementation on the print job before the print request itself, as follows:
printJob.addPrintJobListener(new LoggerPrintJobListener());
printJob.print(doc, pras);
Notice that every method has a PrintJobEvent pje argument. We don't use it in this example for simplicity
purposes, but you can use it to explore the status. For example:
pje.getPrintJob().getAttributes();
Will return a PrintJobAttributeSet object instance and you can run them in a for-each way.
Another option to achieve the same goal is extending the PrintJobAdapter class, as the name says, is an adapter
for PrintJobListener. Implementing the interface we compulsorily have to implement all of them. The advantage
of this way it's we need to override only the methods we want. Let's see how it works:
import javax.print.event.PrintJobEvent;
import javax.print.event.PrintJobAdapter;
As the same way in the example implementing the interface PrintJobListener, we add the listener to the print job
before sending it to print:
printJob.addPrintJobListener(new LoggerPrintJobAdapter());
printJob.print(doc, pras);
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
the data that will be printed (see Building the Doc that will be printed)
a set of attributes
After picking-up the right print service instance, we can request the creation of a print job:
printJob.print(doc, pras);
And the pras argument is a PrintRequestAttributeSet interface: a set of PrintRequestAttribute. Are examples
of print request attributes:
By modeling this in an async way via CompletableFuture, we can continue different work in the method (i.e.
calculating packaging costs).
// Let's just say each 200 grams is a new dollar on your shipping costs
int shippingCosts = weightInGrams / 200;
try {
Thread.sleep(2000L); // Now let's simulate some waiting time...
} catch(InterruptedException e) { /* We can safely ignore that */ }
Unit testing is ensuring that a given module behaves as expected. In large-scale applications, ensuring the
appropriate execution of modules in a vacuum is an integral part of ensuring application fidelity.
// Application-level test.
public Example() {
Consumer c = new Consumer();
System.out.println("VALUE = " + c.getVal());
}
// Your Module.
class Consumer {
private Capitalizer c;
public Consumer() {
c = new Capitalizer();
}
public Capitalizer() {
dr = new DataReader();
}
So this example is trivial; DataReader gets the data from a file, passes it to the Capitalizer, which converts all the
characters to upper-case, which then gets passed to the Consumer. But the DataReader is heavily-linked to our
application environment, so we defer testing of this chain until we are ready to deploy a test release.
Now, assume, somewhere along the way in a release, for reasons unknown, the getVal() method in Capitalizer
changed from returning a toUpperCase() String to a toLowerCase() String:
Clearly, this breaks expected behavior. But, because of the arduous processes involved with execution of the
DataReader, we won't notice this until our next test deployment. So days/weeks/months go by with this bug sitting
in our system, and then the product manager sees this, and instantly turns to you, the team leader associated with
the Consumer. "Why is this happening? What did you guys change?" Obviously, you're clueless. You have no idea
what's going on. You didn't change any code that should be touching this; why is it suddenly broken?
Eventually, after discussion between the teams and collaboration, the issue is traced, and the problem solved. But,
it begs the question; how could this have been prevented?
Our reliance upon manual testing let this bug go by unnoticed far too long. We need a way to automate the process
under which bugs are introduced instantly. Not 5 weeks from now. Not 5 days from now. Not 5 minutes from now.
Right now.
You have to appreciate that, in this example, I've expressed one very trivial bug that was introduced and
unnoticed. In an industrial application, with dozens of modules constantly being updated, these can creep in all
over the place. You fix something with one module, only to realize that the very behavior you "fixed" was relied
upon in some manner elsewhere (either internally or externally).
Without rigorous validation, things will creep into the system. It's possible that, if neglected far enough, this will
result in so much extra work trying to fix changes (and then fixing those fixes, etc.), that a product will actually
increase in remaining work as effort is put into it. You do not want to be in this situation.
The second problem noted in our above example is the amount of time it took to trace the bug. The product
manager pinged you when the testers noticed it, you investigated and found that the Capitalizer was returning
The same point I made above about the quantity and difficulty of this trivial example hold here. Obviously anyone
reasonably well-versed with Java could find the introduced problem quickly. But it's often much, much more
difficult to trace and communicate issues. Maybe the Capitalizer team provided you a JAR with no source. Maybe
they're located on the other side of the world, and communication hours are very limited (perhaps to e-mails that
get sent once daily). It can result in bugs taking weeks or longer to trace (and, again, there could be several of these
for a given release).
In order to mitigate against this, we want rigorous testing on as fine a level as possible (you also want coarse-
grained testing to ensure modules interact properly, but that's not our focal point here). We want to rigorously
specify how all outward-facing functionality (at minimum) operates, and tests for that functionality.
Enter unit-testing
Imagine if we had a test, specifically ensuring that the getVal() method of Capitalizer returned a capitalized
string for a given input string. Furthermore, imagine that test was run before we even committed any code. The bug
introduced into the system (that is, toUpperCase() being replaced with toLowerCase()) would cause no issues
because the bug would never be introduced into the system. We would catch it in a test, the developer would
(hopefully) realize their mistake, and an alternative solution would be reached as to how to introduce their intended
effect.
There's some omissions made here as to how to implement these tests, but those are covered in the framework-
specific documentation (linked in the remarks). Hopefully, this serves as an example of why unit testing is
important.
return a;
jar root
- A.class
- B.class
- C.class
- D.class
- META-INF
- versions
- 9
- A.class
- B.class
- 10
- A.class
On JDKs < 9, only the classes in the root entry are visible to the Java runtime.
On a JDK 9, the classes A and B will be loaded from the directory root/META-INF/versions/9, while C and D
will be loaded from the base entry.
On a JDK 10, class A would be loaded from the directory root/META-INF/versions/10.
The --release 9 option tells jar to include everything that follows (the demo package inside the sampleproject-9
directory) inside a versioned entry in the MRJAR, namely under root/META-INF/versions/9. The result is the
following contents:
jar root
- demo
- SampleClass.class
- META-INF
- versions
- 9
- demo
- SampleClass.class
Let us now create a class called Main that prints the URL of the SampleClass, and add it for the Java 9 version:
import java.net.URL;
If we compile this class and re-run the jar command, we get an error:
The reason is that the jar tool prevents adding public classes to versioned entries if they are not added to the base
entries as well. This is done so that the MRJAR exposes the same public API for the different Java versions. Note that
at runtime, this rule is not required. It may be only applied by tools like jar. In this particular case, the purpose of
Main is to run sample code, so we can simply add a copy in the base entry. If the class were part of a newer
implementation that we only need for Java 9, it could be made non-public.
To add Main to the root entry, we first need to compile it to target a pre-Java 9 release. This can be done using the
new --release option of javac:
Running the Main class shows that the SampleClass gets loaded from the versioned directory:
jar root
- demo
- SampleClass.class
- META-INF
- versions
- 9
- demo
- SampleClass.class
package demo;
If the class is compiled and added on the versioned entry for Java 9 in the MRJAR, running it would result in:
The Just-In-Time (JIT) compiler is a component of the Java™ Runtime Environment that improves the performance of
Java applications at run time.
Java programs consists of classes, which contain platform-neutral bytecodes that can be interpreted by a JVM
on many different computer architectures.
At run time, the JVM loads the class files, determines the semantics of each individual bytecode, and
performs the appropriate computation.
The additional processor and memory usage during interpretation means that a Java application
performs more slowly than a native application.
The JIT compiler helps improve the performance of Java programs by compiling bytecodes into native
machine code at run time.
When a method has been compiled, the JVM calls the compiled code of that method directly instead of interpreting
it. Theoretically, if compilation did not require processor time and memory usage, compiling every method could
allow the speed of the Java program to approach that of a native application.
JIT compilation does require processor time and memory usage. When the JVM first starts up, thousands of
methods are called. Compiling all of these methods can significantly affect startup time, even if the program
eventually achieves very good peak performance.
In practice, methods are not compiled the first time they are called. For each method, the JVM maintains a
call count which is incremented every time the method is called.
The JVM interprets a method until its call count exceeds a JIT compilation threshold.
Therefore, often-used methods are compiled soon after the JVM has started, and less-used methods are
compiled much later, or not at all.
The JIT compilation threshold helps the JVM start quickly and still have improved performance.
The threshold has been carefully selected to obtain an optimal balance between startup times and long term
performance.
After a method is compiled, its call count is reset to zero and subsequent calls to the method continue to
increment its count.
When the call count of a method reaches a JIT recompilation threshold, the JIT compiler compiles it a second
time, applying a larger selection of optimizations than on the previous compilation.
This process is repeated until the maximum optimization level is reached.
The busiest methods of a Java program are always optimized most aggressively, maximizing the
performance benefits of using the JIT compiler.
The JIT compiler can also measure operational data at run time, and use that data to improve the quality of
further recompilations.
The JIT compiler can be disabled, in which case the entire Java program will be interpreted. Disabling the
JIT compiler is not recommended except to diagnose or work around JIT compilation problems.
getstatic - Retrieves the value of a static field of a class. In this case, the PrintStream "Out" of System.
ldc - Push a constant onto the stack. In this case, the String "Hello World"
invokevirtual - Invokes a method on a loaded reference on the stack and puts the result on the stack. Parameters
of the method are also taken from the stack.
There are 255 opcodes, but not all of them are implemented yet. A table with all of the current opcodes can be
found here: Java bytecode instruction listings.
There's multiple ways to write and edit bytecode. You can use a compiler, use a library, or use a program.
For writing:
Jasmin
Krakatau
For editing:
Libraries
ASM
Javassist
BCEL - Doesn't support Java 8+
Tools
Bytecode-Viewer
JBytedit
reJ - Doesn't support Java 8+
JBE - Doesn't support Java 8+
There's probably a specific documentation page specificially for bytecode. This page focuses on the modification of
loadClasses(File)
readJar(JarFile, JarEntry, Map)
getNode(byte[])
With these methods loading and changing a jar file becomes a simple matter of changing ClassNodes in a map. In
this example we will replace all Strings in the jar with capitalized ones using the Tree API.
Now that all of the ClassNode's strings have been modified we need to save the changes. In order to save the
changes and have a working output a few things have to be done:
Usage:
/**
* Classloader that loads a class from bytes.
*/
static class ClassDefiner extends ClassLoader {
public ClassDefiner(ClassLoader parent) {
super(parent);
}
SimpleRemapper is an existing class in the ASM library. However it only allows for class names to be changed. If you
wish to rename fields and methods you should create your own implemenation of the Remapper class.
Lets write the first transformer that actually take an hypothetical class "com.my.to.be.instrumented.MyClass" and
add to the instructions of each method a log call.
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
try {
// retrive default Javassist class pool
ClassPool cp = ClassPool.getDefault();
// get from the class pool our class with this qualified name
CtClass cc = cp.get("com.my.to.be.instrumented.MyClass");
// get all the methods of the retrieved class
CtMethod[] methods = cc.getDeclaredMethods()
for(CtMethod meth : methods) {
// The instrumentation code to be returned and injected
final StringBuffer buffer = new StringBuffer();
String name = meth.getName();
// just print into the buffer a log for example
buffer.append("System.out.println(\"Method " + name + " executed\" );");
meth.insertBefore(buffer.toString())
}
// create the byteclode of the class
byteCode = cc.toBytecode();
// remove the CtClass from the ClassPool
cc.detach();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return byteCode;
}
}
Now in order to use this transformer (so that our JVM will call the method transform on each class at load time) we
need to add this instrumentor this with an agent:
import java.lang.instrument.Instrumentation;
Last step to start our first instrumentor experiment is to actually register this agent class to the JVM machine
execution. The easiest way to actually do it is to register it with an option into the shell command:
As we can see the agent/transformer project is added as a jar to the execution of any application named
MyJavaApplication that is supposed to contain a class named "com.my.to.be.instrumented.MyClass" to actually
execute our injected code.
package com.stackoverflow.documentation;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@Service
public class HelloWorldService {
void stuff() {
System.out.println("stuff");
}
}
After compiling the source file, the most simple usage is:
This lists all non-private methods in the class, but that is not particularly useful for most purposes. The following
command is a lot more useful:
Classfile /Users/pivotal/IdeaProjects/stackoverflow-spring-
docs/target/classes/com/stackoverflow/documentation/HelloWorldService.class
Last modified Jul 22, 2016; size 2167 bytes
MD5 checksum 6e33b5c292ead21701906353b7f06330
Compiled from "HelloWorldService.java"
public class com.stackoverflow.documentation.HelloWorldService
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #5.#60 // java/lang/Object."":()V
#2 = Fieldref #61.#62 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #63 // Hello, World!
#4 = Methodref #64.#65 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #66 // java/lang/Object
#6 = Methodref #5.#67 // java/lang/Object.getClass:()Ljava/lang/Class;
#7 = Methodref #68.#69 //
java/lang/Class.getResourceAsStream:(Ljava/lang/String;)Ljava/io/InputStream;
#8 = Methodref #70.#71 // java/io/InputStream.read:([B)I
#9 = Class #72 // java/lang/String
#10 = Methodref #9.#73 // java/lang/String."":([BII)V
#11 = Methodref #70.#74 // java/io/InputStream.close:()V
#12 = Class #75 // java/lang/Throwable
#13 = Methodref #12.#76 //
java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
#14 = Class #77 // java/io/IOException
#15 = Class #78 // java/lang/RuntimeException
#16 = Methodref #79.#80 // java/lang/Exception.printStackTrace:()V
#17 = String #55 // stuff
#18 = Class #81 // com/stackoverflow/documentation/HelloWorldService
void stuff();
descriptor: ()V
flags:
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #17 // String stuff
5: invokevirtual #4 // Method
java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 32: 0
line 33: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/stackoverflow/documentation/HelloWorldService;
}
SourceFile: "HelloWorldService.java"
RuntimeVisibleAnnotations:
0: #59()
int getUserCount();
String getGreetingString();
void stop();
}
And some simple implementation that will let us see how it's working and how we affect it
@Override
public long getSleepTime() {
return sleepTime.get();
}
@Override
public void setSleepTime(long sleepTime) {
this.sleepTime.set(sleepTime);
}
@Override
public int getUserCount() {
return userCount.get();
}
@Override
public void setUserCount(int userCount) {
this.userCount.set(userCount);
}
@Override
public void setGreetingString(String greetingString) {
this.greetingString.set(greetingString);
}
@Override
public void stop() {
this.interrupted.set(true);
}
@Override
public void run() {
while (!interrupted.get()) {
try {
System.out.printf("User %d, %s%n", userCount.incrementAndGet(),
greetingString.get());
Thread.sleep(sleepTime.get());
} catch (InterruptedException ignored) {
}
}
}
}
For simple example with local or remote management, we need to register our MBean:
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
After that we can run our application and connect to it via jConsole, which can be found in your $JAVA_HOME/bin
directory. First, we need to find our local java process with our application
These parameters can be found in Chapter 2 of JMX guides. After that you will be able to connect to your
application via jConsole remotely with jconsole host:port or with specifying host:port or
service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi in jConsole GUI.
Useful links:
JMX guides
JMX Best practices
Java program will be running inside the JVM which is then mapped onto the underlying physical machine. It is one
of programming tool in JDK.
(Byte code is platform-independent code which is run on every platform and Machine code is platform-specific
code which is run in only specific platform such as windows or linux; it depend on execution.)
(Edited)
XJC is a Java SE tool that compiles an XML schema file into fully annotated Java classes.
The following xml schema (xsd) defines a list of users with attributes name and reputation.
<?xml version="1.0"?>
<xs:schema version="1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ns="http://www.stackoverflow.com/users"
elementFormDefault="qualified"
targetNamespace="http://www.stackoverflow.com/users">
<xs:element name="users" type="ns:Users"/>
<xs:complexType name="Users">
<xs:sequence>
<xs:element type="ns:User" name="user" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="User">
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="reputation" use="required">
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:schema>
Using xjc
This requires the path to the xjc tool (JDK binaries) to be in the OS path variable.
xjc schema.xsd
Result files
There will be some additional comments, but basically the java files generated look like this:
package com.stackoverflow.users;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Users", propOrder = {
"user"
})
public class Users {
package com.stackoverflow.users;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "User")
public class User {
package com.stackoverflow.users;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
public ObjectFactory() {
}
package-info.java
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.stackoverflow.com/users",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.stackoverflow.users;
Usage:
-XXaggressive:<param>
<param> Description
Schedules adaptive optimizations earlier and enables new optimizations, which are expected to be the
opt
default in future releases.
Configures the memory system for memory-intensive workloads and sets an expectation to enable large
memory amounts of memory resources to ensure high throughput. JRockit JVM will also use large pages, if
available.
Usage:
-XXallocClearChunks
-XXallocClearChunks=<true | false>
The above is a boolean option and is generally recommended on IA64 systems; ultimately, its use depends upon
the application. If you want to set the size of chunks cleared, combine this option with -XXallocClearChunkSize. If
you use this flag but do not specify a boolean value, the default is true.
Usage:
-XXallocClearChunks -XXallocClearChunkSize=<size>[k|K][m|M][g|G]
Usage:
Objects in Java become a lock as soon as any thread enters a synchronized block on that object. All locks are held
(that is, stayed locked) until released by the locking thread. If the lock is not going to be released very fast, it can be
inflated to a “fat lock.” “Spinning” occurs when a thread that wants a specific lock continuously checks that lock to
see if it is still taken, spinning in a tight loop as it makes the check. Spinning against a fat lock is generally beneficial
although, in some instances, it can be expensive and might affect performance. -XXdisableFatSpin allows you to
turn off spinning against a fat lock and eliminate the potential performance hit.
Usage:
-XXdisableFatSpin
Usage:
-XXdisableFatSpin
Usage:
-XXdumpsize:<size>
<size> Description
none Does not generate a dump file.
On Windows, a small dump file is generated (on Linux a full core dump is generated). A small dump only
small include the thread stacks including their traces and very little else. This was the default in the JRockit JVM 8.1
with service packs 1 and 2, as well as 7.0 with service pack 3 and higher).
Causes a normal dump to be generated on all platforms. This dump file includes all memory except the java
normal
heap. This is the default value for the JRockit JVM 1.4.2 and later.
Includes everything that is in memory, including the Java heap. This option makes -XXdumpSize equivalent
large
to -XXdumpFullState.
Usage:
-XXexitOnOutOfMemory
#include "agent_util.hpp"
//this file can be found in Java SE Development Kit 8u101 Demos and Samples
//see http://download.oracle.com/otn-pub/java/jdk/8u101-b13-demos/jdk-8u101-windows-x64-demos.zip
//jdk1.8.0_101.zip!\demo\jvmti\versionCheck\src\agent_util.h
/*
* Struct used for jvmti->SetTag(object, <pointer to tag>);
* http://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#SetTag
*
*/
typedef struct Tag
{
jlong referrer_tag;
jlong size;
char* classSignature;
jint hashCode;
} Tag;
/*
* Utility function: jlong -> Tag*
*/
static Tag* pointerToTag(jlong tag_ptr)
{
if (tag_ptr == 0)
{
return new Tag();
}
return (Tag*)(ptrdiff_t)(void*)tag_ptr;
}
/*
* Utility function: Tag* -> jlong
*/
static jlong tagToPointer(Tag* tag)
{
return (jlong)(ptrdiff_t)(void*)tag;
}
/*
* Heap 1.0 Callback
* http://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#jvmtiObjectReferenceCallback
*/
static jvmtiIterationControl JNICALL heabObjectReferencesCallback(
jvmtiObjectReferenceKind reference_kind,
jlong class_tag,
jlong size,
jlong* tag_ptr,
jlong referrer_tag,
jint referrer_index,
void* user_data)
{
return JVMTI_ITERATION_CONTINUE;
}
/*
* Main function for demonstration of Iterate Over Objects Reachable From Object
*
http://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#IterateOverObjectsReachableFromObject
*
*/
void iterateOverObjectHeapReferences(jvmtiEnv* jvmti, JNIEnv* env, jobject object)
{
std::vector<jlong> tag_ptr_list;
if (tag_ptr_list.size() > 0)
{
jint found_count = 0;
jlong* tags = &tag_ptr_list[0];
jobject* found_objects;
jlong* found_tags;
/*
* collect all tagged object (via *tag_ptr = pointer to tag )
* see http://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#GetObjectsWithTags
*/
jvmti->GetObjectsWithTags(tag_ptr_list.size(), tags, &found_count, &found_objects,
&found_tags);
stdout_message("found %d objects\n", found_count);
char* classSignature;
jclass found_object_class = env->GetObjectClass(found_object);
jint hashCode;
/*
* Getting hash code for found_object
* see http://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#GetObjectHashCode
*/
jvmti->GetObjectHashCode(found_object, &hashCode);
if (t->referrer_tag != 0)
{
stdout_message("referrer object %s#%d --> object %s#%d (size: %2d)\n",
rt->classSignature, rt->hashCode, t->classSignature, t->hashCode, t->size);
}
}
}
}
jvmtiEnv* jvmti;
/* Get JVMTI environment */
vm->GetEnv(reinterpret_cast<void **>(&jvmti), JVMTI_VERSION);
jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, nullptr);
return JNI_OK;
}
Note that PermGen was removed in Java 8, and if you attempt to set the PermGen size the option will be ignored
(with a warning message).
If you don't specify Heap and Stack sizes explicitly, the JVM will use defaults that are calculated in a version and
platform specific way. This may result in your application using too little or too much memory. This is typically OK
for thread stacks, but it can be problematic for a program that uses a lot of memory.
The <size> parameter can be a number of bytes, or can have a suffix of k, m or g. The latter specify the size in
kilobytes, megabytes and gigabytes respectively.
Examples:
The -XX:+printFlagsFinal option can be used to print the values of all flags before starting the JVM. This can be
used to print the defaults for the heap and stack size settings as follows:
For Windows:
In a language like C++, the application program is responsible for managing the memory used by dynamically
allocated memory. When an object is created in the C++ heap using the new operator, there needs to be a
corresponding use of the delete operator to dispose of the object:
If program forgets to delete an object and just "forgets" about it, the associated memory is lost to the
application. The term for this situation is a memory leak, and it too much memory leaks an application is
liable to use more and more memory, and eventually crash.
On the other hand, if an application attempts to delete the same object twice, or use an object after it has
been deleted, then the application is liable to crash due to problems with memory corruption
In a complicated C++ program, implementing memory management using new and delete can be time consuming.
Indeed, memory management is a common source of bugs.
Java takes a different approach. Instead of an explicit delete operator, Java provides an automatic mechanism
known as garbage collection to reclaim the memory used by objects that are no longer needed. The Java runtime
system takes responsibility for finding the objects to be disposed of. This task is performed by a component called a
garbage collector, or GC for short.
At any time during the execution of a Java program, we can divide the set of all existing objects into two distinct
subsets1:
A reachable object is any object that can be accessed in any potential continuing computation from
any live thread.
In practice, this means that there is a chain of references starting from an in-scope local variable or a static
variable by which some code might be able to reach the object.
Any objects that are unreachable are eligible for garbage collection. This does not mean that they will be garbage
collected. In fact:
The one thing that the JLS guarantees is that no reachable objects will ever be garbage collected.
First of all, nothing specifically happens when an object becomes unreachable. Things only happen when the
garbage collector runs and it detects that the object is unreachable. Furthermore, it is common for a GC run to not
detect all unreachable objects.
When the GC detects an unreachable object, the following events can occur.
1. If there are any Reference objects that refer to the object, those references will be cleared before the object
is deleted.
2. If the object is finalizable, then it will be finalized. This happens before the object is deleted.
3. The object can be deleted, and the memory it occupies can be reclaimed.
Note that there is a clear sequence in which the above events can occur, but nothing requires the garbage collector
to perform the final deletion of any specific object in any specific time-frame.
Let us examine what happens when test() is called. Statements T1, T2 and T3 create Node objects, and the objects
are all reachable via the n1, n2 and n3 variables respectively. Statement T4 assigns the reference to the 2nd Node
object to the next field of the first one. When that is done, the 2nd Node is reachable via two paths:
n2 -> Node2
In statement T5, we assign null to n2. This breaks the first of the reachability chains for Node2, but the second one
remains unbroken, so Node2 is still reachable.
In statement T6, we assign null to n3. This breaks the only reachability chain for Node3, which makes Node3
unreachable. However, Node1 and Node2 are both still reachable via the n1 variable.
Finally, when the test() method returns, its local variables n1, n2 and n3 go out of scope, and therefore cannot be
accessed by anything. This breaks the remaining reachability chains for Node1 and Node2, and all of the Node objects
are nor unreachable and eligible for garbage collection.
1 - This is a simplification that ignores finalization, and Reference classes. 2 - Hypothetically, a Java implementation
could do this, but the performance cost of doing this makes it impractical.
When you push an object and then immediately pop it, there will still be a reference to the object in the stack array.
The logic of the stack implementation means that that reference cannot be returned to a client of the API. If an
object has been popped then we can prove that it cannot "be accessed in any potential continuing computation from
any live thread". The problem is that a current generation JVM cannot prove this. Current generation JVMs do not
consider the logic of the program in determining whether references are reachable. (For a start, it is not practical.)
But setting aside the issue of what reachability really means, we clearly have a situation here where the NaiveStack
implementation is "hanging onto" objects that ought to be reclaimed. That is a memory leak.
A common strategy for improving service performance is to cache results. The idea is that you keep a record of
common requests and their results in an in-memory data structure known as a cache. Then, each time a request is
made, you lookup the request in the cache. If the lookup succeeds, you return the corresponding saved results.
This strategy can be very effective if implemented properly. However, if implemented incorrectly, a cache can be a
memory leak. Consider the following example:
The problem with this code is that while any call to doRequest could add a new entry to the cache, there is nothing
to remove them. If the service is continually getting different tasks, then the cache will eventually consume all
available memory. This is a form of memory leak.
One approach to solving this is to use a cache with a maximum size, and throw out old entries when the cache
exceeds the maximum. (Throwing out the least recently used entry is a good strategy.) Another approach is to build
the cache using WeakHashMap so that the JVM can evict cache entries if the heap starts getting too full.
@Override
protected void finalize() throws Throwable {
// Cleanup code
}
}
The caveats above mean that it is a bad idea to rely on the finalize method to perform cleanup (or other) actions
that must be performed in a timely fashion. Over reliance on finalization can lead to storage leaks, memory leaks
and other problems.
In short, there are very few situation where finalization is actually a good solution.
Normally, an object is deleted after it has been finalized. However, this doesn't happen all of the time. Consider the
following example1:
When an instance of CaptainJack becomes unreachable and the garbage collector attempts to reclaim it, the
finalize() method will assign a reference to the instance to the notDeadYet variable. That will make the instance
reachable once more, and the garbage collector won't delete it.
Answer: No.
The catch is the JVM will only run a finalizer on an object once in its lifetime. If you assign null to notDeadYet
causing a resurected instance to be unreachable once more, the garbage collector won't call finalize() on the
object.
1 - See https://en.wikipedia.org/wiki/Jack_Harkness.
System.gc();
However, Java does not guarantee that the Garbage Collector has run when the call returns. This method simply
"suggests" to the JVM (Java Virtual Machine) that you want it to run the garbage collector, but does not force it to do
so.
It is generally considered a bad practice to attempt to manually trigger garbage collection. The JVM can be run with
the -XX:+DisableExplicitGC option to disable calls to System.gc(). Triggering garbage collection by calling
System.gc() can disrupt normal garbage management / object promotion activities of the specific garbage
collector implementation in use by the JVM.
"Programmers waste enormous amounts of time thinking about, or worrying about, the speed of
noncritical parts of their programs, and these attempts at efficiency actually have a strong negative
impact when debugging and maintenance are considered. We should forget about small efficiencies, say
about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our
opportunities in that critical 3%."
source
Bearing that sage advice in mind, here is the recommended procedure for optimizing programs:
1. First of all, design and code your program or library with a focus on simplicity and correctness. To start with,
don't spend much effort on performance.
2. Get it to a working state, and (ideally) develop unit tests for the key parts of the codebase.
3. Develop an application level performance benchmark. The benchmark should cover the performance critical
aspects of your application, and should perform a range of tasks that are typical of how the application will
be used in production.
5. Compare the measured performance against your criteria for how fast the application needs to be. (Avoid
unrealistic, unattainable or unquantifiable criteria such as "as fast as possible".)
6. If you have met the criteria, STOP. You job is done. (Any further effort is probably a waste of time.)
8. Examine the profiling results and pick the biggest (unoptimized) "performance hotspots"; i.e. sections of the
code where the application seems to be spending the most time.
9. Analyse the hotspot code section to try to understand why it is a bottleneck, and think of a way to make it
faster.
11. Rerun the benchmark to see if the code change has improved the performance:
Eventually you will get to a point where the application is either fast enough, or you have considered all of the
significant hotspots. At this point you need to stop this approach. If a section of code is consuming (say) 1% of the
overall time, then even a 50% improvement is only going to make the application 0.5% faster overall.
Clearly, there is a point beyond which hotspot optimization is a waste of effort. If you get to that point, you need to
But wherever possible, rely on tools and measurement rather than instinct to direct your optimization effort.
myString += "foo";
The problem is that each + creates a new String (usually, since new compilers optimize some cases). A possible
optimization can be made using StringBuilder or StringBuffer:
If you build long Strings often (SQLs for example), use a String building API.
The third point is mostly about experience and extensive research, and of course raw tips that will show up on this
page and others, like this.
The easiest way to get JHM into your project - is to use maven and shade plugin. Also you can see pom.xml from JHM
examples.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>/benchmarks</finalName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openjdk.jmh.Main</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
package benchmark;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
@State(Scope.Thread)
public class CollectionFinderBenchmarkTest {
private static final int SET_SIZE = 10000;
@Setup
public void setupCollections() {
hashSet = new HashSet<>(SET_SIZE);
treeSet = new TreeSet<>();
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testHashSet(Blackhole blackhole) {
blackhole.consume(hashSet.contains(stringToFind));
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testTreeSet(Blackhole blackhole) {
blackhole.consume(treeSet.contains(stringToFind));
}
}
Please keep in mind this blackhole.consume(), we'll get back to it later. Also we need main class for running
benchmark:
package benchmark;
new Runner(options).run();
}
}
And we're all set. We just need to run mvn package (it will create benchmarks.jar in your /target folder) and run
our benchmark test:
And after some warmup and calculation iterations, we will have our results:
About that blackhole.consume(). If your calculations do not change the state of your application, java will most
likely just ignore it. So, in order to avoid it, you can either make your benchmark methods return some value, or use
Blackhole object to consume it.
You can find more information about writing proper benchmarks in Aleksey Shipilëv's blog, in Jacob Jenkov's blog
and in java-performance blog: 1, 2.
Requirement: secrete key and Access key for s3 bucket where you wanna upload your file.
code: DocumentController.java
@RestController
@RequestMapping("/api/v2")
public class DocumentController {
System.out.println("*****************************");
return url;
return null;
var settings = {
"async": true,
"crossDomain": true,
"url": "http://url/",
"method": "POST",
"headers": {
"cache-control": "no-cache"
},
"processData": false,
"contentType": false,
"mimeType": "multipart/form-data",
"data": form
}
$.ajax(settings).done(function (response) {
console.log(response);
});
4. Go to the end of the file and add (replace ? with your own values as needed or remove the flag that does not
apply): java.extended.properties=-javaagent:/opt/appd/current/appagent/javaagent.jar -
Dappdynamics.http.proxyHost=? -Dappdynamics.http.proxyPort=? -Dappdynamics.agent.applicationName=?
-Dappdynamics.agent.tierName=? -Dappdynamics.agent.nodeName=%tibco.deployment% -
Dappdynamics.controller.ssl.enabled=? -Dappdynamics.controller.sslPort=? -Dappdynamics.agent.logs.dir=? -
Dappdynamics.agent.runtime.dir=? -Dappdynamics.controller.hostName=? -Dappdynamics.controller.port=?
-Dappdynamics.agent.accountName=? -Dappdynamics.agent.accountAccessKey=?
5. Save file and redeploy. All your applications should now be instrumented automatically at deployment time.
Setup steps
2. In the navigation pane on the left right click on This PC (or Computer for older Windows versions). There is a
shorter way without using the explorer in actual Windows versions: Just press Win + Pause
3. In the newly opened Control Panel window, left click Advanced System Settings which should be in the top left
corner. This will open the System Properties window.
Alternatively, type SystemPropertiesAdvanced (case insensitive) in the Run ( Win + R ), and hit Enter .
4. In the Advanced tab of System Properties select the Environment Variables... button in the lower right
corner of the window.
5. Add a New System Variable by clicking the New... button in System Variables with the name JAVA_HOME
and whose value is the path to the directory where the JDK was installed. After entering these values, press
OK .
7. CAUTION: Windows relies on Path to find important programs. If any or all of it is removed,
Windows may not be able to function properly. It must be modified to allow Windows to run the
JDK. With this in mind ,click the "Edit..." button with the Path variable selected. Add
%JAVA_HOME%\bin; to the beginning of the Path variable.
It is better to append at the begining of the line because Oracle's software used to register their own version of Java
in Path - This will cause your version to be ignored if it occurs after Oracle's declaration.
1. Open the command prompt by clicking Start then typing cmd and pressing Enter.
2. Enter javac -version into the prompt. If it was successful, then the version of the JDK will be printed to the
screen.
Note: If you have to try again, close the prompt before checking your work. This will force windows to get the new
version of Path.
JDK and/or JRE releases for OpenJDK or Oracle can be installed using the package manager on most mainstream
Linux distribution. (The choices that are available to you will depend on the distro.)
As a general rule, the procedure is to open terminal window and run the commands shown below. (It is assumed
that you have sufficient access to run commands as the "root" user ... which is what the sudo command does. If you
do not, then please talk to your system's administrators.)
Using the package manager is recommended because it (generally) makes it easier to keep your Java installation up
to date.
If you prefer to create the .deb file yourself from the .tar.gz file downloaded from Oracle, do the following
(assuming you've downloaded the .tar.gz to ./<jdk>.tar.gz):
dnf, Fedora
In recent Fedora releases, there are no packages for installing Java 7 and earlier.
Gentoo Linux
The Gentoo Java guide is maintained by the Gentoo Java team and keeps an updated wiki page including the correct
portage packages and USE flags needed.
1. Download the appropriate Oracle archive ("tar.gz") file for the desired release from the Oracle Java
downloads site.
2. Change directory to the place where you want to put the installation;
1. Retrieve the required RPM file for the desired release from the Oracle Java downloads site.
Java 7 and Java 8 for macOS are available from Oracle. This Oracle page answers a lot of questions about Java for
Mac. Note that Java 7 prior to 7u25 have been disabled by Apple for security reasons.
In general, Oracle Java (Version 7 and later) requires an Intel-based Mac running macOS 10.7.3 or later.
Java 7 & 8 JDK and JRE installers for macOS can be downloaded from Oracle’s website:
After downloading the relevant package, double click on the package and go through the normal installation
process. A JDK should get installed here:
/Library/Java/JavaVirtualMachines/<version>.jdk/Contents/Home
Command-Line Switching
When Java is installed, the installed version is automatically set as the default. To switch between different, use:
The following functions can be added to the ~/.bash_profile (If you use the default Bash shell) for ease of use:
function java_version {
echo 'java -version';
}
function java_set {
if [[ $1 == "6" ]]
then
export JAVA_HOME='/usr/libexec/java_home -v 1.6';
echo "Setting Java to version 6..."
echo "$JAVA_HOME"
elif [[ $1 == "7" ]]
then
export JAVA_HOME='/usr/libexec/java_home -v 1.7';
echo "Setting Java to version 7..."
echo "$JAVA_HOME"
elif [[ $1 == "8" ]]
then
On older versions of macOS (10.11 El Capitan and earlier), Apple's release of Java 6 comes pre-installed. If installed,
it can be be found at this location:
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
Note that Java 6 passed its end-of-life long ago, so upgrading to a newer version is recommended. There is more
information on reinstalling Apple Java 6 on the Oracle website.
An alternate way to install Java on Windows using the command prompt is to use Chocolately:
2. Open a cmd instance, for example hit Win + R and then type "cmd" in the "Run" window followed by an
enter.
3. In your cmd instance, run the following command to download and install a Java 8 JDK:
There are instances where you might want to install JDK/JRE on a system with limited privileges like a VM or you
might want to install and use multiple versions or architectures (x64/x86) of JDK/JRE. The steps remain same till the
point you download the installer (.EXE). The steps after that are as follows (The steps are applicable for JDK/JRE 7
and above, for older versions they are slightly different in the names of folders and files):
1. Move the file to an appropriate location where you would want your Java binaries to reside permanently.
3. With 7-Zip, extract the files from the Java installer EXE to the location.
4. Open up command prompt there by holding Shift and Right-Clicking in the folder in explorer or navigate
to that location from anywhere.
cd .rsrc\JAVA_CAB10
extrac32 111
6. This will create a tools.zip file in that location. Extract the tools.zip with 7-Zip so that the files inside it are
now created under tools in the same directory.
cd tools
8. Wait for the command to complete. Copy the contents of tools to the location where you want your binaries
to be.
This way, you can install any versions of JDK/JRE you need to be installed simultaneously.
Many Linux distributions use the alternatives command for switching between different versions of a command.
You can use this for switching between different versions of Java installed on a machine.
1. In a command shell, set $JDK to the pathname of a newly installed JDK; e.g.
$ JDK=/Data/jdk1.8.0_67
2. Use alternatives --install to add the commands in the Java SDK to alternatives:
And so on.
Now you can switch between different versions of a Java command as follows:
Selection Command
-----------------------------------------------
*+ 1 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.101-1.b14.fc23.x86_64/bin/javac
For more information on using alternatives, refer to the alternatives(8) manual entry.
Arch Linux based installs come with the command archlinux-java to switch java versions.
Eg:
However for serious development work it is recommended that you also use the following:
In general, the recommended Java SE release for use will be the latest update for the latest public version.
Currently, this means the latest available Java 8 release. Java 9 is due for public release in 2017. (Java 7 has passed
its End Of Life and the last public release was in April 2015. Java 7 and earlier releases are not recommended.)
This recommendation applies for all new Java development, and anyone learning Java. It also applies to people who
just want to run Java software provided by a third-party. Generally speaking, well-written Java code will work on a
newer release of Java. (But check the software's release notes, and contact the author / supplier / vendor if you
have doubts.)
1 - It appears that Oracle intends to break from their previous practice of using a "semantic version number"
scheme in the Java version strings. It remains to be seen if they will follow through with this.
The "SE" in the marketing names refers to Standard Edition. This is the base release for running Java on most
laptops, PCs and servers (apart from Android).
There are two other official editions of Java: "Java ME" is the Micro Edition, and "Java EE" is the Enterprise Edition.
The Android flavor of Java is also significantly different from Java SE. Java ME, Java EE and Android Java are outside
of the scope of this Topic.
The full version number for a Java release looks like this:
1.8.0_101-b13
This says JDK 1.8.0, Update 101, Build #13. Oracle refers to this in the release notes as:
The update number is important -- Oracle regularly issue updates to a major release with security patches, bug
fixes and (in some cases) new features. The build number is usually irrelevant. Note that Java 8 and Java 1.8 refer to
the same thing; Java 8 is just the "marketing" name for Java 1.8.
Section A.9: Installing Oracle Java on Linux with latest tar file
Follow the below steps to install Oracle JDK from the latest tar file:
1. Download the latest tar file from here - Current latest is Java SE Development Kit 8u112.
sudo su
ls /opt/jdk
and
java -version
Expected output:
$ java -version
$ javac -version
These commands print out the version information for the JRE and JDK (respectively) that are on your shell's
command search path. Look for the JDK / JRE version string.
If either of the above commands fails, saying "command not found", then the JRE or JDK is not on the search
path at all; go to Configuring PATH directly below.
If either of the above commands displays a different version string to what you were expecting, then either
your search path or the "alternatives" system needs adjusting; go to Checking Alternatives
If the correct version strings are displayed, you are nearly done; skip to Checking JAVA_HOME
If there is no java or javac on the search path at the moment, then the simple solution is to add it to your search
path.
First, find where you installed Java; see Where was Java installed? below if you have doubts.
JAVA_HOME=<installation directory>
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME
export PATH
... replacing <installation directory> with the pathname for your Java installation directory. Note that the above
assumes that the installation directory contains a bin directory, and the bin directory contains the java and javac
commands that you are trying to use.
Next, source the file that you just edited, so that the environment variables for your current shell are updated.
$ source ~/.bash_profile
Next, repeat the java and javac version checks. If there are still problems, use which java and which javac to
verify that you have updates the environment variables correctly.
Finally, logout and login again so that the updated environment variables ptopagate to all of your shells. You should
now be done.
Checking Alternatives
If java -version or javac -version worked but gave an unexpected version number, you need to check where the
commands are coming from. Use which and ls -l to find this out as follows:
$ ls -l `which java`
then the alternatives version switching is being used. You needs to decide whether to continue using it, or simply
override it by setting the PATH directly.
If you are having difficultly finding the installation directory, We suggest that you use find (or slocate) to find the
command. For example:
This gives you the pathnames for all files called java on your system. (The redirection of standard error to
"/dev/null" suppresses messages about files and directories that you can't access.)
Java Runtime Environment or JRE distributions consist of the set of libraries and tools needed to run and manage
Java applications. The tools in a typical modern JRE include:
The java command for running a Java program in a JVM (Java Virtual Machine)
The jjs command for running the Nashorn Javascript engine.
The keytool command for manipulating Java keystores.
The policytool command for editing security sandbox security policies.
The pack200 and unpack200 tools for packing and unpacking "pack200" file for web deployment.
The orbd, rmid, rmiregistry and tnameserv commands that support Java CORBA and RMI applications.
"Desktop JRE" installers include a Java plugin suitable for some web browser. This is deliberately left out of "Server
JRE" installers.linux syscall read benchmarku
From Java 7 update 6 onwards, JRE installers have included JavaFX (version 2.2 or later).
A Java Development Kit or JDK distribution includes the JRE tools, and additional tools for developing Java software.
The additional tools typically include:
The javac command, which compiles Java source code (".java") to bytecode files (".class").
The tools for creating JAR files such as jar and jarsigner
Development tools such as:
appletviewer for running applets
idlj the CORBA IDL to Java compiler
javah the JNI stub generator
native2ascii for character set conversion of Java source code
schemagen the Java to XML schema generator (part of JAXB)
serialver generate Java Object Serialization version string.
the wsgen and wsimport support tools for JAX-WS
Diagnostic tools such as:
jdb the basic Java debugger
jmap and jhat for dumping and analysing a Java heap.
jstack for getting a thread stack dump.
javap for examining ".class" files.
Application management and monitoring tools such as:
jconsole a management console,
jstat, jstatd, jinfo and jps for application monitoring
A typical Sun / Oracle JDK installation also includes a ZIP file with the source code of the Java libraries. Prior to Java
6, this was the only publicly available Java source code.
The following table provides the timeline for the significant major versions of the Java SE platform.
Footnotes:
1. The links are to online copies of the respective releases documentation on Oracle's website. The
documentation for many older releases no longer online, though it typically can be downloaded from the
Oracle Java Archives.
2. Most historical versions of Java SE have passed their official "end of life" dates. When a Java version passes
this milestone, Oracle stop providing free updates for it. Updates are still available to customers with support
contracts.
Source:
Source:
There are several Java platforms. Many developers, even long-time Java programming language developers, do not
understand how the different platforms relate to each other.
Java FX
All Java platforms consist of a Java Virtual Machine (VM) and an application programming interface (API). The Java
Virtual Machine is a program, for a particular hardware and software platform, that runs Java technology
applications. An API is a collection of software components that you can use to create other software components
or applications. Each Java platform provides a virtual machine and an API, and this allows applications written for
that platform to run on any compatible system with all the advantages of the Java programming language:
platform-independence, power, stability, ease-of-development, and security.
Java SE
When most people think of the Java programming language, they think of the Java SE API. Java SE's API provides the
core functionality of the Java programming language. It defines everything from the basic types and objects of the
Java programming language to high-level classes that are used for networking, security, database access, graphical
user interface (GUI) development, and XML parsing.
In addition to the core API, the Java SE platform consists of a virtual machine, development tools, deployment
technologies, and other class libraries and toolkits commonly used in Java technology applications.
Java EE
The Java EE platform is built on top of the Java SE platform. The Java EE platform provides an API and runtime
environment for developing and running large-scale, multi-tiered, scalable, reliable, and secure network
applications.
The Java ME platform provides an API and a small-footprint virtual machine for running Java programming language
applications on small devices, like mobile phones. The API is a subset of the Java SE API, along with special class
libraries useful for small device application development. Java ME applications are often clients of Java EE platform
services.
Java FX
Java FX technology is a platform for creating rich internet applications written in Java FX ScriptTM. Java FX Script is a
statically-typed declarative language that is compiled to Java technology bytecode, which can then be run on a Java
VM. Applications written for the Java FX platform can include and link to Java programming language classes, and
may be clients of Java EE platform services.
Note that the -classpath (or -cp) option takes precedence over the CLASSPATH environment variable.
3. The classpath for an executable JAR file is specified using the Class-Path element in MANIFEST.MF:
Note that this only applies when the JAR file is executed like this:
In this mode of execution, the -classpath option and the CLASSPATH environment variable will be ignored,
even if the JAR file has no Class-Path element.
If no classpath is specified, then the default classpath is the selected JAR file when using java -jar, or the current
directory otherwise.
Related:
https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html
someFolder/*
This tells the JVM to add all JAR and ZIP files in the someFolder directory to the classpath. This syntax can be used in
a -cp argument, a CLASSPATH environment variable, or a Class-Path attribute in an executable JAR file's manifest
file.See Setting the Class Path: Class Path Wild Cards for examples and caveats.
1. Classpath wildcards were first introduced in Java 6. Earlier versions of Java do not treat "*" as a wildcard.
2. You cannot put other characters before or after the ""; e.g. "someFolder/.jar" is not a wildcard.
3. A wildcard matches only files with the suffix ".jar" or ".JAR". ZIP files are ignored, as are JAR files with a
different suffixes.
4. A wildcard matches only JAR files in the directory itself, not in its subdirectories.
5. When a group of JAR files is matched by a wildcard entry, their relative order on the classpath is not specified.
program.jar
|
\-com
\-project
|
|-file.txt
\-Test.class
And we want to access the contents of file.txt from the Test class. We can do so by asking the classloader :
InputStream is = Test.class.getClassLoader().getResourceAsStream("com/project/file.txt");
By using the classloader, we need to specify the fully qualified path of our resource (each package).
InputStream is = Test.class.getResourceAsStream("file.txt");
Using the class object, the path is relative to the class itself. Our Test.class being in the com.project package, the
same as file.txt, we do not need to specify any path at all.
We can, however, use absolute paths from the class object, like so :
is = Test.class.getResourceAsStream("/com/project/file.txt");
For a classpath specified on the command line (e.g. -classpath) or as an environment variable, the entries
must be separated with ; (semicolon) characters on Windows, or : (colon) characters on other platforms
(Linux, UNIX, MacOSX and so on).
For the Class-Path element in a JAR file's MANIFEST.MF, use a single space to separate the entries.
(The details may depend on the command shell that you use.)
When the classpath is specified in a JAR file's a "MANIFEST.MF" file, URL encoding must be used.
Here is an example which selects the correct SWT native JAR for your platform, adds all your application's JARs and
then invokes the real main() method: Create cross platform Java SWT Application
For classes in the default package, the pathnames are simple filenames.
For classes in a named package, the package name components map to directories.
For named nested and inner classes, the filename component is formed by joining the class names with a $
character.
For anonymous inner classes, numbers are used in place of names.
Under normal circumstances, you don't need to concern yourself with this. By default, commands like java, javac
and so on will use the appropriate versions of the runtime libraries.
Very occasionally, it is necessary to override the normal behavior of the Java runtime by using an alternative version
The java command provides the following -X options for modifying the bootstrap classpath:
-Xbootclasspath:<path> replaces the current boot classpath with the path provided.
-Xbootclasspath/a:<path> appends the provided path to the current boot classpath.
-Xbootclasspath/p:<path> prepends the provided path to the current boot classpath.
Note that when use the bootclasspath options to replace or override a Java class (etcetera), you are technically
modifying Java. There may be licensing implications if you then distribute your code. (Refer to the terms and
conditions of the Java Binary License ... and consult a lawyer.)
The classpath is a form of search path which specifies a sequence of locations to look for resources. In a standard
classpath, these places are either, a directory in the host file system, a JAR file or a ZIP file. In each cases, the
location is the root of a namespace that will be searched.
The standard procedure for searching for a class on the classpath is as follows:
1. Map the class name to a relative classfile pathname RP. The mapping for class names to class filenames is
described elsewhere.
The procedure for searching for a resource on the classpath depends on whether the resource path is absolute or
relative. For an absolute resource path, the procedure is as above. For a relative resource path resolved using
Class.getResource or Class.getResourceAsStream, the path for the classes package is prepended prior to
searching.
(Note these are the procedures implemented by the standard Java classloaders. A custom classloader might
perform the search differently.)
package com.example;
defaults.load(defaultsStream);
}
return defaults;
}
}
package com.example;
The last three steps are typically accomplished by passing the URL to a library method or constructor to load the
resource. You will typically use a getResource method in this case. It is also possible to read the resource data in
application code. You will typically use getResourceAsStream in this case.
As the Classpath examples describe, a JVM's classpath defines a namespace by overlaying the namespaces of the
directories and JAR or ZIP files in the classpath. When an absolute path is resolved, it the classloaders interpret the
initial / as meaning the root of the namespace. By contrast, a relative path may be resolved relative to any "folder"
in the namespace. The folder used will depend on the object that you use to resolve the path.
A resource can be located using either a Class object or a ClassLoader object. A Class object can resolve relative
paths, so you will typically use one of these if you have a (class) relative resource. There are a variety of ways to
obtain a Class object. For example:
A class literal will give you the Class object for any class that you can name in Java source code; e.g.
String.class gives you the Class object for the String type.
The Object.getClass() will give you the Class object for the type od any object; e.g. "hello".getClass() is
another way to get Class of the String type.
The Class.forName(String) method will (if necessary) dynamically load a class and return its Class object;
e.g. Class.forName("java.lang.String").
A ClassLoader object is typically obtained by calling getClassLoader() on a Class object. It is also possible to get
hold of the JVM's default classloader using the static ClassLoader.getSystemClassLoader() method.
Once you have a Class or ClassLoader instance, you can find a resource, using one of the following methods:
Methods Description
ClassLoader.getResource(path) Returns a URL which represents the location of the resource with the
ClassLoader.getResources(path) given path.
ClassLoader.getResources(path) Returns an Enumeration<URL> giving the URLs which can be used to
Class.getResources(path) locate the foo.bar resource; see below.
ClassLoader.getResourceAsStream(path) Returns an InputStream from which you can read the contents of the
Class.getResourceStream(path) foo.bar resource as a sequence of bytes.
Notes:
The main difference between the ClassLoader and Class versions of the methods is in the way that relative
paths are interpreted.
The Class methods resolve a relative path in the "folder" that corresponds to the classes package.
The ClassLoader methods treat relative paths as if they were absolute; i.e. the resolve them in the
"root folder" of the classpath namespace.
If the requested resource (or resources) cannot be found, the getResource and
getResourceAsStreammethods returnnull, and thegetResourcesmethods return an emptyEnumeration`.
The URLs returned will be resolvable using URL.toStream(). They could be file: URLs or other conventional
URLs, but if the resource resides in a JAR file, they will be jar: URLs that identify the JAR file and a specific
resource within it.
META-INF/MANIFEST.MF
META-INF/beans.xml (CDI Spec)
ServiceLoader properties containing implementation providers
To get access to all of these resources in different jars, one has to use a ClassLoader, which has a method for this.
The returned Enumeration can be conveniently converted to a List using a Collections function.