Showing posts with label Java 5. Show all posts
Showing posts with label Java 5. Show all posts

Monday, March 4, 2024

Generic Class, Interface And Generic Method in Java

In the post Generics in Java basics of Java generics are already covered. In this post we’ll see how to create generic class, generic method and generic interface in Java.

Generic class in Java

A generic class is defined with the following format:

class name<T1, T2, ..., Tn> { 
  /* ... */ 
} 

The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.

Java Generic class example

Let us create a generic class with two type parameters and see it in use with different data types.

class GenClass<K, V>{
  private K key;
  private V value;
  public GenClass(K key, V value) {
    this.key = key;
    this.value = value;
  }
  public K getKey(){
    return key;
  }
  public V getValue(){
    return value;
  }
}

public class GClassDemo {
  public static void main(String[] args) {
    GenClass<String, String> g1 = new GenClass<>("A", "Value A");
    System.out.println("Key- " + g1.getKey());
    System.out.println("Value- " + g1.getValue());
    
    GenClass<Integer, String> g2 = new GenClass<>(1, "Value 1");
    System.out.println("Key- " + g2.getKey());
    System.out.println("Value- " + g2.getValue());
  }
}

Output

Key- A
Value- Value A
Key- 1
Value- Value 1

Here you can see that first time String is passed as the type for both generic types K and V, where as it is passed as Integer and String second time.

Generic Interface in Java

You can create a generic interface much the same way as a generic class but there are some conditions while implementing the generic interface.

Java Generic interface example

public interface GInterface<E> {
  void setValue(E e);
  E getValue();
}

Class implementing Generic interface

import org.netjs.examples.interfaces.GInterface;

public class GClassImpl<E> implements GInterface<E> {
  E e;
  @Override
  public void setValue(E e) {
    this.e = e;   
  }

  @Override
  public E getValue() {
    return e;
  }
}

Points to note here

  1. Here note that a class that implements a generic interface has to be a generic class.
    public class GClassImpl<E> implements Ginterface<E>
    

    If implementing class of the generic interface is not a generic class that will result in compile time error because the type parameter E is not known in that case.

    public class GClassImpl implements Ginterface<E>
    
    This will result in compile-time error.
  2. Of course providing a proper data type with the interface while implementing it is OK, in that case normal class can be used.
    public class GClassImpl implements GInterface<String> {
      String str;
      @Override
      public void setValue(String e) {
        this.str = e;  
      }
    
      @Override
      public String getValue() {
        return str;
      }
    }
    
    Here you have used String as a type parameter with the interface so it is OK to use a normal class but type will become String in the class then.
  3. A generic class implementing a generic interface can have other parameters too. This is perfectly ok-
    public class GClassImpl<E, K> implements Ginterface<E>
    

Generic method in Java

Any method in the generic class can use the type parameter of the class so that way methods in a generic class are generic. Apart from that keep in mind the following points.

  • Generic methods can add more parameters of their own.
  • There can be generic methods even in a non-generic class.

When you are writing a generic method after the access modifier you need to declare the type parameters then the return type. For example if you are writing a public method that uses one type parameter and doesn’t return anything then it will be written as-

 
public <T> void MethodName(T obj1){

} 

Java Generics - generic method example

If you want to write a generic method that can be used to display elements of an array of any type.

 
public class GenericMethodDemo {  
  public static void main(String[] args) {
    GenericMethodDemo gm = new GenericMethodDemo();
    Integer[] intArray = {1, 2, 3, 4, 5, 6, 7};
    Double[] doubleArray = {3.4, 5.6, 7.8, 1.2, 4.5};
    // integer array
    gm.printElements(intArray);
    // double array
    gm.printElements(doubleArray);
  }
    
  public <T> void printElements(T[] arr){
    // Displaying elements
    for(int i = 0; i < arr.length; i++){
      System.out.print(" " + arr[i]);
    }
    System.out.println();
  }
}

Output

 
1 2 3 4 5 6 7
3.4 5.6 7.8 1.2 4.5

When you are calling a generic method there is no need to specify type (though you can do it if you want). Type will be inferred automatically based on the type of the method arguments. So calling your method using this form gm.<Integer>printElements(intArray); for Integer argument is also OK but it is not needed at all.

That's all for this topic Generic Class, Interface And Generic Method in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Bounded Type Parameter in Java Generics
  2. Wildcard in Java Generics
  3. Type Erasure in Java Generics
  4. AutoBoxing And UnBoxing in Java
  5. Varargs (Variable-length Arguments) in Java

You may also like-

  1. Interface Default Methods in Java
  2. Java join() Method - Joining Strings
  3. Spliterator in Java
  4. Difference Between HashMap And ConcurrentHashMap in Java
  5. Lock Striping in Java Concurrency
  6. finalize() Method in Java
  7. static Import in Java With Examples
  8. Try-With-Resources in Java With Examples

Thursday, March 16, 2023

Comparing Enum to String in Java

Sometimes you may have the scenario where you want to compare String to enum type in Java. For example you may have an enum with product codes and you want to check that the passed produce code is one of the predefined product codes or not.

Here one thing to note is directly comparing enum value with a string won't work as they both will be of different types.

For example, notice in the code snippet given below where enum type d is directly compared with the String, it won't give any output as they will never be equal.

Sunday, March 12, 2023

Converting Enum to String in Java

In this post we'll see the options we have to convert an Enum to String in Java. It may be needed when you want to compare Enum to String in Java.

Converting Enum to String in Java

Enum class in Java has two methods that can convert Enum to String.

  1. name()- Returns the name of this enum constant, exactly as declared in its enum declaration.
  2. toString()- Returns the name of this enum constant, as contained in the declaration.

As per Java docs toString() should be preferred. That’s what the description of the name() method says “Most programmers should use the toString() method in preference to this one, as the toString method may return a more user-friendly name”. This is because of the fact that toString() can be overridden if need be to return a more "programmer-friendly" string form.

Converting Enum to String using name() method

Following example shows how to convert Enum to String in Java using name() method. In the example Enum constants are iterated using the values() method, in each iteration Enum type is converted to String using the name() method.

public class EnumToString {
 private enum Day {
  SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
  THURSDAY, FRIDAY, SATURDAY 
 }
 public static void main(String[] args) {
  EnumToString ed = new EnumToString();
  ed.displayDays();
 }
 
 private void displayDays(){
  Day[] allDays = Day.values();
  for(Day d : allDays){
   String day =  d.name();
   System.out.println("Day of week- " + day);
  }
 } 
}

Output

Day of week- SUNDAY
Day of week- MONDAY
Day of week- TUESDAY
Day of week- WEDNESDAY
Day of week- THURSDAY
Day of week- FRIDAY
Day of week- SATURDAY

Converting Enum to String using toString() method

Following example shows how to convert Enum to String using toString() method. In the example toString() is overridden with in the Enum type to return a short form of the day. Note that it is not always required to override toString() method, here it is done just to demonstrate how it can be used to return a more "programmer-friendly" string form.

public class EnumToString {
 private enum Day {
  SUNDAY("Sun"), MONDAY("Mon"), TUESDAY("Tue"), WEDNESDAY("Wed"),
  THURSDAY("Thu"), FRIDAY("Fri"), SATURDAY("Sat");
  private String shortDay; 
  Day(String shortDay){
    this.shortDay = shortDay;
  }
  @Override
  public String toString() {
    return shortDay;
  }
 }
 
 public static void main(String[] args) {
  EnumToString ed = new EnumToString();
  ed.displayDays();
 }
 
 private void displayDays(){
  Day[] allDays = Day.values();
  for(Day d : allDays){
   String day =  d.toString();
   System.out.println("Day of week- " + day);
  }
 } 
}

Output

Day of week- Sun
Day of week- Mon
Day of week- Tue
Day of week- Wed
Day of week- Thu
Day of week- Fri
Day of week- Sat

That's all for this topic Converting Enum to String in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Converting String to Enum Type in Java
  2. Convert double to int in Java
  3. Convert Numbers to Words Java Program
  4. How to Convert a File to Byte Array
  5. How to Convert String to Date in Java

You may also like-

  1. Split a String Java Program
  2. Java Lambda Expression Comparator Example
  3. Java Program to Display Prime Numbers
  4. Printing Numbers in Sequence Using Threads Java Program
  5. Adding Tomcat Server to Eclipse
  6. Type Erasure in Java Generics
  7. Nested Class And Inner Class in Java
  8. Difference Between @Controller And @RestController Annotations in Spring

Thursday, November 17, 2022

Type Erasure in Java Generics

When generics was introduced in Java there was a requirement for it to be compatible with the existing code, written in previous versions, which of course was non-generic. That is why you can still add raw types, as example- List alist = new ArrayList();
This will give you warning for raw type but you can still have a non-generic list like this. Another thing that happens internally for compatibility is to replace all type parameters which is known as type erasure in Java generics


How type erasure works in Java

As mentioned above, during the type erasure process, the Java compiler erases all type parameters and replaces each with its first bound if the type parameter is bounded, or Object if the type parameter is unbounded.

The Java compiler applies type erasure in generics to-

  • Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. Which means, if you have a unbounded type parameter that will be replaced by Object while compiling the code. If there is a bounded parameter that will be replaced by the provided bound.
    The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
  • Insert type casts if necessary to preserve type safety.
  • Generate bridge methods to preserve polymorphism in extended generic types.

As example if you have the following generic class

 
public class GenType<T> {
  T obj;
  public T getObj() {
    return obj;
  }

  public void setObj(T obj) {
    this.obj = obj;
  }  
}

here type parameter T is unbounded, thus the Java compiler replaces it with Object, so your compiled class won’t have any type parameter

public class GenType {
  Object obj;
  public Object getObj() {
    return obj;
  }

  public void setObj(Object obj) {
    this.obj = obj;
  }
}

If your class were using a bounded parameter as below-

public class GenType<T extends Number> {
  T obj;
  public T getObj() {
    return obj;
  }

  public void setObj(T obj) {
    this.obj = obj;
  }   
}

Here it will be replaced by the bound i.e. Number

public class GenType {
  Number obj;
  public Number getObj() {
    return obj;
  }

  public void setObj(Number obj) {
    this.obj = obj;
  }  
}

Bridge methods in Java

When compiling a class or interface that extends a parameterized class or implements a parameterized interface, the compiler may need to create a synthetic method, called a bridge method, as part of the type erasure process. In order to get an idea what bridge methods are let’s see an example.

If we have the following two classes-

GenType

public class GenType<T> {
  T obj;
  public GenType(T obj) { 
    this.obj = obj; 
  }

  public void setObj(T obj) {
    this.obj = obj;
  }  
}

MyGen

 
public class MyGen extends GenType<Integer> {
  public MyGen(Integer num) { 
    super(num); 
  } 
  public void setObj(Integer data) {
    System.out.println(" In MyGen.setData");
    super.setObj(data);
  } 
}

Here note that MyGen class extends the GenType class which has the Integer parameter. After compilation and type erasure, type parameters will be removed from both the classes and these classes will look as follows-

 
public class GenType {
  Object obj;
  public GenType(Object obj) { 
    this.obj = obj; 
  }

  public void setObj(Object obj) {
    this.obj = obj;
  }
}
 
public class MyGen extends GenType {
  public MyGen(Integer num) { 
    super(num); 
  } 
  public void setObj(Integer num) {
    System.out.println(" In MyGen.setData");
    super.setObj(num);
  }
}

If you have noticed, after type erasure setObj() method signatures don’t match in GenType and MyGen classes. In GenType class it becomes setObj(Object obj) where as in MyGen it becomes setObj(Integer num).

Therefore, the MyGen setObj method does not override the GenType setObj method.

To solve this problem and preserve the polymorphism of generic types after type erasure, a Java compiler generates a bridge method to ensure that subtyping works as expected. For the MyGen class, the compiler generates the following bridge method for setObj:

 
public class MyGen extends GenType {
  public MyGen(Integer num) { 
    super(num); 
  } 

  // Bridge method generated by the compiler
  public void setObj(Object num) {
    setObj((Integer) num);
  }
  public void setObj(Integer num) {
    System.out.println(" In MyGen.setData");
    super.setObj(num);
  }
}

Here you can see a bridge method which has the same signature as the setObj method of the GenType class is inserted and it delegates to the actual setObj method.

Generics Ambiguity errors because of type erasure

Let’s say you have the following class where you are trying to have two overloaded methods (set) with different type parameters K and V respectively.

 
class GenClass<K, V>{
  private K key;
  private V value;
  public GenClass(K key, V value) {
    this.key = key;
    this.value = value;
  }

  public void set(K key){
    this.key = key;
  }

  public void set(V value){
    this.value = value;
  }

  public K getKey(){
    return key;
  }
  public V getValue(){
    return value;
  }
}

This class will give compilation error
Erasure of method set(K) is the same as another method in type GenClass<K,V>
Erasure of method set(V) is the same as another method in type GenClass<K,V>

Though you may think since K and V are two different parameters so its ok to write overloaded methods using these parameters as arguments. But there is no such compulsion that these two parameters will be different, at the time of creating objects you can provide same type for both the type parameters.

Also type erasure will replace the type parameter with Object in this case so both the methods will become-

 
public void set(Object key){
 this.key = key;
}
 
public void set(Object value){
 this.value = value;
}

In a case like this it is better to give different name for the methods and avoid any ambiguity.

That's all for this topic Type Erasure in Java Generics. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Generics in Java
  2. Bounded Type Parameter in Java Generics
  3. Wildcard in Java Generics
  4. Enum Type in Java
  5. Spliterator in Java

You may also like-

  1. Varargs (Variable-length Arguments) in Java
  2. Java Stream API Tutorial
  3. Effectively Final in Java 8
  4. Java ThreadLocal Class With Examples
  5. Is String Thread Safe in Java
  6. Java ReentrantLock With Examples
  7. Java Collections Interview Questions And Answers
  8. Dependency Injection in Spring Framework

Tuesday, October 11, 2022

Generics in Java

There have been many new feature additions in Java over the year, with introduction of lambda expressions in Java 8 it has even moved toward functional programming. But long before the lambda expressions and stream API there was one change which had a very big impact on the way you program and that was generics which was added in Java 5.

Generics in Java not only added a new way to declare classes, methods or interface but it also changed many of the classes in the API, Java collections API is an example. Initially it took some time getting used to the parameters like T, K or V with the classes or methods but now its quite a familiar thing and very much a part of your daily programming.

Java Generics

Generics in Java enable you to specify type parameters when defining classes, interfaces and methods. Here type parameter is the type of data (class or interface) which these classes, interfaces and methods will operate upon.

As example, when you say List<T> that means a list which will store elements of type T. Since you have specified a type parameter so this List class is generic and T is the type parameter which specifies the type of element stored in the List.

Generic class format in Java

A generic class is defined using the following format:

class name<T1, T2, ..., Tn> { 
  /* ... */ 
}

The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.

Java Generics - Type Parameter Naming Conventions

By convention, generic type parameter names are single, upper case letters. That helps n distinguishing between type parameters and normal variables.

The most commonly used type parameter names are:

  • E - Element (used extensively by the Java Collections Framework)
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types

Benefits of Generics in Java

You might be thinking there is already an Object class which provides almost the same thing, as Object is super class of all the other classes so Object class can be used to make a class generic. Though that can be done but it may cause some unseen problems because there is no type safety.

Let’s say you have a List where you intend to store strings and you have not made it generic that means all its elements will be stored as objects of type Object-

List strList = new ArrayList();
strList.add("a");
strList.add("b");
strList.add(new Integer(4));
Iterator itr = strList.iterator();
while(itr.hasNext()){
 String str = (String)itr.next();
 System.out.println("" + str);
}

Since elements are stored as class Object type so there won’t be any compile time error if you store an integer too (as done in this line strList.add(new Integer(4));), even if you intended to store Strings.

Since the elements are stored as class Object type so you need to cast those elements to String while retrieving. At that time you will get a run time exception when the code will try to cast Integer to String.

So the code snippet shown above will throw run time exception-
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

That brings to the fore couple of benefits of using generics in Java-

  • Stronger type checks at compile time- In the above code if you use generics and specify the parameterized type of List as String you will get compile time error if an attempt is made to add element of any other type to the list. 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.

    As example-

    List<String> strList = new ArrayList<String>();
    strList.add("a");
    strList.add("b");
    strList.add(new Integer(4));
    

    With generics this code will throw following compile-time error if you try to add Integer to the list
    The method add(String) in the type List<String> is not applicable for the arguments (Integer)

  • Casting is not required- Another benefit you get with generics in Java is that cast is not required. Since you already specify the type with generics so explicit cast is not required.

    As example-

    List<String> strList = new ArrayList<String>();
    strList.add("a");
    strList.add("b");
    strList.add("c");
    
    Iterator<String> itr = strList.iterator();
    while(itr.hasNext()){
      String str = itr.next();
      System.out.println("" + str);
    }
    

    Here you see casting is not required when retrieving elements from the list.

  • Enabling programmers to implement generic algorithms– In many algorithms, logic remains same, irrespective of the data they are used with. On the other hand, generics make it possible to write classes, methods and interface that work with different kind of data that too in a type safe manner. Now combine these two facts and the result you can write generic algorithms that work with any type of data.

    Let’s take a simple example to see how to create a generic class with parameterized type. While creating an object of the class you can specify the type, which in generics terminology is called generic type invocation, which replaces T with some concrete value.

    Generic class

    public class GenType<T> {
      T obj;
    
      public T getObj() {
        return obj;
      }
    
      public void setObj(T obj) {
        this.obj = obj;
      } 
    }
    

    Using Generic class

    public class GenericDemo {
      public static void main(String[] args) {
        // With Integer type
        GenType<Integer> genInt = new GenType<Integer>();
        genInt.setObj(21);
        int value = genInt.getObj();
        System.out.println("integer value " + value);
        
        // With String type
        GenType<String> genStr = new GenType<String>();
        genStr.setObj("Generic class test");
        String str = genStr.getObj();
        System.out.println("String value " + str);
        
        // With Double type
        GenType<Double> genDouble = new GenType<Double>();
        genDouble.setObj(34.56);
        double dblValue = genDouble.getObj();
        System.out.println("Double value " + dblValue);
      }
    }
    

    Output

    integer value 21
    String value Generic class test
    Double value 34.56
    

    Here you see that the same generic class is first invoked with Integer type, then String and then Double. And you get the added benefit of type safety and no chance of run time exception (which is a probability if you had used an Object class to make the class generic).

Points to remember

  1. Generics in Java provide type safety as there are stronger type checks at compile-time.
  2. Generics don’t work with primitive types, type arguments passed to the type parameters must be references.
  3. You can have generic classes, generic methods and generic interfaces.
  4. Type parameters are erased when generic classes are compiled.
  5. A generic class with type parameters can’t have static members using the type parameter. As example -
    public class GenType<T> {
      static T obj;
      .....
      .....
    }
    
    This code will have compile-time error - Cannot make a static reference to the non-static type T.
  6. In Java 7 and later you can replace the type arguments required to invoke the constructor of a generic class with an empty set of type arguments (<>) as long as the compiler can determine, or infer, the type arguments from the context. This pair of angle brackets, <>, is informally called the diamond.
    As example- List<Integer> ls = new ArrayList<>();

    You don’t need to write <Integer> again, empty set of type argument (<>) will do, type will be inferred automatically.

That's all for this topic Generics in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Generic Class, Interface And Generic Method in Java
  2. Bounded Type Parameter in Java Generics
  3. Wildcard in Java Generics
  4. Type Erasure in Java Generics
  5. Covariant Return Type in Java

You may also like-

  1. Interface Default Methods in Java
  2. Effectively Final in Java 8
  3. Method Reference in Java
  4. Java ThreadLocal Class With Examples
  5. Is String Thread Safe in Java
  6. Dependency Injection using factory-method in Spring
  7. strictfp in Java
  8. Polymorphism in Java

Friday, September 9, 2022

AutoBoxing and UnBoxing in Java

In Java 5 two new features Autoboxing and Unboxing were added. Autoboxing in Java automates the wrapping of primitive data types into the wrapper class for that particular data type when an object instead of primitive type is needed.

Unboxing in Java does the exact opposite, that is it gets the value out of a wrapped object automatically.


Autoboxing and Unboxing example

Before this feature autoboxing was added in Java, wrapping a primitive int to its corresponding wrapper class Integer would have looked like–

int num = 25;
Integer i = Integer.valueOf(num);

Now with Java autoboxing feature you can directly assign value to a wrapper class–

Integer i = 25;

Now valueOf() method call will be done by the compiler behind the scene.

Same way for unboxing in Java; getting a primitive's value out of a wrapped object previously meant calling the method intValue(), longValue(), doubleValue() based on the type

Integer i = new Integer(10);
int num = i.intValue();

Now it can be done directly–

Integer i = new Integer(10);
//unboxing
int num = i;

Or for float type

Float f = new Float(56.78);
float fNum = f;

Benefits of Autoboxing and Unboxing in Java

As you have already seen, with this feature you don’t need to wrap primitive types or unwrap them manually. That is a great help with the other feature generics also added in Java 5. Since generics work only with object so having the auto facility to box and unbox greatly simplifies the coding.

As the Collection classes also work only with objects so it makes working with collections easy too.

As example–

List<Integer> li = new ArrayList<>();
for (int i = 1; i < 10; i++){
    li.add(i);
}

Even though you have a List which stores objects of type Integer you can still add primitive int directly to List because of Autoboxing. Earlier when the primitive ints were added to the list, behind the scene those values were wrapped into the Integer objects and then added to the ArrayList.

Same way unboxing also happens automatically.

int elem = li.get(0);
System.out.println("elem " + elem);

When you are trying to get the first element out of the list and assigned it to an int variable, then Integer is unboxed to get the int value out of the wrapped Integer class and that value is assigned to an int variable elem.

More examples of autoboxing and unboxing in Java

We have already seen few examples of assignments where primitive types are autoboxed into wrapper classes and the boxed objects are automatically unboxed to get the primitive values. But that’s not the only place you can see autoboxing and unboxing.

  • You can see it in methods.
  • You can see it in expressions.
  • Due to Autoboxing and unboxing a wrapper class can be used in a switch statement.

Autoboxing and Unboxing in method parameters

When an argument is passed to a method or a value is returned from a method autoboxing/unboxing can happen, if required.

Here the method calcValue takes Double object as a parameter but primitive value double is passed while calling the method thus the double value is autoboxed to a Double type object.

Then there is an expression also which has a mix of Double object and double value-

dOb = dNum + 13.4;

And it is again assigned to a Double type.

Again the return type of the method is double and the returned value is assigned to a Double object.

public class BoxDemo {

 public static void main(String[] args) {
  BoxDemo bd = new BoxDemo();
  Double dVal = bd.calcValue(15.6);
  System.out.println("Value " + dVal);
 }
 
 public double calcValue(Double dNum){
  Double dOb;
  dOb = dNum + 13.4;
  return dOb;
 }
}

Autoboxing and Unboxing in switch statement

Due to unboxing Integer object can be used in a switch-case statement too. With in the switch statement object is unboxed and the int value is used for the conditions.

Integer iVal = 7;
switch(iVal) {
 case 1: System.out.println("First step");
 break;
 case 2: System.out.println("Second step");
 break;
 default: System.out.println("There is some error");
}

AutoBoxing and Unboxing overhead

There is some overhead involved in the process of autoboxing and unboxing in Java so make sure you don’t start using objects exclusively thinking autoboxing/unboxing will happen anyway behind the scenes. It will happen but don’t forget the involved overhead thus making the code a little less efficient.

That's all for this topic AutoBoxing and UnBoxing in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Enum Type in Java
  2. Comparing Enum to String in Java
  3. Varargs (Variable-length Arguments) in Java
  4. Covariant Return Type in Java
  5. Wildcard in Java Generics

You may also like-

  1. Type Casting in Java With Conversion Examples
  2. StringBuilder Class in Java With Examples
  3. Interface Default Methods in Java
  4. Method Reference in Java
  5. Java Stream API Tutorial
  6. Deadlock in Java Multi-Threading
  7. Java ThreadLocal Class With Examples
  8. Dependency Injection in Spring Framework

Sunday, May 22, 2022

Converting String to Enum Type in Java

There may be a scenario where a string is passed in your code and you have to convert that string into enum type in Java. For that you can use valueOf() method which is implicitly created for all enums.

public static T valueOf(String str)– This method is used to map from a String str to the corresponding enum constant. The name must match exactly an identifier used to declare an enum constant in this type.

If no constant with in the enum is found that matches the string passed IllegalArgumentException is thrown.

So, in order to convert String to enum in Java, the passed string should match one of the predefined constants in the enum. Actually it is not conversion in a true sense but you are searching for the enum type with the same name as the passed string, value returned is of type enum though.

Java Example code converting string to enum

 
enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY 
} 
public class EnumDemo {

 public static void main(String[] args) {
  EnumDemo ed = new EnumDemo();
  ed.lookUp("tuesday");
  
 }
 
 // method to lookup ennum constants
 public void lookUp(String str){
  Day day = Day.valueOf(str.toUpperCase());
  System.out.println("Found enum " + day );
 }
}

Output

 
Found enum TUESDAY

Here you can see that a string "Tuesday" is passed and using valueOf() method you get the corresponding enum constant. Make sure the name is same (that is why converted string to uppercase) not even extraneous whitespace are permitted. Use trim() method if you think there may be extraneous white spaces in the string passed.

That's all for this topic Converting String to Enum Type in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Comparing Enum to String in Java
  2. Convert String to int in Java
  3. Convert String to Byte Array Java Program
  4. Convert float to String in Java
  5. How to Convert Date to String in Java

You may also like-

  1. Java Program to Find The Longest Palindrome in a Given String
  2. Matrix Multiplication Java Program
  3. How to Run a Shell Script From Java Program
  4. How to Read File From The Last Line in Java
  5. Covariant Return Type in Java
  6. Wildcard in Java Generics
  7. Lambda Expressions in Java 8
  8. Java Stream API Tutorial

Friday, March 25, 2022

Covariant Return Type in Java

Before Java 5, when you overrode a superclass method in a subclass the method signature had to be exactly same, i.e. the name, argument types and return type of the overriding method in the sub-class had to be exactly same as that of the super-class method.

This is relaxed a bit in Java 5 in case of return type. The sub-class overridden method's return type may be different from super-class method's return type but the return type of the subclass' method should be a subtype of return type of super class method. Which means, if method in the super-class has return type R1 and the overriding method in the subclass has return type R2 then R2 must be a subtype of R1. That is known as covariant return type in Java.

Covariant name comes from the fact that the type of the return is allowed to vary in the same direction as the subclass.

Covariant return type in Java example

// used as return type
class A{
 String name;
 A(String name){
  this.name = name;
 }
}

//sub-class of A, also used as return type
class B extends A{
 B(String name){
  super(name);
 }
}

class C{
 public A getValue(){
  return new A("Test A");
 }
}

class D extends C{
 // overriding method, returning subtype of the 
 // super class method
 public B getValue(){
  return new B("Test B");
 }
}

public class CovariantDemo {

 public static void main(String[] args) {
  // Reference of Class C
  C c;
  // pointing to class C
  c = new C();
  System.out.println("Value from class C " + c.getValue().name);
  // now pointing to class D
  c = new D();
  System.out.println("Value from class D " + c.getValue().name);
 }
}

Output

Value from class C Test A
Value from class D Test B

It can be seen from the program that in class D which is the sub class of class C, getValue() method is overridden. In class C's getValue() method return type is A where as in the overridden method in class D return type is B, which is sub type of A, making it a covariant return type.

That's all for this topic Covariant Return Type in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Varargs (Variable-length Arguments) in Java
  2. Enum Type in Java
  3. Method Overriding in Java
  4. Inheritance in Java
  5. Core Java Basics Interview Questions And Answers

You may also like-

  1. strictfp in Java
  2. static Import in Java With Examples
  3. Type Erasure in Java Generics
  4. Constructor Chaining in Java
  5. Interface Default Methods in Java
  6. Fail-Fast Vs Fail-Safe Iterator in Java
  7. Difference Between Comparable and Comparator in Java
  8. Deadlock in Java Multi-Threading

Saturday, March 19, 2022

Enum Type in Java

An enum type in Java is a special data type that helps you to define a list of predefined constants which can be accessed using a variable. In the Java programming language, you define an enum type by using the enum keyword.

As example, if you want to declare a enum Day that has all the days as predefined constants.

enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY 
}

Since enum is a data type so you can declare a variable of that type.

Day d;
d = Day.FRIDAY;
System.out.println("Day of the week " + d);

Output

Day of the week FRIDAY

Note: You do not instantiate an enum using new operator, even though enumeration defines a class type. You declare an enumeration variable as you will declare a varibale of primitive data types.

Enum was added in Java 1.5 along with generics, varargs, autoboxing and other features.

Java Enum Example

Here we have a complete code where enum is created for days of the week and then we loop through that enum values and print all the constants defined in the enum.

enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY 
}

public class EnumDemo {

 public static void main(String[] args) {
   Day[] allDays = Day.values();
   for(Day day : allDays){
     System.out.println(day);
   }
 }
}

Benefits & Usage of enum in Java

Apart from the obvious benefit of using enum when you need to represent a fixed set of constants there are other benefits and usages of enum.

  1. Provides type safety– If you use private static final constants you can always assign any random value to a variable instead of these predefined constants.

    For example, if I have constants like below I can still assign dayOfTheWeek as “Funday”.

    private static final String SUNDAY = "Sunday";
    private static final String MONDAY = "Monday";
    private static final String TUESDAY = "Tuesday";
       
    final String dayOfTheWeek;
    dayOfTheWeek = "Funday";
    

    With enums it is not possible. If you have an enum like this-

    enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY 
    }
    

    How much ever you want your day to be a funday you can’t do it now.

    Day day = Day.FUNDAY; // Compile-time error
    
  2. Enums have their own name space– Enums in Java have their own name space. So a enum Day as created above will be created in its own name space and has its own type. You are not permitted to use any value other than the one specified as predefined constants with in the enum.
  3. Comparison using == operator- Two enumeration constants can be compared for equality by using the = = relational operator. As example- This statement compares the value in day variable with the TUESDAY constant:
    Day day = Day.FRIDAY;
       
    if(day == Day.TUESDAY){
     System.out.println("Days are equal");
    }else{
     System.out.println("Days are not equal");
    }
    
  4. Used in switch statement- Java Enum can also be used in a switch statement. All case statements have to use the constants from the enum that is used in the switch statement.

    As example-

    Day day = Day.FRIDAY;
     
     switch(day){
      case MONDAY: 
       System.out.println("Week started");
       break;
      case TUESDAY: case WEDNESDAY: case THURSDAY:
       System.out.println("Keep toiling");
       break;
      case FRIDAY:
       System.out.println("Countdown begins");
       break;
      case SATURDAY: case SUNDAY:
       System.out.println("Weekend !!!");
       break;
    }
    

enum declaration defines a class

Java enumeration is a class type, enum can have constructors, instance variables, methods. Enum can even implement interfaces.

As example– Here I have created an enum Days which defines constants, a constructor, a variable day, a method getDay() and even main method so you can run this enum as any other Java class.

public enum Days {
 SUNDAY(1), 
 MONDAY(2), 
 TUESDAY(3), 
 WEDNESDAY(4),
 THURSDAY(5), 
 FRIDAY(6), 
 SATURDAY(7);
 private int  day;
 private Days(int day){
  this.day = day;
 }
 
 int getDay(){
   return day;
 }
 public static void main(String[] args) {
  Days[] allDays = Days.values();
  for(Days d : allDays){
   System.out.println(d + " " + d.getDay());
  }
 }
}

Output

SUNDAY 1
MONDAY 2
TUESDAY 3
WEDNESDAY 4
THURSDAY 5
FRIDAY 6
SATURDAY 7

Some important points to keep in mind while creating an Enum in Java are as given below.

  1. Java requires that the constants be defined first, prior to any fields or methods. So you can’t have code like below where field day is declared first, as it will result in error.
    public enum Days {
     private int day;
     SUNDAY(1), 
     MONDAY(2), 
     TUESDAY(3), 
     WEDNESDAY(4),
     THURSDAY(5), 
     FRIDAY(6), 
     SATURDAY(7);
     ...
     ...
    }
    
  2. Each enumeration constant is an object of its enumeration type. When you create an object of any class its constructor is called for initialization same way constructor is called when each enumeration constant is created.

    If you have noticed constructor of the Days enum takes one int parameter and all the constants have an integer associated with them i.e. SUNDAY(1), MONDAY(2).

    When these constants are created constructor is called and day gets its value from the integer.
  3. Same like any other object each enumeration constant has its own copy of instance variables defined by the enumeration.

    That’s why d.getDay() gives the correct day of the week for every constant.

  4. The constructor for an enum type must be package-private or private access. It automatically creates the constants that are defined at the beginning of the enum body. You cannot invoke an enum constructor yourself.
  5. All enums implicitly extend java.lang.Enum. Because a class can only extend one parent in Java an enum cannot extend anything else.
  6. An enum can implement one or more interfaces.

Java Enum - values() and valueOf() methods

In the above example code I have already used values() method to iterate over the values of an enum type.

These two methods values() and valueOf() are implicitly declared for all enumerations in Java.

General form of values() and valueOf() methods

public static T valueOf(String)

public static T[] values()

Here T is the enum type whose constant is to be returned

The values() method returns an array of the enumeration constants.

The valueOf() method returns the constant whose value corresponds to the string passed in String argument.

enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY 
}

public class EnumDemo {

 public static void main(String[] args) {
  
  // Using values method
   Day[] allDays = Day.values();
   for(Day day : allDays){
     System.out.println(day);
   }
   // Using valueOf() method
   Day day = Day.valueOf("TUESDAY");
   System.out.println("Day - " + day);  
 }
}

Output

SUNDAY
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
Day - TUESDAY

Points to remember

  1. Java enumeration is a class type.
  2. Enumerations can have Constructors, instance Variables, methods and can even implement Interfaces.
  3. You do not instantiate an enum using new operator, even though enumeration defines a class type.
  4. All Enumerations by default inherit java.lang.Enum class. So they can’t extend any other class.
  5. Enum constants are implicitly static and final and can not be changed once created.

That's all for this topic Enum Type in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Comparing Enum to String in Java
  2. Converting String to Enum Type in Java
  3. Covariant Return Type in Java
  4. Wildcard in Java Generics
  5. static Import in Java

You may also like-

  1. Java Stream API Tutorial
  2. Lambda Expressions in Java 8
  3. Method Reference in Java
  4. Volatile Keyword in Java With Examples
  5. Is String Thread Safe in Java
  6. Constructor Chaining in Java
  7. Matrix Multiplication Java Program
  8. Dependency Injection in Spring Framework

Monday, May 3, 2021

Bounded Type Parameter in Java Generics

In the post generics in Java you would have already seen examples where type parameters are replaced by any class type. But there are times when you want to restrict the types that can be used as type arguments in a parameterized type. That can be done using bounded type parameter in Java Generics.

As example if you have a generic class with a method that operates on numbers, you would want to restrict it to accept instances of Number or its subclasses only.

Let’s first see an example where you don’t bind type parameters to analyse what happens in that case-

You have a generic class Test with a method average which returns the average of the numbers in the array passed to it. Since the class is generic so you intend to pass array of any type integer, double, float. Here return type of method average is double as you want an accurate value. Since Number class (Super class of all numeric classes) has doubleValue() method so you can always get the double value out of any type of number.

public class Test<T> {
  T[] numArr;
  Test(T[] numArr){
    this.numArr = numArr;
  }
  public double getAvg(){
    double sum = 0.0;
    for(int i = 0; i < numArr.length; i++){
      sum += numArr[i].doubleValue();
    }
    double avg = sum/numArr.length;
    return avg;
  }
}

This code will give you compile-time error-

The method doubleValue() is undefined for the type T

You get this error as there is no way for compiler to know type T will always be used for numeric classes. You need to let the compiler know that type T will always be Number and doubleValue() method can be called safely. That’s when you need bounded type to restrict the types that can be used for parameterized type. In the above case that restriction is; the type should be Number.

Bounded type in Java generics

In order to create a bounded type you need to provide an upper bound which acts as a restriction for types. As this upper bound is a superclass, the type that can be used has to be a subclass of that upper bound.

General form of bounded type parameter

To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound.

T extends superclass

In the example used above that upper bound has to be the Number class as Number class is the super class of all the numeric classes. Thus in that case your bounded type will be - T extends Number

Java Generics - Bounded type parameter example

public class Test<T extends Number> {
  T[] numArr;
  Test(T[] numArr){
    this.numArr = numArr;
  }
  public double getAvg(){
    double sum = 0.0;
    for(int i = 0; i < numArr.length; i++){
      sum += numArr[i].doubleValue();
    }
    double avg = sum/numArr.length;
    return avg;
  }
}

Now you won’t get compile-time error as you have provided the Number class as upper bound for your generic type T. Which means any type passed for the generic type T has to be the sub class of class Number. Since doubleValue() method is in Number class it will be part of any sub class of Number through inheritance. So no compile-time error!

Multiple Bounds in Java generics

A type parameter can have multiple bounds:

<T extends B1 & B2 & B3>

A type variable with multiple bounds is a subtype of all the types listed in the bound. If one of the bounds is a class, it must be specified first. For example:

Class A { /* ... */ }
interface B { /* ... */ }
interface C { /* ... */ }

class D <T extends A & B & C> { /* ... */ }

Not specifying bounds in this order will result in compile-time error.

Generic Methods and Bounded Type Parameters

You can also use bounded types with generic methods. Let’s see an example where it becomes necessary to use bounded types. Consider a method where you want to count the number of elements in an array greater than a specified element elem.

public static <T> int countGreaterThan(T[] anArray, T elem) {
  int count = 0;
  for (T e : anArray)
    if (e > elem)  // compiler error
      ++count;
  return count;
}

This method will result in compile-time error as greater than (>) operator can be used only with primitive types such as short, int, double, long, float, byte, and char. It can’t be used to compare objects, you have to use types that implement Comparable interface in order to compare objects. Thus, Comparable interface becomes the upper bound in this case.

Code with upper bound

public class Test{
  public <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {
    int count = 0;
    for (T e : anArray){
      if (e.compareTo(elem) > 0) {
        ++count;
      }
    }
    return count;
  }
}

You can use the following code to run it-

Test test = new Test();
Integer[] numArr = {5, 6, 7, 1, 2};
int count = test.countGreaterThan(numArr, 5);
System.out.println("count - " + count);

Output

count – 2

Reference- https://docs.oracle.com/javase/tutorial/java/generics/boundedTypeParams.html

That's all for this topic Bounded Type Parameter in Java Generics. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Generic Class, Interface And Generic Method in Java
  2. Type Erasure in Java Generics
  3. Covariant Return Type in Java
  4. Lambda Expressions in Java 8
  5. Spliterator in Java

You may also like-

  1. How HashMap Works Internally in Java
  2. How HashSet Works Internally in Java
  3. Java ReentrantReadWriteLock With Examples
  4. Java ArrayBlockingQueue With Examples
  5. Executor And ExecutorService in Java With Examples
  6. Association, Aggregation and Composition in Java
  7. Marker Interface in Java
  8. Best Practices For Exception Handling in Java

Sunday, May 2, 2021

Wildcards in Java Generics

In Java generics there is also an option of giving question mark (?) as type which is called wildcard in Java generics. This question mark (?) represents an unknown type.

The wildcard can be used in a variety of situations-

  • As the type of a parameter, field, or local variable;
  • Sometimes as a return type (though it is better programming practice to be more specific).

Types of wildcards in Java

Wildcards in Java generics can be classified into three types-

  1. Upper bounded wildcards
  2. Lower bounded wildcards
  3. Unbounded wildcards

Upper bounded wildcards in Java generics

The way we can have bounded parameters in generics same way we can have bounded wildcards too. So let’s see with an example when we should have upper bounded wildcards in Java generics.

Suppose you want to write a method that can take list of any type of Number which means a method that works on lists of Number and the subtypes of Number, such as Integer, Double, and Float i.e. List<Integer>, List<Double>, and List<Number>.

Here note one thing, though Integer is a subtype of Number, List<Integer> is not a subtype of List<Number> and, in fact, these two types are not related. Same applies for Double and Float too. So you can’t have your method as follows-

public static  double sumOfElements(List<Number> list){
  double s = 0.0;
  for (Number n : list)
    s += n.doubleValue();
  return s;
}

If you try to write your method as above you can’t call it with a List with integers because of the reason stated above.

List<Integer> li = Arrays.asList(1, 2, 3);
System.out.println("sum = " + sumOfElements(li));

Trying to call the sumOfElements method with argument List<Integer> will result in compile-time error

The method sumOfElements(List<Number>) in the type WildCardDemo is not applicable for the arguments (List<Integer>)

In the case like this where you want your method to be generic enough to be able to work with a list of type Number or any of its subclasses. you can achieve this by using an upper bounded wildcard.

General form of upper bounded wildcard

To declare an upper-bounded wildcard, use the wildcard character ('?'), followed by the extends keyword, followed by its upper bound.

<? extends UpperBoundType>

Upper bounded wildcard Java example

To write the above mentioned method sumOfElements so that it works with Number or any of its subtype you need to provide a wild card and Number as the upper bound i.e. <? extends Number>. This will match Number or any of its subtype.

import java.util.Arrays;
import java.util.List;

public class WildCardDemo {
  public static void main(String[] args) {
    // With List<Integer>
    List<Integer> li = Arrays.asList(5, 6, 7);
    System.out.println("sum = " + sumOfElements(li));
    // With List<Double>
    List<Double> ld = Arrays.asList(1.2, 3.8, 8.2);
    System.out.println("sum = " + sumOfElements(ld));
  }
    
  public static double sumOfElements(List<? extends Number> list){
    double s = 0.0;
    for (Number n : list)
      s += n.doubleValue();
    return s;
  }
}

Output

sum = 18.0
sum = 13.2

Lower Bounded Wildcards in Java Generics

The way Upper bounded wildcard restricts the unknown type to be a specific type or a subtype of that type same way lower bounded wildcard restricts the unknown type to be a specific type or a super type of that type.

General form of the lower bounded wildcard

A lower bounded wildcard is expressed using the wildcard character ('?'), following by the super keyword, followed by its lower bound:

<? super bounded_type>

Lower Bounded Wildcard Java Example

Suppose you want to write a method that put elements of type Integer into a List. If you want to make sure that method works for List<Integer>, List<Number>, and List<Object> — anything that can hold Integer values. Here note that Number and Object are super type of Integer.

That generic method can be written as follows by using the lower bounded wildcard where lower bound is Integer.

public static void addNumbers(List<? super Integer> list) {
  for (int i = 1; i <= 10; i++) {
    list.add(i);
  }
}

You can invoke this method using the following code-

// Using object
List<Object> lo = new ArrayList<Object>();
addNumbers(lo);
// Using Integer
List<Integer> li = new ArrayList<Integer>();
addNumbers(li);

Note- You can specify an upper bound for a wildcard, or you can specify a lower bound, but you cannot specify both.

Unbounded wildcards in Java generics

Unbounded wildcards are, as the name suggests, wild cards with out any upper or lower bound. Unbounded wildcard type is specified using the wildcard character (?), for example, List<?>.This is called a list of unknown type.

There are two scenarios where an unbounded wildcard is a useful approach-

  • If you are writing a method that can be implemented using functionality provided in the Object class.
  • When the code is using methods in the generic class that don't depend on the type parameter. For example, List.size or List.clear.

Java unbounded wildcard example

Suppose you want to write a method that can print elements of a List of any type. If you write that method using Object as type for the List, you will get an error when you pass it a List of integers.

public static void printElements(List<Object> list){
  for (Object elem : list){
    System.out.println(elem + " ");
  }
  System.out.println();
}

If you try to invoke this method using the following lines-

List<Integer> li = Arrays.asList(5, 6, 7);
printElements(li);

You will get compile-time error-

The method printElements(List<Object>) in the type WildCardDemo is not applicable for the arguments (List<Integer>)

You get this error because the above method prints only a list of Object instances; it cannot print List<Integer>, List<String>, List<Double>, and so on, because they are not subtypes of List<Object>. To write a generic printElements method, use List<?>:

import java.util.Arrays;
import java.util.List;

public class WildCardDemo {
  public static void main(String[] args) {
    // With List<Integer>
    List<Integer> li = Arrays.asList(5, 6, 7);
    printElements(li);
    // With List<Double>
    List<Double> ld = Arrays.asList(1.2, 3.8, 8.2);
    printElements(ld);
  }
    
  public static void printElements(List<?> list){
    for (Object elem : list){
      System.out.print(elem + " ");
    }
    System.out.println();
  }
}

Output

5 6 7 
1.2 3.8 8.2

Reference: https://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html

That's all for this topic Wildcard in Java Generics. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Generic Class, Interface And Generic Method in Java
  2. Bounded Type Parameter in Java Generics
  3. Type Erasure in Java Generics
  4. @FunctionalInterface Annotation in Java
  5. Core Java Basics Interview Questions And Answers

You may also like-

  1. Parallel Stream in Java Stream API
  2. Reduction Operations in Java Stream API
  3. Java Multithreading Interview Questions And Answers
  4. Marker Interface in Java
  5. Difference Between Encapsulation and Abstraction in Java
  6. Difference Between Checked And Unchecked Exceptions in Java
  7. Java Exception Handling And Method Overriding
  8. Configuring DataSource in Spring Framework

Thursday, March 25, 2021

Varargs (Variable-length Arguments) in Java

varargs in Java short for variable-length arguments is a feature that allows the method to accept variable number of arguments (zero or more). With varargs it has become simple to create methods that need to take a variable number of arguments. The feature of variable argument (varargs) has been added in Java 5.


Syntax of varargs

A vararg in Java is specified by three ellipsis (three dots) after the data type, its general form is

return_type method_name(data_type ... variableName){
 ..
 ..
}