Chapter 1. Declarations, Initialization and Scoping (Part-2)
In this tutorial you will learn about Enum constructors, Example of enum constructors, Methods provided for the enum types, Example of using enum type, java.util.EnumSet, Example of using java.util.EnumSet, java.util.EnumMap, Example of using EnumMap, Creating and using packages and Static imports.
Enum constructors
Each constant declaration can be followed by an argument list that is passed to the constructor of the enum type having the matching parameter signature.
An implicit standard constructor is created if no constructors are provided for the enum type.
As an enum cannot be instantiated using the new operator, the constructors cannot be called explicitly.
Example of enum constructors:
|
public enum Meal {
.....BREAKFAST(7, 30), LUNCH(12, 15), DINNER(19, 45);
.....private int hh;
.....private int mm;
.....Meal(int hh, int mm) {
..........assert (hh >= 0 && hh <= 23) : "Illegal hour.";
..........assert (mm >= 0 && mm <= 59) : "Illegal mins.";
..........this.hh = hh;
..........this.mm = mm;
.....}
.....public int getHour() {
..........return hh;
.....}
.....public int getMins() {
..........return mm;
.....}
}
|
Methods provided for the enum types
Names of members declared in an enum type cannot conflict with automatically generated member names:
- The enum constant names cannot be redeclared.
- The following methods cannot be redeclared:
|
// Returns an array containing the constants of this enum class,
// in the order they are declared.
static < this enum class >[] values()
// Return the enum constant with the specified name
static < this enum class > valueOf(String name)
|
Enum types are based on the java.lang.Enum class which provides the default behavior.
Enums cannot declare methods which override the final methods of the java.lang.Enum class:
- clone(), compareTo(Object), equals(Object), getDeclaringClass(), hashCode(), name(), ordinal().
- The final methods do what their names imply, but the clone() method throws an CloneNotSupportedException, as an enum constant cannot be cloned.
Note that the enum constants must be declared before any other declarations in an enum type.
public enum Meal {
.....int q = 1; // WRONG ! Compilation error !
.....BREAKFAST(7, 30), LUNCH(12, 15), DINNER(19, 45);
.....private int hh;
........ |
Example of using enum type:
public class MealClient {
.....public static void main(String[] args) {
..........for (Meal meal : Meal.values())
............System.out.println(meal + " served at " + meal.getHour() + ":"
...............+ meal.getMins() + ", has the ordinal value "
...............+ meal.ordinal());
..........}
} |
The output will be:
BREAKFAST served at 7:30, has the ordinal value 0
LUNCH served at 12:15, has the ordinal value 1
DINNER served at 19:45, has the ordinal value 2
Extending enum types: constant-specific class bodies
Constant-specific class bodies define anonymous classes inside an enum type that extend the enclosing enum type.
Instance methods declared in these class bodies are accessible outside the enclosing enum type only if they override accessible methods in the enclosing enum type.
An enum type that contains constant-specific class bodies cannot be declared final:
public enum Meal {
...// Each enum constant defines a constant-specific
...//class body
...BREAKFAST(7, 30) {
......public double mealPrice() {
.........double breakfastPrice = 10.50;
.........return breakfastPrice;
......}
...},
......
...// WRONG! Compilation error! Cannot override the final method
...//from Meal final double mealPrice() { return 0; } |
Correct example:
public enum Meal {
...// Each enum constant defines a constant-specific class body
...BREAKFAST(7, 30) {
......public double mealPrice() {
.........double breakfastPrice = 10.50;
.........return breakfastPrice;
......}
...},
......
...// Abstract method which the constant-specific class body
...abstract double mealPrice();
...... |
java.util.EnumSet
Enums can be used in a special purpose Set implementation (EnumSet) which provides better performance.
All of the elements in an enum set MUST come from a single enum type.
Enum sets are represented internally as bit vectors.
The EnumSet class defines new methods and inherits the ones in the Set/Collection interfaces. NOTE, all methods are static except for the clone() method.
All methods return an EnumSet< E >.
The null reference CANNOT be stored in an enum set.
Method summary for the abstract class EnumSet< E extends Enum < E > > :
// Creates an enum set containing all of the
// elements in the specified element type.
allOf(Class< E > elementType)
// Returns a copy of this set.
clone()
// Creates an enum set with the same element
// type as the specified enum set, initially
// containing all the elements of this type
// that are not contained in the specified set.
complementOf(EnumSet< E > s)
// Creates an enum set initialized from
// the specified collection.
copyOf(Collection< E > c)
// Creates an enum set with the same element
// type as the specified enum set, initially
// containing the same elements (if any).
copyOf(EnumSet< E > s)
// Creates an empty enum set with the
// specified element type.
noneOf(Class< E > elementType)
// These factory methods creates an enum set
// initially containing the specified
// element(s). Note that enums cannot be used
// in varargs as it is not legal to use varargs
// with parameterized types.
of(E e)
of(E e1, E e2)
of(E e1, E e2, E e3)
of(E e1, E e2, E e3, E e4)
of(E e1, E e2, E e3, E e4, E e5)
// Creates an enum set initially containing all of the
// elements in the range defined by
// the two specified endpoints.
range(E from, E to) |
Example of using java.util.EnumSet:
import java.util.EnumSet;
import static java.lang.System.out;
public class UsingEnumSet {
.....enum Day {
..........MONDAY, TUESDAY, WEDNESDAY,
..........THURSDAY, FRIDAY, SATURDAY, SUNDAY
.....}
.....public static void main(String[] args) {
..........EnumSet< Day > allDays =
...............EnumSet.range(Day.MONDAY, Day.SUNDAY);
...............out.println("All days: " + allDays);
..........EnumSet< Day > weekend =
...............EnumSet.range(Day.SATURDAY, Day.SUNDAY);
...............out.println("Weekend: " + weekend);
..........EnumSet< Day > oddDays =
...............EnumSet.of(Day.MONDAY, Day.WEDNESDAY,
...............Day.FRIDAY, Day.SUNDAY);
...............out.println("Odd days: " + oddDays);
..........EnumSet< Day > evenDays =
...............EnumSet.complementOf(oddDays);
...............out.println("Even days: " + evenDays);
..........EnumSet< Day > weekDays =
...............EnumSet.complementOf(weekend);
...............out.println("Week days: " + weekDays);
.....}
} |
Output:
All days: [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
Weekend: [SATURDAY, SUNDAY]
Odd days: [MONDAY, WEDNESDAY, FRIDAY, SUNDAY]
Even days: [TUESDAY, THURSDAY, SATURDAY]
Week days: [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]
java.util.EnumMap
Enums can be used in a special purpose Map implementation (EnumMap) which provides better performance.
Enum maps are represented internally as arrays.
All of the keys in an enum map MUST come from a single enum type.
Enum maps are maintained in the natural order of their keys (i.e. the order of the enum constant declarations).
The EnumMap class re-implements most of the methods in the Map interface.
The null reference as a key is NOT permitted.
Constructor summary of the class EnumMap< K extends Enum< K >,V >:
// Creates an empty enum map with the
// specified key type.
EnumMap(Class< K > keyType)
// Creates an enum map with the same key
// type as the specified enum map, initially
// containing the same mappings (if any).
EnumMap(EnumMap< K,? extends V > m)
// Creates an enum map initialized from the
// specified map.
EnumMap(Map< K,? extends V > m)
|
Method summary of the class EnumMap < K extends Enum< K >,V >:
// Removes all mappings from this map.
void clear()
// Returns a shallow copy of this enum map.
EnumMap< K,V > clone()
// Returns true if this map contains a
// mapping for the specified key.
boolean containsKey(Object key)
// Returns true if this map maps one or
// more keys to the specified value.
boolean containsValue(Object value)
// Returns a Set view of the mappings
// contained in this map.
Set< Map.Entry< K,V > > entrySet()
// Compares the specified object with
// this map for equality.
boolean equals(Object o)
// Returns the value to which this map maps
// the specified key, or null if this map contains
// no mapping for the specified key.
V get(Object key)
// Returns a Set view of the keys
// contained in this map.
Set< K > keySet()
// Associates the specified value with the
// specified key in this map.
V put(K key, V value)
// Copies all of the mappings from the
// specified map to this map.
void putAll(Map< ? extends K,? extends V > m)
// Removes the mapping for this key from
// this map if present.
V remove(Object key)
// Returns the number of key-value mappings
// in this map.
int size()
// Returns a Collection view of the values
// contained in this map.
Collection< V > values()
|
Example of using EnumMap:
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static java.lang.System.out;
public class UsingEnumMap {
.....enum Day {
.....MONDAY, TUESDAY, WEDNESDAY,
.....THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
.....public static void main(String[] args) {
..........int[] freqArray = { 12, 34, 56, 23, 5, 13, 78 };
..........// Create a Map of frequencies
..........Map< Day, Integer > ordinaryMap =
..........new HashMap< Day, Integer>();
..........for (Day day : Day.values()) {
..........ordinaryMap.put(day, freqArray[day.ordinal()]);
..........}
..........out.println("Frequency Map: " + ordinaryMap);
..........// Create an EnumMap of frequencies
..........EnumMap< Day, Integer> frequencyEnumMap =
..........new EnumMap< Day, Integer>(
...............ordinaryMap);
..........// Change some frequencies
..........frequencyEnumMap.put(Day.MONDAY, 100);
..........frequencyEnumMap.put(Day.FRIDAY, 123);
..........out.println("Frequency EnumMap: " +
..........frequencyEnumMap);
..........// Values
..........Collection< Integer > frequencies =
..........frequencyEnumMap.values();
..........out.println("Frequencies: " + frequencies);
..........// Keys
..........Set< Day > days = frequencyEnumMap.keySet();
..........out.println("Days: " + days);
.....}
} |
Output:
Frequency Map: {THURSDAY=23, SUNDAY=78, SATURDAY=13, WEDNESDAY=56, FRIDAY=5, TUESDAY=34, MONDAY=12}
Frequency EnumMap: {MONDAY=100, TUESDAY=34, WEDNESDAY=56, THURSDAY=23, FRIDAY=123, SATURDAY=13, SUNDAY=78}
Frequencies: [100, 34, 56, 23, 123, 13, 78]
Days: [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
Creating and using packages
To make classes easier to find and to use, to avoid naming conflicts, and to control access, programmers bundle groups of related classes and interfaces into packages. A package is a collection of related classes and interfaces providing access protection and namespace management.
The classes and interfaces that are part of the Java platform are members of various packages that bundle classes by function: fundamental classes are in java.lang, classes for reading and writing (input and output) are in java.io, and so on. You can put your classes and interfaces in packages, too.
To create a package, you put a class or an interface in it. To do this, you put a package statement at the top of the source file in which the class or the interface is defined. For example, the following code appears in the source file Circle.java and puts the Circle class in the graphics package:
package graphics;
public class Circle extends Graphic implements Draggable {
.............
}
|
The Circle class is a public member of the graphics package. You must include a package statement at the top of every source file that defines a class or an interface that is to be a member of the graphics package. So you would also include the statement in Rectangle.java and so on:
The Circle class is a public member of the graphics package. You must include a package statement at the top of every source file that defines a class or an interface that is to be a member of the graphics package. So you would also include the statement in Rectangle.java and so on:
package graphics;
public class Rectangele extends Graphic implements Draggable {
.............
}
|
The scope of the package statement is the entire source file, so all classes and interfaces defined in Circle.java and Rectangle.java are also members of the graphics package. If you put multiple classes in a single source file, only one may be public, and it must share the name of the source files base name. Only public package members are accessible from outside the package. If you do not use a package statement, your class or interface ends up in the default package, which is a package that has no name. Generally speaking, the default package is only for small or temporary applications or when you are just beginning development. Otherwise, classes and interfaces belong in named packages.
Only public package members are accessible outside the package in which they are defined. To use a public package member from outside its package, you must do one or more of the following:
- Refer to the member by its long (qualified) name.
.
You can use a package members simple name if the code you are writing is in the same package as that member or if the members package has been imported. However, if you are trying to use a member from a different package and that package has not been imported, you must use the members qualified name, which includes the package name. This is the qualified name for the Rectangle class declared in the graphics package:
.
graphics.Rectangle
.
You could use this long name to create an instance of graphics.Rectangle:
.
graphics.Rectangle myRect = new graphics.Rectangle();
.
Using long names is okay for one-shot uses. You'd likely get annoyed if you had to write graphics.Rectangle again and again. Also, your code would get very messy and difficult to read. In such cases, you can just import the member instead.
.
- Import the package member
.
To import a specific member into the current file, put an import statement at the beginning of your file before any class or interface definitions but after the package statement, if there is one. Here's how you would import the Circle class from the graphics package:
.
import graphics.Circle;
.
Now you can refer to the Circle class by its simple name:
.
Circle myCircle = new Circle();
.
This approach works well if you use just a few members from the graphics package. But if you use many classes and interfaces from a package, you can import the entire package.
.
- Import the members entire package
.
To import all the classes and interfaces contained in a particular package, use the import statement with the asterisk (*) wildcard character:
.
import graphics.*;
.
Now you can refer to any class or interface in the graphics package by its short name:
.
Circle myCircle = new Circle();
Rectangle myRectangle = new Rectangle();
.
The asterisk in the import statement can be used only to specify all the classes within a package, as shown here. It cannot be used to match a subset of the classes in a package. For example, the following does not match all the classes in the graphics package that begin with A:
.
import graphics.A*; // does not work
.
Instead, it generates a compiler error. With the import statement, you can import only a single package member or an entire package. For your convenience, the Java runtime system automatically imports two entire packages: java.lang and the current package.
Static imports
The static import feature enables you to import static members from a class or an interface and thus use them without a qualifying name. As an example, consider the following interface that contains two constant values:
|
package com.name;
interface XYZ {
...public static final double Constant1 = someValue;
...public static final double Constant2 = anotherValue;
}
|
Now, the constants in the XYZ interface can be used as follows:
|
public class MyClass implements XYZ {
........
.....double value = 2 * Constant1;
........
}
|
As you can see, a class must implement the interface in order to have access to the constants defined in the interface.
In J2SE 5.0, static import solves this problem as shown in the following example:
|
import static com.name.XYZ.*;
public class MyClass {
........
.....double value = 2 * Constant1;
........
}
|
As another example, consider the following static imports:
import static java.lang.Math.*;
import static java.lang.System.*;
With these two static imports, you now can use:
double r = cos(PI * theta);
instead of:
double r = Math.cos(PI * theta);
and
out.println("Hello there");
instead of:
System.out.println("Hello there");
___________________
Author: Mikalai Zaikin. Please Click Here to visit Authors site for any updates and changes to the study notes.
Trackback(0)
|