CS F213 Objected Oriented Programming Labsheet 8
Spring 2024
Java Enumerations
The Enum in Java is a data type which contains a fixed set of constants.
It can be used for days of the week (SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, and SATURDAY) , directions (NORTH, SOUTH, EAST, and WEST), season (SPRING, SUMMER, WINTER, and AUTUMN or FALL), colors (RED, YELLOW, BLUE, GREEN, WHITE, and BLACK) etc. According to the Java naming conventions, we should have all constants in capital letters. So, we have enum constants in capital letters
.
Java Enums can be thought of as classes which have a fixed set of constants (a variable that does not change). The Java enum constants are static and final
implicitly.
Unlike C/C++, enum in Java is more powerful. Here, we can define an enum either inside the class or outside the class. Java Enum internally inherits the Enum class, so it cannot inherit any other class, but it can implement many interfaces. We can have fields, constructors, methods, and main methods in Java enum.
Once you have defined an enumeration, you can create a variable of that type. However, even though enumerations define a class type, you do not instantiate an enum using new. Instead, you declare and use an enumeration variable in much the same way as you do one of the primitive types.
Example
The values( ) and valueOf( ) Methods
All enumerations automatically contain two predefined methods: values() and valueOf(). Their general forms are shown here:
public static enum-type [] values() public static enum-type valueOf(String str)
The values() method returns an array
that contains a list of the enumeration constants. The valueOf() method returns the enumeration constant
whose value corresponds to the string passed in str. In both cases, enum-type is the type of the enumeration. For example, in the case of the Season enumeration shown earlier, the return type of Season.valueOf("SUMMER") is SUMMER.
Example
Output
The Java compiler internally adds the ordinal() method when it creates an enum. The ordinal() method returns the index of the enum value.
The semicolon (;) at the end of the enum constants are optional.
Initializing specific values to the enum constants
The enum constants have an initial value which starts from 0, 1, 2, 3, and so on. But, we can initialize the specific value to the enum constants by defining fields and constructors. As specified earlier, Enum can have fields, constructors, and methods.
Example
Output
Constructor of enum type is private. If you don't declare private compiler internally creates private constructor.
You can compare the ordinal value of two constants of the same enumeration by using the compareTo() method. It has this general form:
final int compareTo(enum-type e)
Here, enum-type is the type of the enumeration, and e is the constant being compared to the invoking constant. Remember, both the invoking constant and e must be of the same enumeration. If the invoking constant has an ordinal value less than e’s, then compareTo() returns a negative value. If the two ordinal values are the same, then zero is returned. If the invoking constant has an ordinal value greater than e’s, then a positive value is returned.
Although equals( ) can compare an enumeration constant to any other object, those two objects will be equal only if they both refer to the same constant, within the same enumeration. Simply having ordinal values in common will not cause equals( ) to return true if the two constants are from different enumerations.
Type Wrappers
The wrapper classes in Java are used to convert primitive types (int, char, float, etc) into corresponding objects.
Each of the 8 primitive types has corresponding wrapper classes.
byte
Byte
boolean
Boolean
char
Character
double
Double
float
Float
int
Integer
long
Long
short
Short
Convert Primitive Type to Wrapper Objects
We can also use the valueOf()
method to convert primitive types into corresponding objects.
Example
Advantages of Wrapper Classe
In Java, sometimes we might need to use objects instead of primitive data types. For example, while working with collections. In such cases, wrapper classes help us to use primitive data types as objects.
We can store the null value in wrapper objects. For example,
Autoboxing and Auto-unboxing
Autoboxing is the process by which a primitive type is automatically encapsulated (boxed) into its equivalent type wrapper whenever an object of that type is needed. There is no need to explicitly construct an object. Auto-unboxing is the process by which the value of a boxed object is automatically extracted (unboxed) from a type wrapper when its value is needed.
Output
Autoboxing/unboxing might occur when an argument is passed to a method, or when a value is returned by a method
Ouput
In the program, notice that m() specifies an Integer parameter and returns an int result. Inside main(), m() is passed the value 100. Because m() is expecting an Integer, this value is automatically boxed. Then, m() returns the int equivalent of its argument. This causes v to be auto-unboxed. Next, this int value is assigned to iOb in main(), which causes the int return value to be autoboxed. ++iOb
works like this: iOb is unboxed, the value is incremented, and the result is reboxed.
Advantages of using Autoboxing/unboxing
Autoboxing and Auto-unboxing has a great advantage while working with Java collections.
Example
Output
Annotations
Java Annotation is a tag that represents the metadata i.e. attached with class, interface, methods or fields to indicate some additional information which can be used by java compiler and JVM.
Annotations in Java are used to provide additional information, so it is an alternative option for XML and Java marker interfaces.
Custom Annotations
General syntax is:
Here is the declaration for an annotation called MyAnno:
All annotations consist solely of method declarations. However, you don’t provide bodies for these methods. Instead, Java implements these methods. Moreover, the methods act much like fields, as you will see.
An annotation cannot include an extends clause
. However, all annotation types automatically extend the Annotation interface. Thus, Annotation is a super-interface of all annotations. It is declared within the java.lang.annotation
package.
Any type of declaration can have an annotation associated with it. For example, classes, methods, fields, parameters, and enum constants can be annotated. Even an annotation can be annotated. When you apply an annotation, you give values to its members. For example,
Using Default Values
You can give annotation members default values that will be used if no value is specified when the annotation is applied. A default value is specified by adding a default clause to a member’s declaration. Here, value must be of a type compatible with type.
Built-In Annotations
There are several built-in annotations in Java. Some annotations are applied to Java code and some to other annotations.
Built-In Java Annotations used in Java code
@Override
: Thid annotation assures that the subclass method is overriding the parent class method. If it is not so, compile time error occurs. Sometimes, we do the silly mistake such as spelling mistakes etc. So, it is better to mark @Override annotation that provides assurity that method is overridden.
@SuppressWarnings
: is used to suppress warnings issued by the compiler.
@Deprecated
: It marks that this method is deprecated so compiler prints warning. It informs user that it may be removed in the future versions. So, it is better not to use such methods.
Built-In Java Annotations used in other annotations
@Target
: is used to specify at which type, the annotation is used.
@Retention
: is used to specify to what level annotation will be available.
RetentionPolicy.SOURCE
Refers to the source code, discarded during compilation. It will not be available in the compiled class.
RetentionPolicy.CLASS
Refers to the .class file, available to the Java compiler but not to the JVM. It is included in the class file.
RetentionPolicy.RUNTIME
Refers to the runtime, available to the Java compiler and JVM.
@Inherited
: By default, annotations are not inherited to subclasses. The @Inherited annotation marks the annotation to be inherited to subclasses.@Documented
: Marks the annotation for inclusion in the documentation.
Use of Annotations
Compiler instructions - Annotations can be used for giving instructions to the compiler, detect errors or suppress warnings. The built-in annotations
@Deprecated
,@Override
,@SuppressWarnings
are used for these purposes.Compile-time instructions - Compile-time instructions provided by these annotations help the software build tools to generate code, XML files and many more.
Runtime instructions - Some annotations can be defined to give instructions to the program at runtime. These annotations are accessed using Java Reflection.
Exercises
Exercise 1
You are tasked with implementing a Weekly scheduler that allows multiple tasks to be executed concurrently on different days of the week. The days of the week are represented by an enum named Week
, and each day can have multiple tasks associated with it.
Implement a Java program using threads and the Week enum to schedule and execute tasks concurrently. Ensure that the tasks are performed on the specified days of the week. Additionally, allow users to input the tasks they want to schedule for each day.
Week.java
: enum to contain all days of a week.
Task.java
: implements Runnable and represents a task to be executed on a specific day.
WeeklyScheduler
: responsible for scheduling tasks for different days and executing them concurrently.Threads are used to run tasks concurrently on the specified days of the week.
Main.java
: Users are prompted to input tasks for each day, and the tasks are scheduled accordingly.
Sample Input
Sample Output
For your ease, template of Task.java
and WeeklyScheduler.java
is given below.
You can use these and make the rest two classes to get the desired output.
Exercise 2
You are tasked with implementing a Stock price checker
that concurrently monitors the prices of multiple stocks. Implement a Java program using multithreading concepts, autoboxing, and unboxing to simulate stock price updates.
Create a Stock class that stores the current price of a stock and a StockMonitor class to monitor and update the stock prices. Each stock's price will be updated by a separate thread.
Stock.java
: represents a stock with a symbol and its current price. The price is accessed and updated through synchronized methods to ensure thread safety.
StockMonitor.java
: extends Thread and simulates the continuous monitoring of a stock's price. It updates the stock price randomly to simulate real-world fluctuations.
Main.java
: takes user input for 2 stoscks, creates instances of Stock and StockMonitor, starts the monitoring threads, waits for them to complete using the join() method and prints the final price of both stocks.
Sample Input
Sample Output
For your ease, template of Stock.java
and StockMonitor.java
is given below.
You can use these and make the main class to take input of two stocks and get the desired output.
Last updated