Applying the final Modifier
variable final means the value cannot be changed after it is assigned.method or class final means it cannot be overridden or extendedDECLARING FINAL LOCAL VARIABLES
Just because a variable reference is marked final does not mean the object associated with it cannot be modified.
Consider the following code snippet:
final StringBuilder cobra = new StringBuilder();
cobra.append("Hssssss");
cobra.append("Hssssss!!!");In the cobra example, the object reference is constant, but that doesn’t mean the data in the class is constant.
ADDING FINAL TO INSTANCE AND STATIC VARIABLES
instance final variables
- declared
- instance initializers
- cosntructors
static final variables
- declared
- instance initializers
WRITING FINAL METHODS
MARKING CLASSES FINAL
final modifier can be applied to class declarations as well.
A final class is one that cannot be extended.
implicit modifier
a modifier that is inserted automatically by the compiler is referred to as an implicit modifier
Working with Enums
CREATING SIMPLE ENUMS
public enum Season {
WINTER, SPRING, SUMMER, FALL
}Enum values are considered constants and are commonly written using snake case, often stylized as snake_case.
snake_case
Season s = Season.SUMMER; System.out.println(Season.SUMMER); // SUMMER System.out.println(s == Season.SUMMER); // true
toString() is called.equals() or == to compare enums, since each enum value is initialized only once in the Java Virtual Machine (JVM).for(Season season: Season.values()) {
System.out.println(season.name() + " " + season.ordinal());
}values() method to get an array of all of the values.name() return string, value nameordinal() return int, the order of value declaredThe output shows that each enum value has a corresponding int value, and the values are listed in the order in which they are declared.
WINTER 0 SPRING 1 SUMMER 2 FALL 3
if ( Season.SUMMER == 2) {} // DOES NOT COMPILEYou can’t compare an int and enum value directly anyway since an enum is a type, like a Java class, and not a primitive int.
Season s = Season.valueOf("SUMMER"); // SUMMERretrieving an enum value from a String using the valueOf() method.
Season t = Season.valueOf("summer"); // Throws an exception at runtime
There is no enum value with the lowercase name summer. Java throws an IllegalArgumentException.
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant enums.Season.summer
public enum ExtendedSeason extends Season { } // DOES NOT COMPILEOne thing that you can’t do is extend an enum.
The values in an enum are all that are allowed.
You cannot add more by extending the enum.
USING ENUMS IN SWITCH STATEMENTS
Pay attention to the case values in this code:
Season summer = Season.SUMMER;
switch (summer) {
case WINTER:
System.out.println("Get out the sled!");
break;
case SUMMER:
System.out.println("Time for the pool!");
break;
default:
System.out.println("Is it summer yet?");
}switch (summer) {
case Season.FALL: // DOES NOT COMPILE
System.out.println("Rake some leaves!");
break;
case 0: // DOES NOT COMPILE
System.out.println("Get out the sled!");
break;
}ADDING CONSTRUCTORS, FIELDS, AND METHODS
1: public enum Season {
2: WINTER("Low"), SPRING("Medium"), SUMMER("High"), FALL("Medium");
3: private final String expectedVisitors;
4: private Season(String expectedVisitors) {
5: this.expectedVisitors = expectedVisitors;
6: }
7: public void printExpectedVisitors() {
8: System.out.println(expectedVisitors);
9: } }How do we call an enum method?
Season.SUMMER.printExpectedVisitors();
public enum OnlyOne {
ONCE(true);
private OnlyOne(boolean b) {
System.out.print("constructing,");
}
}
public class PrintTheOne {
public static void main(String[] args) {
System.out.print("begin,");
OnlyOne firstCall = OnlyOne.ONCE; // prints constructing,
OnlyOne secondCall = OnlyOne.ONCE; // doesn't print anything
System.out.print("end");
}
}The first time that we ask for any of the enum values, Java constructs all of the enum values. After that, Java just returns the already constructed enum values.
This class prints the following:
begin,constructing,end
CREATING IMMUTABLE OBJECTS
The immutable objects pattern is an object-oriented design pattern
in which an object cannot be modified after it is created.
Instead of modifying an immutable object,
you create a new object that contains any properties from the original object you want copied over.
Immutable objects are invaluable in concurrent applications
since the state of the object cannot change or be corrupted by a rogue thread.
enum abstract method
public enum Season {
WINTER {
public String getHours() { return "10am-3pm"; }
},
SPRING {
public String getHours() { return "9am-5pm"; }
},
SUMMER {
public String getHours() { return "9am-7pm"; }
},
FALL {
public String getHours() { return "9am-5pm"; }
};
public abstract String getHours();
}default implementation and override
If we don’t want each and every enum value to have a method, we can create a default implementation and override it only for the special cases.
public enum Season {
WINTER {
public String getHours() { return "10am-3pm"; } //override
},
SUMMER {
public String getHours() { return "9am-7pm"; } //override
},
SPRING, FALL;
public String getHours() { return "9am-5pm"; } //default implemenation
}> [!NOTE]
You might have noticed that in each of these enum examples, the list of values came first.
This was not an accident. Whether the enum is simple or contains a ton of methods, constructors, and variables, the compiler requires that the list of values always be declared first.
the compiler requires that the list of values always be declared first.
Creating Nested Classes
A nested class is a class that is defined within another class. A nested class can come in one of four flavors.
* Inner class: A non-static type defined at the member level of a class
* Static nested class: A static type defined at the member level of a class
* Local class: A class defined within a method body
* Anonymous class: A special case of a local class that does not have a name